diff --git a/AmebaZ2 LZMA flash layout_customer.pptx b/AmebaZ2 LZMA flash layout_customer.pptx new file mode 100644 index 00000000..8a665a6d Binary files /dev/null and b/AmebaZ2 LZMA flash layout_customer.pptx differ diff --git a/component/common/api/at_cmd/atcmd_bt.c b/component/common/api/at_cmd/atcmd_bt.c index 051b812c..f24557a8 100644 --- a/component/common/api/at_cmd/atcmd_bt.c +++ b/component/common/api/at_cmd/atcmd_bt.c @@ -11,6 +11,7 @@ #include "app_msg.h" #include "gap_le.h" #include "gap_msg.h" +#include "gap_customer.h" #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT #include "bt_ota_central_client_app_flags.h" @@ -208,7 +209,6 @@ void bt_at_cmd_send_msg(uint16_t subtype, void *arg) } } #endif - #if defined(CONFIG_BT_PERIPHERAL) && CONFIG_BT_PERIPHERAL if (evt_queue_handle != NULL && io_queue_handle != NULL) { if (os_msg_send(io_queue_handle, &io_msg, 0) == false) { @@ -1443,6 +1443,7 @@ void fATBt(void *arg) } #endif +#if ((defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT)) #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT extern bool bt_ota_central_client_set_image(uint8_t *image); extern bool bt_ota_central_client_set_key(uint8_t *key); @@ -1452,6 +1453,44 @@ extern void bt_ota_central_client_app_deinit(void); extern unsigned char rtl8762c_image[]; extern unsigned char rtl8762c_aes256_key[]; +void fATBo(void *arg) +{ + int argc = 0; + int param = 0; + char *argv[MAX_ARGC] = {0}; + + if (arg) { + argc = parse_param(arg, argv); + } else { + goto exit; + } + + if (argc != 2) { + AT_PRINTK("[AT_PRINTK] ERROR: input parameter error!\n\r"); + goto exit; + } + + param = atoi(argv[1]); + if (param == 1) { + AT_PRINTK("[ATBo]:_AT_BT_OTA_CENTRAL_CLIENT_[ON]\n\r"); + bt_ota_central_client_set_image(rtl8762c_image); + bt_ota_central_client_set_key(rtl8762c_aes256_key); + bt_ota_central_client_app_init(); + } else if (param == 0) { + AT_PRINTK("[ATBo]:_AT_BT_OTA_CENTRAL_CLIENT_[OFF]\n\r"); + bt_ota_central_client_app_deinit(); + } else { + goto exit; + } + + return; + +exit: + AT_PRINTK("[ATBo] Start BT OTA Central Client: ATBo=1"); + AT_PRINTK("[ATBo] Stop BT OTA Central Client: ATBo=0"); +} +#endif + #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT void fATBs(void *arg) { @@ -1513,7 +1552,8 @@ void fATBl(void *arg) AT_PRINTK("[ATBl] P=public, R=random"); AT_PRINTK("[ATBl] eg:ATBC=P,001122334455"); } - +#endif +#if ((defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT)) void fATBq(void *arg) { int argc = 0; @@ -1542,8 +1582,9 @@ void fATBq(void *arg) #endif #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT -extern void *bt_ota_central_client_evt_queue_handle; -extern void *bt_ota_central_client_io_queue_handle; +#include + +T_OTA_WRITE_MSG ota_write_msg; static u8 ctoi(char c) { @@ -1599,10 +1640,17 @@ void fATBh(void *arg) uint8_t event = EVENT_IO_TO_APP; T_IO_MSG io_msg; + memset(&ota_write_msg, 0, sizeof(T_OTA_WRITE_MSG)); + ota_write_msg.conn_id = atoi(argv[2]); + ota_write_msg.handle = hex_str_to_int(strlen(argv[3]), (s8 *)argv[3]); + io_msg.type = IO_MSG_TYPE_QDECODE; - io_msg.subtype = atoi(argv[2]); - io_msg.u.param = hex_str_to_int(strlen(argv[3]), (s8 *)argv[3]); + io_msg.subtype = 4; + io_msg.u.buf = &ota_write_msg; +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +extern void *bt_ota_central_client_evt_queue_handle; +extern void *bt_ota_central_client_io_queue_handle; if (bt_ota_central_client_evt_queue_handle != NULL && bt_ota_central_client_io_queue_handle != NULL) { if (os_msg_send(bt_ota_central_client_io_queue_handle, &io_msg, 0) == false) { AT_PRINTK("bt at cmd send msg fail: subtype 0x%x", io_msg.subtype); @@ -1612,6 +1660,18 @@ void fATBh(void *arg) } else { goto exit; } +#endif +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT + if (bt_mesh_provisioner_ota_client_evt_queue_handle != NULL && bt_mesh_provisioner_ota_client_io_queue_handle != NULL) { + if (os_msg_send(bt_mesh_provisioner_ota_client_io_queue_handle, &io_msg, 0) == false) { + AT_PRINTK("bt at cmd send msg fail: subtype 0x%x", io_msg.subtype); + } else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) { + AT_PRINTK("bt at cmd send event fail: subtype 0x%x", io_msg.subtype); + } + } else { + goto exit; + } +#endif } return; @@ -1621,43 +1681,6 @@ void fATBh(void *arg) AT_PRINTK("[ATBh] e.g. ATBh=1,0,0x13"); } #endif - -void fATBo(void *arg) -{ - int argc = 0; - int param = 0; - char *argv[MAX_ARGC] = {0}; - - if (arg) { - argc = parse_param(arg, argv); - } else { - goto exit; - } - - if (argc != 2) { - AT_PRINTK("[AT_PRINTK] ERROR: input parameter error!\n\r"); - goto exit; - } - - param = atoi(argv[1]); - if (param == 1) { - AT_PRINTK("[ATBo]:_AT_BT_OTA_CENTRAL_CLIENT_[ON]\n\r"); - bt_ota_central_client_set_image(rtl8762c_image); - bt_ota_central_client_set_key(rtl8762c_aes256_key); - bt_ota_central_client_app_init(); - } else if (param == 0) { - AT_PRINTK("[ATBo]:_AT_BT_OTA_CENTRAL_CLIENT_[OFF]\n\r"); - bt_ota_central_client_app_deinit(); - } else { - goto exit; - } - - return; - -exit: - AT_PRINTK("[ATBo] Start BT OTA Central Client: ATBo=1"); - AT_PRINTK("[ATBo] Stop BT OTA Central Client: ATBo=0"); -} #endif #if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS @@ -1991,8 +2014,8 @@ extern void bt_mesh_device_matter_app_deinit(void); AT_PRINTK("[ATBm] Stop BT Mesh Mulitple Profile: ATBm=0"); #endif #else - AT_PRINTK("[ATBm] Start BT Mesh Mulitple Profile: ATBm=1"); - AT_PRINTK("[ATBm] Stop BT Mesh Mulitple Profile: ATBm=0"); + AT_PRINTK("[ATBm] Start BT Mesh: ATBm=1"); + AT_PRINTK("[ATBm] Stop BT Mesh: ATBm=0"); #endif } @@ -2074,8 +2097,7 @@ void fATBV(void *arg) log_item_t at_bt_items[ ] = { #if ((defined(CONFIG_BT_CENTRAL) && CONFIG_BT_CENTRAL) || \ (defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ - (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET) || \ - (defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER)) + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) #if defined(CONFIG_BT_CENTRAL) && CONFIG_BT_CENTRAL {"ATBc", fATBc, {NULL, NULL}}, // Start/stop BLE central #endif @@ -2091,9 +2113,7 @@ log_item_t at_bt_items[ ] = { {"ATBg", fATBg, {NULL, NULL}}, // Set PHY 2M #endif #if ((defined(CONFIG_BT_PERIPHERAL) && CONFIG_BT_PERIPHERAL) || \ - (defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ - (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET) || \ - (defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER)) + (defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL)) #if defined(CONFIG_BT_PERIPHERAL) && CONFIG_BT_PERIPHERAL {"ATBp", fATBp, {NULL, NULL}}, // Start/stop BLE peripheral {"ATBP", fATBP, {NULL, NULL}}, // Legacy ADV concurrent test @@ -2101,14 +2121,11 @@ log_item_t at_bt_items[ ] = { {"ATBA", fATBA, {NULL, NULL}}, // Modify adv interval {"ATBe", fATBe, {NULL, NULL}}, // BLE send indiaction/notification #endif - - #if ((defined(CONFIG_BT_CENTRAL) && CONFIG_BT_CENTRAL) || \ (defined(CONFIG_BT_PERIPHERAL) && CONFIG_BT_PERIPHERAL) || \ (defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ (defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ - (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET) || \ - (defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER)) + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) {"ATBK", fATBK, {NULL, NULL}}, // Reply GAP passkey {"ATBY", fATBY, {NULL, NULL}}, // Reply GAP user confirm {"ATBU", fATBU, {NULL, NULL}}, // Update connection request @@ -2134,14 +2151,18 @@ log_item_t at_bt_items[ ] = { {"ATBt", fATBt, {NULL, NULL}}, // Set test configuration {"ATBr", fATBr, {NULL, NULL}}, // rembd #endif +#if ((defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT)) #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT {"ATBo", fATBo, {NULL, NULL}}, // Start/Stop BT OTA Central Client +#endif #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT {"ATBh", fATBh, {NULL, NULL}}, // Send user write request example #endif #if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT {"ATBs", fATBs, {NULL, NULL}}, // Scan start/stop BT OTA Central Client {"ATBl", fATBl, {NULL, NULL}}, // Connection start/stop BT OTA Central Client +#endif +#if ((defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT)) {"ATBq", fATBq, {NULL, NULL}}, // OTA start/stop BT OTA Central Client #endif #endif diff --git a/component/common/api/at_cmd/atcmd_lwip.c b/component/common/api/at_cmd/atcmd_lwip.c index 9d0292aa..68df9e00 100644 --- a/component/common/api/at_cmd/atcmd_lwip.c +++ b/component/common/api/at_cmd/atcmd_lwip.c @@ -6,6 +6,8 @@ #include "atcmd_wifi.h" #include "atcmd_lwip.h" #include "osdep_service.h" +#include "lwip/dns.h" +#include #if CONFIG_USE_POLARSSL @@ -972,7 +974,7 @@ void fATP3(void *arg){ printf("[ATP3]Usage: ATP3=REMOTE_IP\n\r"); goto exit; } - strcpy((char*)remote_addr, (char*)arg); + strncpy((char*)remote_addr, (char*)arg, sizeof(remote_addr)); printf("[ATP3]: _AT_TRANSPORT_REMOTE_IP_ [%s]\n\r", remote_addr); exit: @@ -1568,7 +1570,7 @@ void fATPT(void *arg){ &&(curnode->role == NODE_ROLE_SERVER)) { char udp_clientaddr[16]={0}; - strcpy((char*)udp_clientaddr, (char*)argv[3]); + strncpy((char*)udp_clientaddr, (char*)argv[3], sizeof(udp_clientaddr)); cli_addr.sin_family = AF_INET; cli_addr.sin_port = htons(atoi((char*)argv[4])); if (inet_aton(udp_clientaddr , &cli_addr.sin_addr) == 0) @@ -1686,12 +1688,12 @@ void fATPR(void *arg){ if(curnode->protocol == NODE_MODE_UDP && curnode->role == NODE_ROLE_SERVER){ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, "\r\n[ATPR] OK,%d,%d,%s,%d:%s", total_recv_size, con_id, udp_clientaddr, udp_clientport, rx_buffer); - sprintf(tmpbuf, "\r\n[ATPR] OK,%d,%d,%s,%d:", total_recv_size, con_id, udp_clientaddr, udp_clientport); + snprintf(tmpbuf, ATPR_RSVD_HEADER_SIZE, "\r\n[ATPR] OK,%d,%d,%s,%d:", total_recv_size, con_id, udp_clientaddr, udp_clientport); } else{ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, "\r\n[ATPR] OK,%d,%d:%s", total_recv_size, con_id, rx_buffer); - sprintf(tmpbuf, "\r\n[ATPR] OK,%d,%d:", total_recv_size, con_id); + snprintf(tmpbuf, ATPR_RSVD_HEADER_SIZE, "\r\n[ATPR] OK,%d,%d:", total_recv_size, con_id); } header_len = strlen(tmpbuf); memmove(rx_buffer + header_len, rx_buffer, total_recv_size); @@ -1888,12 +1890,12 @@ void fATPP(void *arg){ addr.s_addr = htonl(curnode->addr); inet_ntoa_r(addr, buf, sizeof(buf)); }else if( curnode->role == 0){//ping local server - strcpy(buf,SERVER); + strncpy(buf,SERVER, sizeof(buf)); }else if( curnode->role == 2){ //ping seed - strcpy(buf,(char*) curnode->addr); + strncpy(buf,(char*) curnode->addr, sizeof(buf)); } }else - strcpy(buf, argv[1]); + strncpy(buf, argv[1], sizeof(buf)); if(argc == 2){ count = 5; @@ -2945,6 +2947,8 @@ log_module_init(at_transport_init); #include "mbedtls/ssl.h" #include "mbedtls/error.h" #include "mbedtls/certs.h" +#include "mbedtls/platform.h" +#include "mbedtls/debug.h" #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_CERTS_C) || \ !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \ !defined(MBEDTLS_SSL_CLI_C) || !defined(MBEDTLS_NET_C) || \ @@ -2960,6 +2964,9 @@ log_module_init(at_transport_init); extern char log_buf[LOG_SERVICE_BUFLEN]; extern struct netif xnetif[NET_IF_NUM]; +extern int atcmd_sntp(char* hostname); + +static int select_check = 0; static unsigned char _tx_buffer[MAX_BUFFER]; static unsigned char _rx_buffer[MAX_BUFFER]; @@ -3034,7 +3041,7 @@ static char *atcmd_lwip_itoa(int value){ len ++; val_str = (char *) pvPortMalloc(len + 1); - sprintf(val_str, "%d", value); + snprintf(val_str, (len+1), "%d", value); return val_str; } @@ -3066,6 +3073,11 @@ int atcmd_lwip_start_tt_task(void); int atcmd_lwip_is_tt_mode(void); void atcmd_lwip_set_tt_mode(int enable); int atcmd_lwip_write_info_to_flash(struct atcmd_lwip_conn_info *cur_conn, int enable); +static void select_task(void *param); +int seek_free_id(); +xTaskHandle atcmd_select_task = NULL; +xTaskHandle atcmd_auto_recv_task = NULL; + #else //#if ATCMD_VER == ATVER_2 xTaskHandle server_task = NULL; @@ -3162,6 +3174,7 @@ static void server_start(void *param) if((ret = mbedtls_net_bind(&server_fd, NULL, s_port_str, MBEDTLS_NET_PROTO_TCP)) != 0) { AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR: net_bind %d\n", ret); error_no = 15; + free(s_port_str); goto err_exit; } s_sockfd = server_fd.fd; @@ -3260,7 +3273,8 @@ static void server_start(void *param) goto err_exit; } srv_key = (atcmd_ssl_server_key[ServerNodeUsed->con_id])?atcmd_ssl_server_key[ServerNodeUsed->con_id]:(char *)mbedtls_test_srv_key; - if((ret = mbedtls_pk_parse_key(server_pk, srv_key, strlen(srv_key)+1, NULL, 0)) != 0) { + + if((ret = mbedtls_pk_parse_key(server_pk, (const unsigned char*)srv_key, strlen(srv_key)+1, NULL, 0)) != 0) { AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR: pk_parse_key server_pk %d\n", ret); error_no = 20; goto err_exit; @@ -3326,7 +3340,7 @@ static void server_start(void *param) mbedtls_ssl_conf_ca_chain(conf, server_x509->next, NULL); mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE); - mbedtls_ssl_conf_rng(conf, atcmd_ssl_random, NULL); + mbedtls_ssl_conf_rng(conf, atcmd_ssl_random, NULL); mbedtls_ssl_set_bio(ssl, &s_newsockfd, mbedtls_net_send, mbedtls_net_recv, NULL); if((ret = mbedtls_ssl_conf_own_cert(conf, server_x509, server_pk)) != 0) { AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ERROR: ssl_set_own_cert %d\n", ret); @@ -3363,6 +3377,7 @@ static void server_start(void *param) AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, "[ATPS]create node failed!"); rtw_free((void *)ssl); + rtw_free((void *)conf); error_no = 28; goto err_exit; } @@ -3370,6 +3385,7 @@ static void server_start(void *param) seednode->port = ntohs(s_cli_addr.sin_port); seednode->addr = ntohl(s_cli_addr.sin_addr.s_addr); seednode->context = (void *)ssl; + seednode->ssl_conf= (void *)conf; if(hang_seednode(ServerNodeUsed,seednode) < 0){ delete_node(seednode); seednode = NULL; @@ -3579,11 +3595,277 @@ static void server_start(void *param) return; } +static int auth_mode = 0; +static int con_id, cert_type; +static int sni = 0; +static char hostname[64]; +#if ATCMD_VER == ATVER_2 && ATCMD_SUPPORT_SSL +static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) +{ + char buf[1024]; + ((void) data); + + printf("Verify requested for (Depth %d):\n", depth); + mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt); + printf("%s", buf); + + if(((*flags) & MBEDTLS_X509_BADCERT_EXPIRED) != 0) + printf("server certificate has expired\n"); + + if(((*flags) & MBEDTLS_X509_BADCERT_REVOKED) != 0) + printf(" ! server certificate has been revoked\n"); + + if(((*flags) & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0) + printf(" ! CN mismatch\n"); + + if(((*flags) & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0) + printf(" ! self-signed or not signed by a trusted CA\n"); + + if(((*flags) & MBEDTLS_X509_BADCRL_NOT_TRUSTED) != 0) + printf(" ! CRL not trusted\n"); + + if(((*flags) & MBEDTLS_X509_BADCRL_EXPIRED) != 0) + printf(" ! CRL expired\n"); + + if(((*flags) & MBEDTLS_X509_BADCERT_OTHER) != 0) + printf(" ! other (unknown) flag\n"); + + if((*flags) == 0) + printf(" Certificate verified without error flags\n"); + + return(0); +} + +static int ssl_client_ssl_setup(mbedtls_ssl_config *conf) + +{ + ( void ) conf; + + atcmd_ssl_cli_crt[con_id] = (mbedtls_x509_crt *) mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); + + if(atcmd_ssl_cli_crt[con_id]) + mbedtls_x509_crt_init(atcmd_ssl_cli_crt[con_id]); + else + return -1; + if(mbedtls_x509_crt_parse(atcmd_ssl_cli_crt[con_id], (const unsigned char*)atcmd_ssl_client_crt[con_id], strlen((char const*)atcmd_ssl_client_crt[con_id]) + 1) != 0) + return -1; + atcmd_ssl_clikey_rsa[con_id] = (mbedtls_pk_context *) mbedtls_calloc(1, sizeof(mbedtls_pk_context)); + + if(atcmd_ssl_clikey_rsa[con_id]) + mbedtls_pk_init(atcmd_ssl_clikey_rsa[con_id]); + else + return -1; +#if CONFIG_MBEDTLS_VERSION3 == 1 + if(mbedtls_pk_parse_key(atcmd_ssl_clikey_rsa[con_id], (const unsigned char*)atcmd_ssl_client_key[con_id], strlen((char const*)atcmd_ssl_client_key[con_id])+1, NULL, 0, rtw_get_random_bytes_f_rng, 1) != 0) +#else + if(mbedtls_pk_parse_key(atcmd_ssl_clikey_rsa[con_id], (const unsigned char*)atcmd_ssl_client_key[con_id], strlen((char const*)atcmd_ssl_client_key[con_id])+1, NULL, 0) != 0) +#endif + return -1; + + mbedtls_ssl_conf_own_cert(conf, atcmd_ssl_cli_crt[con_id], atcmd_ssl_clikey_rsa[con_id]); + + if(auth_mode == MBEDTLS_SSL_VERIFY_REQUIRED){ + + atcmd_ssl_cli_ca_crt[con_id] = (mbedtls_x509_crt *) mbedtls_calloc(1, sizeof(mbedtls_x509_crt)); + + if(atcmd_ssl_cli_ca_crt[con_id]) + mbedtls_x509_crt_init(atcmd_ssl_cli_ca_crt[con_id]); + else + return -1; + if(mbedtls_x509_crt_parse(atcmd_ssl_cli_ca_crt[con_id], (const unsigned char*)atcmd_ssl_client_ca_crt[con_id], strlen((char const*)atcmd_ssl_client_ca_crt[con_id])+1) != 0) + return -1; + + mbedtls_ssl_conf_ca_chain(conf, atcmd_ssl_cli_ca_crt[con_id], NULL); + mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_verify(conf, my_verify, NULL); + } + return 0; +} + +void ssl_client_free(void) +{ + if(atcmd_ssl_cli_crt[con_id]) { + mbedtls_x509_crt_free(atcmd_ssl_cli_crt[con_id]); + mbedtls_free(atcmd_ssl_cli_crt[con_id]); + atcmd_ssl_cli_crt[con_id] = NULL; + } + if (atcmd_ssl_client_crt[con_id]) { + rtw_free(atcmd_ssl_client_crt[con_id]); + atcmd_ssl_client_crt[con_id] = NULL; + } + + if(atcmd_ssl_clikey_rsa[con_id]) { + + mbedtls_pk_free(atcmd_ssl_clikey_rsa[con_id]); + mbedtls_free(atcmd_ssl_clikey_rsa[con_id]); + + atcmd_ssl_clikey_rsa[con_id] = NULL; + } + if (atcmd_ssl_client_key[con_id]) { + rtw_free(atcmd_ssl_client_key[con_id]); + atcmd_ssl_client_key[con_id] = NULL; + } + + if(auth_mode == MBEDTLS_SSL_VERIFY_REQUIRED){ + if(atcmd_ssl_cli_ca_crt[con_id]) { + mbedtls_x509_crt_free(atcmd_ssl_cli_ca_crt[con_id]); + mbedtls_free(atcmd_ssl_cli_ca_crt[con_id]); + atcmd_ssl_cli_ca_crt[con_id] = NULL; + } + if (atcmd_ssl_client_ca_crt[con_id]) { + rtw_free(atcmd_ssl_client_ca_crt[con_id]); + atcmd_ssl_client_ca_crt[con_id] = NULL; + } + } +} +#endif + +//Queue Related functions + +typedef struct { + char *buf; + int read; + int write; + int size; + int space; +} Queue; + +#if ATCMD_VER == ATVER_2 +static Queue* atcmd_lwip_queue[NUM_NS] = {NULL}; +#define RECV_BUFFER_SIZE 4096 + + +#define Avail(q) (q->size - q->space) + +void Queue_Init(Queue *q, int size) +{ + q->buf = (char *)rtw_malloc(sizeof(char) * size); + memset(&q->buf[0], 0x00, size); + q->read = 0; + q->write = 0; + q->size = size; + q->space = size; +} + +void Queue_Destroy(Queue *q) +{ + rtw_free(q->buf); +} + +bool Queue_Empty(Queue *q) +{ + return (q->space == q->size); +} + +bool Queue_Full(Queue *q) +{ + return (q->space == 0); +} + +int AddQueue(Queue *q, char val) +{ + if (!Queue_Full(q)) { + q->buf[q->write] = val; + q->write = (q->write + 1) % q->size; + q->space--; + return 1; + } + return 0; +} + +int DelQueue(Queue *q, char *val) +{ + if (!Queue_Empty(q)) { + *val = q->buf[q->read]; + q->read = (q->read + 1) % q->size; + q->space++; + return 1; + } + return 0; +} + +static int WriteQueue(Queue *q, char *buf, unsigned int len) +{ + unsigned int ret = 0; + unsigned int rest = q->size - q->write; + + if (!Queue_Full(q)) { + if (q->space >= len) { + ret = len; + if (rest >= len) { + memcpy(q->buf + q->write, buf, len); + q->write = (q->write + len) % q->size; + q->space -= len; + } else { + memcpy(q->buf + q->write, buf, rest); + q->write = 0; + memcpy(q->buf, buf + rest, len - rest); + q->write = len -rest; + q->space -= len; + } + } else { + ret = q->space; + if (rest >= q->space) { + memcpy(q->buf + q->write, buf, q->space); + q->write = (q->write + q->space) % q->size; + q->space = 0; + } else { + memcpy(q->buf + q->write, buf, rest); + q->write = 0; + memcpy(q->buf, buf + rest, q->space - rest); + q->write = q->space -rest; + q->space = 0; + } + } + } + return ret; +} + +static int ReadQueue(Queue *q, char *buf, unsigned int len) +{ + unsigned int rest = q->size - q->read; + unsigned int ret = 0; + + if (!Queue_Empty(q)) { + if (Avail(q) >= len) { + ret = len; + if (rest >= len) { + memcpy(buf, q->buf + q->read, len); + q->read = (q->read + len) % q->size; + q->space += len; + } else { + memcpy(buf, q->buf + q->read, rest); + q->read = 0; + memcpy(buf + rest, q->buf, len - rest); + q->read = len -rest; + q->space += len; + } + return len; + } else { + ret = Avail(q); + if (rest >= Avail(q)) { + memcpy(buf, q->buf + q->read, Avail(q)); + q->read = (q->read + Avail(q)) % q->size; + q->space = q->size; + } else { + memcpy(buf, q->buf + q->read, rest); + q->read = 0; + memcpy(buf + rest, q->buf, Avail(q) - rest); + q->read = Avail(q) -rest; + q->space = q->size; + } + } + } + return ret; +} +#endif + static void client_start(void *param) { /* To avoid gcc warnings */ ( void ) param; - + + int select_task_suspend = 0; int c_mode; int c_remote_port; char c_remote_addr[16]; @@ -3675,6 +3957,10 @@ static void client_start(void *param) /*********************************************************** * SSL 1. Setup stuff for this ssl connection ************************************************************/ + if (select_check && (!select_task_suspend)) { + vTaskSuspend(atcmd_select_task); + select_task_suspend = 1; + } int retry_count = 0; AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"Setting up the SSL/TLS structure..." ); mbedtls_platform_set_calloc_free(my_calloc, vPortFree); @@ -3689,35 +3975,67 @@ static void client_start(void *param) mbedtls_ssl_init(ssl); mbedtls_ssl_config_init(conf); + +#ifdef MBEDTLS_DEBUG_C + mbedtls_debug_set_threshold(ATCMD_SSL_DEBUG_LEVEL); +#endif if((ret = mbedtls_ssl_config_defaults(conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"malloc fail for ssl"); + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"set ssl config failed"); error_no = 20; rtw_free((void *)ssl); rtw_free((void *)conf); goto err_exit; } - mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE); + mbedtls_ssl_conf_authmode(conf, auth_mode); mbedtls_ssl_conf_rng(conf, atcmd_ssl_random, NULL); + +#if (defined(MBEDTLS_SSL_IN_CONTENT_LEN) && (MBEDTLS_SSL_IN_CONTENT_LEN == 4096)) || \ + (defined(MBEDTLS_SSL_MAX_CONTENT_LEN) && (MBEDTLS_SSL_MAX_CONTENT_LEN == 4096)) + if(ret = mbedtls_ssl_conf_max_frag_len(conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"mbedtls_ssl_conf_max_frag_len fail for ssl"); + error_no = 23; + goto err_exit; + } +#endif + mbedtls_ssl_set_bio(ssl, &ClientNodeUsed->sockfd, mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_conf_dbg(conf, atcmd_ssl_debug, NULL); + if(sni){ + if((ret = mbedtls_ssl_set_hostname(ssl,hostname)) != 0) { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"sni setup failed"); + error_no = 25; + goto err_exit; + } + } + if(auth_mode != 0){ + if((ret = ssl_client_ssl_setup(conf)) != 0) { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ssl cert setup failed"); + error_no = 24; + goto err_exit; + } + } + + if((ret = mbedtls_ssl_setup(ssl, conf)) != 0) { AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"malloc fail for ssl"); - error_no = 21; + error_no = 20; rtw_free((void *)ssl); rtw_free((void *)conf); goto err_exit; } -#ifdef MBEDTLS_DEBUG_C - mbedtls_debug_set_threshold(ATCMD_SSL_DEBUG_LEVEL); -#endif + int i = 0; + for(i = 0; i < strlen(hostname);i++) + printf("\ndebug: %s\n", ssl->hostname[i]); + + /*********************************************************** * SSL 2. Wait for the ssl handshake done ************************************************************/ @@ -3725,7 +4043,7 @@ static void client_start(void *param) while((ret = mbedtls_ssl_handshake(ssl)) != 0) { if(retry_count >= 5) { AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ssl_handshake failed -0x%x\n", -ret); - error_no = 22; + error_no = 21; goto err_exit; } retry_count++; @@ -3735,7 +4053,7 @@ static void client_start(void *param) * SSL 3. Hang node on mainlist for global management ************************************************************/ if(hang_node(ClientNodeUsed) < 0){ - error_no = 23; + error_no = 22; goto err_exit; } #if CONFIG_LOG_SERVICE_LOCK @@ -3886,6 +4204,27 @@ static void client_start(void *param) log_service_unlock(); #endif exit: + +#if ATCMD_VER == ATVER_2 +#if defined(ATCMD_SUPPORT_SSL) && ATCMD_SUPPORT_SSL + ssl_client_free(); + if (select_check && select_task_suspend) { + vTaskResume(atcmd_select_task); + select_task_suspend = 0; + } +#endif + + if (error_no == 0) { + if (select_check == 0){ + if(xTaskCreate(select_task, ((const char*)"select_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &atcmd_select_task) != pdPASS) + { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "ERROR: Create select task failed."); + } + select_check = 1; + } + } +#endif return; } @@ -3975,7 +4314,7 @@ void fATP3(void *arg){ printf("[ATP3]Usage: ATP3=REMOTE_IP\n\r"); goto exit; } - strcpy((char*)remote_addr, (char*)arg); + strncpy((char*)remote_addr, (char*)arg, sizeof(remote_addr)); printf("[ATP3]: _AT_TRANSPORT_REMOTE_IP_ [%s]\n\r", remote_addr); exit: @@ -4232,70 +4571,384 @@ void fATP0(void *arg){ #endif } -void fATPC(void *arg){ +static void _tt_wait_rx_complete(){ + s32 tick_current = rtw_get_current_time(); + + while(rtw_systime_to_ms(tick_current -atcmd_lwip_tt_lasttickcnt) < ATCMD_LWIP_TT_MAX_DELAY_TIME_MS ){ + rtw_msleep_os(5); + tick_current = rtw_get_current_time(); + } +} +#if ATCMD_SUPPORT_SSL +static void key_handler(void* param) +{ + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "Enter TT data mode"); + + while(rtw_down_sema(&atcmd_lwip_tt_sema) == _SUCCESS) { + _lock lock; + _irqL irqL; + int tt_size = 0; + _tt_wait_rx_complete(); + + rtw_enter_critical(&lock, &irqL); + if((atcmd_lwip_tt_datasize >= 4) && (rtw_memcmp(log_buf, "++++", 4) == _TRUE)){ + atcmd_lwip_set_tt_mode(FALSE); + atcmd_lwip_tt_datasize = 0; + rtw_exit_critical(&lock, &irqL); + break; + } + switch(cert_type){ + case 0: + atcmd_ssl_client_ca_crt[con_id] = (char *)rtw_malloc(atcmd_lwip_tt_datasize); + rtw_memcpy(atcmd_ssl_client_ca_crt[con_id], log_buf, atcmd_lwip_tt_datasize); + printf("\n[ATCK] CA Cert[%d]:%s\n",con_id, atcmd_ssl_client_ca_crt[con_id]); + break; + case 1: + atcmd_ssl_client_crt[con_id] = (char *)rtw_malloc(atcmd_lwip_tt_datasize); + rtw_memcpy(atcmd_ssl_client_crt[con_id], log_buf, atcmd_lwip_tt_datasize); + printf("\n[ATCK] Client Cert[%d]:%s\n",con_id, atcmd_ssl_client_crt[con_id]); + break; + case 2: + atcmd_ssl_client_key[con_id] = (char *)rtw_malloc(atcmd_lwip_tt_datasize); + rtw_memcpy(atcmd_ssl_client_key[con_id], log_buf, atcmd_lwip_tt_datasize); + printf("\n[ATCK] Client Key[%d]:%s\n",con_id,atcmd_ssl_client_key[con_id]); + break; + default: + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"[ATCK] Usage: Content input wrongly, please check"); + goto exit; + } + tt_size = atcmd_lwip_tt_datasize; + atcmd_lwip_tt_datasize = 0; + rtw_exit_critical(&lock, &irqL); + tx_buffer[tt_size] = '\0'; + } +exit: + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "Leave TT data mode"); + rtw_free_sema(&atcmd_lwip_tt_sema); + atcmd_lwip_set_autorecv_mode(FALSE); + at_printf(STR_END_OF_ATCMD_RET); //mark return to command mode + vTaskDelete(NULL); +} + +void fATCK(void *arg){ int argc; - char* argv[MAX_ARGC] = {0}; - node* clientnode = NULL; - int mode = 0; - int remote_port; - int local_port = 0; - //char remote_addr[DNS_MAX_NAME_LENGTH]; - struct in_addr addr; int error_no = 0; - u32 client_task_stksz = ATCP_STACK_SIZE; -#if LWIP_DNS - struct hostent *server_host; -#endif + int enable = 0; + char *argv[MAX_ARGC] = {0}; AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, - "[ATPC]: _AT_TRANSPORT_START_CLIENT"); - - if(atcmd_lwip_is_tt_mode() && mainlist->next){ - error_no = 13; - goto err_exit; - } + "[ATPU]: _AT_TRANSPORT_TT_MODE"); argc = parse_param(arg, argv); - if(argc < 4){ - AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, - "[ATPC] Usage: ATPC=,,,[]"); + if( argc < 4){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATCK] Usage: ATPU=,,\n\r"); error_no = 1; - goto err_exit; - } - - mode = atoi((char*)argv[1]);//tcp, udp or ssl - if(mode != NODE_MODE_TCP && mode != NODE_MODE_UDP -#if (ATCMD_VER == ATVER_2) && ATCMD_SUPPORT_SSL - && mode != NODE_MODE_SSL -#endif - ){ - AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, - "[ATPC] Unknown connection type[%d]", mode); - error_no = 17; - goto err_exit; + goto exit; } - - remote_port = atoi((char*)argv[3]); - if (inet_aton(argv[2], &addr) == 0) + if(((argv[1] == NULL) || (argv[2] == NULL)) || (argv[3] == NULL)) { -#if LWIP_DNS - server_host = gethostbyname(argv[2]); - if (server_host){ - rtw_memcpy(&addr, server_host->h_addr, 4); - AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, - "[ATPC] Found name '%s' = %s", - argv[2], - inet_ntoa(addr) - ); - } - else -#endif - { + error_no = 1; + goto exit; + } + enable = atoi((char*)argv[1]); + cert_type = atoi((char*)argv[2]); + con_id = atoi((char*)argv[3]); + + con_id = seek_free_id(); + at_printf("\r\n[ATCK] con_id: %d", con_id); + + if(enable){ + + rtw_init_sema(&atcmd_lwip_tt_sema, 0); + atcmd_lwip_set_tt_mode(TRUE); + if(xTaskCreate(key_handler, ((const char*)"tt_hdl"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &atcmd_lwip_tt_task) != pdPASS){ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, - "[ATPC] ERROR: Host '%s' not found.", argv[2]); - error_no = 2; - goto err_exit; + "ERROR: Create tt task failed."); + error_no = 1; + goto exit; + } + rtw_msleep_os(20); + if(atcmd_lwip_is_autorecv_mode() != 1){ + if(atcmd_lwip_start_autorecv_task()){ + vTaskDelete(atcmd_lwip_tt_task); + error_no = 2; + goto exit; + } + } + } + +exit: + + if(error_no == 0) + at_printf("\r\n[ATCK] OK"); + + else{ + atcmd_lwip_set_tt_mode(FALSE); + at_printf("\r\n[ATCK] ERROR:%d",error_no); + } + return; +} +#endif +void fATPB(void *arg) +{ + int argc, error_no = 0; + char *argv[MAX_ARGC] = {0}; + int enable; + ip_addr_t dnsserver; + + if(!arg){ + AT_DBG_MSG(AT_FLAG_WIFI, AT_DBG_ERROR, + "\r\n[ATPB] Usage: ATPB=[,]"); + error_no = 1; + goto exit; + } + argc = parse_param(arg, argv); + if(argc < 2){ + //at_printf("\r\n[ATPB] ERROR : command format error"); + error_no = 1; + goto exit; + } + if(argv[1] != NULL){ + enable = atoi((const char *)(argv[1])); + if(enable != 0 && enable != 1){ + //at_printf("\r\n[ATPB] ERROR : parameter must be 0 or 1"); + error_no = 2; + goto exit; + } + } + if(enable){ + if(argv[2] != NULL){ + ip4_addr_set_u32(&dnsserver, ipaddr_addr(argv[2])); + dns_setserver(0,&dnsserver); + } + else{ + ip4_addr_set_u32(&dnsserver, ipaddr_addr("208.67.222.222")); + dns_setserver(0, &dnsserver); + } + } + else{ + if(argv[2] != NULL){ + //at_printf("\r\n[ATPB] ERROR : parameter format error"); + error_no = 2; + goto exit; + } + else{ + ip4_addr_set_u32(&dnsserver, ipaddr_addr("208.67.222.222")); + dns_setserver(0, &dnsserver); + } + } +exit: + if(error_no == 0){ + at_printf("\r\n[ATPB] OK"); + const ip_addr_t *ns; + ns = dns_getserver(0); + at_printf("\r\n[ATPB] DNS SERVER ADDRESS:%s",ipaddr_ntoa(ns)); + } + else + at_printf("\r\n[ATPB] ERROR:%d",error_no); + return; +} + +void fATDN(void *arg){ + + int argc; + char* argv[MAX_ARGC] = {0}; + int error_no = 0; + struct in_addr addr; + +#if LWIP_DNS + struct hostent *server_host; +#endif + + argc = parse_param(arg, argv); + if(argc != 2){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATDN] Usage: ATDN="); + error_no = 1; + goto exit; + } + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } + if (inet_aton(argv[1], &addr) == 0) + { +#if LWIP_DNS + server_host = gethostbyname(argv[1]); + if (server_host){ + rtw_memcpy(&addr, server_host->h_addr, 4); + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "[ATDN] Found name '%s' = %s", + argv[1], + inet_ntoa(addr) + ); + } + else +#endif + { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATDN] ERROR: Host '%s' not found.", argv[1]); + error_no = 2; + goto exit; + } + } +exit: + if(error_no == 0){ + at_printf("\r\n[ATDN] OK"); + at_printf("\r\n[ATDN] Found name '%s' = %s", argv[1],inet_ntoa(addr)); + } + else + at_printf("\r\n[ATDN] ERROR:%d",error_no); + return; +} + +void fATTM(void *arg){ + int argc; + char* argv[MAX_ARGC] = {0}; + int error_no = 0; + int timezone; + struct tm current_tm; + static int config = 0; + + unsigned int update_tick = 0; + long update_sec = 0, update_usec = 0, current_sec = 0; + unsigned int current_tick = xTaskGetTickCount(); + + + argc = parse_param(arg, argv); + if(argc != 3){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATTM] Usage: ATTM = ,"); + error_no = 1; + goto exit; + } + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } + timezone = atoi((char*)argv[1]); + if(timezone < (-12)||timezone > 12){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATTM] Usage: Timezone Invalid"); + error_no = 2; + goto exit; + } + + atcmd_sntp((char*)argv[2]); +retry: + sntp_get_lasttime(&update_sec, &update_usec, &update_tick); + + if(update_tick) { + long tick_diff_sec, tick_diff_ms; + tick_diff_sec = (current_tick - update_tick) / configTICK_RATE_HZ; + tick_diff_ms = (current_tick - update_tick) % configTICK_RATE_HZ / portTICK_RATE_MS; + update_sec += tick_diff_sec; + update_usec += (tick_diff_ms * 1000); + current_sec = update_sec + update_usec / 1000000 + timezone * 3600; + current_tm = *(localtime((time_t const*)¤t_sec)); + current_tm.tm_year += 1900; + current_tm.tm_mon += 1; + } + else + goto retry; + +exit: + if(error_no == 0){ + if(config==1) + at_printf("\r\n[ATTM] %d-%02d-%02d %02d:%02d:%02d\n",current_tm.tm_year, current_tm.tm_mon, current_tm.tm_mday, current_tm.tm_hour, current_tm.tm_min, current_tm.tm_sec); + else{ + at_printf("\r\n[ATTM] OK"); + config++; + } + } + else{ + at_printf("\r\n[ATTM] ERROR:%d",error_no); + config = 0; + } + return; + +} + +void fATPC(void *arg){ + + int argc; + char* argv[MAX_ARGC] = {0}; + node* clientnode = NULL; + int mode = 0; + int remote_port; + int local_port = 0; + //char remote_addr[DNS_MAX_NAME_LENGTH]; + struct in_addr addr; + int error_no = 0; + u32 client_task_stksz = ATCP_STACK_SIZE; +#if LWIP_DNS + struct hostent *server_host; +#endif + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "[ATPC]: _AT_TRANSPORT_START_CLIENT"); + + if(atcmd_lwip_is_tt_mode() && mainlist->next){ + error_no = 13; + goto err_exit; + } + + argc = parse_param(arg, argv); + if(argc < 4){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATPC] Usage: ATPC=,,,[,,]"); + error_no = 1; + goto err_exit; + } + + if(argv[1] == NULL) + { + error_no = 1; + goto err_exit; + } + mode = atoi((char*)argv[1]);//tcp, udp or ssl + if(mode != NODE_MODE_TCP && mode != NODE_MODE_UDP +#if (ATCMD_VER == ATVER_2) && ATCMD_SUPPORT_SSL + && mode != NODE_MODE_SSL +#endif + ){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATPC] Unknown connection type[%d]", mode); + error_no = 17; + goto err_exit; + } + if((argv[3] == NULL) || (argv[2] == NULL)) + { + error_no = 1; + goto err_exit; + } + remote_port = atoi((char*)argv[3]); + if (inet_aton(argv[2], &addr) == 0) + { +#if LWIP_DNS + server_host = gethostbyname(argv[2]); + if (server_host){ + rtw_memcpy(&addr, server_host->h_addr, 4); + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "[ATPC] Found name '%s' = %s", + argv[2], + inet_ntoa(addr) + ); + } + else +#endif + { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATPC] ERROR: Host '%s' not found.", argv[2]); + error_no = 2; + goto err_exit; } } @@ -4316,6 +4969,20 @@ void fATPC(void *arg){ } } + if(argv[5]){ + auth_mode = atoi((char*)argv[5]); + if(auth_mode < 0 || auth_mode > 3) { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATPC] ERROR: ssl auth mode invalid"); + error_no = 12; + goto err_exit; + } + } + if(argv[6]){ + sni = 1; + strcpy(hostname,(char*)(char*)argv[6]); + } + clientnode = create_node(mode, NODE_ROLE_CLIENT); if(clientnode == NULL){ error_no = 4; @@ -4372,7 +5039,11 @@ void fATPS(void *arg){ error_no = 1; goto err_exit; } - + if(argv[1] == NULL) + { + error_no = 1; + goto err_exit; + } mode = atoi((char*)argv[1]); if(mode != NODE_MODE_TCP && mode != NODE_MODE_UDP #if (ATCMD_VER == ATVER_2) && ATCMD_SUPPORT_SSL @@ -4384,7 +5055,11 @@ void fATPS(void *arg){ error_no = 15; goto err_exit; } - + if(argv[2] == NULL) + { + error_no = 1; + goto err_exit; + } local_port = atoi((char*)argv[2]); if(local_port < 0 || local_port > 65535){ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, @@ -4427,7 +5102,11 @@ void socket_close_all(void) node *currNode = mainlist->next; while(currNode) - { + { + if(atcmd_lwip_queue[currNode->con_id]!=NULL) { + Queue_Destroy(atcmd_lwip_queue[currNode->con_id]); + atcmd_lwip_queue[currNode->con_id] = NULL; + } delete_node(currNode); currNode = mainlist->next; } @@ -4460,8 +5139,10 @@ void fATPD(void *arg){ s_node = seek_node(con_id); if(s_node == NULL){ - error_no = 3; - goto exit; + if (atcmd_lwip_queue[con_id] == NULL) { + error_no = 3; + goto exit; + } else goto exit; } delete_node(s_node); @@ -4469,14 +5150,20 @@ void fATPD(void *arg){ s_node = NULL; if(error_no) at_printf("\r\n[ATPD] ERROR:%d", error_no); - else + else{ at_printf("\r\n[ATPD] OK"); + if (atcmd_lwip_queue[con_id] != NULL) { + Queue_Destroy(atcmd_lwip_queue[con_id]); + atcmd_lwip_queue[con_id] = NULL; + } + } + return; } int atcmd_lwip_send_data(node *curnode, u8 *data, u16 data_sz, struct sockaddr_in cli_addr){ int error_no = 0; - + if((curnode->protocol == NODE_MODE_UDP) && (curnode->role == NODE_ROLE_SERVER)) //UDP server { if (sendto(curnode->sockfd, data, data_sz, 0, (struct sockaddr *)&cli_addr, sizeof(cli_addr)) <= 0 ){ @@ -4557,26 +5244,35 @@ void fATPT(void *arg){ error_no = 1; goto exit; } - - data_sz = atoi((char*)argv[1]); - if(data_sz > MAX_BUFFER){ - error_no = 2; - goto exit; + if(argv[1] != NULL) + { + data_sz = atoi((char*)argv[1]); + if(data_sz > MAX_BUFFER){ + error_no = 2; + goto exit; + } } - - con_id = atoi((char*)argv[2]); - curnode = seek_node(con_id); - if(curnode == NULL){ - error_no = 3; - goto exit; + if(argv[2] != NULL) + { + con_id = atoi((char*)argv[2]); + curnode = seek_node(con_id); + if(curnode == NULL){ + error_no = 3; + goto exit; + } } if((curnode->protocol == NODE_MODE_UDP) &&(curnode->role == NODE_ROLE_SERVER)) { char udp_clientaddr[16]={0}; - strcpy((char*)udp_clientaddr, (char*)argv[3]); + strncpy((char*)udp_clientaddr, (char*)argv[3], sizeof(udp_clientaddr)); cli_addr.sin_family = AF_INET; + if(argv[4] == NULL) + { + error_no = 1; + goto exit; + } cli_addr.sin_port = htons(atoi((char*)argv[4])); if (inet_aton(udp_clientaddr , &cli_addr.sin_addr) == 0) { @@ -4605,6 +5301,7 @@ void fATPR(void *arg){ node* curnode = NULL; u8_t udp_clientaddr[16] = {0}; u16_t udp_clientport = 0; + int select_task_suspend = 0; #if defined(EXTEND_ATPR_SIZE) && (EXTEND_ATPR_SIZE == 1) int total_recv_size = 0; @@ -4632,12 +5329,23 @@ void fATPR(void *arg){ goto exit; } + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } + con_id = atoi((char*)argv[1]); if(con_id <= 0 || con_id > NUM_NS){ error_no = 9; goto exit; } + if(argv[2] == NULL) + { + error_no = 1; + goto exit; + } packet_size = atoi((char*)argv[2]); if (packet_size <= 0 @@ -4668,6 +5376,12 @@ void fATPR(void *arg){ } memset(rx_buffer, 0, rx_buffer_size); + if(curnode->protocol == NODE_MODE_SSL) { + if (select_check && (!select_task_suspend)) { + vTaskSuspend(atcmd_select_task); + select_task_suspend = 1; + } + } error_no = atcmd_lwip_receive_data(curnode, rx_buffer, ETH_MAX_MTU, &recv_size, udp_clientaddr, &udp_clientport); exit: if(error_no == 0){ @@ -4693,12 +5407,12 @@ void fATPR(void *arg){ if(curnode->protocol == NODE_MODE_UDP && curnode->role == NODE_ROLE_SERVER){ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, "\r\n[ATPR] OK,%d,%d,%s,%d:%s", total_recv_size, con_id, udp_clientaddr, udp_clientport, rx_buffer); - sprintf(tmpbuf, "\r\n[ATPR] OK,%d,%d,%s,%d:", total_recv_size, con_id, udp_clientaddr, udp_clientport); + snprintf(tmpbuf, ATPR_RSVD_HEADER_SIZE, "\r\n[ATPR] OK,%d,%d,%s,%d:", total_recv_size, con_id, udp_clientaddr, udp_clientport); } else{ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, "\r\n[ATPR] OK,%d,%d:%s", total_recv_size, con_id, rx_buffer); - sprintf(tmpbuf, "\r\n[ATPR] OK,%d,%d:", total_recv_size, con_id); + snprintf(tmpbuf, ATPR_RSVD_HEADER_SIZE, "\r\n[ATPR] OK,%d,%d:", total_recv_size, con_id); } header_len = strlen(tmpbuf); memmove(rx_buffer + header_len, rx_buffer, total_recv_size); @@ -4717,10 +5431,33 @@ void fATPR(void *arg){ } if(recv_size) at_print_data(rx_buffer, recv_size); + else #endif // #if (EXTEND_ATPR_SIZE) + { + if(curnode->protocol == NODE_MODE_SSL) { + if (select_check && select_task_suspend) { + vTaskResume(atcmd_select_task); + select_task_suspend = 0; + } + } + } } - else + else{ at_printf("\r\n[ATPR] ERROR:%d,%d", error_no, con_id); + if((error_no == 8) || (error_no == 7)){ + if(curnode->protocol == NODE_MODE_SSL){ + if(select_check && select_task_suspend){ + delete_node(curnode); + int ret = check_node_pool(); + if(ret == 0){ + select_check = 0; + vTaskDelete(atcmd_select_task); + } + select_task_suspend = 0; + } + } + } + } return; } @@ -4741,7 +5478,11 @@ void fATPK(void *arg){ error_no = 1; goto exit; } - + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } enable = atoi((char*)argv[1]); if(enable){ @@ -4785,7 +5526,11 @@ void fATPU(void *arg){ error_no = 1; goto exit; } - + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } enable = atoi((char*)argv[1]); if(enable){ @@ -4880,7 +5625,11 @@ void fATPP(void *arg){ } argc = parse_param(arg, argv); - + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } if( strlen(argv[1]) < 3 ) { node* curnode; @@ -4896,10 +5645,10 @@ void fATPP(void *arg){ addr.s_addr = htonl(curnode->addr); inet_ntoa_r(addr, buf, sizeof(buf)); }else if( curnode->role == 0){//ping local server - strcpy(buf,SERVER); + strncpy(buf,SERVER, sizeof(buf)); } }else - strcpy(buf, argv[1]); + strncpy(buf, argv[1], sizeof(buf)); if(argc == 2){ count = 5; @@ -4910,6 +5659,11 @@ void fATPP(void *arg){ AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATPP]Repeat Count: %s", "loop"); do_ping_call(buf, 1, 0); //loop, no count }else{ + if(argv[2] == NULL) + { + error_no = 1; + goto exit; + } count = atoi(argv[2]); AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATPP]Repeat Count: %d", count); do_ping_call(buf, 0, count); //Not loop, with count @@ -4991,11 +5745,21 @@ void init_node_pool(void){ } } +int check_node_pool(void){ + + for(int i=1;iprotocol == NODE_MODE_SSL && currSeed->sockfd != INVALID_SOCKET_ID){ mbedtls_ssl_context *ssl = (mbedtls_ssl_context *)currSeed->context; + mbedtls_ssl_config *conf = (mbedtls_ssl_config *)currSeed->ssl_conf; mbedtls_ssl_close_notify(ssl); mbedtls_net_context server_fd; server_fd.fd = currSeed->sockfd; mbedtls_net_free(&server_fd); mbedtls_ssl_free(ssl); + mbedtls_ssl_config_free(conf); rtw_free(currSeed->context); + rtw_free(currSeed->ssl_conf); currSeed->context = NULL; + currSeed->ssl_conf = NULL; } #endif // no task created for seed @@ -5085,11 +5853,17 @@ void delete_node(node *n) if(n->protocol == NODE_MODE_SSL){ if(n->role == NODE_ROLE_SEED){ mbedtls_ssl_context *ssl = (mbedtls_ssl_context *)n->context; + mbedtls_ssl_config *conf = (mbedtls_ssl_config *)n->ssl_conf; mbedtls_ssl_close_notify(ssl); mbedtls_net_context server_fd; - server_fd.fd = currSeed->sockfd; + server_fd.fd = n->sockfd; mbedtls_net_free(&server_fd); mbedtls_ssl_free(ssl); + mbedtls_ssl_config_free(conf); + rtw_free(n->context); + rtw_free(n->ssl_conf); + n->context = NULL; + n->ssl_conf = NULL; } else if(n->role == NODE_ROLE_CLIENT){ mbedtls_ssl_context *ssl = (mbedtls_ssl_context *)n->context; @@ -5156,6 +5930,7 @@ void delete_node(node *n) else #endif { + shutdown(n->sockfd, SHUT_RDWR); close(n->sockfd); } n->sockfd = INVALID_SOCKET_ID; @@ -5171,6 +5946,10 @@ void delete_node(node *n) rtw_free(n->context); n->context = NULL; } + if(n->ssl_conf){ + rtw_free(n->ssl_conf); + n->context = NULL; + } #endif n->con_id = INVALID_CON_ID; return; @@ -5228,6 +6007,19 @@ int hang_seednode(node* main_node ,node* insert_node) return 0; } +int seek_free_id() { + int i; + + for (i = 0; i < NUM_NS; i++) { + if (node_pool[i].con_id == INVALID_CON_ID) { + return i; + } + } + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, "No free con_id available"); + + return -1; +} + node *seek_node(int con_id) { node* n = mainlist; @@ -5387,6 +6179,55 @@ int atcmd_lwip_receive_data(node *curnode, u8 *buffer, u16 buffer_size, int *rec return error_no; } +static void select_task(void *param) +{ + + int i; + int packet_size = ETH_MAX_MTU; + + while(1){ + for (i = 0; i < NUM_NS; ++i) { + node* curnode = NULL; + int error_no = 0; + int recv_size = 0; + u8_t udp_clientaddr[16] = {0}; + u16_t udp_clientport = 0; + curnode = tryget_node(i); + if(curnode == NULL) + continue; + if((curnode->protocol == NODE_MODE_TCP +#if (ATCMD_VER == ATVER_2) && ATCMD_SUPPORT_SSL + ||curnode->protocol == NODE_MODE_SSL +#endif + ) + && curnode->role == NODE_ROLE_SERVER){ + //TCP Server must receive data from the seed + continue; + } + error_no = atcmd_lwip_receive_data(curnode, rx_buffer, packet_size, &recv_size, udp_clientaddr, &udp_clientport); + if(error_no==7 || error_no == 8){ + #if CONFIG_LOG_SERVICE_LOCK + log_service_lock(); + #endif + at_printf("\r\n[SELECT_TASK] ERROR:%d,%d", error_no, curnode->con_id); + at_printf(STR_END_OF_ATCMD_RET); + + #if CONFIG_LOG_SERVICE_LOCK + log_service_unlock(); + #endif + + delete_node(curnode); + int ret = check_node_pool(); + if(ret == 0) goto exit; + } + } + } +exit: + select_check=0; + vTaskDelete(NULL); +} + + static void atcmd_lwip_receive_task(void *param) { @@ -5484,6 +6325,268 @@ int atcmd_lwip_start_autorecv_task(void){ return 0; } +static void receive_task(void *param) +{ + + int i; + int packet_size = ETH_MAX_MTU; + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "Enter auto receive mode"); + + while(atcmd_lwip_is_autorecv_mode()) + { + for (i = 0; i < NUM_NS; ++i) { + node* curnode = NULL; + int error_no = 0; + int recv_size = 0; + u8_t udp_clientaddr[16] = {0}; + u16_t udp_clientport = 0; + curnode = tryget_node(i); + if(curnode == NULL) + continue; + if((curnode->protocol == NODE_MODE_TCP +#if (ATCMD_VER == ATVER_2) && ATCMD_SUPPORT_SSL + ||curnode->protocol == NODE_MODE_SSL +#endif + ) + && curnode->role == NODE_ROLE_SERVER){ + //TCP Server must receive data from the seed + continue; + } + error_no = atcmd_lwip_receive_data(curnode, rx_buffer, packet_size, &recv_size, udp_clientaddr, &udp_clientport); + + if(atcmd_lwip_is_tt_mode()){ + if((error_no == 0) && recv_size){ + rx_buffer[recv_size] = '\0'; + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"Recv[%d]:%s", recv_size, rx_buffer); + at_print_data(rx_buffer, recv_size); + rtw_msleep_os(20); + } + continue; + } + + if(error_no == 0){ + if(recv_size){ + rx_buffer[recv_size] = '\0'; + #if CONFIG_LOG_SERVICE_LOCK + log_service_lock(); + #endif + if(curnode->protocol == NODE_MODE_UDP && curnode->role == NODE_ROLE_SERVER){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "\r\n[ATRV] OK,%d,%d,%s,%d:%s", recv_size, curnode->con_id, udp_clientaddr, udp_clientport, rx_buffer); + at_printf("\r\n[ATRV] OK,%d,%d,%s,%d", recv_size, curnode->con_id, udp_clientaddr, udp_clientport); + } + else{ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "\r\n[ATRV] OK,%d,%d:%s", + recv_size, + curnode->con_id, rx_buffer); + at_printf("\r\n[ATRV] OK,%d,%d", recv_size, curnode->con_id); + } + + if(atcmd_lwip_queue[curnode->con_id]==NULL){ + atcmd_lwip_queue[curnode->con_id] = (Queue *) rtw_malloc(sizeof(Queue)); + Queue_Init(atcmd_lwip_queue[curnode->con_id],RECV_BUFFER_SIZE); + at_printf("\r\n[ATRV] recv buffer allocated for %d: %d",curnode->con_id,atcmd_lwip_queue[curnode->con_id]->size); + } + WriteQueue(atcmd_lwip_queue[curnode->con_id], (char *)rx_buffer, recv_size); + at_printf("\r\n[ATRV] Recv buffer len:%d",Avail(atcmd_lwip_queue[curnode->con_id])); + at_printf(STR_END_OF_ATCMD_RET); + #if CONFIG_LOG_SERVICE_LOCK + log_service_unlock(); + #endif + } + } + else{ + #if CONFIG_LOG_SERVICE_LOCK + log_service_lock(); + #endif + at_printf("\r\n[ATRV] ERROR:%d,%d", error_no, curnode->con_id); + at_printf(STR_END_OF_ATCMD_RET); + #if CONFIG_LOG_SERVICE_LOCK + log_service_unlock(); + #endif + delete_node(curnode); + } + } + } + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "Leave auto receive mode"); + + vTaskDelete(NULL); +} + +int start_autorecv_task(void){ + atcmd_lwip_set_autorecv_mode(TRUE); + if(xTaskCreate(receive_task, ((const char*)"atcmd_lwip_receive_task"), ATCP_STACK_SIZE, NULL, ATCMD_LWIP_TASK_PRIORITY, &atcmd_auto_recv_task) != pdPASS) + { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "ERROR: Create receive task failed."); + atcmd_lwip_set_autorecv_mode(FALSE); + return -1; + } + return 0; +} + +void fATRV(void *arg){ + + int argc; + int error_no = 0; + int enable; + char *argv[MAX_ARGC] = {0}; + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "[ATRV]: _AT_TRANSPORT_AUTO_RECV"); + + argc = parse_param(arg, argv); + if( argc < 2){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATRV] Usage: ATPK=<0/1>\n\r"); + error_no = 1; + goto exit; + } + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } + enable = atoi((char*)argv[1]); + + if(enable){ + if(atcmd_lwip_is_autorecv_mode()){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, "[ATRV] already enter auto receive mode"); + } + else{ + if (select_check) vTaskSuspend(atcmd_select_task); + if(start_autorecv_task()) + error_no = 2; + } + }else{ + if(atcmd_lwip_is_autorecv_mode()) { + atcmd_lwip_set_autorecv_mode(FALSE); + if (select_check) vTaskResume(atcmd_select_task); + } + else{ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS,"[ATRV] already leave auto receive mode"); + } + } + +exit: + if(error_no) + at_printf("\r\n[ATRV] ERROR:%d", error_no); + else + at_printf("\r\n[ATRV] OK"); + return; +} + + +void fATRG(void *arg){ + + int argc; + int error_no = 0; + char *argv[MAX_ARGC] = {0}; + static char RG_buf[RECV_BUFFER_SIZE]; + int c_id = 0, len = 0, ret = 0; + + memset(&RG_buf[0], 0x00, RECV_BUFFER_SIZE); + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "[ATRG]: _AT_TRANSPORT_RECV_BUFFER_GET"); + + argc = parse_param(arg, argv); + if( argc != 3){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATRG] Usage: ATRG=,\n\r"); + error_no = 1; + goto exit; + } + if(argv[1] == NULL) + { + error_no = 1; + goto exit; + } + c_id = atoi((char*)argv[1]); + if( c_id > NUM_NS){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATRG] Usage: con_id invalid\n\r"); + error_no = 2; + goto exit; + } + if(argv[2] == NULL) + { + error_no = 1; + goto exit; + } + len = atoi((char*)argv[2]); + if( len > RECV_BUFFER_SIZE){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATRG] Usage: length invalid\n\r"); + error_no = 3; + goto exit; + } + + if (atcmd_lwip_queue[c_id] == NULL) { + at_printf("\r\n[ATRG] Queue not available"); + error_no = 4; + goto exit; + } + ret = ReadQueue(atcmd_lwip_queue[c_id], RG_buf, len); + +exit: + if(error_no) + at_printf("\r\n[ATRG] ERROR:%d", error_no); + else + at_printf("\r\n[ATRG] OK"); + at_printf("\r\n[ATRG] Recv %d bytes: \n\t%s\n",ret,RG_buf); + return; +} + +void fATRX(void *arg){ + + int argc; + int error_no = 0; + char *argv[MAX_ARGC] = {0}; + int c_id = 0; + + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ALWAYS, + "[ATR?]: _AT_TRANSPORT_RECV_BUF_CK"); + + argc = parse_param(arg, argv); + if( argc != 2){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATR?] Usage: ATR?=\n\r"); + error_no = 1; + goto exit; + } + if(argv[1] != NULL) + { + c_id = atoi((char*)argv[1]); + if( c_id > NUM_NS){ + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR, + "[ATR?] Usage: con_id invalid\n\r"); + error_no = 2; + goto exit; + } + } + if(atcmd_lwip_queue[c_id] == NULL) + { + error_no = 1; + goto exit; + } +exit: + if(error_no) + at_printf("\r\n[ATR?] ERROR:%d", error_no); + else{ + at_printf("\r\n[ATR?] OK"); + at_printf("\r\n[ATR?] Recv Buffer Length for con_id[%d]:%d",c_id,Avail(atcmd_lwip_queue[c_id])); + } + return; +} + + + int atcmd_lwip_is_tt_mode(void){ return (atcmd_lwip_tt_mode == TRUE); } @@ -5498,14 +6601,6 @@ void atcmd_lwip_set_autorecv_mode(int enable){ atcmd_lwip_auto_recv = enable; } -static void _tt_wait_rx_complete(){ - s32 tick_current = rtw_get_current_time(); - - while(rtw_systime_to_ms(tick_current -atcmd_lwip_tt_lasttickcnt) < ATCMD_LWIP_TT_MAX_DELAY_TIME_MS ){ - rtw_msleep_os(5); - tick_current = rtw_get_current_time(); - } -} static void atcmd_lwip_tt_handler(void* param) { @@ -5750,6 +6845,16 @@ int atcmd_lwip_auto_connect(void) } mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(conf, atcmd_ssl_random, NULL); + +#if (defined(MBEDTLS_SSL_IN_CONTENT_LEN) && (MBEDTLS_SSL_IN_CONTENT_LEN == 4096)) || \ + (defined(MBEDTLS_SSL_MAX_CONTENT_LEN) && (MBEDTLS_SSL_MAX_CONTENT_LEN == 4096)) + if(ret = mbedtls_ssl_conf_max_frag_len(conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { + AT_DBG_MSG(AT_FLAG_LWIP, AT_DBG_ERROR,"ssl config max fragment length fail"); + error_no = 23; + continue; + } +#endif + mbedtls_ssl_set_bio(ssl, &re_node->sockfd, mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_conf_dbg(conf, atcmd_ssl_debug, NULL); @@ -5949,6 +7054,17 @@ log_item_t at_transport_items[ ] = { {"ATPI", fATPI,},//printf connection status {"ATPU", fATPU,}, //transparent transmission mode {"ATPL", fATPL,}, //lwip auto reconnect setting +#if defined(ATCMD_SUPPORT_SSL) && ATCMD_SUPPORT_SSL + {"ATCK", fATCK,}, //ssl client cert setting +#endif + {"ATPB", fATPB,}, //set DNS server + {"ATDN", fATDN,}, //DNS Function + {"ATTM", fATTM,}, //SNTP Feature + {"ATRV", fATRV,}, //passive recv with buffer + {"ATRG", fATRG,}, //Recv from passive recv buffer + {"ATR?", fATRX,}, //Recv Buffer Length Check + + #endif }; @@ -5975,4 +7091,4 @@ void at_transport_init(void) log_module_init(at_transport_init); #endif -#endif /*CONFIG_USE_POLARSSL*/ \ No newline at end of file +#endif /*CONFIG_USE_POLARSSL*/ diff --git a/component/common/api/at_cmd/atcmd_wifi.c b/component/common/api/at_cmd/atcmd_wifi.c index 737f9b8a..eacb7e36 100644 --- a/component/common/api/at_cmd/atcmd_wifi.c +++ b/component/common/api/at_cmd/atcmd_wifi.c @@ -36,6 +36,7 @@ #define _AT_WLAN_AP_SET_SEC_KEY_ "ATW4" #define _AT_WLAN_AP_SET_CHANNEL_ "ATW5" #define _AT_WLAN_SET_BSSID_ "ATW6" +#define _AT_WLAN_SET_WPA_MODE_ "ATW8" #define _AT_WLAN_AP_ACTIVATE_ "ATWA" #define _AT_WLAN_AP_STA_ACTIVATE_ "ATWB" #define _AT_WLAN_AP_STA_CONTROL_ "ATWb" @@ -156,6 +157,7 @@ int security = -1; #if ATCMD_VER == ATVER_2 || WIFI_LOGO_CERTIFICATION_CONFIG unsigned char sta_ip[4] = {192,168,1,80}, sta_netmask[4] = {255,255,255,0}, sta_gw[4] = {192,168,1,1}; +u8 use_static_ip = 0; #endif #if WIFI_LOGO_CERTIFICATION_CONFIG @@ -874,6 +876,53 @@ void fATW7(void *arg){ return; } #endif + +void fATW8(void *arg){ + if(!arg){ + printf("[ATW8]Usage: ATW8=[WPA_MODE]\n\r"); + printf(" 0 : WPA_AUTO_MODE\n\r"); + printf(" 1 : WPA_ONLY_MODE\n\r"); + printf(" 2 : WPA2_ONLY_MODE\n\r"); + printf(" 3 : WPA3_ONLY_MODE\n\r"); + printf(" 4 : WPA_WPA2_MIXED_MODE\n\r"); + printf(" 5 : WPA2_WPA3_MIXED_MODE\n\r"); + return; + } + u32 wpa_mode = (u32) atoi((const char *)arg); + + if(wpa_mode<=WPA2_WPA3_MIXED_MODE){ + wifi_set_wpa_mode(wpa_mode); + switch(wpa_mode){ + case 0: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WPA_AUTO_MODE]\n\r"); + break; + case 1: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WPA_ONLY_MODE]\n\r"); + break; + case 2: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WPA2_ONLY_MODE]\n\r"); + break; + case 3: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WPA3_ONLY_MODE]\n\r"); + break; + case 4: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WPA_WPA2_MIXED_MODE]\n\r"); + break; + case 5: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WPA2_WPA3_MIXED_MODE]\n\r"); + break; + default: + printf("[ATW8]: _AT_WLAN_AP_SET_WPA_MODE_ [WRONG WPA MODE]\n\r"); + break; + } + } + else{ + printf("[ATW8] Wrong parameter\n\r"); + } + + return; +} + void fATWA(void *arg){ /* To avoid gcc warnings */ ( void ) arg; @@ -1199,8 +1248,9 @@ void fATWC(void *arg){ printf("\n\rERROR: Can't connect to AP"); goto EXIT; } - tick2 = xTaskGetTickCount(); - printf("\r\nConnected after %dms.\n", (tick2-tick1)); + { + tick2 = xTaskGetTickCount(); + printf("\r\nConnected after %dms.\n", (tick2-tick1)); #if CONFIG_LWIP_LAYER /* Start DHCPClient */ LwIP_DHCP(0, DHCP_START); @@ -1212,6 +1262,7 @@ void fATWC(void *arg){ tick3 = xTaskGetTickCount(); printf("\r\n\nGot IP after %dms.\n", (tick3-tick1)); #endif + } printf("\n\r"); #if WIFI_LOGO_CERTIFICATION_CONFIG @@ -1978,8 +2029,10 @@ void fATPE(void *arg) netif_set_addr(&xnetif[0], ip_2_ip4(&ipaddr), ip_2_ip4(&netmask),ip_2_ip4(&gw)); exit: - if(error_no==0) - at_printf("\r\n[ATPE] OK"); + if(error_no==0){ + at_printf("\r\n[ATPE] OK"); + use_static_ip = 1; + } else at_printf("\r\n[ATPE] ERROR:%d",error_no); @@ -3452,6 +3505,7 @@ log_item_t at_wifi_items[ ] = { {"ATW4", fATW4,{NULL,NULL}}, {"ATW5", fATW5,{NULL,NULL}}, {"ATW6", fATW6,{NULL,NULL}}, + {"ATW8", fATW8,{NULL,NULL}}, #ifdef CONFIG_FPGA {"ATW7", fATW7,}, #endif diff --git a/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c b/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c index a0ed686d..58bc3f73 100644 --- a/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c +++ b/component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c @@ -484,12 +484,13 @@ int eap_cert_setup(ssl_context *ssl) #elif CONFIG_USE_MBEDTLS + #include +#include #include #include -#include -int max_buf_bio_size = ( MBEDTLS_SSL_MAX_CONTENT_LEN \ +int max_buf_bio_size = ( MBEDTLS_SSL_MAX_CONTENT_LEN \ + MBEDTLS_SSL_COMPRESSION_ADD \ + 29 /* counter + header + IV */ \ + MBEDTLS_SSL_MAC_ADD \ diff --git a/component/common/api/wifi/wifi_conf.c b/component/common/api/wifi/wifi_conf.c index f0c9ece0..dc1c6a61 100644 --- a/component/common/api/wifi/wifi_conf.c +++ b/component/common/api/wifi/wifi_conf.c @@ -77,6 +77,8 @@ static void* disconnect_sema = NULL; rtw_mode_t wifi_mode = RTW_MODE_STA; #endif extern rtw_mode_t wifi_mode; +static rtw_wpa_mode wifi_wpa_mode = WPA_AUTO_MODE; + int error_flag = RTW_UNKNOWN; uint32_t rtw_join_status; #if ATCMD_VER == ATVER_2 @@ -218,6 +220,8 @@ static int wifi_connect_local(rtw_network_info_t *pWifi) ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_TKIP, NULL, 0, 0, 0, 0, NULL, 0); if(ret == 0) ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + if(ret == 0) + ret = rltk_wlan_set_wpa_mode(WLAN0_NAME,wifi_wpa_mode); break; case RTW_SECURITY_WPA_AES_PSK: case RTW_SECURITY_WPA_MIXED_PSK: @@ -234,6 +238,8 @@ static int wifi_connect_local(rtw_network_info_t *pWifi) ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_CCMP, NULL, 0, 0, 0, 0, NULL, 0); if(ret == 0) ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + if(ret == 0) + ret = rltk_wlan_set_wpa_mode(WLAN0_NAME,wifi_wpa_mode); break; default: ret = -1; @@ -275,6 +281,8 @@ static int wifi_connect_bssid_local(rtw_network_info_t *pWifi) ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_TKIP, NULL, 0, 0, 0, 0, NULL, 0); if(ret == 0) ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + if(ret == 0) + ret = rltk_wlan_set_wpa_mode(WLAN0_NAME,wifi_wpa_mode); break; case RTW_SECURITY_WPA_AES_PSK: case RTW_SECURITY_WPA_MIXED_PSK: @@ -291,6 +299,8 @@ static int wifi_connect_bssid_local(rtw_network_info_t *pWifi) ret = wext_set_key_ext(WLAN0_NAME, IW_ENCODE_ALG_CCMP, NULL, 0, 0, 0, 0, NULL, 0); if(ret == 0) ret = wext_set_passphrase(WLAN0_NAME, pWifi->password, pWifi->password_len); + if(ret == 0) + ret = rltk_wlan_set_wpa_mode(WLAN0_NAME,wifi_wpa_mode); break; default: ret = -1; @@ -441,7 +451,12 @@ extern void dhcp6_stop(struct netif *netif); extern u32 rltk_wlan_get_link_err(void); static void wifi_rssi_report_hdl( char* buf, int buf_len, int flags, void* userdata) { - printf("%s, rssi: %d\n", __func__, flags); + int rssi = flags; + unsigned char mac_addr[6] = {0}; + memcpy(mac_addr,buf,6); + + printf("scan report rssi: %d bssid: %02x:%02x:%02x:%02x:%02x:%02x\n", rssi, + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); } static void wifi_link_err_parse(u16 reason_code) @@ -505,6 +520,9 @@ static void wifi_link_err_parse(u16 reason_code) case 17: printf("auth stage, ap auth full\n"); break; + case 65530: + printf("SA query timeout\n"); + break; case 65534: printf("connected stage, ap changed\n"); break; @@ -647,7 +665,11 @@ static void wifi_disconn_hdl( char* buf, int buf_len, int flags, void* userdata) dhcp6_stop(&xnetif[0]); #endif #endif - netif_set_link_down(&xnetif[0]); +#if LWIP_ARP + if (xnetif[0].flags & NETIF_FLAG_ETHARP) { + etharp_cleanup_netif(&xnetif[0]); + } +#endif /* LWIP_ARP */ #endif #endif @@ -1397,6 +1419,14 @@ int wifi_set_country(rtw_country_code_t country_code) return ret; } +int wifi_get_country(rtw_country_code_t *country_code) +{ + int ret; + + ret = rltk_wlan_get_country_code(WLAN0_NAME, country_code); + + return ret; +} //----------------------------------------------------------------------------// int wifi_set_channel_plan(uint8_t channel_plan) { @@ -1829,6 +1859,16 @@ int wifi_set_mode(rtw_mode_t mode) return -1; } +int wifi_set_wpa_mode(rtw_wpa_mode wpa_mode) +{ + if(wpa_mode > WPA2_WPA3_MIXED_MODE) + return -1; + else{ + wifi_wpa_mode = wpa_mode; + return 0; + } +} + int wifi_set_power_mode(unsigned char ips_mode, unsigned char lps_mode) { return wext_enable_powersave(WLAN0_NAME, ips_mode, lps_mode); diff --git a/component/common/api/wifi/wifi_conf.h b/component/common/api/wifi/wifi_conf.h index 73af19c8..23b26604 100644 --- a/component/common/api/wifi/wifi_conf.h +++ b/component/common/api/wifi/wifi_conf.h @@ -348,6 +348,13 @@ int wifi_get_ap_info(rtw_bss_info_t * ap_info, rtw_security_t* security); */ int wifi_set_country(rtw_country_code_t country_code); +/** + * @brief get the country code from driver + * @param[in] country_code: Specify the country code. + * @return RTW_SUCCESS: The country code is successfully set. + * @return RTW_ERROR: The country code is not successfully set. + */ +int wifi_get_country(rtw_country_code_t *country_code); /** * @brief get sta mode MAX data rate. * @param[out] inidata_rate: the location will the MAX data rate @@ -493,6 +500,14 @@ int wifi_set_mode(rtw_mode_t mode); */ int wifi_off_fastly(void); +/** + * @brief Specify wpa mode for wifi connection. + * @param[in] wpa_mode: The desired wpa mode. It is defined as enum rtw_wpa_mode. + * @return RTW_SUCCESS if setting wpa mode successful. + * @return RTW_ERROR otherwise. + */ +int wifi_set_wpa_mode(rtw_wpa_mode wpa_mode); + /** * @brief Set IPS/LPS mode. * @param[in] ips_mode: The desired IPS mode. It becomes effective diff --git a/component/common/api/wifi/wifi_ind.c b/component/common/api/wifi/wifi_ind.c index b46c418a..49a1d78e 100644 --- a/component/common/api/wifi/wifi_ind.c +++ b/component/common/api/wifi/wifi_ind.c @@ -210,8 +210,18 @@ void wifi_indication( rtw_event_indicate_t event, char *buf, int buf_len, int fl case WIFI_EVENT_TARGET_SSID_RSSI: #if(WIFI_INDICATE_MSG==1) printf("\n\r%s(): WIFI_EVENT_TARGET_SSID_RSSI, rssi: %d\n", __func__, flags); +#endif + break; + case WIFI_EVENT_DHCP_RENEW: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_DHCP_RENEW\n", __func__); #endif break; + case WIFI_EVENT_SWITCH_CHANNE: +#if(WIFI_INDICATE_MSG==1) + printf("\n\r%s(): WIFI_EVENT_SWITCH_CHANNE, channel: %d\n", __func__, flags); +#endif + break; } #if CONFIG_INIC_EN diff --git a/component/common/application/jdsmart/2.1.22/example/joylink_extern.c b/component/common/application/jdsmart/2.1.22/example/joylink_extern.c new file mode 100644 index 00000000..8772fb37 --- /dev/null +++ b/component/common/application/jdsmart/2.1.22/example/joylink_extern.c @@ -0,0 +1,1397 @@ +/* -------------------------------------------------- + * @brief: + * + * @version: 1.0 + * + * @date: 08/01/2018 + * + * @desc: Functions in this file must be implemented by the device developers when porting the Joylink SDK. + * + * -------------------------------------------------- + */ +//#include +//#include +//#include + +#include "joylink.h" +#include "joylink_time.h" + +#include "joylink_extern.h" +#include "joylink_extern_json.h" + +#include "joylink_memory.h" +#include "joylink_socket.h" +#include "joylink_string.h" +#include "joylink_stdio.h" +//#include "joylink_stdint.h" +#include "joylink_log.h" +#include "joylink_time.h" +#include "joylink_thread.h" +#include "joylink_extern_ota.h" + +#include "FreeRTOS.h" +#include "task.h" +#include +#include +#include "wifi/wifi_conf.h" +#include "flash_api.h" +#include "lwip/ip_addr.h" +#include "lwip/netif.h" +#include "cJSON.h" +#include "sys_api.h" +#include "lwip_netconf.h" +#include "wlan_fast_connect/example_wlan_fast_connect.h" + +#include +#include +#include + +#include "osdep_service.h" +#include + +#if CONFIG_USE_POLARSSL +#include +#include +#include +#include +#elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */ +#include +#include +#include +#include +#endif +#include "platform_opts_bt.h" +#if defined CONFIG_BT_JOYLINK_ADAPTER && CONFIG_BT_JOYLINK_ADAPTER +#include "joylink_sdk.h" +#include "bt_joylink_adapter_app_flags.h" +#endif +user_dev_status_t user_dev; +extern struct netif xnetif[NET_IF_NUM]; + +JLPInfo_t user_jlp = { + .version = JLP_VERSION, + .uuid = JLP_UUID, + .devtype = JLP_DEV_TYPE, + .lancon = JLP_LAN_CTRL, + .cmd_tran_type = JLP_CMD_TYPE, + //.prikey = JLP_PRI_KEY, + .noSnapshot = JLP_SNAPSHOT, +}; + +jl2_d_idt_t user_idt = { + .type = 0, + .cloud_pub_key = IDT_CLOUD_PUB_KEY, + .sig = "01234567890123456789012345678901", + .pub_key = "01234567890123456789012345678901", + .f_sig = "01234567890123456789012345678901", + .f_pub_key = "01234567890123456789012345678901", +}; + +user_dev_status_t user_dev = { + .Power = 1, + .Mode = 0, + .State = 0, +}; + +#if 1 +int joylink_set_feedid(const char *json_in) +{ + uint8_t backup[300] = {0}; + uint8_t readfirst[50] = {0}; + int writeok = -1; + int readok = -1; + flash_t flash; + + if (json_in == NULL) { + return -1; + } + // read first + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 1, 50, readfirst); + if (1 == readok) { + // write directly + if (*((uint32_t *)readfirst) == ~0x0) { + writeok = flash_stream_write(&flash, FLASH_ADD_JLP_INFO + 50 * 1, 50, (unsigned char *)json_in); + if (writeok != 1) { + log_debug("[%s] write err", __func__); + return -1; + } + } else { + // the same thing, return directly + if (!strcmp(readfirst, json_in)) { + log_info("[%s] the same feedid", __func__); + } + // not the same, erase old -> write new + else { + flash_stream_read(&flash, FLASH_ADD_JLP_INFO, 300, backup); + flash_erase_sector(&flash, FLASH_ADD_JLP_INFO); + + strncpy((char *)(backup + 50 * 1), json_in, 50); + if (backup[50 * 2 - 1] != '\0' || flash_stream_write(&flash, FLASH_ADD_JLP_INFO, 300, backup) != 1) { + log_debug("[%s] write err!", __func__); + return -1; + } + } + } + } else { + log_fatal("[%s] flash read first fail !", __func__); + return -1; + } + return 0; +} + +int joylink_set_accesskey(const char *json_in) +{ + uint8_t backup[300] = {0}; + uint8_t readfirst[50] = {0}; + int writeok = -1; + int readok = -1; + flash_t flash; + + if (json_in == NULL) { + return -1; + } + // read first + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 2, 50, readfirst); + if (1 == readok) { + // write directly + if (*((uint32_t *)readfirst) == ~0x0) { + writeok = flash_stream_write(&flash, FLASH_ADD_JLP_INFO + 50 * 2, 50, (unsigned char *)json_in); + if (writeok != 1) { + log_debug("[%s] write err", __func__); + return -1; + } + } else { + // the same thing, return directly + if (!strcmp(readfirst, json_in)) { + log_info("[%s] the same accesskey", __func__); + } + // not the same, erase old -> write new + else { + flash_stream_read(&flash, FLASH_ADD_JLP_INFO, 300, backup); + flash_erase_sector(&flash, FLASH_ADD_JLP_INFO); + strncpy((char *)(backup + 50 * 2), json_in, 50); + if (backup[50 * 3 - 1] != '\0' || flash_stream_write(&flash, FLASH_ADD_JLP_INFO, 300, backup) != 1) { + log_debug("[%s] write err!", __func__); + return -1; + } + } + } + } else { + log_fatal("[%s] flash read first fail !", __func__); + return -1; + } + return 0; +} + +int joylink_set_localkey(const char *json_in) +{ + uint8_t backup[300] = {0}; + uint8_t readfirst[50] = {0}; + int writeok = -1; + int readok = -1; + flash_t flash; + + if (json_in == NULL) { + return -1; + } + // read first + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 3, 50, readfirst); + if (1 == readok) { + // write directly + if (*((uint32_t *)readfirst) == ~0x0) { + writeok = flash_stream_write(&flash, FLASH_ADD_JLP_INFO + 50 * 3, 50, (unsigned char *)json_in); + if (writeok != 1) { + log_debug("[%s] write err", __func__); + return -1; + } + } else { + // the same thing, return directly + if (!strcmp(readfirst, json_in)) { + log_info("[%s] the same localkey", __func__); + } + // not the same, erase old -> write new + else { + flash_stream_read(&flash, FLASH_ADD_JLP_INFO, 300, backup); + flash_erase_sector(&flash, FLASH_ADD_JLP_INFO); + strncpy((char *)(backup + 50 * 3), json_in, 50); + if (backup[50 * 4 - 1] != '\0' || flash_stream_write(&flash, FLASH_ADD_JLP_INFO, 300, backup) != 1) { + log_debug("[%s] write err!", __func__); + return -1; + } + } + } + } else { + log_fatal("[%s] flash read first fail !", __func__); + return -1; + } + return 0; +} + +int joylink_set_server_info(const char *json_in) +{ + uint8_t backup[300] = {0}; + uint8_t readfirst[50] = {0}; + int writeok = -1; + int readok = -1; + flash_t flash; + + if (json_in == NULL) { + return -1; + } + // read first + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 5, 50, readfirst); + if (1 == readok) { + // write directly + if (*((uint32_t *)readfirst) == ~0x0) { + writeok = flash_stream_write(&flash, FLASH_ADD_JLP_INFO + 50 * 5, 50, (unsigned char *)json_in); + if (writeok != 1) { + log_debug("[%s] write err", __func__); + return -1; + } + } else { + // the same thing, return directly + if (!strcmp(readfirst, json_in)) { + log_info("[%s] the same server_info", __func__); + } + // not the same, erase old -> write new + else { + flash_stream_read(&flash, FLASH_ADD_JLP_INFO, 300, backup); + flash_erase_sector(&flash, FLASH_ADD_JLP_INFO); + + strncpy((char *)(backup + 50 * 5), json_in, 50); + if (backup[50 * 6 - 1] != '\0' || flash_stream_write(&flash, FLASH_ADD_JLP_INFO, 300, backup) != 1) { + log_debug("[%s] write err!", __func__); + return -1; + } + } + } + } else { + log_fatal("[%s] flash read first fail !", __func__); + return -1; + } + return 0; +} + +int joylink_set_version(const char *json_in) +{ + uint8_t backup[300] = {0}; + uint8_t readfirst[50] = {0}; + int writeok = -1; + int readok = -1; + flash_t flash; + + if (json_in == NULL) { + return -1; + } + // read first + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 4, 50, readfirst); + if (1 == readok) { + // write directly + if (*((uint32_t *)readfirst) == ~0x0) { + writeok = flash_stream_write(&flash, FLASH_ADD_JLP_INFO + 50 * 4, 50, (unsigned char *)json_in); + if (writeok != 1) { + log_debug("[%s] write err", __func__); + return -1; + } + } else { + // the same thing, return directly + if (!strcmp(readfirst, json_in)) { + log_info("[%s] the same version", __func__); + } + // not the same, erase old -> write new + else { + flash_stream_read(&flash, FLASH_ADD_JLP_INFO, 300, backup); + flash_erase_sector(&flash, FLASH_ADD_JLP_INFO); + strncpy((char *)(backup + 50 * 4), json_in, 50); + if (backup[50 * 5 - 1] != '\0' || flash_stream_write(&flash, FLASH_ADD_JLP_INFO, 300, backup) != 1) { + log_debug("[%s] write err!", __func__); + return -1; + } + } + } + } else { + log_fatal("[%s] flash read first fail !", __func__); + return -1; + } + return 0; +} + +int joylink_get_accesskey(char *buf, unsigned int buf_sz) +{ + int readok = -1; + flash_t flash; + + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 2, 50, (uint8_t *)buf); + if (1 == readok) { + if (*((uint32_t *)buf) == ~0x0) { + log_fatal("[%s] flash read success, but no valid data !", __func__); + return -1; + } else { + return 0; + } + } else { + log_fatal("[%s] flash read fail !", __func__); + return -1; + } +} + +int joylink_get_localkey(char *buf, unsigned int buf_sz) +{ + int readok = -1; + flash_t flash; + + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 3, 50, (uint8_t *)buf); + if (1 == readok) { + if (*((uint32_t *)buf) == ~0x0) { + log_fatal("[%s] flash read success, but no valid data !", __func__); + return -1; + } else { + return 0; + } + } else { + log_fatal("[%s] flash read fail !", __func__); + return -1; + } +} + +int joylink_get_feedid(char *buf, unsigned int buf_sz) +{ + int readok = -1; + flash_t flash; + + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 1, 50, (uint8_t *)buf); + if (1 == readok) { + if (*((uint32_t *)buf) == ~0x0) { + log_fatal("[%s] flash read success, but no valid data !", __func__); + return -1; + } else { + return 0; + } + } else { + log_fatal("[%s] flash read fail !", __func__); + return -1; + } +} + +int joylink_get_server_info(char *buf, unsigned int buf_sz) +{ + int readok = -1; + flash_t flash; + + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 5, 50, (uint8_t *)buf); + if (1 == readok) { + if (*((uint32_t *)buf) == ~0x0) { + log_fatal("[%s] flash read success, but no valid data !", __func__); + return -1; + } else { + return 0; + } + } else { + log_fatal("[%s] flash read fail !", __func__); + return -1; + } +} + +int joylink_get_version(char *buf, unsigned int buf_sz) +{ + int readok = -1; + flash_t flash; + + readok = flash_stream_read(&flash, FLASH_ADD_JLP_INFO + 50 * 4, 50, (uint8_t *)buf); + if (1 == readok) { + if (*((uint32_t *)buf) == ~0x0) { + log_fatal("[%s] flash read success, but no valid data !", __func__); + return -1; + } else { + return 0; + } + } else { + log_fatal("[%s] flash read fail !", __func__); + return -1; + } +} + +/** + * brief: + * + * @Param: jlp + * @Param: pMsg + * + * @Returns: + */ +int +joylink_parse_jlp(JLPInfo_t *jlp, char *pMsg) +{ + int ret = -1; + if (NULL == pMsg || NULL == jlp) { + return ret; + } + cJSON *pVal; + cJSON *pJson = cJSON_Parse(pMsg); + + if (NULL == pJson) { + log_error("--->:ERROR: pMsg is NULL\n"); + goto RET; + } + + pVal = cJSON_GetObjectItem(pJson, "uuid"); + if (NULL != pVal) { + jl_platform_strcpy(jlp->uuid, pVal->valuestring); + } + + pVal = cJSON_GetObjectItem(pJson, "feedid"); + if (NULL != pVal) { + jl_platform_strcpy(jlp->feedid, pVal->valuestring); + } + + pVal = cJSON_GetObjectItem(pJson, "accesskey"); + if (NULL != pVal) { + jl_platform_strcpy(jlp->accesskey, pVal->valuestring); + } + + pVal = cJSON_GetObjectItem(pJson, "localkey"); + if (NULL != pVal) { + jl_platform_strcpy(jlp->localkey, pVal->valuestring); + } + + pVal = cJSON_GetObjectItem(pJson, "version"); + if (NULL != pVal) { + jlp->version = pVal->valueint; + } + + cJSON_Delete(pJson); + ret = 0; +RET: + return ret; +} + +#endif + +/** + * @brief: 用以返回一个整型随机数 + * + * @param: 无 + * + * @returns: 整型随机数 + */ +int +joylink_dev_get_random() +{ + /** + *FIXME:must to do + */ + static unsigned long int next = 1; + next = next * 1103515245 + 12345; + return (int)(next / 65536) % (1134); +} + +/** + * @brief: 返回是否可以访问互联网 + * + * @returns: E_JL_TRUE 可以访问, E_JL_FALSE 不可访问 + */ +E_JLBOOL_t joylink_dev_is_net_ok() +{ + if (RTW_SUCCESS == wifi_is_ready_to_transceive(RTW_STA_INTERFACE)) { + return E_JL_TRUE; + } else { + return E_JL_FALSE; + } +} + +/** + * @brief: 此函数用作通知应用层设备与云端的连接状态. + * + * @param: st - 当前连接状态 0-Socket init, 1-Authentication, 2-Heartbeat + * + * @returns: + */ +E_JLRetCode_t +joylink_dev_set_connect_st(int st) +{ + /** + *FIXME:must to do + */ + char buff[64] = {0}; + int ret = 0; + + jl_platform_sprintf(buff, "{\"conn_status\":\"%d\"}", st); + log_info("--set_connect_st:%s\n", buff); +#if defined CONFIG_BT_JOYLINK_ADAPTER && CONFIG_BT_JOYLINK_ADAPTER + static int iot_st = 0; + if(iot_st != st){ + if(st == JL_SERVER_ST_WORK){ + JLPInfo_t jlp; +#if defined(BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT) && BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT + extern int connect_status; + connect_status = 1; +#endif + memset(&jlp,0,sizeof(jlp)); + joylink_dev_get_jlp_info(&jlp); + jl_send_net_config_state(E_JL_NET_CONF_ST_IOT_CONNECT_SUCCEED,jlp.feedid,jl_platform_strlen(jlp.feedid)); + jl_send_net_config_state(E_JL_NET_CONF_ST_CLOUD_CONNECT_SUCCEED,NULL,0); + } + iot_st = st; + } +#endif + return ret; +} + +/** + * @brief: 传出激活信息 + * + * @param[in] message: 激活信息 + * + * @returns: 0:设置成功 + */ +E_JLRetCode_t joylink_dev_active_message(char *message) +{ + log_info("message = %s", message); + return 0; +} + +/** + * @brief: 存储JLP(Joylink Parameters)信息,将入参jlp结构中的信息持久化存储,如文件、设备flash等方式 + * + * @param [in]: jlp-JLP structure pointer + * + * @returns: + */ +// write feedid, accesskey, localkey, joylink_server, server_port, gURLStr, gTokenStr into flash + +E_JLRetCode_t +joylink_dev_set_attr_jlp(JLPInfo_t *jlp) +{ + if (NULL == jlp) { + return E_RET_ERROR; + } + /** + *FIXME:must to do + *Must save jlp info to flash + */ + int ret = E_RET_ERROR; +#if 1 + char buff[256]; + + JLPInfo_t *pJLPInfo = &(user_jlp); + + memset(buff, 0, sizeof(buff)); + if (strlen(jlp->feedid)) { + strcpy(pJLPInfo->feedid, jlp->feedid); + sprintf(buff, "{\"feedid\":\"%s\"}", jlp->feedid); + log_debug("--set buff:%s", buff); + if (joylink_set_feedid(buff)) { + goto RET; + } + } + + memset(buff, 0, sizeof(buff)); + if (strlen(jlp->accesskey)) { + strcpy(pJLPInfo->accesskey, jlp->accesskey); + sprintf(buff, "{\"accesskey\":\"%s\"}", jlp->accesskey); + log_debug("--set buff:%s", buff); + if (joylink_set_accesskey(buff)) { + goto RET; + } + } + + memset(buff, 0, sizeof(buff)); + if (strlen(jlp->localkey)) { + strcpy(pJLPInfo->localkey, jlp->localkey); + sprintf(buff, "{\"localkey\":\"%s\"}", jlp->localkey); + log_debug("--set buff:%s", buff); + if (joylink_set_localkey(buff)) { + goto RET; + } + } + + memset(buff, 0, sizeof(buff)); + if (strlen(jlp->joylink_server)) { + strcpy(pJLPInfo->joylink_server, jlp->joylink_server); + pJLPInfo->server_port = jlp->server_port; + sprintf(buff, "%s:%d", jlp->joylink_server, jlp->server_port); + log_debug("--set buff:%s", buff); + if (joylink_set_server_info(buff)) { + goto RET; + } + } + + pJLPInfo->version = jlp->version; + memset(buff, 0, sizeof(buff)); + sprintf(buff, "{\"version\":%d}", jlp->version); + log_debug("--set buff:%s", buff); + if (joylink_set_version(buff)) { + goto RET; + } +#else + memcpy(&user_jlp, jlp, sizeof(JLPInfo_t)); +#ifdef _SAVE_FILE_ + FILE *outfile; + outfile = fopen(file, "wb+"); + fwrite(&user_jlp, sizeof(JLPInfo_t), 1, outfile); + fclose(outfile); +#endif +#endif + ret = E_RET_OK; + return ret; + +#if 1 +RET: + log_error("set error"); +#endif + return ret; + +} + +/** + * @brief: 设置设备认证信息 + * + * @param[out]: pidt--设备认证信息结构体指针,需填入必要信息sig,pub_key,f_sig,f_pub_key,cloud_pub_key + * + * @returns: 返回设置成功或失败 + */ +E_JLRetCode_t +joylink_dev_get_idt(jl2_d_idt_t *pidt) +{ + if (NULL == pidt) { + return E_RET_ERROR; + } + pidt->type = 0; + jl_platform_strcpy(pidt->sig, user_idt.sig); + jl_platform_strcpy(pidt->pub_key, user_idt.pub_key); + //jl_platform_strcpy(pidt->rand, user_idt.rand); + jl_platform_strcpy(pidt->f_sig, user_idt.f_sig); + jl_platform_strcpy(pidt->f_pub_key, user_idt.f_pub_key); + jl_platform_strcpy(pidt->cloud_pub_key, user_idt.cloud_pub_key); + + return E_RET_OK; +} + +/** + * @brief: 此函数需返回设备的MAC地址 + * + * @param[out] out: 将设备MAC地址赋值给此参数 + * + * @returns: E_RET_OK 成功, E_RET_ERROR 失败 + */ +E_JLRetCode_t +joylink_dev_get_user_mac(char *out) +{ + unsigned char *tmp; + unsigned char mac[6] = {0}; + /*get mac address*/ + tmp = LwIP_GetMAC(&xnetif[0]); + mac[0] = tmp[0]; + mac[1] = tmp[1]; + mac[2] = tmp[2]; + mac[3] = tmp[3]; + mac[4] = tmp[4]; + mac[5] = tmp[5]; + + sprintf((char *)out, "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + // backup in user_jlp + strcpy(user_jlp.mac, out); + return E_RET_OK; +} + +/** + * @brief: 此函数需返回设备私钥private key,该私钥可从小京鱼后台获取 + * + * @param[out] out: 将私钥字符串赋值给该参数返回 + * + * @returns: E_RET_OK:成功, E_RET_ERROR:发生错误 + */ +E_JLRetCode_t +joylink_dev_get_private_key(char *out) +{ + strcpy(out, JLP_PRIV_KEY); + printf("private_key=out: %s\n", out); + return E_RET_OK; +} + +/** + * @brief: 从永久存储介质(文件或flash)中读取jlp信息,并赋值给参数jlp,其中feedid, accesskey,localkey,joylink_server,server_port必须正确赋值 + * + * @param[out] jlp: 将JLP(Joylink Parameters)读入内存,并赋值给该参数 + * + * @returns: E_RET_OK:成功, E_RET_ERROR:发生错误 + */ +// read feedid, accesskey, localkey, joylink_server, server_port, gURLStr, gTokenStr from flash +E_JLRetCode_t +joylink_dev_get_jlp_info(JLPInfo_t *jlp) +{ + if (NULL == jlp) { + return -1; + } + int ret = E_RET_OK; +#if 1 + char buff[256]; + memset(buff, 0, sizeof(buff)); + if (!joylink_get_accesskey(buff, sizeof(buff))) { + log_debug("-->accesskey:%s\n", buff); + joylink_parse_jlp(jlp, buff); + } else { + log_error("get accesskey error"); + } + + memset(buff, 0, sizeof(buff)); + if (!joylink_get_localkey(buff, sizeof(buff))) { + log_debug("-->localkey:%s\n", buff); + joylink_parse_jlp(jlp, buff); + } else { + log_error("get localkey error"); + } + + memset(buff, 0, sizeof(buff)); + if (!joylink_get_feedid(buff, sizeof(buff))) { + log_debug("-->feedid:%s\n", buff); + joylink_parse_jlp(jlp, buff); + } else { + log_error("get feedid error"); + } + + memset(buff, 0, sizeof(buff)); + if (!joylink_get_server_info(buff, sizeof(buff))) { + log_info("-->server_info:%s\n", buff); + joylink_util_cut_ip_port(buff, jlp->joylink_server, &jlp->server_port); + } else { + log_error("get server_info error"); + } + + memset(buff, 0, sizeof(buff)); + if (!joylink_get_version(buff, sizeof(buff))) { + log_info("-->version:%s\n", buff); + joylink_parse_jlp(jlp, buff); + } else { + log_error("get version error"); + } +#else + + JLPInfo_t fjlp; + memset(&fjlp, 0, sizeof(JLPInfo_t)); + +#ifdef _SAVE_FILE_ + FILE *infile; + infile = fopen(file, "rb+"); + if (infile > 0) { + fread(&fjlp, sizeof(fjlp), 1, infile); + fclose(infile); + + strcpy(user_jlp.feedid, fjlp.feedid); + strcpy(user_jlp.accesskey, fjlp.accesskey); + strcpy(user_jlp.localkey, fjlp.localkey); + strcpy(user_jlp.joylink_server, fjlp.joylink_server); + user_jlp.server_port = fjlp.server_port; + } +#endif + strcpy(jlp->feedid, user_jlp.feedid); + strcpy(jlp->accesskey, user_jlp.accesskey); + strcpy(jlp->localkey, user_jlp.localkey); + strcpy(jlp->joylink_server, user_jlp.joylink_server); + jlp->server_port = user_jlp.server_port; +#endif + + if (joylink_dev_get_user_mac(jlp->mac) < 0) { + strcpy(jlp->mac, user_jlp.mac); + } + + if (joylink_dev_get_private_key(jlp->prikey) < 0) { + strcpy(jlp->prikey, user_jlp.prikey); + } + + jlp->version = user_jlp.version; + strcpy(jlp->uuid, user_jlp.uuid); + jlp->devtype = user_jlp.devtype; + jlp->lancon = user_jlp.lancon; + jlp->cmd_tran_type = user_jlp.cmd_tran_type; + + jlp->noSnapshot = user_jlp.noSnapshot; + //strcpy(jlp->joySdkVersion, user_jlp.joySdkVersion);//2.1.21 delete + return ret; +} + +/** + * @brief: 返回设备状态,通过填充user_data参数,返回设备当前状态 + * + * @param[out] user_data: 设备状态结构体指针 + * + * @returns: 0 + */ +int +joylink_dev_user_data_get(user_dev_status_t *user_data) +{ + user_data->Power = user_dev.Power; + user_data->Mode = user_dev.Mode; + user_data->State = user_dev.State; + log_info("dev current Power: %d Mode: %d State: %d Heap: %d", user_data->Power, user_data->Mode, user_data->State, xPortGetFreeHeapSize()); + return 0; +} + +/** + * @brief: 获取设备快照json结构,结构中包含返回状态码 + * + * @param[in] ret_code: 返回状态码 + * @param[out] out_snap: 序列化为字符串的设备快照json结构 + * @param[in] out_max: out_snap可写入的最大长度 + * + * @returns: 实际写入out_snap的数据长度 + */ +int +joylink_dev_get_snap_shot_with_retcode(int32_t ret_code, char *out_snap, int32_t out_max) +{ + if (NULL == out_snap || out_max < 0) { + return 0; + } + int len = 0; + joylink_dev_user_data_get(&user_dev); + char *packet_data = joylink_dev_package_info(ret_code, &user_dev); + if (NULL != packet_data) { + len = jl_platform_strlen(packet_data); + log_info("------>%s:len:%d\n", packet_data, len); + if (len < out_max) { + jl_platform_memcpy(out_snap, packet_data, len); + } else { + len = 0; + } + } + + if (NULL != packet_data) { + jl_platform_free(packet_data); + } + return len; +} + +/** + * @brief: 获取设备快照json结构 + * + * @param[out] out_snap: 序列化为字符串的设备快照json结构 + * @param[in] out_max: out_snap可写入的最大长度 + * + * @returns: 实际写入out_snap的数据长度 + */ +int +joylink_dev_get_snap_shot(char *out_snap, int32_t out_max) +{ + return joylink_dev_get_snap_shot_with_retcode(0, out_snap, out_max); +} + +/** + * @brief: 获取向App返回的设备快照json结构 + * + * @param[out] out_snap: 序列化为字符串的设备快照json结构 + * @param[in] out_max: out_snap允许写入的最大长度 + * @param[in] code: 返回状态码 + * @param[in] feedid: 设备的feedid + * + * @returns: + */ +int +joylink_dev_get_json_snap_shot(char *out_snap, int32_t out_max, int code, char *feedid) +{ + jl_platform_sprintf(out_snap, "{\"code\":%d, \"feedid\":\"%s\"}", code, feedid); + return jl_platform_strlen(out_snap); +} + +/** + * @brief: 通过App控制设备,需要实现此函数,根据传入的json_cmd对设备进行控制 + * + * @param[in] json_cmd: 设备控制命令 + * + * @returns: E_RET_OK:控制成功, E_RET_ERROR:发生错误 + */ +E_JLRetCode_t +joylink_dev_lan_json_ctrl(const char *json_cmd) +{ + log_debug("json ctrl:%s", json_cmd); + return E_RET_OK; +} + +/** + * @brief: 根据传入的cmd值,设置对应设备属性 + * + * @param[in] cmd: 设备属性名称 + * @param[out] user_data: 设备状态结构体 + * + * @returns: E_RET_OK 设置成功 + */ +E_JLRetCode_t +joylink_dev_user_data_set(char *cmd, user_dev_status_t *user_data) +{ + user_dev.Power = user_data->Power; + user_dev.Mode = user_data->Mode; + user_dev.State = user_data->State; + log_info("set dev Power: %d Mode: %d State: %d", user_dev.Power, user_dev.Mode, user_dev.State); + return E_RET_OK; +} + +/** + * @brief:根据src参数传入的控制命令数据包对设备进行控制.调用joylink_dev_parse_ctrl进行控制命令解析,并更改设备属性值 + * + * @param[in] src: 控制指令数据包 + * @param[in] src_len: src长度 + * @param[in] ctr: 控制码 + * @param[in] from_server: 是否来自server控制 0-App,2-Server + * + * @returns: E_RET_OK 成功, E_RET_ERROR 失败 + */ +E_JLRetCode_t +joylink_dev_script_ctrl(const char *src, int src_len, JLContrl_t *ctr, int from_server) +{ + if (NULL == src || NULL == ctr) { + return E_RET_ERROR; + } + + int ret = -1; + ctr->biz_code = (int)(*((int *)(src + 4))); + ctr->serial = (int)(*((int *)(src + 8))); + + uint32_t tt = jl_time_get_timestamp(NULL); + log_info("bcode:%d:server:%d:time:%ld", ctr->biz_code, from_server, (long)tt); + + if (ctr->biz_code == JL_BZCODE_GET_SNAPSHOT) { + ret = E_RET_OK; + } else if (ctr->biz_code == JL_BZCODE_CTRL) { + joylink_dev_parse_ctrl(src + 12, &user_dev); + return E_RET_OK; + } else if (ctr->biz_code == JL_BZCODE_MENU) { + joylink_dev_parse_ctrl(src + 12, &user_dev); + return E_RET_OK; + } else { + char buf[50]; + jl_platform_sprintf(buf, "Unknown biz_code:%d", ctr->biz_code); + log_error("%s", buf); + } + return ret; +} + +/** + * @brief: 实现接收到ota命令和相关参数后的动作,可使用otaOrder提供的参数进行具体的OTA操作 + * + * @param[in] otaOrder: OTA命令结构体 + * + * @returns: E_RET_OK 成功, E_RET_ERROR 发生错误 + */ +E_JLRetCode_t +joylink_dev_ota(JLOtaOrder_t *otaOrder) +{ + jl_dev_ota_z2(otaOrder); + return E_RET_OK; +} + +/** + * @brief: OTA执行状态上报,无需返回值 + */ +void +joylink_dev_ota_status_upload() +{ + return; +} + +static int joylink_dev_http_parse_content( + char *response, + int response_len, + char *content, + int content_len) +{ + int length = 0; + content[0] = 0; + char *p = jl_platform_strstr(response, "\r\n\r\n"); + if (p == NULL) { + return -1; + } + p += 4; + length = response_len - (p - response); + length = length > content_len ? content_len - 1 : length; + jl_platform_strncpy(content, p, length); + content[length] = 0; + // log_info("content = \r\n%s", content); + + return length; +} + +#if CONFIG_USE_POLARSSL +static int jl_my_random(void *p_rng, unsigned char *output, size_t output_len) +{ + rtw_get_random_bytes(output, output_len); + return 0; +} + +int joylink_dev_https_post(char *host, char *query, char *revbuf, int buflen) +{ + int ret = 0; + int server_fd = -1; + struct sockaddr_in server_addr; + ssl_context ssl; + + memory_set_own(pvPortMalloc, vPortFree); + memset(&ssl, 0, sizeof(ssl_context)); + + if ((ret = net_connect(&server_fd, host, 443)) != 0) { + log_error("ERROR: net_connect ret(%d)", ret); + goto exit; + } + + if ((ret = ssl_init(&ssl)) != 0) { + log_error("ERROR: ssl_init ret(%d)", ret); + goto exit; + } + + ssl_set_endpoint(&ssl, SSL_IS_CLIENT); + ssl_set_authmode(&ssl, SSL_VERIFY_NONE); + ssl_set_rng(&ssl, jl_my_random, NULL); + ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd); + + if ((ret = ssl_handshake(&ssl)) != 0) { + log_error("ERROR: ssl_handshake ret(-0x%x)", -ret); + goto exit; + } else { + char buf[1400] = {0}; + int read_size = 0, resource_size = 0, content_len = 0, header_removed = 0, recv_finish = 0; + + log_info("SSL ciphersuite %s", ssl_get_ciphersuite(&ssl)); + ssl_write(&ssl, query, strlen(query)); + log_info("query=[%s]", query); // + while ((!recv_finish) && ((read_size = ssl_read(&ssl, buf, 1400 - 1)) > 0)) { + + char *response_end = NULL; + response_end = strstr(buf, "\"code\":0}}"); + if (response_end) { + recv_finish = 1; + } + + if (header_removed == 0) { + char *header = NULL; + header = strstr(buf, "\r\n\r\n"); + + if (header) { + char *body, *content_len_pos; + body = header + strlen("\r\n\r\n"); + *(body - 2) = 0; + header_removed = 1; + + // Remove header size to get first read size of data from body head + strcpy(revbuf, body); + resource_size = read_size - (body - buf); + + content_len_pos = strstr(revbuf, "Content-Length: "); + if (content_len_pos) { + content_len_pos += strlen("Content-Length: "); + *(char *)(strstr(content_len_pos, "\r\n")) = 0; + content_len = atoi(content_len_pos); + } + memset(buf, 0, 1400); + } else { + memset(buf, 0, 1400); + } + } else { + strcpy(revbuf + resource_size, buf); + resource_size += read_size; + memset(buf, 0, 1400); + } + } + + log_debug("https response is %s", revbuf); + log_debug("https content-length = %d bytes, download resource size = %d bytes", content_len, resource_size); + } + +exit: + + if (server_fd >= 0) { + net_close(server_fd); + } + + ssl_free(&ssl); + return ret; +} + +#elif CONFIG_USE_MBEDTLS +static int jl_my_random(void *p_rng, unsigned char *output, size_t output_len) +{ + rtw_get_random_bytes(output, output_len); + return 0; +} + +static void *jl_my_calloc(size_t nelements, size_t elementSize) +{ + size_t size; + void *ptr = NULL; + size = nelements * elementSize; + ptr = pvPortMalloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} +static char *jl_atcmd_lwip_itoa(int value) +{ + char *val_str; + int tmp = value, len = 1; + + while ((tmp /= 10) > 0) { + len ++; + } + val_str = (char *) pvPortMalloc(len + 1); + sprintf(val_str, "%d", value); + return val_str; +} + +int joylink_dev_https_post(char *host, char *query, char *revbuf, int buflen) +{ + + int ret = 0; + mbedtls_net_context server_fd; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + + mbedtls_platform_set_calloc_free(jl_my_calloc, vPortFree); + mbedtls_net_init(&server_fd); + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + + int port = 443; + char *jl_port_str = jl_atcmd_lwip_itoa(port); + if ((ret = mbedtls_net_connect(&server_fd, host, jl_port_str, MBEDTLS_NET_PROTO_TCP)) != 0) { + log_error("ERROR: mbedtls_net_connect ret(%d)", ret); + goto exit; + } + + mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); + if ((ret = mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { + log_error("ERRPR: mbedtls_ssl_config_defaults ret(%d)", ret); + goto exit; + } + + mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); + mbedtls_ssl_conf_rng(&conf, jl_my_random, NULL); + if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { + log_error("ERRPR: mbedtls_ssl_setup ret(%d)", ret); + goto exit; + } + + if ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { + log_error("ERROR: mbedtls_ssl_handshake ret(-0x%x)", -ret); + goto exit; + } else { + char buf[1400] = {0}; + int read_size = 0, resource_size = 0, content_len = 0, header_removed = 0, recv_finish = 0; + + log_info("SSL ciphersuite %s", mbedtls_ssl_get_ciphersuite(&ssl)); + mbedtls_ssl_write(&ssl, query, strlen(query)); + log_info("query=\r\n%s", query); + while ((!recv_finish) && ((read_size = mbedtls_ssl_read(&ssl, buf, 1400 - 1)) > 0)) { + log_info("read buf=\r\n%s", buf); + + char *response_end = NULL; + response_end = strstr(buf, "\"code\":0}}"); + if (response_end) { + recv_finish = 1; + } + + if (header_removed == 0) { + char *header = NULL; + //header = strstr(revbuf, "\r\n\r\n"); + header = strstr(buf, "\r\n\r\n");//fix + + if (header) { + char *body, *content_len_pos; + body = header + strlen("\r\n\r\n"); + *(body - 2) = 0; + header_removed = 1; + + // Remove header size to get first read size of data from body head + strcpy(revbuf, body); + resource_size = read_size - (body - buf); + + content_len_pos = strstr(revbuf, "Content-Length: "); + if (content_len_pos) { + content_len_pos += strlen("Content-Length: "); + *(strstr(content_len_pos, "\r\n")) = 0; + content_len = atoi(content_len_pos); + } + memset(buf, 0, 1400); + } else { + memset(buf, 0, 1400); + } + } else { + strcpy(revbuf + resource_size, buf); + resource_size += read_size; + memset(buf, 0, 1400); + } + } + + log_debug("https response is %s", revbuf); + log_debug("https content-length = %d bytes, download resource size = %d bytes", content_len, resource_size); + } + +exit: + mbedtls_net_free(&server_fd); + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + return ret; +} +#endif + +/** + * @brief 实现HTTP的POST请求,请求响应填入revbuf参数. + * + * @param[in] host: POST请求的目标主机 + * @param[in] query: POST请求的路径、HEADER和Payload + * @param[out] revbuf: 填入请求的响应信息的Body + * @param[in] buflen: revbuf的最大长度 + * + * @returns: 负值 - 发生错误, 非负 - 实际填充revbuf的长度 + * + * @note: 此函数必须正确实现,否者设备无法校时,无法正常激活绑定 + * + * */ +int joylink_dev_http_post(char *host, char *query, char *revbuf, int buflen) +{ +#if 1 + int log_socket = -1; + int len = 0; + int ret = -1; + char *recv_buf = NULL; + jl_sockaddr_in saServer; + char ip[20] = {0}; + + if (host == NULL || query == NULL || revbuf == NULL) { + log_error("DNS lookup failed"); + goto RET; + } + + memset(ip, 0, sizeof(ip)); + // ret = joylink_dev_get_host_ip(host, ip); + ret = jl_platform_gethostbyname(host, ip, SOCKET_IP_ADDR_LEN); + if (ret < 0) { + log_error("get ip error"); + ret = -1; + goto RET; + } + + memset(&saServer, 0, sizeof(saServer)); + saServer.sin_family = jl_platform_get_socket_proto_domain(JL_SOCK_PROTO_DOMAIN_AF_INET); + saServer.sin_port = jl_platform_htons(80); + saServer.sin_addr.s_addr = jl_platform_inet_addr(ip); + + log_socket = jl_platform_socket(JL_SOCK_PROTO_DOMAIN_AF_INET, JL_SOCK_PROTO_TYPE_SOCK_STREAM, JL_SOCK_PROTO_PROTO_IPPROTO_TCP); + if (log_socket < 0) { + log_error("... Failed to allocate socket."); + goto RET; + } + int reuseaddrEnable = 1; + if (jl_platform_setsockopt(log_socket, + JL_SOCK_OPT_LEVEL_SOL_SOCKET, + JL_SOCK_OPT_NAME_SO_REUSEADDR, + (uint8_t *)&reuseaddrEnable, + sizeof(reuseaddrEnable)) < 0) { + log_error("set SO_REUSEADDR error"); + } + + /*fcntl(log_socket,F_SETFL,fcntl(log_socket,F_GETFL,0)|O_NONBLOCK);*/ + + if (jl_platform_connect(log_socket, (jl_sockaddr *)&saServer, sizeof(saServer)) != 0) { + log_error("... socket connect failed"); + goto RET; + } + + if (jl_platform_send(log_socket, query, jl_platform_strlen(query), 5000, 0) < 0) { + log_error("... socket send failed"); + goto RET; + } + + struct timeval receiving_timeout; + receiving_timeout.tv_sec = 5; + receiving_timeout.tv_usec = 0; + if (jl_platform_setsockopt(log_socket, + JL_SOCK_OPT_LEVEL_SOL_SOCKET, + JL_SOCK_OPT_NAME_SO_RCVTIMEO, + &receiving_timeout, + sizeof(receiving_timeout)) < 0) { + log_error("... failed to set socket receiving timeout"); + goto RET; + } + + int recv_buf_len = 1024; //2048; + recv_buf = (char *)jl_platform_malloc(recv_buf_len); + if (recv_buf == NULL) { + goto RET; + } + jl_platform_memset(recv_buf, 0, recv_buf_len); + len = jl_platform_recv(log_socket, recv_buf, recv_buf_len, 0, 0); + if (len <= 0) { + ret = -1; + goto RET; + } + log_info("... read data length = %d, response data = \r\n%s", len, recv_buf); + ret = joylink_dev_http_parse_content(recv_buf, len, revbuf, buflen); + +RET: + if (-1 != log_socket) { + jl_platform_close(log_socket); + } + if (recv_buf) { + /* code */ + jl_platform_free(recv_buf); + } + + return ret; +#else + return -1; +#endif + +} + +/** + * @brief: SDK main loop 运行状态报告,正常情况下此函数每5秒会被调用一次,可以用来判断SDK主任务的运行状态. + * + * @param[in] status: SDK main loop运行状态 0正常, -1异常 + * + * @return: reserved 当前此函数仅做通知,调用方不关心返回值. + */ +int joylink_dev_run_status(JLRunStatus_t status) +{ + return -1; +} + +/** + * @brief: 每间隔1个main loop周期此函数将在SDK main loop中被调用,让用户有机会将代码逻辑运行在核心任务中. + * + * @note: 正常情况下一个main loop周期为1s(取决于socket等待接收数据的timeout时间),但不保证精度,请勿用作定时器 + * @note: 仅用作关键的非阻塞任务执行,例如OTA状态上报或设备状态上报. + * @note: 执行阻塞或耗时较多的代码,将会妨碍主task运行. + */ +void joylink_dev_run_user_code() +{ + //You may add some code run in the main loop if necessary. +} + +/** + * @brief: Erase wifi and joylink info. + * @usage: Input command "ATCJ" + */ + +// for ATCJ +void joylink_erase() +{ + flash_t flash; + if (_g_pdev->lan_socket != -1) { + lwip_close(_g_pdev->lan_socket); + } + if (_g_pdev->server_socket != -1) { + lwip_close(_g_pdev->server_socket); + } + LwIP_DHCP(0, DHCP_RELEASE_IP); + LwIP_DHCP(0, DHCP_STOP); + vTaskDelay(10); + fATWD(NULL); + vTaskDelay(20); + flash_erase_sector(&flash, FAST_RECONNECT_DATA); + // flash_erase_sector(&flash, FLASH_ADD_WIFI_ATTR); + flash_erase_sector(&flash, FLASH_ADD_JLP_INFO); + sys_reset(); + +} + diff --git a/component/common/application/mqtt/MQTTClient/MQTTFreertos.c b/component/common/application/mqtt/MQTTClient/MQTTFreertos.c index cb236b0b..929a804c 100644 --- a/component/common/application/mqtt/MQTTClient/MQTTFreertos.c +++ b/component/common/application/mqtt/MQTTClient/MQTTFreertos.c @@ -718,10 +718,27 @@ int NetworkConnect(Network* n, char* addr, int port) mbedtls_ssl_set_bio(n->ssl, &n->my_socket, mbedtls_net_send, mbedtls_net_recv, NULL); mbedtls_ssl_conf_rng(n->conf, my_random, NULL); +#if MBEDTLS_SSL_MAX_CONTENT_LEN == 512 + if(mbedtls_ssl_conf_max_frag_len(n->conf, MBEDTLS_SSL_MAX_FRAG_LEN_512) < 0) { + printf("ssl conf max frag len failed!"); + goto err; + } +#elif MBEDTLS_SSL_MAX_CONTENT_LEN == 1024 + if(mbedtls_ssl_conf_max_frag_len(n->conf, MBEDTLS_SSL_MAX_FRAG_LEN_1024) < 0) { + printf("ssl conf max frag len failed!"); + goto err; + } +#elif MBEDTLS_SSL_MAX_CONTENT_LEN == 2048 + if(mbedtls_ssl_conf_max_frag_len(n->conf, MBEDTLS_SSL_MAX_FRAG_LEN_2048) < 0) { + printf("ssl conf max frag len failed!"); + goto err; + } +#elif MBEDTLS_SSL_MAX_CONTENT_LEN == 4096 if(mbedtls_ssl_conf_max_frag_len(n->conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { printf("ssl conf max frag len failed!"); goto err; } +#endif if((mbedtls_ssl_setup(n->ssl, n->conf)) != 0) { mqtt_printf(MQTT_DEBUG,"mbedtls_ssl_setup failed!"); @@ -758,7 +775,7 @@ int NetworkConnect(Network* n, char* addr, int port) mbedtls_x509_crt_init(client_crt); #if !defined(configENABLE_TRUSTZONE) || (configENABLE_TRUSTZONE == 0) || !defined(CONFIG_SSL_CLIENT_PRIVATE_IN_TZ) || (CONFIG_SSL_CLIENT_PRIVATE_IN_TZ == 0) - client_rsa = (mbedtls_pk_context *) mbedtls_calloc( sizeof(mbedtls_pk_context), 1); + client_rsa = (mbedtls_pk_context *) mbedtls_calloc( sizeof(mbedtls_pk_context), 1); if ( client_rsa == NULL ) { mqtt_printf(MQTT_DEBUG, "malloc client_rsa failed!"); goto err; @@ -772,22 +789,30 @@ int NetworkConnect(Network* n, char* addr, int port) } #if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) && defined(CONFIG_SSL_CLIENT_PRIVATE_IN_TZ) && (CONFIG_SSL_CLIENT_PRIVATE_IN_TZ == 1) - extern mbedtls_pk_context* NS_ENTRY secure_mbedtls_pk_parse_key(void); - client_rsa = secure_mbedtls_pk_parse_key(); - if ( client_rsa == NULL ) { - mqtt_printf(MQTT_DEBUG, "s_parse client_rsa failed!"); - goto err; - } -#else + extern mbedtls_pk_context* NS_ENTRY secure_mbedtls_pk_parse_key(void); + client_rsa = secure_mbedtls_pk_parse_key(); + if ( client_rsa == NULL ) { + mqtt_printf(MQTT_DEBUG, "parse client_rsa failed!"); + goto err; + } +#else + +#if CONFIG_MBEDTLS_VERSION3 == 1 + if ( mbedtls_pk_parse_key(client_rsa, (const unsigned char *)n->private_key, strlen(n->private_key)+1, NULL, 0, rtw_get_random_bytes_f_rng, 1 ) != 0 ) { +#else if ( mbedtls_pk_parse_key(client_rsa, (const unsigned char *)n->private_key, strlen(n->private_key)+1, NULL, 0) != 0 ) { - mqtt_printf(MQTT_DEBUG, "ns_parse client_rsa failed!"); +#endif + mqtt_printf(MQTT_DEBUG, "parse client_rsa failed!"); goto err; } #endif mbedtls_ssl_conf_own_cert(n->conf, client_crt, client_rsa); } - + + if( mbedtls_ssl_set_hostname( n->ssl, addr ) == 0 ) + mqtt_printf(MQTT_DEBUG, "tls server name indication extension exist"); + retVal = mbedtls_ssl_handshake(n->ssl); if (retVal < 0) { mqtt_printf(MQTT_DEBUG, "ssl handshake failed err:-0x%04X", -retVal); @@ -818,8 +843,13 @@ int NetworkConnect(Network* n, char* addr, int port) err: if (client_rsa) { +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) && defined(CONFIG_SSL_CLIENT_PRIVATE_IN_TZ) && (CONFIG_SSL_CLIENT_PRIVATE_IN_TZ == 1) + extern void NS_ENTRY secure_mbedtls_pk_free(mbedtls_pk_context *pk); + secure_mbedtls_pk_free(client_rsa); +#else mbedtls_pk_free(client_rsa); mbedtls_free(client_rsa); +#endif } if (client_crt) { mbedtls_x509_crt_free(client_crt); diff --git a/component/common/application/mqtt/MQTTClient/MQTTFreertos.h b/component/common/application/mqtt/MQTTClient/MQTTFreertos.h index d2d8a655..e371576a 100644 --- a/component/common/application/mqtt/MQTTClient/MQTTFreertos.h +++ b/component/common/application/mqtt/MQTTClient/MQTTFreertos.h @@ -33,7 +33,11 @@ #include "polarssl/error.h" #include "polarssl/memory.h" #elif CONFIG_USE_MBEDTLS +#if CONFIG_MBEDTLS_VERSION3 == 1 +#include "mbedtls/build_info.h" +#else #include "mbedtls/config.h" +#endif #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.c b/component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.c new file mode 100644 index 00000000..8762345e --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.c @@ -0,0 +1,418 @@ +/******************************************************************************* +* Copyright (c) 2017 IBM Corp. +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* and Eclipse Distribution License v1.0 which accompany this distribution. +* +* The Eclipse Public License is available at +* http://www.eclipse.org/legal/epl-v10.html +* and the Eclipse Distribution License is available at +* http://www.eclipse.org/org/documents/edl-v10.php. +* +* Contributors: +* Ian Craggs - initial API and implementation and/or initial documentation +*******************************************************************************/ + +#include "MQTTV5Packet.h" +#include "MQTTClient.h" +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +struct nameToType +{ + enum PropertyNames name; + enum PropertyTypes type; +} namesToTypes[] = +{ + {PAYLOAD_FORMAT_INDICATOR, BYTE}, + {MESSAGE_EXPIRY_INTERVAL, FOUR_BYTE_INTEGER}, + {CONTENT_TYPE, UTF_8_ENCODED_STRING}, + {RESPONSE_TOPIC, UTF_8_ENCODED_STRING}, + {CORRELATION_DATA, BINARY_DATA}, + {SUBSCRIPTION_IDENTIFIER, VARIABLE_BYTE_INTEGER}, + {SESSION_EXPIRY_INTERVAL, FOUR_BYTE_INTEGER}, + {ASSIGNED_CLIENT_IDENTIFER, UTF_8_ENCODED_STRING}, + {SERVER_KEEP_ALIVE, TWO_BYTE_INTEGER}, + {AUTHENTICATION_METHOD, UTF_8_ENCODED_STRING}, + {AUTHENTICATION_DATA, BINARY_DATA}, + {REQUEST_PROBLEM_INFORMATION, BYTE}, + {WILL_DELAY_INTERVAL, FOUR_BYTE_INTEGER}, + {REQUEST_RESPONSE_INFORMATION, BYTE}, + {RESPONSE_INFORMATION, UTF_8_ENCODED_STRING}, + {SERVER_REFERENCE, UTF_8_ENCODED_STRING}, + {REASON_STRING, UTF_8_ENCODED_STRING}, + {RECEIVE_MAXIMUM, TWO_BYTE_INTEGER}, + {TOPIC_ALIAS_MAXIMUM, TWO_BYTE_INTEGER}, + {TOPIC_ALIAS, TWO_BYTE_INTEGER}, + {MAXIMUM_QOS, BYTE}, + {RETAIN_AVAILABLE, BYTE}, + {USER_PROPERTY, UTF_8_STRING_PAIR}, + {MAXIMUM_PACKET_SIZE, FOUR_BYTE_INTEGER}, + {WILDCARD_SUBSCRIPTION_AVAILABLE, BYTE}, + {SUBSCRIPTION_IDENTIFIER_AVAILABLE, BYTE}, + {SHARED_SUBSCRIPTION_AVAILABLE, BYTE} +}; + +struct nametoStringname +{ + enum PropertyNames name; + const char* namestr; +} nametoStringname[] = +{ + {PAYLOAD_FORMAT_INDICATOR, "PAYLOAD_FORMAT_INDICATOR"}, + {MESSAGE_EXPIRY_INTERVAL, "MESSAGE_EXPIRY_INTERVAL"}, + {CONTENT_TYPE, "CONTENT_TYPE"}, + {RESPONSE_TOPIC, "RESPONSE_TOPIC"}, + {CORRELATION_DATA, "CORRELATION_DATA"}, + {SUBSCRIPTION_IDENTIFIER, "SUBSCRIPTION_IDENTIFIER"}, + {SESSION_EXPIRY_INTERVAL, "SESSION_EXPIRY_INTERVAL"}, + {ASSIGNED_CLIENT_IDENTIFER, "ASSIGNED_CLIENT_IDENTIFER"}, + {SERVER_KEEP_ALIVE, "SERVER_KEEP_ALIVE"}, + {AUTHENTICATION_METHOD, "AUTHENTICATION_METHOD"}, + {AUTHENTICATION_DATA, "AUTHENTICATION_DATA"}, + {REQUEST_PROBLEM_INFORMATION, "REQUEST_PROBLEM_INFORMATION"}, + {WILL_DELAY_INTERVAL, "WILL_DELAY_INTERVAL"}, + {REQUEST_RESPONSE_INFORMATION, "REQUEST_RESPONSE_INFORMATION"}, + {RESPONSE_INFORMATION, "RESPONSE_INFORMATION"}, + {SERVER_REFERENCE, "SERVER_REFERENCE"}, + {REASON_STRING, "REASON_STRING"}, + {RECEIVE_MAXIMUM, "RECEIVE_MAXIMUM"}, + {TOPIC_ALIAS_MAXIMUM, "TOPIC_ALIAS_MAXIMUM"}, + {TOPIC_ALIAS, "TOPIC_ALIAS"}, + {MAXIMUM_QOS, "MAXIMUM_QOS"}, + {RETAIN_AVAILABLE, "RETAIN_AVAILABLE"}, + {USER_PROPERTY, "USER_PROPERTY"}, + {MAXIMUM_PACKET_SIZE, "MAXIMUM_PACKET_SIZE"}, + {WILDCARD_SUBSCRIPTION_AVAILABLE, "WILDCARD_SUBSCRIPTION_AVAILABLE"}, + {SUBSCRIPTION_IDENTIFIER_AVAILABLE, "SUBSCRIPTION_IDENTIFIER_AVAILABLE"}, + {SHARED_SUBSCRIPTION_AVAILABLE, "SHARED_SUBSCRIPTION_AVAILABLE"} +}; + +int MQTTProperty_getType(int identifier) +{ + int i, rc = -1; + + for (i = 0; i < ARRAY_SIZE(namesToTypes); ++i) + { + if (namesToTypes[i].name == identifier) + { + rc = namesToTypes[i].type; + break; + } + } + return rc; +} + +const char* MQTTProperty_stringname(int identifier) +{ + int i; + const char* rc = ""; + + for (i = 0; i < ARRAY_SIZE(nametoStringname); ++i) + { + if (nametoStringname[i].name == identifier) + { + rc = nametoStringname[i].namestr; + break; + } + } + return rc; +} + + +int MQTTProperties_len(MQTTProperties* props) +{ + /* properties length is an mbi */ + return props->length + MQTTPacket_VBIlen(props->length); +} + + +int MQTTProperties_add(MQTTProperties* props, MQTTProperty* prop) +{ + int rc = 0, type; + + if (props->count == props->max_count) + rc = -1; /* max number of properties already in structure */ + else if ((type = MQTTProperty_getType(prop->identifier)) < 0) + rc = -2; + else + { + int len = 0; + + props->array[props->count++] = *prop; + /* calculate length */ + switch (type) + { + case BYTE: + len = 1; + break; + case TWO_BYTE_INTEGER: + len = 2; + break; + case FOUR_BYTE_INTEGER: + len = 4; + break; + case VARIABLE_BYTE_INTEGER: + if (prop->value.integer4 >= 0 && prop->value.integer4 <= 127) + len = 1; + else if (prop->value.integer4 >= 128 && prop->value.integer4 <= 16383) + len = 2; + else if (prop->value.integer4 >= 16384 && prop->value.integer4 < 2097151) + len = 3; + else if (prop->value.integer4 >= 2097152 && prop->value.integer4 < 268435455) + len = 4; + break; + case BINARY_DATA: + case UTF_8_ENCODED_STRING: + len = 2 + prop->value.data.len; + break; + case UTF_8_STRING_PAIR: + len = 2 + prop->value.data.len; + len += 2 + prop->value.value.len; + break; + } + props->length += len + 1; /* add identifier byte */ + } + + return rc; +} + + +int MQTTProperty_write(unsigned char** pptr, MQTTProperty* prop) +{ + int rc = -1, + type = -1; + + type = MQTTProperty_getType(prop->identifier); + if (type >= BYTE && type <= UTF_8_STRING_PAIR) + { + writeChar(pptr, prop->identifier); + switch (type) + { + case BYTE: + writeChar(pptr, prop->value.byte); + rc = 1; + break; + case TWO_BYTE_INTEGER: + writeInt(pptr, prop->value.integer2); + rc = 2; + break; + case FOUR_BYTE_INTEGER: + writeInt4(pptr, prop->value.integer4); + rc = 4; + break; + case VARIABLE_BYTE_INTEGER: + rc = MQTTPacket_encode(*pptr, prop->value.integer4); + break; + case BINARY_DATA: + case UTF_8_ENCODED_STRING: + writeMQTTLenString(pptr, prop->value.data); + rc = prop->value.data.len + 2; /* include length field */ + break; + case UTF_8_STRING_PAIR: + writeMQTTLenString(pptr, prop->value.data); + writeMQTTLenString(pptr, prop->value.value); + rc = prop->value.data.len + prop->value.value.len + 4; /* include length fields */ + break; + } + } + return rc + 1; /* include identifier byte */ +} + + +/** +* write the supplied properties into a packet buffer +* @param pptr pointer to the buffer - move the pointer as we add data +* @param remlength the max length of the buffer +* @return whether the write succeeded or not, number of bytes written or < 0 +*/ +int MQTTProperties_write(unsigned char** pptr, MQTTProperties* properties) +{ + int rc = -1; + int i = 0, len = 0; + /* write the entire property list length first */ + *pptr += MQTTPacket_encode(*pptr, properties->length); + len = rc = 1; + for (i = 0; i < properties->count; ++i) + { + rc = MQTTProperty_write(pptr, &properties->array[i]); + if (rc < 0) + break; + else + len += rc; + } + if (rc >= 0) + rc = len; + return rc; +} + + +int MQTTProperty_read(MQTTProperty* prop, unsigned char** pptr, unsigned char* enddata) +{ + int type = -1, + len = 0; + + prop->identifier = readChar(pptr); + type = MQTTProperty_getType(prop->identifier); + if (type >= BYTE && type <= UTF_8_STRING_PAIR) + { + switch (type) + { + case BYTE: + prop->value.byte = readChar(pptr); + len = 1; + break; + case TWO_BYTE_INTEGER: + prop->value.integer2 = readInt(pptr); + len = 2; + break; + case FOUR_BYTE_INTEGER: + prop->value.integer4 = readInt4(pptr); + len = 4; + break; + case VARIABLE_BYTE_INTEGER: + len = MQTTPacket_decodeBuf(*pptr, &prop->value.integer4); + *pptr += len; + break; + case BINARY_DATA: + case UTF_8_ENCODED_STRING: + len = MQTTLenStringRead(&prop->value.data, pptr, enddata); + break; + case UTF_8_STRING_PAIR: + len = MQTTLenStringRead(&prop->value.data, pptr, enddata); + len += MQTTLenStringRead(&prop->value.value, pptr, enddata); + break; + } + } + return len + 1; /* 1 byte for identifier */ +} + + +int MQTTProperties_read(MQTTProperties* properties, unsigned char** pptr, unsigned char* enddata) +{ + int rc = 0; + int remlength = 0; + + properties->count = 0; + if (enddata - (*pptr) > 0) /* enough length to read the VBI? */ + { + *pptr += MQTTPacket_decodeBuf(*pptr, &remlength); + properties->length = remlength; + while (properties->count < properties->max_count && remlength > 0) + { + remlength -= MQTTProperty_read(&properties->array[properties->count], pptr, enddata); + properties->count++; + } + if (remlength == 0) + { + MQTTProperties_Handle(properties); + rc = 1; /* data read successfully */ + } + } + + return rc; +} + +int MQTTProperties_Handle(MQTTProperties* properties) +{ + int rc = 0; + int i = 0; + MQTTProperty *arr = properties->array; + while (arr && i < properties->count ) + { + //check for properties values that affect subequent value + MQTTProperty_check(&properties->array[i]); + if (!MQTTProperty_print(&properties->array[i])) + { + mqtt_printf(MQTT_ERROR, "Invalid Property"); + goto EXIT; + } + arr++; + i++; + } + rc = 1; +EXIT: + return rc; +} +#if defined(MQTTV5) +int MQTTProperty_check(MQTTProperty* property) +{ + switch (property->identifier) + { + case MAXIMUM_QOS: + gMAXQOSSpecified = property->value.byte; + break; + case RETAIN_AVAILABLE: + gRetainAvailable = property->value.byte; + break; + case MAXIMUM_PACKET_SIZE: + gMaxPacketSize = property->value.integer4; + break; + case SERVER_KEEP_ALIVE: + gServerKeepAlive = property->value.integer2; + default: + return 1; + } + return 1; +} +#endif + +int MQTTProperty_print(MQTTProperty* property) +{ + int type = -1; + int i = 0; + char* buf; + type = MQTTProperty_getType(property->identifier); + printf("Property ID: %s, ", MQTTProperty_stringname(property->identifier)); + if (type >= BYTE && type <= UTF_8_STRING_PAIR) + { + switch (type) + { + case BYTE: + printf("Value: %x\r\n", property->value.byte); + break; + case TWO_BYTE_INTEGER: + printf("Value: %d\r\n", property->value.integer2); + break; + case FOUR_BYTE_INTEGER: + printf("Value: %d\r\n", property->value.integer4); + break; + case VARIABLE_BYTE_INTEGER: + printf("Value: %d\r\n", property->value.integer4); + break; + case BINARY_DATA: + case UTF_8_ENCODED_STRING: + buf = property->value.data.data; + printf("Value: "); + for(i = 0;i < property->value.data.len;i++) + { + printf("%c", *buf); + buf++; + } + printf("\r\n"); + break; + case UTF_8_STRING_PAIR: + buf = property->value.data.data; + printf("String Pair Key: "); + for(i = 0;i < property->value.data.len;i++) + { + printf("%c", *buf); + buf++; + } + printf(", "); + buf = property->value.value.data; + printf("String Pair Value: "); + for(i = 0;i < property->value.value.len;i++) + { + printf("%c", *buf); + buf++; + } + printf("\r\n"); + break; + default: + //break incase of error format + return 0; + } + } + return 1; +} diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.h new file mode 100644 index 00000000..4f6dab16 --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.h @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ +#ifndef __MQTTProperties_h__ + #define __MQTTProperties_h__ + +#include "platform_opts.h" + +#if defined(MQTTV5) +static int gMAXQOSSpecified = 2; +static int gRetainAvailable = 1; +static int gMaxPacketSize = 2147483647; //2^21-1 +static int gServerKeepAlive = -1; +#endif + +enum PropertyNames { + PAYLOAD_FORMAT_INDICATOR = 1, + MESSAGE_EXPIRY_INTERVAL = 2, + CONTENT_TYPE = 3, + RESPONSE_TOPIC = 8, + CORRELATION_DATA = 9, + SUBSCRIPTION_IDENTIFIER = 11, + SESSION_EXPIRY_INTERVAL = 17, + ASSIGNED_CLIENT_IDENTIFER = 18, + SERVER_KEEP_ALIVE = 19, + AUTHENTICATION_METHOD = 21, + AUTHENTICATION_DATA = 22, + REQUEST_PROBLEM_INFORMATION = 23, + WILL_DELAY_INTERVAL = 24, + REQUEST_RESPONSE_INFORMATION = 25, + RESPONSE_INFORMATION = 26, + SERVER_REFERENCE = 28, + REASON_STRING = 31, + RECEIVE_MAXIMUM = 33, + TOPIC_ALIAS_MAXIMUM = 34, + TOPIC_ALIAS = 35, + MAXIMUM_QOS = 36, + RETAIN_AVAILABLE = 37, + USER_PROPERTY = 38, + MAXIMUM_PACKET_SIZE = 39, + WILDCARD_SUBSCRIPTION_AVAILABLE = 40, + SUBSCRIPTION_IDENTIFIER_AVAILABLE = 41, + SHARED_SUBSCRIPTION_AVAILABLE = 42 +}; + +enum PropertyTypes { + BYTE, + TWO_BYTE_INTEGER, + FOUR_BYTE_INTEGER, + VARIABLE_BYTE_INTEGER, + BINARY_DATA, + UTF_8_ENCODED_STRING, + UTF_8_STRING_PAIR +}; + + +typedef struct +{ + int identifier; /* mbi */ + union { + char byte; + unsigned short integer2; + int integer4; + MQTTLenString data; + MQTTLenString value; /* for user properties */ + } value; +} MQTTProperty; + +typedef struct MQTTProperties +{ + int count; /* number of property entries */ + int max_count; + int length; /* mbi: byte length of all properties */ + MQTTProperty *array; /* array of properties */ +} MQTTProperties; + +#define MQTTProperties_initializer {0, 0, 0, NULL} + +int MQTTProperties_len(MQTTProperties* props); + +/** + * Add the property pointer to the property array, no allocation, just a reference + * @param props + * @param prop + * @return whether the write succeeded or not, number of bytes written or < 0 + */ +int MQTTProperties_add(MQTTProperties* props, MQTTProperty* prop); + +int MQTTProperties_write(unsigned char** pptr, MQTTProperties* properties); + +int MQTTProperties_read(MQTTProperties* properties, unsigned char** pptr, unsigned char* enddata); +/** + * Print out MQTT Properties + * @param properties to print + * @return success or fail + */ +int MQTTProperties_Handle(MQTTProperties* properties); +/** + * Check for properties + * @param property + * @return 0 + */ +int MQTTProperty_check(MQTTProperty* property); +/** + * Print property + * @param property + * @return 1 + */ +int MQTTProperty_print(MQTTProperty* property); +#endif \ No newline at end of file diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTReasonCodes.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTReasonCodes.h new file mode 100644 index 00000000..ee3d5430 --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTReasonCodes.h @@ -0,0 +1,67 @@ +/******************************************************************************* +* Copyright (c) 2017 IBM Corp. +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* and Eclipse Distribution License v1.0 which accompany this distribution. +* +* The Eclipse Public License is available at +* http://www.eclipse.org/legal/epl-v10.html +* and the Eclipse Distribution License is available at +* http://www.eclipse.org/org/documents/edl-v10.php. +* +* Contributors: +* Ian Craggs - initial API and implementation and/or initial documentation +*******************************************************************************/ +#ifndef __MQTTREASONCODES_H__ +#define __MQTTREASONCODES_H__ + +enum ReasonCodes { + //SUCCESS = 0, + NORMAL_DISCONNECTION = 0, + GRANTED_QOS_0 = 0, + GRANTED_QOS_1 = 1, + GRANTED_QOS_2 = 2, + DISCONNECT_WITH_WILL_MESSAGE = 4, + NO_MATCHING_SUBSCRIBERS = 16, + NO_SUBSCRIPTION_FOUND = 17, + CONTINUE_AUTHENTICATION = 24, + RE_AUTHENTICATE = 25, + UNSPECIFIED_ERROR = 128, + MALFORMED_PACKET = 129, + PROTOCOL_ERROR = 130, + IMPLEMENTATION_SPECIFIC_ERROR = 131, + UNSUPPORTED_PROTOCOL_VERSION = 132, + CLIENT_IDENTIFIER_NOT_VALID = 133, + BAD_USER_NAME_OR_PASSWORD = 134, + NOT_AUTHORIZED = 135, + SERVER_UNAVAILABLE = 136, + SERVER_BUSY = 137, + BANNED = 138, + SERVER_SHUTTING_DOWN = 139, + BAD_AUTHENTICATION_METHOD = 140, + KEEP_ALIVE_TIMEOUT = 141, + SESSION_TAKEN_OVER = 142, + TOPIC_FILTER_INVALID = 143, + TOPIC_NAME_INVALID = 144, + PACKET_IDENTIFIER_IN_USE = 145, + PACKET_IDENTIFIER_NOT_FOUND = 146, + RECEIVE_MAXIMUM_EXCEEDED = 147, + TOPIC_ALIAS_INVALID = 148, + PACKET_TOO_LARGE = 149, + MESSAGE_RATE_TOO_HIGH = 150, + QUOTA_EXCEEDED = 151, + ADMINISTRATIVE_ACTION = 152, + PAYLOAD_FORMAT_INVALID = 153, + RETAIN_NOT_SUPPORTED = 154, + QOS_NOT_SUPPORTED = 155, + USE_ANOTHER_SERVER = 156, + SERVER_MOVED = 157, + SHARED_SUBSCRIPTION_NOT_SUPPORTED = 158, + CONNECTION_RATE_EXCEEDED = 159, + MAXIMUM_CONNECT_TIME = 160, + SUBSCRIPTION_IDENTIFIERS_NOT_SUPPORTED = 161, + WILDCARD_SUBSCRIPTION_NOT_SUPPORTED = 162 +}; + +#endif \ No newline at end of file diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Connect.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Connect.h new file mode 100644 index 00000000..abcdb932 --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Connect.h @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#ifndef MQTT5CONNECT_H_ +#define MQTT5CONNECT_H_ + +#include "MQTTConnect.h" +#include "MQTTClient.h" + +DLLExport int MQTTV5Serialize_connect(unsigned char* buf, int buflen, MQTTPacket_connectData* options, + MQTTProperties* connectProperties, MQTTProperties* willProperties); + +DLLExport int MQTTV5Deserialize_connect(MQTTProperties* willProperties, + MQTTProperties* connectProperties, MQTTPacket_connectData* data, unsigned char* buf, int len); + +DLLExport int MQTTV5Serialize_connack(unsigned char* buf, int buflen, unsigned char connack_rc, + unsigned char sessionPresent, MQTTProperties* connackProperties); + +DLLExport int MQTTV5Deserialize_connack(MQTTProperties* connackProperties, + unsigned char* sessionPresent, unsigned char* connack_rc, unsigned char* buf, int buflen); + +DLLExport int MQTTV5Serialize_disconnect(unsigned char* buf, int buflen, int reasonCode, + MQTTProperties* properties); + +DLLExport int MQTTV5Deserialize_disconnect(MQTTProperties* properties, int* reasonCode, + unsigned char* buf, int buflen); + +DLLExport int MQTTV5Serialize_auth(unsigned char* buf, int buflen, int reasonCode, + MQTTProperties* properties); + +DLLExport int MQTTV5Deserialize_auth(MQTTProperties* properties, int* reasonCode, + unsigned char* buf, int buflen); + +DLLExport int MQTTV5Connect(MQTTClient* c, MQTTPacket_connectData* options, MQTTProperties* connectproperties, MQTTProperties* willproperties); + +DLLExport int MQTTV5Disconnect(MQTTClient* c, int ReasonCode, MQTTProperties* DisconProperties); +#endif /* MQTTV5CONNECT_H_ */ diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.c b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.c new file mode 100644 index 00000000..79915fbb --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.c @@ -0,0 +1,79 @@ +/******************************************************************************* +* Copyright (c) 2017 IBM Corp. +* +* All rights reserved. This program and the accompanying materials +* are made available under the terms of the Eclipse Public License v1.0 +* and Eclipse Distribution License v1.0 which accompany this distribution. +* +* The Eclipse Public License is available at +* http://www.eclipse.org/legal/epl-v10.html +* and the Eclipse Distribution License is available at +* http://www.eclipse.org/org/documents/edl-v10.php. +* +* Contributors: +* Ian Craggs - initial API and implementation and/or initial documentation +*******************************************************************************/ + +#include "MQTTV5Packet.h" + +#include + +/** +* Writes an integer as 4 bytes to an output buffer. +* @param pptr pointer to the output buffer - incremented by the number of bytes used & returned +* @param anInt the integer to write +*/ +void writeInt4(unsigned char** pptr, int anInt) +{ + **pptr = (unsigned char)(anInt / 16777216); + (*pptr)++; + anInt %= 16777216; + **pptr = (unsigned char)(anInt / 65536); + (*pptr)++; + anInt %= 65536; + **pptr = (unsigned char)(anInt / 256); + (*pptr)++; + **pptr = (unsigned char)(anInt % 256); + (*pptr)++; +} + + +/** +* Calculates an integer from two bytes read from the input buffer +* @param pptr pointer to the input buffer - incremented by the number of bytes used & returned +* @return the integer value calculated +*/ +int readInt4(unsigned char** pptr) +{ + unsigned char* ptr = *pptr; + int value = 16777216*(*ptr) + 65536*(*(ptr+1)) + 256*(*(ptr+2)) + (*(ptr+3)); + *pptr += 4; + return value; +} + + +void writeMQTTLenString(unsigned char** pptr, MQTTLenString lenstring) +{ + writeInt(pptr, lenstring.len); + memcpy(*pptr, lenstring.data, lenstring.len); + *pptr += lenstring.len; +} + + +int MQTTLenStringRead(MQTTLenString* lenstring, unsigned char** pptr, unsigned char* enddata) +{ + int len = 0; + + /* the first two bytes are the length of the string */ + if (enddata - (*pptr) > 1) /* enough length to read the integer? */ + { + lenstring->len = readInt(pptr); /* increments pptr to point past length */ + if (&(*pptr)[lenstring->len] <= enddata) + { + lenstring->data = (char*)*pptr; + *pptr += lenstring->len; + len = 2 + lenstring->len; + } + } + return len; +} diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.h new file mode 100644 index 00000000..b52515dc --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.h @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#include "MQTTPacket.h" + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +extern "C" { +#endif + +#include "MQTTReasonCodes.h" + +#include "MQTTProperties.h" + +#include "MQTTV5Connect.h" + +#include "MQTTV5Publish.h" + +#include "MQTTV5Subscribe.h" + +#include "MQTTV5Unsubscribe.h" + +void writeInt4(unsigned char** pptr, int anInt); +int readInt4(unsigned char** pptr); + +void writeMQTTLenString(unsigned char** pptr, MQTTLenString lenstring); + +int MQTTLenStringRead(MQTTLenString* lenstring, unsigned char** pptr, unsigned char* enddata); + +#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */ +} +#endif diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Publish.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Publish.h new file mode 100644 index 00000000..4c888c23 --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Publish.h @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#if !defined(MQTTV5PUBLISH_H_) +#define MQTTV5PUBLISH_H_ + +#if !defined(DLLImport) + #define DLLImport +#endif +#if !defined(DLLExport) + #define DLLExport +#endif + +#include "MQTTPublish.h" +#include "MQTTClient.h" + +DLLExport int MQTTV5Serialize_publish(unsigned char* buf, int buflen, unsigned char dup, int qos, unsigned char retained, + unsigned short packetid, MQTTString topicName, MQTTProperties* props, unsigned char* payload, int payloadlen); + +DLLExport int MQTTV5Deserialize_publish(unsigned char* dup, int* qos, unsigned char* retained, unsigned short* packetid, MQTTString* topicName, + MQTTProperties* props, unsigned char** payload, int* payloadlen, unsigned char* buf, int len); + +DLLExport int MQTTV5Serialize_puback(unsigned char* buf, int buflen, unsigned short packetid, + int reasonCode, MQTTProperties* properties); + +DLLExport int MQTTV5Serialize_pubrec(unsigned char* buf, int buflen, unsigned short packetid, + int reasonCode, MQTTProperties* properties); + +DLLExport int MQTTV5Serialize_pubrel(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, + int reasonCode, MQTTProperties* properties); + +DLLExport int MQTTV5Serialize_pubcomp(unsigned char* buf, int buflen, unsigned short packetid, + int reasonCode, MQTTProperties* properties); + +DLLExport int MQTTV5Deserialize_ack(unsigned char* packettype, unsigned char* dup, unsigned short* packetid, + int *reasonCode, MQTTProperties* properties, unsigned char* buf, int buflen); + +DLLExport int MQTTV5PublishHandle(MQTTClient* c, const char* topicName, MQTTMessage* message, MQTTProperties* pubproperties); + +DLLExport int MQTTV5Serialize_ack(unsigned char* buf, int buflen, unsigned char packettype, unsigned char dup, unsigned short packetid, + int reasonCode, MQTTProperties* properties); +#endif /* MQTTV5PUBLISH_H_ */ diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Subscribe.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Subscribe.h new file mode 100644 index 00000000..ac9e9614 --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Subscribe.h @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#ifndef MQTTV5SUBSCRIBE_H_ +#define MQTTV5SUBSCRIBE_H_ + +#if !defined(DLLImport) + #define DLLImport +#endif +#if !defined(DLLExport) + #define DLLExport +#endif + +#include "MQTTClient.h" + +struct subscribeOptions +{ + unsigned char MaxQOS; /* 0 or 1 */ + unsigned char noLocal; /* 0 or 1 */ + unsigned char retainAsPublished; /* 0 or 1 */ + unsigned char retainHandling; /* 0, 1 or 2 */ +}; + +DLLExport int MQTTV5Serialize_subscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, + MQTTProperties* properties, int count, MQTTString topicFilters[], int requestedQoSs[], struct subscribeOptions options[]); + +DLLExport int MQTTV5Deserialize_subscribe(unsigned char* dup, unsigned short* packetid, MQTTProperties* properties, + int maxcount, int* count, MQTTString topicFilters[], int requestedQoSs[], struct subscribeOptions options[], + unsigned char* buf, int len); + +DLLExport int MQTTV5Serialize_suback(unsigned char* buf, int buflen, unsigned short packetid, + MQTTProperties* properties, int count, int* reasonCodes); + +DLLExport int MQTTV5Deserialize_suback(unsigned short* packetid, MQTTProperties* properties, + int maxcount, int* count, int* reasonCodes, unsigned char* buf, int len); + +DLLExport int MQTTV5Subscribe(MQTTClient* c, const char* topicFilter, struct subscribeOptions* options, + messageHandler messageHandler, MQTTProperties* subproperties); + +#endif /* MQTTV5SUBSCRIBE_H_ */ diff --git a/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Unsubscribe.h b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Unsubscribe.h new file mode 100644 index 00000000..87e98f7a --- /dev/null +++ b/component/common/application/mqtt/MQTTPacket/V5/MQTTV5Unsubscribe.h @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + * Ian Craggs - initial API and implementation and/or initial documentation + *******************************************************************************/ + +#ifndef MQTTV5UNSUBSCRIBE_H_ +#define MQTTV5UNSUBSCRIBE_H_ + +#if !defined(DLLImport) + #define DLLImport +#endif +#if !defined(DLLExport) + #define DLLExport +#endif + +DLLExport int MQTTV5Serialize_unsubscribe(unsigned char* buf, int buflen, unsigned char dup, unsigned short packetid, + MQTTProperties* properties, int count, MQTTString* topicFilters); + +DLLExport int MQTTV5Deserialize_unsubscribe(unsigned char* dup, unsigned short* packetid, MQTTProperties* properties, + int maxcount, int* count, MQTTString* topicFilters, unsigned char* buf, int len); + +DLLExport int MQTTV5Serialize_unsuback(unsigned char* buf, int buflen, unsigned short packetid, + MQTTProperties* properties, int count, int* reasonCodes); + +DLLExport int MQTTV5Deserialize_unsuback(unsigned short* packetid, MQTTProperties* properties, + int maxcount, int* count, int* reasonCodes, unsigned char* buf, int len); + +int MQTTV5Deserialize_subunsuback(int type, unsigned short* packetid, MQTTProperties* properties, + int maxcount, int* count, int* reasonCodes, unsigned char* buf, int buflen); + + +#endif /* MQTTV5UNSUBSCRIBE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/btgap.a b/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/btgap.a index 2ca82d92..ac79dda0 100644 Binary files a/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/btgap.a and b/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/btgap.a differ diff --git a/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/release_note.txt b/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/release_note.txt index 1545d93e..f09d046f 100644 --- a/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/release_note.txt +++ b/component/common/bluetooth/realtek/sdk/board/amebaz2/lib/release_note.txt @@ -2,6 +2,10 @@ /* * Release Note */ + v1.0.1.179 + 2022/06/10 + 1. Add API le_get_dev_ltk. + v1.0.1.175 2022/05/11 1. Fix a bug for multi-link notification and write command send failure issue. diff --git a/component/common/bluetooth/realtek/sdk/board/common/os/liteos/osif_liteos.c b/component/common/bluetooth/realtek/sdk/board/common/os/liteos/osif_liteos.c new file mode 100644 index 00000000..fb61b5dd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/board/common/os/liteos/osif_liteos.c @@ -0,0 +1,1090 @@ +/** + * Copyright (c) 2015, Realsil Semiconductor Corporation. All rights reserved. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cmsis.h" + +/****************************************************************************/ +/* Check if in task context (true), or isr context (false) */ +/****************************************************************************/ +static inline bool osif_task_context_check(void) +{ + return (__get_IPSR() == 0); +} + +/****************************************************************************/ +/* Delay current task in a given milliseconds */ +/****************************************************************************/ +void osif_delay(uint32_t ms) +{ + UINT32 ret; + + ret = LOS_TaskDelay(LOS_MS2Tick(ms)); + if (ret != LOS_OK) { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + } + +} + +/****************************************************************************/ +/* Get system time in milliseconds */ +/****************************************************************************/ +uint32_t osif_sys_time_get(void) +{ + return (uint32_t)LOS_Tick2MS(LOS_TickCountGet()); +} + +/****************************************************************************/ +/* Start os kernel scheduler */ +/****************************************************************************/ +bool osif_sched_start(void) +{ + return true; +} + +/****************************************************************************/ +/* Stop os kernel scheduler */ +/****************************************************************************/ +bool osif_sched_stop(void) +{ + return true; +} + +/****************************************************************************/ +/* Suspend os kernel scheduler */ +/****************************************************************************/ +bool osif_sched_suspend(void) +{ + return true; +} + +/****************************************************************************/ +/* Resume os kernel scheduler */ +/****************************************************************************/ +bool osif_sched_resume(void) +{ + return true; +} + +static inline uint16_t port_helper_prio_l2f(UINT16 priority) +{ + return configMAX_PRIORITIES - priority; +} + +static inline UINT16 port_helper_prio_f2l(uint16_t priority) +{ + return configMAX_PRIORITIES - priority; +} + +/****************************************************************************/ +/* Create os level task routine */ +/****************************************************************************/ +bool osif_task_create(void **pp_handle, const char *p_name, void (*p_routine)(void *), + void *p_param, uint16_t stack_size, uint16_t priority) +{ + UINT32 taskid, retval; + + if (pp_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + TSK_INIT_PARAM_S task_param; + memset(&task_param, 0, sizeof(task_param)); + task_param.pfnTaskEntry = (TSK_ENTRY_FUNC)p_routine; + task_param.usTaskPrio = port_helper_prio_f2l(priority); + task_param.uwArg = (UINT32)(uintptr_t)p_param; + task_param.uwStackSize = (UINT32)stack_size; + task_param.pcName = (CHAR*)p_name; + + retval = LOS_TaskCreate(&taskid, &task_param); + if (retval != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,retval); + return false; + } + + *pp_handle = OS_TCB_FROM_TID(taskid); + return true; +} + +/****************************************************************************/ +/* Delete os level task routine */ +/****************************************************************************/ +bool osif_task_delete(void *p_handle) +{ + LosTaskCB *pstTaskCB; + UINT32 ret; + UINT32 tid; + + if (p_handle == NULL) + { + tid = LOS_CurTaskIDGet(); + } else { + pstTaskCB = (LosTaskCB *)p_handle; + tid = pstTaskCB->taskID; + } + + ret = LOS_TaskDelete(tid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Suspend os level task routine */ +/****************************************************************************/ +bool osif_task_suspend(void *p_handle) +{ + LosTaskCB *pstTaskCB; + UINT32 ret; + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + pstTaskCB = (LosTaskCB *)p_handle; + + UINT32 tid = pstTaskCB->taskID; + + ret = LOS_TaskSuspend(tid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Resume os level task routine */ +/****************************************************************************/ +bool osif_task_resume(void *p_handle) +{ + LosTaskCB *pstTaskCB; + UINT32 ret; + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + pstTaskCB = (LosTaskCB *)p_handle; + UINT32 tid = pstTaskCB->taskID; + + ret = LOS_TaskResume(tid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Yield current os level task routine */ +/****************************************************************************/ +bool osif_task_yield(void) +{ + LOS_TaskYield(); + + return true; +} + +/****************************************************************************/ +/* Get current os level task routine handle */ +/****************************************************************************/ +bool osif_task_handle_get(void **pp_handle) +{ + if (*pp_handle == NULL) + { + printf("%s fail!(*pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + UINT32 tid = LOS_CurTaskIDGet(); + *pp_handle = OS_TCB_FROM_TID(tid); + + return true; +} + +/****************************************************************************/ +/* Get os level task routine priority */ +/****************************************************************************/ +bool osif_task_priority_get(void *p_handle, uint16_t *p_priority) +{ + LosTaskCB *pstTaskCB; + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + if (p_priority == NULL) + { + printf("%s fail!(p_priority == NULL)\r\n", __FUNCTION__); + return false; + } + + pstTaskCB = (LosTaskCB *)p_handle; + UINT32 tid = pstTaskCB->taskID; + + UINT16 prio = LOS_TaskPriGet(tid); + *p_priority = port_helper_prio_l2f(prio); + return true; +} + +/****************************************************************************/ +/* Set os level task routine priority */ +/****************************************************************************/ +bool osif_task_priority_set(void *p_handle, uint16_t priority) +{ + LosTaskCB *pstTaskCB; + UINT32 ret; + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + pstTaskCB = (LosTaskCB *)p_handle; + UINT32 tid = pstTaskCB->taskID; + + ret = LOS_TaskPriSet(tid, port_helper_prio_f2l(priority)); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +static void *sig_handle; +bool osif_signal_init(void) +{ + UINT32 sid, ret; + ret = LOS_SemCreate(0, &sid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + sig_handle = GET_SEM(sid); + return true; +} + +void osif_signal_deinit(void) +{ + LosSemCB *semaphore_id; + UINT32 ret; + + if (sig_handle != NULL) + { + semaphore_id = (LosSemCB *)sig_handle; + UINT32 sid = semaphore_id->semID; + ret = LOS_SemDelete(sid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + } + sig_handle = NULL; + } +} + +/****************************************************************************/ +/* Send signal to target task */ +/****************************************************************************/ +bool osif_task_signal_send(void *p_handle, uint32_t signal) +{ + UINT32 ret; + + if (!sig_handle) + { + printf("osif_task_signal_send: sig_handle is null"); + return false; + } + LosSemCB *semaphore_id; + semaphore_id = (LosSemCB *)sig_handle; + + UINT32 sid = semaphore_id->semID; + + ret = LOS_SemPost(sid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; + +} + +/****************************************************************************/ +/* Receive signal in target task */ +/****************************************************************************/ +bool osif_task_signal_recv(uint32_t *p_handle, uint32_t wait_ms) +{ + UINT32 wait_ticks, ret; + + if (!sig_handle) + { + printf("osif_task_signal_recv: sig_handle is null"); + return false; + } + + wait_ticks = LOS_MS2Tick(wait_ms); + + LosSemCB *semaphore_id; + semaphore_id = (LosSemCB *)sig_handle; + + UINT32 sid = semaphore_id->semID; + + ret = LOS_SemPend(sid, wait_ticks); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Clear signal in target task */ +/****************************************************************************/ +bool osif_task_signal_clear(void *p_handle) +{ + return false; +} + +/****************************************************************************/ +/* Lock critical section */ +/****************************************************************************/ +uint32_t osif_lock(void) +{ + UINTPTR int_status = 0U; + LOS_TaskLock(); + return (uint32_t)int_status; +} + +/****************************************************************************/ +/* Unlock critical section */ +/****************************************************************************/ +void osif_unlock(uint32_t flags) +{ + UINTPTR int_status = (UINTPTR)flags; + LOS_TaskUnlock(); +} + +/****************************************************************************/ +/* Create counting semaphore */ +/****************************************************************************/ +bool osif_sem_create(void **pp_handle, uint32_t init_count, uint32_t max_count) +{ + UINT32 sid, ret; + + if (pp_handle == NULL) + { + printf("%s fail!(pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + // call internal function to use maxCount paramter + extern UINT32 OsSemCreate(UINT16 count, UINT16 maxCount, UINT32 *semHandle); + + ret = OsSemCreate((UINT16)init_count, (UINT16)max_count, &sid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + *pp_handle = GET_SEM(sid); + return true; +} + +/****************************************************************************/ +/* Delete counting semaphore */ +/****************************************************************************/ +bool osif_sem_delete(void *p_handle) +{ + LosSemCB *semaphore_id; + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + semaphore_id = (LosSemCB *)p_handle; + + UINT32 sid = semaphore_id->semID; + + ret = LOS_SemDelete(sid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + return true; +} + +/****************************************************************************/ +/* Take counting semaphore */ +/****************************************************************************/ +bool osif_sem_take(void *p_handle, uint32_t wait_ms) +{ + LosSemCB *semaphore_id; + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + semaphore_id = (LosSemCB *)p_handle; + + UINT32 sid = semaphore_id->semID; + UINT32 wait_ticks; + + wait_ticks = LOS_MS2Tick(wait_ms); + + ret = LOS_SemPend(sid, wait_ticks); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Give counting semaphore */ +/****************************************************************************/ +bool osif_sem_give(void *p_handle) +{ + LosSemCB *semaphore_id; + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + semaphore_id = (LosSemCB *)p_handle; + + UINT32 sid = semaphore_id->semID; + + ret = LOS_SemPost(sid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Create recursive mutex */ +/****************************************************************************/ +bool osif_mutex_create(void **pp_handle) +{ + UINT32 mid, ret; + + if (pp_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + ret = LOS_MuxCreate(&mid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + *pp_handle = GET_MUX(mid); + return true; +} + +/****************************************************************************/ +/* Delete recursive mutex */ +/****************************************************************************/ +bool osif_mutex_delete(void *p_handle) +{ + LosMuxCB * mux_id; + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + mux_id = (LosMuxCB *)p_handle; + UINT32 mid = mux_id->muxID; + + ret = LOS_MuxDelete(mid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + return true; +} + +/****************************************************************************/ +/* Take recursive mutex */ +/****************************************************************************/ +bool osif_mutex_take(void *p_handle, uint32_t wait_ms) +{ + LosMuxCB * mux_id; + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + mux_id = (LosMuxCB *)p_handle; + UINT32 mid = mux_id->muxID; + UINT32 wait_ticks; + + wait_ticks = LOS_MS2Tick(wait_ms); + + ret = LOS_MuxPend(mid, wait_ticks); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Give recursive mutex */ +/****************************************************************************/ +bool osif_mutex_give(void *p_handle) +{ + LosMuxCB * mux_id; + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + mux_id = (LosMuxCB *)p_handle; + UINT32 mid = mux_id->muxID; + + ret = LOS_MuxPost(mid); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Create inter-thread message queue */ +/****************************************************************************/ +bool osif_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) +{ + if (pp_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + *pp_handle = osMessageQueueNew(msg_num, msg_size, NULL); + if (*pp_handle == NULL) + { + printf("%s fail!(*pp_handle == NULL)\n", __FUNCTION__); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Delete inter-thread message queue */ +/****************************************************************************/ +bool osif_msg_queue_delete(void *p_handle) +{ + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + ret = osMessageQueueDelete(p_handle); + if (ret != osOK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Peek inter-thread message queue's pending but not received msg number */ +/****************************************************************************/ +bool osif_msg_queue_peek(void *p_handle, uint32_t *p_msg_num) +{ + if (p_handle == NULL || p_msg_num == NULL) + { + printf("%s fail!(p_handle == NULL || p_msg_num == NULL)\r\n", __FUNCTION__); + return false; + } + + *p_msg_num = osMessageQueueGetCount(p_handle); + + return true; +} + +/****************************************************************************/ +/* Send inter-thread message */ +/****************************************************************************/ +bool osif_msg_send(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + UINT32 ret; + + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + UINT32 wait_ticks; + + if (wait_ms == 0xFFFFFFFFUL) + { + wait_ticks = LOS_WAIT_FOREVER; + } + else + { + wait_ticks = LOS_MS2Tick(wait_ms); + } + + ret = osMessageQueuePut(p_handle, p_msg, 0, wait_ticks); + + if (ret != osOK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Receive inter-thread message */ +/****************************************************************************/ +bool osif_msg_recv(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + UINT32 ret; + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + UINT32 wait_ticks; + + if (wait_ms == 0xFFFFFFFFUL) + { + wait_ticks = LOS_WAIT_FOREVER; + } + else + { + wait_ticks = LOS_MS2Tick(wait_ms); + } + + ret = osMessageQueueGet(p_handle, p_msg, 0, wait_ticks); + + if (ret != osOK) + { + return false; + } + + return true; +} + +/****************************************************************************/ +/* Peek inter-thread message */ +/****************************************************************************/ +bool osif_msg_peek(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + return true; +} + +uint32_t osif_msg_queue_get_space(void *p_handle) +{ + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return 0; + } + + return osMessageQueueGetSpace(p_handle); +} + +uint32_t osif_msg_queue_get_capacity(void *p_handle) +{ + if (p_handle == NULL) + { + printf("%s fail!(p_handle == NULL)\r\n", __FUNCTION__); + return 0; + } + + return osMessageQueueGetCapacity(p_handle); +} + +/****************************************************************************/ +/* Allocate memory */ +/****************************************************************************/ +void *osif_mem_alloc(RAM_TYPE ram_type, size_t size) +{ + (void) ram_type; + return LOS_MemAlloc(m_aucSysMem0, size); +} + +/****************************************************************************/ +/* Allocate aligned memory */ +/****************************************************************************/ +void *osif_mem_aligned_alloc(RAM_TYPE ram_type, size_t size, uint8_t alignment) +{ + (void) ram_type; + void *p; + void *p_aligned; + + if (alignment == 0) + { + alignment = 8; + } + + p = LOS_MemAlloc(m_aucSysMem0, size + sizeof(void *) + alignment); + if (p == NULL) + { + printf("%s fail!(p == NULL)\r\n", __FUNCTION__); + return p; + } + + p_aligned = (void *)(((size_t)p + sizeof(void *) + alignment) & ~(alignment - 1)); + + memcpy((uint8_t *)p_aligned - sizeof(void *), &p, sizeof(void *)); + + return p_aligned; +} + +/****************************************************************************/ +/* Free memory */ +/****************************************************************************/ +void osif_mem_free(void *p_block) +{ + UINT32 ret; + + if (p_block == NULL) + { + printf("%s fail!(p_block == NULL)\r\n", __FUNCTION__); + return; + } + + ret = LOS_MemFree(m_aucSysMem0, p_block); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + } +} + +/****************************************************************************/ +/* Free aligned memory */ +/****************************************************************************/ +void osif_mem_aligned_free(void *p_block) +{ + void *p; + UINT32 ret; + + if (p_block == NULL) + { + printf("%s fail!(p_block == NULL)\r\n", __FUNCTION__); + return; + } + memcpy(&p, (uint8_t *)p_block - sizeof(void *), sizeof(void *)); + + ret = LOS_MemFree(m_aucSysMem0, p); + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + } +} + +/****************************************************************************/ +/* Peek unused (available) memory size */ +/****************************************************************************/ +size_t osif_mem_peek(RAM_TYPE ram_type) +{ + (void) ram_type; + LOS_MEM_POOL_STATUS info; + LOS_MemInfoGet(m_aucSysMem0, &info); + + return info.totalFreeSize; +} + +typedef struct osif_timer_handle { + SWTMR_CTRL_S *pstSwtmr; + uint32_t timer_id; +} OSIF_TIMER_HANDLE_S; + +/****************************************************************************/ +/* Get software timer ID */ +/****************************************************************************/ +bool osif_timer_id_get(void **pp_handle, uint32_t *p_timer_id) +{ + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + + if (pp_handle == NULL || *pp_handle == NULL) + { + printf("%s fail!(pp_handle == NULL || *pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + p_osif_timer_handle = *pp_handle; + *p_timer_id = p_osif_timer_handle->timer_id; + + return true; +} + +/****************************************************************************/ +/* Create software timer */ +/****************************************************************************/ +bool osif_timer_create(void **pp_handle, const char *p_timer_name, uint32_t timer_id, + uint32_t interval_ms, bool reload, void (*p_timer_callback)(void *)) +{ + UINT32 timer_ticks; + SWTMR_CTRL_S *pstSwtmr; + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + if (pp_handle == NULL || p_timer_callback == NULL) + { + printf("%s fail!(pp_handle == NULL || p_timer_callback == NULL)\r\n", __FUNCTION__); + return false; + } + + if (*pp_handle == NULL) + { + p_osif_timer_handle = osif_mem_alloc(0, sizeof(OSIF_TIMER_HANDLE_S)); + if (p_osif_timer_handle == NULL) { + printf("%s fail!(p_osif_timer_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + pstSwtmr = osTimerNew(p_timer_callback, reload ? osTimerPeriodic : osTimerOnce, p_osif_timer_handle, NULL); + if (pstSwtmr == NULL) + { + osif_mem_free(p_osif_timer_handle); + printf("%s fail!(pstSwtmr == NULL)\r\n", __FUNCTION__); + return false; + } + } + else + { + printf("%s fail!(*pp_handle != NULL)\r\n", __FUNCTION__); + return false; + } + + timer_ticks = LOS_MS2Tick(interval_ms); + pstSwtmr->uwInterval = timer_ticks; + p_osif_timer_handle->pstSwtmr = pstSwtmr; + p_osif_timer_handle->timer_id = timer_id; + *pp_handle = p_osif_timer_handle; + + return true; +} + +/****************************************************************************/ +/* Start software timer */ +/****************************************************************************/ +bool osif_timer_start(void **pp_handle) +{ + UINT32 ret; + SWTMR_CTRL_S *pstSwtmr; + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + + if (pp_handle == NULL || *pp_handle == NULL) + { + printf("%s fail!(pp_handle == NULL || *pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + p_osif_timer_handle = *pp_handle; + pstSwtmr = p_osif_timer_handle->pstSwtmr; + ret = LOS_SwtmrStart(pstSwtmr->usTimerID); + + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Restart software timer */ +/****************************************************************************/ +bool osif_timer_restart(void **pp_handle, uint32_t interval_ms) +{ + UINT32 timer_ticks; + SWTMR_CTRL_S *pstSwtmr; + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + UINT32 ret; + + if (pp_handle == NULL || *pp_handle == NULL) + { + printf("%s fail!(pp_handle == NULL || *pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + p_osif_timer_handle = *pp_handle; + pstSwtmr = p_osif_timer_handle->pstSwtmr; + timer_ticks = LOS_MS2Tick(interval_ms); + LOS_SwtmrStop(pstSwtmr->usTimerID); + pstSwtmr->uwInterval = timer_ticks; + ret = LOS_SwtmrStart(pstSwtmr->usTimerID); + + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Stop software timer */ +/****************************************************************************/ +bool osif_timer_stop(void **pp_handle) +{ + UINT32 ret; + SWTMR_CTRL_S *pstSwtmr; + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + + if (pp_handle == NULL || *pp_handle == NULL) + { + printf("%s fail!(pp_handle == NULL || *pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + p_osif_timer_handle = *pp_handle; + pstSwtmr = p_osif_timer_handle->pstSwtmr; + ret = LOS_SwtmrStop(pstSwtmr->usTimerID); + + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + return true; +} + +/****************************************************************************/ +/* Delete software timer */ +/****************************************************************************/ +bool osif_timer_delete(void **pp_handle) +{ + UINT32 ret; + SWTMR_CTRL_S *pstSwtmr; + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + + if (pp_handle == NULL || *pp_handle == NULL) + { + return false; + } + + p_osif_timer_handle = *pp_handle; + pstSwtmr = p_osif_timer_handle->pstSwtmr; + ret = LOS_SwtmrDelete(pstSwtmr->usTimerID); + + if (ret != LOS_OK) + { + printf("%s fail!(err code = %d)\r\n", __FUNCTION__,ret); + return false; + } + + osif_mem_free(p_osif_timer_handle); + *pp_handle = NULL; + + return true; +} + +/****************************************************************************/ +/* Get timer state */ +/****************************************************************************/ +bool osif_timer_state_get(void **pp_handle, uint32_t *p_timer_state) +{ + SWTMR_CTRL_S *pstSwtmr; + OSIF_TIMER_HANDLE_S *p_osif_timer_handle; + + if (pp_handle == NULL || *pp_handle == NULL) + { + printf("%s fail!(pp_handle == NULL || *pp_handle == NULL)\r\n", __FUNCTION__); + return false; + } + + p_osif_timer_handle = *pp_handle; + pstSwtmr = p_osif_timer_handle->pstSwtmr; + *p_timer_state = (pstSwtmr->ucState == OS_SWTMR_STATUS_TICKING) ? 1 :0; + + return true; +} + +/****************************************************************************/ +/* Dump software timer */ +/****************************************************************************/ +bool osif_timer_dump(void) +{ + return true; +} + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) +extern void rtw_create_secure_context(u32 secure_stack_size); +#endif +void osif_create_secure_context(uint32_t size) +{ +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + rtw_create_secure_context(size); +#endif +} diff --git a/component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_at_cmd.c b/component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_at_cmd.c index 476bf41a..4c6d465b 100644 --- a/component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_at_cmd.c +++ b/component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_at_cmd.c @@ -920,8 +920,7 @@ int ble_central_at_cmd_scan(int argc, char **argv) #endif #if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ - (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET) || \ - (defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER)) + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) #if defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE new_state = bt_mesh_provisioner_multiple_profile_gap_dev_state; #elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app.c b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app.c new file mode 100644 index 00000000..8a788487 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app.c @@ -0,0 +1,699 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ble_google_seamless_app.c + * @brief This file handles BLE google_seamless application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_GOOGLE_SEAMLESS) && CONFIG_BT_GOOGLE_SEAMLESS +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "os_mem.h" +#include "log_service.h" +#include "google_seamless.h" +#include "ble_google_seamless_app.h" +#include +#include "platform_stdlib.h" +#include "app_common_flags.h" +#if (F_BT_LE_USE_RANDOM_ADDR==1) +#include "ftl_app.h" +#endif + +/*============================================================================* + * Constants + *============================================================================*/ +#if (F_BT_LE_USE_RANDOM_ADDR==1) +/** @brief Define start offset of the flash to save static random address. */ +#define BLE_PERIPHERAL_APP_STATIC_RANDOM_ADDR_OFFSET 0 +#endif +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE google_seamless application routines. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID google_seamless_srv_id; /**< Google seamless service id */ +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE google_seamless_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE google_seamless_gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ +extern bool google_seamless_provisioned; +/*============================================================================* + * Functions + *============================================================================*/ +void google_seamless_handle_gap_msg(T_IO_MSG *p_gap_msg); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void google_seamless_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + google_seamless_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 0) { + le_adv_stop(); + } else if (io_msg.subtype == 1) { + le_adv_start(); + }else if(io_msg.subtype == GOOGLE_SEAMLESS_MSG_SEND_INDICATION){ + void *arg = io_msg.u.buf; + GOOGLE_SEAMLESS_NOTIFICATION_PARAM *param = io_msg.u.buf; + server_send_data(param->conn_id, param->srv_id, param->attrib_index, (uint8_t *)param->val, param->len, param->type); + os_mem_free(param->val); + os_mem_free(param); + } + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +extern void google_seamless_get_adv_profile_infor(uint8_t **adv_profile, uint8_t* length); +void google_seamless_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("google_seamless_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (google_seamless_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + printf("\n\r[BLE Google Seamless] GAP stack ready\n\r"); + uint8_t bt_addr[6]={0}; +#if (F_BT_LE_USE_RANDOM_ADDR==2) && F_BT_LE_LOCAL_IRK_SETTING_SUPPORT + T_GAP_RAND_ADDR_TYPE rand_addr_type = GAP_RAND_ADDR_RESOLVABLE; + T_GAP_CAUSE result; + result = le_gen_rand_addr(rand_addr_type, bt_addr); + printf("[%s]le_gen_rand_addr result = %x\n\r",__func__,result); + result = le_set_rand_addr(bt_addr); + printf("[%s]le_set_rand_addr result = %x\n\r",__func__,result); + memset(bt_addr,0,sizeof(uint8_t)*6); +#endif + /*stack ready*/ + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + printf("local bd addr: 0x%02x:%02x:%02x:%02x:%02x:%02x\r\n", + bt_addr[5], + bt_addr[4], + bt_addr[3], + bt_addr[2], + bt_addr[1], + bt_addr[0]); + /*update adv data*/ + uint8_t* adv_profile; + uint8_t length; + google_seamless_get_adv_profile_infor(&adv_profile, &length); + uint8_t* adv_data_send = (uint8_t *)os_mem_alloc(0, length); + if(adv_data_send == NULL) + { + os_mem_free(adv_data_send); + printf("Set provision advertisement package fail\n\r"); + } + else + { + memcpy(adv_data_send, &(*adv_profile), length); + if(google_seamless_provisioned == true) + { + *(adv_data_send+5)=LO_WORD(GATT_UUID_PROVISIONED_PROFILE);//the provision byte location is at 5th byte + *(adv_data_send+6)=HI_WORD(GATT_UUID_PROVISIONED_PROFILE);//the provision byte location is at 6th byte + } + le_adv_set_param(GAP_PARAM_ADV_DATA, length, (void *)adv_data_send); + os_mem_free(adv_data_send); + } + le_adv_start(); + } + } + + if (google_seamless_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("\n\rGAP adv stoped: because connection created\n\r"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + printf("\n\rGAP adv stopped\n\r"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("\n\rGAP adv start\n\r"); + } + } + + google_seamless_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void google_seamless_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("google_seamless_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, google_seamless_gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("google_seamless_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + printf("\n\r[BLE Google Seamless] BT Disconnected, cause 0x%x, start ADV\n\r", disc_cause); + /*update adv data*/ + uint8_t* adv_profile; + uint8_t length; + google_seamless_get_adv_profile_infor(&adv_profile, &length); + uint8_t* adv_data_send = (uint8_t *)os_mem_alloc(0, length); + if(adv_data_send == NULL) + { + os_mem_free(adv_data_send); + if(google_seamless_provisioned == true) + { + printf("Set provision advertisement package fail\n\r"); + } + else + { + printf("Set un-provision advertisement package fail\n\r"); + } + } + else + { + memcpy(adv_data_send, &(*adv_profile), length); + if(google_seamless_provisioned == true) + { + *(adv_data_send+5)=LO_WORD(GATT_UUID_PROVISIONED_PROFILE);//the provision byte location is at 5th byte + *(adv_data_send+6)=HI_WORD(GATT_UUID_PROVISIONED_PROFILE);//the provision byte location is at 6th byte + } + le_adv_set_param(GAP_PARAM_ADV_DATA, length, (void *)adv_data_send); + os_mem_free(adv_data_send); + } + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, (void *)&remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + printf("\n\r[BLE Google Seamless] BT Connected\n\r"); + } + break; + + default: + break; + } + google_seamless_gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void google_seamless_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("google_seamless_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("google_seamless_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + printf("Pair success\r\n"); + APP_PRINT_INFO0("google_seamless_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + printf("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("google_seamless_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("google_seamless_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void google_seamless_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("google_seamless_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void google_seamless_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("google_seamless_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + printf("google_seamless_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x\r\n", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("google_seamless_handle_conn_param_update_evt update failed: cause 0x%x", cause); + printf("google_seamles_handle_conn_param_update_evt update failed: cause 0x%x\r\n", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("google_seamless_handle_conn_param_update_evt update pending."); + printf("\n\rgoogle_seamles_handle_conn_param_update_evt update pending: conn_id %d\r\n", conn_id); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void google_seamless_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("google_seamless_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + google_seamless_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + google_seamless_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + google_seamless_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + google_seamless_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + google_seamless_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d\r\n", display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d\r\n", display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + default: + { + APP_PRINT_ERROR1("google_seamless_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT google_seamless_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + { + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; + } +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + { + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + } + + default: + { + APP_PRINT_ERROR1("google_seamless_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT google_seamless_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + { + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + } + + case PROFILE_EVT_SEND_DATA_COMPLETE: + { + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + printf("\n\rPROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + printf("PROFILE_EVT_SEND_DATA_COMPLETE success\r\n"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + printf("PROFILE_EVT_SEND_DATA_COMPLETE failed\r\n"); + } + break; + } + + default: + break; + } + } + else if (service_id == google_seamless_srv_id) + { + T_GOOGLE_SEAMLESS_CALLBACK_DATA *p_google_seamless_cb_data = (T_GOOGLE_SEAMLESS_CALLBACK_DATA *)p_data; + switch (p_google_seamless_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_google_seamless_cb_data->msg_data.notification_indification_index) + { + case GOOGLE_SEAMLESS_NOTIFY_INDICATE_V6_ENABLE: + { + printf("GOOGLE_NOTIFY_INDICATE_V6_ENABLE\r\n"); + } + break; + case GOOGLE_SEAMLESS_NOTIFY_INDICATE_V6_DISABLE: + { + printf("GOOGLE_NOTIFY_INDICATE_V6_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_google_seamless_cb_data->msg_data.write.opcode) + { + case GOOGLE_SEAMLESS_WRITE_V5: + { + APP_PRINT_INFO2("GOOGLE_SEAMLESS_WRITE_V5: write type %d, len %d", p_google_seamless_cb_data->msg_data.write.write_type, + p_google_seamless_cb_data->msg_data.write.len); + google_seamless_set_parameter(GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V5_WRITE_CHAR_VAL, p_google_seamless_cb_data->msg_data.write.len, p_google_seamless_cb_data->msg_data.write.p_value); + } + break; + case GOOGLE_SEAMLESS_WRITE_V6: + { + APP_PRINT_INFO2("GOOGLE_SEAMLESS_WRITE_V6: write type %d, len %d", p_google_seamless_cb_data->msg_data.write.write_type, + p_google_seamless_cb_data->msg_data.write.len); + google_seamless_set_parameter(GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V6_WRITE_CHAR_VAL, p_google_seamless_cb_data->msg_data.write.len, p_google_seamless_cb_data->msg_data.write.p_value); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ +/** @} */ +/** @addtogroup PERIPHERAL_APP + * @{ + */ +/** @defgroup PERIPHERAL_RANDOM Static Random Address Storage + * @brief Use @ref F_BT_LE_USE_RANDOM_ADDR to open + * @{ + */ +#if (F_BT_LE_USE_RANDOM_ADDR==1) +/** + * @brief Save static random address information into flash. + * @param[in] p_addr Pointer to the buffer for saving data. + * @retval 0 Save success. + * @retval other Failed. + */ +uint32_t google_seamless_save_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr) +{ + APP_PRINT_INFO0("google_seamless_save_static_random_address"); + return ftl_save(p_addr, BLE_PERIPHERAL_APP_STATIC_RANDOM_ADDR_OFFSET, sizeof(T_APP_STATIC_RANDOM_ADDR)); +} +/** + * @brief Load static random address information from storage. + * @param[out] p_addr Pointer to the buffer for loading data. + * @retval 0 Load success. + * @retval other Failed. + */ +uint32_t google_seamless_load_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr) +{ + uint32_t result; + result = ftl_load(p_addr, BLE_PERIPHERAL_APP_STATIC_RANDOM_ADDR_OFFSET, + sizeof(T_APP_STATIC_RANDOM_ADDR)); + APP_PRINT_INFO1("google_seamless_load_static_random_address: result 0x%x", result); + if (result) + { + memset(p_addr, 0, sizeof(T_APP_STATIC_RANDOM_ADDR)); + } + return result; +} +#endif +/** @} */ +/** @} */ +/** @} */ /* End of group PERIPH_APP */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app.h b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app.h new file mode 100644 index 00000000..9f9a58f8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app.h @@ -0,0 +1,123 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ble_google_seamless_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _GOOGLE_SEAMLESS_APP__ +#define _GOOGLE_SEAMLESS_APP__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID google_seamless_srv_id;/**< Google seamless service id */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @addtogroup PERIPHERAL_APP + * @{ + */ +#if (F_BT_LE_USE_RANDOM_ADDR==1) +typedef struct +{ + uint8_t is_exist; + uint8_t reserved; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_STATIC_RANDOM_ADDR; +#endif +#define GATT_UUID_UNPROVISION_PROFILE 0xA00A +#define GATT_UUID_PROVISIONED_PROFILE 0xB00B + +/*============================================================================* + * Variables + *============================================================================*/ +typedef enum { + GOOGLE_SEAMLESS_MSG_SEND_INDICATION=2, + GOOGLE_SEAMLESS_MSG_MAX +} T_GOOGLE_SEAMLESS_MSG_TYPE; + +typedef struct { + uint8_t conn_id; + uint8_t srv_id; + uint16_t attrib_index; + bool type; + uint16_t len; + char *val; +} GOOGLE_SEAMLESS_NOTIFICATION_PARAM; +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void google_seamless_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id. + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT google_seamless_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT google_seamless_gap_callback(uint8_t cb_type, void *p_cb_data); + +#if (F_BT_LE_USE_RANDOM_ADDR==1) +/** + * @brief Save static random address information into flash. + * @param[in] p_addr Pointer to the buffer for saving data. + * @retval 0 Save success. + * @retval other Failed. + */ +uint32_t google_seamless_save_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr); + +/** + * @brief Load static random address information from storage. + * @param[out] p_addr Pointer to the buffer for loading data. + * @retval 0 Load success. + * @retval other Failed. + */ +uint32_t google_seamless_load_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_flags.h b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_flags.h new file mode 100644 index 00000000..464d2e89 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_flags.h @@ -0,0 +1,32 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ble_google_seamless_app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "bt_flags.h" + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_main.c b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_main.c new file mode 100644 index 00000000..88ed451b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_main.c @@ -0,0 +1,357 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ble_google_seamless_ble_app_main.c + * @brief Source file for Google seamless setup project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_GOOGLE_SEAMLESS) && CONFIG_BT_GOOGLE_SEAMLESS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ble_google_seamless_app_task.h" +#include "ble_google_seamless_app.h" +#include "app_flags.h" +#include "platform_stdlib.h" +#include "wifi_constants.h" +#include +#include "rtk_coex.h" + + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 352 //220ms +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 384 //240ms +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_UNPROVISION_PROFILE), + HI_WORD(GATT_UUID_UNPROVISION_PROFILE), + /* Local name */ + 0x10, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'G', 'O', 'O', 'G', 'L','E', '_', 'S', 'E', 'A', 'M', 'L', 'E', 'S', 'S', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +#ifndef PLATFORM_OHOS +extern void gap_config_hci_task_secure_context(uint32_t size); +void google_seamless_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); + gap_config_hci_task_secure_context (280); +} +#else +extern void gap_config_deinit_flow(uint8_t deinit_flow); +void google_seamless_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); + //gap_config_hci_task_secure_context (280); + gap_config_deinit_flow(1); +} +#endif + +/** + * @brief Add advertisement package content and length + * @param uint8_t **adv_profile + * @return *length + * @return void + */ +void google_seamless_get_adv_profile_infor(uint8_t **adv_profile, uint8_t *length) +{ + *adv_profile = (uint8_t *)adv_data; + *length = sizeof(adv_data); +} +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void google_seamless_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(google_seamless_gap_callback); + +#if (F_BT_LE_USE_RANDOM_ADDR==1) + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (google_seamless_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + google_seamless_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer + //le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#elif (F_BT_LE_USE_RANDOM_ADDR==2) && F_BT_LE_LOCAL_IRK_SETTING_SUPPORT + uint8_t irk_auto = true; + le_bond_set_param(GAP_PARAM_BOND_GEN_LOCAL_IRK_AUTO, sizeof(uint8_t), &irk_auto); +#endif +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void google_seamless_app_le_profile_init(void) +{ + server_init(1); + + google_seamless_srv_id = google_seamless_add_service((void *)google_seamless_profile_callback); + server_register_app_cb(google_seamless_profile_callback); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void google_seamless_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void google_seamless_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void google_seamless_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Google Seamless APP, thus only one APP task is init here + * @return void + */ +void google_seamless_task_init(void) +{ + google_seamless_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int google_seamless_ble_app_main(void) +{ + bt_trace_init(); + google_seamless_stack_config_init(); + bte_init(); + google_seamless_board_init(); + le_gap_init(APP_MAX_LINKS); + google_seamless_le_gap_init(); + google_seamless_app_le_profile_init(); + google_seamless_pwr_mgr_init(); + google_seamless_task_init(); + return 0; +} + +int google_seamless_app_init(void) +{ + //int bt_stack_already_on = 0; + //(void) bt_stack_already_on; + T_GAP_DEV_STATE new_state; + gap_config_cccd_not_check(CONFIG_GATT_CCCD_NOT_CHECK); +#if !defined(CONFIG_BT_ONLY_WITHOUT_WLAN) || (CONFIG_BT_ONLY_WITHOUT_WLAN == 0) /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } +#endif + + //judge Goolgle seamless setup is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BLE Google Seamless]BT Stack already on\n\r"); + return 0; + } + else + { + google_seamless_ble_app_main(); + } +#if !defined(CONFIG_BT_ONLY_WITHOUT_WLAN) || (CONFIG_BT_ONLY_WITHOUT_WLAN == 0) + bt_coex_init(); +#endif + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern void google_seamless_app_task_deinit(void); +extern bool bt_trace_uninit(void); +extern T_GAP_DEV_STATE google_seamless_gap_dev_state; + +void google_seamless_app_deinit(void) +{ + google_seamless_app_task_deinit(); + + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BLE Google Seamless]BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + memset(&google_seamless_gap_dev_state, 0, sizeof(T_GAP_DEV_STATE)); + printf("[BLE Google Seamless]BT Stack deinitalized\n\r"); + } +#endif +} + +/** @} */ /* End of group PERIPH_DEMO_MAIN */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_task.c b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_task.c new file mode 100644 index 00000000..57ed9561 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_task.c @@ -0,0 +1,135 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_GOOGLE_SEAMLESS) && CONFIG_BT_GOOGLE_SEAMLESS +#include +#include +#include +#include +#include +#include "ble_google_seamless_app_task.h" +#include "ble_google_seamless_app.h" +#include "platform_stdlib.h" +#include +#include + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *google_seamless_app_task_handle = NULL; //!< APP Task handle +void *google_seamless_evt_queue_handle = NULL; //!< Event queue handle +void *google_seamless_io_queue_handle = NULL; //!< IO queue handle + +extern T_GAP_DEV_STATE google_seamless_gap_dev_state; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void google_seamless_app_main_task(void *p_param) +{ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&google_seamless_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&google_seamless_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(google_seamless_evt_queue_handle, google_seamless_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + google_seamless_driver_init(); + while (true) + { + if (os_msg_recv(google_seamless_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(google_seamless_io_queue_handle, &io_msg, 0) == true) + { + google_seamless_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** + * @brief Initialize App task + * @return void + */ +void google_seamless_app_task_init(void) +{ + if(os_task_create(&google_seamless_app_task_handle, "app_google", google_seamless_app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY)==false) + { + printf("create google task fail\n\r"); + } +} +void google_seamless_app_task_deinit(void) +{ + if (google_seamless_app_task_handle) { + os_task_delete(google_seamless_app_task_handle); + } + if (google_seamless_io_queue_handle) { + os_msg_queue_delete(google_seamless_io_queue_handle); + } + if (google_seamless_evt_queue_handle) { + os_msg_queue_delete(google_seamless_evt_queue_handle); + } + google_seamless_io_queue_handle = NULL; + google_seamless_evt_queue_handle = NULL; + google_seamless_app_task_handle = NULL; + + google_seamless_gap_dev_state.gap_init_state = 0; + google_seamless_gap_dev_state.gap_adv_sub_state = 0; + google_seamless_gap_dev_state.gap_adv_state = 0; + google_seamless_gap_dev_state.gap_scan_state = 0; + google_seamless_gap_dev_state.gap_conn_state = 0; +} + +/** @} */ /* End of group PERIPH_APP_TASK */ +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_task.h b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_task.h new file mode 100644 index 00000000..3462a9f7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/ble_google_seamless_app_task.h @@ -0,0 +1,27 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +extern void google_seamless_driver_init(void); + +/** + * @brief Initialize App task + * @return void + */ +void google_seamless_app_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/google_seamless.c b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/google_seamless.c new file mode 100644 index 00000000..c2b5099b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/google_seamless.c @@ -0,0 +1,501 @@ +/** +********************************************************************************************************* +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file google_seamless.c +* @brief google seamless setup ble service source file. +* @details Interfaces to access google seamless setup service. +* @author +* @date +* @version v1.0 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_GOOGLE_SEAMLESS) && CONFIG_BT_GOOGLE_SEAMLESS +#include "stdint.h" +#include "stddef.h" +#include "string.h" +#include "FreeRTOS.h" +#include "Timers.h" +#include "task.h" +#include "os_mem.h" +#include "app_msg.h" +#include "trace_app.h" +#include "ble_google_seamless_app.h" +#include "profile_server.h" +#include "google_seamless.h" +#include "os_msg.h" +#include "app_flags.h" + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +#define GATT_UUID_LIGHT 0xB00B +#define GATT_UUID_CHAR_PROVISON_STATE 0xB005 +#define GATT_UUID_CHAR_LIGHT_ON_STATE 0xB006 + +#define GOOGLE_SEAMLESS_CHAR_V5_WRITE_INDEX 0x02 +#define GOOGLE_SEAMLESS_CHAR_V6_WRITE_INDEX 0x05 +#define GOOGLE_SEAMLESS_CHAR_V6_NOTIFY_INDEX 0x05 +#define GOOGLE_SEAMLESS_CHAR_NOTIFY_CCCD_V6_INDEX (GOOGLE_SEAMLESS_CHAR_V6_NOTIFY_INDEX + 1) + +/**< Value of google seamless setup read characteristic. */ +static uint16_t google_provision_char_read_len = 1; +static uint8_t google_provision_char_read_value[GOOGLE_SEAMLESS_READ_MAX_LEN]; +static uint16_t google_on_char_read_len = 1; +static uint8_t google_on_char_read_value[GOOGLE_SEAMLESS_READ_MAX_LEN]; +/**< Value of google seamless setup provision status. */ +bool google_seamless_provisioned = false; +/**< Value of google seamless setup queue handler. */ +extern void *google_seamless_evt_queue_handle; +extern void *google_seamless_io_queue_handle; +/**< Function pointer used to send event to application from pxp profile. */ +/**< Initiated in PXP_AddService. */ +static P_FUN_SERVER_GENERAL_CB pfn_google_seamless_cb = NULL; + +/**< @brief profile/service definition. */ +static const T_ATTRIB_APPL google_seamless_attr_tbl[] = +{ + /*----------------- Google light Service -------------------*/ + /* <>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_LIGHT), /* service UUID */ + HI_WORD(GATT_UUID_LIGHT) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + + /* <>, demo for provision */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE, /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_PROVISON_STATE), + HI_WORD(GATT_UUID_CHAR_PROVISON_STATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + + /* <>, demo for light on/off */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_NOTIFY | GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE, /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_LIGHT_ON_STATE), + HI_WORD(GATT_UUID_CHAR_LIGHT_ON_STATE) + }, + 0, /* bValueLen */ + NULL, + (GATT_PERM_NOTIF_IND | GATT_PERM_WRITE) /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, +}; +/**< @brief google seamless setup service size definition. */ +static const uint16_t google_seamless_attr_tbl_size = sizeof(google_seamless_attr_tbl); + +/** + * @brief send notification message + * + * @param void + * @return void +*/ +bool google_seamless_send_msg(GOOGLE_SEAMLESS_NOTIFICATION_PARAM* param) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + bool ret = true; + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = GOOGLE_SEAMLESS_MSG_SEND_INDICATION; + io_msg.u.buf = (void*)param; + + if (google_seamless_evt_queue_handle != NULL && google_seamless_io_queue_handle != NULL) { + if (os_msg_send(google_seamless_io_queue_handle, &io_msg, 0) == false) { + printf("bt at cmd send msg fail: subtype 0x%x", io_msg.subtype); + return false; + } else if (os_msg_send(google_seamless_evt_queue_handle, &event, 0) == false) { + printf("bt at cmd send event fail: subtype 0x%x", io_msg.subtype); + return false; + } + printf("notification has been send\n\r"); + } + else + { + return false; + } + return ret; +} + +/** + * @brief check whether write value match the value in google firebase. if match, send back notification value to Google home device. + * + * @param len Receive write value length + * @param p_value Receive write value. + * @return void +*/ +bool google_seamless_edit_notify_arg( uint16_t len, uint8_t * p_value) +{ + int argc = 0; + char *argv[20]; + static const char pcTimerName[] = "google update status"; + static TimerHandle_t *pp_handle = NULL; + BaseType_t xTimerStarted = pdFALSE; + bool receive_match_word = false; + GOOGLE_SEAMLESS_NOTIFICATION_PARAM *param; + param = (GOOGLE_SEAMLESS_NOTIFICATION_PARAM *)os_mem_alloc(0,sizeof(GOOGLE_SEAMLESS_NOTIFICATION_PARAM)); + param->val = (char *)os_mem_alloc(0,google_on_char_read_len*sizeof(char)); + + if((param == NULL)||(param->val == NULL)) + { + return false; + } + param->conn_id = 0;//we only connect to 1 master + param->srv_id = 1;// only 1 profile available in this example + param->attrib_index = GOOGLE_SEAMLESS_CHAR_V6_NOTIFY_INDEX; + param->type = 1; + param->len = google_on_char_read_len; + + if((google_on_char_read_len == 2)&&(strncmp((char *)p_value,"on",2)==0)) + { + strcpy(param->val,"on"); + printf("Google light is ON\n\r"); + receive_match_word = true; + } + else if ((google_on_char_read_len==3)&&(strncmp((char *)p_value,"off",3)==0)) + { + strcpy(param->val,"off"); + printf("Google light is OFF\n\r"); + receive_match_word = true; + } + + if(receive_match_word == true) + { + if(google_seamless_send_msg(param)!=true) + { + os_mem_free(param->val); + os_mem_free(param); + return false; + } + } + else + { + printf( " ERROR: wrong command has been received.\r\n" ); + } + return true; +} +/** + * @brief update the provision status + * + * @param len Receive write value length + * @param p_value Receive write value. + * @return void +*/ +void google_seamless_write_provision_status(uint8_t * p_value) +{ + if(strncmp((char *)p_value,"{true}",6)==0) + { + google_seamless_provisioned = true; + printf("Google light is provisioned\n\r"); + } + else + { + google_seamless_provisioned = false; + printf("Google light is un-provision\n\r"); + } +} + +/** + * @brief Set a google seamless setup service parameter. + * + * NOTE: You can call this function with a google seamless setup service parameter type and + * it will set thegoogle seamless setup service parameter. Google seamless setup service + * parameters are defined in @ref T_GOOGLE_SEAMLESS_PARAM_TYPE. + * If the "len" field sets to the size of a "uint16_t" ,the "p_value" field must point to + * a data with type of "uint16_t". + * + * @param[in] param_type google seamless setup service parameter type: @ref T_GOOGLE_SEAMLESS_PARAM_TYPE + * @param[in] length Length of data to write + * @param[in] p_value Pointer to data to write. This is dependent on + * the parameter type and WILL be cast to the appropriate + * data type (For example: if data type of param is uint16_t, p_value will be cast to + * pointer of uint16_t). + * + * @return Operation result. + * @retval true Operation success. + * @retval false Operation failure. + * + * Example usage + * \code{.c} + void test(void) + { + uint8_t *p_value; + google_seamless_set_parameter(GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V5_READ_CHAR_VAL, 1, &p_value); + } + * \endcode + */ +bool google_seamless_set_parameter(T_GOOGLE_SEAMLESS_PARAM_TYPE param_type, uint8_t length, uint8_t *p_value) +{ + bool ret = true; + + switch (param_type) + { + default: + { + ret = false; + APP_PRINT_ERROR0("bas_set_parameter failed"); + break; + } + case GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V5_WRITE_CHAR_VAL: + { + memset(google_provision_char_read_value, 0x00, GOOGLE_SEAMLESS_READ_MAX_LEN); + memcpy(google_provision_char_read_value, p_value, length); + google_provision_char_read_len = length; + google_seamless_write_provision_status(p_value); + break; + } + case GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V6_WRITE_CHAR_VAL: + { + memset(google_on_char_read_value, 0, GOOGLE_SEAMLESS_READ_MAX_LEN); + memcpy(google_on_char_read_value, p_value, length); + google_on_char_read_len = length; + if(google_seamless_edit_notify_arg(length,p_value) != true) + { + printf("Send notification fail"); + } + break; + } + } + return ret; +} + + +void google_seamless_write_post_callback(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t length, uint8_t *p_value) +{ + (void)p_value; + APP_PRINT_INFO4("google_seamless_write_post_callback: conn_id %d, service_id %d, attrib_index 0x%x, length %d", + conn_id, service_id, attrib_index, length); +} +/** + * @brief write characteristic data from service. + * + * @param conn_id + * @param service_id ServiceID to be written. + * @param attrib_index Attribute index of characteristic. + * @param length length of value to be written. + * @param p_value value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT google_seamless_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + T_GOOGLE_SEAMLESS_CALLBACK_DATA callback_data; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("google_seamless_attr_write_cb write_type = 0x%x", write_type); + *p_write_ind_post_proc = google_seamless_write_post_callback; + if (GOOGLE_SEAMLESS_CHAR_V5_WRITE_INDEX == attrib_index) + { + /* Make sure written value size is valid. */ + if (p_value == NULL) + { + cause = APP_RESULT_INVALID_VALUE_SIZE; + } + else + { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = GOOGLE_SEAMLESS_WRITE_V5; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_google_seamless_cb) + { + pfn_google_seamless_cb(service_id, (void *)&callback_data); + } + } + } + else if (GOOGLE_SEAMLESS_CHAR_V6_WRITE_INDEX == attrib_index) + { + /* Make sure written value size is valid. */ + if (p_value == NULL) + { + cause = APP_RESULT_INVALID_VALUE_SIZE; + } + else + { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = GOOGLE_SEAMLESS_WRITE_V6; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_google_seamless_cb) + { + pfn_google_seamless_cb(service_id, (void *)&callback_data); + } + } + } + else{ + APP_PRINT_ERROR2("simp_ble_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, + length); + cause = APP_RESULT_ATTR_NOT_FOUND; + } + return cause; +} +/** + * @brief update CCCD bits from stack. + * + * @param conn_id Connection ID. + * @param service_id Service ID. + * @param index Attribute index of characteristic data. + * @param ccc_bits CCCD bits from stack. + * @return None +*/ +void google_seamless_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index, uint16_t ccc_bits) +{ + T_GOOGLE_SEAMLESS_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.conn_id = conn_id; + bool handle = true; + APP_PRINT_INFO2("google_seamless_cccd_update_cb index = %d ccc_bits %x", index, ccc_bits); + switch (index) + { + case GOOGLE_SEAMLESS_CHAR_NOTIFY_CCCD_V6_INDEX: + { + if (ccc_bits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_data.notification_indification_index = GOOGLE_SEAMLESS_NOTIFY_INDICATE_V6_ENABLE; + } + else + { + // Disable Notification + callback_data.msg_data.notification_indification_index = GOOGLE_SEAMLESS_NOTIFY_INDICATE_V6_DISABLE; + } + handle = true; + break; + } + default: + { + handle = false; + break; + } + + } + + if (pfn_google_seamless_cb && (handle == true)) + { + pfn_google_seamless_cb(service_id, (void *)&callback_data); + } + + return; +} + +/** + * @brief BAS Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS google_seamless_cbs = +{ + NULL, + google_seamless_attr_write_cb, // Write callback function pointer + google_seamless_cccd_update_cb // CCCD update callback function pointer +}; + +/** + * @brief Add google seamless setup service to the BLE stack database. + * + * + * @param[in] p_func Callback when service attribute was read, write or cccd update. + * @return Service id generated by the BLE stack: @ref T_SERVER_ID. + * @retval 0xFF Operation failure. + * @retval Others Service id assigned by stack. + * + * Example usage + * \code{.c} + void profile_init() + { + server_init(1); + google_seamless_srv_id = google_seamless_add_service(app_handle_profile_message); + } + * \endcode + */ +T_SERVER_ID google_seamless_add_service(void *p_func) +{ + T_SERVER_ID service_id; + if (false == server_add_service(&service_id, + (uint8_t *)google_seamless_attr_tbl, + google_seamless_attr_tbl_size, + google_seamless_cbs)) + { + APP_PRINT_ERROR1("google_seamless_add_service: service_id %d", service_id); + service_id = 0xff; + } + pfn_google_seamless_cb = (P_FUN_SERVER_GENERAL_CB)p_func; + return service_id; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/google_seamless.h b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/google_seamless.h new file mode 100644 index 00000000..b835072d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/google_seamless.h @@ -0,0 +1,180 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file google_seamless.h + * @brief Head file for using google seamless setup service. + * @details google seamless setup data structs and external functions declaration. + * @author + * @date + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _GOOGLE_SEAMLESS_BLE_SERVICE_H_ +#define _GOOGLE_SEAMLESS_BLE_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_server.h" + + +/** @defgroup Google Seamless Setup Service + * @brief Google Seanless setup service + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup GOOGLE_SEAMLESS_SETUP_Service_Application_Parameters GOOGLE SEAMLESS SETUP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +typedef enum +{ + GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V5_WRITE_CHAR_VAL = 0x01, + GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V6_WRITE_CHAR_VAL = 0x02, +} T_GOOGLE_SEAMLESS_PARAM_TYPE; + +/** @} */ + +/** @defgroup GOOGLE_SEAMLESS_SETUP_Service_Write_Info GOOGLE SEAMLESS SETUP Service Write Info + * @brief Parameter for writing characteristic value. + * @{ + */ +#define GOOGLE_SEAMLESS_WRITE_V5 1 +#define GOOGLE_SEAMLESS_WRITE_V6 2 + +/** @} */ + +/** @defgroup GOOGLE_SEAMLESS_SETUP_Service_Notify_Indicate_Info GOOGLE SEAMLESS SETUP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define GOOGLE_SEAMLESS_NOTIFY_INDICATE_V6_ENABLE 1 +#define GOOGLE_SEAMLESS_NOTIFY_INDICATE_V6_DISABLE 2 + +/** @} */ + +#define GOOGLE_SEAMLESS_READ_MAX_LEN 300 + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup GOOGLE_SEAMLESS_SETUP_Exported_Types GOOGLE SEAMLESS SETUP Exported Types + * @brief + * @{ + */ +/** +/** +* @brief google seamless setup service parameter type +*/ + +/** +* @brief set google seamless setup service parameter upstream message data +*/ +typedef struct +{ + uint8_t opcode; //!< ref: @ref GOOGLE_SEAMLESS_SETUP_Service_Write_Info + T_WRITE_TYPE write_type; + uint16_t len; + uint8_t *p_value; +} GOOGLE_SEAMLESS_WRITE_MSG; +typedef union +{ + uint8_t notification_indification_index; //!< ref: @ref GOOGLE_SEAMLESS_SETUP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref GOOGLE_SEAMLESS_SETUP_Service_Read_Info + GOOGLE_SEAMLESS_WRITE_MSG write; +} GOOGLE_SEAMLESS_UPSTREAM_MSG_DATA; + +/** +* @brief set google seamless setup service parameter upstream callback data +*/ +typedef struct +{ + uint8_t conn_id; + T_SERVICE_CALLBACK_TYPE msg_type; + GOOGLE_SEAMLESS_UPSTREAM_MSG_DATA msg_data; +} T_GOOGLE_SEAMLESS_CALLBACK_DATA; +/* +/** End of GOOGLE_SEAMLESS_SETUP_Exported_Types +* @} +*/ + + +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup GOOGLE_SEAMLESS_SETUP_Exported_Functions GOOGLE SEAMLESS SETUP Exported Functions + * @brief + * @{ + */ + +/** + * @brief Add google seamless setup service to the BLE stack database. + * + * + * @param[in] p_func Callback when service attribute was read, write or cccd update. + * @return Service id generated by the BLE stack: @ref T_SERVER_ID. + * @retval 0xFF Operation failure. + * @retval Others Service id assigned by stack. + * + * Example usage + * \code{.c} + void profile_init() + { + server_init(1); + google_seamless_srv_id = google_seamless_add_service(app_handle_profile_message); + } + * \endcode + */ +T_SERVER_ID google_seamless_add_service(void *p_func); + + +/** +/** + * @brief Set a google seamless setup service parameter. + * + * NOTE: You can call this function with a google seamless setup service parameter type and it will set the + * google seamless setup service parameter. Google seamless setup service parameters are defined in @ref T_GOOGLE_SEAMLESS_PARAM_TYPE. + * If the "len" field sets to the size of a "uint16_t" ,the + * "p_value" field must point to a data with type of "uint16_t". + * + * @param[in] param_type Google seamless setup service parameter type: @ref T_GOOGLE_SEAMLESS_PARAM_TYPE + * @param[in] length Length of data to write + * @param[in] p_value Pointer to data to write. This is dependent on + * the parameter type and WILL be cast to the appropriate + * data type (For example: if data type of param is uint16_t, p_value will be cast to + * pointer of uint16_t). + * + * @return Operation result. + * @retval true Operation success. + * @retval false Operation failure. + * + * Example usage + * \code{.c} + void test(void) + { + uint8_t *p_value; + google_seamless_set_parameter(GOOGLE_SEAMLESS_BLE_SERVICE_PARAM_V5_READ_CHAR_VAL, 1, &p_value); + } + * \endcode + */ +bool google_seamless_set_parameter(T_GOOGLE_SEAMLESS_PARAM_TYPE param_type, uint8_t length, uint8_t *p_value); + + + +/** @} End of GOOGLE_SEAMLESS_SETUP_Exported_Functions */ + +/** @} End of GOOGLE SEAMLESS SETUP */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _GOOGLE_SEAMLESS_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/readme.txt b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/readme.txt new file mode 100644 index 00000000..eb59c41e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_google_seamless/readme.txt @@ -0,0 +1,51 @@ +Google Seamless BLE Setup EXAMPLE + +Description: +Perform as BLE peripheral for a Google Nest or Google Home speaker or display + +Configuration: +[platform_opts_bt.h] + #define CONFIG_BT 1 + #define CONFIG_BT_GOOGLE_SEAMLESS 1 +For IAR build, please include build all the module under application_is/bluetooth/example/ble_google_seamless +For GCC build, please remove the comment for module in application.is.mk under +#bluetooth - example - ble_google_seamless + +Execution: +When define CONFIG_BT 1 and define GOOGLE_SEAMLESS_EXAMPLE 1, +By command "ATBH=1", once see "GAP adv start" on the console, you can start +using Google Smart Home Application to connect to Ameba. + +Note: +1."ATBH=1", Ameba start send broadcasting ADV packest. + +2. Ameba stops broadcasting ADV packest when BT connection established + +3. After the connection is successful, and the ameba board is added and shown +in the Google Home App. Speak "Turn on xx(depends on the type of device you + configured in Google local fulfillment)" or "Turn off xx". Google Speaker will +send the "on" or "off"command to Ameba and write to GATT_UUID_CHAR_LIGHT_ON_STATE. +After write successfully, the notification package will be send back to Google speaker +to feedback the current status. + +4. For the auto reconnection function, when the device is added into google home application. +The status of device change from un-provision to provisioned. If there is discounnection happen, +such as ATBH=0, then re-establish the connection by ATBH=1. The device will be controllable again +from the application. You don't need to re-add the new device to the Google Home application. + +5. If you want to save the provisioned state when there is power shut down, please +allocated the flash memory to store the provisioned state. This example is use ATBH=0 to simulate +power shut down during run time. For this example, we are using ram variable which at google_seamless.c +bool google_seamless_provisioned = false; + +6. When the device change to provision status, the advertisement package content will be different +compare to the unprovision device, we will update the advertisement package information at 5th byte + and 6th byte before next advertisement start. For the 5th and 6th byte location is used for this + example only, if there is change for this structure, the byte location is required to be updated accordingly. +The provison and unprovision advertisement package information have been saved in the Google action + console for Google Speaker to identify whether your device has been provision or added to the +application before. + +[Supported List] + Supported : + Ameba-z2 \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200.c new file mode 100644 index 00000000..2d12566a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200.c @@ -0,0 +1,424 @@ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_throughput_app.h" +#include "ble_throughput_user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "gap_adv.h" +#include "ble_throughput_vendor_tp_service.h" +#include "os_sched.h" + +#include +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +#include +#endif + +#include + +extern uint8_t gSimpleProfileServiceId; + +T_TP_TEST_PARAM g_206_tp_test_param; +TTP_PERFER_PARAM g_206_prefer_param; +bool g_206_phy_update = false; + +void ble_throughput_206_tp_notification_tx_start(void) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void ble_throughput_206_tp_notification_tx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check) +{ + + memset(&g_206_tp_test_param, 0, sizeof(g_206_tp_test_param)); + g_206_prefer_param.con_interval = con_interval; + g_206_prefer_param.conn_slave_latency = slave_latency; + g_206_prefer_param.conn_supervision_timeout = 1000; + g_206_prefer_param.count = max_count; + g_206_prefer_param.length = length; + g_206_prefer_param.mode = mode; + g_206_prefer_param.initial_value = 0; + g_206_prefer_param.data_check = data_check; + + g_206_tp_test_param.length = length; + g_206_tp_test_param.count = max_count; + g_206_tp_test_param.count_remain = max_count; + g_206_tp_test_param.initial_value = 0; + + + g_206_phy_update = false; + + vendor_tp_service_config_param(g_206_prefer_param); +} + +void ble_throughput_206_start_send_notification(uint8_t conn_id) +{ + uint8_t credits = 10; + g_206_tp_test_param.begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[206][TX]:begin time = %dms", + g_206_tp_test_param.begin_time); + + while (credits) + { + if (g_206_tp_test_param.count_remain) + { + uint8_t value[250]; + memset(value, g_206_tp_test_param.initial_value, + g_206_tp_test_param.length); + if (vendor_tp_service_v1_notification(conn_id, gSimpleProfileServiceId, value, + g_206_tp_test_param.length)) + { + credits--; + g_206_tp_test_param.initial_value++; + g_206_tp_test_param.count_remain--; + } + else + { + APP_PRINT_INFO0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } +} + +void ble_throughput_206_tp_notification_tx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_206_prefer_param.con_interval == con_interval && + g_206_prefer_param.conn_slave_latency == conn_slave_latency && + g_206_prefer_param.conn_supervision_timeout == conn_supervision_timeout) + { + ble_throughput_206_start_send_notification(0); + } + else + { + data_uart_print("[206][TX] error: Invalid conn parameter\r\n"); + le_disconnect(0); + } + +} +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_206_tp_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + if (g_206_phy_update) + { + return; + } + else + { + g_206_phy_update = true; + } + if (cause == 0) + { + if (g_206_prefer_param.mode == 4 || g_206_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_prefer_param.mode == 6 || g_206_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } + } +} +#endif + +void ble_throughput_206_tp_notification_tx_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (g_206_tp_test_param.count_remain) + { + uint8_t value[250]; + memset(value, g_206_tp_test_param.initial_value, + g_206_tp_test_param.length); + if (vendor_tp_service_v1_notification(0, gSimpleProfileServiceId, value, + g_206_tp_test_param.length)) + { + credits--; + g_206_tp_test_param.initial_value++; + g_206_tp_test_param.count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + g_206_tp_test_param.end_time = os_sys_time_get(); + g_206_tp_test_param.elapsed_time = ble_throughput_os_time_get_elapsed(g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time); + g_206_tp_test_param.data_rate = + g_206_tp_test_param.count * g_206_tp_test_param.length * 1000 / + (g_206_tp_test_param.elapsed_time); + APP_PRINT_ERROR1("[206][TX]:end time = %dms", + g_206_tp_test_param.end_time); + } + break; + } + } +} + +void ble_throughput_206_tp_notification_tx_tx_config(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + + switch (p_simp_client_cb_data->msg_data.write.opcode) + { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM1: + { + le_set_data_len(0, 27, 0x0848); + } + break; + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM2: + { + le_set_data_len(0, 251, 0x0848); + } + break; +#endif + case VENDOR_TP_OP_NOTIFY_START_TEST: + break; + + default: + break; + } + +} + +void ble_throughput_206_dump_result(void) +{ + APP_PRINT_ERROR8("[206][TX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_206_prefer_param.con_interval, + g_206_prefer_param.conn_slave_latency, + g_206_prefer_param.length, + g_206_tp_test_param.count, + g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time, + g_206_tp_test_param.elapsed_time, + g_206_tp_test_param.data_rate); + data_uart_print("[206][TX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_206_prefer_param.con_interval, + g_206_prefer_param.conn_slave_latency, + g_206_prefer_param.length, + g_206_tp_test_param.count, + g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time, + g_206_tp_test_param.elapsed_time, + g_206_tp_test_param.data_rate); + APP_PRINT_ERROR2("[206][TX]: count %d count_remain %d", + g_206_prefer_param.count, g_206_tp_test_param.count_remain); + + data_uart_print("[206][TX]: count %d count_remain %d\r\n", + g_206_prefer_param.count, g_206_tp_test_param.count_remain); +} + +void ble_throughput_206_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + ble_throughput_206_dump_result(); +} + +T_TP_TEST_PARAM g_207_tp_test_param; +TTP_PERFER_PARAM g_207_prefer_param; + +void ble_throughput_207_tp_rx_start(void) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void ble_throughput_207_tp_rx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check) +{ + memset(&g_207_tp_test_param, 0, sizeof(g_207_tp_test_param)); + g_207_prefer_param.con_interval = con_interval; + g_207_prefer_param.conn_slave_latency = slave_latency; + g_207_prefer_param.conn_supervision_timeout = 1000; + g_207_prefer_param.count = max_count; + g_207_prefer_param.length = length; + g_207_prefer_param.mode = mode; + g_207_prefer_param.initial_value = 0; + g_207_prefer_param.data_check = data_check; + + g_207_tp_test_param.length = length; + g_207_tp_test_param.count = 0; + g_207_tp_test_param.count_remain = 0; + g_207_tp_test_param.initial_value = 0; + + vendor_tp_service_config_param(g_207_prefer_param); +} + +void ble_throughput_207_tp_rx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_print("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_207_tp_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + if (cause == 0) + { + if (g_207_prefer_param.mode == 4 || g_207_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_prefer_param.mode == 6 || g_207_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } + } +} +#endif + +void ble_throughput_207_tp_handle_write_data(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + APP_PRINT_INFO1("ble_throughput_207_tp_handle_write_data: length %d", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + + if (g_207_prefer_param.length == p_simp_client_cb_data->msg_data.write.u.write_data.length) + { + if (g_207_tp_test_param.count == 0) + { + g_207_tp_test_param.begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[207][RX]: :begin time = %dms", + g_207_tp_test_param.begin_time); + } + if (g_207_prefer_param.data_check) + { + uint16_t i; + uint8_t *p_value = p_simp_client_cb_data->msg_data.write.u.write_data.p_value; + for (i = 0; i < g_207_prefer_param.length; i++) + { + if (p_value[i] != g_207_tp_test_param.initial_value) + { + APP_PRINT_ERROR4("[207][RX]: data check failed: p_value[%d] 0x%x, initial_value %d, count %d", + i, p_value[i], + g_207_tp_test_param.initial_value, + g_207_tp_test_param.count); + data_uart_print("[207][RX]: data check failed\r\n"); + le_disconnect(0); + return; + } + } + } + } + else + { + APP_PRINT_ERROR1("[207][RX]: Len check failed: length %d", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + data_uart_print("[207][RX]: Len check failed: length %d\r\n", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + le_disconnect(0); + return; + } + g_207_tp_test_param.count++; + g_207_tp_test_param.initial_value++; + if (g_207_tp_test_param.count == g_207_prefer_param.count) + { + g_207_tp_test_param.end_time = os_sys_time_get(); + g_207_tp_test_param.elapsed_time = ble_throughput_os_time_get_elapsed(g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time); + g_207_tp_test_param.data_rate = + g_207_tp_test_param.count * g_207_prefer_param.length * 1000 / + (g_207_tp_test_param.elapsed_time); + APP_PRINT_ERROR1("[207][RX]: :end time = %dms", + g_207_tp_test_param.end_time); + le_disconnect(0); + } +} + + +void ble_throughput_207_dump_result(void) +{ + APP_PRINT_ERROR7("[207][RX]: conn_interval = %d,conn_latency = %d, length = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %d Bytes/s", + g_207_prefer_param.con_interval, + g_207_prefer_param.conn_slave_latency, + g_207_prefer_param.length, + g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time, + g_207_tp_test_param.elapsed_time, + g_207_tp_test_param.data_rate); + data_uart_print("[207][RX]: conn_interval %d, latency %d, length %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_207_prefer_param.con_interval, + g_207_prefer_param.conn_slave_latency, + g_207_prefer_param.length, + g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time, + g_207_tp_test_param.elapsed_time, + g_207_tp_test_param.data_rate); + APP_PRINT_ERROR2("[207][RX]: count %d rx_count %d", + g_207_prefer_param.count, g_207_tp_test_param.count); + + data_uart_print("[207][RX]: count %d rx_count %d\r\n", + g_207_prefer_param.count, g_207_tp_test_param.count); +} + +void ble_throughput_207_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("\r\nDisc reason 0x%04x\r\n", reason); + ble_throughput_207_dump_result(); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200.h new file mode 100644 index 00000000..57980edd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200.h @@ -0,0 +1,69 @@ + +#ifndef _BLE_AUTO_TEST_TC_200_H_ +#define _BLE_AUTO_TEST_TC_200_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef struct t_tp_test_config +{ + uint16_t con_interval; + uint16_t length; + uint8_t tx_octets; + bool test_drop_acl_data; + +} T_TP_TEST_CONFIG; + + +typedef struct t_tp_test_param +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + uint16_t length; + uint32_t count; + uint32_t count_remain; + uint8_t initial_value; + + uint8_t conn_id; + uint32_t begin_time; + uint32_t end_time; + uint32_t elapsed_time; + uint32_t data_rate; +} T_TP_TEST_PARAM; + +void ble_throughput_206_tp_notification_tx_start(void); +void ble_throughput_206_tp_notification_tx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check); +void ble_throughput_206_tp_notification_tx_tx_data_complete(uint8_t credits); +void ble_throughput_206_tp_notification_tx_tx_config(void *pdata); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_206_tp_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +#endif +void ble_throughput_206_tp_notification_tx_conn_param_update_event(uint8_t conn_id); +void ble_throughput_206_link_disconnected(uint8_t conn_id, uint16_t reason); +void ble_throughput_206_dump_result(void); + +void ble_throughput_207_tp_rx_start(void); +void ble_throughput_207_tp_rx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check); +void ble_throughput_207_tp_rx_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_207_tp_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +#endif +void ble_throughput_207_tp_handle_write_data(void *pdata); +void ble_throughput_207_link_disconnected(uint8_t conn_id, uint16_t reason); +void ble_throughput_207_dump_result(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200_sut.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200_sut.c new file mode 100644 index 00000000..8334df8f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200_sut.c @@ -0,0 +1,756 @@ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_throughput_app.h" + +#include "ble_throughput_user_cmd.h" +#include "user_cmd_parse.h" + +#include "os_sched.h" +#include +#include + +#include + +#include +#include + +#include "os_timer.h" +#include "os_msg.h" + +extern void *ble_throughput_evt_queue_handle; +extern void *ble_throughput_io_queue_handle; + +typedef void(*P_FUN_TC_RESULT_CB)(uint16_t case_id, uint16_t result, void *p_cb_data); +P_FUN_TC_RESULT_CB p_tc_result_cb = NULL; + +TC_206_SUT_MGR *p_tc_206_sut_mgr = NULL; +TC_206_SUT_MGR tc_206_sut_mgr; +TTP_PERFER_PARAM g_206_sut_prefer_param; + +TC_207_SUT_MGR *p_tc_207_sut_mgr = NULL; +TC_207_SUT_MGR tc_207_sut_mgr; +TTP_PERFER_PARAM g_207_sut_prefer_param; + +void ble_throughput_20x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data) +{ + T_TP_CB_DATA *p_cb = (T_TP_CB_DATA *)p_cb_data; + APP_PRINT_INFO1("ble_throughput_20x_sut_client_result_callback: %d.", p_cb->cb_type); + switch (p_cb->cb_type) + { + case TP_CLIENT_CB_TYPE_DISC_RESULT: + APP_PRINT_INFO2("TP_CLIENT_CB_TYPE_DISC_RESULT: is_found %d, value_handle 0x%x", + p_cb->cb_content.disc_result.is_found, + p_cb->cb_content.disc_result.char_tp.value_handle); + tp_client_write_cccd(conn_id, GATT_CLIENT_CHAR_CONFIG_NOTIFY); + break; + + case TP_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_cb->cb_content.write_result.type) + { + case TP_WRITE_CCCD: + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + tp_client_read_prefer_param(conn_id); + } + if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + tp_client_read_prefer_param(conn_id); + } + break; + case TP_WRITE_CHAR_VALUE: + APP_PRINT_INFO1("TP_WRITE_CHAR_VALUE: cause 0x%x.", p_cb->cb_content.write_result.cause); + if (p_cb->cb_content.write_result.write_type == GATT_WRITE_TYPE_CMD) + { + if (p_cb->cb_content.write_result.cause == 0) + { + if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + ble_throughput_207_sut_tx_data_complete(p_cb->cb_content.write_result.credits); + } + } + } + break; + default: + break; + } + break; + case TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + APP_PRINT_INFO3("TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: is_notif 0x%x, value_size %d, total_notify_rx_count %d", + p_cb->cb_content.notif_ind_data.is_notif, + p_cb->cb_content.notif_ind_data.value_size, + p_tc_206_sut_mgr->total_notify_rx_count); + if (g_206_sut_prefer_param.length == p_cb->cb_content.notif_ind_data.value_size) + { + if (p_tc_206_sut_mgr->total_notify_rx_count == 0) + { + p_tc_206_sut_mgr->begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[206 SUT]:start rx time = %dms", + p_tc_206_sut_mgr->begin_time); + } + if (g_206_sut_prefer_param.data_check) + { + uint16_t i; + uint8_t *p_value = p_cb->cb_content.notif_ind_data.pValue; + for (i = 0; i < g_206_sut_prefer_param.length; i++) + { + if (p_value[i] != p_tc_206_sut_mgr->initial_value) + { + APP_PRINT_ERROR4("[206 SUT][RX]: data check failed: p_value[%d] 0x%x, initial_value %d, total_notify_rx_count %d", + i, p_value[i], + p_tc_206_sut_mgr->initial_value, + p_tc_206_sut_mgr->total_notify_rx_count); + data_uart_print("[206 SUT][RX]: data check failed\r\n"); + le_disconnect(conn_id); + break; + } + } + } + } + else + { + APP_PRINT_ERROR1("[206 SUT][RX]: Len check failed: length %d", + p_cb->cb_content.notif_ind_data.value_size); + data_uart_print("[206 SUT][RX]: Len check failed: length %d\r\n", + p_cb->cb_content.notif_ind_data.value_size); + le_disconnect(conn_id); + break; + } + p_tc_206_sut_mgr->total_notify_rx_count++; + p_tc_206_sut_mgr->initial_value++; + if (p_tc_206_sut_mgr->total_notify_rx_count == g_206_sut_prefer_param.count) + { + p_tc_206_sut_mgr->end_time = os_sys_time_get(); + p_tc_206_sut_mgr->elapsed_time = ble_throughput_os_time_get_elapsed(p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time); + p_tc_206_sut_mgr->data_rate = + g_206_sut_prefer_param.count * g_206_sut_prefer_param.length * 1000 / + (p_tc_206_sut_mgr->elapsed_time); + APP_PRINT_ERROR1("[206 SUT]:end rx time = %dms", + p_tc_206_sut_mgr->end_time); + le_disconnect(conn_id); + } + } + break; + case TP_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO2("TP_CLIENT_CB_TYPE_READ_RESULT: cause 0x%x, value_size %d", + p_cb->cb_content.read_result.cause, + p_cb->cb_content.read_result.value_size); + switch (p_cb->cb_content.read_result.type) + { + case TP_READ_PREFER_PARAM: + + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + if (p_cb->cb_content.read_result.cause == GAP_SUCCESS + && p_cb->cb_content.read_result.value_size == sizeof(TTP_PERFER_PARAM)) + { + memcpy(&g_206_sut_prefer_param, p_cb->cb_content.read_result.p_value, sizeof(TTP_PERFER_PARAM)); + p_tc_206_sut_mgr->total_test_count = g_206_sut_prefer_param.count; + p_tc_206_sut_mgr->initial_value = g_206_sut_prefer_param.initial_value; + APP_PRINT_INFO6("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d", + g_206_sut_prefer_param.con_interval, g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, g_206_sut_prefer_param.mode, + g_206_sut_prefer_param.count, g_206_sut_prefer_param.data_check); + + data_uart_print("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d\r\n", + g_206_sut_prefer_param.con_interval, g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, g_206_sut_prefer_param.mode, + g_206_sut_prefer_param.count, g_206_sut_prefer_param.data_check); +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + if (g_206_sut_prefer_param.mode != 8) + { + T_TP_CONFIG_OP op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + ble_throughput_206_sut_phy_update(0); +#endif + if (g_206_sut_prefer_param.mode % 2 == 0) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; + data_uart_print("Off data length extension\r\n"); + } + else if (g_206_sut_prefer_param.mode % 2 == 1) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_251; + data_uart_print("On data length extension\r\n"); + } + tp_client_write_value(conn_id, 1, &op); + } + else +#endif + { + ble_throughput_206_sut_update_conn_param(0); + } + } + else + { + APP_PRINT_ERROR0("TP_CLIENT_CB_TYPE_READ_RESULT: TC_0206_TP_NOTIFICATION_TX_02 failed"); + } + } + + if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if (p_cb->cb_content.read_result.cause == GAP_SUCCESS + && p_cb->cb_content.read_result.value_size == sizeof(TTP_PERFER_PARAM)) + { + memcpy(&g_207_sut_prefer_param, p_cb->cb_content.read_result.p_value, sizeof(TTP_PERFER_PARAM)); + p_tc_207_sut_mgr->total_test_count = g_207_sut_prefer_param.count; + p_tc_207_sut_mgr->initial_value = g_207_sut_prefer_param.initial_value; + p_tc_207_sut_mgr->count_remain = g_207_sut_prefer_param.count; + APP_PRINT_INFO6("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d", + g_207_sut_prefer_param.con_interval, g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, g_207_sut_prefer_param.mode, + g_207_sut_prefer_param.count, g_207_sut_prefer_param.data_check); + + data_uart_print("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d\r\n", + g_207_sut_prefer_param.con_interval, g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, g_207_sut_prefer_param.mode, + g_207_sut_prefer_param.count, g_207_sut_prefer_param.data_check); +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + if (g_207_sut_prefer_param.mode != 8) + { +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + ble_throughput_207_sut_phy_update(0); +#endif + if (g_207_sut_prefer_param.mode % 2 == 0) + { + le_set_data_len(0, 27, 0x0848); + data_uart_print("Off data length extension\r\n"); + } + else if (g_207_sut_prefer_param.mode % 2 == 1) + { + le_set_data_len(0, 251, 0x0848); + data_uart_print("On data length extension\r\n"); + } + } + else +#endif + { + ble_throughput_207_sut_update_conn_param(0); + } + } + else + { + APP_PRINT_ERROR0("TP_CLIENT_CB_TYPE_READ_RESULT: TC_0207_TP_NOTIFICATION_TX_02 failed"); + } + } + break; + default: + break; + } + break; + default: + break; + } +} + +void ble_throughput_206_sut_start(uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 0; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_206_sut_mgr) + { + p_tc_206_sut_mgr = &tc_206_sut_mgr; + } + else + { + memset(p_tc_206_sut_mgr, 0, sizeof(TC_206_SUT_MGR)); + } + + memcpy(p_tc_206_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_206_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void ble_throughput_206_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + + ble_throughput_206_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0206_TP_NOTIFICATION_TX_02, 0, NULL); + } +} + +void ble_throughput_206_sut_link_connected(uint8_t conn_id) +{ + tp_client_start_discovery(conn_id); +} + +void ble_throughput_206_sut_update_conn_param(uint8_t conn_id) +{ + le_update_conn_param(conn_id, + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.conn_supervision_timeout, + 2 * (g_206_sut_prefer_param.con_interval - 1), + 2 * (g_206_sut_prefer_param.con_interval - 1) + ); +} + +void ble_throughput_206_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("ble_throughput_206_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + data_uart_print("ble_throughput_206_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout); + + +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_206_sut_phy_update(uint8_t conn_id) +{ + if (g_206_sut_prefer_param.mode == 0 || g_206_sut_prefer_param.mode == 1) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_sut_prefer_param.mode == 2 || g_206_sut_prefer_param.mode == 3) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_sut_prefer_param.mode == 4 || g_206_sut_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_sut_prefer_param.mode == 6 || g_206_sut_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } +} + +void ble_throughput_206_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + bool phy_result = false; + if (cause == 0) + { + if (g_206_sut_prefer_param.mode == 0 || g_206_sut_prefer_param.mode == 1) + { + if (tx_phy == GAP_PHYS_1M && rx_phy == GAP_PHYS_1M) + { + phy_result = true; + } + } + else if (g_206_sut_prefer_param.mode == 2 || g_206_sut_prefer_param.mode == 3) + { + if (tx_phy == GAP_PHYS_2M && rx_phy == GAP_PHYS_2M) + { + phy_result = true; + } + } + else if (g_206_sut_prefer_param.mode == 4 || g_206_sut_prefer_param.mode == 5 || + g_206_sut_prefer_param.mode == 6 || g_206_sut_prefer_param.mode == 7) + { + if (tx_phy == GAP_PHYS_CODED && rx_phy == GAP_PHYS_CODED) + { + phy_result = true; + } + } + } + if (phy_result == false) + { + APP_PRINT_ERROR0("[206 SUT]: Update phy failed"); + + data_uart_print("[206 SUT]: Update phy failed\r\n"); + le_disconnect(0); + } + else + { + ble_throughput_206_sut_update_conn_param(0); + } +} +#endif + +void ble_throughput_206_sut_dump_result(void) +{ + if (p_tc_206_sut_mgr != NULL) + { + APP_PRINT_ERROR8("[206 SUT][RX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, + g_206_sut_prefer_param.count, + p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time, + p_tc_206_sut_mgr->elapsed_time, + p_tc_206_sut_mgr->data_rate); + data_uart_print("[206 SUT][RX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, + g_206_sut_prefer_param.count, + p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time, + p_tc_206_sut_mgr->elapsed_time, + p_tc_206_sut_mgr->data_rate); + APP_PRINT_ERROR3("[206 SUT][RX]: total_test_count %d total_notify_rx_count %d, initial_value 0x%x\r\n", + p_tc_206_sut_mgr->total_test_count, p_tc_206_sut_mgr->total_notify_rx_count, + p_tc_206_sut_mgr->initial_value); + + data_uart_print("[206 SUT][RX]: total_test_count %d total_notify_rx_count %d, initial_value 0x%x\r\n", + p_tc_206_sut_mgr->total_test_count, p_tc_206_sut_mgr->total_notify_rx_count, + p_tc_206_sut_mgr->initial_value); + + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void ble_throughput_207_sut_start(uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 0; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_207_sut_mgr) + { + p_tc_207_sut_mgr = &tc_207_sut_mgr; + } + else + { + memset(p_tc_207_sut_mgr, 0, sizeof(TC_207_SUT_MGR)); + } + + memcpy(p_tc_207_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_207_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void ble_throughput_207_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + + ble_throughput_207_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0207_TP_WRITE_COMMAND_RX_02, 0, NULL); + } +} + +void ble_throughput_207_sut_link_connected(uint8_t conn_id) +{ + tp_client_start_discovery(conn_id); +} + +void ble_throughput_207_sut_update_conn_param(uint8_t conn_id) +{ + le_update_conn_param(conn_id, + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.conn_supervision_timeout, + 2 * (g_207_sut_prefer_param.con_interval - 1), + 2 * (g_207_sut_prefer_param.con_interval - 1) + ); +} + +void ble_throughput_207_sut_start_send_write_command(uint8_t conn_id) +{ + uint8_t credits = 10; + p_tc_207_sut_mgr->begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[207 SUT]:begin time = %dms", + p_tc_207_sut_mgr->begin_time); + + while (credits) + { + if (p_tc_207_sut_mgr->count_remain) + { + uint8_t value[250]; + memset(value, p_tc_207_sut_mgr->initial_value, + g_207_sut_prefer_param.length); + if (tp_client_write_command(conn_id, g_207_sut_prefer_param.length, value)) + { + credits--; + p_tc_207_sut_mgr->initial_value++; + p_tc_207_sut_mgr->count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } +} + +void *ble_throughput_207_timer = NULL; +void ble_throughput_207_timer_handler_func(void *context) +{ + uint8_t event = EVENT_IO_TO_APP; + + T_IO_MSG io_msg; + io_msg.type = IO_MSG_TYPE_QDECODE; + + if (ble_throughput_evt_queue_handle != NULL && ble_throughput_io_queue_handle != NULL) { + if (os_msg_send(ble_throughput_io_queue_handle, &io_msg, 0) == false) { + data_uart_print("ble throughput 207 timer handler func send msg fail"); + } else if (os_msg_send(ble_throughput_evt_queue_handle, &event, 0) == false) { + data_uart_print("ble throughput 207 timer handler func send event fail"); + } + } + os_timer_delete(&ble_throughput_207_timer); +} + +void ble_throughput_207_sut_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (p_tc_207_sut_mgr->count_remain) + { + uint8_t value[250]; + memset(value, p_tc_207_sut_mgr->initial_value, + g_207_sut_prefer_param.length); + if (tp_client_write_command(0, g_207_sut_prefer_param.length, value)) + { + credits--; + p_tc_207_sut_mgr->initial_value++; + p_tc_207_sut_mgr->count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + p_tc_207_sut_mgr->end_time = os_sys_time_get(); + p_tc_207_sut_mgr->elapsed_time = ble_throughput_os_time_get_elapsed(p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time); + p_tc_207_sut_mgr->data_rate = + g_207_sut_prefer_param.count * g_207_sut_prefer_param.length * 1000 / + (p_tc_207_sut_mgr->elapsed_time); + APP_PRINT_ERROR1("[207 SUT]:end time = %dms", + p_tc_207_sut_mgr->end_time); + os_timer_create(&ble_throughput_207_timer, "ble_throughput_207_timer", 1, 5000, false, ble_throughput_207_timer_handler_func); + os_timer_start(&ble_throughput_207_timer); + } + break; + } + } +} + +void ble_throughput_207_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("ble_throughput_207_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + data_uart_print("ble_throughput_207_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_207_sut_prefer_param.con_interval == con_interval && + g_207_sut_prefer_param.conn_slave_latency == conn_slave_latency && + g_207_sut_prefer_param.conn_supervision_timeout == conn_supervision_timeout) + { + ble_throughput_207_sut_start_send_write_command(0); + } + else + { + data_uart_print("[207 SUT] error: Invalid conn parameter\r\n"); + le_disconnect(0); + } +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_207_sut_phy_update(uint8_t conn_id) +{ + if (g_207_sut_prefer_param.mode == 0 || g_207_sut_prefer_param.mode == 1) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_sut_prefer_param.mode == 2 || g_207_sut_prefer_param.mode == 3) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_sut_prefer_param.mode == 4 || g_207_sut_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_sut_prefer_param.mode == 6 || g_207_sut_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } +} + +void ble_throughput_207_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + bool phy_result = false; + if (cause == 0) + { + if (g_207_sut_prefer_param.mode == 0 || g_207_sut_prefer_param.mode == 1) + { + if (tx_phy == GAP_PHYS_1M && rx_phy == GAP_PHYS_1M) + { + phy_result = true; + } + } + else if (g_207_sut_prefer_param.mode == 2 || g_207_sut_prefer_param.mode == 3) + { + if (tx_phy == GAP_PHYS_2M && rx_phy == GAP_PHYS_2M) + { + phy_result = true; + } + } + else if (g_207_sut_prefer_param.mode == 4 || g_207_sut_prefer_param.mode == 5 || + g_207_sut_prefer_param.mode == 6 || g_207_sut_prefer_param.mode == 7) + { + if (tx_phy == GAP_PHYS_CODED && rx_phy == GAP_PHYS_CODED) + { + phy_result = true; + } + } + } + if (phy_result == false) + { + APP_PRINT_INFO0("[207 SUT]: Update phy failed"); + + data_uart_print("[207 SUT]: Update phy failed\r\n"); + le_disconnect(0); + } + else + { + ble_throughput_207_sut_update_conn_param(0); + } +} +#endif + +void ble_throughput_207_sut_dump_result(void) +{ + if (p_tc_207_sut_mgr != NULL) + { + APP_PRINT_ERROR8("[207 SUT][TX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, + g_207_sut_prefer_param.count, + p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time, + p_tc_207_sut_mgr->elapsed_time, + p_tc_207_sut_mgr->data_rate); + data_uart_print("[207 SUT][TX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, + g_207_sut_prefer_param.count, + p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time, + p_tc_207_sut_mgr->elapsed_time, + p_tc_207_sut_mgr->data_rate); + APP_PRINT_ERROR3("[207 SUT][TX]: total_test_count %d count_remain %d, initial_value %d\r\n", + p_tc_207_sut_mgr->total_test_count, p_tc_207_sut_mgr->count_remain, + p_tc_207_sut_mgr->initial_value); + + data_uart_print("[207 SUT][TX]: total_test_count %d count_remain %d, initial_value %d\r\n", + p_tc_207_sut_mgr->total_test_count, p_tc_207_sut_mgr->count_remain, + p_tc_207_sut_mgr->initial_value); + } + else + { + data_uart_print("Not running\r\n"); + } +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200_sut.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200_sut.h new file mode 100644 index 00000000..64f1a79f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_200_sut.h @@ -0,0 +1,90 @@ + +#ifndef _BLE_AUTO_TEST_TC_200_SUT_H_ +#define _BLE_AUTO_TEST_TC_200_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t initial_value; + uint32_t total_test_count; + uint8_t remote_bd[6]; + uint32_t total_notify_rx_count; + uint32_t begin_time; + uint32_t end_time; + uint32_t elapsed_time; + uint32_t data_rate; +} TC_206_SUT_MGR; + +typedef struct +{ + uint8_t initial_value; + uint32_t total_test_count; + uint8_t remote_bd[6]; + uint32_t count_remain; + uint32_t begin_time; + uint32_t end_time; + uint32_t elapsed_time; + uint32_t data_rate; +} TC_207_SUT_MGR; + +typedef void (*P_FUN_PROFILE_CLIENT_RESULT_CB)(uint8_t conn_id, void *p_data); + +typedef enum +{ + TP_CONFIG_OP_SET_LL_DATA_LEN_27 = 1, + TP_CONFIG_OP_SET_LL_DATA_LEN_251 = 2, + TP_CONFIG_OP_START = 3, + + TP_CONFIG_OP_RFU = 0xFF +} T_TP_CONFIG_OP; + + +typedef enum +{ + TP_CONFIG_STATE_CONFIGING = 1, + TP_CONFIG_STATE_STARTED = 2, + + TP_CONFIG_STATE_RFU = 0xFF +} T_TP_CONFIG_STATE; + +void ble_throughput_20x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data); + + +/** + +*/ +void ble_throughput_206_sut_start(uint8_t remote_bd[6]); +void ble_throughput_206_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void ble_throughput_206_sut_link_connected(uint8_t conn_id); +void ble_throughput_206_sut_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_206_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +void ble_throughput_206_sut_phy_update(uint8_t conn_id); +#endif +void ble_throughput_206_sut_update_conn_param(uint8_t conn_id); +void ble_throughput_206_sut_dump_result(void); + +void ble_throughput_207_sut_start(uint8_t remote_bd[6]); +void ble_throughput_207_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void ble_throughput_207_sut_link_connected(uint8_t conn_id); +void ble_throughput_207_sut_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void ble_throughput_207_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +void ble_throughput_207_sut_phy_update(uint8_t conn_id); +#endif +void ble_throughput_207_sut_update_conn_param(uint8_t conn_id); +void ble_throughput_207_sut_dump_result(void); +void ble_throughput_207_sut_tx_data_complete(uint8_t credits); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app.c new file mode 100644 index 00000000..9ff70580 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app.c @@ -0,0 +1,776 @@ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include "app_msg.h" +#include "trace_app.h" +#include +#include "gap_scan.h" +#include "gap.h" +#include "gap_adv.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_throughput_app.h" +#include "ble_throughput_link_mgr.h" +#include "ble_throughput_user_cmd.h" +#include "user_cmd_parse.h" +#include +#include "os_sched.h" + +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#include "ble_throughput_vendor_tp_service.h" +#endif + +#include + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include "gap_adv.h" +#endif + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include +#include +#endif + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif + +extern uint8_t gSimpleProfileServiceId; +//extern bool g_206_phy_update; + + +bool V3NotifyEnable = false; +/* Client ID of Simple BLE Client Module, generated when add this module in main.c. Can't be modified by user. */ +/* Device state maintained in application. */ +T_GAP_DEV_STATE ble_throughput_gap_dev_state = {0, 0, 0, 0, 0}; +#if F_BT_LE_GATT_CLIENT_SUPPORT +extern T_CLIENT_ID vendor_tp_client_id; +#endif + +void ble_throughput_app_handle_gap_msg(T_IO_MSG *pBeeIoMsg); + +/** +* @brief All the application events are pre-handled in this function. +* +* All the IO MSGs are sent to this function. +* Then the event handling function shall be called according to the MSG type. +* +* @param io_msg The T_IO_MSG from peripherals or BT stack state machine. +* @return void +*/ +extern int ble_throughput_app_handle_at_cmd(uint16_t subtype, void *arg); +void ble_throughput_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + uint8_t rx_char; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + ble_throughput_app_handle_gap_msg(&io_msg); + break; + case IO_MSG_TYPE_UART: + /* We handle user command informations from Data UART in this branch. */ + rx_char = (uint8_t)io_msg.subtype; + user_cmd_collect(&user_cmd_if, &rx_char, sizeof(rx_char), user_cmd_table); + break; + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; + ble_throughput_app_handle_at_cmd(subtype, arg); + } + break; + case IO_MSG_TYPE_QDECODE: + { + le_disconnect(0); + data_uart_print("\r\n[207 SUT][TX]: test complete\r\n"); + } + break; + default: + break; + } +} + +/** + * @brief handle messages indicate that GAP device state has changed. + * @param new_state: GAP state. + * @retval none + */ +void ble_throughput_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("ble_throughput_app_handle_dev_state_evt: init state %d scan state %d adv state %d conn state %d", + new_state.gap_init_state, + new_state.gap_scan_state, new_state.gap_adv_state, new_state.gap_conn_state); + if (ble_throughput_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + /*stack ready*/ + } + } + + if (ble_throughput_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + data_uart_print("GAP scan stop"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + data_uart_print("GAP scan start"); + } + } + + if (ble_throughput_gap_dev_state.gap_conn_state != new_state.gap_conn_state) + { + /* + APP_PRINT_INFO2("Conn state: %d -> %d", + ble_throughput_gap_dev_state.gap_conn_state, + new_state.gap_conn_state); + */ + } + + ble_throughput_gap_dev_state = new_state; +} + +/** + * @brief handle messages indicate that GAP connection state has changed. + * @param conn_id: connection ID. + * @param new_state: new connection state. + * @param disc_cause: when new_state=GAP_CONN_STATE_DISCONNECTED, this value is valid. + * @retval none + */ + +extern TC_206_SUT_MGR *p_tc_206_sut_mgr; +extern TC_207_SUT_MGR *p_tc_207_sut_mgr; +extern TTP_PERFER_PARAM g_206_sut_prefer_param; +extern TTP_PERFER_PARAM g_207_sut_prefer_param; +extern T_TP_TEST_PARAM g_207_tp_test_param; + +void ble_throughput_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + APP_PRINT_INFO3("ble_throughput_app_handle_conn_state_evt: conn_id %d oldState %d new_state %d", + conn_id, ble_throughput_app_link_table[conn_id].conn_state, new_state); + + ble_throughput_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + /*device is disconnected.*/ + case GAP_CONN_STATE_DISCONNECTED: + { + APP_PRINT_INFO2("ble_throughput_app_handle_conn_state_evt: conn_id %d disc_cause 0x%04x", + conn_id, disc_cause); + if (ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + ble_throughput_206_link_disconnected(conn_id, disc_cause); + } + else if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if(disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + g_207_tp_test_param.end_time = os_sys_time_get(); + g_207_tp_test_param.elapsed_time = ble_throughput_os_time_get_elapsed(g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time); + g_207_tp_test_param.data_rate = + g_207_tp_test_param.count * g_207_tp_test_param.length * 1000 / (g_207_tp_test_param.elapsed_time); + + } + ble_throughput_207_link_disconnected(conn_id, disc_cause); + } + else + { + data_uart_print("Disconnect conn_id %d\r\n", conn_id); + } +#endif + } + else if (ble_throughput_app_get_cur_role() == TC_ROLE_SUT) + { + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + p_tc_206_sut_mgr->end_time = os_sys_time_get(); + p_tc_206_sut_mgr->elapsed_time = ble_throughput_os_time_get_elapsed(p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time); + p_tc_206_sut_mgr->data_rate = p_tc_206_sut_mgr->total_notify_rx_count * g_206_sut_prefer_param.length * 1000 / + (p_tc_206_sut_mgr->elapsed_time); + ble_throughput_206_sut_link_disconnected(conn_id, disc_cause); + } + else if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + int sut_tx_count = g_207_sut_prefer_param.count - p_tc_207_sut_mgr->count_remain; + p_tc_207_sut_mgr->end_time = os_sys_time_get(); + p_tc_207_sut_mgr->elapsed_time = ble_throughput_os_time_get_elapsed(p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time); + p_tc_207_sut_mgr->data_rate = sut_tx_count * g_207_sut_prefer_param.length * 1000 / + (p_tc_207_sut_mgr->elapsed_time); + ble_throughput_207_sut_link_disconnected(conn_id, disc_cause); + } + else + { + data_uart_print("Disconnect conn_id = %d\r\n", conn_id); + } + } + + if (disc_cause == (HCI_ERR | HCI_ERR_CONN_TIMEOUT)) + { + APP_PRINT_INFO1("Test_HandleBtConnStateChangeEvt: connection lost", conn_id); + } + memset(&ble_throughput_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + /*device is disconnected.*/ + case GAP_CONN_STATE_CONNECTING: + break; + + /*device is connected*/ + case GAP_CONN_STATE_CONNECTED: + { + uint16_t mtu_size; + le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, &mtu_size, conn_id); + //data_uart_print("Connected conn_id = %d, mtu size = %d\r\n", conn_id, mtu_size); + if (ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + data_uart_print("connected success conn_id %d\r\n", conn_id); + } + else if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + data_uart_print("connected success conn_id %d\r\n", conn_id); + } + else + { + data_uart_print("Conn conn_id = %d\r\n", conn_id); + } +#endif + } + else if (ble_throughput_app_get_cur_role() == TC_ROLE_SUT) + { + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + data_uart_print("connected success conn_id %d\r\n", conn_id); + ble_throughput_206_sut_link_connected(conn_id); + } + else if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + data_uart_print("connected success conn_id %d\r\n", conn_id); + ble_throughput_207_sut_link_connected(conn_id); + } + else + { + data_uart_print("Conn conn_id %d\r\n", conn_id); + } + } + } + break; + + /*error comes here*/ + default: + break; + + } +} + +/** + * @brief handle messages indicate that GAP bond state has changed. + * @param conn_id: connection ID. + * @param new_state: GAP bond state. + * @param status: pairing complete status. + * @arg: 0 - success. + * @arg: other - failed. + * @retval none + */ +void ble_throughput_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t status) +{ + APP_PRINT_INFO3("ble_throughput_app_handle_authen_state_evt: conn_id %d, new_state %d, status 0x%x", conn_id, + new_state, status); + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(GAP_AUTHEN_STATE_STARTED)"); + } + break; + case GAP_AUTHEN_STATE_COMPLETE: + { + APP_PRINT_INFO1("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(GAP_AUTHEN_STATE_COMPLETE) status 0x%x", + status); + if (status == 0) + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair success"); + } + else + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair failed"); + data_uart_print("pair failed conn_id = %d\r\n", conn_id); + } + } + break; + + default: + { + APP_PRINT_INFO1("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(unknown newstate: %d)", new_state); + } + break; + } + +} + +/** + * @brief handle messages indicate that connection parameters has changed. + * @param conn_id: connection ID. + * @param status: change status. + * @retval none + */ +void ble_throughput_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + if (ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { + ble_throughput_206_tp_notification_tx_conn_param_update_event(conn_id); + } + else if (ble_throughput_app_get_cur_role() == TC_ROLE_SUT) + { + ble_throughput_206_sut_conn_param_update_event(conn_id); + } + } + else if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if (ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { + ble_throughput_207_tp_rx_conn_param_update_event(conn_id); + } + else if (ble_throughput_app_get_cur_role() == TC_ROLE_SUT) + { + ble_throughput_207_sut_conn_param_update_event(conn_id); + } + } + } + break; + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_INFO0("GAP_MSG_LE_CONN_PARAM_UPDATE failed."); + data_uart_print("LE_CONN_PARAM_UPDATE failed\r\n"); + } + break; + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("GAP_MSG_LE_CONN_PARAM_UPDATE param request pending."); + } + break; + default: + break; + } +} + +void ble_throughput_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("ble_throughput_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); + printf("ble_throughput_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d\r\n", conn_id, mtu_size); +} +/** + * @brief handle messages from GAP layer. + * @param pBeeIoMsg: message from GAP layer. + * @retval none + */ +void ble_throughput_app_handle_gap_msg(T_IO_MSG *p_io_msg) +{ + T_LE_GAP_MSG bt_msg; + uint8_t conn_id; + + memcpy(&bt_msg, &p_io_msg->u.param, sizeof(p_io_msg->u.param)); + + switch (p_io_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + ble_throughput_app_handle_dev_state_evt(bt_msg.msg_data.gap_dev_state_change.new_state, + bt_msg.msg_data.gap_dev_state_change.cause); + } + break; + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + ble_throughput_app_handle_conn_state_evt(bt_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)bt_msg.msg_data.gap_conn_state_change.new_state, + bt_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + case GAP_MSG_LE_CONN_MTU_INFO: + { + ble_throughput_app_handle_conn_mtu_info_evt(bt_msg.msg_data.gap_conn_mtu_info.conn_id, + bt_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + ble_throughput_app_handle_authen_state_evt(bt_msg.msg_data.gap_authen_state.conn_id, + bt_msg.msg_data.gap_authen_state.new_state, + bt_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + uint8_t conn_id = bt_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + uint8_t conn_id = bt_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn id=%d value=%d\r\n", + conn_id, display_value); + } + break; + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t displayValue = 0; + uint8_t conn_id = bt_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &displayValue); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: %d", displayValue); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + conn_id = bt_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_PASSKEY_INPUT"); + + uint32_t passKey = 888888; + le_bond_passkey_input_confirm(conn_id, passKey, GAP_CFM_CAUSE_ACCEPT); + + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + conn_id = bt_msg.msg_data.gap_bond_oob_input.conn_id; + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + ble_throughput_app_handle_conn_param_update_evt(bt_msg.msg_data.gap_conn_param_update.conn_id, + bt_msg.msg_data.gap_conn_param_update.status); + } + break; + default: + APP_PRINT_ERROR1("ble_throughput_app_handle_gap_msg unknown subtype", p_io_msg->subtype); + break; + } + +} + +/** + * @brief This callback will be called when advertising or scan response data received. + * @param msg_type: type of the message sent from GAP Central Role layer. + * @param cb_data: message sent from GAP Central Role layer. + * @retval None + */ +T_APP_RESULT ble_throughput_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_LE_CB_DATA)); + APP_PRINT_INFO1("app_gap_callback: cb_type %d", cb_type); + switch (cb_type) + { +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO4(" GAP_MSG_LE_CONN_UPDATE_IND: max_interval=0x%x, min_interval=0x%x, Latency=0x%x,timeOut=0x%x", + cb_data.p_le_conn_update_ind->conn_interval_max, + cb_data.p_le_conn_update_ind->conn_interval_min, + cb_data.p_le_conn_update_ind->conn_latency, + cb_data.p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_SET_DATA_LEN: + APP_PRINT_INFO2(" GAP_MSG_LE_SET_DATA_LEN: conn_id=0x%x, cause=0x%x", + cb_data.p_le_set_data_len_rsp->conn_id, + cb_data.p_le_set_data_len_rsp->cause); + break; + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO5(" GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id=0x%x MaxTxOctets=0x%x MaxTxTime=0x%x MaxRxOctets=0x%x MaxRxTime=0x%x", + cb_data.p_le_data_len_change_info->conn_id, + cb_data.p_le_data_len_change_info->max_tx_octets, + cb_data.p_le_data_len_change_info->max_tx_time, + cb_data.p_le_data_len_change_info->max_rx_octets, + cb_data.p_le_data_len_change_info->max_rx_time); + data_uart_print("LE data length: con id %d, tx %d octets, %d ms - rx %d octets, %d ms\r\n", + cb_data.p_le_data_len_change_info->conn_id, + cb_data.p_le_data_len_change_info->max_tx_octets, + cb_data.p_le_data_len_change_info->max_tx_time, + cb_data.p_le_data_len_change_info->max_rx_octets, + cb_data.p_le_data_len_change_info->max_rx_time); + break; +#endif + case GAP_MSG_LE_SET_RAND_ADDR: + APP_PRINT_INFO1(" GAP_MSG_LE_SET_RAND_ADDR: cause=0x%x", + cb_data.p_le_set_rand_addr_rsp->cause); + break; + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3(" GAP_MSG_LE_READ_RSSI:conn_id=0x%x cause=0x%x rssi=%01d", + cb_data.p_le_read_rssi_rsp->conn_id, + cb_data.p_le_read_rssi_rsp->cause, + cb_data.p_le_read_rssi_rsp->rssi); + break; +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1(" GAP_MSG_LE_ADV_UPDATE_PARAM:cause=0x%x", + cb_data.p_le_adv_update_param_rsp->cause); + break; +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1(" GAP_MSG_LE_DISABLE_SLAVE_LATENCY:cause=0x%x", + cb_data.p_le_disable_slave_latency_rsp->cause); + break; +#endif + case GAP_MSG_LE_CREATE_CONN_IND: + APP_PRINT_INFO0(" GAP_MSG_LE_CREATE_CONN_IND"); + result = APP_RESULT_ACCEPT; + break; +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4(" GAP_MSG_LE_PHY_UPDATE_INFO:conn %d, cause 0x%x, rx_phy %d, tx_phy %d", + cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->rx_phy, + cb_data.p_le_phy_update_info->tx_phy); + data_uart_print("LE phy update info: con id %d, cause = 0x%x, rx_phy = %d, tx_phy = %d\r\n", + cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->rx_phy, + cb_data.p_le_phy_update_info->tx_phy); + + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + if (ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { + ble_throughput_206_tp_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); + } + else if (ble_throughput_app_get_cur_role() == TC_ROLE_SUT) + { + ble_throughput_206_sut_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); + } + } + else if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if (ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { + ble_throughput_207_tp_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); + } + else if (ble_throughput_app_get_cur_role() == TC_ROLE_SUT) + { + ble_throughput_207_sut_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); + } + } + break; +#endif +#if F_BT_LE_READ_REMOTE_FEATS + case GAP_MSG_LE_REMOTE_FEATS_INFO: + APP_PRINT_INFO3(" GAP_MSG_LE_REMOTE_FEATS_INFO:conn id %d, cause 0x%x, remote_feats %b", + cb_data.p_le_remote_feats_info->conn_id, + cb_data.p_le_remote_feats_info->cause, + TRACE_BINARY(8, cb_data.p_le_remote_feats_info->remote_feats)); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1(" GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + cb_data.p_le_update_passed_chann_map_rsp->cause); + break; +#endif + + default: + break; + } + return result; +} + +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT ble_throughput_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + + if (client_id == vendor_tp_client_id) + { + T_TP_CB_DATA *p_cb = (T_TP_CB_DATA *)p_data; + ble_throughput_20x_sut_client_result_callback(conn_id, p_cb); + } + + return result; +} +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +/****************************************************************** + * @fn app_profile_callback + * @brief All the bt profile callbacks are handled in this function. + * Then the event handling function shall be called according to the serviceID + * of T_IO_MSG. + * + * @param serviceID - service id of profile + * @param p_data - pointer to callback data + * @return void + */ +T_APP_RESULT ble_throughput_app_profile_callback(T_SERVER_ID serviceID, void *p_data) +{ + T_APP_RESULT appResult = APP_RESULT_SUCCESS; + if (serviceID == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *pPara = (T_SERVER_APP_CB_DATA *)p_data; + switch (pPara->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("profile callback PROFILE_EVT_SRV_REG_COMPLETE result", + pPara->event_data.service_reg_result); + { + //peripheral_Init_StartAdvertising(); + } + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO2("profile callback PROFILE_EVT_SEND_DATA_COMPLETE,result = %d wCredits = %d", + pPara->event_data.send_data_result.cause, + pPara->event_data.send_data_result.credits); + + if (pPara->event_data.send_data_result.cause == GAP_SUCCESS) + { + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + ble_throughput_206_tp_notification_tx_tx_data_complete(pPara->event_data.send_data_result.credits); + } + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (serviceID == gSimpleProfileServiceId) + { + TTP_CALLBACK_DATA *pTpCallbackData = (TTP_CALLBACK_DATA *)p_data; + APP_PRINT_INFO1("gSimpleProfileServiceId conn_id = %d", pTpCallbackData->conn_id); + switch (pTpCallbackData->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + APP_PRINT_INFO0("SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION"); + switch (pTpCallbackData->msg_data.notification_indification_index) + { + case VENDOR_TP_SERVICE_V1_INDICATION_ENABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_INDICATION_ENABLE"); + } + break; + + case VENDOR_TP_SERVICE_V1_INDICATION_DISABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_INDICATION_DISABLE"); + } + break; + case VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE"); + } + break; + case VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE"); + } + break; + + } + } + break; + + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + APP_PRINT_INFO0("SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE"); + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + APP_PRINT_INFO0("SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE"); + if (pTpCallbackData->msg_data.write.write_type == WRITE_REQUEST) + { + if (ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + ble_throughput_206_tp_notification_tx_tx_config(p_data); + } + } + else + { + if (ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + ble_throughput_207_tp_handle_write_data(p_data); + } + } + } + } + } + + return appResult; +} +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app.h new file mode 100644 index 00000000..ffb4c531 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app.h @@ -0,0 +1,52 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ble_auto_test_application.h +* @brief gap roles test app implementation +* @details gap roles test app implementation +* @author jane +* @date 2016-02-18 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _GAP_ROLES_TEST_APP_H_ +#define _GAP_ROLES_TEST_APP_H_ +#include "app_msg.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#endif + + +extern void ble_throughput_app_handle_io_msg(T_IO_MSG io_msg); +extern T_APP_RESULT ble_throughput_app_gap_callback(uint8_t cb_type, + void *p_cb_data); + +#if F_BT_LE_GATT_SERVER_SUPPORT +extern T_APP_RESULT ble_throughput_app_profile_callback(T_SERVER_ID serviceID, void *p_data); +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT ble_throughput_app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data); +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT ble_throughput_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_flags.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_flags.h new file mode 100644 index 00000000..0aee458f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_flags.h @@ -0,0 +1,7 @@ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "bt_flags.h" +#define APP_MAX_LINKS 4 + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_main.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_main.c new file mode 100644 index 00000000..5aee438b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_main.c @@ -0,0 +1,339 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief This is the entry of user code which the main function resides in. + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + * @attention + *

© COPYRIGHT 2016 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include "os_sched.h" +#include "ble_throughput_app_task.h" +#include "trace_app.h" +#include "gap.h" +#include "gap_bond_le.h" +#include "gap_scan.h" +#include +#include +#include +#include +#include "rtk_coex.h" + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +#include "gap_msg.h" +#include "ble_throughput_app.h" +#include "ble_throughput_user_cmd.h" +#include "data_uart.h" + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include "gap_adv.h" +#endif + +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#include "ble_throughput_vendor_tp_service.h" +#endif + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include "ble_throughput_vendor_tp_client.h" +#endif + +#include "trace_uart.h" +#include "ble_throughput_app_flags.h" + +/**< Default scan interval (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_INTERVAL 0x10 +/**< Default scan window (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_WINDOW 0x10 + +/**< Client ID for Simple BLE Client module, get from lower layer when add Simple BLE Client module. */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_CLIENT_ID vendor_tp_client_id; +#endif + +uint8_t gSimpleProfileServiceId; + + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +// What is the advertising interval when device is discoverable (units of 625us, 160=100ms) +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 //0x20 /* 20ms */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 //0x30 /* 30ms */ +#define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL + +// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic parameter update request is enabled +#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 80 +// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic parameter update request is enabled +#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 800 +// Slave latency to use if automatic parameter update request is enabled +#define DEFAULT_DESIRED_SLAVE_LATENCY 0 +// Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter update request is enabled +#define DEFAULT_DESIRED_CONN_TIMEOUT 1000 + +// GAP - SCAN RSP data (max size = 31 bytes) +static uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc1, 0x03, /* Keyboard */ +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +// best kept short to conserve power while advertisting) +static uint8_t adv_data[] = +{ + /* Core spec. Vol. 3, Part C, Chapter 18 */ + /* Flags */ + 0x02, /* length */ + 0x01, 0x05, /* type="flags", data="bit 1: LE General Discoverable Mode" */ + /* Service */ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc1, 0x03, /* Keyboard */ + 0x0D, /* length */ + 0x09, /* type="Complete local name" */ + 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '_', 'Q', 'W', 'E' /* Keyboard Name */ +}; +#endif + +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +void ble_throughput_bt_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); +} +/** + * @brief Initiate GAP parameters, these params will affect the local device's behavior. + * @retval none. + */ +void ble_throughput_app_le_gap_init() +{ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "Bee_GapTest"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + +#if F_BT_LE_GAP_SCAN_SUPPORT + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; +#endif + + uint8_t pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t oob_enable = false; + uint32_t passkey = 0; /* passkey "000000"*/ + uint8_t fix_passkey_enable = false; + uint8_t secReqEnable = false; + uint16_t secReqRequirement = GAP_AUTHEN_BIT_BONDING_FLAG; +#if F_BT_LE_PRIVACY_SUPPORT + uint16_t privacy_timeout = 0x384; +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + //advertising parameters + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advDirectType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t advIntMax = DEFAULT_ADVERTISING_INTERVAL_MIN; +#endif + + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(uint8_t), &pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(uint16_t), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(uint8_t), &io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + +#if F_BT_LE_GAP_SCAN_SUPPORT + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(uint32_t), &passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(uint8_t), &fix_passkey_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &secReqRequirement); +#if F_BT_LE_PRIVACY_SUPPORT + le_privacy_set_param(GAP_PARAM_PRIVACY_TIMEOUT, sizeof(uint16_t), &privacy_timeout); +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + //Set advertising parameters + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectType), &advDirectType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); +#endif +} + +/** + * @brief Initiate Profile. + * @retval none. + */ +void ble_throughput_app_le_profile_init(void) +{ +#if F_BT_LE_GATT_SERVER_SUPPORT + server_init(1); + gSimpleProfileServiceId = vendor_tp_service_add((void *)ble_throughput_app_profile_callback); + server_register_app_cb(ble_throughput_app_profile_callback); +#endif + + /* Register app callback--App_CentralRoleCallback to handle events from GAP Central Role. */ + le_register_app_cb(ble_throughput_app_gap_callback); + +#if F_BT_LE_GATT_CLIENT_SUPPORT + client_init(1); + vendor_tp_client_id = tp_client_add(ble_throughput_client_callback); +#endif + +#if F_BT_LE_PRIVACY_SUPPORT + le_privacy_register_cb(App_PrivacyCallback); +#endif +} + +/** + * @brief PwrMgr_Init() contains the setting about power mode. + * @retval none. + */ +void pwrmgr_init() +{ +#if F_BT_DLPS_EN + data_uart_dlps_init(); + lps_mode_set(LPM_DLPS_MODE); + lps_mode_pause(); +#endif +} + +/** + * @brief Task_Init() contains the initialization of all the tasks. + * + * NOTE: There are four tasks are initiated. + * Lowerstack task and upperstack task are used by bluetooth stack. + * Application task is task which user application code resides in. + * Emergency task is reserved. + * + * @retval none. + */ +void ble_throughput_task_init() +{ + ble_throughput_app_task_init(); +} + +/** + * @brief main() is the entry of user code. + * @retval none. + */ +int ble_throughput_app_main(void) +{ + bt_trace_init(); + ble_throughput_bt_stack_config_init(); + bte_init(); + le_gap_init(APP_MAX_LINKS); + ble_throughput_app_le_gap_init(); + ble_throughput_app_le_profile_init(); + pwrmgr_init(); + ble_throughput_task_init(); + + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 0); + + return 0; +} + +int ble_throughput_app_init(void) +{ + int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while( !wifi_is_up(RTW_STA_INTERFACE) ) { + os_delay(1000); + } + + //wifi_disable_powersave(); + + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + bt_stack_already_on = 1; + printf("[BLE Central]BT Stack already on\n\r"); + return 0; + } + else + ble_throughput_app_main(); + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +void ble_throughput_app_deinit(void) +{ + ble_throughput_app_task_deinit(); + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + } +#endif +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_task.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_task.c new file mode 100644 index 00000000..9da3e52c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_task.c @@ -0,0 +1,114 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file application.c + * @brief application task. + * @details + * @author ranhui + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + * @attention + *

© COPYRIGHT 2016 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include +#include +#include "ble_throughput_app_task.h" +#include "app_msg.h" +#include "gap.h" +#include "ble_throughput_user_cmd.h" +#include "gap_msg.h" + +extern T_GAP_DEV_STATE ble_throughput_gap_dev_state; +extern void ble_throughput_app_handle_io_msg(T_IO_MSG io_msg); +void ble_throughput_app_main_task(void *p_param); + +#define BLE_THROUGHPUT_MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define BLE_THROUGHPUT_MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define BLE_THROUGHPUT_MAX_NUMBER_OF_EVENT_MESSAGE (BLE_THROUGHPUT_MAX_NUMBER_OF_GAP_MESSAGE + BLE_THROUGHPUT_MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + + +/**< Handles of app task and queues. */ +void *ble_throughput_app_task_handle; +void *ble_throughput_evt_queue_handle; +void *ble_throughput_io_queue_handle; + +/** + * @brief application task. + * @param pvParameters + * @retval none + */ +void ble_throughput_app_main_task(void *p_param) +{ + char event; + + os_msg_queue_create(&ble_throughput_io_queue_handle, BLE_THROUGHPUT_MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&ble_throughput_evt_queue_handle, BLE_THROUGHPUT_MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(unsigned char)); + + gap_start_bt_stack(ble_throughput_evt_queue_handle, ble_throughput_io_queue_handle, BLE_THROUGHPUT_MAX_NUMBER_OF_GAP_MESSAGE); + + data_uart_init(ble_throughput_evt_queue_handle, ble_throughput_io_queue_handle); + user_cmd_init(&user_cmd_if, "ble_throughput_test"); + + while (true) + { + if (os_msg_recv(ble_throughput_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(ble_throughput_io_queue_handle, &io_msg, 0) == true) + { + ble_throughput_app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** + * @brief Create application task. + * @retval none + */ +void ble_throughput_app_task_init() +{ + + /* Create APP Task. */ + os_task_create(&ble_throughput_app_task_handle, "ble_throughput_app", ble_throughput_app_main_task, 0, 512 * 4, 1); +} + +void ble_throughput_app_task_deinit(void) +{ + if (ble_throughput_app_task_handle) { + os_task_delete(ble_throughput_app_task_handle); + } + if (ble_throughput_io_queue_handle) { + os_msg_queue_delete(ble_throughput_io_queue_handle); + } + if (ble_throughput_evt_queue_handle) { + os_msg_queue_delete(ble_throughput_evt_queue_handle); + } + ble_throughput_io_queue_handle = NULL; + ble_throughput_evt_queue_handle = NULL; + ble_throughput_app_task_handle = NULL; + + ble_throughput_gap_dev_state.gap_init_state = 0; + ble_throughput_gap_dev_state.gap_adv_sub_state = 0; + ble_throughput_gap_dev_state.gap_adv_state = 0; + ble_throughput_gap_dev_state.gap_scan_state = 0; + ble_throughput_gap_dev_state.gap_conn_state = 0; + +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_task.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_task.h new file mode 100644 index 00000000..f3f977f4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_app_task.h @@ -0,0 +1,33 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file application.h + * @brief Application task related interfaces. + * @details + * @author ranhui + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion **/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Add Includes here **/ + +/** Add all public functions here **/ +extern void ble_throughput_app_task_init(void); +extern void ble_throughput_app_task_deinit(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_link_mgr.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_link_mgr.c new file mode 100644 index 00000000..600c6e99 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_link_mgr.c @@ -0,0 +1,96 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include +#include +#include + +/*============================================================================* + * Constants + *============================================================================*/ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup SCATTERNET_GAP_MSG + * @{ + */ +T_APP_LINK ble_throughput_app_link_table[APP_MAX_LINKS]; +/** @} */ +/** @addtogroup SCATTERNET_SCAN_MGR + * @{ + */ +T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +uint8_t dev_list_count = 0; +/** @} */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (dev_list_count < APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < dev_list_count; i++) + { + if (memcmp(bd_addr, dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(dev_list[dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + dev_list[dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void link_mgr_clear_device_list(void) +{ + dev_list_count = 0; +} +/** @} */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_link_mgr.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_link_mgr.h new file mode 100644 index 00000000..37fdd1d3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_link_mgr.h @@ -0,0 +1,74 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _LINK_MANAGER_H_ +#define _LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif + +#include "ble_throughput_app_flags.h" +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Define device list table size. */ +#define APP_MAX_DEVICE_INFO 6 + +/** @addtogroup SCATTERNET_GAP_MSG + * @{ + */ +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; +/** @} */ /* End of group SCATTERNET_GAP_MSG */ +/** @addtogroup SCATTERNET_SCAN_MGR GATT + * @{ + */ +/** + * @brief Device list block defination. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/** @} */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK ble_throughput_app_link_table[APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void link_mgr_clear_device_list(void); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_test_case.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_test_case.c new file mode 100644 index 00000000..7de80d37 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_test_case.c @@ -0,0 +1,422 @@ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_throughput_app.h" +#include "os_sched.h" +#include "ble_throughput_user_cmd.h" +#include "user_cmd_parse.h" +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#endif + +#include +#include "atcmd_bt.h" +#include "log_service.h" + +T_CUR_TEST_CASE g_cur_test_case; + +T_CUR_DEVICE_ROLE g_cur_test_role; + +TGATTDBdAddr tc_rembd_list[] = /* first entry is default BD: */ +{ + { 0x66, 0x66, 0xee, 0x22, 0x11, 0x00 }, /* FPGA v6-5 */ + { 0x3d, 0x19, 0x48, 0x25, 0x80, 0x00 }, /* Stollmann Board 1 */ + { 0xe3, 0x18, 0x48, 0x25, 0x80, 0x00 }, /* Stollmann Board 2 */ + { 0x01, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB1*/ + { 0x02, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB2*/ + { 0x03, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB3*/ + { 0x04, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB4*/ + { 0x05, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB5*/ + { 0x06, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB6*/ + { 0x07, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB7*/ + { 0x08, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB8*/ + { 0x09, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB9*/ + +}; + +TGATTDBdAddr g_cur_rembd; + +uint32_t str_to_uint32(char *p) +{ + uint32_t result = 0; + bool hex = false; + + /* check if value is dec */ + if (p[0] == 'x') + { + hex = true; + p = &p[1]; + } + else if ((p[0] == '0') && (p[1] == 'x')) + { + hex = true; + p = &p[2]; + } + + for (;;) + { + char ch; + ch = *(p++) | 0x20; /* convert to lower case */ + + if (hex) /* dec value */ + { + /* hex value */ + if ((ch >= 'a') && (ch <= 'f')) + { + ch -= ('a' - 10); + } + else if ((ch >= '0') && (ch <= '9')) + { + ch -= '0'; + } + else + { + break; + } + result = (result << 4); + result += (ch & 0x0f); + } + else + { + if (ch < '0' || ch > '9') + { + break; /* end of string reached */ + } + result = 10 * result + ch - '0'; + } + } + return (result); +} + + +uint32_t ble_throughput_os_time_get_elapsed(uint32_t begin, uint32_t end) +{ +#if 1 + if (end > begin) + { + return end - begin; + } + else + { + return ((uint32_t)(2147483647) - begin + end); + } +#else + uint32_t expire_count; + + if (begin <= end) + { + expire_count = end - begin; + } + else + { + expire_count = 0xFFFFFFFF - (begin - end); + } + return expire_count; +#endif +} + +T_CUR_DEVICE_ROLE ble_throughput_app_get_cur_role(void) +{ + return g_cur_test_role; +} + +void ble_throughput_app_set_cur_role(T_CUR_DEVICE_ROLE role) +{ + switch (role) + { + case TC_ROLE_UNDEFINED: + data_uart_print("ble_throughput_app_set_cur_role: TC_ROLE_UNDEFINED\r\n"); + break; + case TC_ROLE_DUT: + data_uart_print("ble_throughput_app_set_cur_role: role TC_ROLE_DUT\r\n"); + break; + case TC_ROLE_SUT: + data_uart_print("ble_throughput_app_set_cur_role: TC_ROLE_SUT\r\n"); + break; + default: + role = TC_ROLE_UNDEFINED; + data_uart_print("ble_throughput_app_set_cur_role: TC_ROLE_UNDEFINED\r\n"); + break; + } + g_cur_test_role = role; +} + + +T_CUR_TEST_CASE ble_throughput_app_get_cur_test_case(void) +{ + return g_cur_test_case; +} + +void ble_throughput_app_display_case_details(T_CUR_TEST_CASE test_case_id) +{ + switch (test_case_id) + { + case TC_IDLE: + { + data_uart_print("select one test case:\r\n"); + + data_uart_print("testcase 1 - %s\r\n", "TC_0206_TP_NOTIFICATION_TX_02"); + data_uart_print("testcase 2 - %s\r\n", "TC_0207_TP_WRITE_COMMAND_RX_02"); + } + break; + + case TC_0206_TP_NOTIFICATION_TX_02: + data_uart_print("TC_0206_TP_NOTIFICATION_TX_02 is selected\r\n"); + APP_PRINT_INFO0("TC_0206_TP_NOTIFICATION_TX_02 Start\r\n"); + break; + + case TC_0207_TP_WRITE_COMMAND_RX_02: + data_uart_print("TC_0207_TP_WRITE_COMMAND_RX_02 is selected\r\n"); + APP_PRINT_INFO0("TC_0207_TP_WRITE_COMMAND_RX_02 Start\r\n"); + break; + + default: + data_uart_print("invlid test case id\r\n"); + return; + } + +} + +bool ble_throughput_app_set_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool ret = true; + if (p_parse_value->param_count == 1) + { + memcpy(g_cur_rembd, &tc_rembd_list[p_parse_value->dw_param[0]], 6); + } + else if (p_parse_value->param_count == 6) + { + g_cur_rembd[0] = p_parse_value->dw_param[5]; + g_cur_rembd[1] = p_parse_value->dw_param[4]; + g_cur_rembd[2] = p_parse_value->dw_param[3]; + g_cur_rembd[3] = p_parse_value->dw_param[2]; + g_cur_rembd[4] = p_parse_value->dw_param[1]; + g_cur_rembd[5] = p_parse_value->dw_param[0]; + } + else + { + ret = false; + } + + data_uart_print("g_cur_rembd: 0x%02x:%02x:%02x:%02x:%02x:%02x\r\n", + g_cur_rembd[5], g_cur_rembd[4], + g_cur_rembd[3], g_cur_rembd[2], + g_cur_rembd[1], g_cur_rembd[0]); + return ret; +} + +void ble_throughput_app_select_cur_test_case(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_CUR_TEST_CASE test_case_id; + T_CUR_DEVICE_ROLE role; + + test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + role = ble_throughput_app_get_cur_role(); + + switch (role) + { + case TC_ROLE_UNDEFINED: + data_uart_print("app_handle_test_case: TC_ROLE_UNDEFINED\r\n"); + return; + + case TC_ROLE_DUT: + { + data_uart_print("app_handle_test_case: role TC_ROLE_DUT\r\n"); + ble_throughput_app_display_case_details(test_case_id); + switch (test_case_id) + { + + case TC_0206_TP_NOTIFICATION_TX_02: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t latency = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t mode = p_parse_value->dw_param[4]; + uint32_t count = p_parse_value->dw_param[5]; + uint8_t data_check = 0; + if (p_parse_value->param_count == 7) + { + data_check = p_parse_value->dw_param[6]; + } + ble_throughput_206_tp_notification_tx_init_config(interval, latency, length, mode, count, data_check); + ble_throughput_206_tp_notification_tx_start(); + } + + break; + + case TC_0207_TP_WRITE_COMMAND_RX_02: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t latency = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t mode = p_parse_value->dw_param[4]; + uint32_t count = p_parse_value->dw_param[5]; + uint8_t data_check = 0; + if (p_parse_value->param_count == 7) + { + data_check = p_parse_value->dw_param[6]; + } + ble_throughput_207_tp_rx_init_config(interval, latency, length, mode, count, data_check); + ble_throughput_207_tp_rx_start(); + } + + break; + + default: + return; + } + } + break; + + case TC_ROLE_SUT: + { + data_uart_print("app_handle_test_case: TC_ROLE_SUT\r\n"); + ble_throughput_app_display_case_details(test_case_id); + switch (test_case_id) + { + + case TC_0206_TP_NOTIFICATION_TX_02: + { + uint8_t peer_addr[6] = {0}; + + memcpy(peer_addr, g_cur_rembd, 6); + + ble_throughput_206_sut_start(peer_addr); + } + break; + + case TC_0207_TP_WRITE_COMMAND_RX_02: + { + uint8_t peer_addr[6] = {0}; + + memcpy(peer_addr, g_cur_rembd, 6); + + ble_throughput_207_sut_start(peer_addr); + } + break; + + default: + return; + } + } + break; + } + + + g_cur_test_case = test_case_id; +} + +extern T_TP_TEST_PARAM g_206_tp_test_param; +extern T_TP_TEST_PARAM g_207_tp_test_param; + +void ble_throughput_app_get_result(void) +{ + if(ble_throughput_app_get_cur_role() == TC_ROLE_DUT) + { + if(ble_throughput_app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + int tx_count = g_206_tp_test_param.count - g_206_tp_test_param.count_remain; + g_206_tp_test_param.end_time = os_sys_time_get(); + g_206_tp_test_param.elapsed_time = ble_throughput_os_time_get_elapsed(g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time); + g_206_tp_test_param.data_rate = tx_count * g_206_tp_test_param.length * 1000 / + (g_206_tp_test_param.elapsed_time); + } else if(ble_throughput_app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02){ + g_207_tp_test_param.end_time = os_sys_time_get(); + g_207_tp_test_param.elapsed_time = ble_throughput_os_time_get_elapsed(g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time); + g_207_tp_test_param.data_rate = g_207_tp_test_param.count * g_207_tp_test_param.length * 1000 / + (g_207_tp_test_param.elapsed_time); + } + le_disconnect(0); + } + else { + printf("ATBT=RESULT only used by DUT!!\n\r"); + } +} + +int ble_throughput_at_cmd(int argc, char **argv) +{ + int ret = 0; + int i = 0; + int role = 0; + T_USER_CMD_PARSED_VALUE parsed_value; + T_USER_CMD_PARSED_VALUE *p_parsed_value = &parsed_value; + p_parsed_value->param_count = argc-2; + + for (unsigned int j = 0 ; j < USER_CMD_MAX_PARAMETERS; j++) + { + p_parsed_value->p_param[j] = NULL; + p_parsed_value->dw_param[j] = 0; + } + + if(strcmp(argv[1],"ROLE") == 0) { + + if(argc != 3){ + printf("ERROR:input parameter error!\n\r"); + return -1; + } + if(strcmp(argv[2],"1")&&strcmp(argv[2],"2")){ + printf("ERROR:input parameter error!\n\r"); + return -1; + } + + role = str_to_uint32(argv[2]); + ble_throughput_app_set_cur_role(role); + }else if(strcmp(argv[1], "REMBD") == 0){ + if(argc !=8){ + printf("ERROR:input parameter error!\n\r"); + return -1; + } + do + { + p_parsed_value->dw_param[i] = str_to_uint32(argv[2+i]); + i++; + }while(i<6); + ret = ble_throughput_app_set_rembd(p_parsed_value); + if(ret == false) + return -1; + }else if(strcmp(argv[1], "TEST") == 0){ + if((argc != 9)&&(argc != 3)){ + printf("ERROR:input parameter error!\n\r"); + return -1; + } + do + { + p_parsed_value->dw_param[i] = str_to_uint32(argv[2+i]); + i++; + }while(i +#include "user_cmd_parse.h" + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include +#endif + +#if F_BT_LE_GAP_CENTRAL_SUPPORT +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t TGATTDBdAddr[6]; +extern TGATTDBdAddr g_cur_rembd; + + +typedef enum +{ + TC_IDLE = 0x0000, + + TC_0206_TP_NOTIFICATION_TX_02 = 206, + TC_0207_TP_WRITE_COMMAND_RX_02, + + TC_MAX = 65535 +} T_CUR_TEST_CASE; + + +typedef enum _T_CUR_DEVICE_ROLE +{ + TC_ROLE_UNDEFINED, + TC_ROLE_DUT, + TC_ROLE_SUT +} T_CUR_DEVICE_ROLE; + +T_CUR_DEVICE_ROLE ble_throughput_app_get_cur_role(void); +void ble_throughput_app_set_cur_role(T_CUR_DEVICE_ROLE role); + +T_CUR_TEST_CASE ble_throughput_app_get_cur_test_case(void); +void ble_throughput_app_select_cur_test_case(T_USER_CMD_PARSED_VALUE *p_parse_value); +bool ble_throughput_app_set_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value); + + +/** + common api +*/ +uint32_t ble_throughput_os_time_get_elapsed(uint32_t begin, uint32_t end); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_user_cmd.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_user_cmd.c new file mode 100644 index 00000000..8771eb7a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_user_cmd.c @@ -0,0 +1,117 @@ +/** +************************************************************************************************************ +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +************************************************************************************************************ +* @file user_cmd.c +* @brief User defined profile test commands. +* @details User command interfaces. +* @author +* @date 2016-02-18 +* @version v0.1 +************************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST + +#include +#include "trace_app.h" +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#include "ble_throughput_vendor_tp_client.h" +#include +#endif +#include "gap_bond_le.h" +#include "gap_scan.h" +#include "ble_throughput_user_cmd.h" +#include "gap.h" +#include "ble_throughput_link_mgr.h" + +#include "ble_throughput_app.h" +#include "gap_adv.h" +#include "gap_le.h" +#include "gap_conn_le.h" +#include "ble_throughput_test_case.h" +#include "gap_storage_le.h" +#include "user_cmd_parse.h" + + +T_USER_CMD_IF user_cmd_if; +extern uint8_t gSimpleProfileServiceId; + + +/** + * @brief print project related string. + * + * @param none. + * @return print project related string. +*/ + +static T_USER_CMD_PARSE_RESULT UserCmdSelectTestCase(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + ble_throughput_app_select_cur_test_case(p_parse_value); + return (RESULT_SUCESS); +} + + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_USER_CMD_PARSE_RESULT result = RESULT_SUCESS; + bool ret; + + ret = ble_throughput_app_set_rembd(p_parse_value); + if (ret == false) + { + result = RESULT_ERR; + } + return result; +} + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_role(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + + T_CUR_DEVICE_ROLE role; + role = (T_CUR_DEVICE_ROLE)p_parse_value->dw_param[0]; + ble_throughput_app_set_cur_role(role); + return (RESULT_SUCESS); +} + + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const T_USER_CMD_TABLE_ENTRY user_cmd_table[] = +{ + /********************************Common*********************************/ + + + { + "tc", + "testcase [index]\n\r", + "testcase\n\r", + UserCmdSelectTestCase + }, + { + "tcrole", + "tcrole [role]\n\r", + "tcrole\n\r", + user_cmd_tc_role + }, + { + "rembd", + "rembd [index]\n\r", + "rembd\n\r", + user_cmd_tc_rembd + }, + + /********************************Peripheral*********************************/ + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; +#endif + + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_user_cmd.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_user_cmd.h new file mode 100644 index 00000000..c8239cab --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_user_cmd.h @@ -0,0 +1,31 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file user_cmd.h +* @brief Define user command. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _USER_CMD_H_ +#define _USER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "data_uart.h" +#include "user_cmd_parse.h" + +extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[]; +extern T_USER_CMD_IF user_cmd_if; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_client.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_client.c new file mode 100644 index 00000000..fb2f3aae --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_client.c @@ -0,0 +1,295 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_client.c + * @brief + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include "trace_app.h" +#include +#include "ble_throughput_vendor_tp_client.h" +#include "ble_throughput_vendor_tp_config.h" + +#if F_BT_LE_GATT_CLIENT_SUPPORT +typedef struct +{ + bool is_find_tp_char; + T_GATT_CHARACT_ELEM16 tp_char; + uint16_t cccd_handle; +} T_TP_LINK; + +/** @brief App link table */ +T_TP_LINK tp_table[4]; +static T_CLIENT_ID tp_client_id = CLIENT_PROFILE_GENERAL_ID; + +static P_FUN_GENERAL_APP_CB tp_client_cb = NULL; + +bool tp_client_start_discovery(uint8_t conn_id) +{ + return client_by_uuid_char_discovery(conn_id, tp_client_id, 1, 0xffff, + GATT_UUID_VENDOR_TP_NOTIFY_INDICATE); +} + +bool tp_client_write_cccd(uint8_t conn_id, uint16_t cccd_bits) +{ + uint16_t handle; + uint16_t length; + uint8_t *p_data; + bool hdl_valid = false; + + APP_PRINT_INFO1("tp_client_write_cccd: cccd_bits = 0x%x", cccd_bits); + + if (tp_table[conn_id].cccd_handle) + { + handle = tp_table[conn_id].cccd_handle; + length = sizeof(uint16_t); + p_data = (uint8_t *)&cccd_bits; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, tp_client_id, GATT_WRITE_TYPE_REQ, handle, + length, p_data) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("tp_client_write_cccd: Request fail! Please check!"); + return false; +} + +bool tp_client_write_value(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + uint16_t handle; + bool hdl_valid = false; + + if (tp_table[conn_id].tp_char.value_handle) + { + handle = tp_table[conn_id].tp_char.value_handle; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, tp_client_id, GATT_WRITE_TYPE_REQ, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("tp_client_write_value: Request fail! Please check!"); + return false; +} + +bool tp_client_write_command(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + uint16_t handle; + bool hdl_valid = false; + + if (tp_table[conn_id].tp_char.value_handle) + { + handle = tp_table[conn_id].tp_char.value_handle; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, tp_client_id, GATT_WRITE_TYPE_CMD, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("tp_client_write_command: Request fail! Please check!"); + return false; +} + +bool tp_client_read_prefer_param(uint8_t conn_id) +{ + if (client_attr_read_using_uuid(conn_id, tp_client_id, 0x01, 0xffff, + GATT_UUID_VENDOR_TP_PREFER_PARAM, NULL) == GAP_CAUSE_SUCCESS) + { + return true; + } + + APP_PRINT_WARN0("tp_client_read_prefer_param: Request fail! Please check!"); + return false; +} + +static void tp_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + T_TP_CB_DATA cb_data; + cb_data.cb_type = TP_CLIENT_CB_TYPE_DISC_RESULT; + cb_data.cb_content.disc_result.is_found = false; + + APP_PRINT_INFO1("tp_client_discover_state_cb: discovery_state = %d", discovery_state); + if (discovery_state == DISC_STATE_CHAR_UUID16_DONE) + { + if (tp_table[conn_id].is_find_tp_char) + { + cb_data.cb_content.disc_result.is_found = true; + memcpy(&cb_data.cb_content.disc_result.char_tp, &tp_table[conn_id].tp_char, + sizeof(T_GATT_CHARACT_ELEM16)); + } + } + else if (discovery_state == DISC_STATE_FAILED) + { + } + + /* Send discover state to application if needed. */ + if (tp_client_cb) + { + (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + return; +} + +static void tp_client_discover_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + //data_uart_print("tp_client_discover_result_cb: result_type = %d", result_type); + APP_PRINT_INFO1("tp_client_discover_result_cb: result_type = %d", result_type); + if (result_type == DISC_RESULT_BY_UUID16_CHAR) + { + tp_table[conn_id].tp_char.decl_handle = result_data.p_char_uuid16_disc_data->decl_handle; + tp_table[conn_id].tp_char.properties = result_data.p_char_uuid16_disc_data->properties; + tp_table[conn_id].tp_char.value_handle = result_data.p_char_uuid16_disc_data->value_handle; + tp_table[conn_id].tp_char.uuid16 = result_data.p_char_uuid16_disc_data->uuid16; + tp_table[conn_id].is_find_tp_char = true; + tp_table[conn_id].cccd_handle = tp_table[conn_id].tp_char.value_handle + 1; + } + + return; +} + +static void tp_client_write_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_TP_CB_DATA cb_data; + cb_data.cb_type = TP_CLIENT_CB_TYPE_WRITE_RESULT; + cb_data.cb_content.write_result.credits = credits; + cb_data.cb_content.write_result.write_type = type; + + APP_PRINT_INFO1("tp_client_write_cb: result = 0x%x", cause); + + /* If write req success, branch to fetch value and send to application. */ + if (handle == tp_table[conn_id].tp_char.value_handle) + { + cb_data.cb_content.write_result.type = TP_WRITE_CHAR_VALUE; + cb_data.cb_content.write_result.cause = cause; + } + else if (handle == tp_table[conn_id].cccd_handle) + { + cb_data.cb_content.write_result.type = TP_WRITE_CCCD; + cb_data.cb_content.write_result.cause = cause; + } + + /* Inform application the write result. */ + if (tp_client_cb) + { + (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + + return; +} + +static T_APP_RESULT tp_client_notify_ind_cb(uint8_t conn_id, bool notify, uint16_t handle, + uint16_t value_size, uint8_t *pValue) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + T_TP_CB_DATA cb_data; + + cb_data.cb_type = TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + + if (handle == tp_table[conn_id].tp_char.value_handle) + { + cb_data.cb_content.notif_ind_data.is_notif = notify; + cb_data.cb_content.notif_ind_data.value_size = value_size; + cb_data.cb_content.notif_ind_data.pValue = pValue; + } + else + { + return app_result; + } + /* Inform application the notif/ind result. */ + if (tp_client_cb) + { + app_result = (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + + return app_result; +} + +static void tp_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_TP_CB_DATA cb_data; + cb_data.cb_type = TP_CLIENT_CB_TYPE_READ_RESULT; + + PROFILE_PRINT_INFO2("tp_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + cb_data.cb_content.read_result.type = TP_READ_PREFER_PARAM; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.value_size = value_size; + cb_data.cb_content.read_result.p_value = p_value; + } + + if (tp_client_cb) + { + (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + return; +} + +static void tp_client_disc_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("tp_client_disc_cb."); + memset(&tp_table[conn_id], 0, sizeof(T_TP_LINK)); + return; +} + +const T_FUN_CLIENT_CBS TP_CLIENT_CBS = +{ + tp_client_discover_state_cb, //!< Discovery State callback function pointer + tp_client_discover_result_cb, //!< Discovery result callback function pointer + tp_client_read_result_cb, //!< Read response callback function pointer + tp_client_write_cb, //!< Write result callback function pointer + tp_client_notify_ind_cb, //!< Notify Indicate callback function pointer + tp_client_disc_cb //!< Link disconnection callback function pointer +}; + + +T_CLIENT_ID tp_client_add(P_FUN_GENERAL_APP_CB app_cb) +{ + T_CLIENT_ID client_id; + if (false == client_register_spec_client_cb(&client_id, &TP_CLIENT_CBS)) + { + tp_client_id = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("tp_client_add_client Fail !!!"); + return tp_client_id; + } + tp_client_id = client_id; + APP_PRINT_INFO1("tp_client_add_client: client ID = %d", tp_client_id); + + /* register callback for profile to inform application that some events happened. */ + tp_client_cb = app_cb; + + return client_id; +} +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_client.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_client.h new file mode 100644 index 00000000..eefa0116 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_client.h @@ -0,0 +1,99 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_client.h + * @brief + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _VD_TP_CLIENT_H_ +#define _VD_TP_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_client.h" + +typedef enum +{ + TP_CLIENT_CB_TYPE_DISC_RESULT, //!< Discovery procedure state, done or pending. + TP_CLIENT_CB_TYPE_WRITE_RESULT, //!< Read request's result data, responsed from server. + TP_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT, + TP_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_TP_CB_TYPE; + +typedef enum +{ + TP_WRITE_CCCD, + TP_WRITE_CHAR_VALUE, +} T_TP_WRITE_TYPE; + +typedef struct +{ + bool is_found; + T_GATT_CHARACT_ELEM16 char_tp; +} T_TP_DISC_RESULT; + +typedef struct +{ + uint8_t is_notif; + uint16_t value_size; + uint8_t *pValue; +} T_TP_NOTIF_IND_DATA; + +typedef struct +{ + T_TP_WRITE_TYPE type; + T_GATT_WRITE_TYPE write_type; + uint16_t cause; + uint8_t credits; +} T_TP_WRITE_RESULT; + +typedef enum +{ + TP_READ_PREFER_PARAM, +} T_TP_READ_TYPE; + +typedef struct +{ + T_TP_READ_TYPE type; + uint16_t cause; + uint16_t value_size; + uint8_t *p_value; +} T_TP_READ_RESULT; + +typedef union +{ + T_TP_DISC_RESULT disc_result; + T_TP_NOTIF_IND_DATA notif_ind_data; + T_TP_WRITE_RESULT write_result; + T_TP_READ_RESULT read_result; +} T_TP_DATA; + +typedef struct +{ + T_TP_CB_TYPE cb_type; + T_TP_DATA cb_content; +} T_TP_CB_DATA; + +T_CLIENT_ID tp_client_add(P_FUN_GENERAL_APP_CB app_cb); +bool tp_client_start_discovery(uint8_t conn_id); +bool tp_client_write_cccd(uint8_t conn_id, uint16_t cccd_bits); +bool tp_client_write_value(uint8_t conn_id, uint16_t length, uint8_t *p_value); +bool tp_client_write_command(uint8_t conn_id, uint16_t length, uint8_t *p_value); +bool tp_client_read_prefer_param(uint8_t conn_id); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _VD_TP_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_config.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_config.h new file mode 100644 index 00000000..84b06224 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_config.h @@ -0,0 +1,53 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file simple_ble_config.h + * @brief This file includes common constants or types for Simple BLE service/client. + * And some optional feature may be defined in this file. + * @details + * @author Ethan + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion **/ +#ifndef _VENDOR_TP_CONFIG_H_ +#define _VENDOR_TP_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t data_check; + uint8_t initial_value; + uint8_t mode; + /** 0 : 1M + w/o data length extension + 1 : 1M + w data length extension + 2 : 2M + w/o data length extension + 3 : 2M + w data length extension + 4 : Coded(s=2) + w/o data length extension + 5 : Coded(s=2) + w data length extension + 6 : Coded(s=8) + w/o data length extension + 7 : Coded(s=8) + w data length extension + 8 : 1M + w/o data length extension(BT4.0) + */ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + uint16_t length; + uint32_t count; +} TTP_PERFER_PARAM; + +#define GATT_UUID_VENDOR_TP_SERVICE 0xA00D +#define GATT_UUID_VENDOR_TP_NOTIFY_INDICATE 0xB001 +#define GATT_UUID_VENDOR_TP_PREFER_PARAM 0xB002 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_service.c b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_service.c new file mode 100644 index 00000000..3e128f4e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_service.c @@ -0,0 +1,348 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file vendor_tp_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_THROUGHPUT_TEST) && CONFIG_BT_THROUGHPUT_TEST +#include "trace_app.h" +#include +#include "ble_throughput_vendor_tp_service.h" +#include "gap.h" + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +T_SERVER_ID vendor_tp_service_id; + + +/**< Function pointer used to send event to application from simple profile. Initiated in vendor_tp_service_add. */ +static P_FUN_SERVER_GENERAL_CB pfn_vendor_tp_service_cb = NULL; +TTP_PERFER_PARAM vendor_tp_param; + + +/**< @brief profile/service definition. */ +const T_ATTRIB_APPL vendor_tp_service_tbl[] = +{ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_VENDOR_TP_SERVICE), /* service UUID */ + HI_WORD(GATT_UUID_VENDOR_TP_SERVICE) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_NOTIFY | GATT_CHAR_PROP_INDICATE | GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_VENDOR_TP_NOTIFY_INDICATE), + HI_WORD(GATT_UUID_VENDOR_TP_NOTIFY_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /* characteristic properties */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VOID, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_VENDOR_TP_PREFER_PARAM), + HI_WORD(GATT_UUID_VENDOR_TP_PREFER_PARAM) + }, + sizeof(vendor_tp_param), /* bValueLen */ + (void *) &vendor_tp_param, + GATT_PERM_READ /* permissions */ + }, +}; + +void vendor_tp_service_config_param(TTP_PERFER_PARAM param) +{ + memcpy(&vendor_tp_param, ¶m, sizeof(TTP_PERFER_PARAM)); +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param iAttribIndex Attribute index of getting characteristic data. + * @param iOffset Used for Blob Read. + * @param piLength length of getting characteristic data. + * @param ppValue data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT vendor_tp_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t iAttribIndex, uint16_t iOffset, uint16_t *piLength, uint8_t **ppValue) +{ + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + + switch (iAttribIndex) + { + default: + APP_PRINT_ERROR1("vendor_tp_service_attr_read_cb, Attr not found, index=%d", iAttribIndex); + wCause = APP_RESULT_ATTR_NOT_FOUND; + break; + + + } + + return (wCause); +} + + +/** + * @brief write characteristic data from service. + * + * @param ServiceID ServiceID to be written. + * @param iAttribIndex Attribute index of characteristic. + * @param wLength length of value to be written. + * @param pValue value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT vendor_tp_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t iAttribIndex, T_WRITE_TYPE write_type, uint16_t wLength, uint8_t *pValue, + P_FUN_WRITE_IND_POST_PROC *pWriteIndPostProc) +{ + TTP_CALLBACK_DATA callback_data; + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + if (VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX == iAttribIndex) + { + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.write_type = write_type; + if (write_type == WRITE_REQUEST) + { + /* Notify Application. */ + uint8_t *p_param = pValue; + callback_data.msg_data.write.opcode = (VENDOR_TP_OP) * p_param; + p_param += 1; + + LE_ARRAY_TO_UINT32(callback_data.msg_data.write.u.notify_param.count, p_param); + p_param += 4; + + LE_ARRAY_TO_UINT16(callback_data.msg_data.write.u.notify_param.length, p_param); + + if (pfn_vendor_tp_service_cb) + { + pfn_vendor_tp_service_cb(service_id, (void *)&callback_data); + } + } + else + { + callback_data.msg_data.write.u.write_data.length = wLength; + callback_data.msg_data.write.u.write_data.p_value = pValue; + if (pfn_vendor_tp_service_cb) + { + pfn_vendor_tp_service_cb(service_id, (void *)&callback_data); + } + } + } + else + { + APP_PRINT_ERROR2("--> vendor_tp_service_attr_write_cb Error iAttribIndex = 0x%x wLength=%d", + iAttribIndex, + wLength); + wCause = APP_RESULT_ATTR_NOT_FOUND; + } + return wCause; +} + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] service_id service ID of service. + * @param[in] value characteristic value to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +//uint8_t counter = 0; + +bool vendor_tp_service_v1_notification(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + uint8_t *p_data = (uint8_t *)p_value; + uint16_t dataLen = length; + + APP_PRINT_INFO0("<-- vendor_tp_service_v1_notification"); + // send notification to client + return server_send_data(conn_id, service_id, VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX, p_data, + dataLen, GATT_PDU_TYPE_NOTIFICATION); +} + +bool vendor_tp_service_v1_indication(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + uint8_t *p_data = (uint8_t *)p_value; + uint16_t dataLen = length; + + APP_PRINT_INFO0("<-- vendor_tp_service_v1_indication"); + //data_uart_print("<-- vendor_tp_service_v1_indication"); + // send notification to client + return server_send_data(conn_id, service_id, VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX, p_data, + dataLen, GATT_PDU_TYPE_INDICATION); +} + +/** + * @brief update CCCD bits from stack. + * + * @param service_id Service ID. + * @param Index Attribute index of characteristic data. + * @param wCCCBits CCCD bits from stack. + * @return None +*/ +void vendor_tp_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID serviceId, uint16_t Index, + uint16_t wCCCBits) +{ + TTP_CALLBACK_DATA callback_data; + + callback_data.conn_id = conn_id; + APP_PRINT_INFO2("vendor_tp_service_cccd_update_cb Index = %d wCCCDBits %x", Index, + wCCCBits); + switch (Index) + { + case VENDOR_TP_SERVICE_CHAR_TP_NOTIFY_INDICATE_CCCD_INDEX: + { + bool bHandle = true; + if (wCCCBits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + else + { + // Disable Notification + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + + if (wCCCBits & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_INDICATION_ENABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + else + { + // Disable Indication + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_INDICATION_DISABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + + } + break; + + default: + break; + } +} + + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS vendor_tp_service_cbs = +{ + vendor_tp_service_attr_read_cb, // Read callback function pointer + vendor_tp_service_attr_write_cb, // Write callback function pointer + vendor_tp_service_cccd_update_cb // CCCD update callback function pointer +}; + + + +/** + * @brief add Simple BLE service to application. + * + * @param[in] pFunc pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + * @retval service_id + */ +T_SERVER_ID vendor_tp_service_add(void *pFunc) +{ + if (false == server_add_service(&vendor_tp_service_id, + (uint8_t *)vendor_tp_service_tbl, + sizeof(vendor_tp_service_tbl), + vendor_tp_service_cbs)) + { + APP_PRINT_ERROR1("vendor_tp_service_add: service_id %d", vendor_tp_service_id); + vendor_tp_service_id = 0xff; + return vendor_tp_service_id; + } + + pfn_vendor_tp_service_cb = (P_FUN_SERVER_GENERAL_CB)pFunc; + return vendor_tp_service_id; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_service.h b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_service.h new file mode 100644 index 00000000..0c5d74a0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/ble_throughput_test/ble_throughput_vendor_tp_service.h @@ -0,0 +1,174 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author ethan + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _VENDOR_TP_SERVICE_H_ +#define _VENDOR_TP_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_server.h" +#include "ble_throughput_vendor_tp_config.h" + +/** @addtogroup SIMP SIMP + * @brief Simple BLE Profile + * @{ + */ + +/** @defgroup SIMP_Service SIMP Service + * @brief Simple BLE Service + * @{ + */ + +/** @defgroup SIMP_Service_Exported_Constants SIMP Service Exported Constants + * @brief macros that other .c files may use all defined here + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +#define SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL 0x01 +#define SIMPLE_BLE_SERVICE_PARAM_CTL_PNT_PROG_CLR 0x02 +/** @} */ + +///@cond +/** @brief Index of each characteristic in Demo Profile service database. */ +#define VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX 0x02 +#define VENDOR_TP_SERVICE_CHAR_TP_NOTIFY_INDICATE_CCCD_INDEX (VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX + 1) +///@endcond + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ + +#define SIMP_WRITE_V1 1 + + +/** @} */ + +/** @defgroup SIMP_Service_Notify_Indicate_Info SIMP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE 1 +#define VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE 2 +#define VENDOR_TP_SERVICE_V1_INDICATION_ENABLE 3 +#define VENDOR_TP_SERVICE_V1_INDICATION_DISABLE 4 + + + +/** @} */ + +/** @} End of SIMP_Service_Upstream_Message */ + + + +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief types that other.c files may use all defined here + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ + +typedef enum +{ + VENDOR_TP_OP_CONFIG_NOTIFY_PARAM1 = 0x01, + VENDOR_TP_OP_CONFIG_NOTIFY_PARAM2 = 0x02, + VENDOR_TP_OP_NOTIFY_START_TEST = 0x03, + +} VENDOR_TP_OP; + +typedef struct _TVENDOR_TP_CONFIG_NOTIFY_PARAM +{ + uint32_t count; + uint16_t length; +} TVENDOR_TP_CONFIG_NOTIFY_PARAM; + +typedef struct +{ + uint16_t length; + uint8_t *p_value; +} TVENDOR_TP_WRITE_DATA; + +typedef struct _TTP_WRITE_MSG +{ + T_WRITE_TYPE write_type; + VENDOR_TP_OP opcode; //!< ref: @ref SIMP_Control_Point_OpCodes, @ref SIMP_Service_Write_Info + union + { + TVENDOR_TP_CONFIG_NOTIFY_PARAM notify_param; + TVENDOR_TP_WRITE_DATA write_data; + uint8_t mode; + } u; +} TTP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union _TTP_UPSTREAM_MSG_DATA +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + TTP_WRITE_MSG write; +} TTP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct _TTP_CALLBACK_DATA +{ + T_SERVICE_CALLBACK_TYPE msg_type; + uint8_t conn_id; + TTP_UPSTREAM_MSG_DATA msg_data; +} TTP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ + +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief functions that other .c files may use all defined here + * @{ + */ +T_SERVER_ID vendor_tp_service_add(void *pFunc); +void vendor_tp_service_config_param(TTP_PERFER_PARAM param); +bool vendor_tp_service_v1_notification(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length); +bool vendor_tp_service_v1_indication(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length); + + +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +/** @} End of SIMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_flags.h new file mode 100644 index 00000000..5ca1c464 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_flags.h @@ -0,0 +1,32 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_AIRSYNC_CONFIG_APP_FLAGS_H_ +#define _BT_AIRSYNC_CONFIG_APP_FLAGS_H_ + +#include "bt_flags.h" + +/** @defgroup PERIPH_Config Peripheral App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 + +/** @} */ /* End of group PERIPH_Config */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_main.c new file mode 100644 index 00000000..8925618c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_main.c @@ -0,0 +1,300 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_AIRSYNC_CONFIG) && CONFIG_BT_AIRSYNC_CONFIG +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wifi_conf.h" +#include "bt_config_wifi.h" +#include "bt_airsync_config_app_task.h" +#include "bt_airsync_config_app_flags.h" +#include "bt_airsync_config_peripheral_app.h" +#include "airsync_ble_service.h" +#include "lwip_netconf.h" +#include "rtk_coex.h" +#include "platform_stdlib.h" +#include "wechat_airsync_protocol.h" + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 400 + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_GAP_DEV_STATE bt_airsync_config_gap_dev_state; +extern uint8_t airsync_specific; +extern airsync_send_data_handler p_airsync_send_data_handler; + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Core spec. Vol. 3, Part C, Chapter 18 */ + /* Flags */ + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Local name */ + 0x0D, /* length */ + 0x09, /* type="Complete local name" */ + 'A', 'M', 'E', 'B', 'A', '_', 'X', 'X', 'Y', 'Y', 'Z', 'Z', /* SmartBracelet */ + /* Service */ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available, service uuid 0xFEE7 0xA00A" */ + 0xE7, + 0xFE, + /* Manufacture specified data*/ + 0x09, /* length */ + 0xFF, /* type: manufacture specific data*/ + 0xC5, 0xFE, /* company id */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* mac address*/ +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +#ifndef PLATFORM_OHOS +extern void gap_config_hci_task_secure_context(uint32_t size); +void bt_airsync_config_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); + gap_config_hci_task_secure_context (280); +} +#else +extern void gap_config_deinit_flow(uint8_t deinit_flow); +void bt_airsync_config_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); + //gap_config_hci_task_secure_context (280); + gap_config_deinit_flow(1); +} +#endif + +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void bt_airsync_config_app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "AMEBA_XXYYZZ"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_airsync_config_app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void bt_airsync_config_app_le_profile_init(void) +{ + server_init(1); + + bt_airsync_config_srv_id = airsync_add_service((void *)bt_airsync_config_app_profile_callback); + server_register_app_cb(bt_airsync_config_app_profile_callback); +} + +void bt_airsync_config_task_init(void) +{ + bt_airsync_config_app_task_init(); + p_airsync_send_data_handler = bt_airsync_config_send_data_to_apptask; + airsync_specific = 1; + bt_config_wifi_init(); +} + +void bt_airsync_config_task_deinit(void) +{ + bt_config_wifi_deinit(); + p_airsync_send_data_handler = NULL; + bt_airsync_config_app_task_deinit(); +} + +int bt_airsync_config_app_init(void) +{ + int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + //T_GAP_CONN_INFO conn_info; + //(void) conn_info; + + /*Check WIFI init complete*/ + if( ! (wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + BC_printf("WIFI is disabled\n\r"); + return -1; + } + +#if CONFIG_AUTO_RECONNECT + /* disable auto reconnect */ + wifi_set_autoreconnect(0); +#endif + + + wifi_disconnect(); +#if CONFIG_LWIP_LAYER + LwIP_ReleaseIP(WLAN0_IDX); +#endif + + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + bt_stack_already_on = 1; + BC_printf("BT Stack already on\n\r"); + } else { + bt_trace_init(); + bt_airsync_config_stack_config_init(); + bte_init(); + le_gap_init(APP_MAX_LINKS); + bt_airsync_config_app_le_profile_init(); + } + + bt_airsync_config_app_le_gap_init(); + bt_airsync_config_task_init(); + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } while (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + if (bt_stack_already_on) { + bt_airsync_config_app_set_adv_data(); + bt_airsync_config_send_msg(1); //Start ADV + } + + return 0; +} + +extern bool bt_trace_uninit(void); +void bt_airsync_config_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + + bt_airsync_config_task_deinit(); + + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + BC_printf("BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + BC_printf("BT Stack deinitalized\n\r"); + } +#endif +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.c new file mode 100644 index 00000000..0e4bea63 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.c @@ -0,0 +1,201 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_AIRSYNC_CONFIG) && CONFIG_BT_AIRSYNC_CONFIG +#include +#include +#include +#include +#include +#include +#include +#include "platform_stdlib.h" +#include "bt_config_wifi.h" +#include "bt_airsync_config_app_task.h" +#include "bt_airsync_config_app_flags.h" +#include "bt_airsync_config_peripheral_app.h" + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +static void *app_task_handle = NULL; //!< APP Task handle +static void *evt_queue_handle = NULL; //!< Event queue handle +static void *io_queue_handle = NULL; //!< IO queue handle +extern T_GAP_DEV_STATE bt_airsync_config_gap_dev_state; +T_BT_AIRSYNC_CONFIG_TX_DATA bt_airsync_config_tx_data; + +/*============================================================================* + * Functions + *============================================================================*/ + +void bt_airsync_config_send_msg(uint16_t sub_type) +{ + uint8_t event = EVENT_IO_TO_APP; + + T_IO_MSG io_msg; + + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + + if (evt_queue_handle != NULL && io_queue_handle != NULL) { + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) { + BC_printf("bt airsync config send msg fail: subtype 0x%x", io_msg.subtype); + } else if (os_msg_send(evt_queue_handle, &event, 0) == false) { + BC_printf("bt airsync config send event fail: subtype 0x%x", io_msg.subtype); + } + } +} + +void bt_airsync_config_app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void bt_airsync_config_app_task_init(void) +{ + if (app_task_handle == NULL) { + BC_printf("bt_airsync_config_app_task_init\n\r"); + os_task_create(&app_task_handle, "bt_airsync_config_app", bt_airsync_config_app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); + } else { + BC_printf("bt_airsync_config_app_main_task already on\n\r"); + } +} + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_airsync_config_app_task_deinit(void) +{ + //gap_stop_bt_stack + if (app_task_handle) { + os_task_delete(app_task_handle); + } + if (io_queue_handle) { + os_msg_queue_delete(io_queue_handle); + } + if (evt_queue_handle) { + os_msg_queue_delete(evt_queue_handle); + } + io_queue_handle = NULL; + evt_queue_handle = NULL; + app_task_handle = NULL; + + bt_airsync_config_gap_dev_state.gap_init_state = 0; + bt_airsync_config_gap_dev_state.gap_adv_sub_state = 0; + bt_airsync_config_gap_dev_state.gap_adv_state = 0; + bt_airsync_config_gap_dev_state.gap_scan_state = 0; + bt_airsync_config_gap_dev_state.gap_conn_state = 0; +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_airsync_config_app_main_task(void *p_param) +{ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + bt_airsync_config_app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +bool bt_airsync_config_app_send_msg_to_apptask(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(io_queue_handle, p_msg, 0) == false) + { + return false; + } + if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + return false; + } + return true; +} + +void bt_airsync_config_send_data_to_apptask(uint8_t *buf, uint16_t length) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + + memset(&bt_airsync_config_tx_data, 0, sizeof(bt_airsync_config_tx_data)); + bt_airsync_config_tx_data.buf = buf; + bt_airsync_config_tx_data.length = length; + + io_msg.type = IO_MSG_TYPE_WRISTBNAD; + io_msg.subtype = IO_MSG_WAS_TX_VALUE; + io_msg.u.buf = &bt_airsync_config_tx_data; + + if (evt_queue_handle != NULL && io_queue_handle != NULL) { + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) { + BC_printf("bt_airsync_config_send_data_to_apptask send msg fail: subtype 0x%x", io_msg.subtype); + } else if (os_msg_send(evt_queue_handle, &event, 0) == false) { + BC_printf("bt_airsync_config_send_data_to_apptask send event fail: subtype 0x%x", io_msg.subtype); + } + } +} +/** @} */ /* End of group PERIPH_APP_TASK */ +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.h new file mode 100644 index 00000000..3ceba4e6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.h @@ -0,0 +1,41 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_AIRSYNC_CONFIG_APP_TASK_H_ +#define _BT_AIRSYNC_CONFIG_APP_TASK_H_ + +typedef struct +{ + uint8_t *buf; + uint16_t length; +} T_BT_AIRSYNC_CONFIG_TX_DATA; + +void bt_airsync_config_send_msg(uint16_t sub_type); + +/** + * @brief Initialize App task + * @return void + */ +void bt_airsync_config_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_airsync_config_app_task_deinit(void); + +void bt_airsync_config_send_data_to_apptask(uint8_t *buf, uint16_t length); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.c b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.c new file mode 100644 index 00000000..4f6d011d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.c @@ -0,0 +1,615 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_AIRSYNC_CONFIG) && CONFIG_BT_AIRSYNC_CONFIG +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bt_airsync_config_app_flags.h" +#include "bt_airsync_config_peripheral_app.h" +#include "wechat_airsync_protocol.h" +#include "airsync_ble_service.h" +#include "bt_airsync_config_app_task.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +T_SERVER_ID bt_airsync_config_srv_id; /**< Wechat airsync service id*/ + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE bt_airsync_config_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE bt_airsync_config_gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +uint8_t bt_airsync_config_conn_id = 0; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static uint8_t adv_data[] = +{ + /* Core spec. Vol. 3, Part C, Chapter 18 */ + /* Flags */ + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Local name */ + 0x0D, /* length */ + 0x09, /* type="Complete local name" */ + 'A', 'M', 'E', 'B', 'A', '_', 'X', 'X', 'Y', 'Y', 'Z', 'Z', /* SmartBracelet */ + /* Service */ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available, service uuid 0xFEE7 0xA00A" */ + 0xE7, + 0xFE, + /* Manufacture specified data*/ + 0x09, /* length */ + 0xFF, /* type: manufacture specific data*/ + 0xC5, 0xFE, /* company id */ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* mac address*/ +}; + +/*============================================================================* + * Functions + *============================================================================*/ +extern bool bt_airsync_config_app_send_msg_to_apptask(T_IO_MSG *p_msg); +extern void airsync_tx_complete(void); + +void bt_airsync_config_app_set_adv_data(void) +{ + uint8_t bt_addr[GAP_BD_ADDR_LEN]; + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "AMEBA_XXYYZZ"; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + + sprintf((char *)device_name, "AMEBA_%02X%02X%02X", bt_addr[2], bt_addr[1], bt_addr[0]); + memcpy(adv_data + 5, device_name, strlen((char const*)device_name)); + for(int i = 0; i < GAP_BD_ADDR_LEN; i ++) { + memcpy(adv_data + 25 + i, bt_addr + 5 - i, 1); + } + + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); +} + +void airsync_handle_io_message(T_IO_MSG *p_wristband_msg) +{ + uint8_t msg_type = p_wristband_msg->subtype; + switch (msg_type) + { + + case IO_MSG_WAS_RX_VALUE: + { + uint8_t length = ((uint8_t *)(p_wristband_msg->u.buf))[0]; + uint8_t *p_data = (uint8_t *)p_wristband_msg->u.buf + 1; + airsync_receive_data(p_data, length); + } + break; + case IO_MSG_WAS_ENABLE_CCCD: + { + airsync_send_data_event(AIRSYNC_AUTH_EVENT); + } + break; + case IO_MSG_WAS_TX_VALUE: + { + T_BT_AIRSYNC_CONFIG_TX_DATA *tx_data = p_wristband_msg->u.buf; + airsync_send_data(tx_data->buf, tx_data->length); + } + break; + default: + break; + } +} + +void bt_airsync_config_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_airsync_config_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_airsync_config_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_WRISTBNAD: + { + airsync_handle_io_message(&io_msg); + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 1) { + le_adv_start(); + } else if (io_msg.subtype == 0) { + le_adv_stop(); + } + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_airsync_config_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (bt_airsync_config_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ + bt_airsync_config_app_set_adv_data(); + le_adv_start(); + } + } + + if (bt_airsync_config_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + bt_airsync_config_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_airsync_config_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, bt_airsync_config_gap_conn_state, new_state, disc_cause); + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + bt_airsync_config_conn_id = 0; + bt_airsync_config_app_set_adv_data(); + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, (void *)&remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + bt_airsync_config_conn_id = conn_id; + } + break; + + default: + break; + } + bt_airsync_config_gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_airsync_config_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_airsync_config_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_airsync_config_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("app_handle_conn_param_update_evt update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("app_handle_conn_param_update_evt update pending."); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_airsync_config_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + bt_airsync_config_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_airsync_config_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_airsync_config_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_airsync_config_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_airsync_config_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_airsync_config_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ + +/** @defgroup PERIPH_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_airsync_config_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + airsync_tx_complete(); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == bt_airsync_config_srv_id) + { + T_WAS_CALLBACK_DATA *pWasCallback_data = (T_WAS_CALLBACK_DATA *)p_data; + switch (pWasCallback_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch ((pWasCallback_data->msg_data).write.opcode) + { + case GATT_UUID_AIRSYNC_CHAR_WRITE_INDEX: + { + APP_PRINT_INFO0("do nothing SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE... "); + } + break; + default: + break; + } + break; + } + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + if ((pWasCallback_data->msg_data).notification_indification_index == + GATT_UUID_AIRSYNC_CHAR_INDICATION_ENABLE) + { + T_IO_MSG enable_indicate_msg; + enable_indicate_msg.type = IO_MSG_TYPE_WRISTBNAD; + enable_indicate_msg.subtype = IO_MSG_WAS_ENABLE_CCCD; + /* Send MSG to APP task */ + bt_airsync_config_app_send_msg_to_apptask(&enable_indicate_msg); + } + else + { + //do nothing + } + break; + } + default: + break; + } + } + + return app_result; +} + +/** @} */ /* End of group PERIPH_SEVER_CALLBACK */ +/** @} */ /* End of group PERIPH_APP */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.h b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.h new file mode 100644 index 00000000..24940795 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_AIRSYNC_CONFIG_PERIPHERAL_APP__ +#define _BT_AIRSYNC_CONFIG_PERIPHERAL_APP__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_SERVER_ID bt_airsync_config_srv_id; /**< Wechat airsync service id*/ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_airsync_config_app_set_adv_data(void); +void bt_airsync_config_app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id. + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_airsync_config_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_airsync_config_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs_main.c b/component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs_main.c new file mode 100644 index 00000000..31041fa6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs_main.c @@ -0,0 +1,293 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_ANCS) && CONFIG_BT_ANCS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wifi_constants.h" +#include +#include "rtk_coex.h" +#include +#include +#include +#if F_BT_ANCS_CLIENT_SUPPORT +#include +#include +#endif + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x08, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'T', '_', 'A', 'N', 'C', 'S', +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +extern void gap_config_hci_task_secure_context(uint32_t size); +void bt_ancs_bt_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_ANCS_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_ANCS_APP_MAX_LINKS); + gap_config_hci_task_secure_context (280); +} + +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void bt_ancs_app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BT_ANCS"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; +#if F_BT_ANCS_CLIENT_SUPPORT + uint8_t auth_sec_req_enable = true; +#else + uint8_t auth_sec_req_enable = false; +#endif + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_ancs_app_gap_callback); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void bt_ancs_app_le_profile_init(void) +{ + server_init(2); + bt_ancs_simp_srv_id = simp_ble_service_add_service((void *)bt_ancs_app_profile_callback); + bt_ancs_bas_srv_id = bas_add_service((void *)bt_ancs_app_profile_callback); + server_register_app_cb(bt_ancs_app_profile_callback); +#if F_BT_ANCS_CLIENT_SUPPORT + client_init(1); + bt_ancs_init(BT_ANCS_APP_MAX_LINKS); +#endif +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void bt_ancs_task_init(void) +{ + bt_ancs_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_ancs_app_main(void) +{ + bt_trace_init(); + bt_ancs_bt_stack_config_init(); + bte_init(); + le_gap_init(BT_ANCS_APP_MAX_LINKS); + bt_ancs_app_le_gap_init(); + bt_ancs_app_le_profile_init(); + bt_ancs_task_init(); + + return 0; +} + +int bt_ancs_app_init(void) +{ + T_GAP_DEV_STATE new_state; +#if !defined(CONFIG_BT_ONLY_WITHOUT_WLAN) || (CONFIG_BT_ONLY_WITHOUT_WLAN == 0) /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } +#endif + + //judge BLE peripheral is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT ANCS]BT Stack already on\n\r"); + return 0; + } + else + bt_ancs_app_main(); + +#if !defined(CONFIG_BT_ONLY_WITHOUT_WLAN) || (CONFIG_BT_ONLY_WITHOUT_WLAN == 0) + bt_coex_init(); +#endif + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern bool bt_trace_uninit(void); +void bt_ancs_app_deinit(void) +{ + bt_ancs_app_task_deinit(); +#if F_BT_ANCS_CLIENT_SUPPORT + bt_ancs_deinit(); +#endif + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT ANCS]BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { + +#if F_BT_ANCS_CLIENT_SUPPORT + extern void ancs_delete_client(void); + ancs_delete_client(); +#endif + bte_deinit(); + bt_trace_uninit(); + printf("[BT ANCS]BT Stack deinitalized\n\r"); + } +#endif +} + +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.c b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.c new file mode 100644 index 00000000..7153db70 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.c @@ -0,0 +1,171 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_BEACON) && CONFIG_BT_BEACON +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include "bt_beacon_app.h" +#include "vendor_cmd_bt.h" + +/** @defgroup PERIPH_APP Peripheral Application + * @brief This file handles BLE peripheral application routines. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE bt_beacon_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_beacon_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_beacon_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_beacon_app_handle_gap_msg(&io_msg); + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_beacon_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (bt_beacon_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + printf("\n\rGAP stack ready\n\r"); + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ + le_adv_start(); + } + } + + if (bt_beacon_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + APP_PRINT_INFO0("GAP adv stopped"); + printf("\n\rGAP adv stopped\n\r"); + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("\n\rGAP adv start\n\r"); + } + } + + bt_beacon_gap_dev_state = new_state; +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_beacon_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + bt_beacon_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group PERIPH_GAP_MSG */ + +/** @defgroup PERIPH_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_beacon_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + case GAP_MSG_LE_ADV_UPDATE_PARAM: + break; + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group PERIPH_GAP_CALLBACK */ +/** @} */ /* End of group PERIPH_APP */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.h b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.h new file mode 100644 index 00000000..b9303535 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.h @@ -0,0 +1,54 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_BEACON_APP__ +#define _BT_BEACON_APP__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_beacon_app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_beacon_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_main.c new file mode 100644 index 00000000..3fb0852f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_main.c @@ -0,0 +1,306 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_BEACON) && CONFIG_BT_BEACON +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include "bt_beacon_app_task.h" +#include "bt_beacon_app.h" +#include "trace_uart.h" +#include +#include +#include "wifi_constants.h" +#include "wifi_conf.h" +#include "rtk_coex.h" + +/** @defgroup BEACON_MAIN Beacon Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 160 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 240 + +int beacon_type = 0; + +#define I_BEACON 1 +#define ALT_BEACON 2 + + +/*============================================================================* + * Variables + *============================================================================*/ + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t i_beacon_scan_rsp_data[] = +{ + /* Manufacturer Specific */ + 0x1A, /* length */ + GAP_ADTYPE_MANUFACTURER_SPECIFIC, + 0x4C, 0x00, /* Company: Apple */ + 0x02, /* Type: iBeacon */ + 0x15, /* iBeacon data length 0x15 (21) = UUID (16) + major (2) + minor (2) + RSSI (1) */ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, /* UUID (example) */ + 0x00, 0x7B, /* major (example: 123)*/ + 0x01, 0xC8, /* minor (example: 456)*/ + 0xBF, /* rssi: (example: -65 dBm) */ +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t i_beacon_adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Manufacturer Specific */ + 0x1A, /* length */ + GAP_ADTYPE_MANUFACTURER_SPECIFIC, + 0x4C, 0x00, /* Company: Apple */ + 0x02, /* Type: iBeacon */ + 0x15, /* iBeacon data length 0x15 (21) = UUID (16) + major (2) + minor (2) + RSSI (1) */ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, /* 16 byte UUID (example) */ + 0x00, 0x7B, /* major (example: 123)*/ + 0x01, 0xC8, /* minor (example: 456)*/ + 0xBF, /* rssi: (example: -65 dBm) */ +}; + +static const uint8_t alt_beacon_scan_rsp_data[] = +{ + /* Manufacturer Specific */ + 0x1B, /* length */ + GAP_ADTYPE_MANUFACTURER_SPECIFIC, + 0x5D, 0x00, /* Company: (example: Realtek) */ + 0xBE, 0xAC, /* Beacon Code: AltBeacon */ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, /* Beacon ID (example) */ + 0x00, 0x7B, /* Beacon ID major (example: 123)*/ + 0x01, 0xC8, /* Beacon ID minor (example: 456)*/ + 0xBF, /* rssi: (example: -65 dBm) */ + 0xAA, /* MFG RSVD (example: 0xAA)*/ +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t alt_beacon_adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Manufacturer Specific */ + 0x1B, /* length */ + GAP_ADTYPE_MANUFACTURER_SPECIFIC, + 0x5D, 0x00, /* Company: (example: Realtek) */ + 0xBE, 0xAC, /* Beacon Code: AltBeacon */ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, /* Beacon ID (example) */ + 0x00, 0x7B, /* Beacon ID major (example: 123)*/ + 0x01, 0xC8, /* Beacon ID minor (example: 456)*/ + 0xBF, /* rssi: (example: -65 dBm) */ + 0xAA, /* MFG RSVD (example: 0xAA)*/ +}; +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ + #ifndef PLATFORM_OHOS +extern void gap_config_hci_task_secure_context(uint32_t size); +static void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(0); + gap_config_max_le_paired_device(0); + gap_config_hci_task_secure_context (280); +} +#else +extern void gap_config_deinit_flow(uint8_t deinit_flow); +static void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(0); + gap_config_max_le_paired_device(0); + gap_config_deinit_flow(1); +} +#endif + +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +static void app_le_gap_init(void) +{ + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + if (beacon_type == I_BEACON) { + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(i_beacon_adv_data), (void *)i_beacon_adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(i_beacon_scan_rsp_data), (void *)i_beacon_scan_rsp_data); + } else if (beacon_type == ALT_BEACON) { + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(alt_beacon_adv_data), (void *)alt_beacon_adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(alt_beacon_scan_rsp_data), (void *)alt_beacon_scan_rsp_data); + } else { + printf("Error beacon type!\r\n"); + } + /* register gap message callback */ + le_register_app_cb(bt_beacon_app_gap_callback); +} + + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +static void board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_beacon_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +static void pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +static void task_init(void) +{ + bt_beacon_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_beacon_app_main(void) +{ + bt_trace_init(); + bt_stack_config_init(); + bte_init(); + board_init(); + le_gap_init(0); + app_le_gap_init(); + pwr_mgr_init(); + task_init(); + printf("\n\r\n\r[BT Beacon Example] %s\n\r\n\r", (beacon_type == I_BEACON)? "Apple iBeacon": (beacon_type == ALT_BEACON)? "AltBeacon":""); + return 0; +} + +int bt_beacon_app_init(int type) +{ + //int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE Beacon is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BLE Beacon]BT Stack already on\n\r"); + return 0; + } + else { + beacon_type = type; + bt_beacon_app_main(); + } + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern void bt_beacon_app_task_deinit(void); +extern bool bt_trace_uninit(void); +extern T_GAP_DEV_STATE bt_beacon_gap_dev_state; + +void bt_beacon_app_deinit(void) +{ + bt_beacon_app_task_deinit(); + + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + memset(&bt_beacon_gap_dev_state, 0, sizeof(T_GAP_DEV_STATE)); + printf("BT Stack deinitalized\n\r"); + } +#endif +} + +/** @} */ /* End of group BEACON_MAIN */ +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.c new file mode 100644 index 00000000..0f9649ff --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.c @@ -0,0 +1,137 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_BEACON) && CONFIG_BT_BEACON +#include +#include +#include +#include +#include +#include "bt_beacon_app_task.h" +#include +#include "bt_beacon_app.h" +#include "platform_stdlib.h" +#include + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +static void *app_task_handle; //!< APP Task handle +static void *evt_queue_handle; //!< Event queue handle +static void *io_queue_handle; //!< IO queue handle + +extern T_GAP_DEV_STATE bt_beacon_gap_dev_state; + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_beacon_app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void bt_beacon_app_task_init() +{ + os_task_create(&app_task_handle, "bt_beacon_app", bt_beacon_app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_beacon_app_main_task(void *p_param) +{ + (void )p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 100); +#endif + + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + bt_beacon_driver_init(); + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + bt_beacon_app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +void bt_beacon_app_task_deinit(void) +{ + //gap_stop_bt_stack + if (app_task_handle) { + os_task_delete(app_task_handle); + } + if (io_queue_handle) { + os_msg_queue_delete(io_queue_handle); + } + if (evt_queue_handle) { + os_msg_queue_delete(evt_queue_handle); + } + io_queue_handle = NULL; + evt_queue_handle = NULL; + app_task_handle = NULL; + + bt_beacon_gap_dev_state.gap_init_state = 0; + bt_beacon_gap_dev_state.gap_adv_sub_state = 0; + bt_beacon_gap_dev_state.gap_adv_state = 0; + bt_beacon_gap_dev_state.gap_scan_state = 0; + bt_beacon_gap_dev_state.gap_conn_state = 0; +} + + +/** @} */ /* End of group PERIPH_APP_TASK */ +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.h new file mode 100644 index 00000000..17bb60cf --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.h @@ -0,0 +1,27 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_BEACON_APP_TASK_H_ +#define _BT_BEACON_APP_TASK_H_ + +extern void bt_beacon_driver_init(void); + +/** + * @brief Initialize App task + * @return void + */ +void bt_beacon_app_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_flags.h new file mode 100644 index 00000000..2edb7490 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_flags.h @@ -0,0 +1,31 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_DATATRANS_APP_FLAGS_H_ +#define _BT_DATATRANS_APP_FLAGS_H_ + +#include + +/*============================================================================* + * Constants + *============================================================================*/ + +#define BT_DATATRANS_APP_MAX_LINKS 1 + +/*if define CENTRAL_MODE to 1,pls include datatrans_client.c & gaps_client.c in target build.*/ +#define CENTRAL_MODE 1 + +/** @} */ /* End of group SCATTERNET_Config */ +/** @} */ /* End of group SCATTERNET_DEMO */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.c new file mode 100644 index 00000000..bdcaf875 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.c @@ -0,0 +1,58 @@ +enum { __FILE_NUM__ = 0 }; + +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file app_queue.c +* @brief +* @details +* @author jane +* @date 2015-03-29 +* @version v0.2 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include "bt_datatrans_app_queue.h" + +#if ! defined (FX_NOFLAGS) +#endif + +void datatrans_app_queue_in(QUEUE_P QueuePtr, void *pQueueElement) +{ + + ELEMENT_P QueueElementPtr = (ELEMENT_P)pQueueElement; + ELEMENT_P LastPtr; + + if ((LastPtr = QueuePtr->Last) == (ELEMENT_P)0) /* if queue is empty, */ + { + QueuePtr->First = QueueElementPtr; /* q->first = q->last = new entry */ + } + else /* if it is not empty, new entry */ + { + LastPtr->Next = QueueElementPtr; /* is next from last entry */ + } + QueuePtr->Last = QueueElementPtr; + QueueElementPtr->Next = (ELEMENT_P)0; + QueuePtr->ElementCount++; /* increment element count */ +} + +void *datatrans_app_queue_out(QUEUE_P QueuePtr) +{ + ELEMENT_P FirstPtr; + + if ((FirstPtr = QueuePtr->First) != (ELEMENT_P)0) + { + /* if queue not empty and */ + /* it is the last entry */ + if ((QueuePtr->First = FirstPtr->Next) == (ELEMENT_P)0) + { + QueuePtr->Last = (ELEMENT_P)0; /* set queue empty */ + } + QueuePtr->ElementCount--; /* decrement element count */ + } + return (FirstPtr); +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.h new file mode 100644 index 00000000..50417776 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.h @@ -0,0 +1,48 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file app_queue.h +* @brief +* @details +* @author jane +* @date 2015-03-29 +* @version v0.2 +********************************************************************************************************* +*/ + +#ifndef __BT_DATATRANS_APP_QUEUE_H +#define __BT_DATATRANS_APP_QUEUE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct QueueElement /* dummy definition */ +{ + struct QueueElement *Next; /* point to next element */ + uint8_t data[2]; /* user data */ +}; +typedef struct QueueElement ELEMENT_T; + +typedef ELEMENT_T *ELEMENT_P; + +typedef struct +{ + ELEMENT_P First; /* first element */ + ELEMENT_P Last; /* last element */ + uint16_t ElementCount; /* element count */ +} QUEUE_T, *QUEUE_P; + + +void datatrans_app_queue_in(QUEUE_P QueuePtr, void *QueueElementPtr); +void *datatrans_app_queue_out(QUEUE_P QueuePtr); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.c new file mode 100644 index 00000000..7294577c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.c @@ -0,0 +1,130 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define BT_DATATRANS_APP_TASK_PRIORITY 4 //!< Task priorities +#define BT_DATATRANS_APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define BT_DATATRANS_MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define BT_DATATRANS_MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define BT_DATATRANS_MAX_NUMBER_OF_EVENT_MESSAGE (BT_DATATRANS_MAX_NUMBER_OF_GAP_MESSAGE + BT_DATATRANS_MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_datatrans_app_task_handle; //!< APP Task handle +void *bt_datatrans_evt_queue_handle; //!< Event queue handle +void *bt_datatrans_io_queue_handle; //!< IO queue handle + +extern T_GAP_DEV_STATE bt_datatrans_gap_dev_state; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_datatrans_app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&bt_datatrans_io_queue_handle, BT_DATATRANS_MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_datatrans_evt_queue_handle, BT_DATATRANS_MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(bt_datatrans_evt_queue_handle, bt_datatrans_io_queue_handle, BT_DATATRANS_MAX_NUMBER_OF_GAP_MESSAGE); + + while (true) + { + if (os_msg_recv(bt_datatrans_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_datatrans_io_queue_handle, &io_msg, 0) == true) + { + bt_datatrans_app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** + * @brief Initialize App task + * @return void + */ +void bt_datatrans_app_task_init() +{ + os_task_create(&bt_datatrans_app_task_handle, "bt_datatrans_app", bt_datatrans_app_main_task, 0, BT_DATATRANS_APP_TASK_STACK_SIZE, + BT_DATATRANS_APP_TASK_PRIORITY); +} + + +void bt_datatrans_app_task_deinit(void) +{ + if (bt_datatrans_app_task_handle) { + os_task_delete(bt_datatrans_app_task_handle); + } + if (bt_datatrans_io_queue_handle) { + os_msg_queue_delete(bt_datatrans_io_queue_handle); + } + if (bt_datatrans_evt_queue_handle) { + os_msg_queue_delete(bt_datatrans_evt_queue_handle); + } + bt_datatrans_io_queue_handle = NULL; + bt_datatrans_evt_queue_handle = NULL; + bt_datatrans_app_task_handle = NULL; + + bt_datatrans_gap_dev_state.gap_init_state = 0; + bt_datatrans_gap_dev_state.gap_adv_sub_state = 0; + bt_datatrans_gap_dev_state.gap_adv_state = 0; + bt_datatrans_gap_dev_state.gap_scan_state = 0; + bt_datatrans_gap_dev_state.gap_conn_state = 0; + +} + +/** @} */ /* End of group PERIPH_APP_TASK */ +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.h new file mode 100644 index 00000000..ecaf3ade --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.h @@ -0,0 +1,26 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_DATATRANS_APP_TASK_H_ +#define _BT_DATATRANS_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_datatrans_app_task_init(void); +void bt_datatrans_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.c new file mode 100644 index 00000000..298b3617 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.c @@ -0,0 +1,1131 @@ +enum { __FILE_NUM__ = 0 }; + +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file at_cmd.c +* @brief +* @details +* @author jane +* @date 2015-03-29 +* @version v0.2 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include "trace_app.h" +#include "bt_datatrans_uart.h" +#include "gap_conn_le.h" +#include +#include +#include "bt_datatrans_module_param_config.h" +#include "bt_datatrans_at_cmd.h" +#include "bt_datatrans_peripheral_application.h" +#include "bt_datatrans_multilink_manager.h" +#include "bt_datatrans_profile.h" +#include "bt_datatrans_at_hci_cmd_process.h" +#include "os_timer.h" +#include +#include +#include +#include "bt_datatrans_client.h" +#include "gap_scan.h" +#include "gap_adv.h" +#include "os_mem.h" +#include "gap_bond_le.h" +#include "ftl_app.h" + +extern T_GAP_DEV_STATE bt_datatrans_gap_dev_state; +extern T_GAP_CONN_STATE bt_datatrans_gap_conn_state; +extern T_SERVER_ID bt_datatrans_srv_id; +extern T_DATATRANS_REMOTE_BDADDR_INFO connect_dev; + +const char AtCmdHeader[AT_CMD_HEADER_LENGTH] = {'A', 'T'}; +const char AtCmdResponseOK[] = "OK\r\n"; +const char AtCmdResponseERR[] = "ERR\r\n"; + +const char AtCmdResponseNAME[] = "+NAME="; +const char AtCmdResponseINQS[] = "+INQS\r\n"; +const char AtCmdResponseINQE[] = "+INQE\r\n"; +const char AtCmdResponseCONNS[] = "+CONNS\r\n"; + +const char AtCmdResponseBAUD[] = "+BAUD="; +const char AtCmdResponseROLE[] = "+ROLE="; +const char AtCmdResponsePINDIS[] = "+PINDIS="; +const char AtCmdResponsePAIR[] = "+PAIR="; +const char AtCmdResponseCONNTIMEOUT[] = "+CONNECTION TIME OUT\r\n"; + +const char AtCmdResponseADVMOD[] = "+ADVMOD="; +const char AtCmdResponseADVEN[] = "+ADVEN="; +const char AtCmdResponseScanRlt[] = "+SCANLT="; +const char AtCmdResponseVERSION[] = "+VERSION="; +const char AtCmdResponseConnect[] = "+CONNECTED>>0x"; +const char AtCmdResponseDisconnect[] = "+DISCONNECT\r\n"; +const char AtCmdResponseDISC[] = "+DISCS\r\n"; + +extern uint8_t DT_SCAN_RSP_DATA[31]; +extern uint8_t DT_ADV_DATA[31]; + +#define CompareExitMagic "AT+XXX\r\n" +#define MAGIC_NUM 8 // = "AT+" + "XXX" + "\r\n" + +uint8_t sendbuffer[255] = {0}; +void Setsendbuffer(uint16_t bufferlen) +{ + uint32_t flags; + flags = os_lock();//enter critical section + + if (IO_Receive.ReadOffset + bufferlen <= RECEIVE_BUF_MAX_LENGTH) + { + memcpy(sendbuffer, IO_Receive.buf + IO_Receive.ReadOffset, bufferlen); + IO_Receive.ReadOffset += bufferlen; + if (IO_Receive.ReadOffset == RECEIVE_BUF_MAX_LENGTH) + { + IO_Receive.ReadOffset = 0; + } + } + else + { + uint16_t len1 = RECEIVE_BUF_MAX_LENGTH - IO_Receive.ReadOffset; + memcpy(sendbuffer, IO_Receive.buf + IO_Receive.ReadOffset, len1); + IO_Receive.ReadOffset = 0; + memcpy(sendbuffer + len1, IO_Receive.buf + IO_Receive.ReadOffset, bufferlen - len1); + IO_Receive.ReadOffset += bufferlen - len1; + } + + IO_Receive.datalen -= bufferlen; + os_unlock(flags); //exit critical section +} + +bool DataTrans_GetCMDBuffer(uint16_t len) +{ + uint16_t rxBufferReadOffset_temp; + + if ((len == 0) || (len > IO_Receive.datalen)) + { + IO_Receive.datalen = 0; + IO_Receive.ReadOffset = IO_Receive.WriteOffset; + return false; + } + + rxBufferReadOffset_temp = IO_Receive.ReadOffset; + IO_Receive.atcmdlength = len; + if (IO_Receive.ReadOffset + len <= RECEIVE_BUF_MAX_LENGTH) + { + memcpy(IO_Receive.atcmd, IO_Receive.buf + IO_Receive.ReadOffset, len); + IO_Receive.ReadOffset += len; + if (IO_Receive.ReadOffset == RECEIVE_BUF_MAX_LENGTH) + { + IO_Receive.ReadOffset = 0; + } + } + else + { + uint16_t len1 = RECEIVE_BUF_MAX_LENGTH - IO_Receive.ReadOffset; + memcpy(IO_Receive.atcmd, IO_Receive.buf + IO_Receive.ReadOffset, len1); + IO_Receive.ReadOffset = 0; + memcpy(IO_Receive.atcmd + len1, IO_Receive.buf + IO_Receive.ReadOffset, len - len1); + IO_Receive.ReadOffset += len - len1; + } + + + if ((len % 8 == 0) && ((IO_Receive.atcmd[len - 1] != '\n') || (IO_Receive.atcmd[len - 2] != '\r'))) + { + IO_Receive.ReadOffset = rxBufferReadOffset_temp; + return false; + } + + uint32_t flags; + flags = os_lock();//enter critical section + IO_Receive.datalen -= len; + os_unlock(flags); //exit critical section + + return true; +} + +void DataTrans_HandleATCMD(void) +{ + if (IO_Receive.datalen == 0) //Data length invalid + { + return; + } + + if ((bt_datatrans_gap_conn_state == GAP_CONN_STATE_CONNECTED) && (transferConfigInfo.select_mode != CMD_MODE)) + { + if ((memcmp(IO_Receive.buf + IO_Receive.ReadOffset, CompareExitMagic, MAGIC_NUM) == 0)) + { + APP_PRINT_ERROR0("Switch to AT mode."); + transferConfigInfo.select_mode = CMD_MODE; + uint32_t flags; + flags = os_lock();//enter critical section + IO_Receive.datalen = 0; + IO_Receive.ReadOffset = IO_Receive.WriteOffset; + os_unlock(flags); //exit critical section + return; + } + + uint16_t len = 0; + le_get_gap_param(GAP_PARAM_LE_REMAIN_CREDITS, &BT_Credits); + + for(; IO_Receive.datalen != 0; ) + { + + if (BT_Credits) + { + if (IO_Receive.datalen >= MTU_SIZE - 3) //buffer length > MTU size - 3, send immediately + { + len = MTU_SIZE - 3; + Setsendbuffer(len); + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + server_send_data(CON_ID, bt_datatrans_srv_id, GATT_UUID_CHAR_DATA_NOTIFY_INDEX, sendbuffer, len, + GATT_PDU_TYPE_ANY); + } +#if CENTRAL_MODE + else if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + kns_client_write_data_char(CON_ID, len, sendbuffer, GATT_WRITE_TYPE_CMD); + } +#endif + } + else if (transferConfigInfo.uart_idle) //buffer length < MTU size - 3 + { + len = IO_Receive.datalen; + Setsendbuffer(len); + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + server_send_data(CON_ID, bt_datatrans_srv_id, GATT_UUID_CHAR_DATA_NOTIFY_INDEX, sendbuffer, len, + GATT_PDU_TYPE_ANY); + } +#if CENTRAL_MODE + else if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + kns_client_write_data_char(CON_ID, len, sendbuffer, GATT_WRITE_TYPE_CMD); + } +#endif + transferConfigInfo.uart_idle = 0; + + } + BT_Credits--; + + } + else + { + break; + } + } + } + else + { + uint16_t T_index = IO_Receive.ReadOffset + 1; + + if (T_index >= RECEIVE_BUF_MAX_LENGTH) + { + T_index = 0; + } + if ((IO_Receive.buf[IO_Receive.ReadOffset] == 'A' || + IO_Receive.buf[IO_Receive.ReadOffset] == 'a') && \ + (IO_Receive.buf[T_index] == 'T' || + IO_Receive.buf[T_index] == 't')) + { + uint16_t len = IO_Receive.datalen; + APP_PRINT_INFO1("received len is %d", len); + if (len > AT_CMD_MAX_LENGTH || len < AT_CMD_MIN_LENGTH) + { + uint32_t flags; + flags = os_lock();//enter critical section + IO_Receive.datalen = 0; + IO_Receive.ReadOffset = IO_Receive.WriteOffset; + os_unlock(flags); //exit critical section + } + else + { + if (DataTrans_GetCMDBuffer(len)) + { + AtCmdParse(); + } + } + + } + else + { + uint32_t flags; + flags = os_lock();//enter critical section + IO_Receive.datalen = 0; + IO_Receive.ReadOffset = IO_Receive.WriteOffset; + os_unlock(flags); //exit critical section + } + + } + +} + +/** +* @brief Send the reponse data of AT cmd to the TX handle task. +* @param p_resp, the pointer of the response data. +* @param len, the length of the response data. +* @return void +*/ +void AtCmdSendResponse(const char *p_resp, uint16_t len) +{ + PTxData pTxData = NULL; + + uint32_t flags; + flags = os_lock(); + pTxData = datatrans_app_queue_out(&txUartDataQueueFree); + os_unlock(flags); + if (pTxData != NULL) + { + uint16_t mem_length = len + 4 - len % 4; + pTxData->tx_buffer = os_mem_alloc(RAM_TYPE_DATA_ON, mem_length); + if (pTxData->tx_buffer != NULL) + { + memcpy(pTxData->tx_buffer, p_resp, len); + pTxData->length = len; + pTxData->is_stack_buf = false; + pTxData->stack_buf_offset = 0; + + if (os_msg_send(TxMessageQueueHandle, &pTxData, 0) == false) + { + APP_PRINT_INFO0("DataTrans_SendResp:send data failed\n"); + os_mem_free(pTxData->tx_buffer); //send message fail, free memory + pTxData->tx_buffer = NULL; + uint32_t flags; + flags = os_lock();//enter critical section + datatrans_app_queue_in(&txUartDataQueueFree, pTxData); + os_unlock(flags); //exit critical section + } + } + else + { + APP_PRINT_INFO0("AtCmdSendResponse: mem malloc fail\n"); + uint32_t flags; + flags = os_lock();//enter critical section + datatrans_app_queue_in(&txUartDataQueueFree, pTxData); + os_unlock(flags); //exit critical section + } + } + else + { + APP_PRINT_INFO0("AtCmdSendResponse: queue is full\n"); + } + +} + +/** +* @brief convert num to string. +* @param num, the number need to convert +* @param str, the result +* @return void +*/ +void DataTrans_Itoa(uint32_t num, char *str) +{ + uint32_t i = 0, j, k; + do + { + str[i++] = (num % 10) + '0'; + num = num / 10; + } + while (num); + + str[i] = '\0'; + k = 0; + char temp; + for (j = k; j <= (i - 1) / 2; j++) + { + temp = str[j]; + str[j] = str[i - 1 + k - j]; + str[i - 1 + k - j] = temp; + } +} + +/** +* @brief convert string to uint32_t. +* @param str +* @return uint32_t +*/ +uint32_t DataTrans_Atoi(const char *str) +{ + uint32_t res = 0, begin = 0; + + while (*str != '\0') + { + if (begin == 0 && (('0' <= *str && *str <= '9') || *str == '-')) + { + begin = 1; + } + else if (begin == 1 && (*str < '0' || *str > '9')) + { + break; + } + if (begin == 1) + { + res = res * 10 + (*str - '0'); + } + str++; + } + return res; +} + +void DataTrans_Hex2String(uint8_t *Src, uint8_t *Dest, uint8_t len) +{ + uint8_t i = 0; + uint8_t byte_low = 0; + uint8_t byte_high = 0; + for (i = 0; i < len; i++) + { + byte_low = Src[i] % 16; + byte_high = Src[i] / 16; + if (byte_low <= 9) + { + Dest[i * 2 + 1] = byte_low + '0'; + } + else + { + Dest[i * 2 + 1] = byte_low - 10 + 'A'; + } + if (byte_high <= 9) + { + Dest[i * 2] = byte_high + '0'; + } + else + { + Dest[i * 2] = byte_high - 10 + 'A'; + } + } +} + +bool DataTrans_String2Hex(uint8_t *Src, uint8_t *Dest, uint8_t len) +{ + uint8_t i = 0; + uint8_t byte_low = 0; + uint8_t byte_high = 0; + for (i = 0; i < len; i = i + 2) + { + if (Src[i] >= '0' && Src[i] <= '9') + { + byte_high = Src[i] - '0'; + } + else if (Src[i] >= 'A' && Src[i] <= 'F') + { + byte_high = Src[i] - 'A' + 10; + } + else if (Src[i] >= 'a' && Src[i] <= 'f') + { + byte_high = Src[i] - 'a' + 10; + } + else + { + return false; + } + + if (Src[i + 1] >= '0' && Src[i + 1] <= '9') + { + byte_low = Src[i + 1] - '0'; + } + else if (Src[i + 1] >= 'A' && Src[i + 1] <= 'F') + { + byte_low = Src[i + 1] - 'A' + 10; + } + else if (Src[i + 1] >= 'a' && Src[i + 1] <= 'f') + { + byte_low = Src[i + 1] - 'a' + 10; + } + else + { + return false; + } + Dest[i / 2] = (byte_high << 4) | byte_low; + } + + return true; +} + + +/* ****************************************** AtCmdSendResponse ******************************************* */ +/** +* @brief Send the reponse data of AT\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseOK() +{ + AtCmdSendResponse(AtCmdResponseOK, strlen(AtCmdResponseOK)); +} + +void AtCmdSendResponseERR() +{ + AtCmdSendResponse(AtCmdResponseERR, strlen(AtCmdResponseERR)); +} + +void AtCmdSendResponseConnect(uint8_t conn_id)//,uint8_t role) +{ + char bda[12]; + AtCmdSendResponse(AtCmdResponseConnect, strlen(AtCmdResponseConnect)); + + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR, connect_dev.bdaddr, conn_id); + DataTrans_Hex2String(connect_dev.bdaddr, (uint8_t *)bda, 6); + + AtCmdSendResponse((const char *)bda, sizeof(bda)); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); +} + +void AtCmdSendResponseDisconnect() +{ + AtCmdSendResponse(AtCmdResponseDisconnect, strlen(AtCmdResponseDisconnect)); +} + +void AtCmdSendResponsePinDis() +{ + char pin_buffer[10] = {0}; + + DataTrans_Itoa(dataTransInfo.pincode, pin_buffer); + AtCmdSendResponse(AtCmdResponsePINDIS, strlen(AtCmdResponsePINDIS)); + AtCmdSendResponse((const char *)(pin_buffer), strlen(pin_buffer)); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); +} + + +/** +* @brief Send the reponse data of AT+NAME\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseName() +{ + AtCmdSendResponse(AtCmdResponseNAME, strlen(AtCmdResponseNAME)); + AtCmdSendResponse((const char *)(dataTransInfo.devicename_info.device_name), + dataTransInfo.devicename_info.length); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); +} + + +/** +* @brief Send the reponse data of AT+BAUD\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseBaudConfig() +{ + AtCmdSendResponse(AtCmdResponseBAUD, strlen(AtCmdResponseBAUD)); + AtCmdSendResponse((const char *)(IO_Receive.atcmd + 8), + IO_Receive.atcmdlength - AT_CMD_BAUD_LENGTH - 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + AtCmdSendResponseOK(); +} + +/** +* @brief Send the reponse data of AT+BAUD\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseBaud() +{ + char baud[10] = {0}; + DataTrans_Itoa(transferConfigInfo.baudrate, baud); + AtCmdSendResponse(AtCmdResponseBAUD, strlen(AtCmdResponseBAUD)); + AtCmdSendResponse((const char *)baud, strlen(baud)); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); +} + +void AtCmdSendResponseDISC() +{ + AtCmdSendResponseOK(); + AtCmdSendResponse(AtCmdResponseDISC, strlen(AtCmdResponseDISC)); +} + +/** +* @brief Send the reponse data of AT+ROLE\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseRoleConfig() +{ + AtCmdSendResponse(AtCmdResponseROLE, strlen(AtCmdResponseROLE)); + AtCmdSendResponse((const char *)(IO_Receive.atcmd + 8), 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + AtCmdSendResponseOK(); +} + +/** +* @brief Send the reponse data of AT+ROLE\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseRole() +{ + + char index = (char)(dataTransInfo.device_mode.role + '0'); + const char *gaproleindex = (const char *)(&index); + AtCmdSendResponse(AtCmdResponseROLE, strlen(AtCmdResponseROLE)); + AtCmdSendResponse(gaproleindex, 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); +} + + +void AtCmdSendResponsePair()//pair flg +{ + char index = (char)(dataTransInfo.pair_info.pair_mode + '0'); + const char *pairindex = (const char *)(&index); + AtCmdSendResponse(AtCmdResponsePAIR, strlen(AtCmdResponsePAIR)); + AtCmdSendResponse(pairindex, 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); +} + +#if CENTRAL_MODE +/** +* @brief Send the reponse data of AT+INQ\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseInqStart() +{ + AtCmdSendResponseOK(); + AtCmdSendResponse(AtCmdResponseINQS, strlen(AtCmdResponseINQS)); +} + +/** +* @brief Send the reponse data of AT+CONN\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseConnStart() +{ + AtCmdSendResponseOK(); + AtCmdSendResponse(AtCmdResponseCONNS, strlen(AtCmdResponseCONNS)); +} + +/** +* @brief Send the reponse data of AT+SINQ\r\n. +* @param void +* @return void +*/ +void AtCmdSendResponseInqEnd() +{ + AtCmdSendResponse(AtCmdResponseINQE, strlen(AtCmdResponseINQE)); +} +#endif +/* ******************************************************************************************** */ + +/* **************************************** AtCmdHandle *************************************** */ +/** +* @brief Handle the Reset cmd. +* @param void +* @return void +*/ +void AtCmdHandleReset(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_RESET_LENGTH) + { + os_timer_start(&TimersReset); + AtCmdSendResponseOK(); + } +} + +/** +* @brief Handle AT+BAUD cmd. +* @param void +* @return void +*/ +void AtCmdHandleBaud(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_BAUD_LENGTH) /* AT CMD: AT+BAUD */ + { + AtCmdSendResponseBaud(); + } + else /* AT CMD: AT+BAUD */ + { + IO_Receive.atcmd[IO_Receive.atcmdlength] = '\0'; + if (IO_Receive.atcmd[7] == '=') + { + uint32_t newbaud = DataTrans_Atoi((const char *)(IO_Receive.atcmd + 8)); + APP_PRINT_INFO1("newbaud is %d", newbaud); + printf("ATCMD set baud, newbaud is %d\n", newbaud); + if (/*(newbaud == 2000000) ||*/(newbaud == 921600) || (newbaud == 2400) || (newbaud == 4800) || + (newbaud == 9600) || + (newbaud == 19200) || (newbaud == 38400) || (newbaud == 57600) || (newbaud == 115200)) + { + if (transferConfigInfo.baudrate != newbaud) + { + transferConfigInfo.baudrate = newbaud; + os_timer_start(&TimersUartConfigChange); + } + AtCmdSendResponseBaudConfig(); + } + } + } +} + +/** +* @brief Handle AT+DEFAULT cmd. +* @param void +* @return void +*/ +void AtCmdHandleDefault(void) +{ + datatrans_setdefault(); + os_timer_start(&TimersReset); + AtCmdSendResponseOK(); +} + +/** +* @brief Handle AT+NAME cmd. +* @param void +* @return void +*/ +void AtCmdHandleName(void) +{ + + if (IO_Receive.atcmdlength == AT_CMD_NAME_LENGTH) /* AT CMD: AT+NAME */ + { + AtCmdSendResponseName(); + } + else /* AT CMD: AT+NAME */ + { + uint16_t len; + if (IO_Receive.atcmd[7] == '=') + { + len = IO_Receive.atcmdlength - (AT_CMD_NAME_LENGTH + 1); + if (len <= DEVICE_NAME_MAX_LENGTH) + { + Device_Name_Write(IO_Receive.atcmd + 8, len); + //const char *rename = (const char *)(name); + AtCmdSendResponse(AtCmdResponseNAME, strlen(AtCmdResponseNAME)); + AtCmdSendResponse((const char *)dataTransInfo.devicename_info.device_name, + dataTransInfo.devicename_info.length); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + AtCmdSendResponseOK(); + } + } + } +} + +/** +* @brief Handle AT+ROLE cmd. +* @param void +* @return void +*/ +void AtCmdHandleRole(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_ROLE_LENGTH) /* AT CMD: AT+ROLE */ + { + AtCmdSendResponseRole(); + } + else if (IO_Receive.atcmdlength == AT_CMD_ROLE_LENGTH + 2) /* AT CMD: AT+ROLE */ + { + if (IO_Receive.atcmd[7] == '=') + { + uint16_t gaproleindex = IO_Receive.atcmd[8] - '0'; + + if (gaproleindex == 0 || gaproleindex == 0x1 || gaproleindex == 0x2) + { + Role_Set(gaproleindex); + AtCmdSendResponseRoleConfig(); + } + } + } +} + +/** +* @brief Handle AT+PAIR cmd. +* @param void +* @return void +*/ +void AtCmdHandlePair(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_PAIR_LENGTH) /* AT CMD: AT+PAIR */ + { + AtCmdSendResponsePair(); + } + else if (IO_Receive.atcmdlength == AT_CMD_PAIR_LENGTH + 2) + { + if (IO_Receive.atcmd[7] == '=') + { + uint8_t newpair = IO_Receive.atcmd[8] - '0'; + if (newpair <= 3) + { + if (newpair != dataTransInfo.pair_info.pair_mode) + { + dataTransInfo.pair_info.pair_mode = newpair; + Pair_Mode_Set(newpair); + AtCmdSendResponse(AtCmdResponsePAIR, strlen(AtCmdResponsePAIR)); + AtCmdSendResponse((const char *)(IO_Receive.atcmd + 8), + IO_Receive.atcmdlength - AT_CMD_PAIR_LENGTH - 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + AtCmdSendResponseOK(); + } + } + } + } +} + +/** +* @brief Handle AT+ADVMODE cmd. +* @param void +* @return void +*/ +void AtCmdHandleAdvMode(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_ADVMOD_LENGTH) + { + char index = (char)(dataTransInfo.device_mode.adv_mode + '0'); + const char *advmodeindex = (const char *)(&index); + AtCmdSendResponse(AtCmdResponseADVMOD, strlen(AtCmdResponseADVMOD)); + AtCmdSendResponse(advmodeindex, 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + } + else if (IO_Receive.atcmdlength == AT_CMD_ADVMOD_LENGTH + 2) + { + if (IO_Receive.atcmd[9] == '=') + { + uint8_t advmode = IO_Receive.atcmd[10] - '0'; + if (advmode <= 1) + { + if (dataTransInfo.device_mode.adv_mode != advmode) + { + dataTransInfo.device_mode.adv_mode = advmode; + if ((dataTransInfo.device_mode.adv_mode == 1) && + (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_IDLE) && + (bt_datatrans_gap_conn_state != GAP_CONN_STATE_CONNECTED) && + (dataTransInfo.device_mode.role == ROLE_PERIPHERAL)) + { + le_adv_start();//adv mode =1, auto mode, adv mode =0 handle mode + } + else if ((dataTransInfo.device_mode.adv_mode == 0) && + (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) && + (bt_datatrans_gap_conn_state != GAP_CONN_STATE_CONNECTED) && + (dataTransInfo.device_mode.role == ROLE_PERIPHERAL)) + { + le_adv_stop(); + } + char index = (char)(dataTransInfo.device_mode.adv_mode + '0'); + const char *advmodeindex = (const char *)(&index); + AtCmdSendResponse(AtCmdResponseADVMOD, strlen(AtCmdResponseADVMOD)); + AtCmdSendResponse(advmodeindex, 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + ftl_save(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4); + } + AtCmdSendResponseOK(); + } + } + } +} + +/** +* @brief Handle AT+ADVEN cmd. +* @param void +* @return void +*/ +void AtCmdHandleAdvEN(void) +{ + if ((dataTransInfo.device_mode.adv_mode == 0) && + (dataTransInfo.device_mode.role == ROLE_PERIPHERAL)) + { + if (IO_Receive.atcmdlength == AT_CMD_ADVEN_LENGTH + 2) + { + if (IO_Receive.atcmd[8] == '=') + { + uint8_t adven = IO_Receive.atcmd[9] - '0'; + if (adven <= 1) + { + if (ADV_Enable_Disable(adven)) + { + AtCmdSendResponse(AtCmdResponseADVEN, strlen(AtCmdResponseADVEN)); + const char *adven = (const char *)(IO_Receive.atcmd + 9); + AtCmdSendResponse(adven, 1); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + AtCmdSendResponseOK(); + } + } + } + } + } +} + +/** +* @brief Handle AT+VERSION cmd. +* @param void +* @return void +*/ +void AtCmdHandleVersion(void) +{ + uint8_t ver[8]; + if (IO_Receive.atcmdlength == AT_CMD_VERSION_LENGTH) + { + uint8_t verstr[16]; + ver[3] = transferConfigInfo.app_version; + ver[2] = transferConfigInfo.app_version >> 8; + ver[1] = transferConfigInfo.app_version >> 16; + ver[0] = transferConfigInfo.app_version >> 24; + ver[7] = transferConfigInfo.patch_version; + ver[6] = transferConfigInfo.patch_version >> 8; + ver[5] = transferConfigInfo.patch_version >> 16; + ver[4] = transferConfigInfo.patch_version >> 24; + DataTrans_Hex2String(ver, verstr, 8); + + AtCmdSendResponse(AtCmdResponseVERSION, strlen(AtCmdResponseVERSION)); + AtCmdSendResponse((const char *)verstr, 8); + AtCmdSendResponse(",", 1); + AtCmdSendResponse((const char *)verstr + 8, 8); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + } +} + +/** +* @brief Handle AT+DISC cmd. +* @param void +* @return void +*/ +void AtCmdHandleDISC(void) +{ + if (bt_datatrans_gap_conn_state == GAP_CONN_STATE_CONNECTED) + { + if (IO_Receive.atcmdlength == AT_CMD_DISC_LENGTH + 2) + { + uint8_t conn_id; + if (IO_Receive.atcmd[7] == '=') + { + conn_id = IO_Receive.atcmd[8] - '0'; + if(le_disconnect(conn_id) == GAP_CAUSE_SUCCESS) + { + transferConfigInfo.select_mode = DATATRANS_MODE; + AtCmdSendResponseDISC(); + } + + } + } + } +} + +#if CENTRAL_MODE +/** +* @brief Handle AT+INQ cmd. +* @param void +* @return void +*/ +void AtCmdHandleInq(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_INQ_LENGTH) /* AT CMD: AT+INQ*/ + { + if (dataTransInfo.device_mode.role == ROLE_CENTRAL && + bt_datatrans_gap_dev_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + DataTrans_Multilink_ClearDeviceList(); + le_scan_start(); + AtCmdSendResponseInqStart(); + } + + } +} + +/** +* @brief Handle AT+SINQ cmd. +* @param void +* @return void +*/ +void AtCmdHandleSInq(void) +{ + if (IO_Receive.atcmdlength == AT_CMD_SINQ_LENGTH) /* AT CMD: AT+SINQ */ + { + if (dataTransInfo.device_mode.role == ROLE_CENTRAL && + bt_datatrans_gap_dev_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + le_scan_stop(); + AtCmdSendResponseInqEnd(); + } + } +} + +/** +* @brief Handle AT+SCANRLT cmd. +* @param void +* @return void +*/ +void AtCmdHandleScanResult(void) +{ + if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + if (IO_Receive.atcmdlength == AT_CMD_SCANRLT_LENGTH + 2) + { + if (IO_Receive.atcmd[10] == '=') + { + uint8_t devicenum = IO_Receive.atcmd[11] - '0'; + if (devicenum < BT_DATATRANS_APP_MAX_DEVICE_INFO) + { + char addstr[15]; + addstr[0] = devicenum + '0'; + addstr[1] = ':'; + + sprintf(addstr + 2, "%02X%02X%02X%02X%02X%02X", DT_DevList[devicenum].bd_addr[5], + DT_DevList[devicenum].bd_addr[4], \ + DT_DevList[devicenum].bd_addr[3], DT_DevList[devicenum].bd_addr[2], + DT_DevList[devicenum].bd_addr[1], DT_DevList[devicenum].bd_addr[0]); + + AtCmdSendResponse(AtCmdResponseScanRlt, strlen(AtCmdResponseScanRlt)); + AtCmdSendResponse((const char *)addstr, 14); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + } + } + } + } +} + +/** +* @brief Handle AT+CONN cmd. +* @param void +* @return void +*/ +void AtCmdHandleConn(void) +{ + if (dataTransInfo.device_mode.role != ROLE_CENTRAL) + { + return; + } + if (IO_Receive.atcmdlength == AT_CMD_CONN_LENGTH + 1) + { + uint8_t connindex; + if (IO_Receive.atcmd[7] == '=') + { + connindex = IO_Receive.atcmd[8] - '0'; + APP_PRINT_INFO2("connindex is %x,DTDevListNum is %x", connindex, DTDevListNum); + if (connindex < DTDevListNum) + { + AtCmdSendResponseConnStart(); + Connect_Device_Num(connindex); + } + } + } + else + { + AtCmdSendResponseERR(); + } +} +#endif + +/* ************************************************************************************ */ + +/** +* @brief Check if the string is at cmd. +* @param at_cmd, the at cmd +* @param pos, index of the cmd buffer received from UART. +* @return true, is at cmd. false, isn't at cmd. +*/ +bool IsAtCmd(char *at_cmd, uint16_t pos) +{ + bool res = true; + + while (*at_cmd != '\0') + { + if ((IO_Receive.atcmd[pos] != *at_cmd) && (IO_Receive.atcmd[pos] != (*at_cmd) + 32)) + { + res = false; + break; + } + pos++; + at_cmd++; + } + + return res; +} + +/** +* @brief AT cmd parse. +* @param void +* @return void +*/ +void AtCmdParse(void) +{ + uint16_t pos = 0; + APP_PRINT_INFO0("ENTER cmd parse 000"); + if (IO_Receive.atcmdlength < AT_CMD_HEADER_LENGTH) + { + return; + } + + if (((IO_Receive.atcmd[pos] != 'A') && (IO_Receive.atcmd[pos] != 'a')) || + ((IO_Receive.atcmd[pos + 1] != 'T') && (IO_Receive.atcmd[pos + 1] != 't'))) + { + return; + } + + if ((IO_Receive.atcmd[IO_Receive.atcmdlength - 2] != '\r') || + (IO_Receive.atcmd[IO_Receive.atcmdlength - 1] != '\n')) + { + return; + } + + pos += AT_CMD_HEADER_LENGTH; + + if ((IO_Receive.atcmd[pos] == '\r') && (IO_Receive.atcmd[pos + 1] == '\n') && + (IO_Receive.atcmdlength == AT_CMD_AT_LENGTH)) + { + AtCmdSendResponseOK(); /* AT cmd: AT */ + } + else if (IO_Receive.atcmd[pos] == '+') + { + APP_PRINT_INFO0("ENTER cmd parse 111"); + pos++; + + if (IsAtCmd("RESET", pos) && (IO_Receive.atcmdlength == AT_CMD_RESET_LENGTH))// + { + AtCmdHandleReset(); + } + else if (IsAtCmd("VERSION", pos))//1 + { + AtCmdHandleVersion(); + } + else if (IsAtCmd("NAME", pos)) + { + AtCmdHandleName(); + } + else if (IsAtCmd("BAUD", pos)) + { + AtCmdHandleBaud(); + } + else if (IsAtCmd("ADVMOD", pos)) + { + AtCmdHandleAdvMode(); + } + else if (IsAtCmd("ADVEN", pos)) + { + AtCmdHandleAdvEN(); + } + else if (IsAtCmd("ROLE", pos)) + { + AtCmdHandleRole(); + } + else if (IsAtCmd("PAIR", pos))//1 + { + AtCmdHandlePair(); + } + else if (IsAtCmd("DEFAULT", pos)) //1 + { + AtCmdHandleDefault(); + } +#if CENTRAL_MODE + else if (IsAtCmd("INQ", pos))//start inq device + { + AtCmdHandleInq(); + } + else if (IsAtCmd("SINQ", pos))//stop inq + { + AtCmdHandleSInq(); + } + else if (IsAtCmd("CONN", pos)) + { + AtCmdHandleConn(); + } + else if (IsAtCmd("SCANRLT", pos))//1 + { + AtCmdHandleScanResult(); + } +#endif + else if(IsAtCmd("DISC", pos)) + { + AtCmdHandleDISC(); + } + } +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.h new file mode 100644 index 00000000..4e48631b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.h @@ -0,0 +1,91 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file at_cmd.h +* @brief +* @details +* @author jane +* @date 2015-03-29 +* @version v0.2 +********************************************************************************************************* +*/ +//#include "rtl876x.h" + +#ifndef _BT_DATATRANS_AT_CMD_H_ +#define _BT_DATATRANS_AT_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "bt_datatrans_app_flags.h" +#include + + +#define AT_CMD_MAX_LENGTH 76 +#define AT_CMD_MIN_LENGTH 4 +#define AT_CMD_MAX_NUMBER 20 + +extern const char AtCmdResponseCONNTIMEOUT[]; + +#define AT_CMD_HEADER_LENGTH 2 +#define AT_CMD_AT_LENGTH 4 + +#define AT_CMD_RESET_LENGTH 10 +#define AT_CMD_ROLE_LENGTH 9 +#define AT_CMD_VERSION_LENGTH 12 +#define AT_CMD_BAUD_LENGTH 9 +#define AT_CMD_NAME_LENGTH 9 +#define AT_CMD_DEFAULT_LENGTH 12 + +#define AT_CMD_INQ_LENGTH 8 +#define AT_CMD_SINQ_LENGTH 9 +#define AT_CMD_CONN_LENGTH 10 +#define AT_CMD_DISC_LENGTH 9 /*AT+DISC=con_id*/ +#define AT_CMD_PAIR_LENGTH 9 + +#define AT_CMD_ADVMOD_LENGTH 11 +#define AT_CMD_ADVEN_LENGTH 10 +#define AT_CMD_SCANRLT_LENGTH 12 + +typedef void (*AtCMDCallback_t)(void); +typedef struct _CMD_TABLE_ +{ + char *CMD; + uint8_t CMD_Length; + bool ContainPara; + uint8_t NextCMD; + AtCMDCallback_t CMD_CB; +} CMD_TABLE; + +void Setsendbuffer(uint16_t bufferlen); +void DataTrans_HandleATCMD(void); + +void AtCmdSendResponse(const char *p_resp, uint16_t len); + +void AtCmdParse(void); +void AtCmdSendResponseOK(void); +void AtCmdSendResponseInqEnd(void); +void AtCmdSendResponseInqEnd(void); +void AtCmdSendResponsePinDis(void); + +void AtCmdHandleReset(void); +void AtCmdHandleBaud(void); +void AtCmdHandleName(void); + +#if CENTRAL_MODE +void AtCmdHandleInq(void); +void AtCmdHandleSInq(void); +void AtCmdHandleConn(void); +#endif + +void AtCmdHandleRole(void); +void AtCmdHandlePair(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.c new file mode 100644 index 00000000..c8403c25 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.c @@ -0,0 +1,420 @@ +enum { __FILE_NUM__ = 0 }; + +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file hci_cmd_event.c +* @brief +* @details +* @author parker_xue +* @date 2017_4_20 +* @version v0.1 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include "trace_app.h" +#include "bt_datatrans_at_hci_cmd_process.h" +#include "gap.h" +#include "gap_conn_le.h" +#include "gap_bond_le.h" +#include "gap_adv.h" +#include "gap_scan.h" +#include "bt_datatrans_multilink_manager.h" +#include +#include "bt_datatrans_profile.h" +#include "bt_datatrans_module_param_config.h" +#include "os_timer.h" +#include "ftl_app.h" +#include +#include +#include "os_mem.h" +#include +#include "bt_datatrans_app_flags.h" +#include "bt_datatrans_uart.h" + +#define DEVICE_NAME_MAX_LENGTH 15 + +extern T_GAP_DEV_STATE bt_datatrans_gap_dev_state; +extern T_GAP_CONN_STATE bt_datatrans_gap_conn_state; +extern T_SERVER_ID bt_datatrans_srv_id; + +extern uint8_t DT_SCAN_RSP_DATA[31]; +extern uint8_t DT_ADV_DATA[31]; + +void Device_Name_Write(uint8_t *payload, uint16_t payloadlen) +{ + memset(dataTransInfo.devicename_info.device_name, 0, DEVICE_NAME_MAX_LENGTH); + memcpy(dataTransInfo.devicename_info.device_name, payload, payloadlen); + dataTransInfo.devicename_info.length = payloadlen; + + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + if (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + le_adv_stop(); + transferConfigInfo.adv_param_update = true; + } + else + { + moduleParam_InitAdvAndScanRspData(); + uint8_t DeviceName[GAP_DEVICE_NAME_LEN] = {0}; + memcpy(DeviceName, dataTransInfo.devicename_info.device_name, dataTransInfo.devicename_info.length); + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, DeviceName); + } + } + else + { + moduleParam_InitAdvAndScanRspData(); + uint8_t DeviceName[GAP_DEVICE_NAME_LEN] = {0}; + memcpy(DeviceName, dataTransInfo.devicename_info.device_name, dataTransInfo.devicename_info.length); + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, DeviceName); + } + //save device name + ftl_save(&dataTransInfo.devicename_info, INFO_DEVICE_NAME_OFFSET, 16); + +} + + +void Pair_Mode_Set(uint8_t pairmode) +{ + uint16_t auth_flags = GAP_AUTHEN_BIT_NONE; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_sec_req_enalbe = true; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_NONE; + + switch (dataTransInfo.pair_info.pair_mode) + { + case NO_PASS_WORD: + { + auth_sec_req_enalbe = false; + } + break; + case JUST_WORK: + break; + case PASS_WORD: + { + auth_flags = GAP_AUTHEN_BIT_MITM_FLAG; + auth_sec_req_flags = GAP_AUTHEN_BIT_MITM_FLAG; + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + auth_io_cap = GAP_IO_CAP_KEYBOARD_ONLY; + } +#if CENTRAL_MODE + else if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + auth_io_cap = GAP_IO_CAP_DISPLAY_ONLY; + } +#endif + } + break; + case PASS_WORD_BOND: + { + auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_MITM_FLAG; + auth_sec_req_flags = GAP_AUTHEN_BIT_MITM_FLAG; + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + auth_io_cap = GAP_IO_CAP_KEYBOARD_ONLY; + } +#if CENTRAL_MODE + else if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + auth_io_cap = GAP_IO_CAP_DISPLAY_ONLY; + } +#endif + } + break; + default: + break; + } + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enalbe), &auth_sec_req_enalbe); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + gap_set_pairable_mode(); + dataTransInfo.pair_info.authenflag.value = auth_flags; + APP_PRINT_INFO2("sc_flag is %x,mitm_flag is %x", \ + dataTransInfo.pair_info.authenflag.flag.sc_flag, dataTransInfo.pair_info.authenflag.flag.mitm_flag); + ftl_save(&dataTransInfo.pair_info, INFO_PAIR_INFO_OFFSET, 4); +} + + +void ADV_Interval_Set(uint16_t newadvi) +{ + if (dataTransInfo.adv_interval != newadvi) + { + dataTransInfo.adv_interval = newadvi; + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + if (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv stoped: because adv interval update"); + le_adv_stop(); + transferConfigInfo.adv_param_update = true; + } + else + { + uint16_t adv_int_min = newadvi; + uint16_t adv_int_max = newadvi; + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + } + } + dataTransInfo.adv_interval = newadvi; + ftl_save(&dataTransInfo.adv_interval, INFO_ADV_INTERVAL_OFFSET, 4); + } +} + + +bool ADV_Enable_Disable(uint8_t adven) +{ + bool ret = true; + if ((adven == 1) && (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_IDLE)) + { + le_adv_start(); + } + else if ((adven == 0) && (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING)) + { + le_adv_stop(); + } + else + { + ret = false; + } + return ret; +} + + +void Role_Set(uint8_t newrole) +{ + uint8_t oldrole = dataTransInfo.device_mode.role; + if (oldrole != newrole) + { + dataTransInfo.device_mode.role = newrole; + if (oldrole == ROLE_BEACON) + { + os_timer_start(&TimersReset); + //ftl_save(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4); + } + else + { + if (newrole == ROLE_BEACON) + { + os_timer_start(&TimersReset); + //ftl_save(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4); + } + else + { + if (dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + if (bt_datatrans_gap_dev_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + if (dataTransInfo.device_mode.adv_mode) + { + le_adv_start(); + } + } +#if CENTRAL_MODE + else if (bt_datatrans_gap_dev_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + if (dataTransInfo.device_mode.adv_mode) + { + transferConfigInfo.stop_scan_then_adv = true; + } + + le_scan_stop(); + } +#endif + } +#if CENTRAL_MODE + else if (dataTransInfo.device_mode.role == ROLE_CENTRAL && + bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + le_adv_stop(); + } +#endif + } + } + + // write config + ftl_save(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4); + if (ftl_load(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4)) + { + APP_PRINT_ERROR0("ROLE Write err."); + } + else + { + APP_PRINT_INFO1("ROLE xx is %d", dataTransInfo.device_mode.role); + printf("ROLE xx is %d\n\r", dataTransInfo.device_mode.role); + } + } +} + +#if CENTRAL_MODE +void Connect_Device_Num(uint8_t connindex) +{ + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; //6*1.25=7.5ms + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (bt_datatrans_gap_dev_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + le_scan_stop(); + transferConfigInfo.create_connection = true; + transferConfigInfo.connect_by_add = false; + transferConfigInfo.connect_dev_num = connindex; + } + else if (bt_datatrans_gap_dev_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_ERROR0("le_connect"); + printf("le_connect\n\r"); + le_connect(0, DT_DevList[connindex].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)DT_DevList[connindex].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + + os_timer_start(&TimersConnTimeOut); + } +} +#endif + +void Enable_New_ADV_SCANRSP_Data(void) +{ + if (dataTransInfo.device_mode.role == ROLE_BEACON) + { + if (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + le_adv_stop(); + transferConfigInfo.adv_param_update = true; + } + else if (bt_datatrans_gap_dev_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + moduleParam_InitAdvAndScanRspData(); + } + } +} + + +void DataTrans_SendBTFlowResponse(void) +{ + if (transferConfigInfo.bt_buf_free) + { + uint8_t data = 0x01; + server_send_data(CON_ID, bt_datatrans_srv_id, GATT_UUID_CHAR_FLOW_NOTIFY_INDEX, + &data, sizeof(uint8_t), GATT_PDU_TYPE_ANY); + transferConfigInfo.bt_buf_free--; + } +} + +T_APP_RESULT HandleBTReceiveData(uint8_t conn_id, uint16_t wLength, uint8_t *pValue) +{ + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + PTxData pTxData = NULL; + + uint32_t flags; + flags = os_lock(); + pTxData = datatrans_app_queue_out(&txUartDataQueueFree); + os_unlock(flags); + if (pTxData != NULL) + { + // tx_buffer allocate memmory + uint16_t mem_length = wLength + 4 - wLength % 4; + pTxData->tx_buffer = os_mem_alloc(RAM_TYPE_DATA_ON, mem_length); + if (pTxData->tx_buffer != NULL) + { + memcpy(pTxData->tx_buffer, pValue, wLength); + pTxData->length = wLength; + pTxData->is_stack_buf = false; + pTxData->stack_buf_offset = 0; + } + + if (pTxData->tx_buffer != NULL && (pTxData->stack_buf_offset == 0)) + { + APP_PRINT_INFO2("DTS_DATA_NOTIFY: value_size %d, value %b", + pTxData->length, TRACE_BINARY(pTxData->length, pTxData->tx_buffer + pTxData->stack_buf_offset)); + if (os_msg_send(TxMessageQueueHandle, &pTxData, 0) == false) + { + APP_PRINT_INFO0("HandleBTReceiveData:send queue failed\n"); + //gap_buffer_free(pTxData->tx_buffer); + os_mem_free(pTxData->tx_buffer); + pTxData->tx_buffer = NULL; + + uint32_t flags; + flags = os_lock();//enter critical section + datatrans_app_queue_in(&txUartDataQueueFree, pTxData); + os_unlock(flags); //exit critical section + } + + wCause = APP_RESULT_SUCCESS; + + } + else + { + APP_PRINT_INFO0("HandleBTReceiveData: get stack buffer fail\n"); + uint32_t flags; + flags = os_lock();//enter critical section + datatrans_app_queue_in(&txUartDataQueueFree, pTxData); + os_unlock(flags); //exit critical section + } + } + else + { + APP_PRINT_INFO0("HandleBTReceiveData: queue is full\n"); + } + + return wCause; +} + + +void TxHandleTask(void *pParameters) +{ + uint32_t i = 0; + uint8_t *pBuffer = NULL; + PTxData pData = NULL; + + while (true) + { + if (os_msg_recv(TxMessageQueueHandle, &pData, 0xFFFFFFFF) == true) + { + APP_PRINT_INFO1("TxHandleTask: %d", pData->length); + + pBuffer = pData->tx_buffer + pData->stack_buf_offset; + *(pBuffer + pData->length)= '\0'; + //APP_PRINT_INFO2("TxHandle received BT data: value_size %d, value %s",pData->length, TRACE_STRING(pBuffer)); //debug + + //send bt data to uart tx fifo + for (i = 0; i < pData->length; i++) + { + bt_datatrans_uart_tx_char(pBuffer[i]); + } + + + os_mem_free(pData->tx_buffer); + pData->tx_buffer = NULL; + + uint32_t flags; + flags = os_lock();//enter critical section + datatrans_app_queue_in(&txUartDataQueueFree, pData); + os_unlock(flags); //exit critical section + + DataTrans_SendBTFlowResponse(); + + } + else + { + APP_PRINT_INFO0("TxHandleTask: xQueueReceive fail"); + } + } +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.h new file mode 100644 index 00000000..360cbc55 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.h @@ -0,0 +1,42 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file hci_cmd_event.h +* @brief +* @details +* @author parker_xue +* @date 2017-04-21 +* @version v0.2 +********************************************************************************************************* +*/ +//#include "rtl876x.h" + +#ifndef _BT_DATATRANS_AT_HCI_CMD_PROCESS_H_ +#define _BT_DATATRANS_AT_HCI_CMD_PROCESS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +extern void Device_Name_Write(uint8_t *payload, uint16_t payloadlen); +extern void Pair_Mode_Set(uint8_t pairmode); +extern void ADV_Interval_Set(uint16_t newadvi); +extern bool ADV_Enable_Disable(uint8_t adven); +extern void Role_Set(uint8_t newrole); +extern void Connect_Device_Num(uint8_t connindex); +extern void Enable_New_ADV_SCANRSP_Data(void); +extern T_APP_RESULT HandleBTReceiveData(uint8_t conn_id, uint16_t wLength, uint8_t *pValue); +//extern void Dle_Set(uint8_t *p_buf); + +//extern void Set_Tx_Power(uint8_t pwr_index); +//extern void Set_CODED(uint8_t code_index); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.c new file mode 100644 index 00000000..a28bcdd7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.c @@ -0,0 +1,241 @@ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include "bt_datatrans_app_flags.h" +#if CENTRAL_MODE +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "bt_datatrans_central_application.h" +#include "bt_datatrans_multilink_manager.h" +#include "bt_datatrans_client.h" +#include "bt_datatrans_module_param_config.h" +#include "bt_datatrans_at_hci_cmd_process.h" +#include +extern T_CLIENT_ID bt_datatrans_client_id; + +/** + * @brief Callback will be called when data sent from specific client module. + * @param client_id: the ID distinguish which module sent the data. + * @param conn_id: connection ID. + * @param pData: pointer to data. + * @retval T_APP_RESULT + */ +extern uint8_t sendbuffer[255]; + +T_APP_RESULT bt_datatrans_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_datatrans_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + //printf("bt_datatrans_app_client_callback: client_id %d, conn_id %d\n", + // client_id, conn_id); //debug + + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + bt_datatrans_client_start_discovery(conn_id); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + if (dataTransInfo.uuid_info.length == 2) + { + uint16_t service_uuid = (dataTransInfo.uuid_info.uuid[0] << 8) | dataTransInfo.uuid_info.uuid[1]; + if (p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16 == + service_uuid) + { + DataTransLinkTable[conn_id].client_id = bt_datatrans_client_id; + } + } + } + else if (p_client_app_cb_data->cb_content.disc_result_data.result_type == + DISC_RESULT_ALL_SRV_UUID128) + { + if (dataTransInfo.uuid_info.length == 16) + { + if (!memcmp(dataTransInfo.uuid_info.uuid, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid128_disc_data->uuid128, 16)) + { + DataTransLinkTable[conn_id].client_id = bt_datatrans_client_id; + } + } + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + } + else if (client_id == bt_datatrans_client_id) + { + T_DTS_CLIENT_CB_DATA *p_dts_client_cb_data = (T_DTS_CLIENT_CB_DATA *)p_data; + uint16_t value_size; + uint8_t *p_value; + switch (p_dts_client_cb_data->cb_type) + { + case DTS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_dts_client_cb_data->cb_content.disc_state) + { + case DISC_DTS_DONE: + APP_PRINT_INFO0("bt_datatrans_app_client_callback: discover dts procedure done."); + dts_client_set_data_notify(conn_id, true); //after discover all, client send Write Request(set data_notify cccd) + break; + case DISC_DTS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("bt_datatrans_app_client_callback: discover dts request failed."); + break; + default: + break; + } + break; + case DTS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_dts_client_cb_data->cb_content.read_result.type) + { + case DTS_READ_DATA_NOTIFY_CCCD: + if (p_dts_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("DTS_READ_DATA_NOTIFY_CCCD: notify %d", + p_dts_client_cb_data->cb_content.read_result.data.data_notify_cccd); + } + else + { + APP_PRINT_ERROR1("DTS_READ_DATA_NOTIFY_CCCD: failed cause 0x%x", + p_dts_client_cb_data->cb_content.read_result.cause); + }; + break; + case DTS_READ_FLOW: + if (p_dts_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_dts_client_cb_data->cb_content.read_result.data.flow_read.value_size; + p_value = p_dts_client_cb_data->cb_content.read_result.data.flow_read.p_value; + APP_PRINT_INFO2("DTS_READ_FLOW: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("DTS_READ_FLOW: failed cause 0x%x", + p_dts_client_cb_data->cb_content.read_result.cause); + } + break; + case DTS_READ_FLOW_NOTIFY_CCCD: + if (p_dts_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("DTS_READ_FLOW_NOTIFY_CCCD: notify %d", + p_dts_client_cb_data->cb_content.read_result.data.flow_notify_cccd); + } + else + { + APP_PRINT_ERROR1("DTS_READ_FLOW_NOTIFY_CCCD: failed cause 0x%x", + p_dts_client_cb_data->cb_content.read_result.cause); + }; + break; + default: + break; + } + break; + case DTS_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_dts_client_cb_data->cb_content.write_result.type) + { + case DTS_WRITE_DATA: + APP_PRINT_INFO1("DTS_WRITE_DATA: write result 0x%x", + p_dts_client_cb_data->cb_content.write_result.cause); + //printf("DTS_WRITE_DATA: write result 0x%x\r\n", + // p_dts_client_cb_data->cb_content.write_result.cause);//debug + if (IO_Receive.datalen >= MTU_SIZE - 3) //buffer length > MTU size - 3, send immediately + { + if (transferConfigInfo.select_io == UART_AT) + { + Setsendbuffer(MTU_SIZE - 3); + kns_client_write_data_char(CON_ID, MTU_SIZE - 3, sendbuffer, GATT_WRITE_TYPE_CMD); + } + else + { + kns_client_write_data_char(CON_ID, MTU_SIZE - 3, IO_Receive.buf + IO_Receive.ReadOffset, + GATT_WRITE_TYPE_CMD); + IO_Receive.ReadOffset += MTU_SIZE - 3; + IO_Receive.datalen = IO_Receive.datalen - (MTU_SIZE - 3); + } + + } + else if (IO_Receive.datalen > 0) //buffer length < MTU size - 3 + { + if (transferConfigInfo.select_io == UART_AT && transferConfigInfo.uart_idle) + { + uint16_t len = IO_Receive.datalen; + Setsendbuffer(IO_Receive.datalen); + kns_client_write_data_char(CON_ID, len, sendbuffer, GATT_WRITE_TYPE_CMD); + transferConfigInfo.uart_idle = 0; + } + } + break; + case DTS_WRITE_DATA_NOTIFY_CCCD: + APP_PRINT_INFO1("DTS_WRITE_DATA_NOTIFY_CCCD: write result 0x%x", + p_dts_client_cb_data->cb_content.write_result.cause); + dts_client_set_flow_notify(conn_id, true); //after write data_notify cccd, client send Write Request(set flow_ctrl_notify cccd) + break; + case DTS_WRITE_CTRL: + APP_PRINT_INFO1("DTS_WRITE_CTRL: write result 0x%x", + p_dts_client_cb_data->cb_content.write_result.cause); + break; + case DTS_WRITE_FLOW_NOTIFY_CCCD: //complete write flow_ctrl_notify cccd + APP_PRINT_INFO1("DTS_WRITE_FLOW_NOTIFY_CCCD: write result 0x%x", + p_dts_client_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + case DTS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_dts_client_cb_data->cb_content.notif_ind_data.type) + { + case DTS_DATA_NOTIFY: + value_size = p_dts_client_cb_data->cb_content.notif_ind_data.data.value_size; + p_value = p_dts_client_cb_data->cb_content.notif_ind_data.data.p_value; + result = HandleBTReceiveData(conn_id, value_size, p_value); + //APP_PRINT_INFO2("DTS_DATA_NOTIFY(client received data_notify value and then send to uart): value_size %d, value %b", + // value_size, TRACE_BINARY(value_size, p_value)); + //printf("DTS_DATA_NOTIFY: value_size %d\r\n", value_size); //debug + break; + case DTS_FLOW_NOTIFY: + value_size = p_dts_client_cb_data->cb_content.notif_ind_data.data.value_size; + p_value = p_dts_client_cb_data->cb_content.notif_ind_data.data.p_value; + //add it for new feature + APP_PRINT_INFO2("DTS_FLOW_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + default: + break; + } + break; + + default: + break; + } + } + + return result; +} +#endif + +#endif // end of CONFIG_BT_DATATRANS diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.h new file mode 100644 index 00000000..efbc8c2a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.h @@ -0,0 +1,33 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file simple_ble_central_application.h +* @brief simpleBLEMultilink app implementation +* @details simpleBLEMultilink app implementation +* @author jane +* @date 2016-02-18 +* @version v0.1 +* ********************************************************************************************************* +*/ +#if CENTRAL_MODE + +#ifndef _BT_DATATRANS_CENTRAL_APPLICATION_H_ +#define _BT_DATATRANS_CENTRAL_APPLICATION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "profile_client.h" +#include "app_msg.h" + +extern T_APP_RESULT bt_datatrans_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, + void *pData); +#ifdef __cplusplus +} +#endif + +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.c new file mode 100644 index 00000000..b5e4c9d2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.c @@ -0,0 +1,666 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file simple_ble_client.c + * @brief Simple BLE client source file. + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + */ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +/** Add Includes here **/ +#include "trace_app.h" +#include +#include "bt_datatrans_client.h" +#include "bt_datatrans_multilink_manager.h" +#include "bt_datatrans_module_param_config.h" +#include + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +typedef struct +{ + T_DTS_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_DTS_CACHE_LEN]; +} T_DTS_LINK, *P_DTS_LINK; +/** + * @{ Used for CCCD handle discovering in discovery procedure + */ +typedef enum +{ + TRANS_CCCD_DISC_START, + TRANS_CCCD_DISC_DT_WRITE_NOTIFY, + TRANS_CCCD_DISC_DT_FLOW_NOTIFY, + TRANS_CCCD_DISC_END +} TSimpCCCD_DiscState, *PSimpCCCD_DiscState; +/** + * @} + */ + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +/**< Simple BLE client ID. */ +static P_DTS_LINK dts_table; +static uint8_t dts_link_num; +static T_CLIENT_ID dts_client = CLIENT_PROFILE_GENERAL_ID; +/**< Callback used to send data to app from Simple BLE client layer. */ +static P_FUN_GENERAL_APP_CB dts_client_cb = NULL; + + +/** + * @brief Used by application, to start the discovery procedure of ias server. + * @param[in] conn_id connection ID. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +extern uint8_t GATT_UUID128_DATATRANS_PROFILE[]; +bool bt_datatrans_client_start_discovery(uint8_t conn_id) +{ + PROFILE_PRINT_INFO0("dts_client_start_discovery"); + if (conn_id >= dts_link_num) + { + PROFILE_PRINT_ERROR1("kns_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + /* First clear handle cache. */ + memset(&dts_table[conn_id], 0, sizeof(T_DTS_LINK)); + dts_table[conn_id].disc_state = DISC_DTS_START; + if (client_by_uuid128_srv_discovery(conn_id, dts_client, + (uint8_t *)GATT_UUID128_DATATRANS_PROFILE) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + + +/** + * @brief Used by application, to read data from server by using handles. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool dts_client_read_by_handle(uint8_t conn_id, + T_DTS_READ_TYPE read_type) +{ + bool hdl_valid = false; + uint16_t handle; + if (conn_id >= dts_link_num) + { + PROFILE_PRINT_ERROR1("dts_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case DTS_READ_FLOW: + if (dts_table[conn_id].hdl_cache[HDL_DTS_FLOW]) + { + handle = dts_table[conn_id].hdl_cache[HDL_DTS_FLOW]; + hdl_valid = true; + } + break; + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, dts_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("dts_client_read_by_handle: Request fail! Please check!"); + return false; +} +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param[in] conn_id connection ID. + * @param[in] notify 0--disable the notification, 1--enable the notification. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool dts_client_set_data_notify(uint8_t conn_id, bool notify) +{ + if (conn_id >= dts_link_num) + { + PROFILE_PRINT_ERROR1("dts_client_set_v3_notify: failed invalid conn_id %d", conn_id); + return false; + } + + if (dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_NOTIFY_CCCD]) + { + uint16_t handle = dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_NOTIFY_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = notify ? 1 : 0; + if (client_attr_write(conn_id, dts_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("dts_client_set_data_notify: Request fail! Please check!"); + return false; +} + +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param[in] conn_id connection ID. + * @param[in] notify 0--disable the notification, 1--enable the notification. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool dts_client_set_flow_notify(uint8_t conn_id, bool notify) +{ + if (conn_id >= dts_link_num) + { + PROFILE_PRINT_ERROR1("dts_client_set_v3_notify: failed invalid conn_id %d", conn_id); + return false; + } + + if (dts_table[conn_id].hdl_cache[HDL_DTS_FLOW_CCCD]) + { + uint16_t handle = dts_table[conn_id].hdl_cache[HDL_DTS_FLOW_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = notify ? 1 : 0; + if (client_attr_write(conn_id, dts_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("dts_client_set_data_notify: Request fail! Please check!"); + return false; +} + + +/** + * @brief Used by application, to write data of V2 write Characteristic. + * @param[in] conn_id connection ID. + * @param[in] length write data length + * @param[in] p_value point the value to write + * @param[in] type write type. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool kns_client_write_data_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type) +{ + if (conn_id >= dts_link_num) + { + PROFILE_PRINT_ERROR1("dts_client_write_v2_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_WRITE]) + { + uint16_t handle = dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_WRITE]; + if (client_attr_write(conn_id, dts_client, type, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("dts_ble_client_write_v2_char: Request fail! Please check!"); + return false; +} + +static bool dts_client_start_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("dts_client_start_ias_char_discovery"); + start_handle = dts_table[conn_id].hdl_cache[HDL_DTS_SRV_START]; + end_handle = dts_table[conn_id].hdl_cache[HDL_DTS_SRV_END]; + if (client_all_char_discovery(conn_id, dts_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} +static bool dts_client_start_char_descriptor_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + PROFILE_PRINT_INFO0("dts_client_start_char_descriptor_discovery"); + start_handle = dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_NOTIFY]; + end_handle = dts_table[conn_id].hdl_cache[HDL_DTS_SRV_END]; + if (client_all_char_descriptor_discovery(conn_id, dts_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} +/** + * @brief Called by profile client layer, when discover state of discovery procedure changed. + * @param conn_id: connection ID. + * @param discovery_state: current service discovery state. + * @retval None + */ +static void datatrans_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + bool cb_flag = false; + T_DTS_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DTS_CLIENT_CB_TYPE_DISC_STATE; + + APP_PRINT_INFO1("datatrans_client_discover_state_cb: discovery_state %d", discovery_state); + + if (dts_table[conn_id].disc_state == DISC_DTS_START) + { + uint16_t *hdl_cache; + hdl_cache = dts_table[conn_id].hdl_cache; + + switch (discovery_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((hdl_cache[HDL_DTS_SRV_START] != 0) + || (hdl_cache[HDL_DTS_SRV_END] != 0)) + { + if (dts_client_start_char_discovery(conn_id) == false) + { + dts_table[conn_id].disc_state = DISC_DTS_FAILED; + cb_flag = true; + } + } + /* No Ias BLE service handle found. Discover procedure complete. */ + else + { + dts_table[conn_id].disc_state = DISC_DTS_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + if (hdl_cache[HDL_DTS_FLOW] != 0) + { + if (dts_client_start_char_descriptor_discovery(conn_id) == false) + { + dts_table[conn_id].disc_state = DISC_DTS_FAILED; + cb_flag = true; + } + } + else + { + dts_table[conn_id].disc_state = DISC_DTS_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + dts_table[conn_id].disc_state = DISC_DTS_DONE; + cb_flag = true; + break; + case DISC_STATE_FAILED: + dts_table[conn_id].disc_state = DISC_DTS_DONE; + cb_flag = true; + break; + default: + APP_PRINT_ERROR0("kns_handle_discover_state: Invalid Discovery State!"); + break; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && dts_client_cb) + { + cb_data.cb_content.disc_state = dts_table[conn_id].disc_state; + (*dts_client_cb)(dts_client, conn_id, &cb_data); + } + return; +} +/** + * @brief Called by profile client layer, when discover result fetched. + * @param conn_id: connection ID. + * @param result_type: indicate which type of value discovered in service discovery procedure. + * @param result_data: value discovered. + * @retval None + */ +static void datatrans_client_discover_result_cb(uint8_t conn_id, + T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + APP_PRINT_INFO1("dts_client_discover_result_cb: result_type %d", result_type); + if (dts_table[conn_id].disc_state == DISC_DTS_START) + { + uint16_t handle; + uint16_t *hdl_cache; + hdl_cache = dts_table[conn_id].hdl_cache; + + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + hdl_cache[HDL_DTS_SRV_START] = result_data.p_srv_disc_data->att_handle; + hdl_cache[HDL_DTS_SRV_END] = result_data.p_srv_disc_data->end_group_handle; + break; + case DISC_RESULT_CHAR_UUID128: +// handle = result_data.p_char_uuid128_disc_data->value_handle; +// if (!memcmp(result_data.p_char_uuid128_disc_data->uuid128, GATT_UUID128_PARAM, 16)) +// { +// hdl_cache[HDL_KNS_PARA] = handle; +// } +// else if (!memcmp(result_data.p_char_uuid128_disc_data->uuid128, GATT_UUID128_KEY, 16)) +// { +// hdl_cache[HDL_KNS_NOTIFY_KEY] = handle; +// } + break; + + case DISC_RESULT_CHAR_UUID16: + handle = result_data.p_char_uuid16_disc_data->value_handle; + if (result_data.p_char_uuid16_disc_data->uuid16 == GATT_UUID_CHAR_DATA) + { + dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_WRITE] = handle; + //dts_table[conn_id].properties = result_data.p_char_uuid16_disc_data->properties; + } + else if (result_data.p_char_uuid16_disc_data->uuid16 == GATT_UUID_CHAR_DATA_NOTIFY) + { + dts_table[conn_id].hdl_cache[HDL_DTS_VALUE_NOTIFY] = handle; + //bas_table[conn_id].properties = result_data.p_char_uuid16_disc_data->properties; + } + else if (result_data.p_char_uuid16_disc_data->uuid16 == GATT_UUID_FLOW_CTRL_NOTIFY) + { + dts_table[conn_id].hdl_cache[HDL_DTS_FLOW] = handle; + //bas_table[conn_id].properties = result_data.p_char_uuid16_disc_data->properties; + } + break; + + case DISC_RESULT_CHAR_DESC_UUID16: + /* When use client_all_char_descriptor_discovery. */ + if (result_data.p_char_desc_uuid16_disc_data->uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) + { + handle = result_data.p_char_desc_uuid16_disc_data->handle; + + if ((handle > hdl_cache[HDL_DTS_VALUE_NOTIFY]) + && (hdl_cache[HDL_DTS_VALUE_NOTIFY_CCCD] == 0)) + { + hdl_cache[HDL_DTS_VALUE_NOTIFY_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_DTS_FLOW]) + && (hdl_cache[HDL_DTS_FLOW_CCCD] == 0)) + { + hdl_cache[HDL_DTS_FLOW_CCCD] = handle; + } + } + break; + + default: + APP_PRINT_ERROR0("kns_handle_discover_result: Invalid Discovery Result Type!"); + break; + } + } + + return; +} + +/** + * @brief Called by profile client layer, when read request responsed. + * @param conn_id: connection ID. + * @param result: read request from peer device success or not. + * @param handle: handle of the value in read response. + * @param value_size: size of the value in read response. + * @param pValue: pointer to the value in read response. + * @retval None + */ +static void datatrans_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_DTS_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = dts_table[conn_id].hdl_cache; + + cb_data.cb_type = DTS_CLIENT_CB_TYPE_READ_RESULT; + + APP_PRINT_INFO2("dts_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + + if (handle == hdl_cache[HDL_DTS_FLOW]) + { + cb_data.cb_content.read_result.type = DTS_READ_FLOW; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.flow_read.p_value = p_value; + cb_data.cb_content.read_result.data.flow_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.flow_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_DTS_VALUE_NOTIFY_CCCD]) + { + cb_data.cb_content.read_result.type = DTS_READ_DATA_NOTIFY_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + PROFILE_PRINT_ERROR1("dts_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + cb_data.cb_content.read_result.data.data_notify_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.data_notify_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_DTS_FLOW_CCCD]) + { + cb_data.cb_content.read_result.type = DTS_READ_FLOW_NOTIFY_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + PROFILE_PRINT_ERROR1("dts_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + cb_data.cb_content.read_result.data.flow_notify_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.flow_notify_cccd = false; + } + } + } + else + { + return; + } + /* Inform application the read result. */ + if (dts_client_cb) + { + (*dts_client_cb)(dts_client, conn_id, &cb_data); + } + + return; +} + +/** + * @brief Called by profile client layer, when write request complete. + * @param conn_id: connection ID. + * @param result: write request send success or not. + * @retval None + */ +static void datatrans_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_DTS_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = dts_table[conn_id].hdl_cache; + cb_data.cb_type = DTS_CLIENT_CB_TYPE_WRITE_RESULT; + + PROFILE_PRINT_INFO2("dts_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); + //APP_PRINT_INFO2("dts_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); //debug + + cb_data.cb_content.write_result.cause = cause; + + if (handle == hdl_cache[HDL_DTS_VALUE_WRITE]) + { + cb_data.cb_content.write_result.type = DTS_WRITE_DATA; + } + else if (handle == hdl_cache[HDL_DTS_FLOW]) + { + cb_data.cb_content.write_result.type = DTS_WRITE_CTRL; + } + else if (handle == hdl_cache[HDL_DTS_VALUE_NOTIFY_CCCD]) + { + cb_data.cb_content.write_result.type = DTS_WRITE_DATA_NOTIFY_CCCD; + } + else if (handle == hdl_cache[HDL_DTS_FLOW_CCCD]) + { + cb_data.cb_content.write_result.type = DTS_WRITE_FLOW_NOTIFY_CCCD; + } + else + { + return; + } + /* Inform application the write result. */ + if (dts_client_cb) + { + (*dts_client_cb)(dts_client, conn_id, &cb_data); + } + + return; +} + +/** + * @brief Called by profile client layer, when notification or indication arrived. + * @param conn_id: connection ID. + * @param handle: handle of the value in received data. + * @param value_size: size of the value in received data. + * @param pValue: pointer to the value in received data. + * @retval APP_RESULT_SUCCESS--procedure OK. + * other--procedure exception. + */ +static T_APP_RESULT datatrans_client_notif_ind_result_cb(uint8_t conn_id, bool notify, + uint16_t handle, + uint16_t value_size, uint8_t *p_value) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + T_DTS_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = dts_table[conn_id].hdl_cache; + APP_PRINT_INFO1("datatrans_client_notif_ind_result_cb: handle 0x%x", handle); + cb_data.cb_type = DTS_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + + if (handle == hdl_cache[HDL_DTS_VALUE_NOTIFY]) + { + cb_data.cb_content.notif_ind_data.type = DTS_DATA_NOTIFY; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_DTS_FLOW]) + { + cb_data.cb_content.notif_ind_data.type = DTS_FLOW_NOTIFY; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else + { + return app_result; + } + /* Inform application the notif/ind result. */ + if (dts_client_cb) + { + app_result = (*dts_client_cb)(dts_client, conn_id, &cb_data); + } + + return app_result; +} + +/** + * @brief Called by profile client layer, when link disconnected. + * NOTE--we should reset some state when disconnected. + * @param conn_id: connection ID. + * @retval None + */ +static void datatrans_client_disconnect_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("dts_client_disconnect_cb."); + if (conn_id >= dts_link_num) + { + PROFILE_PRINT_ERROR1("dts_client_disconnect_cb: failed invalid conn_id %d", conn_id); + return; + } + memset(&dts_table[conn_id], 0, sizeof(T_DTS_LINK)); + return; +} + +/** + * @brief Simple BLE Client Callbacks. +*/ +const T_FUN_CLIENT_CBS dts_client_cbs = +{ + datatrans_client_discover_state_cb, //!< Discovery State callback function pointer + datatrans_client_discover_result_cb, //!< Discovery result callback function pointer + datatrans_client_read_result_cb, //!< Read response callback function pointer + datatrans_client_write_result_cb, //!< Write result callback function pointer + datatrans_client_notif_ind_result_cb, //!< Notify Indicate callback function pointer + datatrans_client_disconnect_cb //!< Link disconnection callback function pointer +}; + +/** + * @brief add Simple BLE client to application. + * @param app_cb: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID datatrans_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + + uint16_t size; + if (link_num > DTS_MAX_LINKS) + { + PROFILE_PRINT_ERROR1("datatrans_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&dts_client, &dts_client_cbs)) + { + dts_client = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("datatrans_add_client failed"); + return dts_client; + } + APP_PRINT_INFO1("datatrans_add_client: dts_client %d", dts_client); + + /* register callback for profile to inform application that some events happened. */ + dts_client_cb = app_cb; + dts_link_num = link_num; + size = dts_link_num * sizeof(T_DTS_LINK); + dts_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + return dts_client; +} + +void bt_datatrans_delete_client(void) +{ + if (dts_table != NULL) { + os_mem_free(dts_table); + dts_table = NULL; + } +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.h new file mode 100644 index 00000000..ce8f2bc3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.h @@ -0,0 +1,202 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file simple_ble_client.h + * @brief Head file for using Simple BLE Client. + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _BT_DATATRANS_CLIENT_H_ +#define _BT_DATATRANS_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_client.h" + + +/** @addtogroup DATATRANS SIMP + * @{ + */ + +/** @defgroup DATATRANS_Client DATATRANS Client + * @brief DATATRANS Client + * @{ + */ + +/** @defgroup DATATRANS_Client_Exported_Types DATATRANS Client Exported Types + * @brief types that other.c files may use all defined here + * @{ + */ +/** @defgroup DATATRANS_UUIDs DATATRANS UUIDs + * @brief DATATRANS Profile UUID definitions + * @{ + */ +#define GATT_UUID_CHAR_DATA 0xFFE1 +#define GATT_UUID_CHAR_DATA_NOTIFY 0xFFE2 +#define GATT_UUID_FLOW_CTRL_NOTIFY 0xFFE3 +/** @} End of DATATRANS_UUIDs */ + +#define GATT_UUID_GAP 0x1800 + +#define DTS_MAX_LINKS 1 + +/** @defgroup T_TransClientHandleType T_TransClientHandleType + * @{ Handle cache for intrested UUIDs + */ +typedef enum +{ + HDL_GAP_SRV_START, // start handle of gap service + HDL_GAP_SRV_END, // end handle of gap service + HDL_GAP_DEVICE_NAME, // device name value handle + HDL_GAP_APPEARANCE, // appearance value handle + HDL_DTS_SRV_START, // start handle of datatrans service + HDL_DTS_SRV_END, // end handle of datatrans service + HDL_DTS_VALUE_WRITE, // data_write value handle + HDL_DTS_VALUE_NOTIFY, // V1_data_notify value handle + HDL_DTS_VALUE_NOTIFY_CCCD, // v1_data_notify cccd handle + HDL_DTS_FLOW, // v2_flow_ctrl value handle + HDL_DTS_FLOW_CCCD, // v2_flow_ctrl cccd handle + HDL_DTS_CACHE_LEN +} T_KNS_HANDLE_TYPE; +/** End of T_TransClientHandleType * @} */ + +/** @defgroup T_TransClientDiscState T_TransClientDiscState + * @{ used to inform app the discovery procedure + */ +typedef enum +{ + DISC_DTS_IDLE, + DISC_DTS_START, + DISC_DTS_DONE, + DISC_DTS_FAILED +} T_DTS_DISC_STATE; +/** End of T_TransClientDiscState + * @} + */ + + +/** @brief kns client read type*/ +typedef enum +{ + DTS_READ_DATA_NOTIFY_CCCD, + DTS_READ_FLOW, + DTS_READ_FLOW_NOTIFY_CCCD, +} T_DTS_READ_TYPE; + +/** @brief KNS client read value*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_DTS_READ_VALUE; + +/** @brief KNS client read data*/ +typedef union +{ + T_DTS_READ_VALUE flow_read; + bool data_notify_cccd; + bool flow_notify_cccd; +} T_DTS_READ_DATA; + +/** @brief KNS client read result*/ +typedef struct +{ + T_DTS_READ_TYPE type; + T_DTS_READ_DATA data; + uint16_t cause; +} T_DTS_READ_RESULT; + + +/** @brief KNS client write type*/ +typedef enum +{ + DTS_WRITE_DATA, // data write + DTS_WRITE_DATA_NOTIFY_CCCD, // data_notify cccd write + DTS_WRITE_CTRL, // flow_ctrl_notify value(r/w/notify) write + DTS_WRITE_FLOW_NOTIFY_CCCD, // flow_ctrl_notify cccd write +} T_DTS_WRTIE_TYPE; + +/** @brief KNS client write result*/ +typedef struct +{ + T_DTS_WRTIE_TYPE type; + uint16_t cause; +} T_DTS_WRITE_RESULT; + +/** @brief KNS client notif/ind receive type*/ +typedef enum +{ + DTS_DATA_NOTIFY, + DTS_FLOW_NOTIFY, +} T_DTS_NOTIF_IND_TYPE; + +/** @brief KNS client notif/ind receive data*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_DTS_NOTIF_IND_VALUE; + +/** @brief KNS client notif/ind receive content*/ +typedef struct +{ + T_DTS_NOTIF_IND_TYPE type; + T_DTS_NOTIF_IND_VALUE data; +} T_DTS_NOTIF_IND_DATA; + +/** @brief KNS client callback type*/ +typedef enum +{ + DTS_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + DTS_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + DTS_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + DTS_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + DTS_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_DTS_CLIENT_CB_TYPE; + +/** @brief KNS client callback content*/ +typedef union +{ + T_DTS_DISC_STATE disc_state; + T_DTS_READ_RESULT read_result; + T_DTS_WRITE_RESULT write_result; + T_DTS_NOTIF_IND_DATA notif_ind_data; +} T_DTS_CLIENT_CB_CONTENT; + +/** @brief KNS client callback data*/ +typedef struct +{ + T_DTS_CLIENT_CB_TYPE cb_type; + T_DTS_CLIENT_CB_CONTENT cb_content; +} T_DTS_CLIENT_CB_DATA; +/** End of KNS_Client_Exported_Types * @} */ + + +extern T_CLIENT_ID datatrans_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num); +extern void bt_datatrans_delete_client(void); +extern bool bt_datatrans_client_start_discovery(uint8_t conn_id); +extern bool dts_client_set_data_notify(uint8_t conn_id, bool notify); +extern bool dts_client_set_flow_notify(uint8_t conn_id, bool notify); +extern bool kns_client_write_data_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type); +extern bool dts_client_read_by_handle(uint8_t conn_id, T_DTS_READ_TYPE read_type); +/** @} End of DataTrans_Client_Exported_Functions */ + +/** @} End of TRANS_Client */ + +/** @} End of Trans */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _DATATRANS_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_main.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_main.c new file mode 100644 index 00000000..abb8586f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_main.c @@ -0,0 +1,341 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bt_datatrans_app_flags.h" +#include "bt_datatrans_uart.h" +#include "bt_datatrans_module_param_config.h" +#include "bt_datatrans_at_hci_cmd_process.h" +#include "gap_config.h" +#include "os_timer.h" +#include "bt_datatrans_profile.h" +#if CENTRAL_MODE +#include "bt_datatrans_multilink_manager.h" +#include "bt_datatrans_client.h" +#include "profile_client.h" +#include "bt_datatrans_central_application.h" +#endif +#include "trace_uart.h" +#include +#include "wifi_constants.h" +#include +#include "rtk_coex.h" +#include "platform_stdlib.h" +#include + +/** @defgroup PERIPH_DEMO_MAIN Peripheral Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default Maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + +/**< Default scan interval (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_INTERVAL 0x10 +/**< Default scan window (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_WINDOW 0x10 +/*============================================================================* + * Variables + *============================================================================*/ + +T_SERVER_ID bt_datatrans_srv_id; +#if CENTRAL_MODE +T_CLIENT_ID bt_datatrans_client_id; +#endif + +transfer_info dataTransInfo; +config_info transferConfigInfo; + +extern void datatrans_send_msg_to_app(T_IO_MSG *p_msg); +extern T_GAP_CONN_STATE bt_datatrans_gap_conn_state; +extern T_GAP_DEV_STATE bt_datatrans_gap_dev_state; +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void bt_datatrans_bt_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_DATATRANS_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_DATATRANS_APP_MAX_LINKS); +} + +void bt_datatrans_app_le_gap_init(void) +{ + //device name and device appearance + uint8_t gap_device_name[GAP_DEVICE_NAME_LEN] = DEFAULT_DEVICE_NAME; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = true; + + //advertising parameters + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + if (dataTransInfo.device_mode.role == ROLE_BEACON) + { + adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND; + } + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = dataTransInfo.adv_interval; + uint16_t adv_int_max = adv_int_min; + + //scan patameters + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + //GAP Bond Manager parameters + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = dataTransInfo.pair_info.authenflag.value; + uint8_t auth_io_cap = dataTransInfo.pair_info.authen_iocap; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = true; + uint32_t auth_fix_passkey = dataTransInfo.pincode; + uint8_t auth_sec_req_enalbe = dataTransInfo.pair_info.auto_security_req; + uint16_t auth_sec_req_flags = dataTransInfo.pair_info.authenflag.value; + + + if (dataTransInfo.devicename_info.length <= 15) + { + memcpy(gap_device_name, dataTransInfo.devicename_info.device_name, + dataTransInfo.devicename_info.length); + } + if (dataTransInfo.device_mode.advtype == GAP_ADTYPE_ADV_HDC_DIRECT_IND || + dataTransInfo.device_mode.advtype == GAP_ADTYPE_ADV_LDC_DIRECT_IND) + { + //for fast pair + //memcpy(adv_direct_addr, datatrans_efuse.beacon_adv_direct_add, GAP_BD_ADDR_LEN); + } + + if (transferConfigInfo.select_io != UART_AT) //HCI CMD mode, fix passkey false + { + auth_use_fix_passkey = false; + } + else //AT CMD mode, set pairing config + { + auth_flags = GAP_AUTHEN_BIT_NONE; + auth_sec_req_enalbe = true; + auth_sec_req_flags = GAP_AUTHEN_BIT_NONE; + + switch (dataTransInfo.pair_info.pair_mode) + { + case NO_PASS_WORD: + { + auth_sec_req_enalbe = false; + } + break; + case JUST_WORK: + break; + case PASS_WORD: + { + auth_flags = GAP_AUTHEN_BIT_MITM_FLAG; + auth_sec_req_flags = GAP_AUTHEN_BIT_MITM_FLAG; + auth_io_cap = GAP_IO_CAP_DISPLAY_ONLY; + } + break; + case PASS_WORD_BOND: + { + auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_MITM_FLAG; + auth_sec_req_flags = GAP_AUTHEN_BIT_MITM_FLAG; + auth_io_cap = GAP_IO_CAP_DISPLAY_ONLY; + } + break; + default: + break; + } + } + + //Set device name and device appearance + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, gap_device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + //Set advertising parameters + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + moduleParam_InitAdvAndScanRspData(); + + // Set scan parameters + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + + // Setup the GAP Bond Manager + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enalbe), &auth_sec_req_enalbe); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + + /* register gap message callback */ + le_register_app_cb(bt_datatrans_app_gap_callback); +} + + +/** + * @brief Add GATT services and register callbacks + * @return void + */ + +void bt_datatrans_app_le_profile_init(void) +{ + server_init(1); + bt_datatrans_srv_id = Datatrans_AddService((void*)bt_datatrans_app_profile_callback); + server_register_app_cb(bt_datatrans_app_profile_callback); + +#if CENTRAL_MODE + client_init(1); + bt_datatrans_client_id = datatrans_add_client(bt_datatrans_app_client_callback, BT_DATATRANS_APP_MAX_LINKS); + client_register_general_client_cb(bt_datatrans_app_client_callback); +#endif +} + + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void bt_datatrans_task_init(void) +{ + DataTransApplicationInit(); + bt_datatrans_uart_task_init(); + bt_datatrans_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_datatrans_app_main(void) +{ + bt_trace_init(); + bt_datatrans_bt_stack_config_init(); + bte_init(); + le_gap_init(BT_DATATRANS_APP_MAX_LINKS); + readconfig(); + bt_datatrans_app_le_gap_init(); + if (dataTransInfo.device_mode.role != ROLE_BEACON) + { + bt_datatrans_app_le_profile_init(); + } + bt_datatrans_task_init(); + + return 0; +} +/** @} */ /* End of group PERIPH_DEMO_MAIN */ + +int bt_datatrans_app_init(void) +{ + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BT DATATRANS is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT Datatrans]BT Stack already on\n\r"); + return 0; + } + else + bt_datatrans_app_main(); + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern bool bt_trace_uninit(void); +void bt_datatrans_app_deinit(void) +{ + bt_datatrans_app_task_deinit(); + DataTransApplicationDeinit(); + bt_datatrans_uart_task_deinit(); + + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Datatrans]BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + bt_datatrans_delete_client(); + memset(&bt_datatrans_gap_dev_state, 0, sizeof(T_GAP_DEV_STATE)); + printf("[BT Datatrans]BT Stack deinitalized\n\r"); + } +#endif +} + +#endif //end: #if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.c new file mode 100644 index 00000000..1d803952 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.c @@ -0,0 +1,545 @@ +enum { __FILE_NUM__ = 0 }; + +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file module_param_config.c +* @brief +* @details +* @author jane +* @date 2015-03-19 +* @version v0.1 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include +#include "bt_datatrans_module_param_config.h" +#include "gap_conn_le.h" +#include +#include +#include +#include +#include +#include "os_timer.h" +#include "bt_datatrans_uart.h" +#include "ftl_app.h" +#include +#include "sys_api.h" + +uint16_t MTU_SIZE = 23; +uint8_t BT_Credits = 10; +uint8_t CON_ID = 0; + +const uint16_t defaultNameLength = 7; +const char defaultName[7] = {'R', 'e', 'a', 'l', 't', 'e', 'k'}; + +const uint8_t default_service_uuid[16] = {0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xE0, 0x00, 0x00}; +const uint16_t default_service_uuid_len = 16; + +const uint16_t default_connection_interval = 0x06;//6*1.25 = 7.5ms +const uint16_t default_slave_lantency = 0; +const uint16_t default_supervision_timeout = 160;//160*10 = 1.6s +const uint16_t default_adv_interval = 320; +const uint16_t default_wake_delay = 200; //default wake delay 200ms; +const uint32_t defaultPin = 123456; + +const uint16_t default_write_uuid = 0xFFE1; +const uint16_t default_notify_uuid = 0xFFE2; +const uint16_t default_flow_uuid = 0xFFE3; + + + +const uint32_t defaultbaudrate = 115200; +const uint8_t default_adv_mode = 1; +const uint8_t default_uart_flow = 0; +const uint8_t default_bt_flow = 0; +const uint8_t default_gap_role = 0xA0; +const uint8_t default_pair = 0; +const uint8_t default_tx_power = 0; +const uint8_t default_rom_version = 0; +const uint8_t default_patch_version = 0; + +extern T_GAP_CONN_STATE bt_datatrans_gap_conn_state; + + +ReceiveBufStruct IO_Receive; + +uint32_t datatrans_efuse_failed_addr = 0; + +//T_DATATRANS_KEY_INFO g_ble_key_info; + +void *TimersUartConfigChange; +void *TimersReset; +void *TimersConnTimeOut; +//void *TimersEnterLowPower; +void *TimersConnParamUpdate; +//void *TimersSwitchToHCI; + + +PBT_UART_BUF g_AppBufCB; +TBT_UART_BUF g_TappbufCB; +QUEUE_T txUartDataQueueFree; +void *TxMessageQueueHandle; +void *TxTaskHandle; +void *DataTrans_Semaphore; + + +#define DT_BEACON_EFUSE_SIZE 44 + +#define DEFAULT_BAUD BAUD_115200 + +#define TX_TASK_PRIORITY 1 /* Task priorities. */ +#define TX_TASK_STACK_SIZE 256 * 4 + + +#define ADV_LENGTH_INDEX 21 +#define ADV_REMOTE_NAME_INDEX 23 +#define ADV_DATA_FIX_DATA_LENGTH 23 +#define SCAN_RSP_LENGTH_START_INDEX 0 +#define SCAN_RSP_LOCAL_NAME_START_INDEX 2 +#define SCAN_DATA_FIX_DATA_LENGTH 2 + + +// GAP - SCAN RSP data (max size = 31 bytes) +#define DT_SCAN_RSP_LENGTH 9 +uint8_t DT_SCAN_RSP_DATA[31] = +{ + 0x08, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'R', 'e', 'a', 'l', 't', 'e', 'k' /* Default local name */ + +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +#define DT_ADV_LENGTH 21 +uint8_t DT_ADV_DATA[31] = +{ + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x11, + GAP_ADTYPE_128BIT_COMPLETE, + 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xE0, 0x00, 0x00, /* Service UUID */ +}; + + +void datatrans_setdefault(void) +{ + dataTransInfo.device_mode.advtype = GAP_ADTYPE_ADV_IND; + dataTransInfo.device_mode.adv_mode = AUTO_ADV; + dataTransInfo.device_mode.baudrateidx = DEFAULT_BAUD; + dataTransInfo.device_mode.bt_flowctrl = false; + dataTransInfo.device_mode.role = ROLE_PERIPHERAL; + dataTransInfo.device_mode.sleep_mode = true; + dataTransInfo.device_mode.uart_flowctrl = false; + dataTransInfo.device_mode.tx_power = TXP_0DBM; + dataTransInfo.device_mode.code_mode = 0; + ftl_save(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4); + + dataTransInfo.devicename_info.length = DEFAULT_DEVICE_NAME_LEN;//false + memcpy(dataTransInfo.devicename_info.device_name, DEFAULT_DEVICE_NAME, DEFAULT_DEVICE_NAME_LEN); + ftl_save(&dataTransInfo.devicename_info, INFO_DEVICE_NAME_OFFSET, 16); + + dataTransInfo.uuid_info.length = default_service_uuid_len;//false + memcpy(dataTransInfo.uuid_info.uuid, default_service_uuid, dataTransInfo.uuid_info.length); + ftl_save(&dataTransInfo.uuid_info, INFO_UUID_OFFSET, 20); + + //local bda +// if(ftl_load(&dataTransInfo.local_bda, INFO_ADV_DATA_OFFSET, 8)) +// { +// dataTransInfo.local_bda.length = default_service_uuid_len;//false +// memcpy(dataTransInfo.local_bda, default_service_uuid,dataTransInfo.uuid_info.length); +// } + //DBG_DIRECT("local_bda%x:%x:%x:%x:%x:%x",dataTransInfo.local_bda.bda[0],dataTransInfo.local_bda.bda[1],dataTransInfo.local_bda.bda[2], + // dataTransInfo.local_bda.bda[3],dataTransInfo.local_bda.bda[4],dataTransInfo.local_bda.bda[5]); + + + dataTransInfo.advdata.length = DT_ADV_LENGTH; + memcpy(dataTransInfo.advdata.adv, DT_ADV_DATA, DT_ADV_LENGTH); + ftl_save(&dataTransInfo.advdata, INFO_ADV_DATA_OFFSET, 32); + + dataTransInfo.scanrspdata.length = DT_SCAN_RSP_LENGTH; + memcpy(dataTransInfo.scanrspdata.adv, DT_SCAN_RSP_DATA, DT_SCAN_RSP_LENGTH); + ftl_save(&dataTransInfo.scanrspdata, INFO_RSP_DATA_OFFSET, 32); + + dataTransInfo.char_uuid.write_uuid = default_write_uuid;//false + dataTransInfo.char_uuid.notify_uuid = default_notify_uuid; + dataTransInfo.char_uuid.flow_uuid = default_flow_uuid; + ftl_save(&dataTransInfo.char_uuid, INFO_CHAR_UUID_OFFSET, 8); + + dataTransInfo.connection_para.interval_min = default_connection_interval; + dataTransInfo.connection_para.interval_max = default_connection_interval; + dataTransInfo.connection_para.slave_lantency = default_slave_lantency; + dataTransInfo.connection_para.supervision_timeout = default_supervision_timeout; + //load connection parameter + ftl_save(&dataTransInfo.connection_para, INFO_CON_PARA_OFFSET, 8); + + dataTransInfo.adv_interval = default_adv_interval; + dataTransInfo.wake_delay = default_wake_delay; + ftl_save(&dataTransInfo.adv_interval, INFO_ADV_INTERVAL_OFFSET, 4); + + dataTransInfo.pincode = defaultPin; + ftl_save(&dataTransInfo.pincode, INFO_PINCODE_OFFSET, 4); + + dataTransInfo.pair_info.authenflag.value = GAP_AUTHEN_BIT_NONE; + dataTransInfo.pair_info.authen_iocap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + dataTransInfo.pair_info.auto_security_req = false; + dataTransInfo.pair_info.paired_flag = false; + dataTransInfo.pair_info.pair_mode = NO_PASS_WORD; + ftl_save(&dataTransInfo.pair_info, INFO_PAIR_INFO_OFFSET, 4); + + transferConfigInfo.baudrate = 115200; + //read version +// transferConfigInfo.app_version = 0x1111; +// transferConfigInfo.patch_version = 0x2222222; + transferConfigInfo.adv_param_update = false; + transferConfigInfo.stop_scan_then_adv = false; + //transferConfigInfo.tx_power_upd = false; +} +void readconfig(void) +{ + //load mode + if (ftl_load(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4)) + { + dataTransInfo.device_mode.advtype = GAP_ADTYPE_ADV_IND; + dataTransInfo.device_mode.adv_mode = AUTO_ADV; + dataTransInfo.device_mode.baudrateidx = DEFAULT_BAUD; + dataTransInfo.device_mode.bt_flowctrl = false; + dataTransInfo.device_mode.role = ROLE_PERIPHERAL; + dataTransInfo.device_mode.sleep_mode = true; + dataTransInfo.device_mode.uart_flowctrl = false; + dataTransInfo.device_mode.tx_power = TXP_0DBM; + dataTransInfo.device_mode.code_mode = 0; + } + + switch (dataTransInfo.device_mode.baudrateidx) + { + case BAUD_2400: + transferConfigInfo.baudrate = 2400; + break; + case BAUD_4800: + transferConfigInfo.baudrate = 4800; + break; + case BAUD_9600: + transferConfigInfo.baudrate = 9600; + break; + case BAUD_19200: + transferConfigInfo.baudrate = 19200; + break; + case BAUD_38400: + transferConfigInfo.baudrate = 38400; + break; + case BAUD_57600: + transferConfigInfo.baudrate = 57600; + break; + case BAUD_115200: + transferConfigInfo.baudrate = 115200; + break; + case BAUD_921600: + transferConfigInfo.baudrate = 921600; + break; + case BAUD_2000000: + transferConfigInfo.baudrate = 2000000; + break; + default: + transferConfigInfo.baudrate = 115200; + break; + } + + //load device name + if (ftl_load(&dataTransInfo.devicename_info, INFO_DEVICE_NAME_OFFSET, 16)) + { + dataTransInfo.devicename_info.length = DEFAULT_DEVICE_NAME_LEN; + memcpy(dataTransInfo.devicename_info.device_name, DEFAULT_DEVICE_NAME, DEFAULT_DEVICE_NAME_LEN); + ftl_save(&dataTransInfo.devicename_info, INFO_DEVICE_NAME_OFFSET, 16); + } + + //load uuid + if (ftl_load(&dataTransInfo.uuid_info, INFO_UUID_OFFSET, 20)) + { + dataTransInfo.uuid_info.length = default_service_uuid_len;//false + memcpy(dataTransInfo.uuid_info.uuid, default_service_uuid, dataTransInfo.uuid_info.length); + } + + //load bda + if (ftl_load(&dataTransInfo.local_bda, INFO_ADV_DATA_OFFSET, 8)) + { +// dataTransInfo.uuid_info.length = default_service_uuid_len;//false +// memcpy(dataTransInfo.uuid_info.uuid, default_service_uuid,dataTransInfo.uuid_info.length); + } + //DBG_DIRECT("local_bda%x:%x:%x:%x:%x:%x",dataTransInfo.local_bda.bda[0],dataTransInfo.local_bda.bda[1],dataTransInfo.local_bda.bda[2], + // dataTransInfo.local_bda.bda[3],dataTransInfo.local_bda.bda[4],dataTransInfo.local_bda.bda[5]); + + //load adv data + if (ftl_load(&dataTransInfo.advdata, INFO_ADV_DATA_OFFSET, 32)) + { + dataTransInfo.advdata.length = DT_ADV_LENGTH;//false + memcpy(dataTransInfo.advdata.adv, DT_ADV_DATA, DT_ADV_LENGTH); + } + //DBG_DIRECT("DT_ADV_LENGTH %d",dataTransInfo.advdata.length); + + //load scan rsp data + if (ftl_load(&dataTransInfo.scanrspdata, INFO_RSP_DATA_OFFSET, 32)) + { + dataTransInfo.scanrspdata.length = DT_SCAN_RSP_LENGTH;//false + memcpy(dataTransInfo.scanrspdata.adv, DT_SCAN_RSP_DATA, DT_SCAN_RSP_LENGTH); + } + //DBG_DIRECT("DT_SCAN_RSP_LENGTH %d",dataTransInfo.advdata.length); + + //load char uuid + if (ftl_load(&dataTransInfo.char_uuid, INFO_CHAR_UUID_OFFSET, 8)) + { + dataTransInfo.char_uuid.write_uuid = default_write_uuid;//false + dataTransInfo.char_uuid.notify_uuid = default_notify_uuid; + dataTransInfo.char_uuid.flow_uuid = default_flow_uuid; + } + //DBG_DIRECT("write_uuid %x;notify_uuid %x;flow_uuid %x",dataTransInfo.char_uuid.write_uuid,dataTransInfo.char_uuid.notify_uuid,dataTransInfo.char_uuid.flow_uuid); + + //load connection parameter + if (ftl_load(&dataTransInfo.connection_para, INFO_CON_PARA_OFFSET, 8)) + { + dataTransInfo.connection_para.interval_min = default_connection_interval; + dataTransInfo.connection_para.interval_max = default_connection_interval; + dataTransInfo.connection_para.slave_lantency = default_slave_lantency; + dataTransInfo.connection_para.supervision_timeout = default_supervision_timeout; + } + + //load adv interval + if (ftl_load(&dataTransInfo.adv_interval, INFO_ADV_INTERVAL_OFFSET, 4)) + { + dataTransInfo.adv_interval = default_adv_interval; + dataTransInfo.wake_delay = default_wake_delay; + } + //DBG_DIRECT("adv_interval %d.",dataTransInfo.adv_interval); + + //load pincode + if (ftl_load(&dataTransInfo.pincode, INFO_PINCODE_OFFSET, 4)) + { + dataTransInfo.pincode = defaultPin; + } + //DBG_DIRECT("pincode %x.",dataTransInfo.pincode); + + //load pair info + if (ftl_load(&dataTransInfo.pair_info, INFO_PAIR_INFO_OFFSET, 4)) + { + dataTransInfo.pair_info.authenflag.value = GAP_AUTHEN_BIT_NONE; + dataTransInfo.pair_info.authen_iocap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + dataTransInfo.pair_info.auto_security_req = false; + dataTransInfo.pair_info.paired_flag = false; + dataTransInfo.pair_info.pair_mode = NO_PASS_WORD; + } + //DBG_DIRECT("pair_mode %x.",dataTransInfo.pair_info.pair_mode); + + transferConfigInfo.select_io = UART_AT; + transferConfigInfo.select_mode = DATATRANS_MODE; + + //read version + transferConfigInfo.app_version = 0; + transferConfigInfo.patch_version = 0; + + transferConfigInfo.adv_param_update = false; + //transferConfigInfo.tx_power_upd = false; + + APP_PRINT_INFO1("datatrans uart baudrate is %d", transferConfigInfo.baudrate); + APP_PRINT_INFO1("device name is %s", TRACE_STRING(dataTransInfo.devicename_info.device_name)); + +} + +void moduleParam_InitAdvAndScanRspData(void) +{ + if (dataTransInfo.device_mode.role != ROLE_BEACON) + { + /* set adv data*/ + if (dataTransInfo.uuid_info.length == 16) + { + DT_ADV_DATA[3] = 17; + DT_ADV_DATA[4] = GAP_ADTYPE_128BIT_COMPLETE; + memcpy(DT_ADV_DATA + 5, dataTransInfo.uuid_info.uuid, 16); + } + else if (dataTransInfo.uuid_info.length == 2) + { + DT_ADV_DATA[3] = 3; + DT_ADV_DATA[4] = GAP_ADTYPE_16BIT_COMPLETE; + memcpy(DT_ADV_DATA + 5, dataTransInfo.uuid_info.uuid, 2); + } + + le_adv_set_param(GAP_PARAM_ADV_DATA, 5 + dataTransInfo.uuid_info.length, DT_ADV_DATA); + + /* set scan response data */ + DT_SCAN_RSP_DATA[SCAN_RSP_LENGTH_START_INDEX] = 1 + dataTransInfo.devicename_info.length; + memcpy(DT_SCAN_RSP_DATA + SCAN_RSP_LOCAL_NAME_START_INDEX, + dataTransInfo.devicename_info.device_name, + dataTransInfo.devicename_info.length); + dataTransInfo.scanrspdata.length = SCAN_DATA_FIX_DATA_LENGTH + + dataTransInfo.devicename_info.length;//???? move + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, + SCAN_DATA_FIX_DATA_LENGTH + dataTransInfo.devicename_info.length, + DT_SCAN_RSP_DATA); + } + else + { + le_adv_set_param(GAP_PARAM_ADV_DATA, dataTransInfo.advdata.length, DT_ADV_DATA); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, dataTransInfo.scanrspdata.length, DT_SCAN_RSP_DATA); + } + +} + + +void moduleParam_SetSystemReset(void) +{ + //WDG_SystemReset(RESET_ALL, (T_SW_RESET_REASON)0xE0); + sys_reset(); +} + + +void TimerResetCallback(void *pxTimer) +{ + APP_PRINT_INFO0("TimerResetCallback."); + moduleParam_SetSystemReset(); +} + +void TimersUartConfigChangeCallback(void *pxTimer) +{ + APP_PRINT_INFO0("TimersUartConfigChangeCallback."); + bt_datatrans_set_baud(); +} + +void TimerConnTimeOutCallback(void *pxTimer) +{ + APP_PRINT_INFO0("TimerConnTimeOutCallback"); + printf("\n\rTimerConnTimeOutCallback\n\r"); + AtCmdSendResponse(AtCmdResponseCONNTIMEOUT, strlen(AtCmdResponseCONNTIMEOUT)); +} + +void TimerConnParamUpdateCallback(void *pxTimer) +{ + APP_PRINT_INFO0("TimerConnParamUpdateCallback"); + printf("\n\rTimerConnParamUpdateCallback\n\r"); + + if (transferConfigInfo.select_io == UART_AT && + bt_datatrans_gap_conn_state == GAP_CONN_STATE_CONNECTED) + { + le_update_conn_param(CON_ID, dataTransInfo.connection_para.interval_min, \ + dataTransInfo.connection_para.interval_max, \ + dataTransInfo.connection_para.slave_lantency, \ + dataTransInfo.connection_para.supervision_timeout, \ + dataTransInfo.connection_para.interval_min * 2 - 1, \ + dataTransInfo.connection_para.interval_max * 2 - 1); + } +} + + +void Datatrans_TimerInit(void) +{ + os_timer_create(&TimersUartConfigChange, "UartConfigChange", 1, 500, false, + TimersUartConfigChangeCallback); + + if (TimersUartConfigChange == NULL) + { + APP_PRINT_INFO0("TimerInit UartConfigChange init failed"); + } + + os_timer_create(&TimersReset, "TimersReset", 1, 500, false, TimerResetCallback); + + if (TimersReset == NULL) + { + APP_PRINT_INFO0("TimerInit TimersReset init failed"); + } + + os_timer_create(&TimersConnTimeOut, "TimersConnTimeOut", 1, 11000, false, TimerConnTimeOutCallback); + + if (TimersConnTimeOut == NULL) + { + APP_PRINT_INFO0("TimerInit TimersConnTimeOut init failed"); + } + + os_timer_create(&TimersConnParamUpdate, "TimersConnParamUpdate", 1, 1000, false, + TimerConnParamUpdateCallback); + + if (TimersConnParamUpdate == NULL) + { + APP_PRINT_INFO0("TimerInit TimersConnParamUpdate init failed"); + } + +} + +#if 0 +void DataTransSemaphoreInit(void) +{ + os_sem_create(&DataTrans_Semaphore, 0, 1); + if (DataTrans_Semaphore == NULL) + { + APP_PRINT_INFO0("DataTrans_Semaphore init failed"); + } +} +#endif +void TxUartQueueInit(void) +{ + uint8_t i = 0; + uint8_t tx_queue_size = TX_PACKET_COUNT; + PTxData pTxData = g_AppBufCB->Bt2UART; + txUartDataQueueFree.ElementCount = 0; + txUartDataQueueFree.First = NULL; + txUartDataQueueFree.Last = NULL; + + for (i = 0; i < tx_queue_size; i++) + { + pTxData->tx_buffer = NULL; + datatrans_app_queue_in(&txUartDataQueueFree, pTxData); + pTxData++; + } +} + +extern void TxHandleTask(void *pParameters); +void DataTransApplicationInit(void) +{ + /* Initialize the Memory of the Queue */ + g_AppBufCB = &g_TappbufCB; + memset(g_AppBufCB, 0, sizeof(TBT_UART_BUF)); + + os_msg_queue_create(&TxMessageQueueHandle, MAX_NUMBER_OF_TX_MESSAGE, sizeof(PTxData)); + + TxUartQueueInit(); + Datatrans_TimerInit(); + //DataTransSemaphoreInit(); + os_task_create(&TxTaskHandle, "TxHandle", TxHandleTask, 0, TX_TASK_STACK_SIZE, TX_TASK_PRIORITY); +} + +void DataTransApplicationDeinit(void) +{ + if (TxTaskHandle){ + os_task_delete(TxTaskHandle); + } + + if (TxMessageQueueHandle){ + os_msg_queue_delete(TxMessageQueueHandle); + } + + if (TimersUartConfigChange){ + os_timer_delete(&TimersUartConfigChange); + } + if (TimersReset){ + os_timer_delete(&TimersReset); + } + if (TimersConnTimeOut){ + os_timer_delete(&TimersConnTimeOut); + } + if (TimersConnParamUpdate){ + os_timer_delete(&TimersConnParamUpdate); + } + + TxMessageQueueHandle = NULL; + TimersUartConfigChange = NULL; + TimersReset = NULL; + TimersConnTimeOut = NULL; + TimersConnParamUpdate = NULL; + TxTaskHandle = NULL; + +} + +#endif + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.h new file mode 100644 index 00000000..c1d9621f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.h @@ -0,0 +1,504 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file module_param_config.h +* @brief +* @details +* @author parker_xue +* @date 2017-4-19 +* @version v0.1 +********************************************************************************************************* +*/ + +#ifndef __BT_DATATRANS_MUDULE_PARAM_CONFIG_H_ +#define __BT_DATATRANS_MUDULE_PARAM_CONFIG_H_ + +//#include "rtl876x.h" +#include "bt_datatrans_app_queue.h" +#include "bt_datatrans_at_cmd.h" +#include + +#define DEFAULT_DEVICE_NAME_LEN 7 +#define DEFAULT_DEVICE_NAME "Realtek" + +#define RECEIVE_BUF_MAX_LENGTH 0x2000 +#define DEVICE_NAME_MAX_LENGTH 15 + +#define DEVICE_NAME_SIZE 16 +#define PINCODE_SIZE 4 +#define SERVICE_CHAR_UUID_SIZE 20 +#define CONFIG_PARAM_SIZE 8 +#define BAUD_SIZE 4 + +#define DEVICE_NAME_OFFSET 0 +#define PINCODE_OFFSET 16 +#define SERVICE_CHAR_UUID_OFFSET 20 +#define CONFIG_PARAM_OFFSET 40 +#define BAUD_OFFSET 48 + +#define TX_PACKET_MAX_LENGTH 260 +#define TX_PACKET_COUNT 80 +#define MAX_NUMBER_OF_TX_MESSAGE TX_PACKET_COUNT + +#define DATATRANS_BLE_KEY_LEN 0x1c +#define DATATRANS_LE_ENCRYPT_DATA_LENGTH 0x10 + +//#define APP_PRIVACY_EN 0 + +/* +Beacon Mode: + | Byte 0 | Byte 1 | Byte 2-3 | Byte 4 | Byte 5 | Byte 6-36 |Byte 37-42 | Byte 43 | + + signature mode adv_int len_con flow control adv_data direct add reserved +*/ +//typedef struct _DATATRANS_BEACON_EFUSE_CONFIG +//{ +// uint8_t datatrans_signature; + +// union +// { +// uint8_t app_mode_select; +// struct +// { +// uint8_t adv_mode : 1; //default is 1: auto adv +// uint8_t baudrate : 3; //baudrate setting +// uint8_t adv_type : 3; //advertising type +// uint8_t dt_beacon_sel: 1; //select datatrans or beacon mode +// }; +// }; + +// uint16_t adv_interval; + +// union +// { +// uint8_t len_config; //datatrans length config or adv data length +// struct +// { +// uint8_t device_name_len : 4; +// uint8_t srv_uuid_len : 1; +// uint8_t gap_role : 1; +// uint8_t pair_mode: 2; //only used in at cmd mode +// }; +// }; + +// union +// { +// uint8_t flow_ctrl; +// struct +// { +// uint8_t uart_flow_disable : 1; //1 -- disable, 0 -- enable +// uint8_t bt_flow_disable : 1; //1 -- disable, 0 -- enable +// uint8_t at_cmd_or_8761att : 1; //1 -- at cmd, 0 -- 8761att mode +// uint8_t auto_security_req : 1; //1 -- send seqReq after connect +// uint8_t not_run_datatrans : 1; //1 -- normal app, 0 -- rom datatrans +// uint8_t without_flash : 1; //1 -- no flash, 0 -- with flash +// uint8_t reserved : 2; +// }; +// }; + +// union +// { +// struct +// { +// uint8_t beacon_adv_data[31]; +// uint8_t beacon_adv_direct_add[6];//if advtype = direct adv +// uint8_t beacon_rsvd; +// };//beacon mode +// struct +// { +// uint8_t service_uuid[16]; +// uint8_t write_char_uuid[2]; +// uint8_t notify_char_uuid[2]; +// uint8_t flow_char_uuid[2]; +// uint8_t device_name[15]; +// uint8_t datatrans_rsvd; +// };//datatrans mode +// }; +//} __attribute__((packed)) DATATRANS_BEACON_EFUSE_CONFIG; + +#define MANUAL_ADV 0 +#define AUTO_ADV 1 + +#define ROLE_PERIPHERAL 0 +#define ROLE_CENTRAL 1 +#define ROLE_BEACON 2 + +#define TXP_0DBM 0 + +//ATCMD MDOE or DATATRANS MODE +#define CMD_MODE 0 +#define DATATRANS_MODE 1 + + +typedef struct +{ + uint8_t length; + uint8_t device_name[15]; +} DEVICENAME_INFO; + + +typedef struct +{ + uint8_t length; + uint8_t uuid[19];//actually max use 16 bytes +} UUID_INFO; + +typedef struct +{ + uint8_t res; + uint8_t adv_type; + uint8_t bda[6]; +} BDADDR_INFO; + +typedef struct +{ + uint8_t length; + uint8_t adv[31]; +} ADVDATA; + +typedef struct +{ + uint16_t write_uuid; + uint16_t notify_uuid; + uint16_t flow_uuid; + uint16_t res; +} PROFILE_CHAR_UUID; + +typedef struct +{ + uint16_t interval_min; + uint16_t interval_max; + uint16_t slave_lantency; + uint16_t supervision_timeout; +} CONNECT_PARA; + +typedef struct +{ + uint32_t role : 2; //0:peripheral mode; 1:central mode; 2:beacon mode + uint32_t adv_mode : 1; + uint32_t sleep_mode: 1; + uint32_t baudrateidx : 4; + + uint32_t uart_flowctrl: 1; + uint32_t bt_flowctrl : 1; + uint32_t advtype : 1; + uint32_t code_mode : 2; + uint32_t res1 : 3; + + uint32_t tx_power : 8; + uint32_t res2 : 8; +} MODE_INFO; + +typedef struct +{ + + uint16_t pair_mode : 6; + uint16_t paired_flag : 1; + uint16_t auto_security_req : 1; + uint16_t authen_iocap : 4; + uint16_t res : 4; + union + { + uint16_t value; + struct + { + uint8_t mitm_flag; + uint8_t sc_flag; + } flag; + } authenflag; +} PAIR_INFO; + +#define INFO_DEVICE_NAME_OFFSET 0 +#define INFO_UUID_OFFSET 16 +#define INFO_LOCAL_BDA_OFFSET 36 +#define INFO_ADV_DATA_OFFSET 44 +#define INFO_RSP_DATA_OFFSET 76 +#define INFO_CHAR_UUID_OFFSET 108 +#define INFO_CON_PARA_OFFSET 116 +#define INFO_ADV_INTERVAL_OFFSET 124 +#define INFO_PINCODE_OFFSET 128 +#define INFO_DEVICE_MODE_OFFSET 132 +#define INFO_PAIR_INFO_OFFSET 136 +typedef struct +{ + DEVICENAME_INFO devicename_info; //16 + UUID_INFO uuid_info;//20 + BDADDR_INFO local_bda; //8 + ADVDATA advdata; //32 + ADVDATA scanrspdata; //32 + + PROFILE_CHAR_UUID char_uuid; //8 + + CONNECT_PARA connection_para; //8 + uint16_t adv_interval; //2 + uint16_t wake_delay; //2 + uint32_t pincode; //4 + + MODE_INFO device_mode; //2 + //uint16_t res2; //2 + PAIR_INFO pair_info; +} transfer_info; + + +typedef struct +{ + uint8_t select_io; + uint8_t bt_buf_free; + uint8_t adv_param_update; + uint8_t tx_power_upd; + uint32_t patch_version; + uint32_t app_version; + uint32_t baudrate; + + uint8_t create_connection; + uint8_t connect_by_add; + uint8_t connect_dev_num; + uint8_t uart_idle; + + uint8_t connect_dev_add[6]; + uint8_t stop_scan_then_adv; + uint8_t at_dfu_mode; + uint8_t select_mode; + //BDADDR_INFO local_bda; //8 +} config_info; + +typedef struct +{ + bool allowedDataTransEnterDlps; + bool is_in_DLPS; + bool is_cmd_enter_dlps; + bool redelay_flg; +} dlps_info; + +extern transfer_info dataTransInfo; +extern config_info transferConfigInfo; +//extern dlps_info DLPSInfo; + +//typedef struct +//{ +// uint8_t len; +// uint8_t device_name[15]; +//} device_name_struct; + +//typedef struct +//{ +// uint32_t pincode; +//} pincode_struct; + +//typedef struct +//{ +// uint8_t service_uuid[16]; +// uint16_t service_uuid_len; +// uint16_t write_uuid; +// uint16_t notify_uuid; +// uint16_t flow_uuid; +//} uuid_struct; + +//typedef struct +//{ +// uint8_t pair; +// uint8_t uart_flow; +// uint16_t adv_interval; +// uint8_t adv_mode; +// uint8_t tx_power; +// uint8_t gap_role; +// uint8_t bt_flow; +//} config_struct; + +//typedef struct +//{ +// uint32_t baudrate; +//} baud_struct; + +//typedef struct +//{ +// uint16_t rom_version; +// uint16_t patch_version; +//} ver_struct; + +//typedef enum +//{ +// PERIPHERAL_ROLE = 0xA0, +// CENTRAL_ROLE = 0xA1 +//} GapRoleType; + +typedef enum +{ + UART_HCI = 0x00, + I2C_HCI = 0x01, + SPI_HCI = 0x02, + UART_AT = 0x03 +} IO_MODE; + +typedef enum +{ + NO_PASS_WORD = 0x00, + JUST_WORK = 0x01, + PASS_WORD = 0x02, + PASS_WORD_BOND = 0x03 +} PAIR_MODE; + + +//typedef struct +//{ +// bool BeaconMode; +// uint8_t ADV_type; +// uint8_t ADV_len; +// uint8_t ScanRsp_len; +// uint8_t Selected_IO; +// bool support_8761_header; +// bool ADV_param_update; +// bool create_connection; +// uint8_t connect_dev_num; +// uint8_t connect_dev_add[6]; +// bool connect_by_add; +// uint16_t auth_flags; +// uint16_t seq_req_flags; +// uint8_t bt_buf_free; +// uint8_t uart_idle; +// bool tx_power_upd; +//} DataTransGlobalFlag; + +//typedef struct +//{ +// bool start_patch; +// uint8_t index; +// uint32_t patch_address; +// bool last; +//} DataTrans_Patch; + +typedef struct +{ + uint8_t buf[RECEIVE_BUF_MAX_LENGTH]; + uint16_t WriteOffset; + uint16_t ReadOffset; + uint16_t datalen; + uint8_t atcmd[AT_CMD_MAX_LENGTH]; + uint16_t atcmdlength; + uint8_t overflow; +} ReceiveBufStruct; + +typedef struct _TXData +{ + struct _TXData *pNext; +// uint8_t tx_buffer[TX_PACKET_MAX_LENGTH]; + uint8_t *tx_buffer; + uint16_t length; + uint16_t stack_buf_offset; + bool is_stack_buf; + +} TTxData, *PTxData; + +typedef struct +{ + TTxData Bt2UART[TX_PACKET_COUNT]; +} TBT_UART_BUF, *PBT_UART_BUF; + + +//typedef struct datatrans_auth_info +//{ +// uint8_t bd_addr[6]; +// uint8_t remote_addr_type; +// uint8_t key_type; +// uint8_t link_key[DATATRANS_BLE_KEY_LEN]; +//} T_DATATRANS_AUTH_INFO; + +//typedef struct +//{ +// uint8_t bd_addr[6]; +// uint8_t remote_addr_type; +// uint8_t ltk_exist; +// uint8_t irk_exist; +// uint8_t ltk_key[DATATRANS_BLE_KEY_LEN]; +// uint8_t irk_key[DATATRANS_BLE_KEY_LEN]; +//} T_DATATRANS_KEY_INFO; + +typedef struct bdaddr_info +{ + uint8_t bdaddr[6]; + uint8_t remote_addr_type; +} T_DATATRANS_REMOTE_BDADDR_INFO; + +//typedef struct ble_all_key_info +//{ +// uint8_t bd_addr[6]; +// uint8_t ltk[DATATRANS_BLE_KEY_LEN]; +// uint8_t irk[DATATRANS_BLE_KEY_LEN]; +//} T_DATATRANS_ALL_KEY_INFO; + +//typedef struct auth_info_header +//{ +// uint8_t bd_addr[6]; +// uint8_t remote_addr_type; +// uint8_t key_type; +//} T_DATATRANS_AUTH_INFO_HEADER; + +//typedef struct t_authen_key_req_ind +//{ +// uint8_t bd_addr[6]; +// uint8_t remote_addr_type; +// uint8_t key_type; +//} T_DATATRANS_KEY_REQ_IND; + + +extern uint16_t MTU_SIZE; +extern uint8_t BT_Credits; +extern uint8_t CON_ID; +//extern device_name_struct device_name; +//extern pincode_struct pincode; +//extern uuid_struct uuid; +//extern config_struct config; +//extern baud_struct baudrate; +//extern ver_struct datatrans_ver; +//extern DataTransGlobalFlag DataTranFlag; +extern ReceiveBufStruct IO_Receive; +//extern DATATRANS_BEACON_EFUSE_CONFIG datatrans_efuse; +//extern DataTrans_Patch DataTrans_PatchFlag; + +//extern T_DATATRANS_KEY_INFO g_ble_key_info; + +extern void *TimersUartConfigChange; +extern void *TimersReset; +extern void *TimersConnTimeOut; +//extern void *TimersEnterLowPower; +extern void *TimersConnParamUpdate; +//extern void *TimersSwitchToHCI; + +extern QUEUE_T txUartDataQueueFree; +extern void *TxMessageQueueHandle; +extern void *DataTrans_Semaphore; +#if 0 +#include "gap_ext_adv.h" + +/** @brief Idle advertising set */ +#define APP_IDLE_ADV_SET 0xFF +/** @brief Maximum advertising set */ +#define APP_MAX_ADV_SET 4 + +#define LE_CODED_PHY_2M 3 +#define LE_CODED_PHY_S8 2 +#define LE_CODED_PHY_S2 1 +#define LE_CODED_PHY_1M 0 +typedef struct +{ + uint8_t adv_handle; + T_GAP_EXT_ADV_STATE ext_adv_state; +} T_APP_EXT_ADV_STATE; + +extern T_APP_EXT_ADV_STATE ext_adv_state[APP_MAX_ADV_SET]; /**< Extended advertising state */ +extern uint8_t adv_set_num; +extern uint8_t adv_handle; +#endif + +void readconfig(void); +void datatrans_setdefault(void); +bool DataTrans_ConfigReadFromEfuse(void); +void DataTrans_SettingConfig(void); +void moduleParam_InitAdvAndScanRspData(void); +void moduleParam_SetSystemReset(void); +void DataTransApplicationInit(void); +void DataTransApplicationDeinit(void); +//void le_init_ext_adv_params_ext_conn(void); +//void le_init_ext_adv_enable_params(uint8_t adv_handle); +#endif /*__MUDULE_PARAM_CONFIG_H_*/ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.c new file mode 100644 index 00000000..e2f1c037 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.c @@ -0,0 +1,367 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file multilink_manager.c + * @brief Multilink manager functions. + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + */ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include +#if CENTRAL_MODE +/** Add Includes here **/ +#include "bt_datatrans_multilink_manager.h" +#include "gap.h" +#include "trace_app.h" +#include +#include "bt_datatrans_module_param_config.h" +#include + +TAppLinkCB DataTransLinkTable[BT_DATATRANS_APP_MAX_LINKS]; +TDevInfo DT_DevList[BT_DATATRANS_APP_MAX_DEVICE_INFO]; +uint8_t DTDevListNum = 0; + +/** + * @brief Split valid information from peer device's ADV data or SCAN RSP data. + * NOTE--this function just for demo, user can cutter the code according + * to requirement. + * + * @param scan_info - message informed from upper stack + */ +//#ifdef _IS_ASIC_ +void DataTrans_Multilink_ParseScanInfo(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length < 1) || (length >= 31)) + { + return; + } + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_INFO2(" AD Structure Info: AD type = 0x%x, AD Data Length = %d", type, length - 1); + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1(" AD Data: Flags = 0x%x", flags); + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *pUUID = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *pUUID++); + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *pUUID = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO2(" AD Data: UUID32 List Item %d = 0x%x", i / 4, *pUUID++); + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *pUUID = (uint32_t *)(buffer); + APP_PRINT_INFO4(" AD Data: UUID128 value: 0x%8.8x%8.8x%8.8x%8.8x", + pUUID[3], pUUID[2], pUUID[1], pUUID[0]); + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO0(" AD Data: Local Name"); + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1(" AD Data: TX power = 0x%x", scan_info->data[pos + 1]); + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *pMin = (uint16_t *)(buffer); + uint16_t *pMax = pMin + 1; + APP_PRINT_INFO2(" AD Data: Slave conn interval range, 0x%x - 0x%x", *pMin, *pMax); + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint16_t *pUUID = (uint16_t *)(buffer); + uint8_t i; + + APP_PRINT_INFO2(" AD Data: Service Data UUID = 0x%x, len = 0x%x", *pUUID, length - 2); + + for (i = 2; i < length; i++) + { + APP_PRINT_INFO1(" AD Data: Service Data = 0x%x", buffer[i]); + } + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); + } + } + break; + } + } + + pos += length; + } +} +//#endif + +/** + * @brief Discovery 16-bit uuid information from ADV data or SCAN RSP data. + * + * @param uuid used to filter scan_info + * @param scan_info message informed from upper stack + * @retval true found the uuid from scan_info. + * @retval false Not found. + */ +bool DataTrans_Multilink_FilterScanInfoByUuid(uint8_t *uuid, T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length < 1) || (length >= 31)) + { + return false; + } + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + if (!memcmp(buffer, uuid, 2)) + { + return true; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + if (!memcmp(buffer, uuid, 16)) + { + return true; + } + + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} + +#if 0 +/** + * @brief Discovery 16-bit uuid information from ADV data or SCAN RSP data. + * + * @param uuid used to filter ex_scan_info + * @param scan_info message informed from upper stack + * @retval true found the uuid from ex_scan_info. + * @retval false Not found. + */ +bool DataTrans_Multilink_FilterExScanInfoByUuid(uint8_t *uuid, T_LE_EXT_ADV_REPORT_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->p_data[pos++]; + uint8_t type; + + if ((length < 1) || (length >= 31)) + { + return false; + } + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->p_data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->p_data[pos]; + + switch (type) + { + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + if (!memcmp(buffer, uuid, 2)) + { + return true; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + if (!memcmp(buffer, uuid, 16)) + { + return true; + } + + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} +#endif + +/** + * @brief Add device information to device list. + * + * @param bd_addr Peer device address. + * @param bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool DataTrans_Multilink_AddDeviceInfo(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (DTDevListNum < BT_DATATRANS_APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < DTDevListNum; i++) + { + if (memcmp(bd_addr, DT_DevList[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(DT_DevList[DTDevListNum].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + DT_DevList[DTDevListNum].bd_type = bd_type; + + if (transferConfigInfo.select_io == UART_AT) + { + char addstr[15]; + addstr[0] = DTDevListNum + '0'; + addstr[1] = ':'; + + sprintf(addstr + 2, "%02X%02X%02X%02X%02X%02X", DT_DevList[DTDevListNum].bd_addr[5], + DT_DevList[DTDevListNum].bd_addr[4], \ + DT_DevList[DTDevListNum].bd_addr[3], DT_DevList[DTDevListNum].bd_addr[2], + DT_DevList[DTDevListNum].bd_addr[1], DT_DevList[DTDevListNum].bd_addr[0]); + + AtCmdSendResponse((const char *)addstr, 14); + AtCmdSendResponse((const char *)("\r\n"), strlen("\r\n")); + } + + /*Increment device list count*/ + DTDevListNum++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void DataTrans_Multilink_ClearDeviceList(void) +{ + DTDevListNum = 0; +} + +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.h new file mode 100644 index 00000000..85a8e47b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.h @@ -0,0 +1,93 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file multilink_manager.h +* @brief Define multilink manager struct and functions. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +* ********************************************************************************************************* +*/ +//#include "bt_datatrans_app_flags.h" +//#if CENTRAL_MODE +#ifndef _BT_DATATRANS_MULTILINK_MANAGER_H_ +#define _BT_DATATRANS_MULTILINK_MANAGER_H_ +#include "app_msg.h" +#include "gap_conn_le.h" +#include "bt_datatrans_app_flags.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Add Includes here */ +//#include "rtl876x.h" +#include "profile_client.h" +//#include "rtl876x_flash_storage.h" + +/** @brief Define links number. range: 0-4 */ +//#define APP_MAX_LINKS 1 +/** @brief Define handle cache table length. */ +#define APP_HDL_CACHE_LEN 24 +/** @brief Define start offset of the falsh to save GATT Server information. */ +#define APP_GATT_SERVER_INFO_FLASH_OFFSET 0 +/** @brief Define device list table size. */ +#define BT_DATATRANS_APP_MAX_DEVICE_INFO 10 + +/** + * @brief GATT Serve information struct. + */ +typedef struct +{ + uint16_t uuid16; + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ + uint8_t reserved[3]; /**< used to TGattServerInfo four byte alignment*/ + uint16_t hdl_cache[APP_HDL_CACHE_LEN]; +} TGattServerInfo; + +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_CLIENT_ID client_id; + uint8_t end_handle_idx; + uint8_t disc_state; + uint8_t state; + TGattServerInfo server_info; +} TAppLinkCB; + +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; + uint8_t bd_type; +} TDevInfo; +/** @brief App link table */ +extern TAppLinkCB DataTransLinkTable[BT_DATATRANS_APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern TDevInfo DT_DevList[BT_DATATRANS_APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in DT_DevList. */ +extern uint8_t DTDevListNum; + +//#ifdef _IS_ASIC_ +extern void DataTrans_Multilink_ParseScanInfo(T_LE_SCAN_INFO *scan_info); +//#endif +extern bool DataTrans_Multilink_FilterScanInfoByUuid(uint8_t *uuid, T_LE_SCAN_INFO *scan_info); +//extern bool DataTrans_Multilink_FilterExScanInfoByUuid(uint8_t *uuid, +// T_LE_EXT_ADV_REPORT_INFO *scan_info); +extern bool DataTrans_Multilink_AddDeviceInfo(uint8_t *bd_addr, uint8_t bd_type); +extern void DataTrans_Multilink_ClearDeviceList(void); + + +#ifdef __cplusplus +} +#endif + +#endif + +//#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.c new file mode 100644 index 00000000..f801593f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.c @@ -0,0 +1,759 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file datatrans_peripheral_application.c +* @brief datatrans application implementation +* @details +* @author parker +* @date 2017-7-4 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include +#include +#include +#include +#include +#include +#include +#include "bt_datatrans_profile.h" +#include +#include +#include "bt_datatrans_module_param_config.h" +#include "bt_datatrans_uart.h" +#include +#include "bt_datatrans_at_cmd.h" +#include "bt_datatrans_multilink_manager.h" +#include "bt_datatrans_at_hci_cmd_process.h" +#include "os_timer.h" +#include "aes_api.h" +#include "gap_callback_le.h" +#include "gap_conn_le.h" +#include "bt_datatrans_app_flags.h" +#include + +//bool g_switch_into_ota_pending = false; +T_GAP_DEV_STATE bt_datatrans_gap_dev_state = {0, 0, 0, 0, 0}; +T_GAP_CONN_STATE bt_datatrans_gap_conn_state = GAP_CONN_STATE_DISCONNECTED; +T_DATATRANS_REMOTE_BDADDR_INFO connect_dev; +extern T_SERVER_ID bt_datatrans_srv_id; +extern uint8_t sendbuffer[255]; + +void bt_datatrans_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +void DataTrans_HandleUART_Event(T_IO_MSG io_driver_msg_recv); + +void AtCmdSendResponseConnect(uint8_t conn_id); +void AtCmdSendResponseDisconnect(void); + +/****************************************************************** + * @fn app_handle_io_msg + * @brief All the application events are pre-handled in this function. + * All the IO MSGs are sent to this function, Then the event handling function + * shall be called according to the MSG type. + * + * @param io_msg - bee io msg data + * @return void + */ +void bt_datatrans_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_datatrans_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + { + DataTrans_HandleUART_Event(io_msg); + } + break; + default: + break; + } +} + +void DataTrans_HandleUART_Event(T_IO_MSG io_driver_msg_recv) +{ + uint8_t subtype = io_driver_msg_recv.subtype; + switch (subtype) + { + case IO_MSG_UART_RX: + case IO_MSG_UART_RX_TIMEOUT: + { + if (transferConfigInfo.select_io == UART_AT && transferConfigInfo.at_dfu_mode == 0) + { + DataTrans_HandleATCMD(); + } + } + break; + case IO_MSG_UART_RX_OVERFLOW: + break; + case IO_MSG_UART_RX_EMPTY: + break; + + } + +} + +/****************************************************************** + * @fn peripheral_HandleBtDevStateChangeEvt + * @brief All the gaprole_States_t events are pre-handled in this function. + * Then the event handling function shall be called according to the newState. + * + * @param newState - new gap state + * @return void + */ +void bt_datatrans_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_datatrans_app_handle_dev_state_evt: init state %d, adv state %d, conn state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_conn_state, cause); + if (bt_datatrans_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + printf("[BT Datatrans] GAP stack ready\n\r"); + + /*stack ready*/ + if (dataTransInfo.device_mode.adv_mode == AUTO_ADV && + dataTransInfo.device_mode.role != ROLE_CENTRAL) + { + le_adv_start(); + } + + } + } + + if (bt_datatrans_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("GAP adv stoped: because connection created\n\r"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + printf("GAP adv stopped\n\r"); + if (transferConfigInfo.adv_param_update) + { + /*****Update adv data, adv interval******/ + moduleParam_InitAdvAndScanRspData(); + uint8_t DeviceName[GAP_DEVICE_NAME_LEN] = {0}; + memcpy(DeviceName, dataTransInfo.devicename_info.device_name, dataTransInfo.devicename_info.length); + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, DeviceName); + + uint16_t adv_int_min = dataTransInfo.adv_interval; + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + uint16_t adv_int_max = dataTransInfo.adv_interval; + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + transferConfigInfo.adv_param_update = false; + } + + if (dataTransInfo.device_mode.adv_mode == AUTO_ADV && + (dataTransInfo.device_mode.role == ROLE_PERIPHERAL || + dataTransInfo.device_mode.role == ROLE_BEACON)) + { + le_adv_start(); + } + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("GAP adv start\n\r"); + } + } + +#if CENTRAL_MODE + if (bt_datatrans_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + printf("GAP scan stop\r\n"); + if (transferConfigInfo.stop_scan_then_adv == true) + { + le_adv_start(); + } + if (transferConfigInfo.create_connection) + { + if (transferConfigInfo.connect_by_add == false) + { + le_connect(0, DT_DevList[transferConfigInfo.connect_dev_num].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)DT_DevList[transferConfigInfo.connect_dev_num].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + } + else + { + le_connect(0, transferConfigInfo.connect_dev_add, + GAP_REMOTE_ADDR_LE_PUBLIC, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + } + os_timer_start(&TimersConnTimeOut); + transferConfigInfo.create_connection = false; + } + else if (dataTransInfo.device_mode.adv_mode == AUTO_ADV && + dataTransInfo.device_mode.role == ROLE_PERIPHERAL) + { + le_adv_start(); + } + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + printf("GAP scan start\r\n"); + } + } +#endif + + bt_datatrans_gap_dev_state = new_state; +} + + +void bt_datatrans_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, + uint16_t disc_cause) +{ + APP_PRINT_INFO3("bt_datatrans_app_handle_conn_state_evt: conn_id = %d old_state = %d new_state = %d", + conn_id, bt_datatrans_gap_conn_state, new_state); + + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR1("connection lost: cause 0x%x", disc_cause); + printf("connection lost: cause 0x%x\r\n", disc_cause); + } + printf("[BT DATATRANS] BT Disconnected\n\r"); + if (dataTransInfo.device_mode.adv_mode == AUTO_ADV && + (dataTransInfo.device_mode.role == ROLE_PERIPHERAL || + dataTransInfo.device_mode.role == ROLE_BEACON)) + { + le_adv_start(); + } +#if CENTRAL_MODE + else if (dataTransInfo.device_mode.role == ROLE_CENTRAL && conn_id < BT_DATATRANS_APP_MAX_LINKS) + { + memset(&DataTransLinkTable[conn_id], 0, sizeof(TAppLinkCB)); + } +#endif + + if (transferConfigInfo.select_io == UART_AT) + { + AtCmdSendResponseDisconnect(); + } + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + if (transferConfigInfo.select_io == UART_AT) + { +#if CENTRAL_MODE + if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + os_timer_stop(&TimersConnTimeOut); + } +#endif + printf("[BT DATATRANS] BT Connected\n\r"); + AtCmdSendResponseConnect(conn_id);//,dataTransInfo.device_mode.role); + os_timer_start(&TimersConnParamUpdate); + } + + CON_ID = conn_id; + + } + break; + + default: + break; + } + + bt_datatrans_gap_conn_state = new_state; + +#if CENTRAL_MODE + if (dataTransInfo.device_mode.role == ROLE_CENTRAL && conn_id < BT_DATATRANS_APP_MAX_LINKS) + { + DataTransLinkTable[conn_id].conn_state = new_state; + } +#endif + +} + +/****************************************************************** + * @fn peripheral_HandleBtGapAuthenStateChangeEvt + * @brief All the bonding state change events are pre-handled in this function. + * Then the event handling function shall be called according to the newState. + * + * @param newState - new bonding state + * @return void + */ +void bt_datatrans_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO1("bt_datatrans_app_handle_authen_state_evt:conn_id %d", conn_id); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + //APP_PRINT_INFO0("GAP_AUTHEN_STATE_COMPLETE"); + if (cause == 0) + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair success"); + } + else + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair failed"); + //memset(&g_ble_key_info, 0, sizeof(T_DATATRANS_KEY_INFO)); + le_disconnect(CON_ID); + } + } + break; + + default: + { + APP_PRINT_INFO1("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(unknown newstate: %d)", new_state); + } + break; + } +} + +/****************************************************************** + * @fn peripheral_HandleBtGapConnParaChangeEvt + * @brief All the connection parameter update change events are pre-handled in this function. + * Then the event handling function shall be called according to the status. + * + * @param status - connection parameter result, 0 - success, otherwise fail. + * @return void + */ +void bt_datatrans_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("GAP_MSG_LE_CONN_STATE_CHANGE update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + printf("GAP_MSG_LE_CONN_STATE_CHANGE update success:conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x\r\n", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR1("GAP_MSG_LE_CONN_STATE_CHANGE failed: cause 0x%x", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("bt_datatrans_app_handle_conn_param_update_evt update pending."); + printf("bt_datatrans_app_handle_conn_param_update_evt update pending.\r\n"); + } + break; + + default: + break; + } +} + +/****************************************************************** + * @fn peripheral_HandleBtGapMessage + * @brief All the bt gap msg events are pre-handled in this function. + * Then the event handling function shall be called according to the subType + * of T_IO_MSG. + * + * @param pBeeIoMsg - pointer to bee io msg + * @return void + */ +void bt_datatrans_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_datatrans_app_handle_gap_msg subType = %d", p_gap_msg->subtype); + printf("\n\rbt_datatrans_app_handle_gap_msg subType = %d\n", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + bt_datatrans_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_datatrans_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_datatrans_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("LE_GAP_MSG_TYPE_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("LE_GAP_MSG_TYPE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + AtCmdSendResponsePinDis(); + + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("LE_GAP_MSG_TYPE_BOND_USER_CONFIRMATION:passkey %d", display_value); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { +// uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; +// APP_PRINT_INFO0("LE_GAP_MSG_TYPE_BOND_PASSKEY_INPUT"); +// le_bond_passkey_input_confirm(conn_id, passkey, BTIF_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("LE_GAP_MSG_TYPE_BOND_OOB_INPUT"); +#if F_BT_LE_SMP_OOB_SUPPORT + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); +#endif + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_datatrans_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + case GAP_MSG_LE_CONN_MTU_INFO: + { + MTU_SIZE = gap_msg.msg_data.gap_conn_mtu_info.mtu_size; + + APP_PRINT_INFO2("GAP_MSG_LE_CONN_MTU_INFO MTU SIZE = %x,conn id is %x", MTU_SIZE, + gap_msg.msg_data.gap_conn_mtu_info.conn_id); + printf("GAP_MSG_LE_CONN_MTU_INFO MTU SIZE = %x,conn id is %x\n", MTU_SIZE, + gap_msg.msg_data.gap_conn_mtu_info.conn_id); +#if CENTRAL_MODE + if (dataTransInfo.device_mode.role == ROLE_CENTRAL) + { + APP_PRINT_INFO0("client discovery primary service!"); + printf("client discovery primary service!\n"); + client_all_primary_srv_discovery(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + CLIENT_PROFILE_GENERAL_ID); + } +#endif + } + break; + default: + break; + } +} + + +T_APP_RESULT bt_datatrans_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { +#if CENTRAL_MODE + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_TRACE5("GAP_MSG_LE_SCAN_INFO: bd_addr %s, bdtype=%d, event=0x%x, rssi=%d, len=%d", + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->adv_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + /* User can split interested information by using the function as follow. */ + + if (DataTrans_Multilink_FilterScanInfoByUuid(dataTransInfo.uuid_info.uuid, p_data->p_le_scan_info)) + { + DataTrans_Multilink_AddDeviceInfo(p_data->p_le_scan_info->bd_addr, + p_data->p_le_scan_info->remote_addr_type); + APP_PRINT_INFO0("found datatrans device"); + } + break; +#endif + + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO4(" GAP_MSG_LE_CONN_UPDATE_IND: max_interval=0x%x, min_interval=0x%x, Latency=0x%x,timeOut=0x%x", + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3(" GAP_MSG_LE_READ_RSSI:conn_id=0x%x cause=0x%x rssi=%d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + if (p_data->p_le_phy_update_info->rx_phy == GAP_PHYS_2M && + p_data->p_le_phy_update_info->tx_phy == GAP_PHYS_2M) + { + APP_PRINT_INFO0("Set 2M Phy success."); + } + else if (p_data->p_le_phy_update_info->rx_phy == GAP_PHYS_1M && + p_data->p_le_phy_update_info->tx_phy == GAP_PHYS_1M) + { + APP_PRINT_INFO0("Set 1M Phy success."); + } + break; +#endif + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_SET_DATA_LEN: + APP_PRINT_INFO2("GAP_MSG_LE_SET_DATA_LEN: conn_id 0x%x, cause 0x%x", + p_data->p_le_set_data_len_rsp->conn_id, + p_data->p_le_set_data_len_rsp->cause); + break; + + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id 0x%x, max_tx_octets 0x%x, max_tx_time 0x%x, max_rx_octets 0x%x, max_rx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time, + p_data->p_le_data_len_change_info->max_rx_octets, + p_data->p_le_data_len_change_info->max_rx_time); + break; +#endif + + default: + APP_PRINT_INFO1("bt_datatrans_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +/****************************************************************** + * @fn app_profile_callback + * @brief All the bt profile callbacks are handled in this function. + * Then the event handling function shall be called according to the serviceID + * of T_IO_MSG. + * + * @param serviceID - service id of profile + * @param pData - pointer to callback data + * @return void + */ + +T_APP_RESULT bt_datatrans_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits = %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + if (IO_Receive.datalen >= MTU_SIZE - 3) //buffer length > MTU size - 3, send immediately + { + if (transferConfigInfo.select_io == UART_AT) + { + Setsendbuffer(MTU_SIZE - 3); + server_send_data(CON_ID, bt_datatrans_srv_id, GATT_UUID_CHAR_DATA_NOTIFY_INDEX, sendbuffer, + MTU_SIZE - 3, GATT_PDU_TYPE_ANY); + } + } + else if (IO_Receive.datalen > 0) //buffer length < MTU size - 3 + { + if (transferConfigInfo.select_io == UART_AT && transferConfigInfo.uart_idle) + { + uint16_t len = IO_Receive.datalen; + Setsendbuffer(IO_Receive.datalen); + server_send_data(CON_ID, bt_datatrans_srv_id, GATT_UUID_CHAR_DATA_NOTIFY_INDEX, sendbuffer, len, + GATT_PDU_TYPE_ANY); + transferConfigInfo.uart_idle = false; + } + } + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == bt_datatrans_srv_id) + { + T_DTS_CALLBACK_DATA *p_dts_cb_data = (T_DTS_CALLBACK_DATA *)p_data; + switch (p_dts_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + //APP_PRINT_INFO1("SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: read_index %d\n", p_dts_cb_data->msg_index.read_index); + if (p_dts_cb_data->msg_index.read_index == DTS_FLOW_READ_PARA) + { + uint8_t feature[2] = {0x22, 0x02}; + dts_set_flow_info_parameter(DTS_FLOW_INFO, 2, feature); //length max 32 bytes here + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + APP_PRINT_INFO1("SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: write_index %d\n",p_dts_cb_data->msg_index.write_index); + switch (p_dts_cb_data->msg_index.write_index) + { + case DTS_WRITE_CHAR_DATA: + if (dataTransInfo.device_mode.bt_flowctrl) + { + transferConfigInfo.bt_buf_free++; + } + app_result = HandleBTReceiveData(0, p_dts_cb_data->msg_data.len, p_dts_cb_data->msg_data.data); + //printf("DTS_DATA_WRITE: value_size %d\r\n", p_dts_cb_data->msg_data.len);//debug + break; + case DTS_WRITE_FLOW_PARA: + dataTransInfo.device_mode.bt_flowctrl = p_dts_cb_data->msg_data.data[0]; + break; + default: + break; + } + } + break; + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_dts_cb_data->msg_index.notification_indification_index) + { + case DTS_DATA_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("DTS_DATA_NOTIFY_ENABLE"); + } + break; + case DTS_DATA_NOTIFY_DISABLE: + { + APP_PRINT_INFO0("DTS_DATA_NOTIFY_DISABLE"); + } + break; + case DTS_FLOW_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("DTS_FLOW_NOTIFY_ENABLE"); + uint8_t info[11] = {0x02, 0x09, 0x17, 0x00, 0x22, 0x01, 0x01}; + info[2] = MTU_SIZE; + info[3] = MTU_SIZE >> 8; + info[6] = dataTransInfo.device_mode.bt_flowctrl; + info[7] = transferConfigInfo.baudrate; + info[8] = (transferConfigInfo.baudrate) >> 8; + info[9] = (transferConfigInfo.baudrate) >> 16; + info[10] = (transferConfigInfo.baudrate) >> 24; + server_send_data(CON_ID, bt_datatrans_srv_id, GATT_UUID_CHAR_FLOW_NOTIFY_INDEX, + info, 11, GATT_PDU_TYPE_ANY); + } + break; + + case DTS_FLOW_NOTIFY_DISABLE: + { + APP_PRINT_INFO0("DTS_FLOW_NOTIFY_DISABLE"); + } + break; + default: + break; + } + } + break; + default: + break; + } + } + return app_result; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.h new file mode 100644 index 00000000..f7b8d0fc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.h @@ -0,0 +1,35 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file simple_ble_peripheral_application.h +* @brief simple_ble_peripheral_application +* @details simple_ble_peripheral_application +* @author jane +* @date 2015-12-22 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _BT_DATATRANS_PERIPHERAL_APPLICATION__ +#define _BT_DATATRANS_PERIPHERAL_APPLICATION__ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#include +#include +//#include +void bt_datatrans_app_handle_io_msg(T_IO_MSG io_driver_msg_recv); +T_APP_RESULT bt_datatrans_app_profile_callback(T_SERVER_ID service_id, void *p_data); +T_APP_RESULT bt_datatrans_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +//void app_privacy_callback(T_PRIVACY_CB_TYPE type, T_PRIVACY_CB_DATA cb_data); +//void datatrans_start_adv(void); +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.c new file mode 100644 index 00000000..d917b95e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.c @@ -0,0 +1,357 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file simple_ble_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include +#include "trace_app.h" +#include "bt_datatrans_profile.h" +#include "gap.h" +#include "bt_datatrans_module_param_config.h" + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +T_SERVER_ID DatatransServiceId; +extern T_SERVER_ID bt_datatrans_srv_id; +uint8_t feature[2] = {0x22, 0x02}; +_T_Feature_Info feature_info; +/**< 128bit UUID of simple BLE service. */ +const uint8_t GATT_UUID128_DATATRANS_PROFILE[16] = { 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xE0, 0x00, 0x00}; + +static P_FUN_SERVER_GENERAL_CB pfn_dts_cb = NULL; + +/**< @brief profile/service definition. */ +T_ATTRIB_APPL datatrans_service_tbl[] = +{ + /* <>, Index 0 */ + { + (ATTRIB_FLAG_VOID | ATTRIB_FLAG_LE), /* flags */ + { + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), /* type_value */ + }, + UUID_128BIT_SIZE, /* bValueLen */ + (void *)GATT_UUID128_DATATRANS_PROFILE, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + + /* <> write/notification Index 1*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE, /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + /* <> Data write Index 2*/ + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_DATA), + HI_WORD(GATT_UUID_CHAR_DATA) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <> Index 3 */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_NOTIFY, /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + /* <> Data Notification Index 4 */ + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_DATA_NOTIFY), + HI_WORD(GATT_UUID_CHAR_DATA_NOTIFY) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NOTIF_IND /* permissions */ + }, + + /* <> CCCD Index 5*/ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + + /* <> Index 6 */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_NOTIFY | GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE\ + | GATT_CHAR_PROP_READ, /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + /* <> Flow Control Index 7 */ + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_FLOW_CTRL_NOTIFY), + HI_WORD(GATT_UUID_FLOW_CTRL_NOTIFY) + }, + 0, /* bValueLen */ + NULL, + (GATT_PERM_NOTIF_IND | GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + + /* <> CCCD Index 8*/ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + } +}; + + +bool dts_set_flow_info_parameter(T_DTS_PARAM_TYPE param_type, uint8_t length, uint8_t *p_value) +{ + bool ret = true; + + switch (param_type) + { + default: + { + ret = false; + PROFILE_PRINT_ERROR0("bas_set_parameter failed"); + } + break; + + case DTS_FLOW_INFO: + { + feature_info.lenth = length; + memcpy(feature_info.info, p_value, length); + } + break; + } + + return ret; +} +T_APP_RESULT DataTransAttrReadCb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + default: + APP_PRINT_ERROR1("DataTransAttrReadCb, Attr not found, index %d", attrib_index); + wCause = APP_RESULT_ATTR_NOT_FOUND; + break; + case GATT_UUID_CHAR_FLOW_NOTIFY_INDEX: + { + T_DTS_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_index.read_index = DTS_FLOW_READ_PARA; + if (pfn_dts_cb) + { + pfn_dts_cb(service_id, (void *)&callback_data); + } + //return the device information. + *pp_value = (uint8_t *)feature_info.info; + *p_length = feature_info.lenth; + } + break; + } + + return (wCause); +} + +/** + * @brief write characteristic data from service. + * + * @param ServiceID ServiceID to be written. + * @param iAttribIndex Attribute index of characteristic. + * @param wLength length of value to be written. + * @param pValue value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT DataTransAttrWriteCb(uint8_t conn_id, T_SERVER_ID ServiceId, + uint16_t iAttribIndex, T_WRITE_TYPE write_type, uint16_t wLength, uint8_t *pValue, + P_FUN_WRITE_IND_POST_PROC *pWriteIndPostProc) +{ + + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + T_DTS_CALLBACK_DATA callback_data; + PROFILE_PRINT_INFO1("--> DataTransAttrWriteCb write_type = 0x%x", write_type); + //APP_PRINT_INFO1("--> DataTransAttrWriteCb write_type = 0x%x", write_type); //DEBUG + + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + + if (pValue == NULL) + { + wCause = APP_RESULT_INVALID_PDU; + return wCause; + } + + if (GATT_UUID_CHAR_DATA_INDEX == iAttribIndex) + { + callback_data.msg_index.write_index = DTS_WRITE_CHAR_DATA; + callback_data.msg_data.data = pValue; + callback_data.msg_data.len = wLength; +// if (dataTransInfo.device_mode.bt_flowctrl) +// { +// transferConfigInfo.bt_buf_free++; +// } + +// wCause = HandleBTReceiveData(conn_id, wLength, pValue); + } + else if (GATT_UUID_CHAR_FLOW_NOTIFY_INDEX == iAttribIndex) + { + callback_data.msg_index.write_index = DTS_WRITE_FLOW_PARA; + callback_data.msg_data.data = pValue; + callback_data.msg_data.len = wLength; + //dataTransInfo.device_mode.bt_flowctrl = pValue[0]; + } + else + { + PROFILE_PRINT_ERROR2("--> DataTransAttrWriteCb Error iAttribIndex = 0x%x wLength=%d", + iAttribIndex, + wLength); + wCause = APP_RESULT_ATTR_NOT_FOUND; + } + if (pfn_dts_cb && (wCause == APP_RESULT_SUCCESS)) + { + wCause = pfn_dts_cb(ServiceId, (void *)&callback_data); + } + PROFILE_PRINT_ERROR1("--> DataTransAttrWriteCb wCause %x", + wCause); + + return wCause; +} + +/** + * @brief update CCCD bits from stack. + * + * @param ServiceId Service ID. + * @param Index Attribute index of characteristic data. + * @param wCCCBits CCCD bits from stack. + * @return None +*/ +void DataTransCccdUpdateCb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t Index, + uint16_t wCCCBits) +{ + + PROFILE_PRINT_INFO2("DataTransCccdUpdateCb Index = %d wCCCDBits %x", Index, wCCCBits); + T_APP_RESULT cause = APP_RESULT_SUCCESS; + T_DTS_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + switch (Index) + { + case GATT_UUID_CHAR_DATA_CCCD_INDEX: + { + if (wCCCBits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + callback_data.msg_index.notification_indification_index = DTS_DATA_NOTIFY_ENABLE; + } + else + { + callback_data.msg_index.notification_indification_index = DTS_DATA_NOTIFY_DISABLE; + } + } + break; + case GATT_UUID_CHAR_FLOW_CCCD_INDEX: + { + if (wCCCBits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + callback_data.msg_index.notification_indification_index = DTS_FLOW_NOTIFY_ENABLE; + } + else + { + callback_data.msg_index.notification_indification_index = DTS_FLOW_NOTIFY_DISABLE; + // Disable Notification + } + } + break; + default: + cause = APP_RESULT_ATTR_NOT_FOUND; + break; + } + + if (pfn_dts_cb && (cause == APP_RESULT_SUCCESS)) + { + pfn_dts_cb(service_id, (void *)&callback_data); + } +} + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS DataTransServiceCBs = +{ + DataTransAttrReadCb, // Read callback function pointer + DataTransAttrWriteCb, // Write callback function pointer + DataTransCccdUpdateCb // CCCD update callback function pointer +}; + +/** + * @brief add Simple BLE service to application. + * + * @param[in] pFunc pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + * @retval ServiceId + */ +T_SERVER_ID Datatrans_AddService(void *pFunc) +{ + if (false == server_add_service(&DatatransServiceId, + (uint8_t *)datatrans_service_tbl, + sizeof(datatrans_service_tbl), + DataTransServiceCBs)) + { + PROFILE_PRINT_ERROR1("Datatrans_AddService: ServiceId %d", DatatransServiceId); + DatatransServiceId = 0xff; + return DatatransServiceId; + } + + pfn_dts_cb = (P_FUN_SERVER_GENERAL_CB)pFunc; + return DatatransServiceId; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.h new file mode 100644 index 00000000..5076faa7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.h @@ -0,0 +1,157 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file datatrans_profile.h + * @brief + * @details + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _BT_DATATRANS_PORFILE_H_ +#define _BT_DATRTRANS_PROFILE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_server.h" + +/** @addtogroup SIMP SIMP + * @brief Simple BLE Profile + * @{ + */ + +/** @defgroup SIMP_Service SIMP Service + * @brief Simple BLE Service + * @{ + */ + +/** @defgroup SIMP_Service_Exported_Constants SIMP Service Exported Constants + * @brief macros that other .c files may use all defined here + * @{ + */ + +/** @defgroup SIMP_UUIDs SIMP UUIDs + * @brief Simple BLE Profile UUID definitions + * @{ + */ +#define GATT_UUID_CHAR_DATA 0xFFE1 +#define GATT_UUID_CHAR_DATA_NOTIFY 0xFFE2 +#define GATT_UUID_FLOW_CTRL_NOTIFY 0xFFE3 +/** @} End of SIMP_UUIDs */ + +///@cond +/** @brief Index of each characteristic in Demo Profile service database. */ +#define GATT_UUID_CHAR_DATA_INDEX 0x02 +#define GATT_UUID_CHAR_DATA_NOTIFY_INDEX 0x04 +#define GATT_UUID_CHAR_DATA_CCCD_INDEX (GATT_UUID_CHAR_DATA_NOTIFY_INDEX + 1) +#define GATT_UUID_CHAR_FLOW_NOTIFY_INDEX 0x07 +#define GATT_UUID_CHAR_FLOW_CCCD_INDEX (GATT_UUID_CHAR_FLOW_NOTIFY_INDEX + 1) +///@endcond + +#define DTS_DATA_NOTIFY_DISABLE 0 +#define DTS_DATA_NOTIFY_ENABLE 1 +#define DTS_FLOW_NOTIFY_DISABLE 2 +#define DTS_FLOW_NOTIFY_ENABLE 3 +#define DTS_FLOW_READ_PARA 4 +#define DTS_WRITE_CHAR_DATA 5 +#define DTS_WRITE_FLOW_PARA 6 +typedef enum +{ + DTS_FLOW_INFO +} T_DTS_PARAM_TYPE; + +typedef struct +{ + uint32_t lenth; + uint8_t info[32]; +} _T_Feature_Info; +/** @} End of SIMP_Service_Exported_Constants */ + +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief types that other.c files may use all defined here + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +//typedef struct _TSIMP_WRITE_MSG +//{ +// uint8_t opcode; //!< ref: @ref SIMP_Control_Point_OpCodes, @ref SIMP_Service_Write_Info +// T_WRITE_TYPE write_type; +// uint16_t len; +// uint8_t *pValue; +//} TSIMP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +//typedef union _TSIMP_UPSTREAM_MSG_DATA +//{ +// uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info +// uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info +// TSIMP_WRITE_MSG write; +//} TSIMP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +//typedef struct _TSIMP_CALLBACK_DATA +//{ +// T_SERVICE_CALLBACK_TYPE msg_type; +// uint8_t conn_id; +// TSIMP_UPSTREAM_MSG_DATA msg_data; +//} TSIMP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +typedef union +{ + uint8_t notification_indification_index; + uint8_t read_index; + uint32_t write_index; +} T_DTS_UPSTREAM_MSG_INDEX; +typedef struct +{ + uint8_t len; + uint8_t *data; +} T_DTS_UPSTREAM_MSG_DATA; +typedef struct _TDTS_CALLBACK_DATA +{ + T_SERVICE_CALLBACK_TYPE msg_type; /**< @brief EventId defined upper */ + T_DTS_UPSTREAM_MSG_INDEX msg_index; + T_DTS_UPSTREAM_MSG_DATA msg_data; +} T_DTS_CALLBACK_DATA; + +/** @} End of SIMP_Service_Exported_Types */ + +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief functions that other .c files may use all defined here + * @{ + */ +//extern void Datatrans_SettingServiceUUID(void); +extern T_SERVER_ID Datatrans_AddService(void *pFunc); +bool dts_set_flow_info_parameter(T_DTS_PARAM_TYPE param_type, uint8_t length, uint8_t *p_value); +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +/** @} End of SIMP */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.c b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.c new file mode 100644 index 00000000..fbfd4ca5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.c @@ -0,0 +1,286 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file dataTrans_uart.c +* @brief Data uart operations for testing profiles. +* @details Data uart init and print data through data uart. +* @author +* @date 2015-03-19 +* @version v0.1 +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_DATATRANS) && CONFIG_BT_DATATRANS +#include "bt_datatrans_uart.h" +#include "bt_datatrans_module_param_config.h" +#include "trace_app.h" +#include "app_msg.h" +#include "os_msg.h" +#include "bt_datatrans_multilink_manager.h" +#include "ftl_app.h" +#include "os_timer.h" +#include "gap_conn_le.h" +#include "os_sched.h" +#include "bt_board.h" +#include "serial_api.h" +#include "serial_ex_api.h" +#include +#include "os_task.h" + +/* task queues used to send message from UART. */ +extern T_GAP_CONN_STATE bt_datatrans_gap_conn_state; +extern void *bt_datatrans_evt_queue_handle; +extern void *bt_datatrans_io_queue_handle; + +static serial_t bt_datatrans_sobj; +void *DataTransHandle = NULL; +void *DatatransUartRxSema = NULL; +char uart_rx_buf[8] = {0}; //read data from rx fifo +uint32_t rx_irq_flag = 0; + +#define BT_DATATRANS_UART_TASK_PRIORITY 6 /* Task priorities. */ +#define BT_DATATRANS_UART_TASK_STACK_SIZE 256 * 4 /* Task stack size. */ + +/* send message to bt_datatrans_app_main_task */ +bool datatrans_send_msg_to_app(T_IO_MSG *p_msg) +{ + uint8_t event = EVENT_IO_TO_APP; + + if (os_msg_send(bt_datatrans_io_queue_handle, p_msg, 0) == false) + { + printf("send_msg_to_app fail2\r\n"); + return false; + } + else if (os_msg_send(bt_datatrans_evt_queue_handle, &event, 0) == false) + { + printf("send_msg_to_app fail\r\n"); + return false; + } + return true; +} + + +/* uart tx data */ +void bt_datatrans_uart_tx_char(int ch) +{ + serial_putc(&bt_datatrans_sobj, ch); +} + +/* handle uart rx data */ +void bt_datatrans_uart_rcv_done(uint32_t id) +{ + T_IO_MSG uart_msg; + + transferConfigInfo.uart_idle = 0; + + if ((IO_Receive.WriteOffset + 8) <= RECEIVE_BUF_MAX_LENGTH) + { + memcpy(IO_Receive.buf + IO_Receive.WriteOffset, uart_rx_buf, 8); + IO_Receive.WriteOffset += 8; + if (IO_Receive.WriteOffset == RECEIVE_BUF_MAX_LENGTH) + { + IO_Receive.WriteOffset = 0; + } + + } + else + { + uint16_t len = 0; + len = RECEIVE_BUF_MAX_LENGTH - IO_Receive.WriteOffset; + memcpy(IO_Receive.buf + IO_Receive.WriteOffset, uart_rx_buf, len); + IO_Receive.WriteOffset = 0; + + memcpy(IO_Receive.buf + IO_Receive.WriteOffset, uart_rx_buf+len, 8-len); + IO_Receive.WriteOffset += (8 - len); + } + + if ((8 + IO_Receive.datalen) > RECEIVE_BUF_MAX_LENGTH) /* Rx overrun */ + { + IO_Receive.datalen = RECEIVE_BUF_MAX_LENGTH; + IO_Receive.ReadOffset = IO_Receive.WriteOffset; + } + else + { + IO_Receive.datalen += 8; /* update length */ + } + + if (bt_datatrans_gap_conn_state == GAP_CONN_STATE_CONNECTED) + { + rx_irq_flag++; + if (rx_irq_flag % 31 == 0) // if IO_Receive.datalen >= MTU_SIZE - 3 + { + uart_msg.type = IO_MSG_TYPE_UART; + uart_msg.subtype = IO_MSG_UART_RX; + datatrans_send_msg_to_app(&uart_msg); + } + } + + os_sem_give(DatatransUartRxSema); + +} + + +/* UART RX idle callback function, send uart msg to bt_datatrans_app_main_task */ +void bt_datatrans_uart_rx_idle(void *arg) +{ + T_IO_MSG uart_msg; + int rx_bytes; + + rx_bytes = serial_recv_stream_abort(&bt_datatrans_sobj); + + if (rx_bytes > 0) + { + + if ((IO_Receive.WriteOffset + rx_bytes) <= RECEIVE_BUF_MAX_LENGTH) + { + memcpy(IO_Receive.buf + IO_Receive.WriteOffset, uart_rx_buf, rx_bytes); + IO_Receive.WriteOffset += rx_bytes; + if (IO_Receive.WriteOffset == RECEIVE_BUF_MAX_LENGTH) + { + IO_Receive.WriteOffset = 0; + } + + } + else + { + uint16_t len = 0; + len = RECEIVE_BUF_MAX_LENGTH - IO_Receive.WriteOffset; + memcpy(IO_Receive.buf + IO_Receive.WriteOffset, uart_rx_buf, len); + IO_Receive.WriteOffset = 0; + + memcpy(IO_Receive.buf + IO_Receive.WriteOffset, uart_rx_buf+len, rx_bytes-len); + IO_Receive.WriteOffset += (rx_bytes - len); + } + + if ((rx_bytes + IO_Receive.datalen) > RECEIVE_BUF_MAX_LENGTH) /* Rx overrun */ + { + IO_Receive.datalen = RECEIVE_BUF_MAX_LENGTH; + IO_Receive.ReadOffset = IO_Receive.WriteOffset; + } + else + { + IO_Receive.datalen += rx_bytes; /* update length */ + } + + } + + rx_irq_flag = 0; + uart_msg.type = IO_MSG_TYPE_UART; + uart_msg.subtype = IO_MSG_UART_RX_TIMEOUT; + datatrans_send_msg_to_app(&uart_msg); + transferConfigInfo.uart_idle = 1; + + os_sem_give(DatatransUartRxSema); + +} + +void bt_datatrans_set_baud(void) +{ + /* dataTransInfo.device_mode.baudrateidx */ + switch (transferConfigInfo.baudrate) + { + case 2400: + dataTransInfo.device_mode.baudrateidx = BAUD_2400; + break; + case 4800: + dataTransInfo.device_mode.baudrateidx = BAUD_4800; + break; + case 9600: + dataTransInfo.device_mode.baudrateidx = BAUD_9600; + break; + case 19200: + dataTransInfo.device_mode.baudrateidx = BAUD_19200; + break; + case 38400: + dataTransInfo.device_mode.baudrateidx = BAUD_38400; + break; + case 57600: + dataTransInfo.device_mode.baudrateidx = BAUD_57600; + break; + case 115200: + dataTransInfo.device_mode.baudrateidx = BAUD_115200; + break; + case 921600: + dataTransInfo.device_mode.baudrateidx = BAUD_921600; + break; + default: + dataTransInfo.device_mode.baudrateidx = BAUD_9600; + break; + } + + serial_baud(&bt_datatrans_sobj, transferConfigInfo.baudrate); + + //WRTIE Baud rate idx. + ftl_save(&dataTransInfo.device_mode, INFO_DEVICE_MODE_OFFSET, 4); + +} + +void bt_datatrans_uart_init(void) +{ + serial_init(&bt_datatrans_sobj, (PinName)PA_11, (PinName)PA_12); + serial_baud(&bt_datatrans_sobj, transferConfigInfo.baudrate); + serial_format(&bt_datatrans_sobj, 8, ParityNone, 1); + serial_recv_comp_handler(&bt_datatrans_sobj, (void*)bt_datatrans_uart_rcv_done, (uint32_t)&bt_datatrans_sobj); + hal_uart_rx_idle_timeout_en(&bt_datatrans_sobj.uart_adp, 200, bt_datatrans_uart_rx_idle, NULL); +} + + +void bt_datatrans_uart_task(void *p_param) +{ + int ret = 0; + memset(uart_rx_buf, 0, 8); + rx_irq_flag = 0; + + while(1) + { + ret = serial_recv_stream(&bt_datatrans_sobj, uart_rx_buf, 8); + + if(ret) + { + printf("serial_recv_stream fail, error %d\r\n", ret); + } + + if (os_sem_take(DatatransUartRxSema, 0xFFFFFFFF) == false) { + printf("DatatransUartRxSema take fail\r\n"); + } + } +} + + +void bt_datatrans_uart_task_init(void) +{ + bt_datatrans_uart_init(); + + os_sem_create(&DatatransUartRxSema, 0, 1); + + if(os_task_create(&DataTransHandle, "bt_datatrans_uart_task", bt_datatrans_uart_task, 0, BT_DATATRANS_UART_TASK_STACK_SIZE, + BT_DATATRANS_UART_TASK_PRIORITY) == false) { + printf("bt_datatrans_uart_task create fail\r\n"); + } + +} + +void bt_datatrans_uart_deinit(void) +{ + serial_free(&bt_datatrans_sobj); + memset(&bt_datatrans_sobj,0,sizeof(serial_t)); +} + +void bt_datatrans_uart_task_deinit(void) +{ + + bt_datatrans_uart_deinit(); + + if (DataTransHandle) { + os_task_delete(DataTransHandle); + } + + os_sem_delete(DatatransUartRxSema); + + DataTransHandle = NULL; + DatatransUartRxSema = NULL; + +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.h b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.h new file mode 100644 index 00000000..90fe96d9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.h @@ -0,0 +1,51 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file dataTrans_uart.h +* @brief Data uart operations for testing profiles. +* @details Data uart init and print data through data uart. +* @author +* @date 2015-03-19 +* @version v0.1 +********************************************************************************************************* +*/ + +#ifndef _DATA_TRANSMIT_UART_H_ +#define _DATA_TRANSMIT_UART_H_ + +#include + + +typedef enum +{ + BAUD_2400 = 0, + BAUD_4800 = 1, + BAUD_9600 = 2, + BAUD_19200 = 3, + BAUD_38400 = 4, + BAUD_57600 = 5, + BAUD_115200 = 6, + BAUD_921600 = 7, + BAUD_2000000 = 8, +} BUAD_SET; + +#define IO_MSG_RECEIVED 0x0A +#define IO_MSG_RECEIVE_ERR 0x0B +#define IO_MSG_RECEIVE_END 0x0C +typedef struct +{ + uint8_t cause; + uint32_t mass_data_remainder; +} T_MASS_DATA_RESULT; + +//#define DMA_BLOCK_SIZE 0x800//(244*10) + +void bt_datatrans_uart_tx_char(int ch); +void bt_datatrans_uart_task_init(void); +void bt_datatrans_uart_task_deinit(void); +void bt_datatrans_uart_init(void); +void bt_datatrans_set_baud(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.c new file mode 100644 index 00000000..ef6d92eb --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.c @@ -0,0 +1,2041 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file scatternet_app.c + * @brief This file handles BLE scatternet application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST +#include +#endif +#include +#include + +/** @defgroup SCATTERNET_APP Scatternet Application + * @brief This file handles BLE scatternet application routines. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup SCATTERNET_CLIIENT_CALLBACK + * @{ + */ +T_CLIENT_ID bt_fuzz_test_gaps_client_id; /**< gap service client id*/ +T_CLIENT_ID bt_fuzz_test_bas_client_id; /**< battery service client id*/ +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST +T_CLIENT_ID bt_fuzz_test_gcs_client_id; /**< general client id*/ +#endif + +/** @} */ /* End of group SCATTERNET_CLIIENT_CALLBACK */ + +/** @addtogroup SCATTERNET_SEVER_CALLBACK + * @{ + */ +T_SERVER_ID bt_fuzz_test_simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bt_fuzz_test_bas_srv_id; /**< Battery service id */ +T_SERVER_ID bt_fuzz_test_gls_srv_id; /**< Glucose service id*/ +T_SERVER_ID bt_fuzz_test_ias_srv_id; /**< Immediate alert level service id */ +T_SERVER_ID bt_fuzz_test_hrs_srv_id; /**< Heart rate service id*/ +T_SERVER_ID bt_fuzz_test_dis_srv_id; /**< Device information service id*/ +/** @} */ /* End of group SCATTERNET_SEVER_CALLBACK */ + +T_FUZZ_TESTSUITE testsuite; + +TGATTDBdAddr g_cur_rembd; +bool m_start_pair = false; + +uint16_t read_handle; +uint16_t write_handle; +uint16_t notify_handle = 0x21; //characteristic UUID-16:0x2a36 +uint16_t indicate_handle = 0x1e; ////characteristic UUID-16:0x2a35 + + + +/** @defgroup SCATTERNET_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE bt_fuzz_test_gap_dev_state = {0, 0, 0, 0}; /**< GAP device state */ +/*============================================================================* + * Functions + *============================================================================*/ +void bt_fuzz_test_app_discov_services(uint8_t conn_id, bool start); +void bt_fuzz_test_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_fuzz_test_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + uint8_t rx_char; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_fuzz_test_app_handle_gap_msg(&io_msg); + } + break; +#if defined (CONFIG_BT_USER_COMMAND) && (CONFIG_BT_USER_COMMAND) + case IO_MSG_TYPE_UART: + /* We handle user command informations from Data UART in this branch. */ + rx_char = (uint8_t)io_msg.subtype; + user_cmd_collect(&bt_fuzz_test_user_cmd_if, &rx_char, sizeof(rx_char), bt_fuzz_test_user_cmd_table); + break; +#endif + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; + bt_fuzz_test_app_handle_at_cmd(subtype, arg); + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_fuzz_test_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_fuzz_test_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_fuzz_test_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + uint8_t bt_addr[6]; + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + } + } + + if (bt_fuzz_test_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + data_uart_print("GAP scan start\r\n"); + } + } + + if (bt_fuzz_test_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + data_uart_print("GAP adv stoped: because connection created\r\n"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + data_uart_print("GAP adv stoped\r\n"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + data_uart_print("GAP adv start\r\n"); + } + } + + bt_fuzz_test_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_fuzz_test_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= BT_FUZZ_TEST_APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("bt_fuzz_test_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, bt_fuzz_test_app_link_table[conn_id].conn_state, new_state, disc_cause); + + bt_fuzz_test_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_fuzz_test_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + //data_uart_print("bt_fuzz_test_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x\r\n", conn_id, + //disc_cause); + } + + switch (testsuite) + { + case FUZZ_TESTUITE_BTLE_SMP_510: + case FUZZ_TESTUITE_BTLE_ATT_510: + case FUZZ_TESTUITE_BTLE_PROFILES_510: + le_adv_start(); + break; + /* Ignore coverity issue of CID 14020. */ + case FUZZ_TESTUITE_BTLE_SMPC_510: + if (m_start_pair) + { + le_bond_clear_all_keys(); + } + case FUZZ_TESTUITE_BTLE_ATTC_510: + case FUZZ_TESTUITE_BTLE_HOGP_510: + case FUZZ_TESTUITE_BTLE_HEALTH_510: + os_delay(300); + le_connect(GAP_PHYS_CONN_INIT_1M_BIT, + g_cur_rembd, + GAP_REMOTE_ADDR_LE_PUBLIC, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + break; + + default: + break; + } + + data_uart_print("Disconnect conn_id %d\r\n", conn_id); + memset(&bt_fuzz_test_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, bt_fuzz_test_app_link_table[conn_id].bd_addr, + &bt_fuzz_test_app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(bt_fuzz_test_app_link_table[conn_id].bd_addr), bt_fuzz_test_app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_print("Connected success conn_id %d\r\n", conn_id); + switch (testsuite) + { + case FUZZ_TESTUITE_BTLE_SMPC_510: + if (m_start_pair) + { + le_bond_pair(conn_id); + } + break; + + default: + break; + } + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_fuzz_test_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_fuzz_test_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_fuzz_test_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_print("Pair success\r\n"); + APP_PRINT_INFO0("bt_fuzz_test_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + }else + { + data_uart_print("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_fuzz_test_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_fuzz_test_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_fuzz_test_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_fuzz_test_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); + data_uart_print("bt_fuzz_test_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST + switch (testsuite) + { + case FUZZ_TESTUITE_BTLE_ATTC_510: + bt_fuzz_test_app_discov_services(conn_id, true); + break; + + default: + break; + } +#endif +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_fuzz_test_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_fuzz_test_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_print("bt_fuzz_test_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x\r\n", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_fuzz_test_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + data_uart_print("bt_fuzz_test_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_fuzz_test_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_fuzz_test_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_fuzz_test_app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + bt_fuzz_test_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_fuzz_test_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_fuzz_test_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_fuzz_test_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_fuzz_test_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + data_uart_print("GAP_MSG_LE_BOND_JUST_WORK\r\n"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: //passkey entry + { + uint32_t display_value = 000000; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + //le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: //numeric comperison + { + uint32_t display_value = 000000; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + //le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + data_uart_print("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + uint32_t passkey = 000000; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + default: + APP_PRINT_ERROR1("bt_fuzz_test_app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group SCATTERNET_GAP_MSG */ + +/** @defgroup SCATTERNET_SCAN_MGR Scan Information manager + * @brief Scan Information manager + * @{ + */ +/** + * @brief Use 16 bit uuid to filter scan information + * @param[in] uuid 16 bit UUID. + * @param[in] scan_info point to scan information data. + * @return filter result + * @retval true found success + * @retval false not found + */ +bool filter_scan_info_by_uuid(uint16_t uuid, T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length < 1) || (length >= 31)) + { + return false; + } + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *p_uuid); + if (*p_uuid == uuid) + { + return true; + } + p_uuid++; + i -= 2; + } + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} +/** @} */ /* End of group SCATTERNET_SCAN_MGR */ + +void bt_fuzz_test_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("bt_fuzz_test_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_scatternet_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, + *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, + data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", + *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); +// BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} + + +/** @defgroup SCATTERNET_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_fuzz_test_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + char adv_type[20]; + char remote_addr_type[10]; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id %d cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + data_uart_print("GAP_MSG_LE_READ_RSSI:conn_id %d cause 0x%x rssi %d\r\n", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + data_uart_print("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x\r\n", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + data_uart_print("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x\r\n", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x\r\n", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + /* If you want to parse the scan info, please reference function ble_central_app_parse_scan_info. */ + sprintf(adv_type,"%s",(p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_UNDIRECTED)? "CON_UNDIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_DIRECTED)? "CON_DIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCANNABLE)? "SCANABLE_UNDIRCT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_NON_CONNECTABLE)? "NON_CONNECTABLE": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCAN_RSP)? "SCAN_RSP":"unknown"); + sprintf(remote_addr_type,"%s",(p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_PUBLIC)? "public": + (p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_RANDOM)? "random":"unknown"); + + BLE_PRINT("ADVType\t\t\t| AddrType\t|%s\t\t\t|rssi\n\r","BT_Addr"); + BLE_PRINT("%s\t\t%s\t"BD_ADDR_FMT"\t%d\n\r",adv_type,remote_addr_type,BD_ADDR_ARG(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->rssi); + + bt_fuzz_test_app_parse_scan_info(p_data->p_le_scan_info); + break; + + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + data_uart_print("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x\r\n", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + data_uart_print("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x\r\n", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + data_uart_print("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x\r\n", + p_data->p_le_adv_update_param_rsp->cause); + break; + +// case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: +// APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", +// p_data->p_le_disable_slave_latency_rsp->cause); +// break; + +// case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: +// APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", +// p_data->p_le_update_passed_chann_map_rsp->cause); +// break; + default: + APP_PRINT_ERROR1("bt_fuzz_test_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group SCATTERNET_GAP_CALLBACK */ + +/** @defgroup CENTRAL_SRV_DIS GATT Services discovery and storage + * @brief GATT Services discovery and storage + * @{ + */ +/** + * @brief Discovery GATT services + * @param conn_id connection ID. + * @param start first call. true - first call this function after conncection, false - not first + * @retval None + */ +void bt_fuzz_test_app_discov_services(uint8_t conn_id, bool start) +{ + if (bt_fuzz_test_app_link_table[conn_id].conn_state != GAP_CONN_STATE_CONNECTED) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: conn_id %d not connected ", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: conn_id %d not connected\r\n ", conn_id); + return; + } +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST + if (start) + { + data_uart_print("\n\rDiscover all primary services\r\n"); + if (gcs_all_primary_srv_discovery(conn_id) == true) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover all primary services failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover all primary services failed conn_id %d\r\n", conn_id); + } + return; + } + if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_GAPS_FLAG) == 0) + { + data_uart_print("\n\rDiscover gaps service\r\n"); + if (gaps_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover gaps failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover gaps failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_BAS_FLAG) == 0) + { + data_uart_print("\n\rDiscover bas service\r\n"); + if (bas_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover bas failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover bas failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_FLAG) == 0) + { + data_uart_print("\n\rDiscover char\r\n"); + if (gcs_all_char_discovery(conn_id, 0x0001, 0xFFFF) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover char failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover char failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG1) == 0) + { + data_uart_print("\n\rDiscover decriptor_0x0016.....\r\n"); + if (gcs_all_char_descriptor_discovery(conn_id, 0x0016, 0x0016) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG2) == 0) + { + data_uart_print("\n\rDiscover decriptor_0x001a.....\r\n"); + if (gcs_all_char_descriptor_discovery(conn_id, 0x001a, 0x001a) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG3) == 0) + { + data_uart_print("\n\rDiscover decriptor_0x001e.....\r\n"); + if (gcs_all_char_descriptor_discovery(conn_id, 0x001e, 0x001e) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG4) == 0) + { + data_uart_print("\n\rDiscover decriptor_0x0021.....\r\n"); + if (gcs_all_char_descriptor_discovery(conn_id, 0x0021, 0x0021) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: discover char descriptor failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_READ_FLAG) == 0) + { + data_uart_print("\n\rRead.....\r\n"); + if (gcs_attr_read(conn_id, read_handle) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: read failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: read failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_WRITE_FLAG) == 0) + { + data_uart_print("\n\rWrite.....\r\n"); + uint8_t data[1] = {0x1}; + if (gcs_attr_write(conn_id, GATT_WRITE_TYPE_REQ, write_handle, 1, data) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: write failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: write failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_NOTIFY_FLAG) == 0) + { + data_uart_print("\n\rEnable notification.....\r\n"); + uint8_t data[1] = {0x01}; + if (gcs_attr_write(conn_id, GATT_WRITE_TYPE_REQ, notify_handle, 1, data) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: enable notification failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: enable notification failed conn_id %d\r\n", conn_id); + } + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_INDICATE_FLAG) == 0) + { + data_uart_print("\n\rEnable indication.....\r\n"); + uint8_t data[1] = {0x02}; + if (gcs_attr_write(conn_id, GATT_WRITE_TYPE_REQ, indicate_handle, 1, data) != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("bt_fuzz_test_app_discov_services: enable indication failed conn_id %d", conn_id); + data_uart_print("bt_fuzz_test_app_discov_services: enable indication failed conn_id %d\r\n", conn_id); + } + } + else + { + APP_PRINT_INFO2("bt_fuzz_test_app_discov_services: discover complete, conn_id %d, srv_found_flags 0x%x", + conn_id, bt_fuzz_test_app_link_table[conn_id].srv_found_flags); + data_uart_print("bt_fuzz_test_app_discov_services: discover complete, conn_id %d, srv_found_flags 0x%x\r\n", + conn_id, bt_fuzz_test_app_link_table[conn_id].srv_found_flags); + } +#endif + return; +} +/** @} */ /* End of group CENTRAL_SRV_DIS */ + + +/** @defgroup SCATTERNET_CLIIENT_CALLBACK Profile Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_fuzz_test_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_fuzz_test_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_fuzz_test_gaps_client_id) + { + T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data; + switch (p_gaps_cb_data->cb_type) + { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_gaps_cb_data->cb_content.disc_state) + { + case DISC_GAPS_DONE: + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_GAPS_FLAG; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_GAPS_FLAG; + bt_fuzz_test_app_discov_services(conn_id, false); + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("bt_fuzz_test_app_client_callback: discover gaps procedure done."); + data_uart_print("bt_fuzz_test_app_client_callback: discover gaps procedure done.\r\n"); + break; + case DISC_GAPS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("bt_fuzz_test_app_client_callback: discover gaps request failed."); + data_uart_print("bt_fuzz_test_app_client_callback: discover gaps request failed.\r\n"); + break; + default: + break; + } + break; + case GAPS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_gaps_cb_data->cb_content.read_result.type) + { + case GAPS_READ_DEVICE_NAME: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.", + TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value)); + data_uart_print("GAPS_READ_DEVICE_NAME: device name %s.\r\n", + TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value)); + } + else + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + data_uart_print("GAPS_READ_DEVICE_NAME: failded cause 0x%x\r\n", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_APPEARANCE: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance %d", + p_gaps_cb_data->cb_content.read_result.data.appearance); + data_uart_print("GAPS_READ_APPEARANCE: appearance %d\r\n", + p_gaps_cb_data->cb_content.read_result.data.appearance); + } + else + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + data_uart_print("GAPS_READ_APPEARANCE: failded cause 0x%x\r\n", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_CENTRAL_ADDR_RESOLUTION: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d", + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + data_uart_print("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d\r\n", + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + } + else + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + data_uart_print("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x\r\n", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + default: + break; + } + break; + + default: + break; + } + } + else if (client_id == bt_fuzz_test_bas_client_id) + { + T_BAS_CLIENT_CB_DATA *p_bas_cb_data = (T_BAS_CLIENT_CB_DATA *)p_data; + switch (p_bas_cb_data->cb_type) + { + case BAS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_bas_cb_data->cb_content.disc_state) + { + case DISC_BAS_DONE: + /* Discovery BAS procedure successfully done. */ + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_BAS_FLAG; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_BAS_FLAG; + bt_fuzz_test_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_fuzz_test_app_client_callback: discover bas procedure done"); + data_uart_print("bt_fuzz_test_app_client_callback: discover bas procedure done\r\n"); + break; + case DISC_BAS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("bt_fuzz_test_app_client_callback: discover bas procedure failed"); + data_uart_print("bt_fuzz_test_app_client_callback: discover bas procedure failed\r\n"); + break; + default: + break; + } + break; + case BAS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_bas_cb_data->cb_content.read_result.type) + { + case BAS_READ_BATTERY_LEVEL: + if (p_bas_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery level %d", + p_bas_cb_data->cb_content.read_result.data.battery_level); + data_uart_print("BAS_READ_BATTERY_LEVEL: battery level %d\r\n", + p_bas_cb_data->cb_content.read_result.data.battery_level); + } + else + { + APP_PRINT_ERROR1("BAS_READ_BATTERY_LEVEL: failed cause 0x%x", + p_bas_cb_data->cb_content.read_result.cause); + data_uart_print("BAS_READ_BATTERY_LEVEL: failed cause 0x%x\r\n", + p_bas_cb_data->cb_content.read_result.cause); + } + break; + case BAS_READ_NOTIFY: + if (p_bas_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("BAS_READ_NOTIFY: notify %d", + p_bas_cb_data->cb_content.read_result.data.notify); + data_uart_print("BAS_READ_NOTIFY: notify %d\r\n", + p_bas_cb_data->cb_content.read_result.data.notify); + } + else + { + APP_PRINT_ERROR1("BAS_READ_NOTIFY: failed cause 0x%x", + p_bas_cb_data->cb_content.read_result.cause); + data_uart_print("BAS_READ_NOTIFY: failed cause 0x%x\r\n", + p_bas_cb_data->cb_content.read_result.cause); + }; + break; + + default: + break; + } + break; + case BAS_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_bas_cb_data->cb_content.write_result.type) + { + case BAS_WRITE_NOTIFY_ENABLE: + APP_PRINT_INFO1("BAS_WRITE_NOTIFY_ENABLE: write result 0x%x", + p_bas_cb_data->cb_content.write_result.cause); + data_uart_print("BAS_WRITE_NOTIFY_ENABLE: write result 0x%x\r\n", + p_bas_cb_data->cb_content.write_result.cause); + break; + case BAS_WRITE_NOTIFY_DISABLE: + APP_PRINT_INFO1("BAS_WRITE_NOTIFY_DISABLE: write result 0x%x", + p_bas_cb_data->cb_content.write_result.cause); + data_uart_print("BAS_WRITE_NOTIFY_DISABLE: write result 0x%x\r\n", + p_bas_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + case BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + APP_PRINT_INFO1("BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: battery level %d", + p_bas_cb_data->cb_content.notify_data.battery_level); + data_uart_print("BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: battery level %d\r\n", + p_bas_cb_data->cb_content.notify_data.battery_level); + break; + + default: + break; + } + } + + return result; +} + +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST +void bt_fuzz_test_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + data_uart_print("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\r\n", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + data_uart_print("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + bt_fuzz_test_app_discov_services(conn_id, false); + + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_print("SRV DATA[%d]: service range: 0x%x-0x%x\r\n", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_print("SRV DATA[%d]: service range: 0x%x-0x%x\r\n", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_print("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\r\n", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_print("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_FLAG; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_FLAG; + bt_fuzz_test_app_discov_services(conn_id, false); + + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_print("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\r\n", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_print("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + data_uart_print("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + data_uart_print("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\r\n", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + data_uart_print("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + + if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG1) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG1; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG1; + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG2) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG2; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG2; + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG3) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG3; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG3; + } + else if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG4) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG4; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG4; + } + bt_fuzz_test_app_discov_services(conn_id, false); + + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + break; + } +} +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_fuzz_test_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_fuzz_test_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + data_uart_print("bt_fuzz_test_gcs_client_callback: client_id %d, conn_id %d\r\n", + client_id, conn_id); + if (client_id == bt_fuzz_test_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_fuzz_test_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_print("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\r\n", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_print("READ VALUE:\r\n"); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_print("0x%2X", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_print("\n\r"); + if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_READ_FLAG) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_READ_FLAG; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_READ_FLAG; + } + bt_fuzz_test_app_discov_services(conn_id, false); + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x ,handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_print("WRITE RESULT: cause 0x%x ,handle 0x%x, type %d\r\n", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_WRITE_FLAG) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_WRITE_FLAG; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_WRITE_FLAG; + bt_fuzz_test_app_discov_services(conn_id, false); + }else if((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_NOTIFY_FLAG) == 0) + { + bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_NOTIFY_FLAG; + bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_NOTIFY_FLAG; + bt_fuzz_test_app_discov_services(conn_id, false); + } + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_print("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_print("INDICATION VALUE: %b\r\n", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_print("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_print("NOTIFICATION VALUE: %b\r\n", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + } + //if ((bt_fuzz_test_app_link_table[conn_id].discovered_flags & BT_FUZZ_TEST_APP_NOTIFY_FLAG) == 0) + //{ + // bt_fuzz_test_app_link_table[conn_id].discovered_flags |= BT_FUZZ_TEST_APP_NOTIFY_FLAG; + //bt_fuzz_test_app_link_table[conn_id].srv_found_flags |= BT_FUZZ_TEST_APP_NOTIFY_FLAG; + //bt_fuzz_test_app_discov_services(conn_id, false); + //} + break; + default: + break; + } + } + + return result; +} +#endif + +/** @} */ /* End of group SCATTERNET_CLIENT_CALLBACK */ +/** @defgroup SCATTERNET_SEVER_CALLBACK Profile Server Callback Event Handler + * @brief Handle profile server callback event + * @{ + */ +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_fuzz_test_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + data_uart_print("PROFILE_EVT_SRV_REG_COMPLETE: result %d\r\n", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + data_uart_print("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + data_uart_print("PROFILE_EVT_SEND_DATA_COMPLETE success\r\n"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + data_uart_print("PROFILE_EVT_SEND_DATA_COMPLETE failed\r\n"); + } + break; + + default: + break; + } + } + else if (service_id == bt_fuzz_test_simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + data_uart_print("SIMP_NOTIFY_INDICATE_V3_ENABLE\r\n"); + } + break; + + case BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + data_uart_print("SIMP_NOTIFY_INDICATE_V3_DISABLE\r\n"); + } + break; + case BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + data_uart_print("SIMP_NOTIFY_INDICATE_V4_ENABLE\r\n"); + } + break; + case BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + data_uart_print("SIMP_NOTIFY_INDICATE_V4_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == BT_FUZZ_TEST_SIMP_READ_V1) + { + uint8_t value[1] = {0x01}; + APP_PRINT_INFO0("SIMP_READ_V1"); + data_uart_print("SIMP_READ_V1\r\n"); + bt_fuzz_test_simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 1, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case BT_FUZZ_TEST_SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_print("SIMP_WRITE_V2: write type %d, len %d\r\n", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bt_fuzz_test_bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + data_uart_print("BAS_NOTIFY_BATTERY_LEVEL_ENABLE\r\n"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + data_uart_print("BAS_NOTIFY_BATTERY_LEVEL_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + data_uart_print("BAS_READ_BATTERY_LEVEL: battery_level %d\r\n", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + + default: + break; + } + } + else if (service_id == bt_fuzz_test_gls_srv_id) + { + T_GLS_CALLBACK_DATA *p_gls_cb_data = (T_GLS_CALLBACK_DATA *)p_data; + switch (p_gls_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_gls_cb_data->msg_data.notify_indicate_index) + { + case GLS_EVT_GLC_MEASUREMENT_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("GLS_EVT_GLC_MEASUREMENT_NOTIFY_ENABLE"); + data_uart_print("GLS_EVT_GLC_MEASUREMENT_NOTIFY_ENABLE\r\n"); + } + break; + + case GLS_EVT_GLC_MEASUREMENT_NOTIFY_DISABLE: + { + APP_PRINT_INFO0("GLS_EVT_GLC_MEASUREMENT_NOTIFY_DISABLE"); + data_uart_print("GLS_EVT_GLC_MEASUREMENT_NOTIFY_DISABLE\r\n"); + } + break; + case GLS_EVT_GLC_MEASUREMENT_CONTEXT_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("GLS_EVT_GLC_MEASUREMENT_CONTEXT_NOTIFY_ENABLE"); + data_uart_print("GLS_EVT_GLC_MEASUREMENT_CONTEXT_NOTIFY_ENABLE\r\n"); + } + break; + + case GLS_EVT_GLC_MEASUREMENT_CONTEXT_NOTIFY_DISABLE: + { + APP_PRINT_INFO0("GLS_EVT_GLC_MEASUREMENT_CONTEXT_NOTIFY_DISABLE"); + data_uart_print("GLS_EVT_GLC_MEASUREMENT_CONTEXT_NOTIFY_DISABLE\r\n"); + } + break; + case GLS_EVT_GLC_RACP_INDICATE_ENABLE: + { + APP_PRINT_INFO0("GLS_EVT_GLC_RACP_INDICATE_ENABLE"); + data_uart_print("GLS_EVT_GLC_RACP_INDICATE_ENABLE\r\n"); + } + break; + + case GLS_EVT_GLC_RACP_INDICATE_DISABLE: + { + APP_PRINT_INFO0("GLS_EVT_GLC_RACP_INDICATE_DISABLE"); + data_uart_print("GLS_EVT_GLC_RACP_INDICATE_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_gls_cb_data->msg_data.read_value_index == GLS_CHAR_GLC_FEATURE_INDEX) + { + uint8_t glc_features = 90; + APP_PRINT_INFO1("GLS_PARAM_GLC_FEATURES: glc_features %d", glc_features); + data_uart_print("GLS_PARAM_GLC_FEATURES: glc_features %d\r\n", glc_features); + gls_set_parameter(GLS_PARAM_GLC_FEATURES, 1, &glc_features); + } + } + break; + + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + APP_PRINT_INFO1("GLS_CHAR_GLC_RACP_INDEX: racp_value %d", p_gls_cb_data->msg_data.write); + data_uart_print("GLS_CHAR_GLC_RACP_INDEX: racp_value %d\r\n", p_gls_cb_data->msg_data.write); + } + break; + + default: + break; + } + } + + else if (service_id == bt_fuzz_test_ias_srv_id) + { + T_IAS_CALLBACK_DATA *p_ias_cb_data = (T_IAS_CALLBACK_DATA *)p_data; + switch (p_ias_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + APP_PRINT_INFO1("GATT_SVC_PXP_IMMEDIATE_AlERT_VALUE_INDEX: alert_level %d", + p_ias_cb_data->msg_data.write_alert_level); + data_uart_print("GATT_SVC_PXP_IMMEDIATE_AlERT_VALUE_INDEX: alert_level %d\r\n", + p_ias_cb_data->msg_data.write_alert_level); + } + break; + + default: + break; + } + } + else if (service_id == bt_fuzz_test_hrs_srv_id) + { + T_HRS_CALLBACK_DATA *p_hrs_cb_data = (T_HRS_CALLBACK_DATA *)p_data; + switch (p_hrs_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_hrs_cb_data->msg_data.notification_indification_index) + { + case HRS_NOTIFY_INDICATE_MEASUREMENT_VALUE_ENABLE: + { + T_HEART_RATE_MEASUREMENT_VALUE_FLAG flag; + uint16_t measurement_value = 267; + uint16_t energy_expended = 5; + uint16_t rr_interval = 6; + flag.heart_rate_value_format_bit = 1; + flag.sensor_contact_status_bits = 3; + flag.energy_expended_status_bit = 1; + flag.rr_interval_bit = 1; + flag.rfu = 0; + + hrs_set_parameter(HRS_HEART_RATE_MEASUREMENT_PARAM_FLAG, 1, &flag); + hrs_set_parameter(HRS_HEART_RATE_MEASUREMENT_PARAM_MEASUREMENT_VALUE, 2, &measurement_value); + hrs_set_parameter(HRS_HEART_RATE_MEASUREMENT_PARAM_ENERGY_EXPENDED, 2, &energy_expended); + hrs_set_parameter(HRS_HEART_RATE_MEASUREMENT_PARAM_RR_INTERVAL, 2, &rr_interval); + APP_PRINT_INFO4("HRS_NOTIFY_INDICATE_MEASUREMENT_VALUE_ENABLE: flag 0x%x, measurement_value 0x%x, energy_expended 0x%x, rr_interval 0x%x", + flag, measurement_value, energy_expended, rr_interval); + data_uart_print("HRS_NOTIFY_INDICATE_MEASUREMENT_VALUE_ENABLE: flag 0x%x, measurement_value 0x%x, energy_expended 0x%x, rr_interval 0x%x\r\n", + flag, measurement_value, energy_expended, rr_interval); + } + break; + + case HRS_NOTIFY_INDICATE_MEASUREMENT_VALUE_DISABLE: + { + APP_PRINT_INFO0("HRS_NOTIFY_INDICATE_MEASUREMENT_VALUE_DISABLE"); + data_uart_print("HRS_NOTIFY_INDICATE_MEASUREMENT_VALUE_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_hrs_cb_data->msg_data.read_value_index == HRS_READ_BODY_SENSOR_LOCATION_VALUE) + { + uint8_t hrs_body_sensor_location = 6; + + hrs_set_parameter(HRS_BODY_SENSOR_LOCATION_PARAM_VALUE, 1, &hrs_body_sensor_location); + APP_PRINT_INFO1("HRS_READ_BODY_SENSOR_LOCATION_VALUE: hrs_body_sensor_location %d", + hrs_body_sensor_location); + data_uart_print("HRS_READ_BODY_SENSOR_LOCATION_VALUE: hrs_body_sensor_location %d\r\n", + hrs_body_sensor_location); + } + } + break; + + + default: + break; + } + } + + return app_result; +} +#endif +/** @} */ /* End of group SCATTERNET_SEVER_CALLBACK */ +/** @} */ /* End of group SCATTERNET_APP */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.h new file mode 100644 index 00000000..5bd52ae1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.h @@ -0,0 +1,138 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file scatternet_app.h + * @brief This file handles BLE scatternet application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_FUZZ_TEST_APP_H_ +#define _BT_FUZZ_TEST_APP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include + +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_CLIENT_ID bt_fuzz_test_gaps_client_id; /**< Simple ble service client id*/ +extern T_CLIENT_ID bt_fuzz_test_bas_client_id; /**< battery service client id*/ +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST +extern T_CLIENT_ID bt_fuzz_test_gcs_client_id; /**< general client id*/ +#endif +#if 0 +extern T_SERVER_ID bt_fuzz_test_simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bt_fuzz_test_bas_srv_id; /**< Battery service id */ +extern T_SERVER_ID bt_fuzz_test_gls_srv_id; /**< Glucose service id*/ +#endif +extern T_SERVER_ID bt_fuzz_test_ias_srv_id; /**< Immediate alert level service id */ +extern T_SERVER_ID bt_fuzz_test_hrs_srv_id; /**< Heart rate service id*/ +extern T_SERVER_ID bt_fuzz_test_gls_srv_id; /**< Glucose service id*/ +extern T_SERVER_ID bt_fuzz_test_dis_srv_id; /**< Device information service id*/ +extern T_SERVER_ID bt_fuzz_test_bas_srv_id; /**< Battery service id */ +extern T_SERVER_ID bt_fuzz_test_simp_srv_id; /**< Simple ble service id*/ + +/** @brief I/O Capabilities */ +typedef enum +{ + FUZZ_TESTUITE_BTLE_SMP_510, //!< Only a Display present, no Keyboard or Yes/No Keys. + FUZZ_TESTUITE_BTLE_SMPC_510, //!< Display and Yes/No Keys present. + FUZZ_TESTUITE_BTLE_ATT_510, //!< Only a Keyboard present, no Display. + FUZZ_TESTUITE_BTLE_ATTC_510, //!< No input/output capabilities. + FUZZ_TESTUITE_BTLE_PROFILES_510, + FUZZ_TESTUITE_BTLE_HOGP_510, + FUZZ_TESTUITE_BTLE_HEALTH_510, + FUZZ_TESTUITE_BTLE_AD_510, + FUZZ_TESTUITE_BTLE_RESERVER = 0xff, +} T_FUZZ_TESTSUITE; +#if 0 +typedef enum +{ + FUZZ_TESTUITE_BTLE_SMP_LEGACY_510, //!< Only a Display present, no Keyboard or Yes/No Keys. + FUZZ_TESTUITE_BTLE_SMP_LEGACY_540, //!< Keyboard dispaly present. + FUZZ_TESTUITE_BTLE_SMP_LEGACY_D11, //!< Only a Display present, no Keyboard or Yes/No Keys. + FUZZ_TESTUITE_BTLE_SMP_LEGACY_D21, //!< Keyboard present. + FUZZ_TESTUITE_BTLE_SMP_LEGACY_D41, //!< Keyboard dispaly present. + FUZZ_TESTUITE_BTLE_SMP_SC_D11, //!< Only a Display present, no Keyboard or Yes/No Keys. + FUZZ_TESTUITE_BTLE_SMPC_510, //!< Display and Yes/No Keys present. + FUZZ_TESTUITE_BTLE_ATT_510, //!< Only a Keyboard present, no Display. + FUZZ_TESTUITE_BTLE_ATTC_510, //!< No input/output capabilities. + FUZZ_TESTUITE_BTLE_PROFILES_510, + FUZZ_TESTUITE_BTLE_HOGP_510, + FUZZ_TESTUITE_BTLE_HEALTH_510, + FUZZ_TESTUITE_BTLE_AD_510, + FUZZ_TESTUITE_BTLE_RESERVER = 0xff, +} T_FUZZ_TESTSUITE; +#endif + +extern T_FUZZ_TESTSUITE testsuite; + +typedef uint8_t TGATTDBdAddr[6]; +extern TGATTDBdAddr g_cur_rembd; + +extern bool m_start_pair; +extern uint16_t read_handle; +extern uint16_t write_handle; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_fuzz_test_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_fuzz_test_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_fuzz_test_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +T_APP_RESULT bt_fuzz_test_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST +T_APP_RESULT bt_fuzz_test_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_flags.h new file mode 100644 index 00000000..ad0452ec --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_flags.h @@ -0,0 +1,38 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_FUZZ_TEST_APP_FLAGS_H_ +#define _BT_FUZZ_TEST_APP_FLAGS_H_ + +//#include "upperstack_config.h" + +/** @defgroup SCATTERNET_Config Scatternet App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define BT_FUZZ_TEST_APP_MAX_LINKS 2 +/** @brief Config DLPS: 0-Disable DLPS, 1-Enable DLPS */ +#define BT_FUZZ_TEST_F_BT_DLPS_EN 0 +/** @brief Use general client: 0-Disable general client, 1-Enable general client */ +#define BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST 1 +/** @brief Config the discovery table number */ +#define BT_FUZZ_TEST_APP_MAX_DISCOV_TABLE_NUM 50 + +/** @} */ /* End of group SCATTERNET_Config */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_main.c new file mode 100644 index 00000000..1ea472c5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_main.c @@ -0,0 +1,306 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace_uart.h" +#include +#include "wifi_constants.h" +#include +#include "rtk_coex.h" +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#if BT_FUZZ_TEST_F_BT_DLPS_EN +#include +#include +#endif +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST +#include +#endif +#include + +extern bool bt_trace_uninit(void); +/** @defgroup SCATTERNET_DEMO_MAIN Scatternet Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default scan interval (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_INTERVAL 0x20 +/** @brief Default scan window (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_WINDOW 0x10 + +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default Maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, + GAP_ADTYPE_APPEARANCE, + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + + 0x0A, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'F', 'U', 'Z', 'Z', '_', 'T', 'E', 'S', 'T', +}; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_fuzz_test_app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "FUZZ_TEST"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Scan parameters */ + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_DISABLE; + + /* advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MIN; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = true; + uint32_t auth_fix_passkey = 000000; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_fuzz_test_app_gap_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_fuzz_test_app_le_profile_init(void) +{ + server_init(6); + bt_fuzz_test_bas_srv_id = bas_add_service((void *)bt_fuzz_test_app_profile_callback); + bt_fuzz_test_gls_srv_id = gls_add_service((void *)bt_fuzz_test_app_profile_callback); + + bt_fuzz_test_ias_srv_id = ias_add_service((void *)bt_fuzz_test_app_profile_callback); + bt_fuzz_test_hrs_srv_id = hrs_add_service((void *)bt_fuzz_test_app_profile_callback); + + bt_fuzz_test_dis_srv_id = dis_add_service((void *)bt_fuzz_test_app_profile_callback); + bt_fuzz_test_simp_srv_id = bt_fuzz_test_simp_ble_service_add_service((void *)bt_fuzz_test_app_profile_callback); + server_register_app_cb(bt_fuzz_test_app_profile_callback); + + client_init(3); + bt_fuzz_test_gaps_client_id = gaps_add_client(bt_fuzz_test_app_client_callback, BT_FUZZ_TEST_APP_MAX_LINKS); +#if BT_FUZZ_TEST_APP_GENERAL_CLIENT_TEST + bt_fuzz_test_gcs_client_id = gcs_add_client(bt_fuzz_test_gcs_client_callback, BT_FUZZ_TEST_APP_MAX_LINKS, BT_FUZZ_TEST_APP_MAX_DISCOV_TABLE_NUM); +#endif + bt_fuzz_test_bas_client_id = bas_add_client(bt_fuzz_test_app_client_callback, BT_FUZZ_TEST_APP_MAX_LINKS); + client_register_general_client_cb(bt_fuzz_test_app_client_callback); +} + +void bt_fuzz_test_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_FUZZ_TEST_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_FUZZ_TEST_APP_MAX_LINKS); +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Central Client APP, thus only one APP task is init here + * @return void + */ +void bt_fuzz_test_task_init(void) +{ + bt_fuzz_test_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_fuzz_test_app_main(void) +{ + bt_trace_init(); + bt_fuzz_test_stack_config_init(); + bte_init(); + le_gap_init(BT_FUZZ_TEST_APP_MAX_LINKS); + bt_fuzz_test_app_le_gap_init(); + bt_fuzz_test_app_le_profile_init(); + bt_fuzz_test_task_init(); + + return 0; +} + +int bt_fuzz_test_app_init(void) +{ + //int bt_stack_already_on = 0; + //(void) bt_stack_already_on; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT Fuzz Test]BT Stack already on\n\r"); + return 0; + } + else + bt_fuzz_test_app_main(); + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern void bt_fuzz_test_task_deinit(void); +extern void gcs_delete_client(void); +extern void gaps_delete_client(void); +extern void bas_delete_client(void); +void bt_fuzz_test_app_deinit(void) +{ + bt_fuzz_test_task_deinit(); + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Fuzz Test]BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { + gcs_delete_client(); + gaps_delete_client(); + bas_delete_client(); + bte_deinit(); + bt_trace_uninit(); + printf("[BT Fuzz Test]BT Stack deinitalized\n\r"); + } +#endif +} +#endif +/** @} */ /* End of group SCATTERNET_DEMO_MAIN */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.c new file mode 100644 index 00000000..ff23ab3b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.c @@ -0,0 +1,139 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** @defgroup SCATTERNET_APP_TASK Scatternet App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ + +#define BT_FUZZ_TEST_APP_TASK_PRIORITY 1 //!< Task priorities +#define BT_FUZZ_TEST_APP_TASK_STACK_SIZE 256 * 6 //!< Task stack size +#define BT_FUZZ_TEST_MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define BT_FUZZ_TEST_MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define BT_FUZZ_TEST_MAX_NUMBER_OF_EVENT_MESSAGE (BT_FUZZ_TEST_MAX_NUMBER_OF_GAP_MESSAGE + BT_FUZZ_TEST_MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_fuzz_test_app_task_handle; //!< APP Task handle +void *bt_fuzz_test_evt_queue_handle; //!< Event queue handle +void *bt_fuzz_test_io_queue_handle; //!< IO queue handle + +extern T_GAP_DEV_STATE bt_fuzz_test_gap_dev_state; +/*============================================================================* + * Functions + *============================================================================*/ +void bt_fuzz_test_app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void bt_fuzz_test_app_task_init() +{ + os_task_create(&bt_fuzz_test_app_task_handle, "bt_fuzz_test_app", bt_fuzz_test_app_main_task, 0, BT_FUZZ_TEST_APP_TASK_STACK_SIZE, + BT_FUZZ_TEST_APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_fuzz_test_app_main_task(void *p_param) +{ + uint8_t event; + + os_msg_queue_create(&bt_fuzz_test_io_queue_handle, BT_FUZZ_TEST_MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_fuzz_test_evt_queue_handle, BT_FUZZ_TEST_MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(bt_fuzz_test_evt_queue_handle, bt_fuzz_test_io_queue_handle, BT_FUZZ_TEST_MAX_NUMBER_OF_GAP_MESSAGE); + + data_uart_init(bt_fuzz_test_evt_queue_handle, bt_fuzz_test_io_queue_handle); +#if defined (CONFIG_BT_USER_COMMAND) && (CONFIG_BT_USER_COMMAND) + user_cmd_init(&bt_fuzz_test_user_cmd_if, "fuzz_test"); +#endif + + while (true) + { + if (os_msg_recv(bt_fuzz_test_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_fuzz_test_io_queue_handle, &io_msg, 0) == true) + { + bt_fuzz_test_app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +void bt_fuzz_test_task_deinit(void) +{ + if (bt_fuzz_test_app_task_handle) { + os_task_delete(bt_fuzz_test_app_task_handle); + } + if (bt_fuzz_test_io_queue_handle) { + os_msg_queue_delete(bt_fuzz_test_io_queue_handle); + } + if (bt_fuzz_test_evt_queue_handle) { + os_msg_queue_delete(bt_fuzz_test_evt_queue_handle); + } + bt_fuzz_test_io_queue_handle = NULL; + bt_fuzz_test_evt_queue_handle = NULL; + bt_fuzz_test_app_task_handle = NULL; + + bt_fuzz_test_gap_dev_state.gap_init_state = 0; + bt_fuzz_test_gap_dev_state.gap_adv_sub_state = 0; + bt_fuzz_test_gap_dev_state.gap_adv_state = 0; + bt_fuzz_test_gap_dev_state.gap_scan_state = 0; + bt_fuzz_test_gap_dev_state.gap_conn_state = 0; + +} +#endif +/** @} */ /* End of group SCATTERNET_APP_TASK */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.h new file mode 100644 index 00000000..003fd261 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.h @@ -0,0 +1,25 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_FUZZ_TEST_APP_TASK_H_ +#define _BT_FUZZ_TEST_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_fuzz_test_app_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.c new file mode 100644 index 00000000..9c9c8612 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.c @@ -0,0 +1,293 @@ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +#include +#include +#include +#include +#include "bt_fuzz_test_app.h" +#include "bt_fuzz_test_app_flags.h" +#include "log_service.h" +#include "atcmd_bt.h" +#include "bt_fuzz_test_at_cmd.h" +#include +#include +#if 0 +#include +#include +#endif +#define BD_ADDR_LEN 6 + +static u8 ctoi(char c) +{ + if((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 0x0A); + } + + if((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 0x0A); + } + + if((c >= '0') && (c <= '9')) { + return (c - '0' + 0x00); + } + + return 0xFF; +} + +static u8 hex_str_to_bd_addr(u32 str_len, s8 *str, u8 *num_arr) +{ + num_arr += str_len/2 -1; + u32 n = 0; + u8 num = 0; + + if (str_len < 2) { + return FALSE; + } + while (n < str_len) { + if ((num = ctoi(str[n++])) == 0xFF) { + return FALSE; + } + *num_arr = num << 4; + if ((num = ctoi(str[n++])) == 0xFF) { + return FALSE; + } + *num_arr |= num; + num_arr--; + } + return TRUE; +} + +int hex_str_to_int(u32 str_len, s8*str) +{ + int result = 0; + unsigned int n = 2; + if(str[0]!='0' && ((str[1] != 'x') && (str[1] != 'X'))){ + return -1; + } + while(n < str_len){ + result = (result << 4) | (ctoi(str[n++])); + } + return result; +} + +void bt_fuzz_test_app_set_pair_mode(uint8_t auth_flag,uint8_t io_capbility) +{ + u8 auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + u16 auth_flags = auth_flag; + u8 auth_io_cap = io_capbility; + + u8 auth_sec_req_enable = false; + u16 auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + int ret = 1; + + auth_sec_req_flags = auth_flags; + + + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + ret = gap_set_pairable_mode(); + if(ret != GAP_CAUSE_SUCCESS) + BLE_PRINT("\n\rSet pairable mode fail!\r\n"); + else + BLE_PRINT("\n\rSet pairable mode success!\r\n"); + +} + +int bt_fuzz_test_rembd(int argc, char **argv) +{ + (void) argc; + u8 DestAddr[6] = {0}; + hex_str_to_bd_addr(strlen(argv[1]), ( s8 *)argv[1], (u8*)DestAddr); + + g_cur_rembd[0] = DestAddr[0]; + g_cur_rembd[1] = DestAddr[1]; + g_cur_rembd[2] = DestAddr[2]; + g_cur_rembd[3] = DestAddr[3]; + g_cur_rembd[4] = DestAddr[4]; + g_cur_rembd[5] = DestAddr[5]; + + BLE_PRINT("g_cur_rembd: 0x%02x:%02x:%02x:%02x:%02x:%02x\r\n", + g_cur_rembd[5], g_cur_rembd[4], + g_cur_rembd[3], g_cur_rembd[2], + g_cur_rembd[1], g_cur_rembd[0]); + +} + +int bt_fuzz_test_set_testsuite(int argc, char **argv) +{ + T_GAP_CAUSE cause; + int ret = 1; + u8 auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + + u16 auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + u8 auth_io_cap; + u8 sec_enable; + + switch(argc){ + case 2: + testsuite = (T_FUZZ_TESTSUITE)(hex_str_to_int(strlen(argv[1]), ( s8 *)argv[1])); + break; + + case 3: + testsuite = (T_FUZZ_TESTSUITE)(hex_str_to_int(strlen(argv[1]), ( s8 *)argv[1])); + auth_io_cap = atoi(argv[2]); + break; + + case 4: + testsuite = (T_FUZZ_TESTSUITE)(hex_str_to_int(strlen(argv[1]), ( s8 *)argv[1])); + auth_io_cap = atoi(argv[2]); + sec_enable = atoi(argv[3]); + break; + + case 5: + testsuite = (T_FUZZ_TESTSUITE)(hex_str_to_int(strlen(argv[1]), ( s8 *)argv[1])); + auth_io_cap = atoi(argv[2]); + sec_enable = atoi(argv[3]); + m_start_pair = atoi(argv[4]); + break; + + case 6: + testsuite = (T_FUZZ_TESTSUITE)(hex_str_to_int(strlen(argv[1]), ( s8 *)argv[1])); + auth_io_cap = atoi(argv[2]); + sec_enable = atoi(argv[3]); + m_start_pair = atoi(argv[4]); + read_handle = hex_str_to_int(strlen(argv[5]), ( s8 *)argv[5]); + break; + + case 7: + testsuite = (T_FUZZ_TESTSUITE)(hex_str_to_int(strlen(argv[1]), ( s8 *)argv[1])); + auth_io_cap = atoi(argv[2]); + sec_enable = atoi(argv[3]); + m_start_pair = atoi(argv[4]); + read_handle = hex_str_to_int(strlen(argv[5]), ( s8 *)argv[5]); + write_handle = hex_str_to_int(strlen(argv[6]), ( s8 *)argv[6]); + break; + } + + u8 oob_enable = false; + u8 auth_sec_req_enable = false; + u16 auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC; +#if 0 + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); +#endif + conn_req_param.scan_interval = 0x520; //820ms + conn_req_param.scan_window = 0x520; //820ms + conn_req_param.conn_interval_min = 0x60; //120ms + conn_req_param.conn_interval_max = 0x60; //120ms + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (auth_io_cap != GAP_IO_CAP_NO_INPUT_NO_OUTPUT) + { + auth_flags |= GAP_AUTHEN_BIT_MITM_FLAG; + auth_sec_req_flags |= GAP_AUTHEN_BIT_MITM_FLAG; + } + + if (sec_enable) + { + auth_flags |= GAP_AUTHEN_BIT_SC_FLAG; + auth_sec_req_flags |= GAP_AUTHEN_BIT_SC_FLAG; + } + + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + cause = gap_set_pairable_mode(); + if(cause == GAP_CAUSE_SUCCESS) + BLE_PRINT("\n\rSet pairable mode success!\r\n"); + else + BLE_PRINT("\n\rSet pairable mode fail!\r\n"); + BLE_PRINT("testsuite = %d\r\n",testsuite); + switch (testsuite) + { + case FUZZ_TESTUITE_BTLE_SMP_510: + bt_fuzz_test_app_set_pair_mode(0xd,4); //dispaly and keyboard SC + case FUZZ_TESTUITE_BTLE_ATT_510: + case FUZZ_TESTUITE_BTLE_PROFILES_510: + le_adv_start(); + break; + + case FUZZ_TESTUITE_BTLE_SMPC_510: + bt_fuzz_test_app_set_pair_mode(0xd,1); //dispaly yes or no SC + case FUZZ_TESTUITE_BTLE_ATTC_510: + case FUZZ_TESTUITE_BTLE_HOGP_510: + case FUZZ_TESTUITE_BTLE_HEALTH_510: + //memcpy(peer_addr, g_cur_rembd, GAP_BD_ADDR_LEN); + BLE_PRINT("g_cur_rembd: 0x%02x:%02x:%02x:%02x:%02x:%02x\r\n", + g_cur_rembd[5], g_cur_rembd[4], + g_cur_rembd[3], g_cur_rembd[2], + g_cur_rembd[1], g_cur_rembd[0]); + cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, + g_cur_rembd, + remote_bd_type, + local_addr_type, + 1000); + break; + + case FUZZ_TESTUITE_BTLE_AD_510: + le_scan_start(); + break; + + case FUZZ_TESTUITE_BTLE_RESERVER: + le_adv_stop(); + le_disconnect(0); + le_scan_stop(); + break; + + default: + break; + } + + return cause; + +} + +int bt_fuzz_test_app_handle_at_cmd(uint16_t subtype, void *arg) +{ + //int common_cmd_flag = 0; + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + if (arg) { + argc = parse_param(arg, argv); + } + + switch (subtype) { + case BT_ATCMD_SET_TEST_SUITE: + bt_fuzz_test_set_testsuite(argc, argv); + break; + default: + break; + } + + return 0; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.h new file mode 100644 index 00000000..0d617ae1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.h @@ -0,0 +1,17 @@ +#ifndef _BT_FUZZ_TEST_AT_CMD_H_ +#define _BT_FUZZ_TEST_AT_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "platform_opts_bt.h" + +int bt_fuzz_test_app_handle_at_cmd(uint16_t subtype, void *arg); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.c new file mode 100644 index 00000000..3cc32d89 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.c @@ -0,0 +1,101 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +//#include + +/*============================================================================* + * Constants + *============================================================================*/ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup SCATTERNET_GAP_MSG + * @{ + */ +T_APP_LINK bt_fuzz_test_app_link_table[BT_FUZZ_TEST_APP_MAX_LINKS]; +/** @} */ +/** @addtogroup SCATTERNET_SCAN_MGR + * @{ + */ +T_DEV_INFO bt_fuzz_test_dev_list[BT_FUZZ_TEST_APP_MAX_DEVICE_INFO]; +uint8_t bt_fuzz_test_dev_list_count = 0; +/** @} */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool bt_fuzz_test_link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (bt_fuzz_test_dev_list_count < BT_FUZZ_TEST_APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < bt_fuzz_test_dev_list_count; i++) + { + if (memcmp(bd_addr, bt_fuzz_test_dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(bt_fuzz_test_dev_list[bt_fuzz_test_dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + bt_fuzz_test_dev_list[bt_fuzz_test_dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + bt_fuzz_test_dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void bt_fuzz_test_link_mgr_clear_device_list(void) +{ + bt_fuzz_test_dev_list_count = 0; +} +#endif +/** @} */ +/** @addtogroup SCATTERNET_APP + * @{ + */ +/** @} */ +/** @} */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.h new file mode 100644 index 00000000..e139ed02 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.h @@ -0,0 +1,109 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_FUZZ_TEST_LINK_MANAGER_H_ +#define _BT_FUZZ_TEST_LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include + + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Define device list table size. */ +#define BT_FUZZ_TEST_APP_MAX_DEVICE_INFO 6 + +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** @defgroup APP_DISCOV_BITS Application discover services Bits +* @{ + */ +//#define APP_DISCOV_ALL_PRIMARY_FLAG 0x01 +#define BT_FUZZ_TEST_APP_DISCOV_GAPS_FLAG 0x01 +#define BT_FUZZ_TEST_APP_DISCOV_BAS_FLAG 0x02 +#define BT_FUZZ_TEST_APP_DISCOV_CHAR_FLAG 0x04 +#define BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG1 0x08 +#define BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG2 0x10 +#define BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG3 0x20 +#define BT_FUZZ_TEST_APP_DISCOV_CHAR_DES_FLAG4 0x40 + + +#define BT_FUZZ_TEST_APP_READ_FLAG 0x80 + +#define BT_FUZZ_TEST_APP_WRITE_FLAG 0x100 + +#define BT_FUZZ_TEST_APP_NOTIFY_FLAG 0x200 +#define BT_FUZZ_TEST_APP_INDICATE_FLAG 0x400 + + +/** + * @} + */ + +#define BT_FUZZ_TEST_APP_MODE_JUST_WORK 0x01 +#define BT_FUZZ_TEST_APP_MODE_PASSKEY_ENTRY 0x02 +#define BT_FUZZ_TEST_APP_MODE_NUMERIC_COMPARISON 0x04 + + +/** @addtogroup SCATTERNET_GAP_MSG + * @{ + */ +/** + * @brief Application Link control block definition. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + uint16_t discovered_flags; /**< discovered flags. */ + uint16_t srv_found_flags; /**< service founded flogs. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t pair_mode; /**< just work, passkey input, sc numeric */ +} T_APP_LINK; +/** @} */ /* End of group SCATTERNET_GAP_MSG */ +/** @addtogroup SCATTERNET_SCAN_MGR + * @{ + */ +/** + * @brief Device list block definition. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/** @} */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK bt_fuzz_test_app_link_table[BT_FUZZ_TEST_APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO bt_fuzz_test_dev_list[BT_FUZZ_TEST_APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t bt_fuzz_test_dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool bt_fuzz_test_link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void bt_fuzz_test_link_mgr_clear_device_list(void); +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.c new file mode 100644 index 00000000..05fbc014 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.c @@ -0,0 +1,476 @@ +/** +********************************************************************************************************* +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file simple_ble_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date +* @version +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +#include + +extern const T_ATTRIB_APPL gls_att_tbl[]; + +#define BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX 0x03 +#define BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX 0x06 +#define BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX 0x08 +#define BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX 0x0b +#define BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX (BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX + 1) +#define BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX (BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX + 1) + + + +T_SERVER_ID bt_fuzz_test_simp_service_id; +/**< Value of simple read characteristic. */ +static uint8_t bt_fuzz_test_simple_char_read_value[BT_FUZZ_TEST_SIMP_READ_V1_MAX_LEN]; +static uint16_t bt_fuzz_test_simple_char_read_len = 1; +char bt_fuzz_test_v1_user_descr[] = "V1 read characteristic"; + +/**< Function pointer used to send event to application from simple profile. Initiated in simp_ble_service_add_service. */ +static P_FUN_SERVER_GENERAL_CB bt_fuzz_test_pfn_simp_ble_service_cb = NULL; + +/**< @brief profile/service definition. */ +const T_ATTRIB_APPL bt_fuzz_test_simple_ble_service_tbl[] = +{ + /* <>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_SIMPLE_PROFILE), /* service UUID */ + HI_WORD(GATT_UUID_SIMPLE_PROFILE) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + /** Include Definition*/ + { + ATTRIB_FLAG_VOID, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_INCLUDE), + HI_WORD(GATT_UUID_INCLUDE), + }, + 0, + ((uint8_t *)&gls_att_tbl[0]), + GATT_PERM_READ /**< permissions */ + }, + /* <> demo for read */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_USER_DESCR), + HI_WORD(GATT_UUID_CHAR_USER_DESCR), + }, + (sizeof(bt_fuzz_test_v1_user_descr) - 1), /* bValueLen */ + (void *)bt_fuzz_test_v1_user_descr, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for write */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <>, demo for notify */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, +}; + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool bt_fuzz_test_simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value) +{ + bool ret = true; + + switch (param_type) + { + default: + ret = false; + break; + case SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL: + if (len <= BT_FUZZ_TEST_SIMP_READ_V1_MAX_LEN) + { + memcpy(bt_fuzz_test_simple_char_read_value, p_value, len); + bt_fuzz_test_simple_char_read_len = len; + } + else + { + ret = false; + } + break; + } + + if (!ret) + { + APP_PRINT_ERROR0("bt_fuzz_test_simp_ble_service_set_parameter failed"); + } + + return ret; +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param attrib_index Attribute index of getting characteristic data. + * @param offset Used for Blob Read. + * @param p_length length of getting characteristic data. + * @param pp_value data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT bt_fuzz_test_simp_ble_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + default: + APP_PRINT_ERROR1("bt_fuzz_test_simp_ble_service_attr_read_cb, Attr not found, index %d", attrib_index); + cause = APP_RESULT_ATTR_NOT_FOUND; + break; + case BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = BT_FUZZ_TEST_SIMP_READ_V1; + callback_data.conn_id = conn_id; + if (bt_fuzz_test_pfn_simp_ble_service_cb) + { + bt_fuzz_test_pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = bt_fuzz_test_simple_char_read_value; + *p_length = bt_fuzz_test_simple_char_read_len; + } + break; + + } + + return (cause); +} + + +void bt_fuzz_test_simple_write_post_callback(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t length, uint8_t *p_value) +{ + APP_PRINT_INFO4("bt_fuzz_test_simple_write_post_callback: conn_id %d, service_id %d, attrib_index 0x%x, length %d", + conn_id, service_id, attrib_index, length); +} +/** + * @brief write characteristic data from service. + * + * @param conn_id + * @param service_id ServiceID to be written. + * @param attrib_index Attribute index of characteristic. + * @param length length of value to be written. + * @param p_value value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT bt_fuzz_test_simp_ble_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + TSIMP_CALLBACK_DATA callback_data; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("bt_fuzz_test_simp_ble_service_attr_write_cb write_type = 0x%x", write_type); + *p_write_ind_post_proc = bt_fuzz_test_simple_write_post_callback; + if (BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX == attrib_index) + { + /* Make sure written value size is valid. */ + if (p_value == NULL) + { + cause = APP_RESULT_INVALID_VALUE_SIZE; + } + else + { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = BT_FUZZ_TEST_SIMP_WRITE_V2; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (bt_fuzz_test_pfn_simp_ble_service_cb) + { + bt_fuzz_test_pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + } + } + else + { + APP_PRINT_ERROR2("bt_fuzz_test_simp_ble_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, + length); + cause = APP_RESULT_ATTR_NOT_FOUND; + } + return cause; +} + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool bt_fuzz_test_simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("bt_fuzz_test_simp_ble_service_send_v3_notify"); + // send notification to client + return server_send_data(conn_id, service_id, BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX, p_value, + length, + GATT_PDU_TYPE_ANY); +} + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool bt_fuzz_test_simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("bt_fuzz_test_simp_ble_service_send_v4_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX, p_value, + length, GATT_PDU_TYPE_ANY); +} + +/** + * @brief update CCCD bits from stack. + * + * @param conn_id connection id. + * @param service_id Service ID. + * @param index Attribute index of characteristic data. + * @param cccbits CCCD bits from stack. + * @return None +*/ +void bt_fuzz_test_simp_ble_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index, + uint16_t cccbits) +{ + TSIMP_CALLBACK_DATA callback_data; + bool is_handled = false; + callback_data.conn_id = conn_id; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + APP_PRINT_INFO2("bt_fuzz_test_simp_ble_service_cccd_update_cb: index = %d, cccbits 0x%x", index, cccbits); + switch (index) + { + case BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_data.notification_indification_index = BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V3_ENABLE; + } + else + { + // Disable Notification + callback_data.msg_data.notification_indification_index = BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V3_DISABLE; + } + is_handled = true; + } + break; + case BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V4_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V4_DISABLE; + } + is_handled = true; + } + break; + + default: + break; + } + /* Notify Application. */ + if (bt_fuzz_test_pfn_simp_ble_service_cb && (is_handled == true)) + { + bt_fuzz_test_pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } +} + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS bt_fuzz_test_simp_ble_service_cbs = +{ + bt_fuzz_test_simp_ble_service_attr_read_cb, // Read callback function pointer + bt_fuzz_test_simp_ble_service_attr_write_cb, // Write callback function pointer + bt_fuzz_test_simp_ble_service_cccd_update_cb // CCCD update callback function pointer +}; + +/** + * @brief Add simple BLE service to the BLE stack database. + * + * @param[in] p_func Callback when service attribute was read, write or cccd update. + * @return Service id generated by the BLE stack: @ref T_SERVER_ID. + * @retval 0xFF Operation failure. + * @retval others Service id assigned by stack. + * + */ +T_SERVER_ID bt_fuzz_test_simp_ble_service_add_service(void *p_func) +{ + if (false == server_add_service(&bt_fuzz_test_simp_service_id, + (uint8_t *)bt_fuzz_test_simple_ble_service_tbl, + sizeof(bt_fuzz_test_simple_ble_service_tbl), + bt_fuzz_test_simp_ble_service_cbs)) + { + APP_PRINT_ERROR0("bt_fuzz_test_simp_ble_service_add_service: fail"); + bt_fuzz_test_simp_service_id = 0xff; + return bt_fuzz_test_simp_service_id; + } + + bt_fuzz_test_pfn_simp_ble_service_cb = (P_FUN_SERVER_GENERAL_CB)p_func; + return bt_fuzz_test_simp_service_id; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.h new file mode 100644 index 00000000..ba30f4ab --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.h @@ -0,0 +1,205 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file simple_ble_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_H_ +#define _BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include +#include + + +/** @defgroup SIMP_Service Simple Ble Service + * @brief Simple BLE service + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Macros SIMP Service Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +typedef enum +{ + SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL = 0x01, +} T_SIMP_PARAM_TYPE; + +/** @} */ + + + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ + +/** @defgroup SIMP_Service_Read_Info SIMP Service Read Info + * @brief Parameter for reading characteristic value. + * @{ + */ +#define BT_FUZZ_TEST_SIMP_READ_V1 1 +/** @} */ + +/** @defgroup SIMP_Service_Write_Info SIMP Service Write Info + * @brief Parameter for writing characteristic value. + * @{ + */ +#define BT_FUZZ_TEST_SIMP_WRITE_V2 1 + +/** @} */ + +/** @defgroup SIMP_Service_Notify_Indicate_Info SIMP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V3_ENABLE 1 +#define BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V3_DISABLE 2 +#define BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V4_ENABLE 3 +#define BT_FUZZ_TEST_SIMP_NOTIFY_INDICATE_V4_DISABLE 4 + + +/** @} */ + +#define BT_FUZZ_TEST_SIMP_READ_V1_MAX_LEN 300 + +/** @} End of SIMP_Service_Upstream_Message */ + + + +/** @} End of SIMP_Service_Exported_Macros */ +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +typedef struct +{ + uint8_t opcode; //!< ref: @ref SIMP_Service_Write_Info + T_WRITE_TYPE write_type; + uint16_t len; + uint8_t *p_value; +} TSIMP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + TSIMP_WRITE_MSG write; +} TSIMP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct +{ + uint8_t conn_id; + T_SERVICE_CALLBACK_TYPE msg_type; + TSIMP_UPSTREAM_MSG_DATA msg_data; +} TSIMP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief + * @{ + */ + +/** + * @brief Add simple BLE service to the BLE stack database. + * + * @param[in] p_func Callback when service attribute was read, write or cccd update. + * @return Service id generated by the BLE stack: @ref T_SERVER_ID. + * @retval 0xFF Operation failure. + * @retval others Service id assigned by stack. + * + */ +T_SERVER_ID bt_fuzz_test_simp_ble_service_add_service(void *p_func); + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool bt_fuzz_test_simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value); + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool bt_fuzz_test_simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool bt_fuzz_test_simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); + +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _BT_FUZZ_TEST_SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.c new file mode 100644 index 00000000..16e115c9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.c @@ -0,0 +1,300 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file user_cmd.c + * @brief User defined test commands. + * @details User command interfaces. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_FUZZ_TEST) && CONFIG_BT_FUZZ_TEST +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @defgroup FUZZ_TEST_CMD Fuzz Test User Command + * @brief This file handles Fuzz Test User Command. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief User command interface data, used to parse the commands from Data UART. */ +T_USER_CMD_IF bt_fuzz_test_user_cmd_if; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Show all devices connecting status + * + * Command table define + * \code{.c} + { + "showcon", + "showcon\n\r", + "Show all devices connecting status\n\r", + cmd_showcon + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_showcon(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id; + T_GAP_CONN_INFO conn_info; + for (conn_id = 0; conn_id < BT_FUZZ_TEST_APP_MAX_LINKS; conn_id++) + { + if (le_get_conn_info(conn_id, &conn_info)) + { + data_uart_print("ShowCon conn_id %d state 0x%x role %d\r\n", conn_id, + conn_info.conn_state, conn_info.role); + data_uart_print("RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + conn_info.remote_bd[5], conn_info.remote_bd[4], + conn_info.remote_bd[3], conn_info.remote_bd[2], + conn_info.remote_bd[1], conn_info.remote_bd[0], + conn_info.remote_bd_type); + } + } + data_uart_print("active link num %d, idle link num %d\r\n", + le_get_active_link_num(), le_get_idle_link_num()); + return (RESULT_SUCESS); +} + +/** + * @brief Disconnect to remote device + * + * Command table define + * \code{.c} + { + "disc", + "disc [conn_id]\n\r", + "Disconnect to remote device\n\r", + cmd_disc + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_disc(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_disconnect(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Config authentication mode + * + * Command table define + * \code{.c} + { + "ts", + "ts [testsuite] [io_cap] [sec_enable] [start_pair] [read_handle] [write_handle]\n\r", + "Set test configuration\r\n\ + [testsuite]: Index of testsuite: 0-(btle-smp), 1-(btle-smpc), 2-(btle-att), 3-(btle-attc)\r\n\ + [io_cap]: Set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\ + [sec_enable]: Enable secure connection flag: 0-(disable), 1-(enable)\r\n\ + [start_pair]: Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\ + [read_handle]: Handle to read\r\n\ + [write_handle]: Handle to write\r\n\ + sample: ts 3 3 0 0 x3 x5\n\r", + cmd_testsuite + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_testsuite(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + testsuite = (T_FUZZ_TESTSUITE)p_parse_value->dw_param[0]; + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + T_GAP_IO_CAP auth_io_cap = (T_GAP_IO_CAP)p_parse_value->dw_param[1]; + bool sec_enable = (T_GAP_IO_CAP)p_parse_value->dw_param[2]; + m_start_pair = (T_GAP_IO_CAP)p_parse_value->dw_param[3]; + read_handle = p_parse_value->dw_param[4]; + write_handle = p_parse_value->dw_param[5]; + uint8_t oob_enable = false; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + //uint8_t peer_addr[GAP_BD_ADDR_LEN] = {0}; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (auth_io_cap != GAP_IO_CAP_NO_INPUT_NO_OUTPUT) + { + auth_flags |= GAP_AUTHEN_BIT_MITM_FLAG; + auth_sec_req_flags |= GAP_AUTHEN_BIT_MITM_FLAG; + } + + if (sec_enable) + { + auth_flags |= GAP_AUTHEN_BIT_SC_FLAG; + auth_sec_req_flags |= GAP_AUTHEN_BIT_SC_FLAG; + } + + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + cause = gap_set_pairable_mode(); + + switch (testsuite) + { + case FUZZ_TESTUITE_BTLE_SMP_510: + case FUZZ_TESTUITE_BTLE_ATT_510: + case FUZZ_TESTUITE_BTLE_PROFILES_510: + le_adv_start(); + break; + + case FUZZ_TESTUITE_BTLE_SMPC_510: + case FUZZ_TESTUITE_BTLE_ATTC_510: + case FUZZ_TESTUITE_BTLE_HOGP_510: + case FUZZ_TESTUITE_BTLE_HEALTH_510: + //memcpy(peer_addr, g_cur_rembd, GAP_BD_ADDR_LEN); + cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, + g_cur_rembd, + remote_bd_type, + local_addr_type, + 1000); + break; + + case FUZZ_TESTUITE_BTLE_AD_510: + le_scan_start(); + break; + + case FUZZ_TESTUITE_BTLE_RESERVER: + le_adv_stop(); + le_disconnect(0); + le_scan_stop(); + break; + + default: + break; + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Clear all bonded devices information + * + * Command table define + * \code{.c} + { + "bondclear", + "bondclear\n\r", + "Clear all bonded devices information\n\r", + cmd_bondclear + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_bondclear(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_bond_clear_all_keys(); + return (RESULT_SUCESS); +} + +/************************** Central only *************************************/ +static T_USER_CMD_PARSE_RESULT cmd_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + g_cur_rembd[0] = p_parse_value->dw_param[5]; + g_cur_rembd[1] = p_parse_value->dw_param[4]; + g_cur_rembd[2] = p_parse_value->dw_param[3]; + g_cur_rembd[3] = p_parse_value->dw_param[2]; + g_cur_rembd[4] = p_parse_value->dw_param[1]; + g_cur_rembd[5] = p_parse_value->dw_param[0]; + + data_uart_print("g_cur_rembd: 0x%02x:%02x:%02x:%02x:%02x:%02x\r\n", + g_cur_rembd[5], g_cur_rembd[4], + g_cur_rembd[3], g_cur_rembd[2], + g_cur_rembd[1], g_cur_rembd[0]); + return (T_USER_CMD_PARSE_RESULT)(RESULT_SUCESS); +} + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const T_USER_CMD_TABLE_ENTRY bt_fuzz_test_user_cmd_table[] = +{ + /************************** Common cmd *************************************/ + { + "showcon", + "showcon\n\r", + "Show all devices connecting status\n\r", + cmd_showcon + }, + { + "disc", + "disc [conn_id]\n\r", + "Disconnect to remote device\n\r", + cmd_disc + }, + { + "ts", + "ts [testsuite] [io_cap] [sec_enable] [start_pair] [read_handle] [write_handle]\n\r", + "Set test configuration\r\n\ + [testsuite]: Index of testsuite: 0-(btle-smp), 1-(btle-smpc), 2-(btle-att), 3-(btle-attc)\r\n\ + [io_cap]: Set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\ + [sec_enable]: Enable secure connection flag: 0-(disable), 1-(enable)\r\n\ + [start_pair]: Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\ + [read_handle]: Handle to read\r\n\ + [write_handle]: Handle to write\r\n\ + sample: ts 3 3 0 0 x3 x5\n\r", + cmd_testsuite + }, + { + "bondclear", + "bondclear\n\r", + "Clear all bonded devices information\n\r", + cmd_bondclear + }, + /************************** Central only *************************************/ + { + "rembd", + "rembd [index]\n\r", + "rembd\n\r", + cmd_rembd + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; +#endif +/** @} */ /* End of group FUZZ_TEST_CMD */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.h new file mode 100644 index 00000000..6dcc8c59 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.h @@ -0,0 +1,31 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file user_cmd.h +* @brief Define user command. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _BT_FUZZ_TEST_USER_CMD_H_ +#define _BT_FUZZ_TEST_USER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[]; +extern T_USER_CMD_IF user_cmd_if; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_flags.h new file mode 100644 index 00000000..b0cb2096 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_flags.h @@ -0,0 +1,29 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_HARMONY_ADAPTER_APP_FLAGS_H_ +#define _BT_HARMONY_ADAPTER_APP_FLAGS_H_ + +#include "bt_flags.h" + +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define BT_HARMONY_ADAPTER_APP_MAX_LINKS 1 + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_main.c new file mode 100644 index 00000000..5ad395b0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_main.c @@ -0,0 +1,235 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_HARMONY_ADAPTER) && CONFIG_BT_HARMONY_ADAPTER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bt_harmony_adapter_app_task.h" +#include "bt_harmony_adapter_peripheral_app.h" +#include "bt_harmony_adapter_app_flags.h" +#include "platform_stdlib.h" +#include "wifi_constants.h" +#include +#include "rtk_coex.h" +#include "ohos_bt_gatt_server.h" +#include "ohos_bt_gatt_client.h" +#include +#include + + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 352 //220ms +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 384 //240ms + + +extern uint16_t H_auth_flags; +extern uint8_t H_auth_io_cap; + +extern void *bt_harmony_BleAdv_Timer; +extern void *send_indication_sem; +uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BT_HARMONY_ADAPTER"; +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +#ifndef PLATFORM_OHOS +extern void gap_config_hci_task_secure_context(uint32_t size); +void bt_harmony_adapter_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_HARMONY_ADAPTER_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_HARMONY_ADAPTER_APP_MAX_LINKS); + gap_config_hci_task_secure_context(280); +} +#else +extern void gap_config_deinit_flow(uint8_t deinit_flow); +void bt_harmony_adapter_stack_config_init(void) +{ + gap_config_cccd_not_check(CONFIG_GATT_CCCD_NOT_CHECK); + gap_config_max_le_link_num(BT_HARMONY_ADAPTER_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_HARMONY_ADAPTER_APP_MAX_LINKS); + //gap_config_hci_task_secure_context(280); + gap_config_deinit_flow(1); +} +#endif +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void bt_harmony_adapter_app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = H_auth_flags; + uint8_t auth_io_cap = H_auth_io_cap; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = H_auth_flags; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_harmony_adapter_app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void bt_harmony_adapter_app_le_profile_init(void) +{ + server_builtin_service_reg(false); + + server_init(BT_HARMONY_ADAPTER_SERVICE_MAX_NUM); + + server_register_app_cb(bt_harmony_adapter_app_profile_callback); +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void bt_harmony_adapter_task_init(void) +{ + bt_harmony_adapter_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_harmony_adapter_app_main(void) +{ + bt_trace_init(); + bt_harmony_adapter_stack_config_init(); + bte_init(); + le_gap_init(BT_HARMONY_ADAPTER_APP_MAX_LINKS); + bt_harmony_adapter_app_le_gap_init(); + bt_harmony_adapter_app_le_profile_init(); + bt_harmony_adapter_task_init(); + + return 0; +} + +int bt_harmony_adapter_app_init(void) +{ + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while (!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BT Harmony Adapter is already on + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + printf("[BT Harmony Adapter] BT Stack already on\r\n"); + return 0; + } else { + bt_harmony_adapter_app_main(); + } + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } while (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern bool bt_trace_uninit(void); +extern T_GAP_DEV_STATE bt_harmony_adapter_gap_dev_state; + +void bt_harmony_adapter_app_deinit(void) +{ + if (bt_harmony_BleAdv_Timer) { + if (os_timer_delete(&bt_harmony_BleAdv_Timer) == true) { + printf("[%s]:delete adv timer success\r\n", __func__); + } + } + if (send_indication_sem) { + os_sem_delete(send_indication_sem); + send_indication_sem = NULL; + } + bt_harmony_adapter_app_task_deinit(); + + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE, &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Harmony Adapter] BT Stack is not running\r\n"); + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + memset(&bt_harmony_adapter_gap_dev_state, 0, sizeof(T_GAP_DEV_STATE)); + printf("[BT Harmony Adapter] BT Stack deinitalized\r\n"); + } +#endif +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_task.c new file mode 100644 index 00000000..d79f66fd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_task.c @@ -0,0 +1,220 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_HARMONY_ADAPTER) && CONFIG_BT_HARMONY_ADAPTER +#include +#include +#include +#include +#include "bt_harmony_adapter_app_task.h" +#include +#include "bt_harmony_adapter_peripheral_app.h" +#include "platform_stdlib.h" +#include +#include +#include +#include +#include "osif.h" + +/*============================================================================* + * Macros + *============================================================================*/ +#define BT_HARMONY_ADAPTER_APP_TASK_PRIORITY 4 //!< Task priorities +#define BT_HARMONY_ADAPTER_APP_TASK_STACK_SIZE 256 * 6 //!< Task stack size +#define BT_HARMONY_ADAPTER_CALLBACK_TASK_PRIORITY 3 //!< Task priorities +#define BT_HARMONY_ADAPTER_CALLBACK_TASK_STACK_SIZE 256 * 20 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size +#define MAX_NUMBER_OF_CALLBACK_MESSAGE 0x20 //!< Callback message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_harmony_adapter_app_task_handle = NULL; //!< APP task handle +void *bt_harmony_adapter_evt_queue_handle = NULL; //!< Event queue handle +void *bt_harmony_adapter_io_queue_handle = NULL; //!< IO queue handle +void *bt_harmony_adapter_callback_task_handle = NULL; //!< Callback task handle +void *bt_harmony_adapter_callback_queue_handle = NULL; //!< Callback queue handle +void *bt_harmony_adapter_callback_sem_handle = NULL; //!< Callback semaphore handle + +extern T_GAP_DEV_STATE bt_harmony_adapter_gap_dev_state; +extern BHA_SERVICE_INFO bt_harmony_adapter_srvs_head; +extern BHA_SERVICE_INFO *bt_harmony_adapter_srv_p; +extern uint8_t bt_harmony_adapter_srvs_num; +extern void *add_service_sem; +extern void bt_harmony_adapter_free_service_info(BHA_SERVICE_INFO *service_info); + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_harmony_adapter_app_main_task(void *p_param) +{ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_harmony_adapter_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_harmony_adapter_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(bt_harmony_adapter_evt_queue_handle, bt_harmony_adapter_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + while (true) { + if (os_msg_recv(bt_harmony_adapter_evt_queue_handle, &event, 0xFFFFFFFF) == true) { + if (event == EVENT_IO_TO_APP) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_harmony_adapter_io_queue_handle, &io_msg, 0) == true) { + bt_harmony_adapter_app_handle_io_msg(io_msg); + } + } else { + gap_handle_msg(event); + } + } + } +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_harmony_adapter_callback_main_task(void *p_param) +{ + (void)p_param; + T_BHA_CALLBACK_MSG callback_msg; + + os_sem_create(&bt_harmony_adapter_callback_sem_handle, 0, MAX_NUMBER_OF_CALLBACK_MESSAGE); + os_msg_queue_create(&bt_harmony_adapter_callback_queue_handle, MAX_NUMBER_OF_CALLBACK_MESSAGE, sizeof(T_BHA_CALLBACK_MSG)); + + while (true) { + if (os_sem_take(bt_harmony_adapter_callback_sem_handle, 0xFFFFFFFF) == true) { + if (os_msg_recv(bt_harmony_adapter_callback_queue_handle, &callback_msg, 0) == true) { + bt_harmony_adapter_app_handle_callback_msg(callback_msg); + } + } + } +} + +void bt_harmony_adapter_app_check_callback_msg(void) +{ + T_BHA_CALLBACK_MSG callback_msg; + + while(osif_msg_queue_get_space(bt_harmony_adapter_callback_queue_handle) < osif_msg_queue_get_capacity(bt_harmony_adapter_callback_queue_handle)) { + if (os_msg_recv(bt_harmony_adapter_callback_queue_handle, &callback_msg, 0) == true) { + bt_harmony_adapter_app_handle_callback_msg(callback_msg); + } + } +} + +/** + * @brief Initialize App task + * @return void + */ +void bt_harmony_adapter_app_task_init(void) +{ + os_task_create(&bt_harmony_adapter_app_task_handle, "bt_harmony_adapter_app", bt_harmony_adapter_app_main_task, 0, BT_HARMONY_ADAPTER_APP_TASK_STACK_SIZE, + BT_HARMONY_ADAPTER_APP_TASK_PRIORITY); + os_task_create(&bt_harmony_adapter_callback_task_handle, "bt_harmony_adapter_callback", bt_harmony_adapter_callback_main_task, 0, + BT_HARMONY_ADAPTER_CALLBACK_TASK_STACK_SIZE, + BT_HARMONY_ADAPTER_CALLBACK_TASK_PRIORITY); +} + +void bt_harmony_adapter_app_task_deinit(void) +{ +#ifdef PLATFORM_OHOS + if (bt_harmony_adapter_app_task_handle) { + os_task_delete(bt_harmony_adapter_app_task_handle); + } + if (bt_harmony_adapter_callback_task_handle) { + os_task_delete(bt_harmony_adapter_callback_task_handle); + } + if (bt_harmony_adapter_io_queue_handle) { + os_msg_queue_delete(bt_harmony_adapter_io_queue_handle); + } + if (bt_harmony_adapter_evt_queue_handle) { + os_msg_queue_delete(bt_harmony_adapter_evt_queue_handle); + } + bt_harmony_adapter_app_check_callback_msg(); + if (bt_harmony_adapter_callback_queue_handle) { + os_msg_queue_delete(bt_harmony_adapter_callback_queue_handle); + } + if (bt_harmony_adapter_callback_sem_handle) { + os_sem_delete(bt_harmony_adapter_callback_sem_handle); + } + + bt_harmony_adapter_app_task_handle = NULL; + bt_harmony_adapter_callback_task_handle = NULL; + bt_harmony_adapter_io_queue_handle = NULL; + bt_harmony_adapter_evt_queue_handle = NULL; + bt_harmony_adapter_callback_queue_handle = NULL; + bt_harmony_adapter_callback_sem_handle = NULL; +#else + if (bt_harmony_adapter_io_queue_handle) { + os_msg_queue_delete(bt_harmony_adapter_io_queue_handle); + } + if (bt_harmony_adapter_evt_queue_handle) { + os_msg_queue_delete(bt_harmony_adapter_evt_queue_handle); + } + if (bt_harmony_adapter_app_task_handle) { + os_task_delete(bt_harmony_adapter_app_task_handle); + } + if (bt_harmony_adapter_callback_queue_handle) { + os_msg_queue_delete(bt_harmony_adapter_callback_queue_handle); + } + if (bt_harmony_adapter_callback_task_handle) { + os_task_delete(bt_harmony_adapter_callback_task_handle); + } + + bt_harmony_adapter_io_queue_handle = NULL; + bt_harmony_adapter_evt_queue_handle = NULL; + bt_harmony_adapter_app_task_handle = NULL; + bt_harmony_adapter_callback_queue_handle = NULL; + bt_harmony_adapter_callback_task_handle = NULL; +#endif + bt_harmony_adapter_gap_dev_state.gap_init_state = 0; + bt_harmony_adapter_gap_dev_state.gap_adv_sub_state = 0; + bt_harmony_adapter_gap_dev_state.gap_adv_state = 0; + bt_harmony_adapter_gap_dev_state.gap_scan_state = 0; + bt_harmony_adapter_gap_dev_state.gap_conn_state = 0; + + BHA_SERVICE_INFO *p_srv = NULL; + while (bt_harmony_adapter_srvs_head.next) { + p_srv = bt_harmony_adapter_srvs_head.next; + bt_harmony_adapter_srvs_head.next = p_srv->next; + bt_harmony_adapter_free_service_info(p_srv); + } + bt_harmony_adapter_srv_p = &bt_harmony_adapter_srvs_head; + bt_harmony_adapter_srvs_num = 0; + + if (add_service_sem) { + os_sem_delete(add_service_sem); + add_service_sem = NULL; + } +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_task.h new file mode 100644 index 00000000..c6fd6838 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_app_task.h @@ -0,0 +1,31 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_HARMONY_ADAPTER_APP_TASK_H_ +#define _BT_HARMONY_ADAPTER_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_harmony_adapter_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_harmony_adapter_app_task_deinit(void); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_peripheral_app.c b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_peripheral_app.c new file mode 100644 index 00000000..c89a57d8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_peripheral_app.c @@ -0,0 +1,857 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_HARMONY_ADAPTER) && CONFIG_BT_HARMONY_ADAPTER +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "bt_harmony_adapter_peripheral_app.h" +#include "ohos_bt_gatt.h" +#include "ohos_bt_gatt_server.h" +#include "ohos_bt_gatt_client.h" +#include +#include "platform_stdlib.h" +#include +#include +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +T_GAP_DEV_STATE bt_harmony_adapter_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE bt_harmony_adapter_gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +extern void *bt_harmony_adapter_evt_queue_handle; +extern void *bt_harmony_adapter_io_queue_handle; +extern void *bt_harmony_adapter_callback_queue_handle; +extern void *bt_harmony_adapter_callback_sem_handle; +extern BHA_SERVICE_INFO bt_harmony_adapter_srvs_head; +extern BHA_SERVICE_INFO *bt_harmony_adapter_srv_p; + +extern H_adv_param h_adv_param; +extern BtGattCallbacks BH_GattCallbacks ; +extern BtGattServerCallbacks BH_GattServerCallbacks; +extern uint8_t H_adv_data[31]; +extern uint8_t H_scan_response_data[31]; +void *bt_harmony_BleAdv_Timer = NULL; +int RT_duration = 0; + +uint8_t RT_remote_bd[OHOS_BD_ADDR_LEN] = {0}; +extern void *send_indication_sem; +extern void *add_service_sem; +extern void bt_harmony_adapter_search_and_free_service(T_BHA_SRV_ADDED_CALLBACK_DATA *p_data); +/*============================================================================* + * Functions + *============================================================================*/ +bool bt_harmony_adapter_app_send_api_msg(T_BHA_API_MSG_TYPE sub_type, void *buf) +{ + T_IO_MSG io_msg; + + uint8_t event = EVENT_IO_TO_APP; + + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + io_msg.u.buf = buf; + + if (bt_harmony_adapter_evt_queue_handle != NULL && bt_harmony_adapter_io_queue_handle != NULL) { + if (os_msg_send(bt_harmony_adapter_io_queue_handle, &io_msg, 0) == false) { + printf("[%s] send io queue fail! type = 0x%x\r\n", __FUNCTION__, io_msg.subtype); + return false; + } else if (os_msg_send(bt_harmony_adapter_evt_queue_handle, &event, 0) == false) { + printf("[%s] send event queue fail! type = 0x%x\r\n", __FUNCTION__, io_msg.subtype); + return false; + } + } else { + printf("[%s] queue is empty! type = 0x%x\r\n", __FUNCTION__, io_msg.subtype); + return false; + } + + return true; +} + +bool bt_harmony_adapter_app_send_callback_msg(T_BHA_CALLBACK_MSG_TYPE type, void *buf) +{ + T_BHA_CALLBACK_MSG callback_msg; + + callback_msg.type = type; + callback_msg.buf = buf; + + if (bt_harmony_adapter_callback_queue_handle != NULL) { + if (os_msg_send(bt_harmony_adapter_callback_queue_handle, &callback_msg, 0) == false) { + printf("[%s] send callback queue fail! type = 0x%x\r\n", __FUNCTION__, callback_msg.type); + return false; + } + } else { + printf("[%s] queue is empty! type = 0x%x\r\n", __FUNCTION__, callback_msg.type); + return false; + } + + if (bt_harmony_adapter_callback_sem_handle) + os_sem_give(bt_harmony_adapter_callback_sem_handle); + return true; +} +void bt_harmony_adapter_adv_timer_handler(void *timer_hdl) +{ +///stop adv + T_GAP_DEV_STATE new_state; + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + if (new_state.gap_adv_state != GAP_ADV_STATE_ADVERTISING) { + printf("[%s]:adv already stopped\r\n", __func__); + } else { + bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_STOP_ADV, NULL); + } +} + +void bt_harmony_adapter_app_handle_api_msg(T_IO_MSG io_msg) +{ + //Handle API msg here + uint16_t msg_type = io_msg.subtype; + + switch (msg_type) { + case BHA_API_MSG_START_ADV: { + H_adv_param *h_adv_param = io_msg.u.buf; + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(h_adv_param->H_adv_evt_type), &h_adv_param->H_adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(h_adv_param->H_adv_direct_type), &h_adv_param->H_adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(h_adv_param->H_local_addr_type), &h_adv_param->H_local_addr_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(h_adv_param->H_adv_direct_addr), h_adv_param->H_adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(h_adv_param->H_adv_chann_map), &h_adv_param->H_adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(h_adv_param->H_adv_filter_policy), &h_adv_param->H_adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(h_adv_param->H_adv_int_min), &h_adv_param->H_adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(h_adv_param->H_adv_int_max), &h_adv_param->H_adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, h_adv_param->adv_datalen, (void *)H_adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, h_adv_param->scanrep_datalen, (void *)H_scan_response_data); + + memset(H_adv_data, 0, 31); + memset(H_scan_response_data, 0, 31); + ///timer + if (h_adv_param->H_duration != 0) { + RT_duration = h_adv_param->H_duration; + if (bt_harmony_BleAdv_Timer == NULL) { + if (os_timer_create(&bt_harmony_BleAdv_Timer, "bt_harmony_BleAdv_Timer", 0, RT_duration * 10, false, bt_harmony_adapter_adv_timer_handler) == true) { + printf("[%s]:create adv timer successful\r\n", __func__); + } else { + printf("[%s]:create adv timer failed\r\n", __func__); + } + + } + } + if (h_adv_param) { + os_mem_free(h_adv_param); + } + le_adv_start(); + } + break; + case BHA_API_MSG_STOP_ADV: + le_adv_stop(); + break; + case BHA_API_MSG_DISCONNECT: + le_disconnect(0); + break; + case BHA_API_MSG_AUTH_RESPOND: { + H_SecurityRsp_param *SecurityRsp_p = io_msg.u.buf; + le_bond_user_confirm(0, SecurityRsp_p->accept); + if (SecurityRsp_p) { + os_mem_free(SecurityRsp_p); + } + } + break; + case BHA_API_MSG_ADD_SERVICE: { + BHA_SERVICE_INFO *srv_info = io_msg.u.buf; + bt_harmony_adapter_add_service(srv_info, (void *)bt_harmony_adapter_app_profile_callback); + } + break; + + case BHA_API_MSG_SEND_INDICATION: { + BHA_INDICATION_PARAM *param = io_msg.u.buf; + BHA_SERVICE_INFO *p_srv = bt_harmony_adapter_srvs_head.next; + while (p_srv) { + if (p_srv->srvId == param->srv_id) { + break; + } else { + p_srv = p_srv->next; + } + } + if (p_srv) { + if (bt_harmony_adapter_send_indication(0, param->srv_id, param->att_handle, (uint8_t *)param->val, param->len, param->type)) { + printf("[%s] send indication success\r\n", __FUNCTION__); + } else { + if (send_indication_sem) { + os_sem_give(send_indication_sem); + } + printf("[%s] send indication fail\r\n", __FUNCTION__); + } + } else { + if (send_indication_sem) { + os_sem_give(send_indication_sem); + } + printf("[%s] Can not find service info\r\n", __FUNCTION__); + } + os_mem_free(param->val); + os_mem_free(param); + } + break; + default: + break; + } + +} + +void bt_harmony_adapter_app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_harmony_adapter_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) { + case IO_MSG_TYPE_BT_STATUS: { + bt_harmony_adapter_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_QDECODE: { + bt_harmony_adapter_app_handle_api_msg(io_msg); + } + break; + default: + break; + } +} + +void bt_harmony_adapter_app_handle_callback_msg(T_BHA_CALLBACK_MSG callback_msg) +{ + //Handle callback msg here + switch (callback_msg.type) { + case BHA_CALLBACK_MSG_ADV_STARTED: { + AdvEnableCallback pfunc_advT = BH_GattCallbacks.advEnableCb; + if (pfunc_advT) { + pfunc_advT(0, OHOS_BT_STATUS_SUCCESS); + } + break; + } + case BHA_CALLBACK_MSG_ADV_STOPED: { + AdvDisableCallback pfunc_advS = BH_GattCallbacks.advDisableCb; + if (pfunc_advS) { + pfunc_advS(0, OHOS_BT_STATUS_SUCCESS); + } + break; + } + case BHA_CALLBACK_MSG_CONNECTED: { + T_BHA_CONNECTED_CALLBACK_DATA *conn_data_C = callback_msg.buf; + ConnectServerCallback pfunc_C = BH_GattServerCallbacks.connectServerCb; + if (pfunc_C) { + pfunc_C(conn_data_C->conn_id, conn_data_C->serverID, &(conn_data_C->bt_addr)); + } + if (conn_data_C) { + os_mem_free(conn_data_C); + } + break; + } + case BHA_CALLBACK_MSG_DISCONNECTED: { + T_BHA_CONNECTED_CALLBACK_DATA *conn_data_D = callback_msg.buf; + DisconnectServerCallback pfunc_D = BH_GattServerCallbacks.disconnectServerCb; + if (pfunc_D) { + pfunc_D(conn_data_D->conn_id, conn_data_D->serverID, &(conn_data_D->bt_addr)); + } + if (conn_data_D) { + os_mem_free(conn_data_D); + } + break; + } + case BHA_CALLBACK_MSG_AUTH_REQUEST: { + BdAddr bt_addr; + memcpy(bt_addr.addr, callback_msg.buf, OHOS_BD_ADDR_LEN); + SecurityRespondCallback pfunc_A = BH_GattCallbacks.securityRespondCb; + if (pfunc_A) { + pfunc_A(&bt_addr); + } + break; + } + case BHA_CALLBACK_MSG_MTU_CHANGED: { + T_BHA_MTU_CALLBACK_DATA *mtu_data = callback_msg.buf; + MtuChangeCallback pfunc_M = BH_GattServerCallbacks.mtuChangeCb; + if (pfunc_M) { + pfunc_M(mtu_data->conn_id, mtu_data->mtu_size); + } + if (mtu_data) { + os_mem_free(mtu_data); + } + break; + } + case BHA_CALLBACK_MSG_SERVICE_ADDED: { + ServiceStartCallback p_func = BH_GattServerCallbacks.serviceStartCb; + T_BHA_SRV_ADDED_CALLBACK_DATA *p_data = callback_msg.buf; + BHA_SERVICE_INFO *p_srv = bt_harmony_adapter_srvs_head.next; + while (p_srv) { + if (p_srv->srvId == p_data->srv_id && p_srv->status == BHA_SERVICE_REG_SUCCESS) { + break; + } else { + p_srv = p_srv->next; + } + } + int status = OHOS_BT_STATUS_FAIL; + int srv_id = 0xffff; + int srv_handle = 0; + if (p_srv) { + srv_id = p_data->srv_id; + srv_handle = p_srv->start_handle; + if (p_data->result == GATT_SERVER_SUCCESS) { + status = OHOS_BT_STATUS_SUCCESS; + } else { + bt_harmony_adapter_search_and_free_service(p_data); + } + } else { + printf("[%s] Can not find service info\r\n", __FUNCTION__); + } + + if (p_func) { + p_func(status, srv_id, srv_handle); + } else { + printf("[%s] serviceStartCallback callback is NULL\r\n", __FUNCTION__); + } + os_mem_free(p_data); + } + break; + + case BHA_CALLBACK_MSG_INDICATION_SENT: { + T_BHA_IND_SENT_CALLBACK_DATA *p_data = callback_msg.buf; + BHA_SERVICE_INFO *p_srv = bt_harmony_adapter_srvs_head.next; + while (p_srv) { + if (p_srv->srvId == p_data->srv_id && p_srv->status == BHA_SERVICE_REG_SUCCESS) { + break; + } else { + p_srv = p_srv->next; + } + } + if (p_srv) { + BleGattServiceIndicate pfunc = (p_srv->cbInfo[p_data->att_index]).func.indicate; + if (pfunc) { + pfunc(&(p_data->result), 1); + } else { + printf("[%s] BleGattServiceIndicate callback is NULL\r\n", __FUNCTION__); + } + } else { + printf("[%s] Can not find service info\r\n", __FUNCTION__); + } + os_mem_free(p_data); + } + break; + case BHA_CALLBACK_MSG_WRITE_SENT: { + T_BHA_WRITE_DATA *p_data = callback_msg.buf; + BleGattServiceWrite p_func = p_data->write_cb; + if (p_func) { + p_func(p_data->write_value, p_data->write_len); + } else { + printf("[%s] BleGattServiceWrite callback is NULL\r\n", __FUNCTION__); + } + os_mem_free(p_data); + } + default: + break; + } + +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_harmony_adapter_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("bt_harmony_adapter_app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (bt_harmony_adapter_gap_dev_state.gap_init_state != new_state.gap_init_state) { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + APP_PRINT_INFO0("GAP stack ready"); + printf("GAP stack ready\r\n"); + } + } + + if (bt_harmony_adapter_gap_dev_state.gap_adv_state != new_state.gap_adv_state) { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("GAP adv stoped: because connection created\r\n"); + } else { + APP_PRINT_INFO0("GAP adv stoped"); + printf("GAP adv stopped\r\n"); + bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_ADV_STOPED, NULL); + } + } else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) { + APP_PRINT_INFO0("GAP adv start"); + printf("GAP adv start\r\n"); + + if (RT_duration != 0) { + os_timer_start(&bt_harmony_BleAdv_Timer); + RT_duration = 0; + } + bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_ADV_STARTED, NULL); + } + } + + bt_harmony_adapter_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_harmony_adapter_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("bt_harmony_adapter_app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, bt_harmony_adapter_gap_conn_state, new_state, disc_cause); + switch (new_state) { + case GAP_CONN_STATE_DISCONNECTED: { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) { + APP_PRINT_ERROR1("bt_harmony_adapter_app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + printf("BT Disconnected\r\n"); + T_BHA_CONNECTED_CALLBACK_DATA *conn_data = (T_BHA_CONNECTED_CALLBACK_DATA *) os_mem_alloc(0, sizeof(T_BHA_CONNECTED_CALLBACK_DATA)); + memset(conn_data, 0, sizeof(T_BHA_CONNECTED_CALLBACK_DATA)); + conn_data->conn_id = conn_id; + conn_data->serverID = 0; + memcpy(conn_data->bt_addr.addr, RT_remote_bd, OHOS_BD_ADDR_LEN); + if (bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_DISCONNECTED, conn_data) != true) { + os_mem_free(conn_data); + } + memset(RT_remote_bd, 0, OHOS_BD_ADDR_LEN); + if (send_indication_sem) { + os_sem_give(send_indication_sem); + } + } + break; + + case GAP_CONN_STATE_CONNECTED: { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, RT_remote_bd, (void *)&remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED: remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(RT_remote_bd), remote_bd_type, conn_interval, conn_latency, conn_supervision_timeout); + printf("BT Connected\r\n"); + uint8_t tmp = 0; + for (int i = 0; i < OHOS_BD_ADDR_LEN / 2; ++i) { + tmp = RT_remote_bd[OHOS_BD_ADDR_LEN - 1 - i]; + RT_remote_bd[OHOS_BD_ADDR_LEN - 1 - i] = RT_remote_bd[i]; + RT_remote_bd[i] = tmp; + } + T_BHA_CONNECTED_CALLBACK_DATA *conn_data = (T_BHA_CONNECTED_CALLBACK_DATA *)os_mem_alloc(0, sizeof(T_BHA_CONNECTED_CALLBACK_DATA)); + memset(conn_data, 0, sizeof(T_BHA_CONNECTED_CALLBACK_DATA)); + conn_data->conn_id = conn_id; + conn_data->serverID = 0; + memcpy(conn_data->bt_addr.addr, RT_remote_bd, OHOS_BD_ADDR_LEN); + if (bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_CONNECTED, conn_data) != true) { + os_mem_free(conn_data); + } + } + break; + + default: + break; + } + + bt_harmony_adapter_gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_harmony_adapter_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_harmony_adapter_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) { + case GAP_AUTHEN_STATE_STARTED: { + APP_PRINT_INFO0("bt_harmony_adapter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: { + if (cause == GAP_SUCCESS) { + printf("Pair success\r\n"); + APP_PRINT_INFO0("bt_harmony_adapter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } else { + printf("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_harmony_adapter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: { + APP_PRINT_ERROR1("bt_harmony_adapter_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_harmony_adapter_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); + T_BHA_MTU_CALLBACK_DATA *mtu_data = (T_BHA_MTU_CALLBACK_DATA *)os_mem_alloc(0, sizeof(T_BHA_MTU_CALLBACK_DATA)); + mtu_data->conn_id = conn_id; + mtu_data->mtu_size = mtu_size; + if (bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_MTU_CHANGED, mtu_data) != true) { + os_mem_free(mtu_data); + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_harmony_adapter_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("bt_harmony_adapter_app_handle_conn_param_update_evt update success: conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + printf("bt_harmony_adapter_app_handle_conn_param_update_evt update success: conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x\r\n", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: { + APP_PRINT_ERROR1("bt_harmony_adapter_app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + printf("bt_harmony_adapter_app_handle_conn_param_update_evt update failed: cause 0x%x\r\n", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: { + APP_PRINT_INFO0("bt_harmony_adapter_app_handle_conn_param_update_evt update pending"); + printf("bt_harmony_adapter_app_handle_conn_param_update_evt update pending\r\n"); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_harmony_adapter_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_harmony_adapter_app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) { + case GAP_MSG_LE_DEV_STATE_CHANGE: { + bt_harmony_adapter_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: { + bt_harmony_adapter_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: { + bt_harmony_adapter_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: { + bt_harmony_adapter_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: { + bt_harmony_adapter_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: passkey %06d\r\n", display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %06d\r\n", display_value); + bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_AUTH_REQUEST, RT_remote_bd); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: { + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + printf("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + default: + APP_PRINT_ERROR1("bt_harmony_adapter_app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_harmony_adapter_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_harmony_adapter_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) { + case PROFILE_EVT_SRV_REG_COMPLETE: + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", p_param->event_data.service_reg_result); + break; + case PROFILE_EVT_SRV_REG_AFTER_INIT_COMPLETE: { + printf("T_SERVER_REG_AFTER_INIT_RESULT: result %d service_id %d cause %d\r\n", + p_param->event_data.server_reg_after_init_result.result, + p_param->event_data.server_reg_after_init_result.service_id, + p_param->event_data.server_reg_after_init_result.cause); + if (add_service_sem) + os_sem_give(add_service_sem); + T_BHA_SRV_ADDED_CALLBACK_DATA *callback_data = (T_BHA_SRV_ADDED_CALLBACK_DATA *) os_mem_alloc(0, sizeof(T_BHA_SRV_ADDED_CALLBACK_DATA)); + callback_data->result = p_param->event_data.server_reg_after_init_result.result; + callback_data->srv_id = p_param->event_data.server_reg_after_init_result.service_id; + if (bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_SERVICE_ADDED, callback_data) != true) { + if (callback_data->result != GATT_SERVER_SUCCESS) { + bt_harmony_adapter_search_and_free_service(callback_data); + } + os_mem_free(callback_data); + } + } + break; + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + printf("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } else { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + if (send_indication_sem) { + os_sem_give(send_indication_sem); + } + T_BHA_IND_SENT_CALLBACK_DATA *callback_data = (T_BHA_IND_SENT_CALLBACK_DATA *) os_mem_alloc(0, sizeof(T_BHA_IND_SENT_CALLBACK_DATA)); + callback_data->result = p_param->event_data.send_data_result.cause; + callback_data->srv_id = p_param->event_data.send_data_result.service_id; + callback_data->att_index = p_param->event_data.send_data_result.attrib_idx; + if (bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_INDICATION_SENT, callback_data) != true) { + os_mem_free(callback_data); + } + break; + + default: + break; + } + } else { + T_HARMONY_CALLBACK_DATA *p_harmony_cb_data = p_data; + + switch (p_harmony_cb_data->msg_type) { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: { + if (p_harmony_cb_data->msg_data.cccd.ccc_val & GATT_CLIENT_CHAR_CONFIG_NOTIFY) { + printf("[%s] cccd 0x%x update : notify enable\r\n", __FUNCTION__, p_harmony_cb_data->msg_data.cccd.attr_index); + } else { + printf("[%s] cccd 0x%x update : notify disable\r\n", __FUNCTION__, p_harmony_cb_data->msg_data.cccd.attr_index); + } + if (p_harmony_cb_data->msg_data.cccd.ccc_val & GATT_CLIENT_CHAR_CONFIG_INDICATE) { + printf("[%s] cccd 0x%x update : indicate enable\r\n", __FUNCTION__, p_harmony_cb_data->msg_data.cccd.attr_index); + } else { + printf("[%s] cccd 0x%x update : indicate disable\r\n", __FUNCTION__, p_harmony_cb_data->msg_data.cccd.attr_index); + } + break; + } + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: { + /* call user defined callback */ + if (p_harmony_cb_data->msg_data.read.read_cb) { + BleGattServiceRead p_func = p_harmony_cb_data->msg_data.read.read_cb; + p_func(p_harmony_cb_data->msg_data.read.p_value, p_harmony_cb_data->msg_data.read.p_len); + } else { + printf("[%s] User's read callback is NULL\r\n", __FUNCTION__); + } + printf("[%s] read len %d data 0x\r\n", __FUNCTION__, + *(p_harmony_cb_data->msg_data.read.p_len)); + for (int i = 0; i < * (p_harmony_cb_data->msg_data.read.p_len); i++) { + printf("%x ", *(p_harmony_cb_data->msg_data.read.p_value + i)); + } + printf("\n\r"); + break; + } + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: { + printf("[%s] write_type %d len %d data 0x\r\n", __FUNCTION__, + p_harmony_cb_data->msg_data.write.write_type, + p_harmony_cb_data->msg_data.write.len); + if (p_harmony_cb_data->msg_data.write.write_cb) { + T_BHA_WRITE_DATA *MSG_DATA = (T_BHA_WRITE_DATA *)os_mem_alloc(0, sizeof(T_BHA_WRITE_DATA)); + memcpy(MSG_DATA->write_value, p_harmony_cb_data->msg_data.write.p_value, p_harmony_cb_data->msg_data.write.len); + MSG_DATA->write_len = p_harmony_cb_data->msg_data.write.len; + MSG_DATA->write_cb = p_harmony_cb_data->msg_data.write.write_cb; + if (bt_harmony_adapter_app_send_callback_msg(BHA_CALLBACK_MSG_WRITE_SENT, MSG_DATA) != true) { + os_mem_free(MSG_DATA); + } + } else { + printf("[%s] User's write callback is NULL\r\n", __FUNCTION__); + } + + break; + } + default: + break; + } + } + + return app_result; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_peripheral_app.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_peripheral_app.h new file mode 100644 index 00000000..0c083d3d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_peripheral_app.h @@ -0,0 +1,146 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_HARMONY_ADAPTER_PERIPHERAL_APP_H_ +#define _BT_HARMONY_ADAPTER_PERIPHERAL_APP_H_ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include "ohos_bt_def.h" +#include "ohos_bt_gatt.h" +#include "bt_harmony_adapter_service.h" + +/*============================================================================* + * Variables + *============================================================================*/ +#define BT_HARMONY_ADAPTER_SERVICE_MAX_NUM 12 + +typedef struct { + uint16_t H_adv_int_min; //represent H_adv_int_min * 0.625ms + uint16_t H_adv_int_max; //represent H_adv_int_max * 0.625ms + uint8_t H_adv_evt_type; + uint8_t H_local_addr_type; + uint8_t H_adv_direct_type; + uint8_t H_adv_direct_addr[OHOS_BD_ADDR_LEN]; + uint8_t H_adv_chann_map; + uint8_t H_adv_filter_policy; + int H_duration; //represent H_duration * 10ms + uint8_t txPower; + unsigned int adv_datalen; + unsigned int scanrep_datalen; +} H_adv_param; + +typedef struct { + BdAddr Address; + bool accept; +} H_SecurityRsp_param; +typedef enum { + BHA_API_MSG_START_ADV, + BHA_API_MSG_STOP_ADV, + BHA_API_MSG_DISCONNECT, + BHA_API_MSG_AUTH_RESPOND, + BHA_API_MSG_ADD_SERVICE, + BHA_API_MSG_SEND_INDICATION, + BHA_API_MSG_MAX +} T_BHA_API_MSG_TYPE; + +typedef enum { + BHA_CALLBACK_MSG_ADV_STARTED, + BHA_CALLBACK_MSG_ADV_STOPED, + BHA_CALLBACK_MSG_CONNECTED, + BHA_CALLBACK_MSG_DISCONNECTED, + BHA_CALLBACK_MSG_AUTH_REQUEST, + BHA_CALLBACK_MSG_SERVICE_ADDED, + BHA_CALLBACK_MSG_INDICATION_SENT, + BHA_CALLBACK_MSG_WRITE_SENT, + BHA_CALLBACK_MSG_MTU_CHANGED, + BHA_CALLBACK_MSG_MAX +} T_BHA_CALLBACK_MSG_TYPE; + +typedef struct { + T_BHA_CALLBACK_MSG_TYPE type; + void *buf; +} T_BHA_CALLBACK_MSG; + +typedef struct { + T_SERVER_RESULT result; + T_SERVER_ID srv_id; +} T_BHA_SRV_ADDED_CALLBACK_DATA; + +typedef struct { + uint8_t conn_id; + uint8_t serverID; + BdAddr bt_addr; +} T_BHA_CONNECTED_CALLBACK_DATA; + +typedef struct { + int conn_id; + int mtu_size; +} T_BHA_MTU_CALLBACK_DATA; + +typedef struct { + T_SERVER_RESULT result; + T_SERVER_ID srv_id; + uint8_t att_index; +} T_BHA_IND_SENT_CALLBACK_DATA; + +typedef struct { + uint8_t write_len; + uint8_t write_value[HARMONY_WRITE_MAX_LEN]; + BleGattServiceWrite write_cb; +} T_BHA_WRITE_DATA; +/*============================================================================* + * Functions + *============================================================================*/ + +bool bt_harmony_adapter_app_send_api_msg(T_BHA_API_MSG_TYPE sub_type, void *buf); + +bool bt_harmony_adapter_app_send_callback_msg(T_BHA_CALLBACK_MSG_TYPE type, void *buf); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_harmony_adapter_app_handle_io_msg(T_IO_MSG io_msg); + +void bt_harmony_adapter_app_handle_callback_msg(T_BHA_CALLBACK_MSG callback_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id. + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_harmony_adapter_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_harmony_adapter_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_service.c b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_service.c new file mode 100644 index 00000000..abfe4ed0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_service.c @@ -0,0 +1,397 @@ +//#include +#include +#include +#include +#include "bt_harmony_adapter_peripheral_app.h" +#include "ohos_bt_gatt_server.h" +#include "ohos_bt_gatt_client.h" +#include +#include "platform_stdlib.h" +#include + +static uint8_t bt_harmony_char_read_value[HARMONY_READ_MAX_LEN]; +static unsigned int bt_harmony_char_read_len = 0; +static uint8_t bt_harmony_char_write_value[HARMONY_WRITE_MAX_LEN]; +BHA_SRV_DATABASE ble_srv_database[12] = {0}; +uint8_t ble_srv_count = 0; + +BHA_SERVICE_INFO bt_harmony_adapter_srvs_head; +BHA_SERVICE_INFO *bt_harmony_adapter_srv_p = &bt_harmony_adapter_srvs_head; +uint8_t bt_harmony_adapter_srvs_num = 0; +static P_FUN_SERVER_GENERAL_CB bt_harmony_service_cb = NULL; +extern void *add_service_sem; + +void bt_harmony_adapter_free_service_info(BHA_SERVICE_INFO *service_info) +{ + for (int i = 0; i < service_info->att_num; i ++) { + if (service_info->att_tbl[i].p_value_context != NULL) { + os_mem_free(service_info->att_tbl[i].p_value_context); + } + } + os_mem_free(service_info->att_tbl); + os_mem_free(service_info->cbInfo); + os_mem_free(service_info); + ble_srv_count --; +} + +void bt_harmony_adapter_move_pointer_and_free_service(BHA_SERVICE_INFO *service_info) +{ + BHA_SERVICE_INFO *pnext = service_info->next; + BHA_SERVICE_INFO *p_srv = &bt_harmony_adapter_srvs_head; + + while (p_srv) { + if (p_srv->next == service_info) { + p_srv->next = pnext; + if (pnext == NULL) { + bt_harmony_adapter_srv_p = p_srv; + } + break; + } else { + p_srv = p_srv->next; + } + } + bt_harmony_adapter_free_service_info(service_info); +} + +void bt_harmony_adapter_search_and_free_service(T_BHA_SRV_ADDED_CALLBACK_DATA *p_data) +{ + BHA_SERVICE_INFO *p_srv = &bt_harmony_adapter_srvs_head; + BHA_SERVICE_INFO *pnext; + + while (p_srv) { + pnext = p_srv->next; + if (pnext->srvId == p_data->srv_id) { + p_srv->next = pnext->next; + if (pnext->next == NULL) { + bt_harmony_adapter_srv_p = p_srv; + } + bt_harmony_adapter_srvs_num --; + bt_harmony_adapter_free_service_info(pnext); + break; + } else { + p_srv = p_srv->next; + } + } + +} + +bool bt_harmony_adapter_send_indication(uint8_t conn_id, uint8_t service_id, uint8_t handle, + uint8_t *p_value, uint16_t length, bool type) +{ + if (p_value == NULL) { + return false; + } + printf("[%s] service_id %d index %d\r\n", __FUNCTION__, service_id, handle); + T_GATT_PDU_TYPE pdu_type; + if (type == 1) { + pdu_type = GATT_PDU_TYPE_INDICATION; + } else { + pdu_type = GATT_PDU_TYPE_NOTIFICATION; + } + return server_send_data(conn_id, service_id, handle, p_value, length, pdu_type); +} + +void bt_harmony_adapter_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t cccbits) +{ + T_HARMONY_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.conn_id = conn_id; + callback_data.srv_id = service_id; + callback_data.msg_data.cccd.attr_index = attrib_index; + callback_data.msg_data.cccd.ccc_val = cccbits; + + /* Notify Application. */ + if (bt_harmony_service_cb) { + bt_harmony_service_cb(service_id, (void *)&callback_data); + } +} + +T_APP_RESULT bt_harmony_adapter_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + printf("[%s] service_id %d index 0x%x\r\n", __FUNCTION__, service_id, attrib_index); + T_HARMONY_CALLBACK_DATA callback_data; + + /* Make sure written value size is valid. */ + if (p_value == NULL) { + cause = APP_RESULT_INVALID_VALUE_SIZE; + } else { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.srv_id = service_id; + callback_data.msg_data.write.write_type = write_type; + memcpy(bt_harmony_char_write_value, p_value, length); + callback_data.msg_data.write.p_value = bt_harmony_char_write_value; + callback_data.msg_data.write.len = length; + + BHA_SERVICE_INFO *p = bt_harmony_adapter_srvs_head.next; + while (p) { + if (p->srvId == service_id) { + break; + } else { + p = p->next; + } + } + if (p) { + callback_data.msg_data.write.write_cb = (p->cbInfo[attrib_index]).func.write; + } else { + callback_data.msg_data.write.write_cb = NULL; + } + if (bt_harmony_service_cb) { + bt_harmony_service_cb(service_id, (void *)&callback_data); + } + } + + return (cause); +} + + +T_APP_RESULT bt_harmony_adapter_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + (void)offset; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + printf("[%s] service_id %d index 0x%x\r\n", __FUNCTION__, service_id, attrib_index); + bt_harmony_char_read_len = HARMONY_READ_MAX_LEN; + + T_HARMONY_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.srv_id = service_id; + callback_data.msg_data.read.p_value = bt_harmony_char_read_value; + callback_data.msg_data.read.p_len = &bt_harmony_char_read_len; + BHA_SERVICE_INFO *p = bt_harmony_adapter_srvs_head.next; + while (p) { + if (p->srvId == service_id) { + break; + } else { + p = p->next; + } + } + if (p) { + callback_data.msg_data.read.read_cb = (p->cbInfo[attrib_index]).func.read; + } else { + callback_data.msg_data.read.read_cb = NULL; + } + + if (bt_harmony_service_cb) { + bt_harmony_service_cb(service_id, (void *)&callback_data); + } + + *pp_value = bt_harmony_char_read_value; + *p_length = bt_harmony_char_read_len; + + return (cause); +} + +const T_FUN_GATT_SERVICE_CBS bt_harmony_adapter_service_cbs = { + bt_harmony_adapter_attr_read_cb, /* Read callback function pointer */ + bt_harmony_adapter_attr_write_cb, /* Write callback function pointer */ + bt_harmony_adapter_cccd_update_cb /* CCCD update callback function pointer */ +}; + +T_SERVER_ID bt_harmony_adapter_add_service(BHA_SERVICE_INFO *service_info, void *p_func) +{ + if (service_info == NULL || service_info->att_tbl == NULL) { + if (add_service_sem) + os_sem_give(add_service_sem); + return 0xff; + } + if (false == server_add_service(&(service_info->srvId), + (uint8_t *) service_info->att_tbl, + (service_info->att_num) * sizeof(T_ATTRIB_APPL), + bt_harmony_adapter_service_cbs)) { + printf("[%s] add service fail\r\n", __FUNCTION__); + bt_harmony_adapter_move_pointer_and_free_service(service_info); + if (add_service_sem) + os_sem_give(add_service_sem); + return 0xff; + } else { + printf("[%s] add service %d success\r\n", __FUNCTION__, service_info->srvId); + bt_harmony_adapter_srvs_num++; + service_info->status = BHA_SERVICE_REG_SUCCESS; + } + + if (bt_harmony_service_cb == NULL) { + bt_harmony_service_cb = (P_FUN_SERVER_GENERAL_CB) p_func; + } + return service_info->srvId; +} + +bool setup_ble_srv_info(uint8_t service_index, uint8_t att_handle, uint16_t char_index) +{ + if (bt_harmony_adapter_srv_p == &bt_harmony_adapter_srvs_head) { + ble_srv_database[service_index].start_handle = 1; //first service, handle start from 0x1 + } else { + ble_srv_database[service_index].start_handle = bt_harmony_adapter_srv_p->start_handle + bt_harmony_adapter_srv_p->att_num; + } + ble_srv_database[service_index].srv_id = service_index; + return true; +} +bool setup_ble_char_info(uint8_t service_index, uint16_t att_handle, uint16_t char_index) +{ + ble_srv_database[service_index].rela_atthandle[char_index] = att_handle; + return true; +} +uint32_t switch_perm(uint8_t perm) +{ + uint32_t permission = 0x0000; + if (perm & 0x01) { + permission = permission | GATT_PERM_READ; + } else if (perm & 0x02) { + permission = permission | GATT_PERM_READ_AUTHEN_REQ; + } else if (perm & 0x04) { + permission = permission | GATT_PERM_READ_AUTHEN_MITM_REQ; + } + + if (perm & 0x10) { + permission = permission | GATT_PERM_WRITE; + } else if (perm & 0x20) { + permission = permission | GATT_PERM_WRITE_AUTHEN_REQ; + } else if (perm & 0x40) { + permission = permission | GATT_PERM_WRITE_AUTHEN_MITM_REQ; + } else if (perm & 0x80) { + permission = permission | GATT_PERM_WRITE_AUTHOR_REQ; + } + return permission; +} + +static int setup_ble_char_usd_attr(T_ATTRIB_APPL *attr, uint8_t *val, uint8_t len, uint8_t perm) +{ + attr->permissions = switch_perm(perm); + attr->flags = ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z; + attr->type_value[0] = LO_WORD(GATT_UUID_CHAR_USER_DESCR); + attr->type_value[1] = HI_WORD(GATT_UUID_CHAR_USER_DESCR); + attr->value_len = len; + attr->p_value_context = os_mem_alloc(0, attr->value_len); + memset(attr->p_value_context, 0, attr->value_len); + memcpy(attr->p_value_context, (void *)val, attr->value_len); + return 0; +} + +static int setup_ble_char_ccc_attr(T_ATTRIB_APPL *attr) +{ + attr->flags = ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL; + attr->type_value[0] = LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG); + attr->type_value[1] = HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG); + attr->type_value[2] = 0; + attr->type_value[3] = 0; + attr->p_value_context = NULL; + attr->value_len = 2; + attr->permissions = GATT_PERM_READ | GATT_PERM_WRITE; + return 0; +} + +static int setup_ble_char_val_attr(T_ATTRIB_APPL *attr, uint8_t *uuid, UuidType uuid_type, uint8_t perm) +{ + attr->permissions = switch_perm(perm); + if (uuid_type == OHOS_UUID_TYPE_128_BIT) { + attr->flags = ATTRIB_FLAG_UUID_128BIT | ATTRIB_FLAG_VALUE_APPL; + memcpy(attr->type_value, uuid, 16); + } else if (uuid_type == OHOS_UUID_TYPE_16_BIT) { + attr->flags = ATTRIB_FLAG_VALUE_APPL; + attr->type_value[0] = uuid[0]; + attr->type_value[1] = uuid[1]; + } + attr->value_len = 0; + attr->p_value_context = NULL; + return 0; +} + +static int setup_ble_char_dec_attr(T_ATTRIB_APPL *attr, uint8_t prop) +{ + attr->flags = ATTRIB_FLAG_VALUE_INCL; + attr->type_value[0] = LO_WORD(GATT_UUID_CHARACTERISTIC); + attr->type_value[1] = HI_WORD(GATT_UUID_CHARACTERISTIC); + attr->type_value[2] = prop; + attr->value_len = 1; + attr->p_value_context = NULL; + attr->permissions = GATT_PERM_READ; + return 0; +} + +static int setup_ble_serv_dec_attr(T_ATTRIB_APPL *attr, uint8_t *uuid, UuidType uuid_type) +{ + attr->type_value[0] = LO_WORD(GATT_UUID_PRIMARY_SERVICE); /* type */ + attr->type_value[1] = HI_WORD(GATT_UUID_PRIMARY_SERVICE); + if (uuid_type == OHOS_UUID_TYPE_128_BIT) { + attr->flags = ATTRIB_FLAG_LE | ATTRIB_FLAG_VOID; + attr->value_len = 16; + attr->p_value_context = os_mem_alloc(0, attr->value_len); + memset(attr->p_value_context, 0, attr->value_len); + memcpy(attr->p_value_context, (void *)uuid, attr->value_len); + } else if (uuid_type == OHOS_UUID_TYPE_16_BIT) { + attr->flags = ATTRIB_FLAG_LE | ATTRIB_FLAG_VALUE_INCL; + attr->type_value[2] = uuid[0]; /* value */ + attr->type_value[3] = uuid[1]; + attr->p_value_context = NULL; + attr->value_len = 2; + } + attr->permissions = GATT_PERM_READ; + return 0; +} + +BHA_SERVICE_INFO *bt_harmony_adapter_parse_srv_tbl(BleGattService *profile) +{ + BHA_SERVICE_INFO *new_srv = (BHA_SERVICE_INFO *) os_mem_alloc(0, sizeof(BHA_SERVICE_INFO)); + memset(new_srv, 0, sizeof(BHA_SERVICE_CALLBACK_INFO)); + new_srv->status = BHA_SERVICE_REG_PENDING; + uint8_t srv_index = 0; + + + uint8_t att_count = profile->attrNum; + BleGattAttr *att_list = profile->attrList; + new_srv->att_tbl = (T_ATTRIB_APPL *) os_mem_alloc(0, (4 * att_count - 3) * sizeof(T_ATTRIB_APPL)); + memset(new_srv->att_tbl, 0, (4 * att_count - 3) * sizeof(T_ATTRIB_APPL)); + new_srv->cbInfo = (BHA_SERVICE_CALLBACK_INFO *) os_mem_alloc(0, (4 * att_count - 3) * sizeof(BHA_SERVICE_CALLBACK_INFO)); + memset(new_srv->cbInfo, 0, (4 * att_count - 3) * sizeof(BHA_SERVICE_CALLBACK_INFO)); + uint16_t j = 0, k = 0; + for (int i = 0; i < att_count; i++) { + if (att_list[i].attrType == OHOS_BLE_ATTRIB_TYPE_SERVICE) { + srv_index = ble_srv_count ++; + setup_ble_serv_dec_attr(&new_srv->att_tbl[j], att_list[i].uuid, att_list[i].uuidType); + new_srv->cbInfo[j].att_handle = j; + memcpy(&(new_srv->cbInfo[j].func), &(att_list[i].func), sizeof(BleGattOperateFunc)); + setup_ble_srv_info(srv_index, j, i); + j ++; + } else if (att_list[i].attrType == OHOS_BLE_ATTRIB_TYPE_CHAR) { + setup_ble_char_dec_attr(&new_srv->att_tbl[j], att_list[i].properties); + new_srv->cbInfo[j].att_handle = j; + memcpy(&(new_srv->cbInfo[j].func), &(att_list[i].func), sizeof(BleGattOperateFunc)); + j ++; + k ++; + setup_ble_char_val_attr(&new_srv->att_tbl[j], att_list[i].uuid, att_list[i].uuidType, att_list[i].permission); + setup_ble_char_info(srv_index, j, k); + new_srv->cbInfo[j].att_handle = j; + memcpy(&(new_srv->cbInfo[j].func), &(att_list[i].func), sizeof(BleGattOperateFunc)); + j ++; + if ((att_list[i].properties & OHOS_GATT_CHARACTER_PROPERTY_BIT_NOTIFY) || (att_list[i].properties & OHOS_GATT_CHARACTER_PROPERTY_BIT_INDICATE)) { + setup_ble_char_ccc_attr(&new_srv->att_tbl[j]); + new_srv->cbInfo[j].att_handle = j; + memcpy(&(new_srv->cbInfo[j].func), &(att_list[i].func), sizeof(BleGattOperateFunc)); + j ++; + } + } else if (att_list[i].attrType == OHOS_BLE_ATTRIB_TYPE_CHAR_USER_DESCR) { + setup_ble_char_usd_attr(&new_srv->att_tbl[j], att_list[i].value, att_list[i].valLen, att_list[i].permission); + new_srv->cbInfo[j].att_handle = j; + memcpy(&(new_srv->cbInfo[j].func), &(att_list[i].func), sizeof(BleGattOperateFunc)); + j ++; + } else { + printf("[%s] Unknown Attribute Type\r\n", __FUNCTION__); + } + } + new_srv->att_num = j; + ble_srv_database[srv_index].chrc_num = j; + if (bt_harmony_adapter_srv_p == &bt_harmony_adapter_srvs_head) { + new_srv->start_handle = 1; //first service, handle start from 0x1 + } else { + new_srv->start_handle = bt_harmony_adapter_srv_p->start_handle + bt_harmony_adapter_srv_p->att_num; + } + bt_harmony_adapter_srv_p->next = new_srv; + bt_harmony_adapter_srv_p = bt_harmony_adapter_srv_p->next; + return new_srv; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_service.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_service.h new file mode 100644 index 00000000..c6ca5541 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/bt_harmony_adapter_service.h @@ -0,0 +1,84 @@ +#include +#include "ohos_bt_gatt_server.h" +#include "ohos_bt_gatt_client.h" + +#define HARMONY_READ_MAX_LEN 300 +#define HARMONY_WRITE_MAX_LEN 300 +#define BHA_MAX_ATTR_NUM 12 + +typedef struct { + T_WRITE_TYPE write_type; + unsigned int len; + uint8_t *p_value; + BleGattServiceWrite write_cb; +} T_HARMONY_WRITE_MSG; + +typedef struct { + unsigned int *p_len; + uint8_t *p_value; + BleGattServiceRead read_cb; +} T_HARMONY_READ_MSG; + +typedef struct { + uint16_t attr_index; + uint16_t ccc_val; +} T_HARMONY_CCCD_MSG; + +typedef union { + T_HARMONY_CCCD_MSG cccd; + T_HARMONY_READ_MSG read; + T_HARMONY_WRITE_MSG write; +} T_HARMONY_MSG_DATA; + +typedef struct { + uint8_t conn_id; + T_SERVER_ID srv_id; + T_SERVICE_CALLBACK_TYPE msg_type; + T_HARMONY_MSG_DATA msg_data; +} T_HARMONY_CALLBACK_DATA; + + +typedef struct { + uint8_t att_handle; + BleGattOperateFunc func; +} BHA_SERVICE_CALLBACK_INFO; + +typedef enum { + BHA_SERVICE_REG_SUCCESS = 1, + BHA_SERVICE_REG_PENDING +} BHA_SERVICE_STATUS; + +typedef struct BHA_SERVICE_INFO { + uint8_t srvId; + uint8_t att_num; + uint8_t start_handle; + BHA_SERVICE_STATUS status; + T_ATTRIB_APPL *att_tbl; + BHA_SERVICE_CALLBACK_INFO *cbInfo; + struct BHA_SERVICE_INFO *next; +} BHA_SERVICE_INFO; + +typedef struct { + bool type; + uint8_t srv_id; + uint8_t att_handle; + char *val; + uint16_t len; +} BHA_INDICATION_PARAM; + +typedef struct { + uint8_t srv_id; + uint16_t start_handle; + uint16_t chrc_num; + uint16_t rela_atthandle[BHA_MAX_ATTR_NUM]; /* characteristic info */ +} BHA_SRV_DATABASE; +extern uint8_t bt_harmony_adapter_srvs_num; + +BHA_SERVICE_INFO *bt_harmony_adapter_parse_srv_tbl(BleGattService *profile); + +T_SERVER_ID bt_harmony_adapter_add_service(BHA_SERVICE_INFO *service_info, void *p_func); + +bool bt_harmony_adapter_send_indication(uint8_t conn_id, uint8_t service_id, uint8_t handle, uint8_t *p_value, uint16_t length, bool type); + + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/harmony_bt_api.c b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/harmony_bt_api.c new file mode 100644 index 00000000..e28ef182 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/harmony_bt_api.c @@ -0,0 +1,468 @@ +//#include +#include +#include +#include "bt_harmony_adapter_peripheral_app.h" +#include "ohos_bt_gatt_server.h" +#include "ohos_bt_gatt_client.h" +#include +#include "platform_stdlib.h" +#include "string.h" +#include +#include + +uint8_t H_adv_data[31]; +uint8_t H_scan_response_data[31]; +uint16_t H_auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; +uint8_t H_auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +void *send_indication_sem = NULL; +void *add_service_sem = NULL; +extern BHA_SRV_DATABASE ble_srv_database[12]; +extern uint8_t device_name[GAP_DEVICE_NAME_LEN]; + +extern uint8_t RT_remote_bd[OHOS_BD_ADDR_LEN]; +extern int bt_get_mac_address(uint8_t *mac); +extern void bt_harmony_adapter_app_init(void); +extern void bt_harmony_adapter_app_deinit(void); +extern bool bt_harmony_adapter_app_send_api_msg(T_BHA_API_MSG_TYPE sub_type, void *buf); +int SetDeviceName(const char *name, unsigned int len) +{ + if (name == NULL || len > GAP_DEVICE_NAME_LEN) { + printf("[%s]invalid name or len\r\n",__func__,__LINE__); + return OHOS_BT_STATUS_PARM_INVALID; + } + memset(device_name,GAP_DEVICE_NAME_LEN,0); + memcpy(device_name,name,len); + + return OHOS_BT_STATUS_SUCCESS; +} + +int InitBtStack(void) +{ + return OHOS_BT_STATUS_SUCCESS; +} + +int EnableBtStack(void) +{ + bt_harmony_adapter_app_init(); + + return OHOS_BT_STATUS_SUCCESS; +} + +int DisableBtStack(void) +{ + bt_harmony_adapter_app_deinit(); + + return OHOS_BT_STATUS_SUCCESS; +} + +int BleStopAdv(int advId) +{ + int cause = false; + T_GAP_DEV_STATE new_state; + + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[%s]:BLE is not running\r\n", __func__); + return OHOS_BT_STATUS_SUCCESS; + } + + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) { + printf("[%s]:adv is stopped\r\n", __func__); + return OHOS_BT_STATUS_SUCCESS; + } + cause = bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_STOP_ADV, NULL); + + if (cause == false) { + return OHOS_BT_STATUS_FAIL; + } else { + while (new_state.gap_adv_state != GAP_ADV_STATE_IDLE) { + os_delay(1); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } + return OHOS_BT_STATUS_SUCCESS; + } +} + +int BleSetSecurityIoCap(BleIoCapMode mode) +{ + switch (mode) { + case OHOS_BLE_IO_CAP_OUT: + H_auth_io_cap = GAP_IO_CAP_DISPLAY_ONLY; + break; + case OHOS_BLE_IO_CAP_IO: + H_auth_io_cap = GAP_IO_CAP_DISPLAY_YES_NO; + break; + case OHOS_BLE_IO_CAP_IN: + H_auth_io_cap = GAP_IO_CAP_KEYBOARD_ONLY; + break; + case OHOS_BLE_IO_CAP_NONE: + H_auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + break; + case OHOS_BLE_IO_CAP_KBDISP: + H_auth_io_cap = GAP_IO_CAP_KEYBOARD_DISPLAY; + break; + default: + printf("[%s]:invalid IO Capability\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + break; + } + return OHOS_BT_STATUS_SUCCESS; +} + +int BleSetSecurityAuthReq(BleAuthReqMode mode) +{ + switch (mode) { + case OHOS_BLE_AUTH_NO_BOND: + //no bond,no MITM,no SC + H_auth_flags = GAP_AUTHEN_BIT_NONE; + break; + case OHOS_BLE_AUTH_BOND: + //bond,no MITM,no SC + H_auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + break; + case OHOS_BLE_AUTH_REQ_MITM: + //no bond,no SC + H_auth_flags = GAP_AUTHEN_BIT_MITM_FLAG; + break; + case OHOS_BLE_AUTH_REQ_SC_ONLY: + //no bond,no MITM,SC only + H_auth_flags = GAP_AUTHEN_BIT_SC_FLAG | GAP_AUTHEN_BIT_SC_ONLY_FLAG; + break; + case OHOS_BLE_AUTH_REQ_SC_BOND: + //bond,sc,no MITM + H_auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_SC_FLAG; + break; + case OHOS_BLE_AUTH_REQ_SC_MITM: + //no bond,SC,MITM + H_auth_flags = GAP_AUTHEN_BIT_MITM_FLAG | GAP_AUTHEN_BIT_SC_FLAG; + break; + case OHOS_BLE_AUTH_REQ_SC_MITM_BOND: + //bond,SC,MITM + H_auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_MITM_FLAG | GAP_AUTHEN_BIT_SC_FLAG; + break; + default: + printf("[%s]:invalid authreqmode\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + break; + } + return OHOS_BT_STATUS_SUCCESS; + +} + +int BleGattSecurityRsp(BdAddr bdAddr, bool accept) +{ + int cause = false; + if (memcmp(RT_remote_bd, bdAddr.addr, OHOS_BD_ADDR_LEN) == 0) { + H_SecurityRsp_param *SecurityRsp = (H_SecurityRsp_param *)os_mem_alloc(0, sizeof(H_SecurityRsp_param)); + SecurityRsp->accept = accept; + memcpy(SecurityRsp->Address.addr, bdAddr.addr, OHOS_BD_ADDR_LEN); + cause = bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_AUTH_RESPOND, SecurityRsp); + if (cause == false) { + os_mem_free(SecurityRsp); + return OHOS_BT_STATUS_FAIL; + } else { + return OHOS_BT_STATUS_SUCCESS; + } + } else { + printf("[%s]:invalid param bdAddr\r\n", __func__, __LINE__); + return OHOS_BT_STATUS_PARM_INVALID; + } +} + +int BleGattsDisconnect(int serverId, BdAddr bdAddr, int connId) +{ + uint8_t conn_id = 0; + int cause = false; + if (connId == conn_id) { + if (memcmp(RT_remote_bd, bdAddr.addr, OHOS_BD_ADDR_LEN) == 0) { + cause = bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_DISCONNECT, &bdAddr.addr); + if (cause == false) { + return OHOS_BT_STATUS_FAIL; + } else { + return OHOS_BT_STATUS_SUCCESS; + } + } else { + printf("[%s]:invalid bt address\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } + } else { + printf("[%s]:invalid connId\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } +} + +int BleGattsSetEncryption(BdAddr bdAddr, BleSecAct secAct) +{ + printf("[%s]:we not support this feature\r\n", __func__); + return OHOS_BT_STATUS_SUCCESS; +} + + +int ReadBtMacAddr(unsigned char *mac, unsigned int len) +{ + if ((mac == NULL) || (len != 6)) { + return OHOS_BT_STATUS_PARM_INVALID; + } + + uint8_t p_mac[6]; +#if defined(CONFIG_PLATFORM_8721D) + uint8_t logical_efuse[1024]; + + if (EFUSE_LMAP_READ(logical_efuse) == _FAIL) { + printf("EFUSE_LMAP_READ fail\r\n"); + return OHOS_BT_STATUS_FAIL; + } + + memcpy(p_mac, logical_efuse + 0x190, 6); + if ((p_mac[0] == 0xff) || (p_mac[1] == 0xff)) { + printf("BT mac address is not PG in eFuse, use default address in rtlbt_init_config[]\r\n"); + p_mac[0] = 0x89; + p_mac[1] = 0x51; + p_mac[2] = 0x12; + p_mac[3] = 0x36; + p_mac[4] = 0x28; + p_mac[5] = 0x11; + } + memcpy(mac, p_mac, 6); +#else if defined(CONFIG_PLATFORM_8710C) + extern int bt_get_mac_address(uint8_t *mac); + + bt_get_mac_address(p_mac); + + if ((p_mac[0] == 0xff) || (p_mac[1] == 0xff)) { + printf("BT mac address is not PG in eFuse, use default address in rtlbt_init_config[]\r\n"); + p_mac[0] = 0x66; + p_mac[1] = 0x55; + p_mac[2] = 0x44; + p_mac[3] = 0x77; + p_mac[4] = 0x88; + p_mac[5] = 0x99; + } + memcpy(mac, p_mac, 6); +#endif + return OHOS_BT_STATUS_SUCCESS; +} + +int BleStartAdvEx(int *advId, const StartAdvRawData rawData, BleAdvParams advParam) +{ + + T_GAP_DEV_STATE new_state = {0}; + H_adv_param *h_adv_param = (H_adv_param *)os_mem_alloc(0, sizeof(H_adv_param)); + int cause = false; + + if ((rawData.advDataLen > 31) || (rawData.rspDataLen > 31)) { + printf("[%s]:invalid advdata length or scan resp length\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } + if ((advParam.minInterval < 0x20) || (advParam.maxInterval > 0x4000) || (advParam.minInterval > advParam.maxInterval)) { + printf("[%s]:invalid adv interval param\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } + if ((advParam.ownAddrType != 0) && (advParam.ownAddrType != 1) && (advParam.ownAddrType != 2) && (advParam.ownAddrType != 3)) { + printf("[%s]:invalid owner address type\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } + if ((advParam.peerAddrType != 0) && (advParam.peerAddrType != 1)) { + printf("[%s]:invalid peer address type\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } + if (((advParam.channelMap & (~GAP_ADVCHAN_ALL)) != 0) || (advParam.channelMap == 0)) { + printf("[%s]:invalid channel map\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + } + + switch (advParam.advType) { + case OHOS_BLE_ADV_IND: + h_adv_param->H_adv_evt_type = GAP_ADTYPE_ADV_IND; + break; + case OHOS_BLE_ADV_DIRECT_IND_HIGH: + h_adv_param->H_adv_evt_type = GAP_ADTYPE_ADV_HDC_DIRECT_IND; + break; + case OHOS_BLE_ADV_SCAN_IND: + h_adv_param->H_adv_evt_type = GAP_ADTYPE_ADV_SCAN_IND; + break; + case OHOS_BLE_ADV_NONCONN_IND: + h_adv_param->H_adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND; + break; + case OHOS_BLE_ADV_DIRECT_IND_LOW: + h_adv_param->H_adv_evt_type = GAP_ADTYPE_ADV_LDC_DIRECT_IND; + break; + default: + printf("[%s]:invalid adv type\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + break; + } + + switch (advParam.advFilterPolicy) { + case OHOS_BLE_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY: + h_adv_param->H_adv_filter_policy = GAP_ADV_FILTER_ANY; + break; + case OHOS_BLE_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY: + h_adv_param->H_adv_filter_policy = GAP_ADV_FILTER_WHITE_LIST_SCAN; + break; + case OHOS_BLE_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST: + h_adv_param->H_adv_filter_policy = GAP_ADV_FILTER_WHITE_LIST_CONN; + break; + case OHOS_BLE_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST: + h_adv_param->H_adv_filter_policy = GAP_ADV_FILTER_WHITE_LIST_ALL; + break; + default: + printf("[%s]:invalid Filter Policy\r\n", __func__); + return OHOS_BT_STATUS_PARM_INVALID; + break; + } + + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + if (new_state.gap_adv_state == GAP_ADV_STATE_START) { + while (new_state.gap_adv_state != GAP_ADV_STATE_ADVERTISING) { + os_delay(1); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } + } + if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) { + cause = bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_STOP_ADV, NULL); //stop adv + if (cause == false) { + return OHOS_BT_STATUS_FAIL; + } + } + while (new_state.gap_adv_state != GAP_ADV_STATE_IDLE) { + os_delay(1); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } + + memcpy(H_adv_data, rawData.advData, rawData.advDataLen); + memcpy(H_scan_response_data, rawData.rspData, rawData.rspDataLen); + + h_adv_param->H_adv_int_min = advParam.minInterval; + h_adv_param->H_adv_int_max = advParam.maxInterval; + h_adv_param->H_local_addr_type = advParam.ownAddrType; + h_adv_param->H_adv_direct_type = advParam.peerAddrType; + memcpy(h_adv_param->H_adv_direct_addr, advParam.peerAddr.addr, OHOS_BD_ADDR_LEN); + h_adv_param->H_adv_chann_map = advParam.channelMap; + h_adv_param->H_duration = advParam.duration; + h_adv_param->adv_datalen = rawData.advDataLen; + h_adv_param->scanrep_datalen = rawData.rspDataLen; + cause = bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_START_ADV, h_adv_param); + if (cause == false) { + os_mem_free(h_adv_param); + return OHOS_BT_STATUS_FAIL; + } else { + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + while (new_state.gap_adv_state != GAP_ADV_STATE_ADVERTISING) { + os_delay(1); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } + return OHOS_BT_STATUS_SUCCESS; + } +} + +BtGattCallbacks BH_GattCallbacks ; +BtGattServerCallbacks BH_GattServerCallbacks; + +int BleGattRegisterCallbacks(BtGattCallbacks *func) +{ + if (func == NULL) { + return OHOS_BT_STATUS_PARM_INVALID; + } + + BH_GattCallbacks.advEnableCb = func->advEnableCb; + BH_GattCallbacks.advDisableCb = func->advDisableCb; + BH_GattCallbacks.securityRespondCb = func->securityRespondCb; + return OHOS_BT_STATUS_SUCCESS; +} + +int BleGattsRegisterCallbacks(BtGattServerCallbacks *func) +{ + if (func == NULL) { + return OHOS_BT_STATUS_PARM_INVALID; + } + BH_GattServerCallbacks.connectServerCb = func->connectServerCb; + BH_GattServerCallbacks.disconnectServerCb = func->disconnectServerCb; + BH_GattServerCallbacks.mtuChangeCb = func->mtuChangeCb; + BH_GattServerCallbacks.serviceStartCb = func->serviceStartCb; + return OHOS_BT_STATUS_SUCCESS; +} + +extern void bt_harmony_adapter_move_pointer_and_free_service(BHA_SERVICE_INFO *service_info); +int BleGattsStartServiceEx(int *srvcHandle, BleGattService *srvcInfo) +{ + if (srvcInfo == NULL || srvcInfo->attrList == NULL) { + return OHOS_BT_STATUS_PARM_INVALID; + } + + if (bt_harmony_adapter_srvs_num >= BT_HARMONY_ADAPTER_SERVICE_MAX_NUM) { + printf("[%s] BLE Stack only support up to 12 Services!\r\n", __FUNCTION__); + return OHOS_BT_STATUS_FAIL; + } + if (add_service_sem == NULL) { + if (os_sem_create(&add_service_sem,0,1) == true){ + printf("[%s]:create sem success\r\n",__func__); + }else{ + printf("[%s]:create sem fail\r\n",__func__); + } + } + + BHA_SERVICE_INFO *srv_info = bt_harmony_adapter_parse_srv_tbl(srvcInfo); + if (bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_ADD_SERVICE, srv_info) == false) { + bt_harmony_adapter_move_pointer_and_free_service(srv_info); + return OHOS_BT_STATUS_FAIL; + } + if (os_sem_take(add_service_sem, 3000) == true){ + *srvcHandle = srv_info->start_handle; + return OHOS_BT_STATUS_SUCCESS; + } else { + printf("[%s] take add_service_sem timeout\r\n",__func__); + bt_harmony_adapter_move_pointer_and_free_service(srv_info); + return OHOS_BT_STATUS_FAIL; + + } +} + +int BleGattsSendIndication(int serverId, GattsSendIndParam *param) +{ + if (param == NULL || param->value == NULL || param->connectId != 0) { + return OHOS_BT_STATUS_PARM_INVALID; + } + if (send_indication_sem == NULL) { + if (os_sem_create(&send_indication_sem, 0, 1) == true) { + printf("[%s]:create sem success\r\n", __func__); + } else { + printf("[%s]:create sem fail\r\n", __func__); + } + } + for (int i = 0; i < BT_HARMONY_ADAPTER_SERVICE_MAX_NUM; i ++) { + if ((param->attrHandle > ble_srv_database[i].start_handle) && (param->attrHandle < (ble_srv_database[i].start_handle + ble_srv_database[i].chrc_num))) { + serverId = i; + } + } + + int real_handle = 0; + real_handle = param->attrHandle - ble_srv_database[serverId].start_handle; + BHA_INDICATION_PARAM *indi = (BHA_INDICATION_PARAM *) os_mem_alloc(0, sizeof(BHA_INDICATION_PARAM)); + indi->srv_id = serverId; + indi->type = param->confirm ? 1 : 0; + indi->att_handle = ble_srv_database[serverId].rela_atthandle[real_handle]; + indi->len = param->valueLen; + indi->val = (char *) os_mem_alloc(0, param->valueLen); + memcpy(indi->val, param->value, param->valueLen); + if (bt_harmony_adapter_app_send_api_msg(BHA_API_MSG_SEND_INDICATION, indi)) { + + if (os_sem_take(send_indication_sem, 30000) == true) { + os_sem_delete(send_indication_sem); + send_indication_sem = NULL; + return OHOS_BT_STATUS_SUCCESS; + } + } else { + os_mem_free(indi->val); + os_mem_free(indi); + } + os_sem_delete(send_indication_sem); + send_indication_sem = NULL; + return OHOS_BT_STATUS_FAIL; +} + +int BleGattsStopServiceEx(int srvcHandle) +{ + printf("[%s] BLE Stack do not support stop service!\r\n", __FUNCTION__); + return OHOS_BT_STATUS_SUCCESS; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_def.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_def.h new file mode 100644 index 00000000..2f95da24 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_def.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * Description: Common definition + */ + +#ifndef OHOS_BT_DEF_H +#define OHOS_BT_DEF_H + +/* Device address length */ +#define OHOS_BD_ADDR_LEN 6 + +/* Bluetooth 16-byte UUID */ +#define OHOS_BLE_UUID_MAX_LEN 16 + +/* Characteristic Properties */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_BROADCAST 0x01 /* Characteristic is broadcastable */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_READ 0x02 /* Characteristic is readable */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_WRITE_NO_RSP 0x04 /* Characteristic can be written without response */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_WRITE 0x08 /* Characteristic can be written */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_NOTIFY 0x10 /* Characteristic supports notification */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_INDICATE 0x20 /* Characteristic supports indication */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_SIGNED_WRITE 0x40 /* Characteristic supports write with signature */ +#define OHOS_GATT_CHARACTER_PROPERTY_BIT_EXTENDED_PROPERTY 0x80 /* Characteristic has extended properties */ + +/* Attribute permissions */ +#define OHOS_GATT_PERMISSION_READ 0x01 /* read permission */ +#define OHOS_GATT_PERMISSION_READ_ENCRYPTED 0x02 /* Allow encrypted read operations */ +#define OHOS_GATT_PERMISSION_READ_ENCRYPTED_MITM 0x04 /* Allow reading with man-in-the-middle protection */ +#define OHOS_GATT_PERMISSION_WRITE 0x10 /* write permission */ +#define OHOS_GATT_PERMISSION_WRITE_ENCRYPTED 0x20 /* Allow encrypted writes */ +#define OHOS_GATT_PERMISSION_WRITE_ENCRYPTED_MITM 0x40 /* Allow encrypted writes with man-in-the-middle protection */ +#define OHOS_GATT_PERMISSION_WRITE_SIGNED 0x80 /* Allow signed write operations */ +/* Allow signed write operations with man-in-the-middle protection */ +#define OHOS_GATT_PERMISSION_WRITE_SIGNED_MITM = 0x100 + +typedef enum { + OHOS_BT_TRANSPORT_INVALID = 0x00, + OHOS_BT_TRANSPORT_BR_EDR = 0x01, + OHOS_BT_TRANSPORT_LE = 0x02 +} BtTransportId; + +typedef enum { + OHOS_BT_STATUS_SUCCESS, + OHOS_BT_STATUS_FAIL, + OHOS_BT_STATUS_NOT_READY, + OHOS_BT_STATUS_NOMEM, + OHOS_BT_STATUS_BUSY, + OHOS_BT_STATUS_DONE, + OHOS_BT_STATUS_UNSUPPORTED, + OHOS_BT_STATUS_PARM_INVALID, + OHOS_BT_STATUS_UNHANDLED, + OHOS_BT_STATUS_AUTH_FAILURE, + OHOS_BT_STATUS_RMT_DEV_DOWN, + OHOS_BT_STATUS_AUTH_REJECTED +} BtStatus; + +/* Error Code, BLUETOOTH CORE SPECIFICATION Version 5.2 | Vol 3, Part F, table 3.4 */ +typedef enum { + OHOS_GATT_SUCCESS = 0x00, + OHOS_GATT_INVALID_HANDLE = 0x01, + OHOS_GATT_READ_NOT_PERMITTED = 0x02, + OHOS_GATT_WRITE_NOT_PERMITTED = 0x03, + OHOS_GATT_INVALID_PDU = 0x04, + OHOS_GATT_INSUFFICIENT_AUTHENTICATION = 0x05, + OHOS_GATT_REQUEST_NOT_SUPPORTED = 0x06, + OHOS_GATT_INVALID_OFFSET = 0x07, + OHOS_GATT_INSUFFICIENT_AUTHORIZATION = 0x08, + OHOS_GATT_PREPARE_QUEUE_FULL = 0x09, + OHOS_GATT_ATTRIBUTE_NOT_FOUND = 0x0A, + OHOS_GATT_ATTRIBUTE_NOT_LONG = 0x0B, + OHOS_GATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE = 0x0C, + OHOS_GATT_INVALID_ATTRIBUTE_VALUE_LENGTH = 0x0D, + OHOS_GATT_UNLIKELY_ERROR = 0x0E, + OHOS_GATT_INSUFFICIENT_ENCRYPTION = 0x0F, + OHOS_GATT_UNSUPPORTED_GROUP_TYPE = 0x10, + OHOS_GATT_INSUFFICIENT_RESOURCES = 0x11, + OHOS_GATT_DATABASE_OUT_OF_SYNC = 0x12, + OHOS_GATT_VALUE_NOT_ALLOWED = 0x13, +} GattStatus; + +typedef enum { + OHOS_BLE_ATTRIB_TYPE_SERVICE = 0x00, + OHOS_BLE_ATTRIB_TYPE_CHAR, + OHOS_BLE_ATTRIB_TYPE_CHAR_VALUE, + OHOS_BLE_ATTRIB_TYPE_CHAR_CLIENT_CONFIG, + OHOS_BLE_ATTRIB_TYPE_CHAR_USER_DESCR, +} BleAttribType; + +typedef enum { + OHOS_UUID_TYPE_NULL = 0x00, + OHOS_UUID_TYPE_16_BIT, + OHOS_UUID_TYPE_32_BIT, + OHOS_UUID_TYPE_128_BIT, +} UuidType; + +typedef enum { + OHOS_GATT_AUTH_REQ_NONE = 0x00, + OHOS_GATT_AUTH_REQ_NO_MITM = 0x01, /* unauthenticated encryption */ + OHOS_GATT_AUTH_REQ_MITM = 0x02, /* authenticated encryption */ + OHOS_GATT_AUTH_REQ_SIGNED_NO_MITM = 0x03, + OHOS_GATT_AUTH_REQ_SIGNED_MITM = 0x04 +} BtGattAuthReq; + +typedef enum { + OHOS_GATT_WRITE_NO_RSP = 0x01, /* Write only. "Write Command" */ + OHOS_GATT_WRITE_DEFAULT = 0x02, /* Write and need response from remote device. "Write Request" */ + OHOS_GATT_WRITE_PREPARE = 0x03, /* Request the server to prepare to write the value. "Prepare Write" */ + OHOS_GATT_WRITE_SIGNED = 0x04 /* Write including authentication signature. "Signed Write Command" */ +} BtGattWriteType; + +/* Device address */ +typedef struct { + unsigned char addr[OHOS_BD_ADDR_LEN]; +} BdAddr; + +/* uuid with len */ +typedef struct { + unsigned char uuidLen; + char *uuid; +} BtUuid; +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt.h new file mode 100644 index 00000000..7822898e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt.h @@ -0,0 +1,458 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * Description: GATT interfaces + */ + +#ifndef OHOS_BT_GATT_H +#define OHOS_BT_GATT_H + +#include "ohos_bt_def.h" + +/* e.g. Legacy SCAN_RSP to an ADV_IND, 0x1B + OHOS_BLE_EVT_TYPE_LEGACY_ADV | OHOS_BLE_EVT_TYPE_SCAN_RESPONSE | OHOS_BLE_EVT_TYPE_SCANNABLE_ADV | */ + +#define OHOS_BLE_EVT_TYPE_CONNECTABLE_ADV 0x01 /* bit[0] */ +#define OHOS_BLE_EVT_TYPE_SCANNABLE_ADV 0x02 /* bit[1] */ +#define OHOS_BLE_EVT_TYPE_DIRECTED_ADV 0x04 /* bit[2] */ +#define OHOS_BLE_EVT_TYPE_SCAN_RESPONSE 0x08 /* bit[3] */ +#define OHOS_BLE_EVT_TYPE_LEGACY_ADV 0x10 /* bit[4] */ +#define OHOS_BLE_EVT_TYPE_DATA_STATUS_COMPLETE 0x00 /* bit[6:5] , 0b00:Complete */ +#define OHOS_BLE_EVT_TYPE_DATA_STATUS_INCOMPLETE 0x20 /* bit[6:5], 0b01:Incomplete, more data to come */ +/* bit[6:5], 0b10:Incomplete,data truncated, no more to come */ +#define OHOS_BLE_EVT_TYPE_DATA_STATUS_INCOMPLETE_TRUNCATED 0x40 + +typedef enum { + OHOS_BLE_ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY = 0x00, + OHOS_BLE_ADV_FILTER_ALLOW_SCAN_WLST_CON_ANY = 0x01, + OHOS_BLE_ADV_FILTER_ALLOW_SCAN_ANY_CON_WLST = 0x02, + OHOS_BLE_ADV_FILTER_ALLOW_SCAN_WLST_CON_WLST = 0x03, +} BleAdvFilter; + +/* BLUETOOTH CORE SPECIFICATION Version 5.2|Vol4,Part E, "HCI_LE_Set_Advertising_Parameters" */ +typedef enum { + OHOS_BLE_ADV_IND = 0x00, /* Connectable and scannable undirected advertising (default) */ + OHOS_BLE_ADV_DIRECT_IND_HIGH = 0x01, /* Connectable high duty cycle directed advertising */ + OHOS_BLE_ADV_SCAN_IND = 0x02, /* Scannable undirected advertising */ + OHOS_BLE_ADV_NONCONN_IND = 0x03, /* Non connectable undirected advertising */ + OHOS_BLE_ADV_DIRECT_IND_LOW = 0x04, /* Connectable low duty cycle directed advertising */ +} BleAdvType; + +/* Local IO capability, shall be the same value defined in HCI Specification. */ +typedef enum { + OHOS_BLE_IO_CAP_OUT = 0x00, /* DisplayOnly */ + OHOS_BLE_IO_CAP_IO, /* DisplayYesNo */ + OHOS_BLE_IO_CAP_IN, /* KeyboardOnly */ + OHOS_BLE_IO_CAP_NONE, /* NoInputNoOutput */ + OHOS_BLE_IO_CAP_KBDISP, /* Keyboard display */ +} BleIoCapMode; + +typedef enum { + OHOS_BLE_AUTH_NO_BOND = 0x00, + OHOS_BLE_AUTH_BOND, + OHOS_BLE_AUTH_REQ_MITM, + OHOS_BLE_AUTH_REQ_SC_ONLY, + OHOS_BLE_AUTH_REQ_SC_BOND, + OHOS_BLE_AUTH_REQ_SC_MITM, + OHOS_BLE_AUTH_REQ_SC_MITM_BOND +} BleAuthReqMode; + +typedef enum { + OHOS_BLE_FILTER_ACTION_ADD = 0x00, + OHOS_BLE_FILTER_ACTION_DELETE, + OHOS_BLE_FILTER_ACTION_CLEAR +} BleFilterActionType; + +typedef enum { + OHOS_BLE_ADV_ADDRESS_FILTER_MASK = 0x01, + OHOS_BLE_SERVICE_DATA_CHANGE_FILTER_MASK = 0x02, + OHOS_BLE_SERVICE_UUID_CHECK_MASK = 0x04, + OHOS_BLE_SERVICE_SOLICITATION_UUID_CHECK_MASK = 0x08, + OHOS_BLE_LOCAL_NAME_CHECK_MASK = 0x10, + OHOS_BLE_MANUFACTURER_DATA_CHECK_MASK = 0x20, + OHOS_BLE_SERVICE_DATA_CHECK_MASK = 0x40 +} BleFilterSelectMask; + +typedef enum { + OHOS_BLE_FILTER_LOGIC_OR = 0x00, + OHOS_BLE_FILTER_LOGIC_AND +} BleFilterLogicType; + +typedef enum { + OHOS_BLE_FILTER_IMMEDIATE_MODE = 0x00, + OHOS_BLE_FILTER_ON_FOUND_MODE, + OHOS_BLE_FILTER_BATCHED_MODE +} BleFilterDeliveryMode; + +typedef enum { + OHOS_BLE_ADV_ADDRESS_FILTER = 0x00, + OHOS_BLE_SERVICE_DATA_CHANGE_FILTER, + OHOS_BLE_SERVICE_UUID_CHECK_FILTER, + OHOS_BLE_SERVICE_SOLICITATION_UUID_CHECK_FILTER, + OHOS_BLE_LOCAL_NAME_CHECK_FILTER, + OHOS_BLE_MANUFACTURER_DATA_CHECK_FILTER, + OHOS_BLE_SERVICE_DATA_CHECK_FILTER +} BleFilterSelectType; + +typedef enum { + OHOS_BLE_FILTER_PUBLIC_ADDR = 0x00, + OHOS_BLE_FILTER_RANDOM_ADDR +} BleFilterAddrType; + +/* Ble scan type */ +typedef enum { + OHOS_BLE_SCAN_TYPE_PASSIVE = 0x00, /* Passive Scanning. No scan request PDUs shall be sent. */ + OHOS_BLE_SCAN_TYPE_ACTIVE, /* Active Scanning. Scan request PDUs may be sent. */ +} BleScanType; + +/* Scan filter policy, possible values of BleScanParams::scanFilterPolicy + 0-Accept all advertisement packets except directed advertising packets not addressed to this device (default); + 1-Accept only advertisement packets from devices where the advertiser's address is in the White list. + Directed advertising packets which are not addressed for this device shall be ignored; + 2-Accept all undirected advertisement packets, and all directed advertising packets where the initiator address + is a resolvable private address, and all directed advertising packets addressed to this device; + 3-Accept all undirected advertisement packets from devices where the advertiser's address is in the White list, + and all directed advertising packets where the initiator address is a resolvable private address, and all + directed advertising packets addressed to this device. */ +typedef enum { + OHOS_BLE_SCAN_FILTER_POLICY_ACCEPT_ALL = 0x00, + OHOS_BLE_SCAN_FILTER_POLICY_ONLY_WHITE_LIST, + OHOS_BLE_SCAN_FILTER_POLICY_ACCEPT_ALL_AND_RPA, + OHOS_BLE_SCAN_FILTER_POLICY_ONLY_WHITE_LIST_AND_RPA +} BleScanFilterPolicy; + +/* Extended Advertising Event Type, possible values of BtScanResultData::eventType */ +typedef enum { + OHOS_BLE_EVT_NON_CONNECTABLE_NON_SCANNABLE = 0x00, /* Extended Non-Connectable and Non-Scannable undirected */ + OHOS_BLE_EVT_NON_CONNECTABLE_NON_SCANNABLE_DIRECTED = 0x04, /* Extended NonConnectable and NonScannable directed */ + OHOS_BLE_EVT_CONNECTABLE = 0x01, /* Extended Connectable undirected */ + OHOS_BLE_EVT_CONNECTABLE_DIRECTED = 0x05, /* Extended Connectable directed */ + OHOS_BLE_EVT_SCANNABLE = 0x02, /* Extended Scannable undirected */ + OHOS_BLE_EVT_SCANNABLE_DIRECTED = 0x06, /* Extended Scannable directed */ + + OHOS_BLE_EVT_LEGACY_NON_CONNECTABLE = 0x10, /* Legacy Non-Connectable undirected, ADV_NONCONN_IND */ + OHOS_BLE_EVT_LEGACY_SCANNABLE = 0x12, /* Legacy Scannable undirected, ADV_SCAN_IND */ + OHOS_BLE_EVT_LEGACY_CONNECTABLE = 0x13, /* Legacy Connectable & Scannable undirected, ADV_IND */ + OHOS_BLE_EVT_LEGACY_CONNECTABLE_DIRECTED = 0x15, /* Legacy Connectable directed, ADV_DIRECT_IND */ + OHOS_BLE_EVT_LEGACY_SCAN_RSP_TO_ADV_SCAN = 0x1A, /* Legacy SCAN_RSP to an ADV_SCAN_IND */ + OHOS_BLE_EVT_LEGACY_SCAN_RSP_TO_ADV = 0x1B, /* Legacy SCAN_RSP to an ADV_IND */ +} BleScanResultEvtType; + +/* Extended Advertising Data Status, possible values of BtScanResultData::dataStatus */ +typedef enum { + OHOS_BLE_DATA_COMPLETE = 0x00, /* Complete data or final trunck */ + OHOS_BLE_DATA_INCOMPLETE_MORE_TO_COME = 0x01, /* Incomplete data, more data to come */ + OHOS_BLE_DATA_INCOMPLETE_TRUNCATED = 0x02, /* Incomplete data, truncated, no more data to come */ +} BleScanResultDataStatus; + +/* Addr type of scan result, possible values of BtScanResultData::addrType */ +typedef enum { + OHOS_BLE_PUBLIC_DEVICE_ADDRESS = 0x00, /* Public Device Address */ + OHOS_BLE_RANDOM_DEVICE_ADDRESS = 0x01, /* Random Device Address */ + OHOS_BLE_PUBLIC_IDENTITY_ADDRESS = 0x02, /* Public Identity Address (corresponds to Resolved Private Address) */ + /* Random (static) Identity Address (corresponds to Resolved Private Address) */ + OHOS_BLE_RANDOM_STATIC_IDENTITY_ADDRESS = 0x03, + OHOS_BLE_UNRESOLVABLE_RANDOM_DEVICE_ADDRESS = 0xFE, + OHOS_BLE_NO_ADDRESS = 0xFF, /* No address provided (anonymous advertisement) */ +} BleScanResultAddrType; + +/* adv data */ +typedef struct { + unsigned short advLength; + char *advData; /* advertising data */ + unsigned short scanRspLength; + char *scanRspData; /* scan response data */ +} BleConfigAdvData; + +typedef struct { + /* Minimum advertising interval for undirected and low duty cycle directed advertising. [N * 0.625ms] */ + int minInterval; + /* Maximum advertising interval for undirected and low duty cycle directed advertising. [N * 0.625ms] */ + int maxInterval; + BleAdvType advType; + unsigned char ownAddrType; /* Ref. Core spec Version 5.2|Vol 4,Part E, HCI_LE_Set_Advertising_Parameters */ + unsigned char peerAddrType; /* Ref. Core spec Version 5.2|Vol 4,Part E, HCI_LE_Set_Advertising_Parameters */ + BdAddr peerAddr; + int channelMap; /* channel used bit map, bit[0:2]->[37,38,39]. e.g. 0x01-only 37 used, 0x07-all used */ + BleAdvFilter advFilterPolicy; + int txPower; /* dbm */ + int duration; /* duration for sending BLE ADV. [N * 10 ms] */ +} BleAdvParams; + +/* used to add or delete a filter specification or clear a filter list for onchip filtering */ +typedef struct { + unsigned char clientId; /* APP identifier */ + unsigned char action; /* BleFilterActionType, [0->add,1->delte,2->clear] */ + unsigned char filtIndex; /* Filter index 0 ~ max_filter */ + unsigned int featureSelection; /* BleFilterSelectMask, Bit masks for the selected features */ + unsigned int listLogicType; /* BleFilterLogicType, Logic operation for each feature selected in featureSelection */ + unsigned char filtLogicType; /* BleFilterLogicType */ + unsigned char rssiHighThres; /* [In dBm] ignore the advertiser if the signal is lower than rssiHighThres */ + unsigned char rssiLowThres; /* Valid only if delivery_mode is on_found [in dBm] */ + unsigned char deliveryMode; /* BleFilterDeliveryMode */ + /* Time for firmware to linger and collect additional advertisements before reporting. + (Valid only if deliveryMode is on_found)[in milliseconds] */ + unsigned int onFoundTimeout; + /* If an advertisement, after being found, is not seen contiguously for the lost_timeout period, + it will be reported lost. (Valid only if deliveryMode is on_found)[in milliseconds] */ + unsigned int onLostTimeout; + /* If an advertisement in onFound lingers in firmware for the onfound_timeout duration, + it will collect a few advertisements and the count is checked. If the count exceeds onFoundTimeoutCnt, + it's reported OnFound, immediately thereafter. Valid only if deliveryMode is on_found [count] */ + unsigned char onFoundTimeoutCnt; + /* Total number of advertisers to track per filter. Valid only if delivery_mode is on_found [count] */ + unsigned int numOfTrackingEntries; +} BleAdvScanFilterParam; + +typedef struct { + unsigned char clientId; /* APP identifier */ + unsigned char action; /* BleFilterActionType, [0->add, 1->delte, 2->clear] */ + unsigned char filtType; /* BleFilterSelectType */ + unsigned char filtIndex; /* filter index */ + int manufacturerId; /* manufacturer id */ + int manufacturerIdMask; /* the mask of manufacturer id */ + BtUuid *uuid; /* uuid, 128bit */ + BtUuid *uuidMask; /* mask of 128bit uuid */ + BdAddr *bdAddr; /* address, e.g. "AA:BB:CC:DD:EE:FF" */ + unsigned char addrType; /* BleFilterAddrType, [0->public, 1->random] */ + unsigned int dataLen; /* length of value */ + char *data; /* value */ + unsigned int maskLen; /* length of mask */ + char mask; /* mask */ +} BleAdvScanFilterCondition; + +/* BLE scan parameter */ +typedef struct { + /* Time interval from when the Controller started its last scan until it begins the subsequent scan. + [N=0xXX] Time = N * 0.625 ms */ + unsigned short scanInterval; + /* Duration of the scan on the primary advertising physical channel. [N=0xXX] Time = N * 0.625 ms */ + unsigned short scanWindow; + unsigned char scanType; /* one of BleScanType, [0->Passive, 1->Active] */ + unsigned char scanPhy; /* [0->LE 1M phy, 1->LE 2M phy, 2->LE Coded phy] */ + unsigned char scanFilterPolicy; /* one of BleScanFilterPolicy */ +} BleScanParams; + +typedef struct { + unsigned char *advData; + unsigned int advDataLen; + unsigned char *rspData; + unsigned int rspDataLen; +} StartAdvRawData; + +typedef struct { + unsigned char eventType; /* Advertising event type, one of BleScanResultEvtType */ + unsigned char dataStatus; /* Data status, one of BleScanResultDataStatus */ + unsigned char addrType; /* one of BleScanResultAddrType, except 0xFE */ + BdAddr addr; + unsigned char primaryPhy; /* 0x01->LE 1M phy, 0x03->LE Coded phy */ + unsigned char secondaryPhy; /* 0x00->No packets, 0x01->LE 1M phy, 0x02->LE 2M phy, 0x03->LE Coded phy */ + /* Value of the Advertising SID subfield in the ADI field of the PDU or, for scan responses, + in the ADI field of the original scannable advertisement, 0xFF->No ADI field provided */ + unsigned char advSid; + char txPower; /* Range: -127 to +20dBm, 0x7F->Tx Power information not available */ + char rssi; /* Range: -127 to +20dBm, 0x7F->RSSI is not available */ + /* Interval of the periodic advertising, Time = N * 1.25 ms, 0x0000->No periodic advertising */ + unsigned short periodicAdvInterval; + unsigned char directAddrType; /* one of BleScanResultAddrType, except 0xFF */ + BdAddr directAddr; /* TargetA address for directed advertising event only */ + unsigned char advLen; + unsigned char *advData; +} BtScanResultData; + +/* Callback invoked when start adv operation has completed */ +typedef void (*AdvEnableCallback)(int advId, int status); + +/* Callback invoked when stop adv operation has completed */ +typedef void (*AdvDisableCallback)(int advId, int status); + +/* Callback invoked when adv instance data set operation has completed */ +typedef void (*AdvDataCallback)(int advId, int status); + +/* Callback invoked when adv param update operation has completed */ +typedef void (*AdvUpdateCallback)(int advId, int status); + +/* Callback invoked when security response operation has completed */ +typedef void (*SecurityRespondCallback)(const BdAddr *bdAddr); + +/* Callback for scan results */ +typedef void (*ScanResultCallback)(BtScanResultData *scanResultdata); + +/* Callback invoked when a scan filter enable/disable has completed */ +typedef void (*ScanFilterStatusCallback)(int enable, int clientId, int status); + +/* Callback invoked when a scan filter configuration command has completed */ +typedef void (*ScanFilterCfgCallback)(int action, int clientId, int status, int filtType, int avblSpace); + +/* Callback invoked when a scan filter param setup has completed */ +typedef void (*ScanFilterParamCallback)(int action, int clientId, int status, int avblSpace); + +/* Callback invoked when scan parameter set has completed */ +typedef void (*ScanParameterSetCompletedCallback)(int clientId, int status); + +typedef struct { + AdvEnableCallback advEnableCb; /* start adv */ + AdvDisableCallback advDisableCb; /* stop adv */ + AdvDataCallback advDataCb; + AdvUpdateCallback advUpdateCb; /* update adv */ + SecurityRespondCallback securityRespondCb; + ScanResultCallback scanResultCb; + ScanFilterCfgCallback scanFilterCfgCb; + ScanFilterParamCallback scanFilterParamCb; + ScanFilterStatusCallback scanFilterStatusCb; + ScanParameterSetCompletedCallback scanParamSetCb; +} BtGattCallbacks; + +/* + * @brief Initialize the Bluetooth protocol stack + * @param[in] void + * @return 0-success, other-fail + */ +int InitBtStack(void); + +/* + * @brief Bluetooth protocol stack enable + * @param[in] void + * @return 0-success, other-fail + */ +int EnableBtStack(void); + +/* + * @brief Bluetooth protocol stack disable + * @param[in] void + * @return 0-success, other-fail + */ +int DisableBtStack(void); + +/* + * @brief set this device's name for friendly + * @param[in] device name + * @param[in] length + * @return 0-success, other-fail + */ +int SetDeviceName(const char *name, unsigned int len); + +/* + * @brief set advertising data + * @param[in] specified by upper layer + * @param[in] adv data or scan response + * @return 0-success, other-fail + */ +int BleSetAdvData(int advId, const BleConfigAdvData *data); + +/* + * @brief start ble advertising + * @param[in] specified by upper layer + * @param[in] ble advertising param list + * @return 0-success, other-fail + */ +int BleStartAdv(int advId, const BleAdvParams *param); + +/* + * @brief stop ble advertising + * @param[in] specified by upper layer + * @return 0-success, other-fail + */ +int BleStopAdv(int advId); + +/* + * @Update the parameters as per spec, user manual specified values and restart multi ADV + * @param[in] specified by upper layer + * @param[in] ble advertising param list + * @return 0-success, other-fail + */ +int BleUpdateAdv(int advId, const BleAdvParams *param); + +/* + * @brief set security IO capability + * @param[in] BleIoCapMode + * @return 0-success, other-fail + */ +int BleSetSecurityIoCap(BleIoCapMode mode); + +/* + * @brief set security authority + * @param[in] BleAuthReqMode + * @return 0-success, other-fail + */ +int BleSetSecurityAuthReq(BleAuthReqMode mode); + +/* + * @brief The device accept or reject the connection initiator. + * @param[in] initiator's address + * @param[in] 0-reject, 1-accept + * @return 0-success, other-fail + */ +int BleGattSecurityRsp(BdAddr bdAddr, bool accept); + +/* + * @brief read bt mac address + * @param[in] mac addr + * @param[in] addr length + * @return 0-success, other-fail + */ +int ReadBtMacAddr(unsigned char *mac, unsigned int len); + +/* + * @brief Setup scan filter params + * @param[in] BleAdvScanFilterParam + * @return 0-success, other-fail + */ +int BleScanFilterParamSetup(BleAdvScanFilterParam *param); + +/* + * @brief Configure a scan filter condition + * @param[in] BleAdvScanFilterCondition + * @return 0-success, other-fail + */ +int BleScanFilterAddRemove(BleAdvScanFilterCondition *param); + +/* + * @brief Clear all scan filter conditions for specific filter index + * @param[in] client Id + * @param[in] filter index + * @return 0-success, other-fail + */ +int BleScanFilterClear(int clientId, int filterIndex); + +/* + * @brief Enable / disable scan filter feature + * @param[in] client Id + * @param[in] 0-disable, 1-enable + * @return 0-success, other-fail + */ +int BleScanFilterEnable(int clientId, bool enable); + +/* + * @brief Set BLE scan parameters + * @param[in] client Id + * @param[in] BleScanParams, include scanInterval,scanWindow and so on. + * @return 0-success, other-fail + */ +int BleSetScanParameters(int clientId, BleScanParams *param); + +/* + * @brief Start Ble scan + * @return 0-success, other-fail + */ +int BleStartScan(void); + +/* + * @brief Stop Ble scan + * @return 0-success, other-fail + */ +int BleStopScan(void); + +/* + * @brief Callback invoked for gatt common function + * @param[in] Callback funcs + * @return 0-success, other-fail + */ +int BleGattRegisterCallbacks(BtGattCallbacks *func); + +/* + * @brief Start advertising include set adv data. + * This API will not described in the development manual, only for Hilink. + * @return 0-success, other-fail + */ +int BleStartAdvEx(int *advId, const StartAdvRawData rawData, BleAdvParams advParam); +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt_client.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt_client.h new file mode 100644 index 00000000..49e211a9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt_client.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * Description: GATT client interfaces + */ + +#ifndef OHOS_BT_GATT_CLIENT_H +#define OHOS_BT_GATT_CLIENT_H + +#include "ohos_bt_def.h" + +/* Refer to the definition of "HCI_LE_Connection_Update" in core 5.2|Vol 4,Part E */ +typedef struct { + int connIntervalMin; /* Minimum value for the connection interval. [N * 1.25ms] */ + int connIntervalMax; /* Maximum value for the connection interval. [N * 1.25ms] */ + int connLatency; /* Slave latency for the connection in number of connection events. [Range: 0x0000 to 0x01F3] */ + int supervisionTimeout; /* Supervision timeout for the LE Link. [N * 10 ms] */ + int minConnectionEventLen; /* The minimum length of connection event needed for LE connection. [N * 0.625ms] */ + int maxConnectionEventLen; /* [N * 0.625ms] */ +} BtGattcConnPara; + +/* notification/indication data */ +typedef struct { + unsigned short handle; + unsigned char isNotify; /* 1: notification, 0: indication */ + unsigned short dataLen; + unsigned char *data; +} BtGattNotifyData; + +/* Parameters for GATT read operations */ +typedef struct { + unsigned short handle; + unsigned short dataLen; + unsigned char *data; +} BtGattReadData; + +/* Callback invoked in response to BleGattcRegister */ +typedef void (*RegisterClientCallback)(int status, int clientId, const BtUuid *appUuid); + +/* Callback invoked in response to BleGattcConnect */ +typedef void (*ConnectClientCallback)(int connId, int status, int clientId, const BdAddr *bdAddr); + +/* Callback invoked in response to BleGattcDisconnect */ +typedef void (*DisconnectClientCallback)(int connId, int status, int clientId, const BdAddr *bdAddr); + +/* Callback invoked when the connection parameters for a given connection changed */ +typedef void (*ConnectParaUpdateCallback)(int connId, int interval, int latency, int timeout, int status); + +/* Invoked in response to BleGattcSearchServices when the GATT service discovery has been completed */ +typedef void (*SearchServiceCompleteCallback)(int connId, int status); + +/* Reports result of a GATT read operation */ +typedef void (*ReadCharacteristicCallback)(int connId, int status, BtGattReadData *readData); + +/* GATT write characteristic operation callback */ +typedef void (*WriteCharacteristicCallback)(int connId, int status, unsigned short handle); + +/* Callback invoked in response to BleGattcReadDescriptor */ +typedef void (*ReadDescriptorCallback)(int connId, int status, BtGattReadData *readData); + +/* Callback invoked in response to BleGattcWriteDescriptor */ +typedef void (*WriteDescriptorCallback)(int connId, int status, unsigned short handle); + +/* GATT execute prepared write callback */ +typedef void (*ExecuteWriteCallback)(int connId, int status); + +/* Callback invoked when the MTU size for a given connection changes */ +typedef void (*ConfigureMtuSizeCallback)(int connId, int status, int mtuSize); + +/* Callback invoked in response to BleGattcReadRemoteRssi */ +typedef void (*ReadRemoteRssiCallback)(int clientId, const BdAddr *bdAddr, int rssi, int status); + +/* Callback invoked in response to BleGattcRegisterNotifications, register/deregister */ +typedef void (*RegisterNotificationCallback)(int connId, int registered, int status, unsigned short handle); + +/* Callback invoked when a remote device sends a notification/indication that a client has registered for */ +typedef void (*NotificationCallback)(int connId, BtGattNotifyData notifyData); + +typedef struct { + RegisterClientCallback registerClientCb; + ConnectClientCallback connectClientCb; + DisconnectClientCallback disconnectCb; + ConnectParaUpdateCallback connectParaUpdateCb; + SearchServiceCompleteCallback searchServiceCompleteCb; + ReadCharacteristicCallback readCharacteristicCb; + WriteCharacteristicCallback writeCharacteristicCb; + ReadDescriptorCallback readDescriptorCb; + WriteDescriptorCallback writeDescriptorCb; + ExecuteWriteCallback executeWriteCb; + ConfigureMtuSizeCallback configureMtuSizeCb; + ReadRemoteRssiCallback readRemoteRssiCb; + RegisterNotificationCallback registerNotificationCb; + NotificationCallback notificationCb; +} BtGattClientCallbacks; + +/* + * @brief gatt client register, callback return clientId + * @param[in] specified by upper layer + * @return 0-success, other-fail + */ +int BleGattcRegister(BtUuid appUuid); + +/* + * @brief gatt client deregister + * @param[in] client Id + * @return 0-success, other-fail + */ +int BleGattcUnRegister(int clientId); + +/* + * @brief Create a connection to a remote LE or dual-mode device + * @param[in] client Id + * @param[in] remote address + * @param[in] is a direct connection or a background auto connection + * @param[in] BtTransportId + * @return 0-success, other-fail + */ +int BleGattcConnect(int clientId, const BdAddr *bdAddr, bool isDirect, int transport); + +/* + * @brief Disconnect a remote device or cancel a pending connection + * @param[in] client Id + * @param[in] remote address + * @param[in] connection index. + * @return 0-success, other-fail + */ +int BleGattcDisconnect(int clientId, const BdAddr *bdAddr, int connId); + +/* + * @brief Send a connection parameter update request to the remote device. + * @param[in] remote address + * @param[in] connection param refer to "HCI_LE_Connection_Update". + * @return 0-success, other-fail + */ +int BleGattcConnectParaUpdate(const BdAddr *bdAddr, BtGattcConnPara connPara); + +/* + * @brief This function is called to request a GATT service discovery on a GATT server. + Optionally, the results can be filtered for a given UUID. + * @param[in] remote address + * @param[in] a UUID of the service application is interested in. If Null, discover for all services + * @return 0-success, other-fail + */ +int BleGattcSearchServices(int connId, BtUuid filterUuid); + +/* + * @brief This function is called to read a characteristics value from the server. + * @param[in] connection ID + * @param[in] characteritic handle to read + * @return 0-success, other-fail + */ +int BleGattcReadCharacteristic(int connId, int handle); + +/* + * @brief This function is called to write a characteristics value to the server. + * @param[in] connection ID + * @param[in] characteritic handle to read + * @param[in] BtGattWriteType, default: write need rsp + * @param[in] the data length + * @param[in] the data to be writen + * @return 0-success, other-fail + */ +int BleGattcWriteCharacteristic(int connId, int handle, int writeType, int len, char *value); + +/* + * @brief This function is called to read a characteristics value from the server. + * @param[in] connection ID + * @param[in] descriptor handle to read + * @return 0-success, other-fail + */ +int BleGattcReadDescriptor(int connId, int handle); + +/* + * @brief This function is called to write a descriptor value to the server. + * @param[in] connection ID + * @param[in] descriptor handle to read + * @param[in] BtGattWriteType, default: write need rsp + * @param[in] the data length + * @param[in] the data to be writen + * @return 0-success, other-fail + */ +int BleGattcWriteDescriptor(int connId, int handle, int writeType, int len, char *value); + +/* + * @brief This function is called to send an execute write request to the server(or cancel the prepare write). + * @param[in] connection ID + * @param[in] [1-execute, 0-cancel], to execute or cancel the prepare write request(s). + * @return 0-success, other-fail + */ +int BleGattcExecuteWrite(int connId, int execute); + +/* + * @brief This function is called to configure the ATT MTU size for a connection on an LE transport. + * @param[in] connection ID + * @param[in] attribute MTU size. + * @return 0-success, other-fail + */ +int BleGattcConfigureMtuSize(int connId, int mtuSize); + +/* + * @brief Read the RSSI for a connected remote device. + * @param[in] client Id + * @param[in] remote address + * @return 0-success, other-fail + */ +int BleGattcReadRemoteRssi(int clientId, const BdAddr *bdAddr); + +/* + * @brief Enable or disable notifications/indications for a given characteristic. + * @param[in] client Id + * @param[in] remote address + * @param[in] characteristic handle + * @param[in] 1-register, 0-deregister + * @return 0-success, other-fail + */ +int BleGattcRegisterNotifications(int clientId, const BdAddr *bdAddr, int handle, int enable); + +/* + * @brief Callback invoked for gatt client function + * @param[in] Callback funcs + * @return 0-success, other-fail + */ +int BleGattcRegisterCallbacks(BtGattClientCallbacks *func); +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt_server.h b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt_server.h new file mode 100644 index 00000000..60522990 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_harmony_adapter/ohos_bt_gatt_server.h @@ -0,0 +1,281 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * Description: GATT server interfaces + */ + +#ifndef OHOS_BT_GATT_SERVER_H +#define OHOS_BT_GATT_SERVER_H + +#include "ohos_bt_def.h" + +typedef enum { + OHOS_BLE_SEC_NONE = 0x00, + OHOS_BLE_SEC_ENCRYPT, + OHOS_BLE_SEC_ENCRYPT_NO_MITM, + OHOS_BLE_SEC_ENCRYPT_MITM +} BleSecAct; + +typedef struct { + int connectId; /* connection index */ + int status; /* read/write character status, GattStatus */ + int attrHandle; /* attribute handle */ + int valueLen; + char *value; /* response data from host */ +} GattsSendRspParam; + +typedef struct { + int connectId; /* connection index */ + int attrHandle; /* attribute handle */ + int confirm; /* true(indication)-the client shall respond a conformation, false(notification)-send a notification */ + int valueLen; /* response data from host */ + char *value; +} GattsSendIndParam; + +typedef struct { + int connId; /* connect index */ + int transId; /* BtTransportId */ + BdAddr *bdAddr; + int attrHandle; /* The handle of the attribute to be read */ + int offset; /* The offset of the first octet to be read */ + bool isLong; /* If isLong is true, then this request is part of a Long Read procedure */ +} BtReqReadCbPara; + +typedef struct { + int connId; /* connect index */ + int transId; /* BtTransportId */ + BdAddr *bdAddr; + int attrHandle; /* The handle of the attribute to be written */ + int offset; /* The offset of the first octet to be written */ + int length; + bool needRsp; /* if the remote device requires a response */ + bool isPrep; /* if this write operation should be queued for later execution */ + unsigned char *value; +} BtReqWriteCbPara; + +/* Callback invoked in response to register_server */ +typedef void (*RegisterServerCallback)(int status, int serverId, BtUuid *appUuid); + +/* Callback indicating that a remote device has connected */ +typedef void (*ConnectServerCallback)(int connId, int serverId, const BdAddr *bdAddr); + +/* Callback indicating that a remote device has disconnected */ +typedef void (*DisconnectServerCallback)(int connId, int serverId, const BdAddr *bdAddr); + +/* Callback invoked in response to add service */ +typedef void (*ServiceAddCallback)(int status, int serverId, BtUuid *uuid, int srvcHandle); + +/* Callback indicating that an included service has been added to a service */ +typedef void (*IncludeServiceAddCallback)(int status, int serverId, int srvcHandle, int includeSrvcHandle); + +/* Callback invoked when a characteristic has been added to a service */ +typedef void (*CharacteristicAddCallback)(int status, int serverId, BtUuid *uuid, + int srvcHandle, int characteristicHandle); + +/* Callback invoked when a descriptor has been added to a characteristic */ +typedef void (*DescriptorAddCallback)(int status, int serverId, BtUuid *uuid, + int srvcHandle, int descriptorHandle); + +/* Callback invoked in response to start_service */ +typedef void (*ServiceStartCallback)(int status, int serverId, int srvcHandle); + +/* Callback invoked in response to stop_service */ +typedef void (*ServiceStopCallback)(int status, int serverId, int srvcHandle); + +/* Callback triggered when a service has been deleted */ +typedef void (*ServiceDeleteCallback)(int status, int serverId, int srvcHandle); + +/* Callback invoked when a remote device has requested to read a characteristicor descriptor. + * The application must respond by calling send_response + */ +typedef void (*RequestReadCallback)(BtReqReadCbPara readCbPara); + +/* Callback invoked when a remote device has requested to write to a characteristic or descriptor. */ +typedef void (*RequestWriteCallback)(BtReqWriteCbPara writeCbPara); + +/* Callback triggered in response to send_response if the remote device sends a confirmation */ +typedef void (*ResponseConfirmationCallback)(int status, int handle); + +/* Callback confirming that a notification or indication has been sent to a remote device */ +typedef void (*IndicationSentCallback)(int connId, int status); + +/* Callback invoked when the MTU for a given connection changes */ +typedef void (*MtuChangeCallback)(int connId, int mtu); + +typedef struct { + RegisterServerCallback registerServerCb; + ConnectServerCallback connectServerCb; + DisconnectServerCallback disconnectServerCb; + ServiceAddCallback serviceAddCb; + IncludeServiceAddCallback includeServiceAddCb; + CharacteristicAddCallback characteristicAddCb; + DescriptorAddCallback descriptorAddCb; + ServiceStartCallback serviceStartCb; + ServiceStopCallback serviceStopCb; + ServiceDeleteCallback serviceDeleteCb; + RequestReadCallback requestReadCb; + RequestWriteCallback requestWriteCb; + ResponseConfirmationCallback responseConfirmationCb; + IndicationSentCallback indicationSentCb; + MtuChangeCallback mtuChangeCb; +} BtGattServerCallbacks; + +typedef int (*BleGattServiceRead)(unsigned char *buff, unsigned int *len); + +typedef int (*BleGattServiceWrite)(unsigned char *buff, unsigned int len); + +typedef int (*BleGattServiceIndicate)(unsigned char *buff, unsigned int len); + +typedef struct { + BleGattServiceRead read; + BleGattServiceWrite write; + BleGattServiceIndicate indicate; +} BleGattOperateFunc; + +typedef struct { + BleAttribType attrType; + unsigned int permission; /* e.g. (OHOS_GATT_PERMISSION_READ | OHOS_GATT_PERMISSION_WRITE) */ + UuidType uuidType; + unsigned char uuid[OHOS_BLE_UUID_MAX_LEN]; + unsigned char *value; + unsigned char valLen; + /* e.g. (OHOS_GATT_CHARACTER_PROPERTY_BIT_BROADCAST | OHOS_GATT_CHARACTER_PROPERTY_BIT_READ) */ + unsigned char properties; + BleGattOperateFunc func; +} BleGattAttr; + +typedef struct { + unsigned int attrNum; + BleGattAttr *attrList; +} BleGattService; + +/* + * @brief gatt server application register, callback return serverId + * @param[in] specified by upper layer + * @return 0-success, other-fail + */ +int BleGattsRegister(BtUuid appUuid); + +/* + * @brief gatt server deregister + * @param[in] server interface Id + * @return 0-success, other-fail + */ +int BleGattsUnRegister(int serverId); + +/* + * @brief Cancel connection with remote device + * @param[in] server interface id + * @param[in] remote address + * @param[in] connection index. + * @return 0-success, other-fail + */ +int BleGattsDisconnect(int serverId, BdAddr bdAddr, int connId); + +/* + * @brief add service + * @param[in] server interface id + * @param[in] service uuid and uuid length + * @param[in] is primary or secondary service. + * @param[in] service characther attribute number. + * @return 0-success, other-fail + */ +int BleGattsAddService(int serverId, BtUuid srvcUuid, bool isPrimary, int number); + +/* + * @brief add characteristic + * @param[in] server interface id + * @param[in] service handle + * @param[in] characteristic uuid and uuid length + * @param[in] e.g. (OHOS_GATT_CHARACTER_PROPERTY_BIT_BROADCAST | OHOS_GATT_CHARACTER_PROPERTY_BIT_READ) + * @param[in] e.g. (OHOS_GATT_PERMISSION_READ | OHOS_GATT_PERMISSION_WRITE) + * @return 0-success, other-fail + */ +int BleGattsAddCharacteristic(int serverId, int srvcHandle, BtUuid characUuid, + int properties, int permissions); + +/* + * @brief add descriptor + * @param[in] server interface id + * @param[in] service handle + * @param[in] descriptor uuid and uuid length + * @param[in] e.g. (OHOS_GATT_PERMISSION_READ | OHOS_GATT_PERMISSION_WRITE) + * @return 0-success, other-fail + */ +int BleGattsAddDescriptor(int serverId, int srvcHandle, BtUuid descUuid, int permissions); + +/* + * @brief start service + * @param[in] server interface id + * @param[in] service handle + * @return 0-success, other-fail + */ +int BleGattsStartService(int serverId, int srvcHandle); + +/* + * @brief start service + * @param[in] server interface id + * @param[in] service handle + * @return 0-success, other-fail + */ +int BleGattsStopService(int serverId, int srvcHandle); + +/* + * @brief remove a service from the list of provided services + * @param[in] server interface id + * @param[in] service handle + * @return 0-success, other-fail + */ +int BleGattsDeleteService(int serverId, int srvcHandle); + +/* + * @brief remove all services from the list of provided services + * @param[in] server interface id + * @return 0-success, other-fail + */ +int BleGattsClearServices(int serverId); + +/* + * @brief Send a response to a read or write request to a remote device. + * @param[in] server interface id + * @param[in] response param + * @return 0-success, other-fail + */ +int BleGattsSendResponse(int serverId, GattsSendRspParam *param); + +/* + * @brief Send a notification or indication that a local characteristic has been updated + * @param[in] server interface id + * @param[in] indication param + * @return 0-success, other-fail + */ +int BleGattsSendIndication(int serverId, GattsSendIndParam *param); + +/* + * @brief Set the encryption level of the data transmission channel during connection + * @param[in] remote address + * @param[in] BleSecAct + * @return 0-success, other-fail + */ +int BleGattsSetEncryption(BdAddr bdAddr, BleSecAct secAct); + +/* + * @brief Callback invoked for gatt server function + * @param[in] Callback funcs + * @return 0-success, other-fail + */ +int BleGattsRegisterCallbacks(BtGattServerCallbacks *func); + +/* + * @brief Start sevice include add service/characteristic/Descriptor option. + * This API will not described in the development manual, only for Hilink. + * @return 0-success, other-fail + */ +int BleGattsStartServiceEx(int *srvcHandle, BleGattService *srvcInfo); + +/* + * @brief Stop service. + * This API will not described in the development manual, only for Hilink. + * @return 0-success, other-fail + */ +int BleGattsStopServiceEx(int srvcHandle); +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_flags.h new file mode 100644 index 00000000..b63efb09 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_flags.h @@ -0,0 +1,31 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_JOYLINK_ADAPTER_APP_FLAGS_H_ +#define _BT_JOYLINK_ADAPTER_APP_FLAGS_H_ + +#include "bt_flags.h" + +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define BT_JOYLINK_ADAPTER_APP_MAX_LINKS 1 + +#define BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT 0 + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_main.c new file mode 100644 index 00000000..2c5c333b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_main.c @@ -0,0 +1,305 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include "platform_opts_bt.h" +#if defined(CONFIG_BT_JOYLINK_ADAPTER) && CONFIG_BT_JOYLINK_ADAPTER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bt_joylink_adapter_app_task.h" +#include "bt_joylink_adapter_peripheral_app.h" +#include "bt_joylink_adapter_app_flags.h" +#include "platform_stdlib.h" +#include "wifi_constants.h" +#include +#include "rtk_coex.h" +#include "os_timer.h" +#include +#include "joylink_sdk.h" +#include + + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 352 //220ms +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 384 //240ms + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = { + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; +uint8_t *adv_data = NULL; +uint8_t adv_data_len = 0; + +extern T_SERVER_ID joylink_service_id; +T_ATTRIB_APPL *joylink_service_table = NULL; +uint8_t CHAR_NUM = 6; +#if defined(BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT) && BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT +int connect_status; +#endif + + +/*============================================================================* + * Functions + *============================================================================*/ + +void bt_joylink_adapter_app_start_adv() +{ + jl_gap_data_t *gatt_data = (jl_gap_data_t *)os_mem_alloc(0,sizeof(jl_gap_data_t)); + jl_get_gap_config_data(gatt_data); + + uint8_t service_uuid_length = sizeof(gatt_data->service_uuid16); + uint8_t manufacture_data_length = sizeof(gatt_data->manufacture_data); + + uint8_t local_name[] = {'J','D'}; + uint8_t local_name_lengh = sizeof(local_name); + adv_data_len = 3 + + 2 + service_uuid_length + + 2 + local_name_lengh + + 2 + manufacture_data_length; + + adv_data = (uint8_t *)os_mem_alloc(0,adv_data_len); + uint8_t offset = 0; + //Flags + *(adv_data + offset) = 0x2; + *(adv_data + offset + 1) = GAP_ADTYPE_FLAGS; /* type="Flags" */; + *(adv_data + offset + 2) = GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED; + //service + offset += 3; + *(adv_data + offset) = service_uuid_length + 1; + *(adv_data + offset + 1) = GAP_ADTYPE_16BIT_COMPLETE; + memcpy(adv_data + offset + 2,gatt_data->service_uuid16,service_uuid_length); + offset += service_uuid_length + 2; + //local name + *(adv_data + offset) = local_name_lengh + 1; + *(adv_data + offset + 1) = GAP_ADTYPE_LOCAL_NAME_COMPLETE; + memcpy(adv_data + offset + 2,local_name,local_name_lengh); + offset += local_name_lengh + 2; + //manufacture data + *(adv_data + offset) = manufacture_data_length + 1; + *(adv_data + offset + 1) = GAP_ADTYPE_MANUFACTURER_SPECIFIC; + memcpy(adv_data + offset + 2,gatt_data->manufacture_data,manufacture_data_length); + + if(gatt_data != NULL) + os_mem_free(gatt_data); +} +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +//extern void gap_config_hci_task_secure_context(uint32_t size); +void bt_joylink_adapter_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_JOYLINK_ADAPTER_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_JOYLINK_ADAPTER_APP_MAX_LINKS); +} + +/** + * @brief Initialize peripheral and gap bond manager related parameters + * @return void + */ +void bt_joylink_adapter_app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "JD"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + /* Set advertising parameters */ + bt_joylink_adapter_app_start_adv(); + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + le_adv_set_param(GAP_PARAM_ADV_DATA, adv_data_len, (void *)adv_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_joylink_adapter_app_gap_callback); +} + +/** + * @brief Add GATT services and register callbacks + * @return void + */ +void bt_joylink_adapter_app_le_profile_init(void) +{ + server_init(1); + + bt_joylink_adapter_parse_service_info(); + joylink_service_id = bt_joylink_adapter_add_service((void *)bt_joylink_adapter_app_profile_callback); + server_register_app_cb(bt_joylink_adapter_app_profile_callback); +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Peripheral APP, thus only one APP task is init here + * @return void + */ +void bt_joylink_adapter_task_init(void) +{ + bt_joylink_adapter_app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_joylink_adapter_app_main(void) +{ + bt_trace_init(); + bt_joylink_adapter_stack_config_init(); + bte_init(); + le_gap_init(BT_JOYLINK_ADAPTER_APP_MAX_LINKS); + bt_joylink_adapter_app_le_gap_init(); + bt_joylink_adapter_app_le_profile_init(); + bt_joylink_adapter_task_init(); + + return 0; +} + +int bt_joylink_adapter_app_init(void) +{ + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BT joylink Adapter is already on + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + printf("[BT Joylink Adapter] BT Stack already on\r\n"); + return 0; + } else { + bt_joylink_adapter_app_main(); + } + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE, &new_state); + } while (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +#if defined(BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT) && BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT +void bt_joylink_adapter_deint_BT(void *p_param) +{ + (void)p_param; + connect_status = 0; + bt_joylink_adapter_app_deinit(); + os_task_delete(NULL); +} +#endif +extern bool bt_trace_uninit(void); +extern T_GAP_DEV_STATE bt_joylink_adapter_gap_dev_state; + +void bt_joylink_adapter_app_deinit(void) +{ + if(joylink_service_table != NULL){ + for(int i = 0;i < CHAR_NUM; i ++){ + if(joylink_service_table[i].p_value_context != NULL) + os_mem_free(joylink_service_table[i].p_value_context); + } + os_mem_free(joylink_service_table); + joylink_service_table = NULL; + } + if(adv_data != NULL){ + os_mem_free(adv_data); + adv_data = NULL; + } + bt_joylink_adapter_app_task_deinit(); + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE, &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Joylink Adapter] BT Stack is not running\r\n"); + } +#if F_BT_DEINIT + else { + bte_deinit(); + bt_trace_uninit(); + memset(&bt_joylink_adapter_gap_dev_state, 0, sizeof(T_GAP_DEV_STATE)); + printf("[BT Joylink Adapter] BT Stack deinitalized\r\n"); + } +#endif +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_task.c new file mode 100644 index 00000000..1a691799 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_task.c @@ -0,0 +1,154 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include "platform_opts_bt.h" +#if defined(CONFIG_BT_JOYLINK_ADAPTER) && CONFIG_BT_JOYLINK_ADAPTER +#include +#include +#include +#include +#include "bt_joylink_adapter_app_task.h" +#include +#include "bt_joylink_adapter_peripheral_app.h" +#include "platform_stdlib.h" +#include +#include +#include + +/*============================================================================* + * Macros + *============================================================================*/ +#define BT_JOYLINK_ADAPTER_APP_TASK_PRIORITY 4 //!< Task priorities +#define BT_JOYLINK_ADAPTER_APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define BT_JOYLINK_ADAPTER_CALLBACK_TASK_PRIORITY 4 //!< Task priorities +#define BT_JOYLINK_ADAPTER_CALLBACK_TASK_STACK_SIZE 256 * 8 //!< Task stack size + +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size +#define MAX_NUMBER_OF_CALLBACK_MESSAGE 0x20 //!< Callback message queue size + + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_joylink_adapter_app_task_handle = NULL; //!< APP task handle +void *bt_joylink_adapter_evt_queue_handle = NULL; //!< Event queue handle +void *bt_joylink_adapter_io_queue_handle = NULL; //!< IO queue handle +void *bt_joylink_adapter_callback_task_handle = NULL; //!< Callback task handle +void *bt_joylink_adapter_callback_queue_handle = NULL; //!< Callback queue handle + + +extern T_GAP_DEV_STATE bt_joylink_adapter_gap_dev_state; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_joylink_adapter_app_main_task(void *p_param) +{ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_joylink_adapter_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_joylink_adapter_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(bt_joylink_adapter_evt_queue_handle, bt_joylink_adapter_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + while (true) { + if (os_msg_recv(bt_joylink_adapter_evt_queue_handle, &event, 0xFFFFFFFF) == true) { + if (event == EVENT_IO_TO_APP) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_joylink_adapter_io_queue_handle, &io_msg, 0) == true) { + bt_joylink_adapter_app_handle_io_msg(io_msg); + } + } else { + gap_handle_msg(event); + } + } + } +} + +void bt_joylink_adapter_callback_main_task(void *p_param) +{ + (void)p_param; + T_BJA_CALLBACK_MSG callback_msg; + + os_msg_queue_create(&bt_joylink_adapter_callback_queue_handle, MAX_NUMBER_OF_CALLBACK_MESSAGE, sizeof(T_BJA_CALLBACK_MSG)); + + while (true) { + if (os_msg_recv(bt_joylink_adapter_callback_queue_handle, &callback_msg, 0xFFFFFFFF) == true) { + bt_joylink_adapter_app_handle_callback_msg(callback_msg); + } + } +} + +/** + * @brief Initialize App task + * @return void + */ +void bt_joylink_adapter_app_task_init(void) +{ + os_task_create(&bt_joylink_adapter_app_task_handle, "bt_joylink_adapter_app", bt_joylink_adapter_app_main_task, 0, BT_JOYLINK_ADAPTER_APP_TASK_STACK_SIZE, + BT_JOYLINK_ADAPTER_APP_TASK_PRIORITY); + os_task_create(&bt_joylink_adapter_callback_task_handle, "bt_joylink_adapter_callback", bt_joylink_adapter_callback_main_task, 0, + BT_JOYLINK_ADAPTER_CALLBACK_TASK_STACK_SIZE, + BT_JOYLINK_ADAPTER_CALLBACK_TASK_PRIORITY); +} + +void bt_joylink_adapter_app_task_deinit(void) +{ + if (bt_joylink_adapter_app_task_handle) { + os_task_delete(bt_joylink_adapter_app_task_handle); + } + if (bt_joylink_adapter_callback_task_handle) { + os_task_delete(bt_joylink_adapter_callback_task_handle); + } + if (bt_joylink_adapter_io_queue_handle) { + os_msg_queue_delete(bt_joylink_adapter_io_queue_handle); + } + if (bt_joylink_adapter_evt_queue_handle) { + os_msg_queue_delete(bt_joylink_adapter_evt_queue_handle); + } + if (bt_joylink_adapter_callback_queue_handle) { + os_msg_queue_delete(bt_joylink_adapter_callback_queue_handle); + } + bt_joylink_adapter_app_task_handle = NULL; + bt_joylink_adapter_callback_task_handle = NULL; + bt_joylink_adapter_io_queue_handle = NULL; + bt_joylink_adapter_evt_queue_handle = NULL; + bt_joylink_adapter_callback_queue_handle = NULL; + + bt_joylink_adapter_gap_dev_state.gap_init_state = 0; + bt_joylink_adapter_gap_dev_state.gap_adv_sub_state = 0; + bt_joylink_adapter_gap_dev_state.gap_adv_state = 0; + bt_joylink_adapter_gap_dev_state.gap_scan_state = 0; + bt_joylink_adapter_gap_dev_state.gap_conn_state = 0; + +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_task.h new file mode 100644 index 00000000..b531d467 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_app_task.h @@ -0,0 +1,31 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_JOYLINK_ADAPTER_APP_TASK_H_ +#define _BT_JOYLINK_ADAPTER_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_joylink_adapter_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_joylink_adapter_app_task_deinit(void); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_peripheral_app.c b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_peripheral_app.c new file mode 100644 index 00000000..a364ef39 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_peripheral_app.c @@ -0,0 +1,589 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include "platform_opts_bt.h" +#if defined(CONFIG_BT_JOYLINK_ADAPTER) && CONFIG_BT_JOYLINK_ADAPTER +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "bt_joylink_adapter_peripheral_app.h" +#include +#include "platform_stdlib.h" +#include +#include +#include +#include +#include "joylink_sdk.h" +#include "bt_joylink_adapter_app_flags.h" + +/*============================================================================* + * Variables + *============================================================================*/ +T_GAP_DEV_STATE bt_joylink_adapter_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_GAP_CONN_STATE bt_joylink_adapter_gap_conn_state = GAP_CONN_STATE_DISCONNECTED; /**< GAP connection state */ + +extern void *bt_joylink_adapter_evt_queue_handle; +extern void *bt_joylink_adapter_io_queue_handle; +extern void *bt_joylink_adapter_callback_queue_handle; + +#if defined(BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT) && BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT +#define BT_JOYLINK_ADAPTER_DEINT_BT_STACK_SIZE 256 * 2 //!< deint BT stack size +#define BT_JOYLINK_ADAPTER_DEINT_BT_PRIORITY 3 +void *bt_joylink_adapter_deint_bt_handle = NULL; //!< deint BT handle +#endif +extern void bt_joylink_adapter_app_start_adv(); + +/*============================================================================* + * Functions + *============================================================================*/ +bool bt_joylink_adapter_app_send_api_msg(T_BJA_API_MSG_TYPE sub_type, void *buf) +{ + T_IO_MSG io_msg; + + uint8_t event = EVENT_IO_TO_APP; + + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + io_msg.u.buf = buf; + + if (bt_joylink_adapter_evt_queue_handle != NULL && bt_joylink_adapter_io_queue_handle != NULL) { + if (os_msg_send(bt_joylink_adapter_io_queue_handle, &io_msg, 0) == false) { + printf("[%s] send io queue fail! type = 0x%x\r\n", __FUNCTION__, io_msg.subtype); + return false; + } else if (os_msg_send(bt_joylink_adapter_evt_queue_handle, &event, 0) == false) { + printf("[%s] send event queue fail! type = 0x%x\r\n", __FUNCTION__, io_msg.subtype); + return false; + } + } else { + printf("[%s] queue is empty! type = 0x%x\r\n", __FUNCTION__, io_msg.subtype); + return false; + } + + return true; +} + +void bt_joylink_adapter_app_handle_api_msg(T_IO_MSG io_msg) +{ + //Handle API msg here + uint16_t msg_type = io_msg.subtype; + + switch (msg_type){ + case BJA_API_MSG_SEND_INDICATION:{ + BJA_INDICATION_PARAM *param = io_msg.u.buf; + if (bt_joylink_adapter_send_indication(0, param->srv_id, param->index, (uint8_t*)param->val, param->len, param->type)) { + printf("\n\r[%s]:send indication success...",__func__); + } + os_mem_free(param->val); + os_mem_free(param); + } + break; + default: + break; + } + +} +bool bt_joylink_adapter_app_send_callback_msg(T_BJA_CALLBACK_MSG_TYPE type, void *buf) +{ + T_BJA_CALLBACK_MSG callback_msg; + + callback_msg.type = type; + callback_msg.buf = buf; + + if (bt_joylink_adapter_callback_queue_handle != NULL) { + if (os_msg_send(bt_joylink_adapter_callback_queue_handle, &callback_msg, 0) == false) { + printf("[%s] send callback queue fail! type = 0x%x\r\n", __FUNCTION__, callback_msg.type); + return false; + } + } else { + printf("[%s] queue is empty! type = 0x%x\r\n", __FUNCTION__, callback_msg.type); + return false; + } + + return true; +} +#if defined(BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT) && BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT +extern int connect_status; +extern void bt_joylink_adapter_deint_BT(void *p_param) ; +#endif +void bt_joylink_adapter_app_handle_callback_msg(T_BJA_CALLBACK_MSG callback_msg) +{ + //Handle callback msg here + switch (callback_msg.type){ + case BJA_CALLBACK_MSG_DISCONNECTED: + jl_disconnet_reset(); +#if defined(BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT) && BT_JOYLINK_ADAPTER_AUTO_DEINIT_BT + if (connect_status == 1) { + os_task_create(&bt_joylink_adapter_deint_bt_handle, "bt_joylink_adapter_deint_bt", bt_joylink_adapter_deint_BT, 0, BT_JOYLINK_ADAPTER_DEINT_BT_STACK_SIZE, + BT_JOYLINK_ADAPTER_DEINT_BT_PRIORITY); + } + +#endif + break; + case BJA_CALLBACK_MSG_INDICATION_SENT: + jl_send_confirm(); + break; + case BJA_CALLBACK_MSG_WRITE_SENT:{ + T_BJA_WRITE_DATA *param = callback_msg.buf; + jl_write_data(param->write_value,param->write_len); + os_mem_free(param); + } + break; + default: + break; + } + +} +void bt_joylink_adapter_app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_joylink_adapter_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) { + case IO_MSG_TYPE_BT_STATUS: { + bt_joylink_adapter_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_QDECODE: { + bt_joylink_adapter_app_handle_api_msg(io_msg); + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_joylink_adapter_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("bt_joylink_adapter_app_handle_dev_state_evt: init state %d, adv state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, cause); + if (bt_joylink_adapter_gap_dev_state.gap_init_state != new_state.gap_init_state) { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + APP_PRINT_INFO0("GAP stack ready"); + printf("GAP stack ready\r\n"); + } + //start adv + le_adv_start(); + } + + if (bt_joylink_adapter_gap_dev_state.gap_adv_state != new_state.gap_adv_state) { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("GAP adv stoped: because connection created\r\n"); + } else { + APP_PRINT_INFO0("GAP adv stoped"); + printf("GAP adv stopped\r\n"); + } + } else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) { + APP_PRINT_INFO0("GAP adv start"); + printf("GAP adv start\r\n"); + } + } + + bt_joylink_adapter_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_joylink_adapter_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + APP_PRINT_INFO4("bt_joylink_adapter_app_handle_conn_state_evt: conn_id %d old_state %d new_state %d, disc_cause 0x%x", + conn_id, bt_joylink_adapter_gap_conn_state, new_state, disc_cause); + switch (new_state) { + case GAP_CONN_STATE_DISCONNECTED: { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) { + APP_PRINT_ERROR1("bt_joylink_adapter_app_handle_conn_state_evt: connection lost cause 0x%x", disc_cause); + } + printf("BT Disconnected\r\n"); + bt_joylink_adapter_app_send_callback_msg(BJA_CALLBACK_MSG_DISCONNECTED,NULL); + le_adv_start(); + } + break; + + case GAP_CONN_STATE_CONNECTED: { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, remote_bd, (void *)&remote_bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(remote_bd), remote_bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + printf("BT Connected\r\n"); + } + break; + + default: + break; + } + + bt_joylink_adapter_gap_conn_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_joylink_adapter_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_joylink_adapter_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) { + case GAP_AUTHEN_STATE_STARTED: { + APP_PRINT_INFO0("bt_joylink_adapter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: { + if (cause == GAP_SUCCESS) { + printf("Pair success\r\n"); + APP_PRINT_INFO0("bt_joylink_adapter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } else { + printf("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_joylink_adapter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: { + APP_PRINT_ERROR1("bt_joylink_adapter_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_joylink_adapter_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_joylink_adapter_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_joylink_adapter_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO3("bt_joylink_adapter_app_handle_conn_param_update_evt update success: conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_interval, conn_slave_latency, conn_supervision_timeout); + printf("\n\rbt_joylink_adapter_app_handle_conn_param_update_evt update success: conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x\r\n", + conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: { + APP_PRINT_ERROR1("bt_joylink_adapter_app_handle_conn_param_update_evt update failed: cause 0x%x", cause); + printf("\n\rbt_joylink_adapter_app_handle_conn_param_update_evt update failed: cause 0x%x\r\n", cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: { + APP_PRINT_INFO0("bt_joylink_adapter_app_handle_conn_param_update_evt update pending"); + printf("\n\rbt_joylink_adapter_app_handle_conn_param_update_evt update pending\r\n"); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_joylink_adapter_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_joylink_adapter_app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) { + case GAP_MSG_LE_DEV_STATE_CHANGE: { + bt_joylink_adapter_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: { + bt_joylink_adapter_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: { + bt_joylink_adapter_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: { + bt_joylink_adapter_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: { + bt_joylink_adapter_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + printf("\n\rGAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: passkey %06d\r\n", display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %d", display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: passkey %06d\r\n", display_value); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: { + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + printf("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + default: + APP_PRINT_ERROR1("bt_joylink_adapter_app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_joylink_adapter_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("bt_joylink_adapter_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_joylink_adapter_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) { + case PROFILE_EVT_SRV_REG_COMPLETE: + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", p_param->event_data.service_reg_result); + break; + case PROFILE_EVT_SRV_REG_AFTER_INIT_COMPLETE: { + printf("\r\nT_SERVER_REG_AFTER_INIT_RESULT: result %d service_id %d cause %d", + p_param->event_data.server_reg_after_init_result.result, + p_param->event_data.server_reg_after_init_result.service_id, + p_param->event_data.server_reg_after_init_result.cause); + } + break; + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + printf("\r\nPROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } else { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + //notify JD BLE SDK send indication already success + bt_joylink_adapter_app_send_callback_msg(BJA_CALLBACK_MSG_INDICATION_SENT,NULL); + break; + + default: + break; + } + } else { + T_JOYLINK_CALLBACK_DATA *p_joylink_cb_data = p_data; + + switch (p_joylink_cb_data->msg_type) { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: { + if (p_joylink_cb_data->msg_data.cccd.ccc_val & GATT_CLIENT_CHAR_CONFIG_NOTIFY) { + printf("\r\n[%s] cccd 0x%x update : notify enable", __FUNCTION__, p_joylink_cb_data->msg_data.cccd.attr_index); + } else { + printf("\r\n[%s] cccd 0x%x update : notify disable", __FUNCTION__, p_joylink_cb_data->msg_data.cccd.attr_index); + } + if (p_joylink_cb_data->msg_data.cccd.ccc_val & GATT_CLIENT_CHAR_CONFIG_INDICATE) { + printf("\r\n[%s] cccd 0x%x update : indicate enable", __FUNCTION__, p_joylink_cb_data->msg_data.cccd.attr_index); + } else { + printf("\r\n[%s] cccd 0x%x update : indicate disable", __FUNCTION__, p_joylink_cb_data->msg_data.cccd.attr_index); + } + break; + } + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + /* call user defined callback */ + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + printf("\r\n[%s] write_type %d len %d,data:", __FUNCTION__, + p_joylink_cb_data->msg_data.write.write_type, + p_joylink_cb_data->msg_data.write.len); + for(int i = 0;i < p_joylink_cb_data->msg_data.write.len;i ++){ + printf("0x%x ",*(p_joylink_cb_data->msg_data.write.p_value + i)); + } + printf("\n\r"); + T_BJA_WRITE_DATA *write_data = (T_BJA_WRITE_DATA *)os_mem_alloc(0,sizeof(T_BJA_WRITE_DATA)); + memcpy(write_data->write_value,p_joylink_cb_data->msg_data.write.p_value,p_joylink_cb_data->msg_data.write.len); + write_data->write_len = p_joylink_cb_data->msg_data.write.len; + if(bt_joylink_adapter_app_send_callback_msg(BJA_CALLBACK_MSG_WRITE_SENT,write_data) != true) + os_mem_free(write_data); + + break; + default: + break; + } + + return app_result; + } +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_peripheral_app.h b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_peripheral_app.h new file mode 100644 index 00000000..80d4863a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_peripheral_app.h @@ -0,0 +1,101 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_JOYLINK_ADAPTER_PERIPHERAL_APP_H_ +#define _BT_JOULINK_ADAPTER_PERIPHERAL_APP_H_ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include "bt_joylink_adapter_service.h" + +/*============================================================================* + * Variables + *============================================================================*/ +#define BT_JOULINK_ADAPTER_SERVICE_MAX_NUM 12 + +typedef enum { + BJA_API_MSG_SEND_INDICATION, + BHA_API_MSG_MAX +} T_BJA_API_MSG_TYPE; + +typedef struct { + T_SERVER_RESULT result; + T_SERVER_ID srv_id; +} T_BJA_SRV_ADDED_CALLBACK_DATA; + +typedef struct { + T_SERVER_RESULT result; + T_SERVER_ID srv_id; + uint8_t att_index; +} T_BJA_IND_SENT_CALLBACK_DATA; + +typedef struct { + uint8_t write_len; + uint8_t write_value[JOYLINK_WRITE_MAX_LEN]; + //BleGattServiceWrite write_cb; +} T_BJA_WRITE_DATA; +typedef enum +{ + BJA_CALLBACK_MSG_DISCONNECTED, + BJA_CALLBACK_MSG_INDICATION_SENT, + BJA_CALLBACK_MSG_WRITE_SENT, + BJA_CALLBACK_MSG_MAX +} T_BJA_CALLBACK_MSG_TYPE; + +typedef struct +{ + T_BJA_CALLBACK_MSG_TYPE type; + void *buf; +} T_BJA_CALLBACK_MSG; + +/*============================================================================* + * Functions + *============================================================================*/ + +bool bt_joylink_adapter_app_send_api_msg(T_BJA_API_MSG_TYPE sub_type, void *buf); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_joylink_adapter_app_handle_io_msg(T_IO_MSG io_msg); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id. + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_joylink_adapter_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_joylink_adapter_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_service.c b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_service.c new file mode 100644 index 00000000..17764cd9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_service.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include "bt_joylink_adapter_peripheral_app.h" +#include +#include "platform_stdlib.h" +#include "joylink_sdk.h" + +static uint8_t bt_joylink_char_read_value[JOYLINK_READ_MAX_LEN]; +static unsigned int bt_joylink_char_read_len = 0; + +static P_FUN_SERVER_GENERAL_CB bt_joylink_service_cb = NULL; +T_SERVER_ID joylink_service_id; + +bool bt_joylink_adapter_send_indication(uint8_t conn_id, uint8_t service_id, uint8_t handle, + uint8_t *p_value, uint16_t length, T_GATT_PDU_TYPE type) +{ + if (p_value == NULL) { + return false; + } + printf("\r\n[%s] service_id %d index %d", __FUNCTION__, service_id, handle); + return server_send_data(conn_id, service_id, handle, p_value, length, type); +} + +void bt_joylink_adapter_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t cccbits) +{ + printf("\r\n[%s] service_id %d index 0x%x, cccbits = 0x%x ", __FUNCTION__, service_id, attrib_index, cccbits); + T_JOYLINK_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.conn_id = conn_id; + callback_data.srv_id = service_id; + callback_data.msg_data.cccd.attr_index = attrib_index; + callback_data.msg_data.cccd.ccc_val = cccbits; + + /* Notify Application. */ + if (bt_joylink_service_cb) { + bt_joylink_service_cb(service_id, (void *)&callback_data); + } +} + +T_APP_RESULT bt_joylink_adapter_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + printf("\r\n[%s] service_id %d index 0x%x", __FUNCTION__, service_id, attrib_index); + T_JOYLINK_CALLBACK_DATA callback_data; + + if(BT_JOYLINK_ADAPTER_CHAR_WRITE_INDEX == attrib_index) + { + if (p_value == NULL) { + cause = APP_RESULT_INVALID_VALUE_SIZE; + } else { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.srv_id = service_id; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.p_value = p_value; + callback_data.msg_data.write.len = length; + + if (bt_joylink_service_cb) { + bt_joylink_service_cb(service_id, (void *)&callback_data); + } + } + } + else + { + printf("simp_ble_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, + length); + cause = APP_RESULT_ATTR_NOT_FOUND; + + } + + return (cause); +} + + +T_APP_RESULT bt_joylink_adapter_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + (void)offset; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + + printf("\r\n[%s] service_id %d index 0x%x", __FUNCTION__, service_id, attrib_index); + bt_joylink_char_read_len = JOYLINK_READ_MAX_LEN; + + T_JOYLINK_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.srv_id = service_id; + callback_data.msg_data.read.p_value = bt_joylink_char_read_value; + callback_data.msg_data.read.p_len = &bt_joylink_char_read_len; + + if (bt_joylink_service_cb) { + bt_joylink_service_cb(service_id, (void *)&callback_data); + } + + *pp_value = bt_joylink_char_read_value; + *p_length = bt_joylink_char_read_len; + + return (cause); +} + +const T_FUN_GATT_SERVICE_CBS bt_joylink_adapter_service_cbs = { + bt_joylink_adapter_attr_read_cb, /* Read callback function pointer */ + bt_joylink_adapter_attr_write_cb, /* Write callback function pointer */ + bt_joylink_adapter_cccd_update_cb /* CCCD update callback function pointer */ +}; + +extern T_ATTRIB_APPL *joylink_service_table; +extern uint8_t CHAR_NUM; + +T_SERVER_ID bt_joylink_adapter_add_service(void *p_func) +{ + uint16_t bt_joylink_attr_tbl_size = CHAR_NUM * sizeof(T_ATTRIB_APPL); + if (false == server_add_service(&joylink_service_id, + (uint8_t *) joylink_service_table, + bt_joylink_attr_tbl_size, + bt_joylink_adapter_service_cbs)) { + printf("\r\n[%s] add service fail", __FUNCTION__); + return 0xff; + } else { + printf("\r\n[%s] add service %d success", __FUNCTION__, joylink_service_id); + } + + if (bt_joylink_service_cb == NULL) { + bt_joylink_service_cb = (P_FUN_SERVER_GENERAL_CB) p_func; + } + return joylink_service_id; +} + + +static int setup_ble_char_indication_attr(uint8_t *uuid,T_ATTRIB_APPL *attr) +{ + ///characteristic dec + attr->flags = ATTRIB_FLAG_VALUE_INCL; + attr->type_value[0] = LO_WORD(GATT_UUID_CHARACTERISTIC); + attr->type_value[1] = HI_WORD(GATT_UUID_CHARACTERISTIC); + attr->type_value[2] = GATT_CHAR_PROP_INDICATE; + attr->value_len = 1; + attr->p_value_context = NULL; + attr->permissions = GATT_PERM_READ; + //characteristic value dec + attr ++; + + attr->permissions = GATT_PERM_NONE; + attr->flags = ATTRIB_FLAG_UUID_128BIT | ATTRIB_FLAG_VALUE_APPL; + memcpy(attr->type_value, uuid, 16); + + attr->value_len = 0; + attr->p_value_context = NULL; + //cccd + attr ++; + attr->flags = ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL; + attr->type_value[0] = LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG); + attr->type_value[1] = HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG); + attr->type_value[2] = 0; + attr->type_value[3] = 0; + attr->p_value_context = NULL; + attr->value_len = 2; + attr->permissions = GATT_PERM_READ | GATT_PERM_WRITE; + + return 0; +} + + +static int setup_ble_char_write_attr(uint8_t *uuid,T_ATTRIB_APPL *attr) +{ + ///characteristic dec + attr->flags = ATTRIB_FLAG_VALUE_INCL; + attr->type_value[0] = LO_WORD(GATT_UUID_CHARACTERISTIC); + attr->type_value[1] = HI_WORD(GATT_UUID_CHARACTERISTIC); + attr->type_value[2] = GATT_CHAR_PROP_WRITE; + attr->value_len = 1; + attr->p_value_context = NULL; + attr->permissions = GATT_PERM_READ; + //characteristic value dec + attr ++; + + attr->permissions = GATT_PERM_WRITE; + attr->flags = ATTRIB_FLAG_UUID_128BIT | ATTRIB_FLAG_VALUE_APPL; + memcpy(attr->type_value, uuid, 16); + + attr->value_len = 0; + attr->p_value_context = NULL; + + return 0; + +} + + +static int setup_ble_serv_dec_attr(uint8_t *uuid,T_ATTRIB_APPL *attr) +{ + + attr->type_value[0] = LO_WORD(GATT_UUID_PRIMARY_SERVICE); /* type */ + attr->type_value[1] = HI_WORD(GATT_UUID_PRIMARY_SERVICE); + + attr->flags = ATTRIB_FLAG_LE | ATTRIB_FLAG_VOID; + attr->value_len = 16; + attr->p_value_context = os_mem_alloc(0, attr->value_len); + memset(attr->p_value_context, 0, attr->value_len); + memcpy(attr->p_value_context, (void *)uuid, attr->value_len); + + attr->permissions = GATT_PERM_READ; + + return 0; +} +bool bt_joylink_adapter_parse_service_info() +{ + //get service data form JD ble sdk + jl_gatt_data_t *service_data = (jl_gatt_data_t *)os_mem_alloc(0,sizeof(jl_gatt_data_t)); + jl_get_gatt_config_data(service_data); + ////joylink service include characteristic(indication) and characteristic(write) + joylink_service_table = (T_ATTRIB_APPL *)os_mem_alloc(0,CHAR_NUM * sizeof(T_ATTRIB_APPL)); + memset(joylink_service_table,0,CHAR_NUM * sizeof(T_ATTRIB_APPL)); + //parse service data + int i = 0; + setup_ble_serv_dec_attr(service_data->service_uuid128,&joylink_service_table[i]); + i ++; + setup_ble_char_write_attr(service_data->chra_uuid128_write,&joylink_service_table[i]); + i = i + 2; + setup_ble_char_indication_attr(service_data->chra_uuid128_indicate,&joylink_service_table[i]); + if(service_data != NULL) + os_mem_free(service_data); + return true; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_service.h b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_service.h new file mode 100644 index 00000000..860efcd8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_joylink_adapter/bt_joylink_adapter_service.h @@ -0,0 +1,56 @@ +#ifndef _BT_JOYLINK_ADAPTER_SERVICE_H_ +#define _BT_JOYLINK_ADAPTER_SERVICE_H_ + +#include +#include "joylink_log.h" + +#define JOYLINK_READ_MAX_LEN 300 +#define JOYLINK_WRITE_MAX_LEN 300 +#define BJA_MAX_ATTR_NUM 12 + +#define BT_JOYLINK_ADAPTER_CHAR_WRITE_INDEX 0x02 +#define BT_JOYLINK_ADAPTER_CHAR_INDICATION_INDEX 0x04 +#define BT_JOYLINK_ADAPTER_CHAR_INDICATION_CCCD_INDEX (BT_JOYLINK_ADAPTER_CHAR_INDICATION_INDEX + 1) + +T_SERVER_ID joylink_service_id; + +typedef struct { + T_WRITE_TYPE write_type; + unsigned int len; + uint8_t *p_value; +} T_JOYLINK_WRITE_MSG; + +typedef struct { + unsigned int *p_len; + uint8_t *p_value; +} T_JOYLINK_READ_MSG; + +typedef struct { + uint16_t attr_index; + uint16_t ccc_val; +} T_JOYLINK_CCCD_MSG; + +typedef union { + T_JOYLINK_CCCD_MSG cccd; + T_JOYLINK_READ_MSG read; + T_JOYLINK_WRITE_MSG write; +} T_JOYLINK_MSG_DATA; + +typedef struct { + uint8_t conn_id; + T_SERVER_ID srv_id; + T_SERVICE_CALLBACK_TYPE msg_type; + T_JOYLINK_MSG_DATA msg_data; +} T_JOYLINK_CALLBACK_DATA; + +typedef struct { + uint8_t type; + uint8_t srv_id; + uint8_t index; + char *val; + uint16_t len; +} BJA_INDICATION_PARAM; + +bool bt_joylink_adapter_send_indication(uint8_t conn_id, uint8_t service_id, uint8_t handle, uint8_t *p_value, uint16_t length, T_GATT_PDU_TYPE type); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_cmd_types.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_cmd_types.h new file mode 100644 index 00000000..84d1f549 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_cmd_types.h @@ -0,0 +1,19 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_CMD_TYPES_H_ +#define _BT_MESH_CMD_TYPES_H_ + +#define GEN_MESH_HANDLER(cmd) {user_cmd ## cmd}, + +struct bt_mesh_api_hdl { + user_cmd_parse_result_t (*mesh_func)(user_cmd_parse_value_t *pparse_value); +}; + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c new file mode 100644 index 00000000..db9be31d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c @@ -0,0 +1,836 @@ +/** +***************************************************************************************** +* Copyright(c) 2019, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_mesh_user_api.c + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author sherman + * @date 2019-09-16 + * @version v1.0 + * ************************************************************************************* + */ +#include "bt_mesh_user_api.h" +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) +#include "bt_mesh_provisioner_api.h" +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) +#include "bt_mesh_device_api.h" +#endif + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#if ((defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER) || \ + (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE) || \ + (defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) || \ + (defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE)) + +CMD_MOD_INFO_S btMeshCmdPriv; +INDICATION_ITEM btMeshCmdIdPriv; +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) +extern struct mesh_task_struct meshProvisionerCmdThread; +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) +extern struct mesh_task_struct meshDeviceCmdThread; +#endif + +static const mesh_cmd_entry mesh_cmd_table[] = { +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + PARAM_MESH_CODE("pbadvcon", "\r pbadvcon [dev uuid]", "\r create a pb-adv link with the device uuid\n\r", GEN_MESH_CODE(_pb_adv_con)) + PARAM_MESH_CODE("prov", "\r prov [attn_dur] [manual]", "\r provision a new mesh device\n\r", GEN_MESH_CODE(_prov)) + PARAM_MESH_CODE("provs", "\r provs", "\r provision stop\n\r", GEN_MESH_CODE(_prov_stop)) + PARAM_MESH_CODE("aka", "\r aka [dst] [net_key_index] [app_key_index]", "\r app key add\n\r", GEN_MESH_CODE(_app_key_add)) + PARAM_MESH_CODE("mab", "\r mab [dst] [element index] [model_id] [app_key_index]", "\r model app bind\n\r", GEN_MESH_CODE(_model_app_bind)) + PARAM_MESH_CODE("goos", "\r goos [dst] [on/off] [ack] [app_key_index] [steps] [resolution] [delay]", "\r generic on off set\n\r", GEN_MESH_CODE(_generic_on_off_set)) + PARAM_MESH_CODE("goog", "\r goog [dst] [app_key_index]", "\r generic on off get\n\r", GEN_MESH_CODE(_generic_on_off_get)) + PARAM_MESH_CODE("nr", "\r nr [dst]", "\r node reset\n\r", GEN_MESH_CODE(_node_reset)) + PARAM_MESH_CODE("msd", "\r msd [dst] [element index] [model_id] ", "\r model subsribe delete\n\r", GEN_MESH_CODE(_model_sub_delete)) + PARAM_MESH_CODE("msa", "\r msa [dst] [element index] [model_id] [group addr]", "\r model subsribe add\n\r", GEN_MESH_CODE(_model_sub_add)) + PARAM_MESH_CODE("provdis", "\r provdis [conn id]", "\r Start discovery provisioning service\n\r", GEN_MESH_CODE(_prov_discover)) + PARAM_MESH_CODE("provcmd", "\r provcmd [char CCCD] [command: enable/disable]", "\r Provisioning notify/ind switch command\n\r", GEN_MESH_CODE(_prov_cccd_operate)) + PARAM_MESH_CODE("proxydis", "\r proxydis [conn id]", "\r Start discovery proxy service\n\r", GEN_MESH_CODE(_proxy_discover)) + PARAM_MESH_CODE("proxycmd", "\r proxycmd [char CCCD] [command: enable/disable]", "\r Proxy notify/ind switch command\n\r", GEN_MESH_CODE(_proxy_cccd_operate)) + PARAM_MESH_CODE("llg", "\r llg [dst] [app_key_index]", "\r light lightness get\n\r",GEN_MESH_CODE(_light_lightness_get)) + PARAM_MESH_CODE("lls", "\r lls [dst] [lightness] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light lightness set\n\r", GEN_MESH_CODE(_light_lightness_set)) + PARAM_MESH_CODE("lllg", "\r lllg [dst] [app_key_index]", "\r light lightness linear get\n\r", GEN_MESH_CODE(_light_lightness_linear_get)) + PARAM_MESH_CODE("llls", "\r llls [dst] [lightness] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light lightness linear set\n\r", GEN_MESH_CODE(_light_lightness_linear_set)) + PARAM_MESH_CODE("lllag", "\r lllag [dst] [app_key_index]", "\r light lightness last get\n\r", GEN_MESH_CODE(_light_lightness_last_get)) + PARAM_MESH_CODE("lldg", "\r lldg [dst] [app_key_index]", "\r light lightness default get\n\r", GEN_MESH_CODE(_light_lightness_default_get)) + PARAM_MESH_CODE("llds", "\r llds [dst] [lightness] [ack] [app_key_index]", "\r light lightness default set\n\r", GEN_MESH_CODE(_light_lightness_default_set)) + PARAM_MESH_CODE("llrg", "\r llrg [dst] [app_key_index]", "\r light lightness range get\n\r", GEN_MESH_CODE(_light_lightness_range_get)) + PARAM_MESH_CODE("llrs", "\r llrs [dst] [min] [max] [ack] [app_key_index]", "\r light lightness range set\n\r", GEN_MESH_CODE(_light_lightness_range_set)) + PARAM_MESH_CODE("lcg", "\r lcg [dst] [app_key_index]", "\r light ctl set\n\r", GEN_MESH_CODE(_light_ctl_get)) + PARAM_MESH_CODE("lcs", "\r lcs [dst] [lightness] [temperature] [delta uv] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light ctl set\n\r", GEN_MESH_CODE(_light_ctl_set)) + PARAM_MESH_CODE("lctg", "\r lctg [dst] [app_key_index]", "\r light ctl temperature get\n\r", GEN_MESH_CODE(_light_ctl_temperature_get)) + PARAM_MESH_CODE("lcts", "\r lcts [dst] [temperature] [delta uv] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light ctl temperature set\n\r", GEN_MESH_CODE(_light_ctl_temperature_set)) + PARAM_MESH_CODE("lctrg", "\r lctrg [dst] [app_key_index]", "\r light ctl temperature range get\n\r", GEN_MESH_CODE(_light_ctl_temperature_range_get)) + PARAM_MESH_CODE("lctrs", "\r lctrs [dst] [min] [max] [ack] [app_key_index]", "\r light ctl temperature range set\n\r", GEN_MESH_CODE(_light_ctl_temperature_range_set)) + PARAM_MESH_CODE("lcdg", "\r lcdg [dst] [app_key_index]", "\r light ctl default get\n\r", GEN_MESH_CODE(_light_ctl_default_get)) + PARAM_MESH_CODE("lcds", "\r lcds [dst] [lightness] [temperature] [delta uv] [ack] [app_key_index]", "\r light ctl default set\n\r", GEN_MESH_CODE(_light_ctl_default_set)) + PARAM_MESH_CODE("lhg", "\r lhg [dst] [app_key_index]", "\r light hsl get\n\r", GEN_MESH_CODE(_light_hsl_get)) + PARAM_MESH_CODE("lhs", "\r lhs [dst] [hue] [saturation] [lightness] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light hsl set\n\r", GEN_MESH_CODE(_light_hsl_set)) + PARAM_MESH_CODE("lhtg", "\r lhtg [dst] [app_key_index]", "\r light hsl target get\n\r", GEN_MESH_CODE(_light_hsl_target_get)) + PARAM_MESH_CODE("lhhg", "\r lhhg [dst] [app_key_index]", "\r light hsl hue get\n\r", GEN_MESH_CODE(_light_hsl_hue_get)) + PARAM_MESH_CODE("lhhs", "\r lhhs [dst] [hue] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light hsl hue set\n\r", GEN_MESH_CODE(_light_hsl_hue_set)) + PARAM_MESH_CODE("lhsg", "\r lhsg [dst] [app_key_index]", "\r light hsl saturation get\n\r", GEN_MESH_CODE(_light_hsl_saturation_get)) + PARAM_MESH_CODE("lhss", "\r lhss [dst] [saturation] [ack] [app_key_index] [steps] [resolution] [delay]", "\r light hsl saturation set\n\r", GEN_MESH_CODE(_light_hsl_saturation_set)) + PARAM_MESH_CODE("lhdg", "\r lhdg [dst] [app_key_index]", "\r light hsl default get\n\r", GEN_MESH_CODE(_light_hsl_default_get)) + PARAM_MESH_CODE("lhds", "\r lhds [dst] [lightness] [hue] [saturation] [ack] [app_key_index]", "\r light hsl default set\n\r", GEN_MESH_CODE(_light_hsl_default_set)) + PARAM_MESH_CODE("lhrg", "\r lhrg [dst] [app_key_index]", "\r light hsl range get\n\r", GEN_MESH_CODE(_light_hsl_range_get)) + PARAM_MESH_CODE("lhrs", "\r lhrs [dst] [hue min] [hue max] [saturation min] [saturation max] [ack] [app_key_index]", "\r light hsl range set\n\r", GEN_MESH_CODE(_light_hsl_range_set)) + PARAM_MESH_CODE("lxg", "\r lxg [dst] [app_key_index]\n\r", "light xyl get\n\r", GEN_MESH_CODE(_light_xyl_get)) + PARAM_MESH_CODE("lxs", "\r lxs [dst] [lightness] [xyl_x] [xyl_y] [ack] [app_key_index] [steps] [resolution] [delay]\n\r", "light xyl set\n\r", GEN_MESH_CODE(_light_xyl_set)) + PARAM_MESH_CODE("lxtg", "\r lxtg [dst] [app_key_index]\n\r", "light xyl target get\n\r", GEN_MESH_CODE(_light_xyl_target_get)) + PARAM_MESH_CODE("lxdg", "\r lxdg [dst] [app_key_index]\n\r", "light xyl default get\n\r", GEN_MESH_CODE(_light_xyl_default_get)) + PARAM_MESH_CODE("lxds", "\r lxds [dst] [lightness] [xyl_x] [xyl_y] [ack] [app_key_index]\n\r", "light xyl default set\n\r", GEN_MESH_CODE(_light_xyl_default_set)) + PARAM_MESH_CODE("lxrg", "\r lxrg [dst] [app_key_index]\n\r", "light xyl range get\n\r", GEN_MESH_CODE(_light_xyl_range_get)) + PARAM_MESH_CODE("lxrs", "\r lxrs [dst] [xyl_x min] [xyl_x max] [xyl_y min] [xyl_y max] [ack] [app_key_index]\n\r", "light xyl range set\n\r", GEN_MESH_CODE(_light_xyl_range_set)) + PARAM_MESH_CODE("ts", "\r ts [dst] [tai second low] [tai second high] [subsecond] [uncertainty] [time authority] [tai utc delta] [time zone offset] [app_key_index]\n\r", "time set\n\r", GEN_MESH_CODE(_time_set)) + PARAM_MESH_CODE("tg", "\r tg [dst] [app_key_index]\n\r", "time get\n\r", GEN_MESH_CODE(_time_get)) + PARAM_MESH_CODE("tzs", "\r tzs [dst] [time zone offset new] [tai of zone change low] [tai of zone change high] [app_key_index]\n\r", "time zone set\n\r", GEN_MESH_CODE(_time_zone_set)) + PARAM_MESH_CODE("tzg", "\r tzg [dst] [app_key_index]\n\r", "time zone get\n\r", GEN_MESH_CODE(_time_zone_get)) + PARAM_MESH_CODE("ttuds", "\r ttuds [dst] [tai utc delta new] [tai of delta change low] [tai of delta change high] [app_key_index]\n\r", "time tai utc delta set\n\r", GEN_MESH_CODE(_time_tai_utc_delta_set)) + PARAM_MESH_CODE("ttudg", "\r ttudg [dst] [app_key_index]\n\r", "time tai utc delta get\n\r", GEN_MESH_CODE(_time_tai_utc_delta_get)) + PARAM_MESH_CODE("trs", "\r trs [dst] [role] [app_key_index]\n\r", "time role set\n\r", GEN_MESH_CODE(_time_role_set)) + PARAM_MESH_CODE("trg", "\r trg [dst] [app_key_index]\n\r", "time role get\n\r", GEN_MESH_CODE(_time_role_get)) + PARAM_MESH_CODE("ss", "\r ss [dst] [scene number] [ack] [app_key_index]", "\r scene store\n\r", GEN_MESH_CODE(_scene_store)) + PARAM_MESH_CODE("sr", "\r sr [dst] [scene number] [ack] [app_key_index] [steps] [resolution] [delay]", "\r scene recall\n\r", GEN_MESH_CODE(_scene_recall)) + PARAM_MESH_CODE("sg", "\r sg [dst] [app_key_index]", "\r scene get\n\r", GEN_MESH_CODE(_scene_get)) + PARAM_MESH_CODE("srg", "\r srg [dst] [app_key_index]", "\r scene register get\n\r", GEN_MESH_CODE(_scene_register_get)) + PARAM_MESH_CODE("sd", "\r sd [dst] [scene number] [ack] [app_key_index]", "\r scene delete\n\r", GEN_MESH_CODE(_scene_delete)) + PARAM_MESH_CODE("scheg", "\r scheg [dst] [app_key_index]", "\r scheduler get\n\r", GEN_MESH_CODE(_scheduler_get)) + PARAM_MESH_CODE("scheag", "\r scheag [dst] [index] [app_key_index]", "\r scheduler action get\n\r", GEN_MESH_CODE(_scheduler_action_get)) + PARAM_MESH_CODE("scheas", "\r scheag [dst] [index] [app_key_index]", "\r scheduler action get\n\r", GEN_MESH_CODE(_scheduler_action_set)) +#if defined(MESH_RPR) && MESH_RPR + PARAM_MESH_CODE("rmtscan", "\r rmtscan [dst] [net key index] [scanned items limit] [scan timeout] [dev uuid]", "\r romte provision scan start\n\r", GEN_MESH_CODE(_rmt_prov_client_scan_start)) + PARAM_MESH_CODE("rmtcon", "\r rmtcon [dst] [net key index] [dev uuid] [link open timeout]", "\r romte link open for provision\n\r", GEN_MESH_CODE(_rmt_prov_client_link_open_prov)) + PARAM_MESH_CODE("rmtdisc", "\r rmtdisc [dst] [net_key_index] [reason]", "\r romte link close for provision\n\r", GEN_MESH_CODE(_rmt_prov_client_close)) +#endif +#if defined(MESH_DFU) && MESH_DFU + PARAM_MESH_CODE("fuig", "\r fuig [dst] [app_key_index] [first_index] [entries_limit]", "\r firmware update information get\n\r", GEN_MESH_CODE(_fw_update_info_get)) + PARAM_MESH_CODE("fus", "\r fus [dst] [app_key_index] [update ttl] [update timeout base] [blob id] [fw image idx] [fw metadata] [metadata len]", "\r firmware update start\n\r", GEN_MESH_CODE(_fw_update_start)) + PARAM_MESH_CODE("fuc", "\r fuc [dst] [app_key_index]\n\r", "\r firmware update cancel\n\r", GEN_MESH_CODE(_fw_update_cancel)) +#endif +#endif +#if (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + PARAM_MESH_CODE("nr", "\r nr [mode]\n\r", "\r node reset\n\r", GEN_MESH_CODE(_node_reset)) + PARAM_MESH_CODE("pcs", "\r pcs [public key oob] [static oob] [output size] [output action] [input size] [input action]\n\r", "\r provision capability set\n\r", GEN_MESH_CODE(_prov_capa_set)) + PARAM_MESH_CODE("lpninit", "\r lpninit [fn_num]\n\r", "\r low power node init\n\r", GEN_MESH_CODE(_lpn_init)) + PARAM_MESH_CODE("lpndeinit", "\r lpndeinit\n\r", "\r low power node deinit\n\r", GEN_MESH_CODE(_lpn_deinit)) + PARAM_MESH_CODE("lpnreq", "\r lpnreq [fn_index] [net_key_index] [poll int(100ms)] [poll to(100ms)] [rx delay(ms)] [rx widen(ms)]\n\r", "\r LPN request to estabish a friendship\n\r", GEN_MESH_CODE(_lpn_req)) + PARAM_MESH_CODE("lpnsub", "\r lpnsub [fn_index] [addr] [add/rm]\n\r", "\r LPN subsript list add or rm\n\r", GEN_MESH_CODE(_lpn_sub)) + PARAM_MESH_CODE("lpnclear", "\r lpnclear [fn_index]\n\r", "\r LPN clear\n\r", GEN_MESH_CODE(_lpn_clear)) + PARAM_MESH_CODE("dtn", "\r dtn [conn_id] [value...]\n\r", "\r data transmission notify\n\r", GEN_MESH_CODE(_data_transmission_notify)) +#endif + PARAM_MESH_CODE("dtw", "\r dtw [dst] [data...] [app_key_index] [ack]", "\r data transmission write data\n\r", GEN_MESH_CODE(_datatrans_write)) + PARAM_MESH_CODE("dtr", "\r dtr [dst] [len] [app_key_index]", "\r data transmission read data\n\r", GEN_MESH_CODE(_datatrans_read)) + PARAM_MESH_CODE("con", "\r con [bt addr] [addr type]", "\r connect to remote device\n\r", GEN_MESH_CODE(_connect)) + PARAM_MESH_CODE("disc", "\r disc [conn id]", "\r disconnect to remote device\n\r", GEN_MESH_CODE(_disconnect)) + PARAM_MESH_CODE("ls", "\r ls\n\r", "\rlist node state info\n\r", GEN_MESH_CODE(_list)) + PARAM_MESH_CODE("dis", "\r dis [1 on/0 off]\n\r", "\rdevice information show\n\r", GEN_MESH_CODE(_dev_info_show)) + PARAM_MESH_CODE("fninit", "\r fninit [lpn num] [queue size] [rx window(ms)]\n\r", "\r friend node init\n\r", GEN_MESH_CODE(_fn_init)) + PARAM_MESH_CODE("fndeinit", "\r fndeinit\n\r", "\r friend node deinit\n\r", GEN_MESH_CODE(_fn_deinit)) +}; + +void bt_mesh_io_msg_handler(T_IO_MSG io_msg) +{ + uint8_t ret = 1; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)io_msg.u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + if ((btMeshCmdPriv.meshMode != BT_MESH_PROVISIONER) && (btMeshCmdPriv.meshMode != BT_MESH_DEVICE)) { + printf("[BT_MESH] %s(): Error BT MESH mode %d \r\n",__func__); + goto exit; + } +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshMode == BT_MESH_PROVISIONER) { + if (io_msg.type < MAX_MESH_PROVISIONER_CMD) { + ret = bt_mesh_user_cmd_hdl(io_msg.type, (CMD_ITEM_S *)io_msg.u.buf); + if(ret != 0) { + printf("[BT_MESH] %s(): bt_mesh_io_msg_handler Fail!\r\n",__func__); + } + return; + } else { + printf("[BT_MESH] %s(): Error mesh code %d \r\n",__func__, io_msg.type); + goto exit; + } + } +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshMode == BT_MESH_DEVICE) { + if (io_msg.type < MAX_MESH_DEVICE_CMD) { + ret = bt_mesh_user_cmd_hdl(io_msg.type, (CMD_ITEM_S *)io_msg.u.buf); + if(ret != 0) { + printf("[BT_MESH] %s(): bt_mesh_io_msg_handler Fail!\r\n",__func__); + } + return; + } else { + printf("[BT_MESH] %s(): Error mesh code %d \r\n",__func__, io_msg.type); + goto exit; + } + } +#endif + +exit: + if (pmeshCmdItem_s->userApiMode == USER_API_ASYNCH) { + bt_mesh_free_hdl(puserItem); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } else if (pmeshCmdItem_s->userApiMode == USER_API_CMDLINE) { + bt_mesh_cmdunreg(pmeshCmdItem_s); + } + + return; +} + +extern int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg); + +int bt_mesh_user_cmd(uint16_t mesh_code, void *pmesh_cmd_item_s) +{ + T_IO_MSG io_msg; + CMD_ITEM_S *pmeshCmdItem_s = (CMD_ITEM_S *)pmesh_cmd_item_s; + int ret; + + io_msg.type = mesh_code; + io_msg.u.buf = (void *)pmeshCmdItem_s; + pmeshCmdItem_s->msgRecvFlag = 0; + ret = bt_mesh_send_io_msg(&io_msg); + + return ret; +} + +uint8_t bt_mesh_user_cmd_hdl(uint16_t mesh_code, CMD_ITEM_S *pmesh_cmd_item_s) +{ + uint8_t ret = 1; + user_cmd_parse_result_t (*cmd_hdl)(user_cmd_parse_value_t *pparse_value); + CMD_ITEM_S *pmeshCmdItem_s = (CMD_ITEM_S *)pmesh_cmd_item_s; + CMD_ITEM *pmeshCmdItem = NULL; + PUSER_ITEM puserItem = NULL; + user_cmd_parse_value_t *pparse_value = NULL; + + pmeshCmdItem = pmeshCmdItem_s->pmeshCmdItem; + puserItem = (PUSER_ITEM)pmeshCmdItem->userData; + if ((btMeshCmdPriv.meshMode != BT_MESH_PROVISIONER) && (btMeshCmdPriv.meshMode != BT_MESH_DEVICE)) { + printf("[BT_MESH] %s(): Error BT MESH mode %d \r\n",__func__); + goto exit; + } + if (pmeshCmdItem_s->msgRecvFlag) { + printf("[BT_MESH] %s(): mesh code %d send msg fail \r\n", __func__, pmeshCmdItem->meshCmdCode); + goto exit; + } +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshMode == BT_MESH_PROVISIONER) { + cmd_hdl = provisionercmds[mesh_code].mesh_func; + } +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshMode == BT_MESH_DEVICE) { + cmd_hdl = devicecmds[mesh_code].mesh_func; + } +#endif + if (pmeshCmdItem_s->userApiMode != USER_API_ASYNCH && pmeshCmdItem_s->semaDownTimeOut) { + printf("[BT_MESH] %s(): mesh code %d timeout \r\n", __func__, pmeshCmdItem->meshCmdCode); + goto exit; + } + + os_mutex_take(btMeshCmdPriv.ppvalueMutex, 0xFFFFFFFF); + pparse_value = puserItem->pparseValue; + if (pparse_value == NULL) { + printf("[BT_MESH] %s(): pparse_value is NULL!\r\n",__func__); + os_mutex_give(btMeshCmdPriv.ppvalueMutex); + goto exit; + } + ret = cmd_hdl(pparse_value); + os_mutex_give(btMeshCmdPriv.ppvalueMutex); + + if (pmeshCmdItem_s->userApiMode == USER_API_CMDLINE) { + if (!pmeshCmdItem_s->semaDownTimeOut) { + os_sem_give(puserItem->cmdLineSema); + } + } + if (ret != USER_CMD_RESULT_OK) { + printf("[BT_MESH] %s(): provisioner cmd fail! (%d)\r\n",__func__,ret); + } + +exit: + pmeshCmdItem_s->msgRecvFlag = 1; + if (pmeshCmdItem_s->userApiMode == USER_API_CMDLINE) { + bt_mesh_cmdunreg(pmeshCmdItem_s); + } else if (pmeshCmdItem_s->userApiMode == USER_API_ASYNCH) { + bt_mesh_free_hdl(puserItem); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } + + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + + return ret; +} + +uint8_t bt_mesh_enqueue_cmd(struct list_head *queue, uint8_t head_or_tail) +{ + if (!btMeshCmdPriv.meshCmdEnable) { + printf("[BT_MESH] %s(): Mesh user command is disabled!\r\n", __func__); + return 1;; + } + os_mutex_take(btMeshCmdPriv.cmdMutex, 0xFFFFFFFF); + if (head_or_tail) { + rtw_list_insert_head(queue, &btMeshCmdPriv.meshCmdList); + } else { + rtw_list_insert_tail(queue, &btMeshCmdPriv.meshCmdList); + } + btMeshCmdPriv.cmdListNum ++; + os_mutex_give(btMeshCmdPriv.cmdMutex); +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshCmdEnable) { + os_sem_give(meshProvisionerCmdThread.wakeup_sema); + } +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshCmdEnable) { + os_sem_give(meshDeviceCmdThread.wakeup_sema); + } +#endif + else { + printf("[BT_MESH] %s(): Mesh user command is disabled\r\n"); + return 2; + } + + return 0; +} + +struct list_head *bt_mesh_dequeue_cmd(void) +{ + struct list_head *queue = NULL; + + os_mutex_take(btMeshCmdPriv.cmdMutex, 0xFFFFFFFF); + if (rtw_is_list_empty(&btMeshCmdPriv.meshCmdList)) { + printf("[BT_MESH] %s(): btMeshCmdPriv.meshCmdList is empty !\r\n", __func__); + os_mutex_give(btMeshCmdPriv.cmdMutex); + return NULL; + } else { + queue = get_next(&btMeshCmdPriv.meshCmdList); + rtw_list_delete(queue); + } + btMeshCmdPriv.cmdListNum --; + os_mutex_give(btMeshCmdPriv.cmdMutex); + + return queue; +} + +CMD_ITEM_S* bt_mesh_cmdreg(uint16_t mesh_code, user_cmd_parse_value_t *pparse_value, bt_mesh_func func, user_cmd_cbk cbk, void *user_data) +{ + PUSER_ITEM puserItem = NULL; + CMD_ITEM *pmeshCmdItem = NULL; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + + if (!btMeshCmdPriv.meshCmdEnable) { + printf("[BT_MESH] %s(): Mesh user command is disabled!\r\n"); + return NULL; + } + puserItem = (PUSER_ITEM)user_data; + pmeshCmdItem = (CMD_ITEM *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(CMD_ITEM)); + if (pmeshCmdItem == NULL) { + printf("[BT_MESH] %s(): alloc pmeshCmdItem for mesh code %d fail !\r\n", __func__, mesh_code); + return NULL; + } + pmeshCmdItem->meshCmdCode = mesh_code; + pmeshCmdItem->pparseValue = pparse_value; + pmeshCmdItem->meshFunc = func; + pmeshCmdItem->userCbk = cbk; + pmeshCmdItem->userData = user_data; + pmeshCmdItem_s = (CMD_ITEM_S *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(CMD_ITEM_S)); + if (pmeshCmdItem_s == NULL) { + os_mem_free((uint8_t *)pmeshCmdItem); + printf("[BT_MESH] %s(): alloc pmeshCmdItem_s for mesh code %d fail !\r\n", __func__, mesh_code); + return NULL; + } + pmeshCmdItem_s->pmeshCmdItem = pmeshCmdItem; + pmeshCmdItem_s->semaDownTimeOut = 0; + pmeshCmdItem_s->userApiMode = puserItem->userApiMode; + if (bt_mesh_enqueue_cmd(&pmeshCmdItem_s->list, 0) == 1) { + printf("[BT_MESH] %s(): enqueue cmd for mesh code %d fail !\r\n", __func__, mesh_code); + os_mem_free((uint8_t *)pmeshCmdItem); + os_mem_free((uint8_t *)pmeshCmdItem_s); + return NULL; + } + + return pmeshCmdItem_s; +} + +uint8_t bt_mesh_cmdunreg(CMD_ITEM_S *pmesh_cmd_item_s) +{ + CMD_ITEM *pmeshCmdItem = NULL; + CMD_ITEM_S *pmeshCmdItem_s = pmesh_cmd_item_s; + + os_mutex_take(btMeshCmdPriv.cmdItemsMutex, 0xFFFFFFFF); + pmeshCmdItem = pmeshCmdItem_s->pmeshCmdItem; + os_mem_free((uint8_t *)pmeshCmdItem); + os_mem_free((uint8_t *)pmeshCmdItem_s); + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + + return 0; +} + +user_api_parse_result_t bt_mesh_set_user_cmd(uint16_t mesh_code, user_cmd_parse_value_t *pparse_value, user_cmd_cbk cbk, void *user_data) +{ + PUSER_ITEM puserItem = NULL; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + uint8_t ret = USER_API_RESULT_ERROR; + uint8_t user_api_mode = 0; + uint32_t time_out = 4000; + + puserItem = (PUSER_ITEM)user_data; + if (!puserItem) { + printf("[BT_MESH] %s(): puserItem is null!\r\n"); + return USER_API_RESULT_ERROR; + } + if (!btMeshCmdPriv.meshCmdEnable) { + printf("[BT_MESH] %s(): Mesh user command is disabled!\r\n"); + ret = USER_API_RESULT_NOT_ENABLE; + goto exit; + } +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshMode == BT_MESH_PROVISIONER) { + if (mesh_code == MAX_MESH_PROVISIONER_CMD || mesh_code > MAX_MESH_PROVISIONER_CMD ) { + printf("[BT_MESH] %s(): user cmd %d illegal !\r\n", __func__, mesh_code); + ret = USER_API_RESULT_NOT_FOUND; + goto exit; + } + } else { + printf("[BT_MESH] %s(): Error BT MESH mode %d \r\n",__func__); + ret = USER_API_RESULT_ERROR_MESH_MODE; + goto exit; + } +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + if (btMeshCmdPriv.meshMode == BT_MESH_DEVICE) { + if (mesh_code == MAX_MESH_DEVICE_CMD || mesh_code > MAX_MESH_DEVICE_CMD ) { + printf("[BT_MESH] %s(): user cmd %d illegal !\r\n", __func__, mesh_code); + ret = USER_API_RESULT_NOT_FOUND; + goto exit; + } + } else { + printf("[BT_MESH] %s(): Error BT MESH mode %d \r\n",__func__); + ret = USER_API_RESULT_ERROR_MESH_MODE; + goto exit; + } +#endif + user_api_mode = puserItem->userApiMode; + pmeshCmdItem_s = bt_mesh_cmdreg(mesh_code, pparse_value, bt_mesh_user_cmd, cbk, user_data); + if (!pmeshCmdItem_s) { + printf("[BT_MESH] %s(): user cmd %d regiter fail !\r\n", __func__, mesh_code); + ret = USER_API_RESULT_ERROR; + goto exit; + } +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + /* proivsioning takes more time */ + if (mesh_code == GEN_MESH_CODE(_prov)) { + time_out = 20000; + } else { + time_out = 4000; + } +#else + time_out = 4000; +#endif + if (user_api_mode == USER_API_SYNCH) { + if (os_sem_take(puserItem->userSema, time_out) == _FAIL) { + /* if timeout, puserItem will be free by mesh_cmd_thread or bt_mesh_user_cmd_cbk */ + os_mutex_take(btMeshCmdPriv.cmdItemsMutex, 0xFFFFFFFF); + pmeshCmdItem_s->semaDownTimeOut = 1; + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + printf("[BT_MESH] %s(): user cmd %d timeout !\r\n", __func__, mesh_code); + ret = USER_API_RESULT_TIMEOUT; + goto exit; + }else { + if (puserItem->userCmdResult) { + ret = USER_API_RESULT_OK; + goto exit; + } else { + printf("[BT_MESH] %s():mesh cmd = %d FAIL!\r\n", __func__, mesh_code); + ret = USER_API_RESULT_ERROR; + goto exit; + } + } + } else if (user_api_mode == USER_API_CMDLINE) { + if (os_sem_take(puserItem->cmdLineSema, time_out) == _FAIL) { + /* if timeout, puserItem will be free by mesh_cmd_thread or bt_mesh_user_cmd_cbk */ + os_mutex_take(btMeshCmdPriv.cmdItemsMutex, 0xFFFFFFFF); + pmeshCmdItem_s->semaDownTimeOut = 1; + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + printf("[BT_MESH] %s(): user cmd %d timeout !\r\n", __func__, mesh_code); + ret = USER_API_RESULT_TIMEOUT; + goto exit; + }else { + ret = USER_API_RESULT_OK; + goto exit; + } + } else { + /* if timeout, puserItem will be free by mesh_cmd_thread or bt_mesh_user_cmd_cbk */ + return USER_API_RESULT_OK; + } + +exit: + bt_mesh_free_hdl(puserItem); + return ret; +} + +user_api_parse_result_t bt_mesh_indication(uint16_t mesh_code, uint8_t state, void *pparam) +{ + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem; + uint8_t ret; + + if ((btMeshCmdPriv.meshMode != BT_MESH_PROVISIONER) && (btMeshCmdPriv.meshMode != BT_MESH_DEVICE)) { + printf("[BT_MESH] %s(): BT mesh indication is not eable !\r\n", __func__); + return USER_API_RESULT_OK; + } + //printf("\r\n %s()",__func__); + if (btMeshCmdIdPriv.userApiMode != USER_API_SYNCH) { + printf("[BT_MESH] %s(): BT mesh indication is not USER_API_SYNCH !\r\n", __func__); + return USER_API_RESULT_OK; + } + if (mesh_code != btMeshCmdIdPriv.meshCmdCode) { + printf("[BT_MESH] %s(): user cmd %d not found !\r\n", __func__, mesh_code); + //rtw_up_sema(&btMeshCmdPriv.meshThreadSema); + return USER_API_RESULT_INCORRECT_CODE;//Cause there are several cmd use the same in prov_cb + } +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + if (btMeshCmdIdPriv.meshCmdCode == GEN_MESH_CODE(_prov)) { + if ((plt_time_read_ms() < btMeshCmdIdPriv.startTime) || ((plt_time_read_ms() - btMeshCmdIdPriv.startTime) > 10000)) { + printf("[BT_MESH] %s(): BT mesh code start time is not reasonable !\r\n", __func__); + return USER_API_RESULT_TIMEOUT; + } + } else { + if ((plt_time_read_ms() < btMeshCmdIdPriv.startTime) || ((plt_time_read_ms() - btMeshCmdIdPriv.startTime) > 2000)) { + printf("[BT_MESH] %s(): BT mesh code start time is not reasonable !\r\n", __func__); + return USER_API_RESULT_TIMEOUT; + } + } +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + if ((plt_time_read_ms() < btMeshCmdIdPriv.startTime) || ((plt_time_read_ms() - btMeshCmdIdPriv.startTime) > 2000)) { + printf("[BT_MESH] %s(): BT mesh code start time is not reasonable !\r\n", __func__); + return USER_API_RESULT_TIMEOUT; + } +#endif + os_mutex_take(btMeshCmdPriv.cmdItemsMutex, 0xFFFFFFFF); + pmeshCmdItem_s = btMeshCmdIdPriv.pmeshCmdItem_s; + if (pmeshCmdItem_s->semaDownTimeOut) { + printf("[BT_MESH] %s(): mesh_code %d indication is timeout !\r\n", __func__, mesh_code); + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + return USER_API_RESULT_TIMEOUT; + } + if (!pmeshCmdItem_s->msgRecvFlag) { + printf("[BT_MESH] %s(): This indication is not matched !\r\n", __func__, mesh_code); + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + return USER_API_RESULT_ERROR; + } + if (pmeshCmdItem_s->pmeshCmdItem->userData && pmeshCmdItem_s->pmeshCmdItem->userCbk) { + /* whatever modification to state is user difined, ex: memcpy state to pmeshCmdItem_s->pmeshCmdItem->userData*/ + os_mutex_take(btMeshCmdPriv.ppvalueMutex, 0xFFFFFFFF); + puserItem = (USER_ITEM *)pmeshCmdItem_s->pmeshCmdItem->userData; + puserItem->userCmdResult = state; + printf("\r\n %s() userCmdResult = %d",__func__,puserItem->userCmdResult); + puserItem->userParam = pparam; + ret = pmeshCmdItem_s->pmeshCmdItem->userCbk(mesh_code, (void *)pmeshCmdItem_s); + os_mutex_give(btMeshCmdPriv.ppvalueMutex); + if (ret == USER_API_RESULT_INDICATION_NOT_MATCHED) { + printf("[BT_MESH] %s(): user cmd %d not matched !\r\n", __func__, mesh_code); + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + return USER_API_RESULT_ERROR; + } + } else { + printf("[BT_MESH] %s(): user cmd %d pmeshCmdItem_s->pmeshCmdItem->userData is NULL !\r\n", __func__, mesh_code); + } + os_mutex_give(btMeshCmdPriv.cmdItemsMutex); + if (!btMeshCmdIdPriv.semaDownTimeOut) { + os_sem_give(btMeshCmdPriv.meshThreadSema); + } else { + printf("[BT_MESH] %s(): user cmd %d timeout !\r\n", __func__, mesh_code); + } + + return USER_API_RESULT_OK; +} + +PUSER_ITEM bt_mesh_alloc_hdl(uint8_t user_api_mode) +{ + PUSER_ITEM puserItem; + + if (!btMeshCmdPriv.meshCmdEnable) { + printf("[BT_MESH] Mesh user command is disabled!\r\n"); + return NULL; + } + puserItem = (PUSER_ITEM)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(USER_ITEM)); + if (!puserItem) { + printf("[BT_MESH] PUSER_ITEM alloc fail!\r\n"); + return NULL; + } + puserItem->userApiMode = user_api_mode; + puserItem->pparseValue = (user_cmd_parse_value_t *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(user_cmd_parse_value_t)); + if (!puserItem->pparseValue) { + printf("[BT_MESH] puserItem->pparse_value alloc fail!\r\n"); + os_mem_free((uint8_t *)puserItem); + return NULL; + } + if (user_api_mode == USER_API_SYNCH) { + os_sem_create(&puserItem->userSema, 0, 0xffffffff); + if (puserItem->userSema == NULL) { + printf("[BT_MESH] puserItem->user_sema init fail!\r\n"); + os_mem_free((uint8_t *)puserItem->pparseValue); + os_mem_free((uint8_t *)puserItem); + return NULL; + } + } + if (user_api_mode == USER_API_CMDLINE) { + os_sem_create(&puserItem->cmdLineSema, 0, 0xffffffff); + if (puserItem->cmdLineSema == NULL) { + printf("[BT_MESH] puserItem->cmdLineSema init fail!\r\n"); + os_mem_free((uint8_t *)puserItem->pparseValue); + os_mem_free((uint8_t *)puserItem); + return NULL; + } + } + + return puserItem; +} + +void bt_mesh_free_hdl(PUSER_ITEM puser_item) +{ + PUSER_ITEM puserItem; + + puserItem = puser_item; + os_mutex_take(btMeshCmdPriv.ppvalueMutex, 0xFFFFFFFF); + if (puserItem->userApiMode == USER_API_SYNCH) { + os_sem_delete(puserItem->userSema); + } else if (puserItem->userApiMode == USER_API_CMDLINE) { + os_sem_delete(puserItem->cmdLineSema); + } + os_mem_free((uint8_t *)puserItem->pparseValue); + os_mem_free((uint8_t *)puserItem); + os_mutex_give(btMeshCmdPriv.ppvalueMutex); +} + +static void mesh_user_cmd_list(void) +{ + uint8_t i = 0; + + /* find command in table */ + for (i = 0; i < sizeof(mesh_cmd_table) / sizeof(mesh_cmd_table[0]); i ++) + { + data_uart_debug(mesh_cmd_table[i].poption); + data_uart_debug(" *"); + data_uart_debug(mesh_cmd_table[i].phelp); + }; + + return; +} + +static user_cmd_parse_result_t mesh_user_cmd_parse(user_cmd_parse_value_t *pparse_value, char *mesh_user_cmd_line) +{ + int32_t i; + user_cmd_parse_result_t Result; + char *p, *q; + + /* clear all results */ + Result = USER_CMD_RESULT_OK; + pparse_value->pcommand = NULL; + pparse_value->para_count = 0; + for (i = 0 ; i < USER_CMD_MAX_PARAMETERS; i ++) + { + pparse_value->pparameter[i] = NULL; + pparse_value->dw_parameter[i] = 0; + } + /* Parse line */ + p = mesh_user_cmd_line; + /*ignore leading spaces */ + p = user_cmd_skip_spaces(p); + if (*p == '\0') /* empty command line ? */ + { + Result = USER_CMD_RESULT_EMPTY_CMD_LINE; + } + else + { + /* find end of word */ + q = user_cmd_find_end_of_word(p); + if (p == q) /* empty command line ? */ + { + Result = USER_CMD_RESULT_EMPTY_CMD_LINE; + } + else /* command found */ + { + pparse_value->pcommand = p; + *q = '\0'; /* mark end of command */ + p = q + 1; + /* parse parameters */ + if (*p != '\0') /* end of line ? */ + { + uint8_t j = 0; + do + { + uint32_t d; + /* ignore leading spaces */ + p = user_cmd_skip_spaces(p); + d = user_cmd_string2uint32(p); + pparse_value->pparameter[j] = p; + pparse_value->dw_parameter[j++] = d; + if (j >= USER_CMD_MAX_PARAMETERS) + { + break; + } + /* find next parameter */ + p = user_cmd_find_end_of_word(p); + *p++ = '\0'; /* mark end of parameter */ + } + while (*p != '\0'); + pparse_value->para_count = j; + } + } + } + + return (Result); +} + +void bt_mesh_param_user_cmd(unsigned int argc, char **argv) +{ + uint8_t i ,j ,k = 0; + uint8_t found = 0; + char meshUserCmdLine[USER_CMD_MAX_COMMAND_LINE + 2]; + PUSER_ITEM puserItem = NULL; + + if (strcmp(argv[0], "pro") == 0) { + if (btMeshCmdPriv.meshMode != BT_MESH_PROVISIONER) { + printf("[BT_MESH] Currently mode is not provisioner\r\n"); + return; + } + } else if (strcmp(argv[0], "dev") == 0) { + if (btMeshCmdPriv.meshMode != BT_MESH_DEVICE) { + printf("[BT_MESH] Currently mode is not device\r\n"); + return; + } + } + if (strcmp((const char *)argv[1], (const char *)"?") == 0) { + mesh_user_cmd_list(); + return; + } + for (i = 0; i < sizeof(mesh_cmd_table) / sizeof(mesh_cmd_table[0]); i ++) { + if (strcmp((const char *)argv[1], (const char *)(mesh_cmd_table[i].pcommand)) == 0) { + if (argc > 2) { + if (strcmp(argv[2], "?") == 0) { + data_uart_debug(mesh_cmd_table[i].poption); + data_uart_debug(" *"); + data_uart_debug(mesh_cmd_table[i].phelp); + return; + } + } + k = 0; + memset(meshUserCmdLine, 0, sizeof(meshUserCmdLine)); + for (j = 1; j < argc; j ++) { + if (strlen(argv[j]) < (size_t)(USER_CMD_MAX_COMMAND_LINE - k)) { + memcpy(&meshUserCmdLine[k], argv[j], strlen(argv[j])); + k += strlen(argv[j]); + strcpy(&meshUserCmdLine[k++], " "); + } else { + printf("[BT_MESH] No Enough buffer for user cmd\r\n"); + return; + } + } + puserItem = bt_mesh_alloc_hdl(USER_API_CMDLINE); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return; + } + mesh_user_cmd_parse(puserItem->pparseValue, meshUserCmdLine); + bt_mesh_set_user_cmd(mesh_cmd_table[i].meshCode, puserItem->pparseValue, NULL, puserItem); + found = 1; + break; + } + } + if (!found) { + printf("\r\n [BT_MESH] unknown command %s", argv[1]); + } + + return; +} + +extern char *_strncat(char *dest, char const *src, size_t count); + +void user_cmd_array2string(uint8_t *buf, unsigned int buflen, char *out) +{ + /* larger than 32 for "/0" */ + char strBuf[40] = {0}; + char pbuf[2]; + uint8_t i; + + if (buflen >16) { + printf("\r\n [BT_MESH] input pbuf buflen %d is to large", buflen); + return; + } + for(i = 0; i < buflen; i++) + { + sprintf(pbuf, "%02X", buf[i]); + strncat(strBuf, pbuf, 2); + } + strncpy(out, strBuf, buflen * 2); +} + +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) +#include "firmware_distribution.h" +#include "dfudep_service.h" + +#if defined(MESH_DFU) && MESH_DFU +uint8_t metadata_client[] = { + 0x1F, + 0xEE +}; + +typedef uint32_t (*fw_image_data_get_t)(uint32_t len, uint8_t *pout); +extern bool dfu_dist_start(uint16_t dst, uint16_t app_key_index, uint16_t update_timeout_base, + uint8_t *pfw_metadata, uint8_t metadata_len, + uint32_t fw_image_size, fw_image_data_get_t fw_image_data_get); + +extern uint8_t dfu_dist_model_enabled; + +void bt_mesh_dfu_param_user_cmd(unsigned int argc, char **argv) +{ + uint16_t dst; + uint16_t app_key_index; + uint16_t update_timeout_base; + uint32_t blob_size; + + if (!dfu_dist_model_enabled) { + printf("[BT_MESH] device firmware update model is not enabled \r\n"); + return; + } + if (strcmp((const char *)argv[1], (const char *)"?") == 0) { + printf("[BT_MESH] ATBM=mesh_ota,dst,app_key_index,update_timeout_base,blob_size \r\n"); + printf("[BT_MESH] Start firmware update procedure to node \r\n"); + return; + } + if (argc != 5) { + printf("[BT_MESH] Param num is incorrect, Please tap in >> ATBM = mesh_ota,? << for help \r\n"); + return; + } + dst = (uint16_t)user_cmd_string2uint32(argv[1]); + app_key_index = (uint16_t)user_cmd_string2uint32(argv[2]); + update_timeout_base = (uint16_t)user_cmd_string2uint32(argv[3]); + blob_size = (uint32_t)user_cmd_string2uint32(argv[4]); + dfu_dist_start(dst, app_key_index, update_timeout_base, (uint8_t *)metadata_client, sizeof(metadata_client), blob_size, + (fw_image_data_get_t)dfu_fw_image_data_get); +} +#endif +#endif +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.h new file mode 100644 index 00000000..e02eb2f3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.h @@ -0,0 +1,309 @@ +/** +***************************************************************************************** +* Copyright(c) 2019, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_mesh_user_api.h + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author sherman + * @date 2019-09-16 + * @version v1.0 + * ************************************************************************************* + */ +#ifndef _BT_MESH_USER_API_H_ +#define _BT_MESH_USER_API_H_ + +#include "mesh_user_cmd_parse.h" +#include "provisioner_cmd.h" +#include "device_cmd.h" +#include "osdep_service.h" +#include "os_task.h" +#include "platform_os.h" +#include "mesh_data_uart.h" +#include "app_msg.h" +#include "mesh_config.h" + +#define BT_MESH_PROVISIONER 1 +#define BT_MESH_DEVICE 2 + +#define GEN_MESH_CODE(cmd) cmd ## _cmd_ +#define BT_MESH_CMD_ID_PRIV_MOD(cmd, pointer, mode, timeout, start_time) do {\ + btMeshCmdIdPriv.meshCmdCode = cmd;\ + btMeshCmdIdPriv.pmeshCmdItem_s = pointer;\ + btMeshCmdIdPriv.userApiMode = mode;\ + btMeshCmdIdPriv.semaDownTimeOut = timeout;\ + btMeshCmdIdPriv.startTime = start_time;\ + }while(0) +#define PARAM_MESH_CODE(command, option, help, mesh_code) {command, option, help, mesh_code}, + +/** @brief declare function for bt mesh cmd thread*/ +typedef int (*bt_mesh_func)(uint16_t mesh_code, void *pmeshCmdItem_s); +/** @brief declare function for user call back*/ +typedef uint8_t (*user_cmd_cbk)(uint16_t mesh_code, void *user_data); + +/** @brief Indicate the result of user command */ +enum bt_mesh_op_result +{ + BT_MESH_USER_CMD_FAIL , + BT_MESH_USER_CMD_SUCCESS +}; + +/** @brief Indicate the result of goo command */ +enum bt_mesh_goo_result +{ + BT_MESH_GOO_OFF , + BT_MESH_GOO_ON +}; + +/** @brief Indicate the result of user api */ +typedef enum +{ + USER_API_RESULT_OK, + USER_API_RESULT_NOT_FOUND, + USER_API_RESULT_ERROR, + USER_API_RESULT_TIMEOUT, + USER_API_RESULT_INCORRECT_CODE, + USER_API_RESULT_ERROR_MESH_MODE, + USER_API_RESULT_NOT_ENABLE, + USER_API_RESULT_INDICATION_NOT_MATCHED +} user_api_parse_result_t; + +/** @brief Indicate the sync mode of user api */ +typedef enum { + USER_API_ASYNCH , + USER_API_SYNCH , + USER_API_CMDLINE , + USER_API_DEFAULT_MODE +} BT_MESH_API_SYNCHCONFIG; + +/** @brief Param string cmd to mesh code */ +typedef struct _mesh_cmd_entry { + char *pcommand; + char *poption; + char *phelp; + uint16_t meshCode; +} mesh_cmd_entry; + +/** @brief bt mesh command private struct */ +typedef struct meshCmdModInfo +{ + struct list_head meshCmdList; //!< List contains user command. + uint8_t meshMode; //!< Indicate currently mesh mode(provisioner/device). + uint8_t cmdListNum; //!< user command num included in .meshCmdList. + uint8_t cmdTransmittedNum; //!< user command num which have been sent to mesh stack. + uint8_t meshCmdEnable; //!< user command enable flag. + void *cmdMutex; //!< mesh command private struct mutex. + void *ppvalueMutex; //!< pparseValue mutex. + void *cmdItemsMutex; //!< meshCmdItem_s mutex. + void *meshThreadSema; //!< sema for cmd thread according to current meshMode. +} CMD_MOD_INFO_S; + +/** @brief bt mesh cmd thread private struct */ +typedef struct meshCmdItem +{ + uint16_t meshCmdCode; //!< user command code index. + user_cmd_parse_value_t *pparseValue; //!< pointer of parameter array. + bt_mesh_func meshFunc; //!< func will be called in cmd thread according to current meshMode. + user_cmd_cbk userCbk; //!< suer callback will be involked in bt_mesh_indication if not NULL. + void *userData; //!< pointer os user private data struct. +} CMD_ITEM; + +/** @brief bt mesh user command struct */ +struct meshUserItem +{ + uint8_t userCmdResult; //!< indicate results of command to upper layer. + uint8_t userApiMode; //!< 2: cmd line mode 1: sync mode 0: async mode. + void *userSema; //!< sema for sync mode. + void *cmdLineSema; //!< sema for command line mode. + user_cmd_parse_value_t *pparseValue; //!< pointer of parameter array. + void *userParam; //!< pointer of user parameter. +}; + +/** @brief typedef struct meshUserItem */ +typedef struct meshUserItem USER_ITEM, *PUSER_ITEM; + +/** @brief bt mesh cmd thread private struct*/ +typedef struct meshCmdItemSet +{ + struct list_head list; //!< list of .pmeshCmdItem. + uint8_t semaDownTimeOut; //!< wait time out for sync mode. + uint8_t userApiMode; //!< 2: cmd line mode 1: sync mode 0: async mode. + uint8_t msgRecvFlag; //!< indicate the callback has received of previous message. + CMD_ITEM *pmeshCmdItem; //!< pointer of meshCmdItem. +} CMD_ITEM_S; + +/** @brief bt mesh indication private struct */ +typedef struct meshCmdIndicationPriv +{ + CMD_ITEM_S *pmeshCmdItem_s; //!< pointer of meshCmdItem. + uint8_t semaDownTimeOut; //!< wait time out for sync mode. + uint16_t meshCmdCode; //!< mesh code index. + uint32_t userApiMode; //!< 2: cmd line mode 1: sync mode 0: async mode. + uint32_t startTime; //!< record the start time for mesh code in process. +} INDICATION_ITEM; + +/** @brief bt mesh task private struct */ +struct mesh_task_struct { + void *task; /* I: workqueue thread */ + void *wakeup_sema; /* for internal use only */ + void *terminate_sema; /* for internal use only */ + u32 blocked; /* for internal use only */ +}; + +/** + * @brief call back handler of bt mesh io msg + * + * @param[in] io_msg: input io msg struct value + * @return none + */ +void bt_mesh_io_msg_handler(T_IO_MSG io_msg); + +/** + * @brief function configure io_msg and call bt_mesh_send_io_msg + * + * @param[in] mesh_code: mesh code index + * @param[in] pmesh_cmd_item_s: pointer of meshCmdItem_s + * @return none + */ +int bt_mesh_user_cmd(uint16_t mesh_code, void *pmesh_cmd_item_s); + +/** + * @brief enqueue user command to cmd list and wake up bt mesh cmd threads + * + * @param[in] queue: user command list + * @param[in] head_or_tail: 1 for head, 0 for tail + * @return 0 for success 1 for fail + */ +uint8_t bt_mesh_enqueue_cmd(struct list_head *queue, uint8_t head_or_tail); + +/** + * @brief dequeue user command from cmd list + * + * @return list of dequeue command + */ +struct list_head *bt_mesh_dequeue_cmd(void); + +/** + * @brief search handler included in provisionercmds/devicecmds according to mesh_code index + * + * @param[in] mesh_code: mesh code index + * @param[in] pmesh_cmd_item_s: pointer of meshCmdItem_s + * @return result of calling handler + */ +uint8_t bt_mesh_user_cmd_hdl(uint16_t mesh_code, CMD_ITEM_S *pmesh_cmd_item_s); + +/** + * @brief allocate struct value for user and configure structure member with the input parameters + * + * @param[in] mesh_code: mesh code index + * @param[in] pparse_value: pointer of parameter array + * @param[in] func: functions will be involked in bt mesh cmd thread + * @param[in] cbk: user callback function + * @param[in] user_data: pointer of user's private structure + * @return CMD_ITEM_S + */ +CMD_ITEM_S* bt_mesh_cmdreg(uint16_t mesh_code, user_cmd_parse_value_t *pparse_value, bt_mesh_func func, user_cmd_cbk cbk, void *user_data); + +/** + * @brief free struct value + * + * @param[in] pmesh_cmd_item_s: pointer to previous allocated memory + * @return 0 + */ +uint8_t bt_mesh_cmdunreg(CMD_ITEM_S *pmesh_cmd_item_s); + +/** + * @brief set user command + * + * @param[in] mesh_code: mesh code index + * @param[in] pparse_value: pointer of parameter array + * @param[in] func: functions will be involked in bt mesh cmd thread + * @param[in] cbk: user callback function + * @param[in] user_data: pointer of user's private structure + * @return user_api_parse_result_t + */ +user_api_parse_result_t bt_mesh_set_user_cmd(uint16_t mesh_code, user_cmd_parse_value_t *pparse_value, user_cmd_cbk cbk, void *user_data); + +/** + * @brief indicate mesh command result + * + * @param[in] mesh_code: mesh code index + * @param[in] state: result + * @param[in] pparam: parameters need to be indicated + * @return user_api_parse_result_t + */ +user_api_parse_result_t bt_mesh_indication(uint16_t mesh_code, uint8_t state, void *pparam); + +/** + * @brief allocate PUSER_ITEM for user to configure + * + * @param[in] synch_enable: 1 for synch, 0 for asynch + * @return pointer to PUSER_ITEM + */ +PUSER_ITEM bt_mesh_alloc_hdl(uint8_t synch_enable); + +/** + * @brief free allocated PUSER_ITEM + * + * @param[in] puser_item: pointer to PUSER_ITEM + * @return none + */ +void bt_mesh_free_hdl(PUSER_ITEM puser_item); + +/** + * @brief Read uint8_t and convert to string. + * + * @param[in] buf: address of uint8_t array. + * @param[in] buflen: num of array. + * @param[in] out: target string buf. + * @return +*/ +void user_cmd_array2string(uint8_t *buf, unsigned int buflen, char *out); + +/** + * @brief Read ASCII string and convert to uint32_t. + * + * @param[in] p + * @return +*/ +extern uint32_t user_cmd_string2uint32(char *p); + +/** + * @brief Skip white spaces in buffer. + * + * @param[in] buffer + * @return pointer to skipped white spaces' new buffer. +*/ +extern char *user_cmd_skip_spaces(char *buffer); + +/** + * @brief Find end of a word. + * + * @param[in] buffer + * @return +*/ +extern char *user_cmd_find_end_of_word(char *buffer); + +/** + * @brief pram user cmd. + * + * @param[in] argc + * @param[in] argv + * @return +*/ +void bt_mesh_param_user_cmd(unsigned int argc, char **argv); + +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) +/** + * @brief pram mesh ota user cmd. + * + * @param[in] argc + * @param[in] argv + * @return +*/ +void bt_mesh_dfu_param_user_cmd(unsigned int argc, char **argv); +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.c new file mode 100644 index 00000000..8408a7dd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.c @@ -0,0 +1,207 @@ +/** +***************************************************************************************** +* Copyright(c) 2019, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_mesh_device_api.c + * @brief Source file for device cmd. + * @details User command interfaces. + * @author sherman + * @date 2019-09-16 + * @version v1.0 + * ************************************************************************************* + */ +#include "bt_mesh_device_api.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#if (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + +struct mesh_task_struct meshDeviceCmdThread; +extern CMD_MOD_INFO_S btMeshCmdPriv; +extern INDICATION_ITEM btMeshCmdIdPriv; + +thread_return mesh_device_cmd_thread(thread_context context) +{ + /* avoid gcc compile warning */ + (void)context; + uint8_t count = 0; + uint32_t time_out = 2000; + uint16_t mesh_code = MAX_MESH_DEVICE_CMD; + CMD_ITEM *pmeshCmdItem = NULL; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + uint8_t userApiMode = USER_API_DEFAULT_MODE; + //user_cmd_parse_value_t *pparse_value = NULL; + struct list_head *plist; + struct mesh_task_struct *pcmdtask = &(meshDeviceCmdThread); + + printf("[BT_MESH] %s(): mesh cmd thread enter !\r\n", __func__); + + while(1) + { + if (os_sem_take(pcmdtask->wakeup_sema, 0xFFFFFFFF) == _FAIL) { + printf("[BT_MESH] %s(): down wakeup_sema fail !\r\n", __func__); + break; + } + if (pcmdtask->blocked == _TRUE) { + /* wait mesh stack handling mesh cmds */ + while (btMeshCmdPriv.cmdTransmittedNum) { + printf(" waiting mesh command's implementation by mesh stack \r\n"); + os_delay(100); + } + printf("[BT_MESH] %s(): blocked(%d) !\r\n", __func__, pcmdtask->blocked); + break; + } + plist = bt_mesh_dequeue_cmd(); + if (!plist) { + printf("[BT_MESH] %s(): bt_mesh_dequeue_cmd fail !\r\n", __func__); + goto _next; + } + pmeshCmdItem_s = (CMD_ITEM_S *)plist; + pmeshCmdItem = pmeshCmdItem_s->pmeshCmdItem; + mesh_code = pmeshCmdItem->meshCmdCode; + //pparse_value = pmeshCmdItem->pparseValue; + puserItem = (PUSER_ITEM)pmeshCmdItem->userData; + userApiMode = pmeshCmdItem_s->userApiMode; + if (pmeshCmdItem_s->semaDownTimeOut) { + count = 0; + printf("[BT_MESH] %s(): mesh cmd %d has already timeout !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + goto _next; + } + BT_MESH_CMD_ID_PRIV_MOD(mesh_code, pmeshCmdItem_s, puserItem->userApiMode, 1, plt_time_read_ms()); + if (pmeshCmdItem_s->pmeshCmdItem->meshFunc) { + if (pmeshCmdItem_s->pmeshCmdItem->meshFunc(mesh_code, pmeshCmdItem_s)) { + if (userApiMode == USER_API_ASYNCH) { + bt_mesh_free_hdl(puserItem); + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + goto _next; + } else if (userApiMode == USER_API_CMDLINE) { + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + goto _next; + } + } + if (userApiMode != USER_API_SYNCH) { + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + goto _next; + } + btMeshCmdIdPriv.semaDownTimeOut = 0; + time_out = 2000; + /* guarantee the integrity of each mesh_code cmd */ + if (os_sem_take(btMeshCmdPriv.meshThreadSema, time_out) == _FAIL) { + count++; + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + /* guarantee that previous msg has already been handled */ + while (!pmeshCmdItem_s->msgRecvFlag) { + printf("[BT_MESH] %s(): Wait bt_mesh_user_cmd_hdl implementation %d, %d !\r\n", __func__, mesh_code, btMeshCmdPriv.cmdTransmittedNum); + os_delay(100); + } + if (count == BT_MESH_DEV_CMD_RETRY_COUNT) { + count = 0; + printf("[BT_MESH] %s(): down sema timeout mesh cmd = %d !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } else { + /* enqueue to head for another try */ + printf("\r\n enqueue again 0x%x \r\n", plist); + if (bt_mesh_enqueue_cmd(plist, 1) == 1) { + printf("[BT_MESH] %s(): enqueue cmd for mesh code %d fail !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } + } + }else { + count = 0; + if (pmeshCmdItem_s->semaDownTimeOut) { + printf("[BT_MESH] %s(): mesh_code %d indication is timeout !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } else { + os_sem_give(puserItem->userSema); + printf("[BT_MESH] %s():mesh cmd = %d puserItem->userCmdResult = %d !\r\n", __func__, mesh_code, puserItem->userCmdResult); + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + } + } + } else { + printf("[BT_MESH] %s(): meshFunc is NULL mesh_code = %d !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + } +_next: + /* make sure os shedule can switch out */ + os_delay(10); + } + /* prevent previous cmd involking bt_mesh_indication */ + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + /* free all pmeshCmdItem_s resources */ + do{ + plist = bt_mesh_dequeue_cmd(); + if (plist == NULL) { + break; + } + bt_mesh_cmdunreg((CMD_ITEM_S *)plist); + }while(1); + os_sem_give(pcmdtask->terminate_sema); + printf("[BT_MESH] %s(): mesh cmd thread exit !\r\n", __func__); + os_task_delete(NULL); +} + +uint8_t bt_mesh_device_api_init(void) +{ + if (btMeshCmdPriv.meshMode == BT_MESH_DEVICE) { + printf("[BT_MESH] %s(): MESH DEVICE is already running !\r\n", __func__); + return 1; + } else if (btMeshCmdPriv.meshMode == BT_MESH_PROVISIONER) { + printf("[BT_MESH] %s(): MESH PROVISIONER is running, need deinitialization firstly !\r\n", __func__); + return 1; + } + rtw_init_listhead(&btMeshCmdPriv.meshCmdList); + os_mutex_create(&btMeshCmdPriv.cmdMutex); + os_mutex_create(&btMeshCmdPriv.ppvalueMutex); + os_mutex_create(&btMeshCmdPriv.cmdItemsMutex); + os_sem_create(&btMeshCmdPriv.meshThreadSema, 0, 0xffffffff); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + meshDeviceCmdThread.blocked = 0; + os_sem_create(&meshDeviceCmdThread.wakeup_sema, 0, 0xffffffff); + os_sem_create(&meshDeviceCmdThread.terminate_sema, 0, 0xffffffff); + if (os_task_create(&meshDeviceCmdThread.task, "mesh_device_cmd_thread", mesh_device_cmd_thread, + NULL, 1024, 3) != true) { + meshDeviceCmdThread.blocked = 1; + os_sem_delete(meshDeviceCmdThread.wakeup_sema); + os_sem_delete(meshDeviceCmdThread.terminate_sema); + printf("[BT_MESH] %s(): create mesh_device_cmd_thread fail !\r\n", __func__); + os_mutex_delete(btMeshCmdPriv.cmdMutex); + os_sem_delete(btMeshCmdPriv.meshThreadSema); + + return 1; + } + btMeshCmdPriv.cmdListNum = 0; + btMeshCmdPriv.cmdTransmittedNum = 0; + btMeshCmdPriv.meshMode = BT_MESH_DEVICE; + btMeshCmdPriv.meshCmdEnable = 1; + + return 0; +} + +void bt_mesh_device_api_deinit(void) +{ + if (btMeshCmdPriv.meshMode != BT_MESH_DEVICE) { + printf("[BT_MESH] %s(): MESH DEVICE is not running !\r\n", __func__); + return; + } + btMeshCmdPriv.meshCmdEnable = 0; + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_DEVICE_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + meshDeviceCmdThread.blocked = 1; + os_sem_give(meshDeviceCmdThread.wakeup_sema); + os_sem_take(meshDeviceCmdThread.terminate_sema, 0xFFFFFFFF); + btMeshCmdPriv.meshMode = 0; + os_sem_delete(meshDeviceCmdThread.wakeup_sema); + os_sem_delete(meshDeviceCmdThread.terminate_sema); + os_mutex_delete(btMeshCmdPriv.cmdMutex); + os_mutex_delete(btMeshCmdPriv.ppvalueMutex); + os_mutex_delete(btMeshCmdPriv.cmdItemsMutex); + os_sem_delete(btMeshCmdPriv.meshThreadSema); +} + +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.h new file mode 100644 index 00000000..6f1b619b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.h @@ -0,0 +1,64 @@ +/** +***************************************************************************************** +* Copyright(c) 2019, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_mesh_device_api.h + * @brief Source file for device cmd. + * @details User command interfaces. + * @author sherman + * @date 2019-09-16 + * @version v1.0 + * ************************************************************************************* + */ +#ifndef _BT_MESH_DEV_API_H_ +#define _BT_MESH_DEV_API_H_ + +#include "bt_mesh_user_api.h" + +#define BT_MESH_DEV_CMD_RETRY_COUNT 2 + +/** @brief bt mesh device command table */ +enum bt_mesh_device_cmd +{ + GEN_MESH_CODE(_node_reset) , /*0*/ + GEN_MESH_CODE(_prov_capa_set) , +#if MESH_LPN + GEN_MESH_CODE(_lpn_init) , + GEN_MESH_CODE(_lpn_deinit) , + GEN_MESH_CODE(_lpn_req) , + GEN_MESH_CODE(_lpn_sub) , + GEN_MESH_CODE(_lpn_clear) , /*5*/ +#endif +#if MESH_FN + GEN_MESH_CODE(_fn_init) , + GEN_MESH_CODE(_fn_deinit) , +#endif + GEN_MESH_CODE(_data_transmission_notify) , + GEN_MESH_CODE(_generic_on_off_publish) , + GEN_MESH_CODE(_datatrans_write) , + GEN_MESH_CODE(_datatrans_read) , + GEN_MESH_CODE(_connect) , + GEN_MESH_CODE(_disconnect) , + GEN_MESH_CODE(_list) , + GEN_MESH_CODE(_dev_info_show) , + + MAX_MESH_DEVICE_CMD +}; + +/** + * @brief initialize bt mesh device api + * + * @return 1: success 0: fail + */ +uint8_t bt_mesh_device_api_init(void); + +/** + * @brief deinitialize bt mesh device api + * + * @return none + */ +void bt_mesh_device_api_deinit(void); + +#endif + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.c new file mode 100644 index 00000000..4573a554 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.c @@ -0,0 +1,111 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file device_idle_check.c + * @brief Source file of idel check function specific for scenario together with wifi. + * @details User command interfaces. + * @author sherman_sun + * @date 2020_11_06 + * @version v1.0 + * ************************************************************************************* + */ + +#include "device_idle_check.h" + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK +#define ACCESS_DATA_MONITOR_INTERVAL 2000 //2s +#define ACCESS_DATA_MONITOR_THRESHOLD 14 //monitor timeout = (ACCESS_DATA_MONITOR_THRESHOLD+1) * ACCESS_DATA_MONITOR_INTERVAL + +extern bool mesh_initial_state; +extern uint8_t mesh_device_conn_state; +uint8_t mesh_access_data_flow_state = 1; +uint8_t mesh_access_data_received = 0; +plt_timer_t bt_mesh_access_data_flow_monitor_timer = NULL; + +void bt_mesh_access_data_flow_monitor_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + static uint8_t mesh_access_msg_dec_count = 0; + + if (!mesh_access_data_received) { + if (++mesh_access_msg_dec_count > ACCESS_DATA_MONITOR_THRESHOLD) { + mesh_access_data_flow_state = 0; + //prevent mesh_access_msg_dec_count overflow + mesh_access_msg_dec_count = ACCESS_DATA_MONITOR_THRESHOLD; + } + //printf("\r\n Enter bt_mesh_access_data_flow_monitor_timer_handler mesh_access_msg_dec_count = %d \r\n",mesh_access_msg_dec_count); + } else { + mesh_access_data_received = 0; + mesh_access_msg_dec_count = 0; + mesh_access_data_flow_state = 1; + //printf("\r\n Enter bt_mesh_access_data_flow_monitor_timer_handler mesh_access_msg_dec_count = %d \r\n",mesh_access_msg_dec_count); + } + + plt_timer_change_period(bt_mesh_access_data_flow_monitor_timer, ACCESS_DATA_MONITOR_INTERVAL, 0xFFFFFFFF); +} + +int32_t bt_mesh_access_process(mesh_msg_p pmesh_msg) +{ + mesh_access_data_received = 1; + //printf("\r\n Enter bt_mesh_access_process \r\n"); + return 0; +} + +uint8_t bt_mesh_idle_check_init(void) +{ + //register mesh access detached function + access_set_dispatch_preprocess((dispatch_preprocess_t)bt_mesh_access_process); + bt_mesh_access_data_flow_monitor_timer = plt_timer_create("bt_mesh_access_data_flow_monitor_timer", 0xFFFFFFFF, FALSE, NULL, bt_mesh_access_data_flow_monitor_timer_handler); + if (!bt_mesh_access_data_flow_monitor_timer) { + printf("[BT Mesh Device] Create adv timer failed\n\r"); + return 0; + } + plt_timer_change_period(bt_mesh_access_data_flow_monitor_timer, 2000, 0xFFFFFFFF); + + return 1; +} + +uint8_t bt_mesh_idle_check_deinit(void) +{ + plt_timer_delete(bt_mesh_access_data_flow_monitor_timer, 0xFFFFFFFF); + bt_mesh_access_data_flow_monitor_timer = NULL; + + return 1; +} + +device_idle_check_t bt_mesh_idle_check(void) +{ + device_idle_check_t ret = DEVICE_IDLE_CHECK_FALSE; + + if (!mesh_initial_state) { + //check whether mesh is inited + printf("[BT_MESH] %s(): Please init mesh firstly \r\n",__func__); + goto exit; + } + + if (!mesh_node.node_state) { + //mesh device havn't been provisioned to a mesh net + printf("[BT_MESH] %s(): Please do provisioning firstly \r\n",__func__); + goto exit; + } + + if (mesh_device_conn_state) { + //mesh device is connecting to another device through gatt + printf("[BT_MESH] %s(): Please disconnect gatt connection \r\n",__func__); + goto exit; + } + + if (mesh_access_data_flow_state) { + //mesh access has data flow + printf("[BT_MESH] %s(): Cannot enter power save cause mesh message interaction \r\n",__func__); + goto exit; + } + + ret = DEVICE_IDLE_CHECK_TRUE; + +exit: + return ret; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.h new file mode 100644 index 00000000..1b006fac --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.h @@ -0,0 +1,52 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file device_idle_check.h + * @brief Source file of idle check function specific for scenario together with wifi. + * @details User command interfaces. + * @author sherman_sun + * @date 2020_11_06 + * @version v1.0 + * ************************************************************************************* + */ +#ifndef _DEVICE_IDLE_CHECK_H_ +#define _DEVICE_IDLE_CHECK_H_ + +#include "mesh_api.h" +#include "platform_os.h" + +/** @brief Indicate the result of power save enable */ +typedef enum +{ + DEVICE_IDLE_CHECK_FALSE, + DEVICE_IDLE_CHECK_TRUE +} device_idle_check_t; + +/** + * @for init resources of bt mesh idle check. + * + * @param[in] none + * @return result 1: success 0: fail + */ +uint8_t bt_mesh_idle_check_init(void); + +/** + * @for deinit resources of bt mesh idle check. + * + * @param[in] none + * @return result 1: success 0: fail + */ +uint8_t bt_mesh_idle_check_deinit(void); + +/** + * @get idle state of bt mesh. + * + * @param[in] none + * @return result of device_enter_ps_enable_t + */ +device_idle_check_t bt_mesh_idle_check(void); + +#endif + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.c new file mode 100644 index 00000000..7b618e9b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.c @@ -0,0 +1,211 @@ +/** +***************************************************************************************** +* Copyright(c) 2019, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_mesh_provisioner_api.c + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author sherman + * @date 2019-09-16 + * @version v1.0 + * ************************************************************************************* + */ +#include "bt_mesh_provisioner_api.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + +struct mesh_task_struct meshProvisionerCmdThread; +extern CMD_MOD_INFO_S btMeshCmdPriv; +extern INDICATION_ITEM btMeshCmdIdPriv; + +thread_return mesh_provisioner_cmd_thread(thread_context context) +{ + /* avoid gcc compile warning */ + (void)context; + uint8_t count = 0; + uint32_t time_out = 2000; + uint16_t mesh_code = MAX_MESH_PROVISIONER_CMD; + CMD_ITEM *pmeshCmdItem = NULL; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + uint8_t userApiMode = USER_API_DEFAULT_MODE; + //user_cmd_parse_value_t *pparse_value = NULL; + struct list_head *plist; + struct mesh_task_struct *pcmdtask = &(meshProvisionerCmdThread); + + printf("[BT_MESH] %s(): mesh cmd thread enter !\r\n", __func__); + + while(1) + { + if (os_sem_take(pcmdtask->wakeup_sema, 0xFFFFFFFF) == _FAIL) { + printf("[BT_MESH] %s(): down wakeup_sema fail !\r\n", __func__); + break; + } + if (pcmdtask->blocked == _TRUE) { + /* wait mesh stack handling mesh cmds */ + while (btMeshCmdPriv.cmdTransmittedNum) { + printf(" waiting mesh command's implementation by mesh stack \r\n"); + os_delay(100); + } + printf("[BT_MESH] %s(): blocked(%d) !\r\n", __func__, pcmdtask->blocked); + break; + } + plist = bt_mesh_dequeue_cmd(); + if (!plist) { + printf("[BT_MESH] %s(): bt_mesh_dequeue_cmd fail !\r\n", __func__); + goto _next; + } + pmeshCmdItem_s = (CMD_ITEM_S *)plist; + pmeshCmdItem = pmeshCmdItem_s->pmeshCmdItem; + mesh_code = pmeshCmdItem->meshCmdCode; + //pparse_value = pmeshCmdItem->pparseValue; + puserItem = (PUSER_ITEM)pmeshCmdItem->userData; + userApiMode = pmeshCmdItem_s->userApiMode; + if (pmeshCmdItem_s->semaDownTimeOut) { + count = 0; + printf("[BT_MESH] %s(): mesh cmd %d has already timeout !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + goto _next; + } + BT_MESH_CMD_ID_PRIV_MOD(mesh_code, pmeshCmdItem_s, puserItem->userApiMode, 1, plt_time_read_ms()); + if (pmeshCmdItem_s->pmeshCmdItem->meshFunc) { + if (pmeshCmdItem_s->pmeshCmdItem->meshFunc(mesh_code, pmeshCmdItem_s)) { + if (userApiMode == USER_API_ASYNCH) { + bt_mesh_free_hdl(puserItem); + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + goto _next; + } else if (userApiMode == USER_API_CMDLINE) { + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + goto _next; + } + } + if (userApiMode != USER_API_SYNCH) { + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + goto _next; + } + btMeshCmdIdPriv.semaDownTimeOut = 0; + /* proivsioning takes more time */ + if (mesh_code == GEN_MESH_CODE(_prov)) { + time_out = 10000; + } else { + time_out = 2000; + } + /* guarantee the integrity of each mesh_code cmd */ + if (os_sem_take(btMeshCmdPriv.meshThreadSema, time_out) == _FAIL) { + count++; + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + /* guarantee that previous msg has already been handled */ + while (!pmeshCmdItem_s->msgRecvFlag) { + printf("[BT_MESH] %s(): Wait bt_mesh_user_cmd_hdl implementation %d, %d !\r\n", __func__, mesh_code, btMeshCmdPriv.cmdTransmittedNum); + os_delay(100); + } + if (count == BT_MESH_PROV_CMD_RETRY_COUNT) { + count = 0; + printf("[BT_MESH] %s(): down sema timeout mesh cmd = %d !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } else { + /* enqueue to head for another try */ + printf("\r\n enqueue again 0x%x \r\n", plist); + if (bt_mesh_enqueue_cmd(plist, 1) == 1) { + printf("[BT_MESH] %s(): enqueue cmd for mesh code %d fail !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } + } + }else { + count = 0; + if (pmeshCmdItem_s->semaDownTimeOut) { + printf("[BT_MESH] %s(): mesh_code %d indication is timeout !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + } else { + os_sem_give(puserItem->userSema); + printf("[BT_MESH] %s():mesh cmd = %d puserItem->userCmdResult = %d !\r\n", __func__, mesh_code, puserItem->userCmdResult); + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + } + } + } else { + printf("[BT_MESH] %s(): meshFunc is NULL mesh_code = %d !\r\n", __func__, mesh_code); + bt_mesh_cmdunreg(pmeshCmdItem_s); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + } +_next: + /* make sure os shedule can switch out */ + os_delay(10); + } + /* prevent previous cmd involking bt_mesh_indication */ + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + /* free all pmeshCmdItem_s resources */ + do{ + plist = bt_mesh_dequeue_cmd(); + if (plist == NULL) { + break; + } + bt_mesh_cmdunreg((CMD_ITEM_S *)plist); + }while(1); + os_sem_give(pcmdtask->terminate_sema); + printf("[BT_MESH] %s(): mesh cmd thread exit !\r\n", __func__); + os_task_delete(NULL); +} + +uint8_t bt_mesh_provisioner_api_init(void) +{ + if (btMeshCmdPriv.meshMode == BT_MESH_PROVISIONER) { + printf("[BT_MESH] %s(): MESH PROVISIONER is already running !\r\n", __func__); + return 1; + } else if (btMeshCmdPriv.meshMode == BT_MESH_DEVICE) { + printf("[BT_MESH] %s(): MESH Device is running, need deinitialization firstly !\r\n", __func__); + return 1; + } + rtw_init_listhead(&btMeshCmdPriv.meshCmdList); + os_mutex_create(&btMeshCmdPriv.cmdMutex); + os_mutex_create(&btMeshCmdPriv.ppvalueMutex); + os_mutex_create(&btMeshCmdPriv.cmdItemsMutex); + os_sem_create(&btMeshCmdPriv.meshThreadSema, 0, 0xffffffff); + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + meshProvisionerCmdThread.blocked = 0; + os_sem_create(&meshProvisionerCmdThread.wakeup_sema, 0, 0xffffffff); + os_sem_create(&meshProvisionerCmdThread.terminate_sema, 0, 0xffffffff); + if (os_task_create(&meshProvisionerCmdThread.task, "mesh_provisioner_cmd_thread", mesh_provisioner_cmd_thread, + NULL, 1024, 3) != true) { + meshProvisionerCmdThread.blocked = 1; + os_sem_delete(meshProvisionerCmdThread.wakeup_sema); + os_sem_delete(meshProvisionerCmdThread.terminate_sema); + printf("[BT_MESH] %s(): create mesh_provisioner_cmd_thread fail !\r\n", __func__); + os_mutex_delete(btMeshCmdPriv.cmdMutex); + os_sem_delete(btMeshCmdPriv.meshThreadSema); + return 1; + } + btMeshCmdPriv.cmdListNum = 0; + btMeshCmdPriv.cmdTransmittedNum = 0; + btMeshCmdPriv.meshMode = BT_MESH_PROVISIONER; + btMeshCmdPriv.meshCmdEnable = 1; + + return 0; +} + +void bt_mesh_provisioner_api_deinit(void) +{ + if (btMeshCmdPriv.meshMode != BT_MESH_PROVISIONER) { + printf("[BT_MESH] %s(): MESH PROVISIONER is not running !\r\n", __func__); + return; + } + btMeshCmdPriv.meshCmdEnable = 0; + BT_MESH_CMD_ID_PRIV_MOD(MAX_MESH_PROVISIONER_CMD, NULL, USER_API_DEFAULT_MODE, 1, 0); + meshProvisionerCmdThread.blocked = 1; + os_sem_give(meshProvisionerCmdThread.wakeup_sema); + os_sem_take(meshProvisionerCmdThread.terminate_sema, 0xFFFFFFFF); + btMeshCmdPriv.meshMode = 0; + os_sem_delete(meshProvisionerCmdThread.wakeup_sema); + os_sem_delete(meshProvisionerCmdThread.terminate_sema); + os_mutex_delete(btMeshCmdPriv.cmdMutex); + os_mutex_delete(btMeshCmdPriv.ppvalueMutex); + os_mutex_delete(btMeshCmdPriv.cmdItemsMutex); + os_sem_delete(btMeshCmdPriv.meshThreadSema); +} + +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.h new file mode 100644 index 00000000..a612a8d2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.h @@ -0,0 +1,126 @@ +/** +***************************************************************************************** +* Copyright(c) 2019, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_mesh_provisioner_api.h + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author sherman + * @date 2019-09-16 + * @version v1.0 + * ************************************************************************************* + */ +#ifndef _BT_MESH_PROV_API_H_ +#define _BT_MESH_PROV_API_H_ + +#include "bt_mesh_user_api.h" + +#define BT_MESH_PROV_CMD_RETRY_COUNT 2 + +/** @brief bt mesh provisioner command table */ +enum bt_mesh_provisioner_cmd +{ + GEN_MESH_CODE(_pb_adv_con) , /*0*/ + GEN_MESH_CODE(_prov) , + GEN_MESH_CODE(_prov_stop) , + GEN_MESH_CODE(_app_key_add) , + GEN_MESH_CODE(_model_app_bind) , + GEN_MESH_CODE(_model_pub_set) , /*5*/ + GEN_MESH_CODE(_generic_on_off_set) , + GEN_MESH_CODE(_generic_on_off_get) , + GEN_MESH_CODE(_node_reset) , + GEN_MESH_CODE(_model_sub_delete) , + GEN_MESH_CODE(_model_sub_add) , /*10*/ + GEN_MESH_CODE(_model_sub_get) , + GEN_MESH_CODE(_prov_discover) , + GEN_MESH_CODE(_prov_cccd_operate) , + GEN_MESH_CODE(_proxy_discover) , + GEN_MESH_CODE(_proxy_cccd_operate) , /*15*/ + GEN_MESH_CODE(_datatrans_write) , + GEN_MESH_CODE(_datatrans_read) , + GEN_MESH_CODE(_connect) , + GEN_MESH_CODE(_disconnect) , + GEN_MESH_CODE(_list) , + GEN_MESH_CODE(_dev_info_show) , + GEN_MESH_CODE(_fn_init) , + GEN_MESH_CODE(_fn_deinit) , + GEN_MESH_CODE(_light_lightness_get) , + GEN_MESH_CODE(_light_lightness_set) , + GEN_MESH_CODE(_light_lightness_linear_get) , + GEN_MESH_CODE(_light_lightness_linear_set) , + GEN_MESH_CODE(_light_lightness_last_get) , + GEN_MESH_CODE(_light_lightness_default_get) , + GEN_MESH_CODE(_light_lightness_default_set) , + GEN_MESH_CODE(_light_lightness_range_get) , + GEN_MESH_CODE(_light_lightness_range_set) , + GEN_MESH_CODE(_light_ctl_get) , + GEN_MESH_CODE(_light_ctl_set) , + GEN_MESH_CODE(_light_ctl_temperature_get) , + GEN_MESH_CODE(_light_ctl_temperature_set) , + GEN_MESH_CODE(_light_ctl_temperature_range_get) , + GEN_MESH_CODE(_light_ctl_temperature_range_set) , + GEN_MESH_CODE(_light_ctl_default_get) , + GEN_MESH_CODE(_light_ctl_default_set) , + GEN_MESH_CODE(_light_hsl_get) , + GEN_MESH_CODE(_light_hsl_set) , + GEN_MESH_CODE(_light_hsl_target_get) , + GEN_MESH_CODE(_light_hsl_hue_get) , + GEN_MESH_CODE(_light_hsl_hue_set) , + GEN_MESH_CODE(_light_hsl_saturation_get) , + GEN_MESH_CODE(_light_hsl_saturation_set) , + GEN_MESH_CODE(_light_hsl_default_get) , + GEN_MESH_CODE(_light_hsl_default_set) , + GEN_MESH_CODE(_light_hsl_range_get) , + GEN_MESH_CODE(_light_hsl_range_set) , + GEN_MESH_CODE(_light_xyl_get) , + GEN_MESH_CODE(_light_xyl_set) , + GEN_MESH_CODE(_light_xyl_target_get) , + GEN_MESH_CODE(_light_xyl_default_get) , + GEN_MESH_CODE(_light_xyl_default_set) , + GEN_MESH_CODE(_light_xyl_range_get) , + GEN_MESH_CODE(_light_xyl_range_set) , + GEN_MESH_CODE(_time_set) , + GEN_MESH_CODE(_time_get) , + GEN_MESH_CODE(_time_zone_get) , + GEN_MESH_CODE(_time_zone_set) , + GEN_MESH_CODE(_time_tai_utc_delta_set) , + GEN_MESH_CODE(_time_tai_utc_delta_get) , + GEN_MESH_CODE(_time_role_set) , + GEN_MESH_CODE(_time_role_get) , + GEN_MESH_CODE(_scene_store) , + GEN_MESH_CODE(_scene_recall) , + GEN_MESH_CODE(_scene_get) , + GEN_MESH_CODE(_scene_register_get) , + GEN_MESH_CODE(_scene_delete) , + GEN_MESH_CODE(_scheduler_get) , + GEN_MESH_CODE(_scheduler_action_get) , + GEN_MESH_CODE(_scheduler_action_set) , +#if defined(MESH_RPR) && MESH_RPR + GEN_MESH_CODE(_rmt_prov_client_scan_start) , + GEN_MESH_CODE(_rmt_prov_client_link_open_prov) , + GEN_MESH_CODE(_rmt_prov_client_close) , +#endif +#if defined(MESH_DFU) && MESH_DFU + GEN_MESH_CODE(_fw_update_info_get) , + GEN_MESH_CODE(_fw_update_start) , + GEN_MESH_CODE(_fw_update_cancel) , +#endif + MAX_MESH_PROVISIONER_CMD +}; + +/** + * @brief initialize bt mesh provisioner api + * + * @return 1: success 2: fail + */ +uint8_t bt_mesh_provisioner_api_init(void); + +/** + * @brief deinitialize bt mesh provisioner api + * + * @return none + */ +void bt_mesh_provisioner_api_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_flags.h new file mode 100644 index 00000000..c49fab63 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_flags.h @@ -0,0 +1,41 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_DEVICE_APP_FLAGS_H_ +#define _BT_MESH_DEVICE_APP_FLAGS_H_ + +#include + +/** + * @addtogroup MESH_APP_CONFIG + * @{ + */ + +/** + * @defgroup Mesh_App_Config Mesh App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/ +#define F_BT_AIRPLANE_MODE_SUPPORT 0 + +/** @} */ +/** @} */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_main.c new file mode 100644 index 00000000..8c20a7fb --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_main.c @@ -0,0 +1,631 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesh_api.h" +#include +#include +#include +#include +#include +#include +#include + +#include "mesh_cmd.h" +#include "device_app.h" +#include "health.h" +#include "generic_on_off.h" +#include "light_server_app.h" +#include "time_server_app.h" +#include "scheduler_server_app.h" +#include "scene_server_app.h" +#include "ping.h" +#include "ping_app.h" +#include "tp.h" +#include "datatrans_server.h" +#include "health.h" +#include "datatrans_app.h" +#include "bt_mesh_device_app_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#include "bt_mesh_device_test.h" +#include "bt_mesh_test_result.h" +#include "gpio_api.h" +#endif + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +#include "bt_mesh_device_api.h" +#include "generic_on_off.h" +#include "gpio_api.h" +#include "gpio_irq_api.h" +#endif +#include "osdep_service.h" +#include "wifi_constants.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_device_api.h" +#endif +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK +#include "device_idle_check.h" +#endif +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_updater_app.h" +#endif +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +#if defined(CONFIG_PLATFORM_8721D) +#define GPIO_LED_PIN PA_25 +#elif defined(CONFIG_PLATFORM_8710C) +#define GPIO_LED_PIN PA_19 +#endif +#define GPIO_IRQ_PIN PA_13 +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#if defined(CONFIG_PLATFORM_8721D) +#define GPIO_LED_PIN PA_25 +#elif defined(CONFIG_PLATFORM_8710C) +#define GPIO_LED_PIN PA_19 +#endif +#endif +#define COMPANY_ID 0x005D +#define PRODUCT_ID 0x0000 +#define VERSION_ID 0x0000 + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +plt_timer_t device_publish_timer = NULL; +#endif +mesh_model_info_t health_server_model; +mesh_model_info_t generic_on_off_server_model; +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +gpio_t gpio_led; +gpio_irq_t gpio_btn; + +uint32_t last_push_button_time = 0; +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +gpio_t gpio_led; +#endif + +generic_on_off_t current_on_off = GENERIC_OFF; + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +void device_publish_api(generic_on_off_t on_off) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + /* _generic_on_off_publish */ + puserItem = bt_mesh_alloc_hdl(USER_API_ASYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + } + puserItem->pparseValue->dw_parameter[0] = on_off; + puserItem->pparseValue->para_count = 1; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_generic_on_off_publish), puserItem->pparseValue, NULL, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + } +} + +void device_publish_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + device_publish_api(current_on_off); +} +#endif + +static int32_t generic_on_off_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case GENERIC_ON_OFF_SERVER_GET: + { + generic_on_off_server_get_t *pdata = pargs; + pdata->on_off = current_on_off; + } + break; + case GENERIC_ON_OFF_SERVER_GET_DEFAULT_TRANSITION_TIME: + break; + case GENERIC_ON_OFF_SERVER_SET: + { + generic_on_off_server_set_t *pdata = pargs; + if (pdata->total_time.num_steps == pdata->remaining_time.num_steps) + { + if (pdata->on_off != current_on_off) + { + current_on_off = pdata->on_off; + if (current_on_off == GENERIC_OFF) + { + printf("Provisioner turn light OFF!\r\n"); +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + gpio_write(&gpio_led, 0); + plt_timer_change_period(device_publish_timer, 200, 0xFFFFFFFF); +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + gpio_write(&gpio_led, 0); +#endif + } + else if (current_on_off == GENERIC_ON) + { + printf("Provisioner turn light ON!\r\n"); +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + gpio_write(&gpio_led, 1); + plt_timer_change_period(device_publish_timer, 200, 0xFFFFFFFF); +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + gpio_write(&gpio_led, 1); +#endif + } + } + } + } + break; + default: + break; + } + + return 0; +} + +void generic_on_off_server_model_init(void) +{ + generic_on_off_server_model.model_data_cb = generic_on_off_server_data; + generic_on_off_server_reg(0, &generic_on_off_server_model); +} + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +#if 0 +void push_button_handler(uint32_t id, gpio_irq_event event) +{ + /* avoid gcc compile warning */ + (void)event; + gpio_t *gpio_led = (gpio_t *)id; + uint32_t current_time = rtw_get_current_time(); + //mesh_model_info_t pmodel_info = generic_on_off_server_model; + + gpio_irq_disable(&gpio_btn); + + if (current_time > last_push_button_time && rtw_systime_to_ms(current_time - last_push_button_time) > 100) { + if (current_on_off == GENERIC_OFF) { + current_on_off = GENERIC_ON; + gpio_write(gpio_led, 1); + printf("User turn light ON!\r\n"); + device_publish_api(GENERIC_ON); + } else if (current_on_off == GENERIC_ON) { + current_on_off = GENERIC_OFF; + gpio_write(gpio_led, 0); + printf("User turn light OFF!\r\n"); + device_publish_api(GENERIC_OFF); + } + } + + last_push_button_time = current_time; + gpio_irq_enable(&gpio_btn); +} +#endif + +void light_button_init(void) +{ + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); + gpio_mode(&gpio_led, PullNone); + +#if 0 + gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, push_button_handler, (uint32_t)(&gpio_led)); + gpio_irq_set(&gpio_btn, IRQ_FALL, 1); + gpio_irq_enable(&gpio_btn); +#endif + + if (current_on_off == GENERIC_OFF) + gpio_write(&gpio_led, 0); + else if (current_on_off == GENERIC_ON) + gpio_write(&gpio_led, 1); +} +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +void light_init(void) +{ + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); + gpio_mode(&gpio_led, PullNone); + if (current_on_off == GENERIC_OFF) + gpio_write(&gpio_led, 0); + else if (current_on_off == GENERIC_ON) + gpio_write(&gpio_led, 1); +} +#endif + +#if defined(MESH_DFU) && MESH_DFU +extern void blob_transfer_server_caps_set(blob_server_capabilites_t *pcaps); +#endif + +/****************************************************************** + * @fn Initial gap parameters + * @brief Initialize peripheral and gap bond manager related parameters + * + * @return void + */ +void bt_mesh_device_stack_init(void) +{ + /** set ble stack log level, disable nonsignificant log */ + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + // log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_ERROR, 0); + // log_module_trace_set(TRACE_MODULE_SNOOP, TRACE_LEVEL_ERROR, 0); + + /** set mesh stack log level, default all on, disable the log of level LEVEL_TRACE */ + uint32_t module_bitmap[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(TRACE_LEVEL_TRACE, module_bitmap); + + /** mesh stack needs rand seed */ + plt_srand(platform_random(0xffffffff)); + + /** set device name and appearance */ + char *dev_name = "Mesh Device"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + gap_sched_params_set(GAP_SCHED_PARAMS_DEVICE_NAME, dev_name, GAP_DEVICE_NAME_LEN); + gap_sched_params_set(GAP_SCHED_PARAMS_APPEARANCE, &appearance, sizeof(appearance)); + + /** configure provisioning parameters */ + prov_capabilities_t prov_capabilities = + { + .algorithm = PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE, + .public_key = 0, + .static_oob = 0, + .output_oob_size = 0, + .output_oob_action = 0, + .input_oob_size = 0, + .input_oob_action = 0 + }; + prov_params_set(PROV_PARAMS_CAPABILITIES, &prov_capabilities, sizeof(prov_capabilities_t)); + prov_params_set(PROV_PARAMS_CALLBACK_FUN, (void *)prov_cb, sizeof(prov_cb_pf)); + + /** config node parameters */ + mesh_node_features_t features = + { + .role = MESH_ROLE_DEVICE, + .relay = 1, + .proxy = 1, + .fn = 1, + .lpn = 1, + .prov = 1, + .udb = 1, + .snb = 1, + .bg_scan = 1, + .flash = 1, + .flash_rpl = 1 + }; + + mesh_node_cfg_t node_cfg = + { + .dev_key_num = 2, + .net_key_num = 10, + .app_key_num = 3, + .vir_addr_num = 3, + .rpl_num = 20, + .sub_addr_num = 5, + .proxy_num = 1, + .prov_interval = 2, + .udb_interval = 2, + .proxy_interval = 5 + }; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + features.flash_rpl = 0; + node_cfg.rpl_num = 50; +#endif + + mesh_node_cfg(features, &node_cfg); + proxy_server_support_prov_on_proxy(true); + mesh_node.net_trans_count = 6; + mesh_node.relay_retrans_count = 2; + mesh_node.trans_retrans_count = 4; + mesh_node.ttl = 5; +#if MESH_LPN + mesh_node.frnd_poll_retry_times = 32; +#endif + + /** create elements and register models */ + mesh_element_create(GATT_NS_DESC_UNKNOWN); +#if !defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) || (!CONFIG_BT_MESH_DEVICE_RTK_DEMO) + health_server_reg(0, &health_server_model); + health_server_set_company_id(&health_server_model, COMPANY_ID); + ping_control_reg(ping_app_ping_cb, pong_receive); + trans_ping_pong_init(ping_app_ping_cb, pong_receive); + tp_control_reg(tp_reveive); + datatrans_model_init(); + light_server_models_init(); + time_server_models_init(); + scene_server_model_init(); + scheduler_server_model_init(); +#endif + generic_on_off_server_model_init(); +#if defined(MESH_DFU) && MESH_DFU + dfu_updater_models_init(); + blob_server_capabilites_t caps = { + 6, //BLOB_TRANSFER_CPAS_MIN_BLOCK_SIZE_LOG + 12, //BLOB_TRANSFER_CPAS_MAX_BLOCK_SIZE_LOG + 20, //BLOB_TRANSFER_CPAS_MAX_TOTAL_CHUNKS + 256, //BLOB_TRANSFER_CPAS_MAX_CHUNK_SIZE + 1000000, //!< supported max size + 350, //BLOB_TRANSFER_CPAS_SERVER_MTU_SIZE + 1, //BLOB_TRANSFER_CPAS_MODE_PULL_SUPPORT + 1, //BLOB_TRANSFER_CPAS_MODE_PUSH_SUPPORT + 0 //RFU + }; + blob_transfer_server_caps_set(&caps); +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + init_bt_mesh_test_parameter(); + link_list_init(); + light_init(); +#endif +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + light_button_init(); + device_publish_timer = plt_timer_create("device_publish_timer", 0xFFFFFFFF, FALSE, NULL, device_publish_timer_handler); + if (!device_publish_timer) { + printf("[BT Mesh Device] Create device publish timer failed\n\r"); + } + datatrans_model_init(); +#endif + compo_data_page0_header_t compo_data_page0_header = {COMPANY_ID, PRODUCT_ID, VERSION_ID}; + compo_data_page0_gen(&compo_data_page0_header); + + /** init mesh stack */ + mesh_init(); + + /** register proxy adv callback */ + device_info_cb_reg(device_info_cb); + hb_init(hb_cb); +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_mesh_device_app_le_gap_init(void) +{ + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + uint16_t scan_window = 0x100; /* 160ms */ + uint16_t scan_interval = 0x120; /* 180ms */ + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_mesh_device_app_gap_callback); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + + vendor_cmd_init(bt_mesh_device_app_vendor_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_mesh_device_app_le_profile_init(void) +{ + server_init(MESH_GATT_SERVER_COUNT); + + /* Register Server Callback */ + server_register_app_cb(bt_mesh_device_app_profile_callback); + + client_init(MESH_GATT_CLIENT_COUNT); + /* Add Client Module */ + + /* Register Client Callback--App_ClientCallback to handle events from Profile Client layer. */ + client_register_general_client_cb(bt_mesh_device_app_client_callback); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void bt_mesh_device_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_mesh_device_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void bt_mesh_device_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void bt_mesh_device_task_init(void) +{ + bt_mesh_device_app_task_init(); +} + +void bt_mesh_device_task_deinit(void) +{ + bt_mesh_device_app_task_deinit(); +} + +void bt_mesh_device_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_mesh_device_app_main(void) +{ + bt_trace_init(); + bt_mesh_device_stack_config_init(); + bte_init(); + bt_mesh_device_board_init(); + bt_mesh_device_driver_init(); + le_gap_init(APP_MAX_LINKS); + bt_mesh_device_app_le_gap_init(); + bt_mesh_device_app_le_profile_init(); + bt_mesh_device_stack_init(); + bt_mesh_device_pwr_mgr_init(); + bt_mesh_device_task_init(); + + return 0; +} + +extern int wifi_is_up(rtw_interface_t interface); +extern void bt_coex_init(void); + +int bt_mesh_device_app_init(void) +{ + //int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT Mesh Device]BT Stack already on\n\r"); + return 0; + } + else + bt_mesh_device_app_main(); + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_device_api_init()) { + printf("[BT Mesh Device] bt_mesh_device_api_init fail ! \n\r"); + return 1; + } +#endif + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK + bt_mesh_idle_check_init(); +#endif + + return 0; + +} + +extern void mesh_deinit(void); +extern bool mesh_initial_state; +extern bool bt_trace_uninit(void); + +void bt_mesh_device_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + bt_mesh_device_api_deinit(); +#endif + bt_mesh_device_task_deinit(); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Device] BT Stack is not running\n\r"); + mesh_initial_state = FALSE; + return; + } +#if F_BT_DEINIT + else { + bte_deinit(); + printf("[BT Mesh Device] BT Stack deinitalized\n\r"); + } +#endif + mesh_deinit(); + bt_trace_uninit(); + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK + bt_mesh_idle_check_deinit(); +#endif + mesh_initial_state = FALSE; +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.c new file mode 100644 index 00000000..5b2d0da4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.c @@ -0,0 +1,235 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif + +#include "mesh_api.h" +#include "device_app.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "device_cmd.h" +#include "platform_opts.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif + +/*============================================================================* + * Macros + *============================================================================*/ +#define EVENT_MESH 0x80 +#define APP_TASK_PRIORITY 4 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#else +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#endif + +#if defined(CONFIG_PLATFORM_8721D) +#define UART_TX _PA_18 +#define UART_RX _PA_19 +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +#define UART_TX PA_14 +#define UART_RX PA_13 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_mesh_device_app_task_handle; //!< APP Task handle +void *bt_mesh_device_evt_queue_handle; //!< Event queue handle +void *bt_mesh_device_io_queue_handle; //!< IO queue handle +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +void *bt_mesh_device_user_cmd_io_queue_handle; //!< user cmd queue handle +#endif + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_mesh_device_app_main_task(void *p_param); + +void app_send_uart_msg(uint8_t data) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = IO_MSG_TYPE_UART; + msg.subtype = data; + if (os_msg_send(bt_mesh_device_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_evt_queue_handle, &event, 0) == false) + { + } +} + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern CMD_MOD_INFO_S btMeshCmdPriv; +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg) +{ + uint8_t event = EVENT_USER_API_REQ; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)p_io_msg->u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + //trace commands transmitted to mesh stack + btMeshCmdPriv.cmdTransmittedNum ++; + if (os_msg_send(bt_mesh_device_user_cmd_io_queue_handle, p_io_msg, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_device_user_cmd_io_queue_handle fail!\r\n"); + return 1; + } + else if (os_msg_send(bt_mesh_device_evt_queue_handle, &event, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_device_evt_queue_handle fail!\r\n"); + return 1; + } + + return 0; +} +#endif + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_device_app_task_init() +{ + os_task_create(&bt_mesh_device_app_task_handle, "bt_mesh_device_app", bt_mesh_device_app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_mesh_device_app_main_task(void *p_param) +{ + /* avoid gcc compile warning */ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_mesh_device_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_mesh_device_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + os_msg_queue_create(&bt_mesh_device_user_cmd_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); +#endif + gap_start_bt_stack(bt_mesh_device_evt_queue_handle, bt_mesh_device_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + mesh_start(EVENT_MESH, EVENT_IO_TO_APP, bt_mesh_device_evt_queue_handle, bt_mesh_device_io_queue_handle); + + mesh_data_uart_init(UART_TX, UART_RX, app_send_uart_msg); + mesh_user_cmd_init("MeshDevice"); + + while (true) + { + if (os_msg_recv(bt_mesh_device_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_device_app_handle_io_msg(io_msg); + } + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + else if (event == EVENT_USER_API_REQ) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_user_cmd_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_io_msg_handler(io_msg); + } + } +#endif +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + else if (event == EVENT_USER_HTTP_SERVER) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_demo_io_msg_handler(io_msg); + } + } +#endif + else if (event == EVENT_MESH) + { + mesh_inner_msg_handle(event); + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_device_app_task_deinit(void) +{ + if (bt_mesh_device_app_task_handle) { + os_task_delete(bt_mesh_device_app_task_handle); + } + if (bt_mesh_device_io_queue_handle) { + os_msg_queue_delete(bt_mesh_device_io_queue_handle); + } + if (bt_mesh_device_evt_queue_handle) { + os_msg_queue_delete(bt_mesh_device_evt_queue_handle); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_device_user_cmd_io_queue_handle) { + os_msg_queue_delete(bt_mesh_device_user_cmd_io_queue_handle); + } + bt_mesh_device_user_cmd_io_queue_handle = NULL; +#endif + bt_mesh_device_io_queue_handle = NULL; + bt_mesh_device_evt_queue_handle = NULL; + bt_mesh_device_app_task_handle = NULL; + mesh_user_cmd_deinit("MeshDevice"); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.h new file mode 100644 index 00000000..4f7c6143 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.h @@ -0,0 +1,25 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_DEVICE_APP_TASK_H_ +#define _BT_MESH_DEVICE_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_device_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_device_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.c new file mode 100644 index 00000000..b49b9d1b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.c @@ -0,0 +1,1004 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.c +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "device_app.h" +#include "trace_app.h" +#include "gap_wrapper.h" +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "device_cmd.h" +#include "mesh_cmd.h" +#include "ping_app.h" +#include "datatrans_server.h" +#include "bt_flags.h" +#include "bt_mesh_device_app_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#include "bt_mesh_device_api.h" +#endif + +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; + +T_GAP_DEV_STATE bt_mesh_device_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_APP_LINK app_link_table[APP_MAX_LINKS]; + +prov_auth_value_type_t prov_auth_value_type; + +void bt_mesh_device_app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +static uint8_t datatrans_sample_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + +uint8_t lpn_disable_scan_flag = 0; + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_device_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + bt_mesh_device_app_handle_gap_msg(&io_msg); + break; + case IO_MSG_TYPE_UART: + { + /* We handle user command informations from Data UART in this branch. */ + uint8_t data = io_msg.subtype; + mesh_user_cmd_collect(&data, sizeof(data), device_cmd_table); + } + break; + case PING_TIMEOUT_MSG: + ping_handle_timeout(); + break; + case PING_APP_TIMEOUT_MSG: + ping_app_handle_timeout(); + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_mesh_device_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_mesh_device_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_mesh_device_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + } + } + bt_mesh_device_gap_dev_state = new_state; +} + +uint8_t mesh_device_conn_state = 0; + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_mesh_device_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("bt_mesh_device_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, app_link_table[conn_id].conn_state, new_state, disc_cause); + + app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_mesh_device_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + data_uart_debug("Disconnect conn_id %d\r\n", conn_id); + mesh_device_conn_state = 0; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } + } else { + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_disconnect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_disconnect)); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } + } else { + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } +#endif + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, app_link_table[conn_id].bd_addr, + &app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(app_link_table[conn_id].bd_addr), app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_debug("Connected success conn_id %d\r\n", conn_id); + mesh_device_conn_state = 1; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + } +#endif +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, 251, 2120); +#endif + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_mesh_device_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_mesh_device_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_mesh_device_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_debug("Pair success\r\n"); + APP_PRINT_INFO0("bt_mesh_device_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_debug("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_mesh_device_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_mesh_device_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_mesh_device_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_mesh_device_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_mesh_device_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_mesh_device_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_mesh_device_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_mesh_device_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + } + break; + + default: + break; + } +} + +bool mesh_initial_state = FALSE; + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * sub_type of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_mesh_device_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_mesh_device_app_handle_gap_msg: sub_type %d", p_gap_msg->subtype); + mesh_inner_msg_t mesh_inner_msg; + mesh_inner_msg.type = MESH_BT_STATUS_UPDATE; + mesh_inner_msg.sub_type = p_gap_msg->subtype; + mesh_inner_msg.parm = p_gap_msg->u.param; + gap_sched_handle_bt_status_msg(&mesh_inner_msg); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + if (!mesh_initial_state) + { + mesh_initial_state = TRUE; + /** set device uuid according to bt address */ + uint8_t bt_addr[6]; + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + memcpy(dev_uuid, bt_addr, sizeof(bt_addr)); + device_uuid_set(dev_uuid); + } + bt_mesh_device_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_mesh_device_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_mesh_device_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_mesh_device_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_mesh_device_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_debug("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_device_app_handle_gap_msg: unknown sub_type %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + gap_sched_handle_adv_report(p_data->p_le_scan_info); + break; + +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + gap_sched_adv_params_set_done(); + break; + /* + case GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: cause 0x%x", + p_data->le_cause.cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + break; + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; + + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; + */ +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif + default: + APP_PRINT_ERROR1("bt_mesh_device_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_device_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_device_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == datatrans_server_id) + { + datatrans_server_data_t *pdata = p_data; + switch (pdata->type) + { + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + pdata->len = sizeof(datatrans_sample_data); + pdata->data = datatrans_sample_data; + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + if (pdata->len > sizeof(datatrans_sample_data)) + { + pdata->len = sizeof(datatrans_sample_data); + } + memcpy(datatrans_sample_data, pdata->data, pdata->len); + break; + default: + break; + } + } + return app_result; +} + +/****************************************************************** + * @fn device_info_cb + * @brief device_info_cb callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return void + */ +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + if (!dev_info_show_flag) + { + return; + } + data_uart_debug("bt addr=0x%02x%02x%02x%02x%02x%02x type=%d rssi=%d ", bt_addr[5], bt_addr[4], + bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0], bt_addr_type, rssi); + switch (pinfo->type) + { + case DEVICE_INFO_UDB: + data_uart_debug("udb="); + data_uart_dump(pinfo->pbeacon_udb->dev_uuid, 16); + break; + case DEVICE_INFO_PROV_ADV: + data_uart_debug("prov="); + data_uart_dump(pinfo->pservice_data->provision.dev_uuid, 16); + break; + case DEVICE_INFO_PROXY_ADV: + data_uart_debug("proxy="); + data_uart_dump((uint8_t *)&pinfo->pservice_data->proxy, pinfo->len); + break; + default: + break; + } +} + +/****************************************************************** + * @fn prov_cb + * @brief Provisioning callbacks are handled in this function. + * + * @param cb_data - @ref TProvisioningCbData + * @return the operation result + */ +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data) +{ + APP_PRINT_INFO1("prov_cb: type = %d", cb_type); + + switch (cb_type) + { + case PROV_CB_TYPE_PB_ADV_LINK_STATE: + switch (cb_data.pb_generic_cb_type) + { + case PB_GENERIC_CB_LINK_OPENED: + data_uart_debug("PB-ADV Link Opened!\r\n>"); + break; + case PB_GENERIC_CB_LINK_OPEN_FAILED: + data_uart_debug("PB-ADV Link Open Failed!\r\n>"); + break; + case PB_GENERIC_CB_LINK_CLOSED: + data_uart_debug("PB-ADV Link Closed!\r\n>"); + break; + default: + break; + } + break; + case PROV_CB_TYPE_UNPROV: + data_uart_debug("unprov device!\r\n>"); + break; + case PROV_CB_TYPE_START: + data_uart_debug("being prov-ed!\r\n"); + break; + case PROV_CB_TYPE_PUBLIC_KEY: + { + uint8_t public_key[64] = {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79}; + uint8_t private_key[32] = {0x52, 0x9a, 0xa0, 0x67, 0x0d, 0x72, 0xcd, 0x64, 0x97, 0x50, 0x2e, 0xd4, 0x73, 0x50, 0x2b, 0x03, 0x7e, 0x88, 0x03, 0xb5, 0xc6, 0x08, 0x29, 0xa5, 0xa3, 0xca, 0xa2, 0x19, 0x50, 0x55, 0x30, 0xba}; + prov_params_set(PROV_PARAMS_PUBLIC_KEY, public_key, sizeof(public_key)); + prov_params_set(PROV_PARAMS_PRIVATE_KEY, private_key, sizeof(private_key)); + APP_PRINT_INFO0("prov_cb: Please show the public key to the provisioner"); + } + break; + case PROV_CB_TYPE_AUTH_DATA: + { + prov_start_p pprov_start = cb_data.pprov_start; + prov_auth_value_type = prov_auth_value_type_get(pprov_start); + /* use cmd to set auth data */ + data_uart_debug("auth method=%d[nsoi] action=%d size=%d type=%d[nbNa]\r\n>", + pprov_start->auth_method, + pprov_start->auth_action, pprov_start->auth_size, prov_auth_value_type); + //uint8_t auth_data[16] = {1}; + switch (pprov_start->auth_method) + { + case PROV_AUTH_METHOD_STATIC_OOB: + //prov_auth_value_set(auth_data, sizeof(auth_data)); + APP_PRINT_INFO0("prov_cb: Please exchange the oob data with the provisioner"); + break; + case PROV_AUTH_METHOD_OUTPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.output_oob_size); + APP_PRINT_INFO2("prov_cb: Please output the oob data to the provisioner, output size = %d, action = %d", + pprov_start->auth_size.output_oob_size, pprov_start->auth_action.output_oob_action); + break; + case PROV_AUTH_METHOD_INPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.input_oob_size); + APP_PRINT_INFO2("prov_cb: Please input the oob data provided by the provisioner, input size = %d, action = %d", + pprov_start->auth_size.input_oob_size, pprov_start->auth_action.input_oob_action); + break; + default: + break; + } + } + break; + case PROV_CB_TYPE_COMPLETE: + { + mesh_node.iv_timer_count = MESH_IV_INDEX_48W; + prov_data_p pprov_data = cb_data.pprov_data; + data_uart_debug("been prov-ed with addr 0x%04x!\r\n", pprov_data->unicast_address); + } + break; + case PROV_CB_TYPE_FAIL: + data_uart_debug("provision fail, type=%d!\r\n", cb_data.prov_fail.fail_type); + break; + case PROV_CB_TYPE_PROV: + /* stack ready */ + data_uart_debug("ms addr: 0x%04x\r\n>", mesh_node.unicast_addr); + break; + default: + break; + } + return true; +} + +/****************************************************************** + * @fn fn_cb + * @brief fn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"establishing with lpn 0x%04x\r\n", "no poll from 0x%04x\r\n", "established with lpn 0x%04x\r\n", "lpn 0x%04x lost\r\n"}; + data_uart_debug(string[type], lpn_addr); + if (type == FN_CB_TYPE_ESTABLISH_SUCCESS || type == FN_CB_TYPE_FRND_LOST) + { + user_cmd_time(NULL); + } +} + +/****************************************************************** + * @fn lpn_cb + * @brief lpn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"established with fn 0x%04x\r\n", "no frnd offer\r\n", "no frnd update\r\n", "fn 0x%04x lost\r\n"}; + data_uart_debug(string[type], fn_addr); + if (type == LPN_CB_TYPE_ESTABLISH_SUCCESS || type == LPN_CB_TYPE_FRIENDSHIP_LOST) + { + user_cmd_time(NULL); + } + + if (type == LPN_CB_TYPE_ESTABLISH_SUCCESS) + { + gap_sched_scan(false); + lpn_disable_scan_flag = 1; + mesh_service_adv_stop(); + } + else if (type == LPN_CB_TYPE_FRIENDSHIP_LOST) + { + if (lpn_disable_scan_flag){ + gap_sched_scan(true); + lpn_disable_scan_flag = 0; + } + mesh_service_adv_start(); + } +} + +/****************************************************************** + * @fn hb_cb + * @brief heartbeat callbacks are handled in this function. + * + * @param type + * @param pdata + * @return void + */ +void hb_cb(hb_data_type_t type, void *pargs) +{ + switch (type) + { + case HB_DATA_PUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat publish timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat publish timer stop\r\n"); + } + } + break; + case HB_DATA_SUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat subscription timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat subscription timer stop\r\n"); + } + } + break; + case HB_DATA_PUB_COUNT_UPDATE: + { + hb_data_pub_count_update_t *pdata = pargs; + data_uart_debug("heartbeat publish count update: %d\r\n", pdata->count); + } + break; + case HB_DATA_SUB_PERIOD_UPDATE: + { + hb_data_sub_period_update_t *pdata = pargs; + data_uart_debug("heartbeat subscription period update: %d\r\n", pdata->period); + } + break; + case HB_DATA_SUB_RECEIVE: + { + hb_data_sub_receive_t *pdata = pargs; + data_uart_debug("receive heartbeat: src = %d, init_ttl = %d, features = %d-%d-%d-%d, ttl = %d\r\n", + pdata->src, pdata->init_ttl, pdata->features.relay, pdata->features.proxy, + pdata->features.frnd, pdata->features.lpn, pdata->ttl); + } + break; + default: + break; + } +} + +void bt_mesh_device_app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("bt_mesh_device_app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_ERROR1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.h new file mode 100644 index 00000000..6f783421 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.h @@ -0,0 +1,66 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.h +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _MESH_APPLICATION__ +#define _MESH_APPLICATION__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "app_msg.h" +#include "mesh_api.h" + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_device_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +T_APP_RESULT bt_mesh_device_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo); +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +void hb_cb(hb_data_type_t type, void *pargs); +void bt_mesh_device_app_vendor_callback(uint8_t cb_type, void *p_cb_data); +#ifdef __cplusplus +} +#endif + +#endif /* _MESH_APPLICATION__S */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.c new file mode 100644 index 00000000..f2789c86 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.c @@ -0,0 +1,346 @@ +/** +************************************************************************************************************ +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +************************************************************************************************************ +* @file device_cmd.c +* @brief User defined Mesh test commands. +* @details User command interfaces. +* @author +* @date 2015-03-19 +* @version v0.1 +************************************************************************************************************* +*/ +#include +#include "trace.h" +#include "gap_wrapper.h" +#include "mesh_cmd.h" +#include "test_cmd.h" +#include "mesh_api.h" +#include "device_cmd.h" +#include "device_app.h" +#include "datatrans_model.h" +#include "datatrans_app.h" +#include "datatrans_server.h" +#include "generic_on_off.h" + +extern mesh_model_info_t health_server_model; +extern mesh_model_info_t generic_on_off_server_model; +extern uint8_t lpn_disable_scan_flag; + +static user_cmd_parse_result_t user_cmd_node_reset(user_cmd_parse_value_t *pparse_value) +{ + switch (pparse_value->dw_parameter[0]) + { + case 0: + mesh_node_reset(); + break; + case 1: + mesh_node_clean(); + break; + case 2: + mesh_node_restore(); + break; + default: + break; + } + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_prov_capa_set(user_cmd_parse_value_t *pparse_value) +{ + prov_capabilities_t prov_capabilities; + prov_capabilities.algorithm = PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE; + prov_capabilities.public_key = pparse_value->dw_parameter[0] ? PROV_CAP_PUBLIC_KEY_OOB : 0; + prov_capabilities.static_oob = pparse_value->dw_parameter[1] ? PROV_CAP_STATIC_OOB : 0; + prov_capabilities.output_oob_size = pparse_value->dw_parameter[2]; + prov_capabilities.output_oob_action = pparse_value->dw_parameter[3]; + prov_capabilities.input_oob_size = pparse_value->dw_parameter[4]; + prov_capabilities.input_oob_action = pparse_value->dw_parameter[5]; + if (prov_capabilities.output_oob_size > OUTPUT_OOB_SIZE_MAX || + prov_capabilities.input_oob_size > INPUT_OOB_SIZE_MAX) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + else + { + prov_params_set(PROV_PARAMS_CAPABILITIES, &prov_capabilities, sizeof(prov_capabilities_t)); + return USER_CMD_RESULT_OK; + } +} + +#if MESH_LPN +static user_cmd_parse_result_t user_cmd_lpn_init(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_num = pparse_value->dw_parameter[0]; + return lpn_init(fn_num, lpn_cb) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_lpn_deinit(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + lpn_deinit(); + if (lpn_disable_scan_flag){ + gap_sched_scan(true); + lpn_disable_scan_flag = 0; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_lpn_req(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + lpn_req_params_t req_params = {50, 100, {1, 0, 0, 0}}; + + if(le_get_active_link_num() != 0) + { + data_uart_debug("Have BLE active link, cannot establish friendship\n\r"); + return (USER_CMD_RESULT_ERROR); + } + + if (pparse_value->dw_parameter[2]) + { + req_params.poll_interval = pparse_value->dw_parameter[2]; + } + if (pparse_value->dw_parameter[3]) + { + req_params.poll_timeout = pparse_value->dw_parameter[3]; + } + if (pparse_value->dw_parameter[4] >= 0xa && pparse_value->dw_parameter[4] <= 0xff) + { + mesh_node.frnd_rx_delay = pparse_value->dw_parameter[4]; + } + if (pparse_value->para_count >= 6 && pparse_value->dw_parameter[5] <= 0xff) + { + mesh_node.frnd_rx_widen = pparse_value->dw_parameter[5]; + } + return lpn_req(fn_index, net_key_index, + &req_params) == LPN_REQ_REASON_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_lpn_sub(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + uint16_t addr = pparse_value->dw_parameter[1]; + bool add_rm = pparse_value->dw_parameter[2]; + frnd_sub_list_add_rm(fn_index, &addr, 1, add_rm); + return (USER_CMD_RESULT_OK); +} + +static user_cmd_parse_result_t user_cmd_lpn_clear(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + lpn_clear(fn_index); + return (USER_CMD_RESULT_OK); +} +#endif + +#if MESH_RMT_PRO_CLIENT +static user_cmd_parse_result_t user_cmd_rmt_pro_scan(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t mode = 0; + if (pparse_value->para_count > 1) + { + mode = pparse_value->dw_parameter[1]; + } + switch (mode) + { + case 0: + RmtProClient_ScanStart(dst); + break; + case 1: + { + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + RmtProClient_ScanStartWithFilter(dst, dev_uuid); + } + break; + case 2: + RmtProClient_ScanUnproDeviceNum(dst, 3); + break; + default: + break; + } + + return (USER_CMD_RESULT_OK); +} +#endif + +static user_cmd_parse_result_t user_cmd_data_transmission_notify(user_cmd_parse_value_t + *pparse_value) +{ + uint8_t conn_id = pparse_value->dw_parameter[0]; + uint8_t data_len = pparse_value->para_count - 1; + uint8_t data[20]; + if (data_len > 20) + { + data_len = 20; + } + + for (uint8_t i = 0; i < data_len; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + + datatrans_server_notify(conn_id, data, data_len); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_generic_on_off_publish(user_cmd_parse_value_t *pparse_value) +{ + generic_on_off_t on_off = (generic_on_off_t)pparse_value->dw_parameter[0]; + mesh_model_p pmodel = generic_on_off_server_model.pmodel; + + pmodel->pub_params.pub_addr = 0xFEFF; + pmodel->pub_params.pub_ttl = 0x3F; + generic_on_off_publish(&generic_on_off_server_model, on_off); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_write(user_cmd_parse_value_t *pparse_value) +{ + uint8_t para_count = pparse_value->para_count; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + uint8_t data[75]; +#else + uint8_t data[18]; +#endif + + for (uint8_t i = 0; i < para_count - 3; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + datatrans_write(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[para_count - 2], para_count - 3, data, + pparse_value->dw_parameter[para_count - 1]); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_read(user_cmd_parse_value_t *pparse_value) +{ + datatrans_read(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const user_cmd_table_entry_t device_cmd_table[] = +{ + // mesh common cmd + MESH_COMMON_CMD, + TEST_CMD, + // device cmd + { + "nr", + "nr [mode]\n\r", + "node reset\n\r", + user_cmd_node_reset + }, + // prov + { + "pcs", + "pcs [public key oob] [static oob] [output size] [output action] [input size] [input action]\n\r", + "provision capability set\n\r", + user_cmd_prov_capa_set + }, +#if MESH_LPN + { + "lpninit", + "lpninit [fn_num]\n\r", + "low power node init\n\r", + user_cmd_lpn_init + }, + { + "lpndeinit", + "lpndeinit\n\r", + "low power node deinit\n\r", + user_cmd_lpn_deinit + }, + { + "lpnreq", + "lpnreq [fn_index] [net_key_index] [poll int(100ms)] [poll to(100ms)] [rx delay(ms)] [rx widen(ms)]\n\r", + "LPN request to estabish a friendship\n\r", + user_cmd_lpn_req + }, + { + "lpnsub", + "lpnsub [fn_index] [addr] [add/rm]\n\r", + "LPN subsript list add or rm\n\r", + user_cmd_lpn_sub + }, + { + "lpnclear", + "lpnclear [fn_index]\n\r", + "LPN clear\n\r", + user_cmd_lpn_clear + }, +#endif +#if MESH_RMT_PRO_CLIENT + { + "rmtproscan", + "rmtproscan [dst addr]\n\r", + "command remote server to scan\n\r", + user_cmd_rmt_pro_scan + }, +#endif + { + "dtn", + "dtn [conn_id] [value...]\n\r", + "data transmission notify\n\r", + user_cmd_data_transmission_notify + }, + { + "dtw", + "dtw [dst] [data...] [app_key_index] [ack] \n\r", + "data transmission write data\n\r", + user_cmd_datatrans_write + }, + { + "dtr", + "dtr [dst] [len] [app_key_index]\n\r", + "data transmission read data\n\r", + user_cmd_datatrans_read + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +const struct bt_mesh_api_hdl devicecmds[] = +{ + GEN_MESH_HANDLER(_node_reset) + GEN_MESH_HANDLER(_prov_capa_set) +#if MESH_LPN + GEN_MESH_HANDLER(_lpn_init) + GEN_MESH_HANDLER(_lpn_deinit) + GEN_MESH_HANDLER(_lpn_req) + GEN_MESH_HANDLER(_lpn_sub) + GEN_MESH_HANDLER(_lpn_clear) +#endif +#if MESH_FN + GEN_MESH_HANDLER(_fn_init) + GEN_MESH_HANDLER(_fn_deinit) +#endif + GEN_MESH_HANDLER(_data_transmission_notify) + GEN_MESH_HANDLER(_generic_on_off_publish) + GEN_MESH_HANDLER(_datatrans_write) + GEN_MESH_HANDLER(_datatrans_read) + GEN_MESH_HANDLER(_connect) + GEN_MESH_HANDLER(_disconnect) + GEN_MESH_HANDLER(_list) + GEN_MESH_HANDLER(_dev_info_show) +}; +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.h new file mode 100644 index 00000000..6e831ea0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.h @@ -0,0 +1,36 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _DEV_CMD_H_ +#define _DEV_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_config.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_cmd_types.h" +#endif + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +extern const user_cmd_table_entry_t device_cmd_table[]; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern const struct bt_mesh_api_hdl devicecmds[]; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.c new file mode 100644 index 00000000..283d8da6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.c @@ -0,0 +1,1893 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file client_cmd.c + * @brief Source file for mesh client model cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#include "trace.h" +#include "app_msg.h" +#include "gap_wrapper.h" +#include "client_cmd.h" +#include "mesh_api.h" +#include "health.h" +#include "generic_client_app.h" +#include "light_client_app.h" + + +/** + * @brief configuration model parameter get command + * @param pparse_value - parsed parameters + * @return command execute status + */ +user_cmd_parse_result_t user_cmd_cmg(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint8_t model; + if (pparse_value->para_count < 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + dst = pparse_value->dw_parameter[0]; + model = pparse_value->dw_parameter[1]; + user_cmd_parse_result_t ret = USER_CMD_RESULT_OK; + switch (model) + { + case 0: + cfg_beacon_get(dst); + break; + case 1: + cfg_compo_data_get(dst, pparse_value->dw_parameter[2]); + break; + case 2: + cfg_default_ttl_get(dst); + break; + case 3: + cfg_proxy_get(dst); + break; + case 4: + cfg_frnd_get(dst); + break; + case 5: + cfg_relay_get(dst); + break; + case 6: + cfg_model_pub_get(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + break; + case 7: + cfg_model_sub_get(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + break; + case 8: + cfg_net_key_get(dst); + break; + case 9: + cfg_app_key_get(dst, pparse_value->dw_parameter[2]); + break; + case 10: + cfg_model_app_get(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + break; + case 11: + cfg_node_identity_get(dst, pparse_value->dw_parameter[2]); + break; + case 13: + cfg_hb_pub_get(dst); + break; + case 14: + cfg_hb_sub_get(dst); + break; + case 15: + cfg_net_transmit_get(dst); + break; + case 16: + cfg_lpn_poll_timeout_get(dst, pparse_value->dw_parameter[2]); + break; + default: + ret = USER_CMD_RESULT_WRONG_PARAMETER; + break; + } + return ret; +} + +/** + * @brief configuration model parameter set command + * @param pparse_value - parsed parameters + * @return command execute status + */ +user_cmd_parse_result_t user_cmd_cms(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint8_t model; + if (pparse_value->para_count < 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + dst = pparse_value->dw_parameter[0]; + model = pparse_value->dw_parameter[1]; + user_cmd_parse_result_t ret = USER_CMD_RESULT_OK; + switch (model) + { + case 0: + cfg_beacon_set(dst, pparse_value->dw_parameter[2]); + break; + case 2: + cfg_default_ttl_set(dst, pparse_value->dw_parameter[2]); + break; + case 3: + cfg_proxy_set(dst, pparse_value->dw_parameter[2]); + break; + case 4: + cfg_frnd_set(dst, pparse_value->dw_parameter[2]); + break; + case 5: + cfg_relay_set(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4]); + break; + case 6: + { + pub_key_info_t pub_key_info = {pparse_value->dw_parameter[5], pparse_value->dw_parameter[6], 0}; + pub_period_t pub_period = {pparse_value->dw_parameter[8] & 0x3f, pparse_value->dw_parameter[8] >> 6}; + pub_retrans_info_t pub_retrans_info = {pparse_value->dw_parameter[9], pparse_value->dw_parameter[10]}; + uint8_t addr[16]; + if (0 == pparse_value->dw_parameter[3]) + { + uint16_t element_addr = (uint16_t)(pparse_value->dw_parameter[4]); + LE_WORD2EXTRN(addr, element_addr); + } + else + { + plt_hex_to_bin(addr, (uint8_t *)pparse_value->pparameter[4], 16); + } + + cfg_model_pub_set(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + addr, pub_key_info, pparse_value->dw_parameter[7], pub_period, + pub_retrans_info, pparse_value->dw_parameter[11]); + } + break; + case 7: + { + uint8_t mode = pparse_value->dw_parameter[2]; + uint8_t addr[16]; + if ((mode < 4) && (2 != mode)) + { + if (0 == pparse_value->dw_parameter[3]) + { + uint16_t element_addr = (uint16_t)(pparse_value->dw_parameter[5]); + LE_WORD2EXTRN(addr, element_addr); + } + else + { + plt_hex_to_bin(addr, (uint8_t *)pparse_value->pparameter[5], 16); + } + } + switch (mode) + { + case 0: + cfg_model_sub_add(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + addr, pparse_value->dw_parameter[6]); + break; + case 1: + cfg_model_sub_delete(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + addr, pparse_value->dw_parameter[6]); + break; + case 2: + cfg_model_sub_delete_all(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4]); + break; + case 3: + cfg_model_sub_overwrite(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + addr, pparse_value->dw_parameter[6]); + break; + default: + break; + } + } + break; + case 8: + { + uint8_t mode = pparse_value->dw_parameter[2]; + uint8_t key[16]; + switch (mode) + { + case 0: + plt_hex_to_bin(key, (uint8_t *)pparse_value->pparameter[4], 16); + cfg_net_key_add(dst, pparse_value->dw_parameter[3], key); + break; + case 1: + plt_hex_to_bin(key, (uint8_t *)pparse_value->pparameter[4], 16); + cfg_net_key_update(dst, pparse_value->dw_parameter[3], key); + break; + case 2: + cfg_net_key_delete(dst, pparse_value->dw_parameter[3]); + break; + default: + break; + } + } + break; + case 9: + { + uint8_t mode = pparse_value->dw_parameter[2]; + uint8_t key[16]; + switch (mode) + { + case 0: + plt_hex_to_bin(key, (uint8_t *)pparse_value->pparameter[5], 16); + cfg_app_key_add(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + key); + break; + case 1: + plt_hex_to_bin(key, (uint8_t *)pparse_value->pparameter[5], 16); + cfg_app_key_update(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + key); + break; + case 2: + cfg_app_key_delete(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4]); + break; + default: + break; + } + } + break; + case 10: + { + uint8_t mode = pparse_value->dw_parameter[2]; + switch (mode) + { + case 0: + cfg_model_app_bind(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5]); + break; + case 1: + cfg_model_app_unbind(dst, pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5]); + break; + default: + break; + } + } + break; + case 11: + cfg_node_identity_set(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + break; + case 12: + cfg_node_reset(dst); + break; + case 13: + { + hb_pub_features_t features = {pparse_value->dw_parameter[6]}; + cfg_hb_pub_set(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[5], + features, pparse_value->dw_parameter[7]); + } + break; + case 14: + cfg_hb_sub_set(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4]); + break; + case 15: + cfg_net_transmit_set(dst, pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + break; + default: + ret = USER_CMD_RESULT_WRONG_PARAMETER; + break; + } + return ret; +} + +user_cmd_parse_result_t user_cmd_gdtt_get(user_cmd_parse_value_t *pparse_value) +{ + generic_default_transition_time_get(&model_gdtt_client, + pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_gdtt_set(user_cmd_parse_value_t *pparse_value) +{ + generic_transition_time_t trans_time = {pparse_value->dw_parameter[1], pparse_value->dw_parameter[2]}; + generic_default_transition_time_set(&model_gdtt_client, + pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], trans_time, + pparse_value->dw_parameter[3]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_fault_get(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + health_fault_get(&model_health_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_fault_clear(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + + health_fault_clear(&model_health_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_fault_test(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 5) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + health_fault_test(&model_health_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_period_get(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + health_period_get(&model_health_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_period_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + health_period_set(&model_health_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_attn_get(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + health_attn_get(&model_health_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_health_attn_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + + health_attn_set(&model_health_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_on_off_get(user_cmd_parse_value_t *pparse_value) +{ + generic_on_off_get(&model_goo_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_on_off_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + generic_on_off_set(&model_goo_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], (generic_on_off_t)pparse_value->dw_parameter[1], + tid, optional, trans_time, pparse_value->dw_parameter[6], pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_level_get(user_cmd_parse_value_t *pparse_value) +{ + generic_level_get(&model_gl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_level_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + generic_level_set(&model_gl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + tid, optional, trans_time, pparse_value->dw_parameter[6], + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_delta_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + generic_delta_set(&model_gl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + tid, optional, trans_time, pparse_value->dw_parameter[6], + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_move_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + generic_move_set(&model_gl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + tid, optional, trans_time, pparse_value->dw_parameter[6], + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + + +user_cmd_parse_result_t user_cmd_generic_on_powerup_get(user_cmd_parse_value_t *pparse_value) +{ + generic_on_power_up_get(&model_gpoo_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_on_powerup_set(user_cmd_parse_value_t *pparse_value) +{ + generic_on_power_up_set(&model_gpoo_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], (generic_on_power_up_t)pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + + +user_cmd_parse_result_t user_cmd_generic_power_level_get(user_cmd_parse_value_t *pparse_value) +{ + generic_power_level_get(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_power_level_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + generic_power_level_set(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + tid, optional, trans_time, pparse_value->dw_parameter[6], + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_power_last_get(user_cmd_parse_value_t *pparse_value) +{ + generic_power_last_get(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_power_default_get(user_cmd_parse_value_t *pparse_value) +{ + generic_power_default_get(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_power_default_set(user_cmd_parse_value_t *pparse_value) +{ + generic_power_default_set(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_power_range_get(user_cmd_parse_value_t *pparse_value) +{ + generic_power_range_get(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_power_range_set(user_cmd_parse_value_t *pparse_value) +{ + generic_power_range_set(&model_gpl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_battery_get(user_cmd_parse_value_t *pparse_value) +{ + generic_battery_get(&model_gb_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint16_t app_key_index; + dst = pparse_value->dw_parameter[0]; + app_key_index = pparse_value->dw_parameter[1]; + light_lightness_get(&light_lightness_client, dst, app_key_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + light_lightness_set(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], tid, optional, trans_time, + pparse_value->dw_parameter[6], pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_linear_get(user_cmd_parse_value_t + *pparse_value) +{ + uint16_t dst; + uint16_t app_key_index; + dst = pparse_value->dw_parameter[0]; + app_key_index = pparse_value->dw_parameter[1]; + light_lightness_linear_get(&light_lightness_client, dst, app_key_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_linear_set(user_cmd_parse_value_t + *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + light_lightness_linear_set(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], tid, optional, trans_time, + pparse_value->dw_parameter[6], pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_last_get(user_cmd_parse_value_t *pparse_value) +{ + light_lightness_last_get(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_default_get(user_cmd_parse_value_t *pparse_value) +{ + light_lightness_default_get(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_default_set(user_cmd_parse_value_t *pparse_value) +{ + light_lightness_default_set(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_range_get(user_cmd_parse_value_t *pparse_value) +{ + light_lightness_range_get(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lightness_range_set(user_cmd_parse_value_t *pparse_value) +{ + light_lightness_range_set(&light_lightness_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_get(user_cmd_parse_value_t *pparse_value) +{ + light_ctl_get(&light_ctl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 6) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[6], + pparse_value->dw_parameter[7] + }; + + light_ctl_set(&light_ctl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[5], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + pparse_value->dw_parameter[3], tid, optional, trans_time, + pparse_value->dw_parameter[8], pparse_value->dw_parameter[4]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_temperature_get(user_cmd_parse_value_t *pparse_value) +{ + light_ctl_temperature_get(&light_ctl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_temperature_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 5) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[5], + pparse_value->dw_parameter[6] + }; + + + light_ctl_temperature_set(&light_ctl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + tid, optional, trans_time, pparse_value->dw_parameter[7], pparse_value->dw_parameter[3]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_temperature_range_get(user_cmd_parse_value_t + *pparse_value) +{ + light_ctl_temperature_range_get(&light_ctl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_temperature_range_set(user_cmd_parse_value_t + *pparse_value) +{ + light_ctl_temperature_range_set(&light_ctl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_default_get(user_cmd_parse_value_t *pparse_value) +{ + light_ctl_default_get(&light_ctl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_ctl_default_set(user_cmd_parse_value_t *pparse_value) +{ + light_ctl_default_set(&light_ctl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[5], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint16_t app_key_index; + dst = pparse_value->dw_parameter[0]; + app_key_index = pparse_value->dw_parameter[1]; + light_hsl_get(&light_hsl_client, dst, app_key_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 6) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[6], + pparse_value->dw_parameter[7] + }; + + light_hsl_set(&light_hsl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[5], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], tid, optional, trans_time, pparse_value->dw_parameter[8], + pparse_value->dw_parameter[4]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_target_get(user_cmd_parse_value_t *pparse_value) +{ + light_hsl_target_get(&light_hsl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_hue_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint16_t app_key_index; + dst = pparse_value->dw_parameter[0]; + app_key_index = pparse_value->dw_parameter[1]; + light_hsl_hue_get(&light_hsl_client, dst, app_key_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_hue_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + light_hsl_hue_set(&light_hsl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], tid, optional, trans_time, + pparse_value->dw_parameter[6], pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; + +} + +user_cmd_parse_result_t user_cmd_light_hsl_saturation_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint16_t app_key_index; + dst = pparse_value->dw_parameter[0]; + app_key_index = pparse_value->dw_parameter[1]; + light_hsl_saturation_get(&light_hsl_client, dst, app_key_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_saturation_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + light_hsl_saturation_set(&light_hsl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], tid, optional, trans_time, + pparse_value->dw_parameter[6], pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + + +user_cmd_parse_result_t user_cmd_light_hsl_default_get(user_cmd_parse_value_t *pparse_value) +{ + light_hsl_default_get(&light_hsl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_default_set(user_cmd_parse_value_t *pparse_value) +{ + light_hsl_default_set(&light_hsl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[5], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[4]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_range_get(user_cmd_parse_value_t *pparse_value) +{ + light_hsl_range_get(&light_hsl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_hsl_range_set(user_cmd_parse_value_t *pparse_value) +{ + light_hsl_range_set(&light_hsl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[6], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], pparse_value->dw_parameter[5]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_set(user_cmd_parse_value_t *pparse_value) +{ + tai_time_t time; + time.tai_seconds[0] = pparse_value->dw_parameter[1]; + time.tai_seconds[1] = pparse_value->dw_parameter[1] >> 8; + time.tai_seconds[2] = pparse_value->dw_parameter[1] >> 16; + time.tai_seconds[3] = pparse_value->dw_parameter[1] >> 24; + time.tai_seconds[4] = pparse_value->dw_parameter[2]; + time.subsecond = pparse_value->dw_parameter[3]; + time.uncertainty = pparse_value->dw_parameter[4]; + time.time_authority = pparse_value->dw_parameter[5]; + time.tai_utc_delta = pparse_value->dw_parameter[6]; + time.time_zone_offset = pparse_value->dw_parameter[7]; + time_set(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[8], time); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_get(user_cmd_parse_value_t *pparse_value) +{ + time_get(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_zone_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t change[5]; + change[0] = pparse_value->dw_parameter[2]; + change[1] = pparse_value->dw_parameter[2] >> 8; + change[2] = pparse_value->dw_parameter[2] >> 16; + change[3] = pparse_value->dw_parameter[2] >> 24; + change[4] = pparse_value->dw_parameter[3]; + + time_set_zone(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[1], + change); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_zone_get(user_cmd_parse_value_t *pparse_value) +{ + time_get_zone(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_tai_utc_delta_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t delta[5]; + delta[0] = pparse_value->dw_parameter[2]; + delta[1] = pparse_value->dw_parameter[2] >> 8; + delta[2] = pparse_value->dw_parameter[2] >> 16; + delta[3] = pparse_value->dw_parameter[2] >> 24; + delta[4] = pparse_value->dw_parameter[3]; + + time_set_tai_utc_delta(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[1], + delta); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_tai_utc_delta_get(user_cmd_parse_value_t *pparse_value) +{ + time_get_tai_utc_delta(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_role_set(user_cmd_parse_value_t *pparse_value) +{ + time_set_role(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], (time_role_t)(pparse_value->dw_parameter[1])); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time_role_get(user_cmd_parse_value_t *pparse_value) +{ + time_get_role(&model_time_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + + +user_cmd_parse_result_t user_cmd_scene_store(user_cmd_parse_value_t *pparse_value) +{ + scene_store(&model_scene_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scene_recall(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + scene_recall(&model_scene_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], tid, optional, trans_time, + pparse_value->dw_parameter[6], pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scene_get(user_cmd_parse_value_t *pparse_value) +{ + scene_get(&model_scene_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scene_register_get(user_cmd_parse_value_t *pparse_value) +{ + scene_register_get(&model_scene_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scene_delete(user_cmd_parse_value_t *pparse_value) +{ + scene_delete(&model_scene_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_descriptor_get(user_cmd_parse_value_t *pparse_value) +{ + sensor_descriptor_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_cadence_get(user_cmd_parse_value_t *pparse_value) +{ + sensor_cadence_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_cadence_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t trigger_down[10]; + uint8_t trigger_up[10]; + uint8_t cadence_low[10]; + uint8_t cadence_high[10]; + sensor_cadence_t cadence; + cadence.fast_cadence_period_divisor = pparse_value->dw_parameter[2]; + cadence.status_trigger_type = pparse_value->dw_parameter[3]; + cadence.status_trigger_delta_down = trigger_down; + cadence.status_trigger_delta_up = trigger_up; + cadence.fast_cadence_low = cadence_low; + cadence.fast_cadence_high = cadence_high; + uint8_t data_len = pparse_value->para_count - 7; + uint8_t trigger_len = 0; + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == cadence.status_trigger_type) + { + cadence.raw_value_len = data_len / 4; + trigger_len = cadence.raw_value_len; + } + else + { + cadence.raw_value_len = (data_len - 4) / 2; + trigger_len = 2; + } + + uint32_t *pdata = pparse_value->dw_parameter + 4; + for (uint8_t i = 0; i < trigger_len; ++i) + { + trigger_down[i] = *pdata ++; + } + + for (uint8_t i = 0; i < trigger_len; ++i) + { + trigger_up[i] = *pdata ++; + } + + cadence.status_min_interval = *pdata ++; + + for (uint8_t i = 0; i < cadence.raw_value_len; ++i) + { + cadence_low[i] = *pdata ++; + } + + for (uint8_t i = 0; i < cadence.raw_value_len; ++i) + { + cadence_high[i] = *pdata ++; + } + + bool ack = *pdata ++; + uint16_t app_key_index = *pdata; + + sensor_cadence_set(&model_sensor_client, pparse_value->dw_parameter[0], + app_key_index, pparse_value->dw_parameter[1], &cadence, ack); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_settings_get(user_cmd_parse_value_t *pparse_value) +{ + sensor_settings_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_setting_get(user_cmd_parse_value_t *pparse_value) +{ + sensor_setting_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_setting_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t data_len = pparse_value->para_count - 5; + uint8_t setting_raw[10]; + for (uint8_t i = 0; i < data_len; ++i) + { + setting_raw[i] = pparse_value->dw_parameter[3 + i]; + } + sensor_setting_set(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[pparse_value->para_count - 1], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], + data_len, setting_raw, pparse_value->dw_parameter[pparse_value->para_count - 2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_get(user_cmd_parse_value_t *pparse_value) +{ + sensor_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_column_get(user_cmd_parse_value_t *pparse_value) +{ + uint8_t data_len = pparse_value->para_count - 3; + uint8_t raw_value_x[10]; + for (uint8_t i = 0; i < data_len; ++i) + { + raw_value_x[i] = pparse_value->dw_parameter[2 + i]; + } + + sensor_column_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[pparse_value->para_count - 1], pparse_value->dw_parameter[1], + data_len, raw_value_x); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_sensor_series_get(user_cmd_parse_value_t *pparse_value) +{ + uint8_t data_len = (pparse_value->para_count - 3) / 2; + uint8_t raw_value_x1[10]; + uint8_t raw_value_x2[10]; + uint32_t *pdata = pparse_value->dw_parameter + 2; + for (uint8_t i = 0; i < data_len; ++i) + { + raw_value_x1[i] = *pdata ++; + } + + for (uint8_t i = 0; i < data_len; ++i) + { + raw_value_x2[i] = *pdata ++; + } + + sensor_series_get(&model_sensor_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[pparse_value->para_count - 1], pparse_value->dw_parameter[1], + data_len, raw_value_x1, raw_value_x2); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scheduler_get(user_cmd_parse_value_t *pparse_value) +{ + scheduler_get(&model_scheduler_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scheduler_action_get(user_cmd_parse_value_t *pparse_value) +{ + scheduler_action_get(&model_scheduler_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_scheduler_action_set(user_cmd_parse_value_t *pparse_value) +{ + scheduler_register_t scheduler = {pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[5], pparse_value->dw_parameter[6], + pparse_value->dw_parameter[7], pparse_value->dw_parameter[8], pparse_value->dw_parameter[9], + pparse_value->dw_parameter[10], pparse_value->dw_parameter[11], pparse_value->dw_parameter[12] + }; + scheduler_action_set(&model_scheduler_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[14], scheduler, pparse_value->dw_parameter[13]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_location_global_get(user_cmd_parse_value_t *pparse_value) +{ + generic_location_global_get(&model_generic_location_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_location_global_set(user_cmd_parse_value_t *pparse_value) +{ + generic_location_global_t global = {pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]}; + generic_location_global_set(&model_generic_location_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[5], global, pparse_value->dw_parameter[4]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_location_local_get(user_cmd_parse_value_t *pparse_value) +{ + generic_location_local_get(&model_generic_location_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_location_local_set(user_cmd_parse_value_t *pparse_value) +{ + generic_location_local_t local; + local.local_north = pparse_value->dw_parameter[1]; + local.local_east = pparse_value->dw_parameter[2]; + local.local_altitude = pparse_value->dw_parameter[3]; + local.floor_num = pparse_value->dw_parameter[4]; + local.uncertainty.stationary = pparse_value->dw_parameter[5]; + local.uncertainty.update_time = pparse_value->dw_parameter[6]; + local.uncertainty.precision = pparse_value->dw_parameter[7]; + generic_location_local_set(&model_generic_location_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[9], local, pparse_value->dw_parameter[8]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_user_properties_get(user_cmd_parse_value_t *pparse_value) +{ + generic_user_properties_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_user_property_get(user_cmd_parse_value_t *pparse_value) +{ + generic_user_property_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_user_property_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t property_value[20]; + uint8_t value_len = pparse_value->para_count - 4; + if (value_len > 20) + { + value_len = 20; + } + for (uint8_t i = 0; i < value_len; ++i) + { + property_value[i] = pparse_value->dw_parameter[4 + i]; + } + + generic_user_property_set(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[3], property_value, value_len, + pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_admin_properties_get(user_cmd_parse_value_t *pparse_value) +{ + generic_admin_properties_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_admin_property_get(user_cmd_parse_value_t *pparse_value) +{ + generic_admin_property_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_admin_property_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 5) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t property_value[20]; + uint8_t value_len = pparse_value->para_count - 5; + if (value_len > 20) + { + value_len = 20; + } + for (uint8_t i = 0; i < value_len; ++i) + { + property_value[i] = pparse_value->dw_parameter[5 + i]; + } + + generic_admin_property_set(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], + property_value, value_len, pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_manufacturer_properties_get(user_cmd_parse_value_t + *pparse_value) +{ + generic_manufacturer_properties_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_manufacturer_property_get(user_cmd_parse_value_t + *pparse_value) +{ + generic_manufacturer_property_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_manufacturer_property_set(user_cmd_parse_value_t + *pparse_value) +{ + generic_manufacturer_property_set(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[3], + pparse_value->dw_parameter[4], pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_generic_client_properties_get(user_cmd_parse_value_t *pparse_value) +{ + generic_client_properties_get(&model_gp_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst; + uint16_t app_key_index; + dst = pparse_value->dw_parameter[0]; + app_key_index = pparse_value->dw_parameter[1]; + light_xyl_get(&light_xyl_client, dst, app_key_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 6) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[6], + pparse_value->dw_parameter[7] + }; + + light_xyl_t xyl = {pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]}; + light_xyl_set(&light_xyl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[5], xyl, + tid, optional, trans_time, pparse_value->dw_parameter[8], pparse_value->dw_parameter[4]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_target_get(user_cmd_parse_value_t *pparse_value) +{ + light_xyl_target_get(&light_xyl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_default_get(user_cmd_parse_value_t *pparse_value) +{ + light_xyl_default_get(&light_xyl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_default_set(user_cmd_parse_value_t *pparse_value) +{ + light_xyl_t xyl = {pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]}; + light_xyl_default_set(&light_xyl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[5], xyl, + pparse_value->dw_parameter[4]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_range_get(user_cmd_parse_value_t *pparse_value) +{ + light_xyl_range_get(&light_xyl_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_xyl_range_set(user_cmd_parse_value_t *pparse_value) +{ + light_xyl_range_set(&light_xyl_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[6], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + pparse_value->dw_parameter[3], pparse_value->dw_parameter[4], pparse_value->dw_parameter[5]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_mode_get(user_cmd_parse_value_t *pparse_value) +{ + light_lc_mode_get(&light_lc_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_mode_set(user_cmd_parse_value_t *pparse_value) +{ + light_lc_mode_set(&light_lc_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[2], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[3]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_om_get(user_cmd_parse_value_t *pparse_value) +{ + light_lc_om_get(&light_lc_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_om_set(user_cmd_parse_value_t *pparse_value) +{ + light_lc_om_set(&light_lc_client, pparse_value->dw_parameter[0], pparse_value->dw_parameter[2], + pparse_value->dw_parameter[1], pparse_value->dw_parameter[3]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_light_on_off_set(user_cmd_parse_value_t *pparse_value) +{ + static uint8_t tid = 0; + tid++; + bool optional = FALSE; + if (pparse_value->para_count > 4) + { + optional = TRUE; + } + generic_transition_time_t trans_time = {pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5] + }; + + light_lc_light_on_off_set(&light_lc_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[3], + pparse_value->dw_parameter[1], tid, optional, trans_time, pparse_value->dw_parameter[6], + pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_light_on_off_get(user_cmd_parse_value_t *pparse_value) +{ + light_lc_light_on_off_get(&light_lc_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_property_get(user_cmd_parse_value_t *pparse_value) +{ + light_lc_property_get(&light_lc_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_light_lc_property_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count < 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t property_value[20]; + uint8_t value_len = pparse_value->para_count - 4; + if (value_len > 20) + { + value_len = 20; + } + for (uint8_t i = 0; i < value_len; ++i) + { + property_value[i] = pparse_value->dw_parameter[4 + i]; + } + + light_lc_property_set(&light_lc_client, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[1], + pparse_value->dw_parameter[3], property_value, value_len, pparse_value->dw_parameter[2]); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_private_beacon_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_PRB + private_beacon_get(pparse_value->dw_parameter[0], 0); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_private_beacon_set(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_PRB + if (pparse_value->para_count > 2) + { + private_beacon_set(pparse_value->dw_parameter[0], 0, pparse_value->dw_parameter[1], true, + pparse_value->dw_parameter[2]); + } + else + { + private_beacon_set(pparse_value->dw_parameter[0], 0, pparse_value->dw_parameter[1], false, 0); + } +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_private_gatt_proxy_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_PRB + private_gatt_proxy_get(pparse_value->dw_parameter[0], 0); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_private_gatt_proxy_set(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_PRB + private_gatt_proxy_set(pparse_value->dw_parameter[0], 0, pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_private_node_identity_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_PRB + private_node_identity_get(pparse_value->dw_parameter[0], 0, pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_private_node_identity_set(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_PRB + private_node_identity_set(pparse_value->dw_parameter[0], 0, pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_transfer_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + blob_transfer_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_transfer_start(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + uint8_t blob_id[8]; + plt_hex_to_bin(blob_id, (uint8_t *)pparse_value->pparameter[3], sizeof(blob_id)); + blob_transfer_start(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], blob_id, pparse_value->dw_parameter[4], + pparse_value->dw_parameter[5], pparse_value->dw_parameter[6]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_transfer_cancel(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + uint8_t blob_id[8]; + plt_hex_to_bin(blob_id, (uint8_t *)pparse_value->pparameter[2], sizeof(blob_id)); + blob_transfer_cancel(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], blob_id); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_block_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + blob_block_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_block_start(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + blob_block_start(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_chunk_transfer(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + uint16_t chunk_size = pparse_value->dw_parameter[3]; + uint8_t *pdata = plt_zalloc(chunk_size, RAM_TYPE_DATA_ON); + if (NULL == pdata) + { + return USER_CMD_RESULT_ERROR; + } + memset(pdata, 0x31, chunk_size); + blob_chunk_transfer(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pdata, chunk_size); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_blob_info_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_BLOB + blob_info_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_update_info_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_update_info_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_update_metadata_check(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + uint8_t metadata[255]; + uint8_t metadata_len = pparse_value->dw_parameter[4]; + plt_hex_to_bin(metadata, (uint8_t *)pparse_value->pparameter[3], metadata_len); + fw_update_fw_metadata_check(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], metadata, metadata_len); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_update_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_update_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_update_start(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + uint8_t blob_id[8]; + uint8_t metadata[255]; + uint8_t metadata_len = pparse_value->dw_parameter[7]; + /* parameter is string */ + if (pparse_value->dw_parameter[8]) { + plt_hex_to_bin(blob_id, (uint8_t *)pparse_value->pparameter[4], 8); + plt_hex_to_bin(metadata, (uint8_t *)pparse_value->pparameter[6], metadata_len); + } else { + memcpy(blob_id, pparse_value->pparameter[4], 8); + memcpy(metadata, pparse_value->pparameter[6], metadata_len); + } + + fw_update_start(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3], blob_id, + pparse_value->dw_parameter[5], metadata, metadata_len); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_update_cancel(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_update_cancel(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_update_apply(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_update_apply(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_recvs_add(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_receiver_t receiver; + receiver.addr = pparse_value->dw_parameter[2]; + receiver.update_fw_image_idx = pparse_value->dw_parameter[3]; + fw_dist_recvs_add(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], &receiver, 1); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_recvs_delete_all(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_recvs_delete_all(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_recvs_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_recvs_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[3]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_caps_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_caps_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_start(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_start_data_t start; + start.dist_app_key_index = pparse_value->dw_parameter[2]; + start.dist_ttl = pparse_value->dw_parameter[3]; + start.dist_timeout_base = pparse_value->dw_parameter[4]; + start.dist_transfer_mode = pparse_value->dw_parameter[5]; + start.update_policy = pparse_value->dw_parameter[6]; + start.rfu = 0; + start.dist_fw_image_idx = pparse_value->dw_parameter[7]; + uint8_t dist_dst_len = pparse_value->dw_parameter[9]; + if (2 == dist_dst_len) + { + *(uint16_t *)start.dist_multicast_addr = pparse_value->dw_parameter[8]; + } + else + { + plt_hex_to_bin(start.dist_multicast_addr, (uint8_t *)pparse_value->pparameter[8], 16); + } + + fw_dist_start(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], start, dist_dst_len); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_cancel(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_cancel(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_apply(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_apply(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_upload_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_upload_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_user_cmd_fw_dist_upload_start(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + uint8_t blob_id[8]; + plt_hex_to_bin(blob_id, (uint8_t *)pparse_value->pparameter[4], 8); + uint8_t metadata[64]; + plt_hex_to_bin(blob_id, (uint8_t *)pparse_value->pparameter[6], pparse_value->dw_parameter[7]); + uint8_t fw_id[64]; + plt_hex_to_bin(blob_id, (uint8_t *)pparse_value->pparameter[8], pparse_value->dw_parameter[9]); + fw_dist_upload_start(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2], + pparse_value->dw_parameter[3], blob_id, pparse_value->dw_parameter[5], + metadata, pparse_value->dw_parameter[7], fw_id, pparse_value->dw_parameter[9]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_upload_oob_start(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + uint8_t upload_uri[64]; + plt_hex_to_bin(upload_uri, (uint8_t *)pparse_value->pparameter[2], pparse_value->dw_parameter[3]); + uint8_t fw_id[64]; + plt_hex_to_bin(fw_id, (uint8_t *)pparse_value->pparameter[4], pparse_value->dw_parameter[5]); + fw_dist_upload_oob_start(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], upload_uri, + pparse_value->dw_parameter[3], fw_id, pparse_value->dw_parameter[5]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_upload_cancel(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_upload_cancel(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_fw_get(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + uint8_t fw_id[64]; + plt_hex_to_bin(fw_id, (uint8_t *)pparse_value->pparameter[2], pparse_value->dw_parameter[3]); + fw_dist_fw_get(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], fw_id, + pparse_value->dw_parameter[3]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_fw_get_by_index(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_fw_get_by_index(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], + pparse_value->dw_parameter[2]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_fw_delete(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + uint8_t fw_id[64]; + plt_hex_to_bin(fw_id, (uint8_t *)pparse_value->pparameter[2], pparse_value->dw_parameter[3]); + fw_dist_fw_delete(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1], fw_id, + pparse_value->dw_parameter[3]); +#endif + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_fw_dist_fw_delete_all(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_DFU + fw_dist_fw_delete_all(pparse_value->dw_parameter[0], pparse_value->dw_parameter[1]); +#endif + return USER_CMD_RESULT_OK; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.h new file mode 100644 index 00000000..e2b18974 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.h @@ -0,0 +1,1100 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file client_cmd.h + * @brief Head file for mesh client model cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _CLIENT_CMD_H +#define _CLIENT_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_api.h" +#include "blob_transfer.h" +#include "firmware_update.h" +#include "firmware_distribution.h" + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ + +/** + * @addtogroup CLIENT_CMD + * @{ + */ + +/** + * @defgroup Client_Cmd_Exported_Macros Client Command Exported Macros + * @brief + * @{ + */ +#define CLIENT_CMD \ + {\ + "cmg",\ + "cmg [dst] [model]\n\r",\ + "configuration model get parameters\n\r",\ + user_cmd_cmg\ + },\ + {\ + "cms",\ + "cms [dst] [model] [parameters]\n\r",\ + "configuration model set parameters\n\r",\ + user_cmd_cms\ + },\ + {\ + "gdttg",\ + "gdttg [dst address] [app key index]\n\r",\ + "generic default transition time get\n\r",\ + user_cmd_gdtt_get\ + },\ + {\ + "gdtts",\ + "gdtts [dst address] [steps] [resolution] [ack] [app key index]\n\r",\ + "generic default transition time set\n\r",\ + user_cmd_gdtt_set\ + },\ + {\ + "hfg",\ + "hfg [dst address] [app key index] [company id]\n\r",\ + "health fault get\n\r",\ + user_cmd_health_fault_get\ + },\ + {\ + "hfc",\ + "hfc [dst address] [app key index] [company_id] [ack]\n\r",\ + "health fault clear\n\r",\ + user_cmd_health_fault_clear\ + },\ + {\ + "hft",\ + "hft [dst address] [app key index] [test id] [company id] [ack]\n\r",\ + "health fault test\n\r",\ + user_cmd_health_fault_test\ + },\ + {\ + "hpg",\ + "hps [dst address] [app key index]\n\r",\ + "health period get\n\r",\ + user_cmd_health_period_get\ + },\ + {\ + "hps",\ + "hps [dst address] [app key index] [period] [ack]\n\r",\ + "health period set\n\r",\ + user_cmd_health_period_set\ + },\ + {\ + "hag",\ + "hag [dst address] [app key index]\n\r",\ + "health attention timer get\n\r",\ + user_cmd_health_attn_get\ + },\ + {\ + "has",\ + "has [dst address] [app key index] [time] [ack]\n\r",\ + "health attention timer set\n\r",\ + user_cmd_health_attn_set\ + },\ + {\ + "goog",\ + "goog [dst] [app_key_index]\n\r",\ + "generic on off get\n\r",\ + user_cmd_generic_on_off_get\ + },\ + {\ + "goos",\ + "goos [dst] [on/off] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "generic on off set\n\r",\ + user_cmd_generic_on_off_set\ + },\ + {\ + "glg",\ + "glg [dst] [app_key_index]\n\r",\ + "generic level get\n\r",\ + user_cmd_generic_level_get\ + },\ + {\ + "gls",\ + "gls [dst] [level] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "generic level set\n\r",\ + user_cmd_generic_level_set\ + },\ + {\ + "gds",\ + "gds [dst] [delta] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "generic delta set\n\r",\ + user_cmd_generic_delta_set\ + },\ + {\ + "gms",\ + "gms [dst] [move] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "generic move set\n\r",\ + user_cmd_generic_move_set\ + },\ + {\ + "gopug",\ + "gopug [dst] [app_key_index]\n\r",\ + "generic on power up get\n\r",\ + user_cmd_generic_on_powerup_get\ + },\ + {\ + "gopus",\ + "gopus [dst] [power] [ack] [app_key_index]\n\r",\ + "generic on power up set\n\r",\ + user_cmd_generic_on_powerup_set\ + },\ + {\ + "gplg",\ + "gplg [dst] [app_key_index]\n\r",\ + "generic power level get\n\r",\ + user_cmd_generic_power_level_get\ + },\ + {\ + "gpls",\ + "gpls [dst] [level] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "generic power level set\n\r",\ + user_cmd_generic_power_level_set\ + },\ + {\ + "gpllg",\ + "gpllg [dst] [app_key_index]\n\r",\ + "generic power last get\n\r",\ + user_cmd_generic_power_last_get\ + },\ + {\ + "gpdg",\ + "gpdg [dst] [app_key_index]\n\r",\ + "generic power default get\n\r",\ + user_cmd_generic_power_default_get\ + },\ + {\ + "gpds",\ + "gpds [dst] [power] [ack] [app_key_index]\n\r",\ + "generic power default set\n\r",\ + user_cmd_generic_power_default_set\ + },\ + {\ + "gprg",\ + "gprg [dst] [app_key_index]\n\r",\ + "generic power range get\n\r",\ + user_cmd_generic_power_range_get\ + },\ + {\ + "gprs",\ + "gprs [dst] [min] [max] [ack] [app_key_index]\n\r",\ + "generic power range set\n\r",\ + user_cmd_generic_power_range_set\ + },\ + {\ + "gbg",\ + "gbg [dst] [app_key_index]\n\r",\ + "generic battery get\n\r",\ + user_cmd_generic_battery_get\ + },\ + {\ + "llg",\ + "llg [dst] [app_key_index]\n\r",\ + "light lightness get\n\r",\ + user_cmd_light_lightness_get\ + },\ + {\ + "lls",\ + "lls [dst] [lightness] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light lightness set\n\r",\ + user_cmd_light_lightness_set\ + },\ + {\ + "lllg",\ + "lllg [dst] [app_key_index]\n\r",\ + "light lightness linear get\n\r",\ + user_cmd_light_lightness_linear_get\ + },\ + {\ + "llls",\ + "llls [dst] [lightness] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light lightness linear set\n\r",\ + user_cmd_light_lightness_linear_set\ + },\ + {\ + "lllag",\ + "lllag [dst] [app_key_index]\n\r",\ + "light lightness last get\n\r",\ + user_cmd_light_lightness_last_get\ + },\ + {\ + "lldg",\ + "lldg [dst] [app_key_index]\n\r",\ + "light lightness default get\n\r",\ + user_cmd_light_lightness_default_get\ + },\ + {\ + "llds",\ + "llds [dst] [lightness] [ack] [app_key_index]\n\r",\ + "light lightness default set\n\r",\ + user_cmd_light_lightness_default_set\ + },\ + {\ + "llrg",\ + "llrg [dst] [app_key_index]\n\r",\ + "light lightness range get\n\r",\ + user_cmd_light_lightness_range_get\ + },\ + {\ + "llrs",\ + "llrs [dst] [min] [max] [ack] [app_key_index]\n\r",\ + "light lightness range set\n\r",\ + user_cmd_light_lightness_range_set\ + },\ + {\ + "lcg",\ + "lcg [dst] [app_key_index]\n\r",\ + "light ctl set\n\r",\ + user_cmd_light_ctl_get\ + },\ + {\ + "lcs",\ + "lcs [dst] [lightness] [temperature] [delta uv] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light ctl set\n\r",\ + user_cmd_light_ctl_set\ + },\ + {\ + "lctg",\ + "lctg [dst] [app_key_index]\n\r",\ + "light ctl temperature get\n\r",\ + user_cmd_light_ctl_temperature_get\ + },\ + {\ + "lcts",\ + "lcts [dst] [temperature] [delta uv] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light ctl temperature set\n\r",\ + user_cmd_light_ctl_temperature_set\ + },\ + {\ + "lctrg",\ + "lctrg [dst] [app_key_index]\n\r",\ + "light ctl temperature range get\n\r",\ + user_cmd_light_ctl_temperature_range_get\ + },\ + {\ + "lctrs",\ + "lctrs [dst] [min] [max] [ack] [app_key_index]\n\r",\ + "light ctl temperature range set\n\r",\ + user_cmd_light_ctl_temperature_range_set\ + },\ + {\ + "lcdg",\ + "lcdg [dst] [app_key_index]\n\r",\ + "light ctl default get\n\r",\ + user_cmd_light_ctl_default_get\ + },\ + {\ + "lcds",\ + "lcds [dst] [lightness] [temperature] [delta uv] [ack] [app_key_index]\n\r",\ + "light ctl default set\n\r",\ + user_cmd_light_ctl_default_set\ + },\ + {\ + "lhg",\ + "lhg [dst] [app_key_index]\n\r",\ + "light hsl get\n\r",\ + user_cmd_light_hsl_get\ + },\ + {\ + "lhs",\ + "lhs [dst] [hue] [saturation] [lightness] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light hsl set\n\r",\ + user_cmd_light_hsl_set\ + },\ + {\ + "lhtg",\ + "lhtg [dst] [app_key_index]\n\r",\ + "light hsl target get\n\r",\ + user_cmd_light_hsl_target_get\ + },\ + {\ + "lhhg",\ + "lhhg [dst] [app_key_index]\n\r",\ + "light hsl hue get\n\r",\ + user_cmd_light_hsl_hue_get\ + },\ + {\ + "lhhs",\ + "lhhs [dst] [hue] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light hsl hue set\n\r",\ + user_cmd_light_hsl_hue_set\ + },\ + {\ + "lhsg",\ + "lhsg [dst] [app_key_index]\n\r",\ + "light hsl saturation get\n\r",\ + user_cmd_light_hsl_saturation_get\ + },\ + {\ + "lhss",\ + "lhss [dst] [saturation] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light hsl saturation set\n\r",\ + user_cmd_light_hsl_saturation_set\ + },\ + {\ + "lhdg",\ + "lhdg [dst] [app_key_index]\n\r",\ + "light hsl default get\n\r",\ + user_cmd_light_hsl_default_get\ + },\ + {\ + "lhds",\ + "lhds [dst] [lightness] [hue] [saturation] [ack] [app_key_index]\n\r",\ + "light hsl default set\n\r",\ + user_cmd_light_hsl_default_set\ + },\ + {\ + "lhrg",\ + "lhrg [dst] [app_key_index]\n\r",\ + "light hsl range get\n\r",\ + user_cmd_light_hsl_range_get\ + },\ + {\ + "lhrs",\ + "lhrs [dst] [hue min] [hue max] [saturation min] [saturation max] [ack] [app_key_index]\n\r",\ + "light hsl range set\n\r",\ + user_cmd_light_hsl_range_set\ + },\ + {\ + "ts",\ + "ts [dst] [tai second low] [tai second high] [subsecond] [uncertainty] [time authority] [tai utc delta] [time zone offset] [app_key_index]\n\r",\ + "time set\n\r",\ + user_cmd_time_set\ + },\ + {\ + "tg",\ + "tg [dst] [app_key_index]\n\r",\ + "time get\n\r",\ + user_cmd_time_get\ + },\ + {\ + "tzs",\ + "tzs [dst] [time zone offset new] [tai of zone change low] [tai of zone change high] [app_key_index]\n\r",\ + "time zone set\n\r",\ + user_cmd_time_zone_set\ + },\ + {\ + "tzg",\ + "tzg [dst] [app_key_index]\n\r",\ + "time zone get\n\r",\ + user_cmd_time_zone_get\ + },\ + {\ + "ttuds",\ + "ttuds [dst] [tai utc delta new] [tai of delta change low] [tai of delta change high] [app_key_index]\n\r",\ + "time tai utc delta set\n\r",\ + user_cmd_time_tai_utc_delta_set\ + },\ + {\ + "ttudg",\ + "ttudg [dst] [app_key_index]\n\r",\ + "time tai utc delta get\n\r",\ + user_cmd_time_tai_utc_delta_get\ + },\ + {\ + "trs",\ + "trs [dst] [role] [app_key_index]\n\r",\ + "time role set\n\r",\ + user_cmd_time_role_set\ + },\ + {\ + "trg",\ + "trg [dst] [app_key_index]\n\r",\ + "time role get\n\r",\ + user_cmd_time_role_get\ + },\ + {\ + "ss",\ + "ss [dst] [scene number] [ack] [app_key_index]\n\r",\ + "scene store\n\r",\ + user_cmd_scene_store\ + },\ + {\ + "sr",\ + "sr [dst] [scene number] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "scene recall\n\r",\ + user_cmd_scene_recall\ + },\ + {\ + "sg",\ + "sg [dst] [app_key_index]\n\r",\ + "scene get\n\r",\ + user_cmd_scene_get\ + },\ + {\ + "srg",\ + "srg [dst] [app_key_index]\n\r",\ + "scene register get\n\r",\ + user_cmd_scene_register_get\ + },\ + {\ + "sd",\ + "sd [dst] [scene number] [ack] [app_key_index]\n\r",\ + "scene delete\n\r",\ + user_cmd_scene_delete\ + },\ + {\ + "sdg",\ + "sdg [dst] [property id] [app_key_index]\n\r",\ + "sensor descriptor get\n\r",\ + user_cmd_sensor_descriptor_get\ + },\ + {\ + "scg",\ + "scg [dst] [property id] [app_key_index]\n\r",\ + "sensor cadence get\n\r",\ + user_cmd_sensor_cadence_get\ + },\ + {\ + "scs",\ + "scs [dst] [property id] [divisor] [tirgger type] [trigger delta] [min interval] [fast cadence] [ack] [app_key_index]\n\r",\ + "sensor cadence set\n\r",\ + user_cmd_sensor_cadence_set\ + },\ + {\ + "sssg",\ + "sssg [dst] [property id] [app_key_index]\n\r",\ + "sensor settings get\n\r",\ + user_cmd_sensor_settings_get\ + },\ + {\ + "sss",\ + "sss [dst] [property id] [setting property id] [raw data] [ack] [app_key_index]\n\r",\ + "sensor setting set\n\r",\ + user_cmd_sensor_setting_set\ + },\ + {\ + "ssg",\ + "ssg [dst] [property id] [setting property id] [app_key_index]\n\r",\ + "sensor setting get\n\r",\ + user_cmd_sensor_setting_get\ + },\ + {\ + "seg",\ + "seg [dst] [property id] [app_key_index]\n\r",\ + "sensor get\n\r",\ + user_cmd_sensor_get\ + },\ + {\ + "scog",\ + "scog [dst] [property id] [raw value x] [app_key_index]\n\r",\ + "sensor column get\n\r",\ + user_cmd_sensor_column_get\ + },\ + {\ + "sseg",\ + "sseg [dst] [property id] [raw value xn] [app_key_index]\n\r",\ + "sensor series get\n\r",\ + user_cmd_sensor_series_get\ + },\ + {\ + "scheg",\ + "scheg [dst] [app_key_index]\n\r",\ + "scheduler get\n\r",\ + user_cmd_scheduler_get\ + },\ + {\ + "scheag",\ + "scheag [dst] [index] [app_key_index]\n\r",\ + "scheduler action get\n\r",\ + user_cmd_scheduler_action_get\ + },\ + {\ + "scheas",\ + "scheas [dst] [index] [year] [month] [day] [hour] [minute] [second] [day_of_week] [action] [num_steps] [step_resolution] [scene_number] [ack] [app_key_index]\n\r",\ + "scheduler action set\n\r",\ + user_cmd_scheduler_action_set\ + },\ + {\ + "glgg",\ + "glgg [dst] [app key index]\n\r",\ + "generic location global get\n\r",\ + user_cmd_generic_location_global_get\ + },\ + {\ + "glgs",\ + "glgs [dst] [latitude] [longitude] [altitude] [ack] [app key index]\n\r",\ + "generic location global set\n\r",\ + user_cmd_generic_location_global_set\ + },\ + {\ + "gllg",\ + "gllg [dst] [app key index]\n\r",\ + "generic location local get\n\r",\ + user_cmd_generic_location_local_get\ + },\ + {\ + "glls",\ + "glls [dst] [north] [east] [altitude] [floor] [sationary] [update time] [precision] [ack] [app key index]\n\r",\ + "generic location local set\n\r",\ + user_cmd_generic_location_local_set\ + },\ + {\ + "gupsg",\ + "gupsg [dst] [app key index]\n\r",\ + "generic user properties get\n\r",\ + user_cmd_generic_user_properties_get\ + },\ + {\ + "gupg",\ + "gupg [dst] [property id] [app key index]\n\r",\ + "generic user property get\n\r",\ + user_cmd_generic_user_property_get\ + },\ + {\ + "gups",\ + "gups [dst] [app key index] [ack] [property id] [property value...] \n\r",\ + "generic user property set\n\r",\ + user_cmd_generic_user_property_set\ + },\ + {\ + "gapsg",\ + "gapsg [dst] [app key index]\n\r",\ + "generic admin properties get\n\r",\ + user_cmd_generic_admin_properties_get\ + },\ + {\ + "gapg",\ + "gapg [dst] [property id] [app key index]\n\r",\ + "generic admin property get\n\r",\ + user_cmd_generic_admin_property_get\ + },\ + {\ + "gaps",\ + "gaps [dst] [app key index] [ack] [property id] [property access] [property value...]\n\r",\ + "generic admin property set\n\r",\ + user_cmd_generic_admin_property_set\ + },\ + {\ + "gmpsg",\ + "gmpsg [dst] [app key index]\n\r",\ + "generic manufacturer properties get\n\r",\ + user_cmd_generic_manufacturer_properties_get\ + },\ + {\ + "gmpg",\ + "gmpg [dst] [property id] [app key index]\n\r",\ + "generic manufacturer property get\n\r",\ + user_cmd_generic_manufacturer_property_get\ + },\ + {\ + "gmps",\ + "gmps [dst] [app key index] [ack] [property id] [property access]\n\r",\ + "generic manufacturer property set\n\r",\ + user_cmd_generic_manufacturer_property_set\ + },\ + {\ + "gcpsg",\ + "gcpsg [dst] [app key index] [property id]\n\r",\ + "generic client properties get\n\r",\ + user_cmd_generic_client_properties_get\ + },\ + {\ + "lxg",\ + "lxg [dst] [app_key_index]\n\r",\ + "light xyl get\n\r",\ + user_cmd_light_xyl_get\ + },\ + {\ + "lxs",\ + "lxs [dst] [lightness] [xyl_x] [xyl_y] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light xyl set\n\r",\ + user_cmd_light_xyl_set\ + },\ + {\ + "lxtg",\ + "lxtg [dst] [app_key_index]\n\r",\ + "light xyl target get\n\r",\ + user_cmd_light_xyl_target_get\ + },\ + {\ + "lxdg",\ + "lxdg [dst] [app_key_index]\n\r",\ + "light xyl default get\n\r",\ + user_cmd_light_xyl_default_get\ + },\ + {\ + "lxds",\ + "lxds [dst] [lightness] [xyl_x] [xyl_y] [ack] [app_key_index]\n\r",\ + "light xyl default set\n\r",\ + user_cmd_light_xyl_default_set\ + },\ + {\ + "lxrg",\ + "lxrg [dst] [app_key_index]\n\r",\ + "light xyl range get\n\r",\ + user_cmd_light_xyl_range_get\ + },\ + {\ + "lxrs",\ + "lxrs [dst] [xyl_x min] [xyl_x max] [xyl_y min] [xyl_y max] [ack] [app_key_index]\n\r",\ + "light xyl range set\n\r",\ + user_cmd_light_xyl_range_set\ + },\ + {\ + "llcmg",\ + "llcmg [dst] [app_key_index]\n\r",\ + "light lc mode get\n\r",\ + user_cmd_light_lc_mode_get\ + },\ + {\ + "llcms",\ + "llcms [dst] [mode] [app_key_index] [ack]\n\r",\ + "light lc mode set\n\r",\ + user_cmd_light_lc_mode_set\ + },\ + {\ + "llcomg",\ + "llcomg [dst] [app_key_index]\n\r",\ + "light lc om get\n\r",\ + user_cmd_light_lc_om_get\ + },\ + {\ + "llcoms",\ + "llcoms [dst] [mode] [app_key_index] [ack]\n\r",\ + "light lc om set\n\r",\ + user_cmd_light_lc_om_set\ + },\ + {\ + "llcloog",\ + "llcloog [dst] [app_key_index]\n\r",\ + "light lc light on off get\n\r",\ + user_cmd_light_lc_light_on_off_get\ + },\ + {\ + "llcloos",\ + "llcloos [dst] [on off] [ack] [app_key_index] [steps] [resolution] [delay]\n\r",\ + "light lc light on off set\n\r",\ + user_cmd_light_lc_light_on_off_set\ + },\ + {\ + "llcpg",\ + "llcpg [dst] [property id] [app_key_index]\n\r",\ + "light lc property get\n\r",\ + user_cmd_light_lc_property_get\ + },\ + {\ + "llcps",\ + "llcps [dst] [app_key_index] [ack] [property id] [property value...] \n\r",\ + "light lc property set\n\r",\ + user_cmd_light_lc_property_set\ + },\ + {\ + "prbg",\ + "prbg [dst]\n\r",\ + "Private beacon get\n\r",\ + user_cmd_private_beacon_get\ + },\ + {\ + "prbs",\ + "prbs [dst] [enable/disable] [random_update_interval]\n\r",\ + "Private beacon set\n\r",\ + user_cmd_private_beacon_set\ + },\ + {\ + "pgpg",\ + "pgpg [dst]\n\r",\ + "Private gatt proxy get\n\r",\ + user_cmd_private_gatt_proxy_get\ + },\ + {\ + "pgps",\ + "pgps [dst] [state]\n\r",\ + "Private gatt proxy set\n\r",\ + user_cmd_private_gatt_proxy_set\ + },\ + {\ + "pnig",\ + "pnig [dst] [net_key_index]\n\r",\ + "Private node identity get\n\r",\ + user_cmd_private_node_identity_get\ + },\ + {\ + "pnis",\ + "pnis [dst] [net_key_index] [state]\n\r",\ + "Private node identity set\n\r",\ + user_cmd_private_node_identity_set\ + },\ + {\ + "btg",\ + "btg [dst] [app_key_index]\n\r",\ + "blob transfer get\n\r",\ + user_cmd_blob_transfer_get\ + },\ + {\ + "bts",\ + "bts [dst] [app_key_index] [mode] [object id] [object size] [block size log] [client mtu size]\n\r",\ + "blob transfer start\n\r",\ + user_cmd_blob_transfer_start\ + },\ + {\ + "btc",\ + "btc [dst] [app_key_index] [object id]\n\r",\ + "blob transfer cancel\n\r",\ + user_cmd_blob_transfer_cancel\ + },\ + {\ + "bbg",\ + "bbg [dst] [app_key_index]\n\r",\ + "blob block get\n\r",\ + user_cmd_blob_block_get\ + },\ + {\ + "bbs",\ + "bbs [dst] [app_key_index] [block num] [chunk size]\n\r",\ + "blob block start\n\r",\ + user_cmd_blob_block_start\ + },\ + {\ + "bct",\ + "bct [dst] [app_key_index] [chunk num] [chunk size]\n\r",\ + "blob chunk transfer\n\r",\ + user_cmd_blob_chunk_transfer\ + },\ + {\ + "big",\ + "big [dst] [app_key_index]\n\r",\ + "blob information get\n\r",\ + user_cmd_blob_info_get\ + },\ + {\ + "fuig",\ + "fuig [dst] [app_key_index] [first_index] [entries_limit]\n\r",\ + "firmware update information get\n\r",\ + user_cmd_fw_update_info_get\ + },\ + {\ + "fumc",\ + "fumc [dst] [app_key_index] [fw_image_idx] [fw_metadata] [metadata len]\n\r",\ + "firmware update metadata check\n\r",\ + user_cmd_fw_update_metadata_check\ + },\ + {\ + "fug",\ + "fug [dst] [app_key_index]\n\r",\ + "firmware update get\n\r",\ + user_cmd_fw_update_get\ + },\ + {\ + "fus",\ + "fus [dst] [app_key_index] [update ttl] [update timeout base] [blob id] [fw image idx] [fw metadata] [metadata len]\n\r",\ + "firmware update start\n\r",\ + user_cmd_fw_update_start\ + },\ + {\ + "fuc",\ + "fuc [dst] [app_key_index]\n\r",\ + "firmware update cancel\n\r",\ + user_cmd_fw_update_cancel\ + },\ + {\ + "fua",\ + "fua [dst] [app_key_index]\n\r",\ + "firmware update apply\n\r",\ + user_cmd_fw_update_apply\ + },\ + {\ + "fdra",\ + "fdra [dst] [app_key_index] [address] [update fw index]\n\r",\ + "firmware distribution receivers add\n\r",\ + user_cmd_fw_dist_recvs_add\ + },\ + {\ + "fdrda",\ + "fdrda [dst] [app_key_index]\n\r",\ + "firmware distribution receivers delete all\n\r",\ + user_cmd_fw_dist_recvs_delete_all\ + },\ + {\ + "fdrg",\ + "fdrg [dst] [app_key_index] [first_index] [entries_limit]\n\r",\ + "firmware distribution receivers get\n\r",\ + user_cmd_fw_dist_recvs_get\ + },\ + {\ + "fdcg",\ + "fdcg [dst] [app_key_index]\n\r",\ + "firmware distribution capabilites get\n\r",\ + user_cmd_fw_dist_caps_get\ + },\ + {\ + "fdg",\ + "fdg [dst] [app_key_index]\n\r",\ + "firmware distribution get\n\r",\ + user_cmd_fw_dist_get\ + },\ + {\ + "fds",\ + "fds [dst] [app_key_index] [dist_app_key_index] [dist_ttl] [dist_timeout_base] [dist_transfer_mode] [update_policy] [dist_fw_image_idx] [dist_multicast_addr] [dist_dst_len]\n\r",\ + "firmware distribution start\n\r",\ + user_cmd_fw_dist_start\ + },\ + {\ + "fdc",\ + "fdc [dst] [app_key_index]\n\r",\ + "firmware distribution cancel\n\r",\ + user_cmd_fw_dist_cancel\ + },\ + {\ + "fda",\ + "fua [dst] [app_key_index]\n\r",\ + "firmware distribution apply\n\r",\ + user_cmd_fw_dist_apply\ + },\ + {\ + "fdug",\ + "fdug [dst] [app_key_index]\n\r",\ + "firmware distribution upload get\n\r",\ + user_cmd_fw_dist_upload_get\ + },\ + {\ + "fdus",\ + "fdus [dst] [app_key_index] [upload_ttl] [upload_timeout_base] [blob_id] [upload_fw_size] [metadata] [metadata_len] [fw_id] [fw_id_len]\n\r",\ + "firmware distribution upload start\n\r",\ + user_cmd_user_cmd_fw_dist_upload_start\ + },\ + {\ + "fduos",\ + "fduos [dst] [app_key_index] [upload_uri] [upload_uri_len] [fw_id] [fw_id_len]\n\r",\ + "firmware distribution upload oob start\n\r",\ + user_cmd_fw_dist_upload_oob_start\ + },\ + {\ + "fduc",\ + "fduc [dst] [app_key_index]\n\r",\ + "firmware distribution upload cancel\n\r",\ + user_cmd_fw_dist_upload_cancel\ + },\ + {\ + "fdfg",\ + "fdfg [dst] [app_key_index] [fw_id] [fw_id_len]\n\r",\ + "firmware distribution firmware get\n\r",\ + user_cmd_fw_dist_fw_get\ + },\ + {\ + "fdgbi",\ + "fdgbi [dst] [app_key_index] [dist_fw_image_index]\n\r",\ + "firmware distribution get by index\n\r",\ + user_cmd_fw_dist_fw_get_by_index\ + },\ + {\ + "fdfd",\ + "fdfd [dst] [app_key_index] [fw_id] [fw_id_len]\n\r",\ + "firmware distribution firmware delete\n\r",\ + user_cmd_fw_dist_fw_delete\ + },\ + {\ + "fdfda",\ + "fdfda [dst] [app_key_index]\n\r",\ + "firmware distribution firmware delete all\n\r",\ + user_cmd_fw_dist_fw_delete_all\ + } +/** @} */ + + +/** + * @defgroup Client_Cmd_Exported_Functions Client Command Exported Functions + * @brief + * @{ + */ +user_cmd_parse_result_t user_cmd_cmg(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_cms(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_gdtt_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_gdtt_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_health_fault_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_health_fault_clear(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_health_fault_test(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_health_period_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_health_period_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_health_attn_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_health_attn_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_on_off_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_on_off_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_level_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_level_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_delta_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_move_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_on_powerup_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_on_powerup_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_power_level_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_power_level_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_power_last_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_power_default_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_power_default_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_power_range_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_power_range_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_battery_get(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_light_lightness_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_linear_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_linear_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_last_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_default_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_default_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_range_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lightness_range_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_light_ctl_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_temperature_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_temperature_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_temperature_range_get(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_temperature_range_set(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_default_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_ctl_default_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_light_hsl_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_target_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_hue_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_hue_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_saturation_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_saturation_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_default_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_default_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_range_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_hsl_range_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_time_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_zone_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_zone_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_tai_utc_delta_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_tai_utc_delta_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_role_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time_role_get(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_scene_store(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_scene_recall(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_scene_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_scene_register_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_scene_delete(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_sensor_descriptor_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_cadence_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_cadence_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_settings_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_setting_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_setting_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_column_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_sensor_series_get(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_scheduler_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_scheduler_action_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_scheduler_action_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_location_global_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_location_global_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_location_local_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_location_local_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_generic_user_properties_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_user_property_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_user_property_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_admin_properties_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_admin_property_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_admin_property_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_generic_manufacturer_properties_get(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_generic_manufacturer_property_get(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_generic_manufacturer_property_set(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_generic_client_properties_get(user_cmd_parse_value_t + *pparse_value); + +user_cmd_parse_result_t user_cmd_light_xyl_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_xyl_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_xyl_target_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_xyl_default_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_xyl_default_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_xyl_range_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_xyl_range_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_light_lc_mode_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_mode_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_om_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_om_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_light_on_off_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_light_on_off_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_property_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_light_lc_property_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_private_beacon_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_private_beacon_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_private_gatt_proxy_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_private_gatt_proxy_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_private_node_identity_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_private_node_identity_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_blob_transfer_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_blob_transfer_start(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_blob_transfer_cancel(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_blob_block_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_blob_block_start(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_blob_chunk_transfer(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_blob_info_get(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_fw_update_info_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_update_metadata_check(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_update_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_update_start(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_update_cancel(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_update_apply(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_fw_dist_recvs_add(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_recvs_delete_all(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_recvs_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_caps_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_start(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_cancel(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_apply(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_upload_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_user_cmd_fw_dist_upload_start(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_upload_oob_start(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_upload_cancel(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_fw_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_fw_get_by_index(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_fw_delete(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fw_dist_fw_delete_all(user_cmd_parse_value_t *pparse_value); + + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _MESH_CMD_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c new file mode 100644 index 00000000..a3a44f9d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c @@ -0,0 +1,747 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_cmd.c + * @brief Source file for mesh common cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +#include "trace.h" +#include "app_msg.h" +#include "gap_wrapper.h" +#include "mesh_cmd.h" +#include "mesh_api.h" +#include "proxy_client.h" +#include "ping.h" +#include "tp.h" + +bool dev_info_show_flag; +uint8_t proxy_client_conn_id; + +user_cmd_parse_result_t user_cmd_reset(user_cmd_parse_value_t *pparse_value) +{ + //WDG_SystemReset(RESET_ALL, SW_RESET_APP_START); + /* avoid gcc compile warning */ + (void)pparse_value; + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_list(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("MeshState:\t%d\r\n", mesh_node.node_state); + data_uart_debug("DevUUID:\t"); + data_uart_dump(mesh_node.dev_uuid, 16); + uint8_t bt_addr[6]; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("BTAddr:\t\t0x%02x%02x%02x%02x%02x%02x\r\n", + bt_addr[5], bt_addr[4], bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0]); + for (uint16_t index = 0; index < mesh_node.dev_key_num; index++) + { + if (mesh_node.dev_key_list[index].used && mesh_node.dev_key_list[index].element_num != 0) + { + data_uart_debug("DevKey:\t\t%d-0x%04x-%d-", index, mesh_node.dev_key_list[index].unicast_addr, + mesh_node.dev_key_list[index].element_num); + data_uart_dump(mesh_node.dev_key_list[index].dev_key, 16); + } + } + for (uint16_t index = 0; index < mesh_node.app_key_num; index++) + { + if (mesh_node.app_key_list[index].key_state != MESH_KEY_STATE_INVALID) + { + data_uart_debug("AppKey:\t\t%d-0x%04x-%d-%d-%d\r\n", index, + mesh_node.app_key_list[index].app_key_index_g, mesh_node.app_key_list[index].key_state, + key_state_to_tx_loop(mesh_node.app_key_list[index].key_state), + mesh_node.app_key_list[index].net_key_binding); + for (uint8_t loop = 0; loop < 2; loop++) + { + if (mesh_node.app_key_list[index].papp_key[loop] != NULL) + { + data_uart_debug("\t\t"); + data_uart_dump(mesh_node.app_key_list[index].papp_key[loop]->app_key, 16); + } + } + } + } + for (uint16_t index = 0; index < mesh_node.net_key_num; index++) + { + if (mesh_node.net_key_list[index].key_state != MESH_KEY_STATE_INVALID) + { + data_uart_debug("NetKey:\t\t%d-0x%04x-%d-%d-%d\r\n", index, + mesh_node.net_key_list[index].net_key_index_g, mesh_node.net_key_list[index].key_state, + key_state_to_tx_loop(mesh_node.net_key_list[index].key_state), + key_state_to_key_refresh_phase(mesh_node.net_key_list[index].key_state)); + if (mesh_node.net_key_list[index].net_key_index_g & 0x8000) + { + break; + } + for (uint8_t loop = 0; loop < 2; loop++) + { + if (mesh_node.net_key_list[index].pnet_key[loop] != NULL) + { + data_uart_debug("\t\t"); + data_uart_dump(mesh_node.net_key_list[index].pnet_key[loop]->net_key, 16); + } + } + } + } + data_uart_debug("IVindex:\t%d-0x%x\r\n", mesh_node.iv_update_flag, mesh_node.iv_index); + data_uart_debug("Seq:\t\t0x%06x\r\n", mesh_node.seq); + data_uart_debug("NodeAddr:\t0x%04x-%d-%d\r\n", mesh_node.unicast_addr, + mesh_node.element_queue.count, mesh_node.model_num); + mesh_element_p pelement = (mesh_element_p)mesh_node.element_queue.pfirst; + while (pelement != NULL) + { + data_uart_debug("Element:\t%d-%d\r\n", pelement->element_index, pelement->model_queue.count); + mesh_model_p pmodel = (mesh_model_p)pelement->model_queue.pfirst; + while (pmodel != NULL) + { + data_uart_debug("Model:\t\t%d-%d-0x%08x", pmodel->pmodel_info->model_index, + pmodel->model_index, pmodel->pmodel_info->model_id); + uint8_t key_flag = true; + for (uint16_t index = 0; index < mesh_node.app_key_num; index++) + { + if (plt_bit_pool_get(pmodel->app_key_binding, index) && + mesh_node.app_key_list[index].key_state != MESH_KEY_STATE_INVALID) + { + if (key_flag) + { + key_flag = false; + data_uart_debug("-(key:%d", index); + } + else + { + data_uart_debug("-%d", index); + } + } + } + if (!key_flag) + { + data_uart_debug(")"); + } + if (MESH_NOT_UNASSIGNED_ADDR(pmodel->pub_params.pub_addr)) + { + data_uart_debug("-(pub:0x%04x-%d-%d)", pmodel->pub_params.pub_addr, pmodel->pub_params.pub_ttl, + pmodel->pub_params.pub_key_info.app_key_index); + } + mesh_model_p pmodelb = pmodel; + while (pmodelb->pmodel_info->pmodel_bound != NULL) + { + pmodelb = (mesh_model_p)pmodelb->pmodel_info->pmodel_bound->pmodel; + } + mesh_addr_member_p paddr_element = (mesh_addr_member_p)pmodelb->sub_queue.pfirst; + while (paddr_element != NULL) + { + if (paddr_element == (mesh_addr_member_p)pmodelb->sub_queue.pfirst) + { + if (pmodelb != pmodel) + { + data_uart_debug("-(sub:-%d-%d-0x%04x", + ((mesh_model_p)pmodel->pmodel_info->pmodel_bound->pmodel)->model_index, + pmodelb->model_index, paddr_element->mesh_addr); + } + else + { + data_uart_debug("-(sub:0x%04x", paddr_element->mesh_addr); + } + } + else + { + data_uart_debug("-0x%04x", paddr_element->mesh_addr); + } + paddr_element = paddr_element->pnext; + if (paddr_element == NULL) + { + data_uart_debug(")"); + } + } + pmodel = pmodel->pnext; + data_uart_debug("\r\n"); + } + pelement = pelement->pnext; + } + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_dev_info_show(user_cmd_parse_value_t *pparse_value) +{ + dev_info_show_flag = pparse_value->dw_parameter[0] ? true : false; + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_dev_uuid_set(user_cmd_parse_value_t *pparse_value) +{ + plt_hex_to_bin(mesh_node.dev_uuid, (uint8_t *)pparse_value->pparameter[0], 16); + data_uart_debug("DevUUID:\t"); + data_uart_dump(mesh_node.dev_uuid, 16); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_bearer_adv_set(user_cmd_parse_value_t *pparse_value) +{ + bearer_adv_set(pparse_value->dw_parameter[0]); + data_uart_debug("Adv bearer: %s\r\n", pparse_value->dw_parameter[0] ? "on" : "off"); + return USER_CMD_RESULT_OK; +} + +extern prov_auth_value_type_t prov_auth_value_type; +user_cmd_parse_result_t user_cmd_prov_auth_value(user_cmd_parse_value_t *pparse_value) +{ + uint8_t auth_data[16]; + uint8_t auth_value_len; + uint8_t *auth_value; + if (prov_auth_value_type != PROV_AUTH_VALUE_TYPE_ALPHANUMERIC) + { + auth_value_len = plt_hex_to_bin(auth_data, (uint8_t *)pparse_value->pparameter[0], + sizeof(auth_data)); + auth_value = auth_data + sizeof(auth_data) - auth_value_len; + } + else + { + auth_value_len = strlen(pparse_value->pparameter[0]); + auth_value = (uint8_t *)pparse_value->pparameter[0]; + } + data_uart_debug("AuthValue: len=%d, value=", auth_value_len); + data_uart_dump(auth_value, auth_value_len); + return prov_auth_value_set(auth_value, auth_value_len) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +user_cmd_parse_result_t user_cmd_vir_addr_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t label_uuid[16]; + uint16_t va_index; + uint16_t va_addr; + plt_hex_to_bin(label_uuid, (uint8_t *)pparse_value->pparameter[0], sizeof(label_uuid)); + va_index = vir_addr_add(label_uuid); + va_addr = vir_addr_get(va_index); + if (MESH_NOT_UNASSIGNED_ADDR(va_addr)) + { + data_uart_debug("index=%d va=0x%04x\r\n", va_index, va_addr); + return USER_CMD_RESULT_OK; + } + else + { + return USER_CMD_RESULT_ERROR; + } +} + +static uint32_t ping_time_us; +static uint32_t ping_time_ms; +static uint16_t pong_count; +static uint32_t rtime_sum; +static uint32_t ping_count; +static uint32_t pong_count_sum; +static uint32_t rtime_sum_sum; +static plt_timer_t ping_timer; +static ping_pong_type_t ping_type; +static uint16_t ping_dst; +static uint8_t ping_ttl; +static uint16_t ping_key_index; +static uint16_t pong_max_delay; +static uint32_t rtime_min; +static uint32_t rtime_max; +static mesh_msg_send_cause_t (*const ping_pf[3])(uint16_t dst, uint8_t ttl, uint16_t key_index, + uint16_t pong_max_delay) = {trans_ping, ping, big_ping}; + +int32_t tp_reveive(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + (void)type; + mesh_msg_t *pmesh_msg = (mesh_msg_t *)pargs; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + tp_msg_t *pmsg = (tp_msg_t *)(pbuffer); + + data_uart_debug("From:0x%04x To:0x%04x Tid:%d Time:%dms\r\n", pmesh_msg->src, pmesh_msg->dst, + pmsg->tid, plt_time_read_ms()); + if (pmesh_msg->msg_len < sizeof(tp_msg_t)) + { + data_uart_send_string(pmsg->padding, pmesh_msg->msg_len - MEMBER_OFFSET(tp_msg_t, padding)); + data_uart_debug("\r\n>"); + } + return 0; +} + +void pong_receive(uint16_t src, uint16_t dst, uint8_t hops_forward, ping_pong_type_t type, + uint8_t hops_reverse, uint16_t pong_delay) +{ + /* avoid gcc compile warning */ + (void)dst; + (void)type; + + pong_count++; + uint32_t pong_time_us = plt_time_read_us(); + uint32_t pong_time_ms = plt_time_read_ms(); + uint32_t diff_time = plt_time_diff(ping_time_ms, ping_time_us, pong_time_ms, pong_time_us); + if (diff_time & 0x80000000) + { + diff_time &= 0x7fffffff; + diff_time /= 1000; + } + if (ping_count == 1) + { + data_uart_debug("\b"); + } + uint32_t rtime = diff_time - pong_delay * 10 + (diff_time > pong_delay * 10 ? 0 : 30); + rtime_sum += rtime; + if (rtime > rtime_max) + { + rtime_max = rtime; + } + if (rtime < rtime_min) + { + rtime_min = rtime; + } + data_uart_debug("%d\t0x%04x\t%d\t%d\t%d\t%d\t%d\t%d\r\n", pong_count, src, hops_forward, + hops_reverse, diff_time, pong_delay * 10, rtime, rtime_sum / pong_count); +} + +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER +extern void *bt_mesh_provisioner_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_io_queue_handle; //!< IO queue handle +#elif defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE +extern void *bt_mesh_device_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_device_io_queue_handle; //!< IO queue handle +#elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +extern void *bt_mesh_device_matter_evt_queue_handle; +extern void *bt_mesh_device_matter_io_queue_handle; +#else +extern void *bt_mesh_device_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_device_multiple_profile_io_queue_handle; //!< IO queue handle +#endif +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +extern void *bt_mesh_provisioner_ota_client_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_ota_client_io_queue_handle; //!< IO queue handle +#else +extern void *bt_mesh_provisioner_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_multiple_profile_io_queue_handle; //!< IO queue handle +#endif +#endif +static void ping_timeout_cb(void *ptimer) +{ + /* avoid gcc compile warning */ + (void)ptimer; + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = PING_TIMEOUT_MSG; +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER + if (os_msg_send(bt_mesh_provisioner_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_evt_queue_handle, &event, 0) == false) + { + } +#elif defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE + if (os_msg_send(bt_mesh_device_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_evt_queue_handle, &event, 0) == false) + { + } +#elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER + if (os_msg_send(bt_mesh_device_matter_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_matter_evt_queue_handle, &event, 0) == false) + { + } +#else + if (os_msg_send(bt_mesh_device_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +#endif +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT + if (os_msg_send(bt_mesh_provisioner_ota_client_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) + { + } +#else + if (os_msg_send(bt_mesh_provisioner_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +#endif +#endif +} + +mesh_msg_send_cause_t ping_handle_timeout(void) +{ + ping_count++; + pong_count_sum += pong_count; + rtime_sum_sum += rtime_sum; + data_uart_debug("count\tdst\tf-hops\tr-hops\ttime\tdelay\trtime\tatime\t%d\r\n", ping_count); + ping_time_us = plt_time_read_us(); + ping_time_ms = plt_time_read_ms(); + pong_count = 0; + rtime_sum = 0; + return ping_pf[ping_type](ping_dst, ping_ttl, ping_key_index, pong_max_delay); +} + +static user_cmd_parse_result_t common_ping(user_cmd_parse_value_t *pparse_value) +{ + ping_dst = pparse_value->dw_parameter[0]; + ping_ttl = pparse_value->dw_parameter[1]; + ping_key_index = pparse_value->dw_parameter[2]; + pong_max_delay = pparse_value->dw_parameter[3]; + uint16_t period = pparse_value->dw_parameter[4]; + if (0 == period || 0 == pparse_value->para_count) + { + if (ping_timer != NULL) + { + plt_timer_delete(ping_timer, 0); + ping_timer = NULL; + } + if (0 == pparse_value->para_count) + { + pong_count_sum += pong_count; + rtime_sum_sum += rtime_sum; + data_uart_debug("ping statistic: ping=%d pong=%d time(ms) min=%d max=%d avg=%d\r\n", ping_count, + pong_count_sum, + rtime_min, rtime_max, rtime_sum_sum / pong_count_sum); + return USER_CMD_RESULT_OK; + } + } + else + { + if (period < pong_max_delay) + { + period = pong_max_delay; + } + if (NULL == ping_timer) + { + ping_timer = plt_timer_create("ping", period * 10, true, 0, + ping_timeout_cb); + if (ping_timer != NULL) + { + plt_timer_start(ping_timer, 0); + } + } + else + { + plt_timer_change_period(ping_timer, period * 10, 0); + } + } + ping_count = 0; + pong_count = 0; + pong_count_sum = 0; + rtime_sum = 0; + rtime_sum_sum = 0; + rtime_min = 0xffffffff; + rtime_max = 0x0; + if (MESH_MSG_SEND_CAUSE_SUCCESS == ping_handle_timeout()) + { + return USER_CMD_RESULT_OK; + } + else + { + return USER_CMD_RESULT_ERROR; + } +} + +user_cmd_parse_result_t user_cmd_trans_ping(user_cmd_parse_value_t *pparse_value) +{ + ping_type = PING_PONG_TYPE_TRANSPORT; + return common_ping(pparse_value); +} + +user_cmd_parse_result_t user_cmd_ping(user_cmd_parse_value_t *pparse_value) +{ + ping_type = PING_PONG_TYPE_ACCESS; + return common_ping(pparse_value); +} + +user_cmd_parse_result_t user_cmd_big_ping(user_cmd_parse_value_t *pparse_value) +{ + ping_type = PING_PONG_TYPE_ACCESS_BIG; + return common_ping(pparse_value); +} + +user_cmd_parse_result_t user_cmd_tp_msg(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t ttl = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (MESH_MSG_SEND_CAUSE_SUCCESS == tp_msg(dst, ttl, app_key_index, + (uint8_t *)pparse_value->pparameter[3], strlen(pparse_value->pparameter[3]))) + { + return USER_CMD_RESULT_OK; + } + else + { + return USER_CMD_RESULT_ERROR; + } +} + +user_cmd_parse_result_t user_cmd_tp_start(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t ttl = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + uint32_t count = pparse_value->dw_parameter[3]; + if (MESH_MSG_SEND_CAUSE_SUCCESS == tp_start(dst, ttl, app_key_index, count)) + { + return USER_CMD_RESULT_OK; + } + else + { + return USER_CMD_RESULT_ERROR; + } +} + +user_cmd_parse_result_t user_cmd_connect(user_cmd_parse_value_t *pparse_value) +{ + uint8_t addr[6]; + plt_hex_to_bin(addr, (uint8_t *)pparse_value->pparameter[0], 6); + plt_swap1(addr, 6); + uint8_t addr_type = pparse_value->dw_parameter[1] ? GAP_LOCAL_ADDR_LE_RANDOM : + GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + conn_req_param.scan_interval = 0xA0; //100ms + conn_req_param.scan_window = 0x80; //80ms + conn_req_param.conn_interval_min = 0x60; //120ms + conn_req_param.conn_interval_max = 0x60; //120ms + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + le_connect(GAP_PHYS_CONN_INIT_1M_BIT, addr, (T_GAP_REMOTE_ADDR_TYPE)addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, 1000); + data_uart_debug("Connecting "); + plt_swap1(addr, 6); + data_uart_dump(addr, 6); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_disconnect(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Disconnecting\r\n"); + le_disconnect(pparse_value->dw_parameter[0]); + return USER_CMD_RESULT_OK; +} + + +user_cmd_parse_result_t user_cmd_proxy_discover(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Proxy Start Discover\r\n"); +#if defined(MESH_DEVICE) && MESH_DEVICE + /* for pts test */ + proxy_client_add(NULL); + /* replace proxy server */ + //proxy_ctx_set_cb(proxy_ctx_id, proxy_client_data_in_write, proxy_service_receive); + //proxy_ctx_set_filter_type(proxy_ctx_id, PROXY_CFG_FILTER_TYPE_BLACK_LIST); +#endif + proxy_client_conn_id = pparse_value->dw_parameter[0]; + proxy_client_start_discovery(proxy_client_conn_id); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_proxy_cccd_operate(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char CCCD command. */ + uint8_t cmd_type = (uint8_t)pparse_value->dw_parameter[0]; + /* Enable or disable, 1--enable, 0--disable. */ + bool cmd_data = (bool)pparse_value->dw_parameter[1]; + data_uart_debug("Proxy Cccd Operate\r\n"); + switch (cmd_type) + { + case 0:/* V3 Notify char notif enable/disable. */ + { + proxy_client_data_out_cccd_set(proxy_client_conn_id, cmd_data); + //proxy_ctx_set_link(proxy_ctx_id, proxy_client_conn_id); + data_uart_debug("GATT bearer: on\r\n"); + if (bearer_adv_get()) + { + data_uart_debug("\r\nThe adv bearer exits too, you can use \"bas\" cmd to close it\r\n"); + } + } + break; + default: + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_proxy_list(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Proxy Server Handle List:\r\nidx\thandle\r\n"); + for (proxy_handle_type_t hdl_idx = HDL_PROXY_SRV_START; hdl_idx < HDL_PROXY_CACHE_LEN; hdl_idx++) + { + data_uart_debug("%d\t0x%x\r\n", hdl_idx, proxy_client_handle_get(proxy_client_conn_id, hdl_idx)); + } + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_proxy_cfg_set_filter_type(user_cmd_parse_value_t + *pparse_value) +{ + proxy_cfg_filter_type_t filter_type = (proxy_cfg_filter_type_t)pparse_value->dw_parameter[0]; + proxy_cfg_set_filter_type(proxy_ctx_id_get(proxy_client_conn_id, PROXY_CTX_TYPE_PROXY), + filter_type); + data_uart_debug("Proxy cfg set filter type %d\r\n", filter_type); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_proxy_cfg_add_addr(user_cmd_parse_value_t *pparse_value) +{ + uint16_t addr = pparse_value->dw_parameter[0]; + proxy_cfg_add_remove_addr(proxy_ctx_id_get(proxy_client_conn_id, PROXY_CTX_TYPE_PROXY), TRUE, &addr, + 1); + data_uart_debug("Proxy cfg add addr 0x%04x\r\n", addr); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_proxy_cfg_remove_addr(user_cmd_parse_value_t *pparse_value) +{ + uint16_t addr = pparse_value->dw_parameter[0]; + proxy_cfg_add_remove_addr(proxy_ctx_id_get(proxy_client_conn_id, PROXY_CTX_TYPE_PROXY), FALSE, + &addr, 1); + data_uart_debug("Proxy cfg remove addr 0x%04x\r\n", addr); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_log_set(user_cmd_parse_value_t *pparse_value) +{ + log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_ERROR, + pparse_value->dw_parameter[0] & 0x1); + log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_WARN, + pparse_value->dw_parameter[0] & 0x1); + log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_INFO, + pparse_value->dw_parameter[0] & 0x1); + log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_TRACE, + pparse_value->dw_parameter[0] & 0x1); + + log_module_bitmap_trace_set(0x7FFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, + pparse_value->dw_parameter[0] & 0x2); + log_module_bitmap_trace_set(0x7FFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, + pparse_value->dw_parameter[0] & 0x2); + + uint32_t log_value[MESH_LOG_LEVEL_SIZE]; + memset(log_value, pparse_value->dw_parameter[0] & 0x4 ? 0xff : 0, sizeof(log_value)); + diag_level_set(TRACE_LEVEL_TRACE, log_value); + + data_uart_debug("Log setting %d!\r\n", pparse_value->dw_parameter[0]); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_time(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + uint32_t time_ms = plt_time_read_ms(); + uint32_t day, hour, minute, second; + second = time_ms / 1000; + minute = second / 60; + second %= 60; + hour = minute / 60; + minute %= 60; + day = hour / 24; + hour %= 24; + data_uart_debug("Time: %dd%dh%dm%ds\r\n", day, hour, minute, second); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_adv_power_set(user_cmd_parse_value_t *pparse_value) +{ + //uint8_t tx_gain[4] = {0x30, 0x80, 0xA0, 0xF0}; + int8_t tx_gain_info[4] = {-20, 0, 4, 8}; + //le_adv_set_tx_power(GAP_ADV_TX_POW_SET_1M, tx_gain[pparse_value->dw_parameter[0]]); + data_uart_debug("Adv power %d dBm\r\n", tx_gain_info[pparse_value->dw_parameter[0]]); + return USER_CMD_RESULT_OK; +} + +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +user_cmd_parse_result_t user_cmd_fn_init(user_cmd_parse_value_t *pparse_value) +{ +#if MESH_FN + fn_params_t fn_params; + uint8_t fn_num = pparse_value->dw_parameter[0]; + fn_params.queue_size = pparse_value->dw_parameter[1]; + if (pparse_value->dw_parameter[2] > 0 && pparse_value->dw_parameter[2] < 0xff) + { + mesh_node.frnd_rx_window = pparse_value->dw_parameter[2]; + } + return fn_init(fn_num, &fn_params, fn_cb) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +#else + return USER_CMD_RESULT_ERROR; +#endif +} + +user_cmd_parse_result_t user_cmd_fn_deinit(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + fn_deinit(); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_hb_pub(user_cmd_parse_value_t *pparse_value) +{ + hb_pub_t pub; + pub.dst = pparse_value->dw_parameter[0]; + pub.count = pparse_value->dw_parameter[1]; + pub.period = pparse_value->dw_parameter[2]; + pub.ttl = 0x7f; + pub.features.relay = 0; + pub.features.proxy = 0; + pub.features.frnd = 0; + pub.features.lpn = 0; + pub.features.rfu = 0; + pub.net_key_index = 0; + + hb_publication_set(pub); + hb_timer_start(HB_TIMER_PUB); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_hb_sub(user_cmd_parse_value_t *pparse_value) +{ + hb_sub_t sub; + sub.src = pparse_value->dw_parameter[0]; + sub.dst = pparse_value->dw_parameter[1]; + sub.period = pparse_value->dw_parameter[2]; + sub.count = 0; + sub.min_hops = 0x7f; + sub.max_hops = 0; + + hb_subscription_set(sub); + hb_timer_start(HB_TIMER_SUB); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_mesh_deinit(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + mesh_deinit(); + return USER_CMD_RESULT_OK; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.h new file mode 100644 index 00000000..5964915c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.h @@ -0,0 +1,277 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_cmd.h + * @brief Head file for mesh common cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_CMD_H +#define _MESH_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_api.h" + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +/** + * @addtogroup MESH_CMD + * @{ + */ + +/** + * @defgroup Mesh_Cmd_Exported_Macros Mesh Command Exported Macros + * @brief + * @{ + */ + +#define MESH_COMMON_CMD \ + {\ + "reset",\ + "reset\n\r",\ + "reset\n\r",\ + user_cmd_reset\ + },\ + {\ + "ls",\ + "ls\n\r",\ + "list node state info\n\r",\ + user_cmd_list\ + },\ + {\ + "dis",\ + "dis [1 on/0 off]\n\r",\ + "device information show\n\r",\ + user_cmd_dev_info_show\ + },\ + {\ + "dus",\ + "dus [dev uuid]\n\r",\ + "device uuid set\n\r",\ + user_cmd_dev_uuid_set\ + },\ + {\ + "bas",\ + "bas [on off]\n\r",\ + "bearer adv set\n\r",\ + user_cmd_bearer_adv_set\ + },\ + {\ + "pav",\ + "pav [value]\n\r",\ + "prov authentication value\n\r",\ + user_cmd_prov_auth_value\ + },\ + {\ + "vas",\ + "vas [label uuid]\n\r",\ + "virtual addr set\n\r",\ + user_cmd_vir_addr_set\ + },\ + {\ + "tping",\ + "tping [dst] [init ttl] [net_key_index] [pong_max_delay/10ms] [period/10ms]\n\r",\ + "ping a remote device at the transport layer\n\r",\ + user_cmd_trans_ping\ + },\ + {\ + "ping",\ + "ping [dst] [init ttl] [app_key_index] [pong_max_delay/10ms] [period/10ms]\n\r",\ + "ping a remote device at the model layer\n\r",\ + user_cmd_ping\ + },\ + {\ + "bping",\ + "bping [dst] [init ttl] [app_key_index] [pong_max_delay/10ms] [period/10ms]\n\r",\ + "ping a remote device with a big seg msg at the model layer\n\r",\ + user_cmd_big_ping\ + },\ + {\ + "tp",\ + "tp [dst] [init ttl] [app_key_index] [msg]\n\r",\ + "tp test the transparent message\n\r",\ + user_cmd_tp_msg\ + },\ + {\ + "tps",\ + "tps [dst] [init ttl] [app_key_index] [count]\n\r",\ + "tp start to test the throughput of messages\n\r",\ + user_cmd_tp_start\ + },\ + {\ + "con",\ + "con [bt addr] [addr type]\n\r",\ + "connect to remote device\n\r",\ + user_cmd_connect\ + },\ + {\ + "disc",\ + "disc [conn id]\n\r",\ + "disconnect to remote device\n\r",\ + user_cmd_disconnect\ + },\ + {\ + "proxydis",\ + "proxydis [conn id]\n\r",\ + "Start discovery proxy service\n\r",\ + user_cmd_proxy_discover\ + },\ + {\ + "proxycmd",\ + "proxycmd [char CCCD] [command: enable/disable]\n\r",\ + "Proxy notify/ind switch command\n\r",\ + user_cmd_proxy_cccd_operate\ + },\ + {\ + "proxyls",\ + "proxyls\n\r",\ + "Proxy server handle list\n\r",\ + user_cmd_proxy_list\ + },\ + {\ + "pcsft",\ + "pcsft [type]\n\r",\ + "proxy cfg set filter type\n\r",\ + user_cmd_proxy_cfg_set_filter_type\ + },\ + {\ + "pcaa",\ + "pcaa [addr]\n\r",\ + "proxy cfg add addr\n\r",\ + user_cmd_proxy_cfg_add_addr\ + },\ + {\ + "pcra",\ + "pcra [addr]\n\r",\ + "proxy cfg remove addr\n\r",\ + user_cmd_proxy_cfg_remove_addr\ + },\ + {\ + "log",\ + "log [bit0: lower, bit1: upper, bit2: mesh]\n\r",\ + "log level setting\n\r",\ + user_cmd_log_set\ + },\ + {\ + "time",\ + "time\n\r",\ + "time since power-on\n\r",\ + user_cmd_time\ + },\ + {\ + "aps",\ + "aps [0:-20dBm, 1:0dBm, 2:4dBm, 3:8dBm]\n\r",\ + "adv power set\n\r",\ + user_cmd_adv_power_set\ + },\ + {\ + "fninit",\ + "fninit [lpn num] [queue size] [rx window(ms)]\n\r",\ + "friend node init\n\r",\ + user_cmd_fn_init\ + },\ + {\ + "fndeinit",\ + "fndeinit\n\r",\ + "friend node deinit\n\r",\ + user_cmd_fn_deinit\ + },\ + {\ + "hbpub",\ + "hbpub [dst] [count] [period]\n\r",\ + "Publish heartbeat\n\r",\ + user_cmd_hb_pub\ + },\ + {\ + "hbsub",\ + "hbsub [src] [dst] [period]\n\r",\ + "Subscribe heartbeat\n\r",\ + user_cmd_hb_sub\ + },\ + {\ + "md",\ + "md\n\r",\ + "mesh deinit\n\r",\ + user_cmd_mesh_deinit\ + } + + +#define PING_TIMEOUT_MSG 101 +/** @} */ + + +/** + * @defgroup Mesh_Cmd_Exported_Types Mesh Command Exported Types + * @brief + * @{ + */ +extern bool dev_info_show_flag; +/** @} */ + +/** + * @defgroup Mesh_Cmd_Exported_Functions Mesh Command Exported Functions + * @brief + * @{ + */ +user_cmd_parse_result_t user_cmd_reset(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_list(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_dev_info_show(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_dev_uuid_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_bearer_adv_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_prov_auth_value(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_vir_addr_set(user_cmd_parse_value_t *pparse_value); +mesh_msg_send_cause_t ping_handle_timeout(void); +user_cmd_parse_result_t user_cmd_trans_ping(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_ping(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_big_ping(user_cmd_parse_value_t *pparse_value); +int32_t tp_reveive(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs); +void pong_receive(uint16_t src, uint16_t dst, uint8_t hops_forward, ping_pong_type_t type, + uint8_t hops_reverse, uint16_t pong_delay); +user_cmd_parse_result_t user_cmd_tp_msg(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_tp_start(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_connect(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_disconnect(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_proxy_discover(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_proxy_cccd_operate(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_proxy_list(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_proxy_cfg_set_filter_type(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_proxy_cfg_add_addr(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_proxy_cfg_remove_addr(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_log_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_time(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_adv_power_set(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_fn_init(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_fn_deinit(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_hb_pub(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_hb_sub(user_cmd_parse_value_t *pparse_value); + +user_cmd_parse_result_t user_cmd_mesh_deinit(user_cmd_parse_value_t *pparse_value); +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _MESH_CMD_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c new file mode 100644 index 00000000..4ec9307f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c @@ -0,0 +1,380 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file data_uart.h + * @brief Head file for Data uart operations. + * @details Data uart init and print vital data through data uart. + * @author bill + * @date 2015-03-19 + * @version v2.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +#include "mesh_data_uart.h" +#include "platform_diagnose.h" +#include "mesh_config.h" + +#if MESH_DATA_UART_DEBUG + +#define USE_DEDICATED_BT_MESH_DATA_UART 0 + +#define SPRINTF_BUF_LEN 20 + +static bool data_uart_flag; +static pf_send_msg_from_isr_t pf_data_uart_send_msg; +#if defined(CONFIG_PLATFORM_8721D) +extern UART_TypeDef *data_uart_def; +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +static serial_t datauart_sobj; +#endif + +/** + * @brief retarge print. + * + * @param ch char data to sent. + * @return char data to sent. +*/ +static int32_t data_uart_send_char(int32_t ch) +{ +#if defined(CONFIG_PLATFORM_8721D) +#if (USE_DEDICATED_BT_MESH_DATA_UART == 0) + LOGUART_PutChar((uint8_t)ch); +#else + UART_CharPut(data_uart_def, (uint8_t)ch); + UART_WaitBusy(data_uart_def, 10); +#endif + return (ch); +#elif defined(CONFIG_PLATFORM_8710C) +#if (USE_DEDICATED_BT_MESH_DATA_UART == 1) + serial_putc(&datauart_sobj, (uint8_t)ch); +#else + uart_put_char((uint8_t)ch); +#endif + return (ch); +#endif +} + +uint32_t data_uart_send_string(const uint8_t *data, uint32_t len) +{ + for (uint32_t i = 0; i < len; ++i) + { + data_uart_send_char(data[i]); + } + + return len; +} +/** + * @brief retarge print. + * + * @param buf + * @param fmt + * @param dp + * @return. +*/ +static int32_t data_uart_vsprintf(char *buf, const char *fmt, const int32_t *dp) +{ + char *p, *s; + + s = buf; + for (; *fmt != '\0'; ++fmt) + { + if (*fmt != '%') + { + buf ? *s++ = *fmt : data_uart_send_char(*fmt); + continue; + } + if (*++fmt == 's') + { + for (p = (char *)*dp++; *p != '\0'; p++) + { + buf ? *s++ = *p : data_uart_send_char(*p); + } + } + else /* Length of item is bounded */ + { + char tmp[SPRINTF_BUF_LEN], *q = tmp; + int32_t alt = 0; + int32_t shift = 28; + int32_t width = 0; + bool placeholder = false; + +#if 1 //wei patch for %02x + if ((*fmt >= '0') && (*fmt <= '9')) + { + unsigned char fch = *fmt; + if (fch == '0') + { + placeholder = true; + } + for (; (fch >= '0') && (fch <= '9'); fch = *++fmt) + { + width = width * 10 + fch - '0'; + } + shift = (width - 1) * 4; + } +#endif + + /* + * Before each format q points to tmp buffer + * After each format q points past end of item + */ + + if ((*fmt == 'x') || (*fmt == 'X') || (*fmt == 'p') || (*fmt == 'P')) + { + /* With x86 gcc, sizeof(long) == sizeof(int32_t) */ + const long *lp = (const long *)dp; + long h = *lp++; + int32_t ncase = (*fmt & 0x20); + dp = (const int32_t *)lp; + if ((*fmt == 'p') || (*fmt == 'P')) + { + alt = 1; + } + if (alt) + { + *q++ = '0'; + *q++ = 'X' | ncase; + } + bool skip = true; + for (; shift >= 0; shift -= 4) + { + char ts = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase; + if (ts != '0' || shift == 0) + { + skip = false; + } + if (skip) + { + if (!width) + { + continue; + } + else if (placeholder == false) + { + ts = ' '; + } + } + *q++ = ts; + if (q - tmp >= SPRINTF_BUF_LEN) + { + break; + } + } + } + else if (*fmt == 'd') + { + int32_t i = *dp++; + char *r; + if (i < 0) + { + *q++ = '-'; + i = -i; + } + p = q; /* save beginning of digits */ + do + { + *q++ = '0' + (i % 10); + i /= 10; + if (q - tmp >= SPRINTF_BUF_LEN) + { + break; + } + } + while (i); + + if (width > q - tmp) + { + if (width > SPRINTF_BUF_LEN) + { + width = SPRINTF_BUF_LEN; + } + width -= (q - tmp); + memset(q, placeholder ? '0' : ' ', width); + q += width; + } + + /* reverse digits, stop in middle */ + r = q; /* don't alter q */ + while (--r > p) + { + i = *r; + *r = *p; + *p++ = i; + } + } + else if (*fmt == 'c') + { + *q++ = *dp++; + } + else + { + *q++ = *fmt; + } + /* now output the saved string */ + for (p = tmp; p < q; ++p) + { + buf ? *s++ = *p : data_uart_send_char(*p); + } + } + } + if (buf) + { + *s = '\0'; + } + return (s - buf); +} + +/** + * @brief Data UART interrupt handle. + * + * @param none + * @return none +*/ +#if defined(CONFIG_PLATFORM_8721D) +void mesh_data_uart_irq(void *data) +{ + /* avoid gcc compile warning */ + (void)data; + uint8_t int_id; + uint8_t rx_data; + uint8_t reg_iir = UART_IntStatus(data_uart_def); + if ((reg_iir & RUART_IIR_INT_PEND) != 0) + { + /* no pending irq */ + return ; + } + + int_id = (reg_iir & RUART_IIR_INT_ID) >> 1; + + switch (int_id) + { + /* rx data valiable */ + case RUART_RECEIVER_DATA_AVAILABLE: + case RUART_TIME_OUT_INDICATION: + if (UART_Readable(data_uart_def)) + //while (UART_Readable(data_uart_def)) + { + UART_CharGet(data_uart_def, &rx_data); + pf_data_uart_send_msg(rx_data); + } + break; + /* receive line status interrupt */ + case RUART_RECEIVE_LINE_STATUS: + printe("data_uart_isr Line status error, fail!"); + break; + default: + break; + } +} +#elif defined(CONFIG_PLATFORM_8710C) +void mesh_data_uart_irq(uint32_t id, SerialIrq event) +{ + uint8_t rx_char; + serial_t *sobj = (void *)id; + + if (event == RxIrq) + { + rx_char = serial_getc(sobj); + pf_data_uart_send_msg(rx_char); + } +} +#endif + +/** + * @brief initiate Data UART. + * + * @param none + * @return none +*/ +#define DATAUART_IRQ_PRIO 11 +void mesh_data_uart_init(uint32_t tx_pin, uint32_t rx_pin, pf_send_msg_from_isr_t pf_send) +{ + /* avoid gcc compile warning */ + (void)tx_pin; + (void)rx_pin; + + data_uart_flag = true; + pf_data_uart_send_msg = pf_send; +#if defined(CONFIG_PLATFORM_8721D) +#if (USE_DEDICATED_BT_MESH_DATA_UART == 1) + //PIN TX:A_18 RX:PA 19 + IRQn_Type irqn = UART0_IRQ; + UART_InitTypeDef UART_InitStruct; + Pinmux_Config(tx_pin, PINMUX_FUNCTION_UART); + Pinmux_Config(rx_pin, PINMUX_FUNCTION_UART); + + PAD_PullCtrl(tx_pin, GPIO_PuPd_UP); + PAD_PullCtrl(rx_pin, GPIO_PuPd_UP); + data_uart_def = UART0_DEV; + + //UART_PinMuxInit(0, S0); + UART_StructInit(&UART_InitStruct); + UART_InitStruct.WordLen = RUART_WLS_8BITS; + UART_InitStruct.StopBit = RUART_STOP_BIT_1; + UART_InitStruct.Parity = RUART_PARITY_DISABLE; + UART_InitStruct.ParityType = RUART_EVEN_PARITY; + UART_InitStruct.StickParity = RUART_STICK_PARITY_DISABLE; + UART_InitStruct.RxFifoTrigLevel = UART_RX_FIFOTRIG_LEVEL_1BYTES; + UART_InitStruct.FlowControl = FALSE; + UART_Init(data_uart_def, &UART_InitStruct); + UART_SetBaud(data_uart_def, 115200); + + InterruptDis(irqn); + InterruptUnRegister(irqn); + InterruptRegister((IRQ_FUN)mesh_data_uart_irq, irqn, NULL, DATAUART_IRQ_PRIO); + InterruptEn(irqn, DATAUART_IRQ_PRIO); + UART_INTConfig(data_uart_def, RUART_IER_ERBI | RUART_IER_ETOI | RUART_IER_ELSI, ENABLE); + + UART_RxCmd(data_uart_def, ENABLE); +#endif +#elif defined(CONFIG_PLATFORM_8710C) +#if (USE_DEDICATED_BT_MESH_DATA_UART == 1) + hal_pinmux_unregister(tx_pin, 0x01 << 4); + hal_pinmux_unregister(rx_pin, 0x01 << 4); + hal_gpio_pull_ctrl(tx_pin, 0); + hal_gpio_pull_ctrl(rx_pin, 0); + + serial_init(&datauart_sobj, tx_pin, rx_pin); + serial_baud(&datauart_sobj, 115200); + serial_format(&datauart_sobj, 8, ParityNone, 1); + serial_irq_handler(&datauart_sobj, mesh_data_uart_irq, (uint32_t)&datauart_sobj); + serial_irq_set(&datauart_sobj, RxIrq, 1); + serial_irq_set(&datauart_sobj, TxIrq, 1); +#endif +#endif +} + +void data_uart_debug(char *fmt, ...) +{ + if (data_uart_flag) + { + data_uart_vsprintf(0, fmt, ((const int32_t *)&fmt) + 1); + } +} + +void data_uart_dump(uint8_t *pbuffer, uint32_t len) +{ + if (data_uart_flag) + { + data_uart_send_char('0'); + data_uart_send_char('x'); + for (uint32_t loop = 0; loop < len; loop++) + { + char data = "0123456789ABCDEF"[pbuffer[loop] >> 4]; + data_uart_send_char(data); + data = "0123456789ABCDEF"[pbuffer[loop] & 0x0f]; + data_uart_send_char(data); + } + data_uart_send_char('\r'); + data_uart_send_char('\n'); + } +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.h new file mode 100644 index 00000000..8635685b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.h @@ -0,0 +1,61 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file data_uart.h + * @brief Head file for Data uart operations. + * @details Data uart init and print vital data through data uart. + * @author bill + * @date 2015-03-19 + * @version v2.0 + * ************************************************************************************* + */ + +#ifndef _DATA_UART_H_ +#define _DATA_UART_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "platform_misc.h" +/**************************************************************************************************************** +* macros that other .c files may use all defined here +****************************************************************************************************************/ +/** + * @addtogroup DATA_UART + * @{ + */ + +/** + * @defgroup Data_Uart_Exported_Types Data Uart Exported Types + * @brief + * @{ + */ + +/** @brief Print data use Data UART. */ +typedef void (*pf_send_msg_from_isr_t)(uint8_t data); +/** @} */ + +/**************************************************************************************************************** +* exported functions other .c files may use all defined here. +****************************************************************************************************************/ +/** + * @defgroup Data_Uart_Exported_Functions Data Uart Exported Functions + * @brief + * @{ + */ +/* Print formated data use Data UART */ +extern void data_uart_debug(char *fmt, ...); +extern void data_uart_dump(uint8_t *pbuffer, uint32_t len); +extern uint32_t data_uart_send_string(const uint8_t *data, uint32_t len); +extern void mesh_data_uart_init(uint32_t tx_pin, uint32_t rx_pin, pf_send_msg_from_isr_t pf_send); +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c new file mode 100644 index 00000000..f4cff3fc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c @@ -0,0 +1,580 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file user_cmd_parse.c + * @brief Source file for command parse. + * @details Parse user commands and execute right commands. + * @author bill + * @date 2017-05-16 + * @version v2.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "platform_os.h" + +/* User command interface data, used to parse the commands from Data UART. */ +user_cmd_if_t *puser_cmd_if; + +/** + * @brief Check, if a character is a white space. + * + * @param c char data to check. + * @return check result. + * @retval 1 TRUE. + * @retval 1 FALSE. +*/ +static bool user_cmd_is_white_space(char c) +{ + return (((c >= 9) && (c <= 13)) || (c == 32)); +} + +/** + * @brief Skip white spaces in buffer. + * + * @param buffer + * @return pointer to skipped white spaces' new buffer. +*/ +char *user_cmd_skip_spaces(char *buffer) +{ + char *p = buffer; + + while (user_cmd_is_white_space(*p)) /* white space */ + { + p++; + } + return p; +} + +/** + * @brief Find end of a word. + * + * @param buffer + * @return +*/ +char *user_cmd_find_end_of_word(char *buffer) +{ + char *p = buffer; + + while (!user_cmd_is_white_space(*p) && (*p != '\0')) + { + p++; + } + return p; +} + +/** + * @brief Read ASCII string and convert to uint32_t. + * + * @param p + * @return +*/ +uint32_t user_cmd_string2uint32(char *p) +{ + uint32_t result = 0; + char ch; + bool hex = false; + + /* check if value is dec */ + if (p[0] == 'x' || p[0] == 'X') + { + hex = true; + p = &p[1]; + } + else if ((p[0] == '0') && (p[1] == 'x' || p[1] == 'X')) + { + hex = true; + p = &p[2]; + } + + for (;;) + { + ch = *(p++) | 0x20; /* convert to lower case */ + + if (hex) /* dec value */ + { + /* hex value */ + if ((ch >= 'a') && (ch <= 'f')) + { + ch -= ('a' - 10); + } + else if ((ch >= '0') && (ch <= '9')) + { + ch -= '0'; + } + else + { + break; + } + result = (result << 4); + result += (ch & 0x0f); + } + else + { + if (ch < '0' || ch > '9') + { + break; /* end of string reached */ + } + result = 10 * result + ch - '0'; + } + } + return (result); +} + +/** + * @brief Send result, display in UART Assitant. + * + * @param pUserCmdIF command parsed. + * @param Result command parse result. + * @return none +*/ +static void user_cmd_send_result(user_cmd_parse_result_t result) +{ + switch (result) + { + case USER_CMD_RESULT_ERROR: + data_uart_debug("Error\n\r"); + break; + case USER_CMD_RESULT_CMD_NOT_FOUND: + data_uart_debug("Command not found\n\r"); + break; + case USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS: + data_uart_debug("Wrong number of parameters\n\r"); + break; + case USER_CMD_RESULT_WRONG_PARAMETER: + data_uart_debug("Wrong parameter\n\r"); + break; + case USER_CMD_RESULT_VALUE_OUT_OF_RANGE: + data_uart_debug("Value out of range\n\r"); + break; + default: + break; + } +} + +/** + * @brief execute cmd. + * + * @param pUserCmdIF command parsed. + * @param pparse_value command parse value. + * @param pCmdTable command table, include user self-definition command function. + * @return command execute result. +*/ +static user_cmd_parse_result_t user_cmd_list(user_cmd_parse_value_t *pparse_value, + const user_cmd_table_entry_t *pcmd_table) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + int32_t i = 0; + user_cmd_parse_result_t Result = USER_CMD_RESULT_CMD_NOT_FOUND; + + /* find command in table */ + while ((pcmd_table + i)->pcommand != NULL) + { + data_uart_debug((pcmd_table + i)->poption); + data_uart_debug(" *"); + data_uart_debug((pcmd_table + i)->phelp); + Result = USER_CMD_RESULT_OK; + i++; + }; + + data_uart_debug(",.\r\n *up down\r\n"); + data_uart_debug("[]\r\n *left right\r\n"); + data_uart_debug("/\\\r\n *home end\r\n"); + data_uart_debug("backspace\r\n *delete\r\n"); + + return (Result); +} + +static user_cmd_parse_result_t user_cmd_execute(user_cmd_parse_value_t *pparse_value, + const user_cmd_table_entry_t *pcmd_table) +{ + int32_t i = 0; + user_cmd_parse_result_t Result = USER_CMD_RESULT_CMD_NOT_FOUND; + + if (strcmp((const char *)pparse_value->pcommand, (const char *)"?") == 0) + { + user_cmd_list(pparse_value, pcmd_table); + return USER_CMD_RESULT_OK; + } + + /* find command in table */ + while ((pcmd_table + i)->pcommand != NULL) + { + if (strcmp((const char *)(pcmd_table + i)->pcommand, (const char *)pparse_value->pcommand) == 0) + { + /* command found */ + /* check if user wants help */ + if (pparse_value->para_count && *pparse_value->pparameter[0] == '?') + { + data_uart_debug((pcmd_table + i)->poption); + data_uart_debug(" *"); + data_uart_debug((pcmd_table + i)->phelp); + Result = USER_CMD_RESULT_OK; + } + else + { + /* execute command function */ + Result = (pcmd_table + i)->user_cmd_func(pparse_value); + } + /* exit while */ + break; + } + i++; + }; + + return (Result); +} + +/** + * @brief Parse a command line and return the found + * command and parameters in "pparse_value" + * + * @param pUserCmdIF command parsed. + * @param pparse_value command parse value. + * @return command parse result. +*/ +static user_cmd_parse_result_t user_cmd_parse(user_cmd_parse_value_t *pparse_value) +{ + int32_t i; + user_cmd_parse_result_t Result; + char *p, *q; + + /* clear all results */ + Result = USER_CMD_RESULT_OK; + pparse_value->pcommand = NULL; + pparse_value->para_count = 0; + for (i = 0 ; i < USER_CMD_MAX_PARAMETERS; i++) + { + pparse_value->pparameter[i] = NULL; + pparse_value->dw_parameter[i] = 0; + } + + /* Parse line */ + p = puser_cmd_if->cmd_line; + + /*ignore leading spaces */ + p = user_cmd_skip_spaces(p); + if (*p == '\0') /* empty command line ? */ + { + Result = USER_CMD_RESULT_EMPTY_CMD_LINE; + } + else + { + /* find end of word */ + q = user_cmd_find_end_of_word(p); + if (p == q) /* empty command line ? */ + { + Result = USER_CMD_RESULT_EMPTY_CMD_LINE; + } + else /* command found */ + { + pparse_value->pcommand = p; + *q = '\0'; /* mark end of command */ + p = q + 1; + /* parse parameters */ + if (*p != '\0') /* end of line ? */ + { + uint8_t j = 0; + + do + { + uint32_t d; + /* ignore leading spaces */ + p = user_cmd_skip_spaces(p); + d = user_cmd_string2uint32(p); + + pparse_value->pparameter[j] = p; + pparse_value->dw_parameter[j++] = d; + + if (j >= USER_CMD_MAX_PARAMETERS) + { + break; + } + + /* find next parameter */ + p = user_cmd_find_end_of_word(p); + *p++ = '\0'; /* mark end of parameter */ + } + while (*p != '\0'); + pparse_value->para_count = j; + } + } + } + + return (Result); +} + +static void user_cmd_move_back(void) +{ + for (uint8_t loop = 0; loop < puser_cmd_if->cmd_len - puser_cmd_if->cmd_cur; loop ++) + { + puser_cmd_if->cmd_line[puser_cmd_if->cmd_len - loop] = puser_cmd_if->cmd_line[puser_cmd_if->cmd_len + - loop - 1]; + } +} + +static void user_cmd_move_forward(void) +{ + for (uint8_t loop = 0; loop < puser_cmd_if->cmd_len - puser_cmd_if->cmd_cur; loop ++) + { + puser_cmd_if->cmd_line[puser_cmd_if->cmd_cur + loop - 1] = + puser_cmd_if->cmd_line[puser_cmd_if->cmd_cur + loop]; + } +} + +/** + * @brief clear command line buffer + * + * @param none + * @return none + */ +static void user_cmd_clear_command(void) +{ + puser_cmd_if->cmd_len = 0; + puser_cmd_if->cmd_cur = 0; + memset(puser_cmd_if->cmd_line, 0, sizeof(puser_cmd_if->cmd_line)); +} + +/** + * @brief clear screen from cursor + * + * @param none + * @return none + */ +static void user_cmd_clear_screen(void) +{ + if (puser_cmd_if->cmd_cur < puser_cmd_if->cmd_len) + { + data_uart_debug("%s", puser_cmd_if->cmd_line + puser_cmd_if->cmd_cur); + } + + while (puser_cmd_if->cmd_len != 0) + { + puser_cmd_if->cmd_len--; + puser_cmd_if->cmd_line[puser_cmd_if->cmd_len] = '\0'; + data_uart_debug("\b \b"); + } + puser_cmd_if->cmd_cur = 0; +} + +/** + * @brief collect cmd characters. + * + * @param pUserCmdIF store parsed commands. + * @param pdata data to be parsed. + * @param len length of data to be command parsed. + * @param pcmd_table command table to execute function. + * @return command collect result. + * @retval 1 TRUE. + * @retval 0 FALSE. + */ +bool mesh_user_cmd_collect(uint8_t *pdata, uint8_t len, const user_cmd_table_entry_t *pcmd_table) +{ + user_cmd_parse_value_t parse_value; + char c; + + /* discard rx data as long help text output is in progress */ + while (len--) + { + c = *pdata++; + if (c != 0x0) /* not ESC character received */ + { + switch (c) /* Normal handling */ + { + case '\n': + case '\r': /* end of line */ + data_uart_debug("%s", puser_cmd_if->cmd_crlf); + puser_cmd_if->history_cur = USER_CMD_MAX_HISTORY_LINE; + if (puser_cmd_if->cmd_len > 0) /* at least one character in command line ? */ + { + // save cmd first + if (puser_cmd_if->history_head == USER_CMD_MAX_HISTORY_LINE) + { + puser_cmd_if->history_head = 0; + puser_cmd_if->history_tail = 0; + } + else + { + puser_cmd_if->history_tail = (puser_cmd_if->history_tail + 1) % USER_CMD_MAX_HISTORY_LINE; + if (puser_cmd_if->history_tail == puser_cmd_if->history_head) + { + puser_cmd_if->history_head = (puser_cmd_if->history_head + 1) % USER_CMD_MAX_HISTORY_LINE; + } + } + puser_cmd_if->cmd_history_len[puser_cmd_if->history_tail] = puser_cmd_if->cmd_len; + memcpy(puser_cmd_if->cmd_history[puser_cmd_if->history_tail], puser_cmd_if->cmd_line, + puser_cmd_if->cmd_len); + + user_cmd_parse_result_t Result; + //puser_cmd_if->cmd_line[puser_cmd_if->cmd_len] = '\0'; + Result = user_cmd_parse(&parse_value); + if (Result == USER_CMD_RESULT_OK) + { + Result = user_cmd_execute(&parse_value, pcmd_table); + } + + if (Result != USER_CMD_RESULT_OK) + { + user_cmd_send_result(Result); + } + } + + data_uart_debug("%s", puser_cmd_if->cmd_prompt); + + /* maybe more than 1 cmd in pData: */ + user_cmd_clear_command(); + break; + case '\b': /* backspace */ + if (puser_cmd_if->cmd_len > 0 && puser_cmd_if->cmd_cur > 0) + { + //memcpy(puser_cmd_if->cmd_line + puser_cmd_if->cmd_cur - 1, puser_cmd_if->cmd_line + puser_cmd_if->cmd_cur, puser_cmd_if->cmd_len - puser_cmd_if->cmd_cur); + user_cmd_move_forward(); + puser_cmd_if->cmd_len--; + puser_cmd_if->cmd_cur--; + puser_cmd_if->cmd_line[puser_cmd_if->cmd_len] = '\0'; + data_uart_debug("\b%s", puser_cmd_if->cmd_line + puser_cmd_if->cmd_cur); + data_uart_debug(" \b"); + for (uint8_t loop = 0; loop < puser_cmd_if->cmd_len - puser_cmd_if->cmd_cur; loop++) + { + data_uart_debug("\b"); + } + } + break; + case 44: /* up: , */ + if (puser_cmd_if->history_head != USER_CMD_MAX_HISTORY_LINE) + { + user_cmd_clear_screen(); + if (puser_cmd_if->history_cur == USER_CMD_MAX_HISTORY_LINE) + { + puser_cmd_if->history_cur = puser_cmd_if->history_tail; + } + else + { + if (puser_cmd_if->history_cur != puser_cmd_if->history_head) + { + puser_cmd_if->history_cur = (puser_cmd_if->history_cur + USER_CMD_MAX_HISTORY_LINE - 1) % + USER_CMD_MAX_HISTORY_LINE; + } + else + { + puser_cmd_if->history_cur = USER_CMD_MAX_HISTORY_LINE; + break; + } + } + puser_cmd_if->cmd_len = puser_cmd_if->cmd_history_len[puser_cmd_if->history_cur]; + puser_cmd_if->cmd_cur = puser_cmd_if->cmd_len; + memcpy(puser_cmd_if->cmd_line, puser_cmd_if->cmd_history[puser_cmd_if->history_cur], + puser_cmd_if->cmd_len); + data_uart_debug("%s", puser_cmd_if->cmd_line); + } + break; + case 46: /* down: . */ + if (puser_cmd_if->history_head != USER_CMD_MAX_HISTORY_LINE) + { + user_cmd_clear_screen(); + if (puser_cmd_if->history_cur == USER_CMD_MAX_HISTORY_LINE) + { + puser_cmd_if->history_cur = puser_cmd_if->history_head; + } + else + { + if (puser_cmd_if->history_cur != puser_cmd_if->history_tail) + { + puser_cmd_if->history_cur = (puser_cmd_if->history_cur + 1) % USER_CMD_MAX_HISTORY_LINE; + } + else + { + puser_cmd_if->history_cur = USER_CMD_MAX_HISTORY_LINE; + break; + } + } + puser_cmd_if->cmd_len = puser_cmd_if->cmd_history_len[puser_cmd_if->history_cur]; + puser_cmd_if->cmd_cur = puser_cmd_if->cmd_len; + memcpy(puser_cmd_if->cmd_line, puser_cmd_if->cmd_history[puser_cmd_if->history_cur], + puser_cmd_if->cmd_len); + data_uart_debug("%s", puser_cmd_if->cmd_line); + } + break; + case 91: /* left: [ */ + if (puser_cmd_if->cmd_cur > 0) + { + data_uart_debug("\b"); + puser_cmd_if->cmd_cur--; + } + break; + case 93: /* right: ] */ + if (puser_cmd_if->cmd_cur < puser_cmd_if->cmd_len) + { + data_uart_debug("%c", puser_cmd_if->cmd_line[puser_cmd_if->cmd_cur]); + puser_cmd_if->cmd_cur++; + } + break; + case 92: /* end: \ */ + if (puser_cmd_if->cmd_cur < puser_cmd_if->cmd_len) + { + data_uart_debug("%s", puser_cmd_if->cmd_line + puser_cmd_if->cmd_cur); + puser_cmd_if->cmd_cur = puser_cmd_if->cmd_len; + } + break; + case 47: /* begin: / */ + while (puser_cmd_if->cmd_cur > 0) + { + data_uart_debug("\b"); + puser_cmd_if->cmd_cur--; + } + break; + default: + /* Put character in command buffer */ + if (puser_cmd_if->cmd_len < USER_CMD_MAX_COMMAND_LINE) + { + user_cmd_move_back(); + puser_cmd_if->cmd_line[puser_cmd_if->cmd_cur] = c; + data_uart_debug("%s", puser_cmd_if->cmd_line + puser_cmd_if->cmd_cur); + puser_cmd_if->cmd_len++; + puser_cmd_if->cmd_cur++; + for (uint8_t loop = 0; loop < puser_cmd_if->cmd_len - puser_cmd_if->cmd_cur; loop++) + { + data_uart_debug("\b"); + } + } + break; + } + } + else + { + //clear + + } + } + + return (true); +} + +void mesh_user_cmd_init(char *s) +{ + puser_cmd_if = (user_cmd_if_t *)plt_malloc(sizeof(user_cmd_if_t), RAM_TYPE_DATA_OFF); + memset((void *)puser_cmd_if, 0, sizeof(user_cmd_if_t)); + puser_cmd_if->cmd_crlf[0] = '\r'; + puser_cmd_if->cmd_crlf[1] = '\n'; + puser_cmd_if->cmd_prompt[0] = '>'; + puser_cmd_if->history_head = USER_CMD_MAX_HISTORY_LINE; + puser_cmd_if->history_tail = USER_CMD_MAX_HISTORY_LINE; + puser_cmd_if->history_cur = USER_CMD_MAX_HISTORY_LINE; + + data_uart_debug(">> Hello %s <<\r\n%s", s, puser_cmd_if->cmd_prompt); +} + +void mesh_user_cmd_deinit(char *s) +{ + if (puser_cmd_if) { + data_uart_debug(">> Goodbye %s <<\r\n", s); + plt_free(puser_cmd_if, RAM_TYPE_DATA_OFF); + puser_cmd_if = NULL; + } +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.h new file mode 100644 index 00000000..f534d0ed --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.h @@ -0,0 +1,143 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file user_cmd_parse.h + * @brief Source file for command parse. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-05-16 + * @version v2.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#ifndef __MESH_USER_CMD_PARSE_H +#define __MESH_USER_CMD_PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "platform_misc.h" +#include + +/**************************************************************************************************************** +* macros that other .c files may use all defined here +****************************************************************************************************************/ +/** + * @addtogroup CMD_PARSE + * @{ + */ + +/** + * @defgroup Cmd_Parse_Exported_Macros Command Parser Exported Macros + * @brief + * @{ + */ + +/** @brief command parse related macros. */ +#define USER_CMD_MAX_COMMAND_LINE 70 /* max. length of command line in bytes */ + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#define USER_CMD_MAX_PARAMETERS 80 /* max. number of parameters that the parser will scan */ +#else +#define USER_CMD_MAX_PARAMETERS 25 /* max. number of parameters that the parser will scan */ +#endif + +#define USER_CMD_MAX_HISTORY_LINE 3 +/** @} */ + +/** + * @defgroup Cmd_Parse_Exported_Types Command Parser Exported Types + * @brief + * @{ + */ + +/** + * @brief Data UART command parse value. + * + * This is the structure where the command line parser puts its values. + */ +typedef struct +{ + char *pcommand; /* pointer to command */ + uint8_t para_count; /* number of found parameters */ + uint32_t dw_parameter[USER_CMD_MAX_PARAMETERS]; /* automatically parsed parameters */ + char *pparameter[USER_CMD_MAX_PARAMETERS]; /* automatically parsed parameters */ +} user_cmd_parse_value_t; + +/** + * @brief Data UART command parse result. + * + * This is the structure where the command line parser puts its result. + */ +typedef enum +{ + USER_CMD_RESULT_OK, + USER_CMD_RESULT_ERROR, + USER_CMD_RESULT_EMPTY_CMD_LINE, + USER_CMD_RESULT_CMD_NOT_FOUND, + USER_CMD_RESULT_WRONG_PARAMETER, + USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS, + USER_CMD_RESULT_VALUE_OUT_OF_RANGE +} user_cmd_parse_result_t; + +/** + * @brief command interface. + */ +typedef struct +{ + char cmd_line[USER_CMD_MAX_COMMAND_LINE + 2]; + uint8_t cmd_len; /**< accumulated length of command */ + uint8_t cmd_cur; /**< cmd cursor */ + uint8_t cmd_history[USER_CMD_MAX_HISTORY_LINE][USER_CMD_MAX_COMMAND_LINE + 2]; + uint8_t cmd_history_len[USER_CMD_MAX_HISTORY_LINE]; + uint8_t history_head; + uint8_t history_tail; + uint8_t history_cur; /**< current cmd pointer */ + char cmd_prompt[2]; + char cmd_crlf[3]; +} user_cmd_if_t, *user_cmd_if_p; + +/** + * @brief functions that can be called from command table. + */ +typedef user_cmd_parse_result_t (*pf_user_cmd_func_t)(user_cmd_parse_value_t *pparse_value); + +/** + * @brief command table entry. + * +*/ +typedef struct +{ + char *pcommand; + char *poption; + char *phelp; + pf_user_cmd_func_t user_cmd_func; +} user_cmd_table_entry_t; +/** @} */ + +/**************************************************************************************************************** +* exported functions other .c files may use all defined here. +****************************************************************************************************************/ +/** + * @defgroup Cmd_Parse_Exported_Functions Command Parser Exported Functions + * @brief + * @{ + */ +/* initiate command interface struct */ +extern void mesh_user_cmd_init(char *s); +/* deinitiate command interface struct */ +extern void mesh_user_cmd_deinit(char *s); +/* collect user command from Data UART strings */ +extern bool mesh_user_cmd_collect(uint8_t *pdata, uint8_t len, const user_cmd_table_entry_t *pcmd_table); +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __USER_CMD_PARSE_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/misc_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/misc_cmd.c new file mode 100644 index 00000000..f1ed222d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/misc_cmd.c @@ -0,0 +1,188 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file misc_cmd.h + * @brief Head file for miscellaneous cmd. + * @details User command interfaces. + * @author bill + * @date 2017-12-18 + * @version v1.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include "misc_cmd.h" +#include "gap.h" +#include "gap_bondmgr.h" +#include "profile.h" +#include "profile_client.h" + +user_cmd_parse_result_t user_cmd_io_capa_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t ioCap = GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT; + if (pparse_value->para_count >= 1) + { + switch (pparse_value->dw_parameter[0]) + { + case 0: + ioCap = GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT; + data_uart_debug("GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT\r\n"); + break; + case 1: + ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; + data_uart_debug("GAPBOND_IO_CAP_DISPLAY_ONLY\r\n"); + break; + case 2: + ioCap = GAPBOND_IO_CAP_KEYBOARD_ONLY; + data_uart_debug("GAPBOND_IO_CAP_KEYBOARD_ONLY\r\n"); + break; + case 3: + ioCap = GAPBOND_IO_CAP_DISPLAY_YES_NO; + data_uart_debug("GAPBOND_IO_CAP_DISPLAY_YES_NO\r\n"); + break; + case 4: + ioCap = GAPBOND_IO_CAP_KEYBOARD_DISPLAY; + data_uart_debug("GAPBOND_IO_CAP_KEYBOARD_DISPLAY\r\n"); + break; + default: + data_uart_debug("GAPBOND_IO_CAP parameter error!!!\r\n"); + break; + } + } + else + { + data_uart_debug("GAPBOND_IO_CAP_NO_INPUT_NO_OUTPUT\r\n"); + } + GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap); + GAPBondMgr_SetPairable(); + + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_security_req(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Security Req\r\n"); + GAPBondMgr_Pair(); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_con_update_req(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Con Update Req\r\n"); + gap_con_params_update(); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_service_discover(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Service Discoverying\r\n"); + clientAPI_AllPrimarySrvDiscovery(); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_relation_discover(user_cmd_parse_value_t *pparse_value) +{ + TRelationDiscReq relationReq; + relationReq.wStartHandle = (uint16_t)pparse_value->dw_parameter[0]; + relationReq.wEndHandle = (uint16_t)pparse_value->dw_parameter[1]; + if (relationReq.wStartHandle > relationReq.wEndHandle) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + data_uart_debug("Relationship Discoverying\r\n"); + clientAPI_RelationshipDiscovery(AppProcessGeneralClientMsgID, relationReq); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_character_discover(user_cmd_parse_value_t *pparse_value) +{ + TCharDiscReq char_req; + char_req.wStartHandle = (uint16_t)pparse_value->dw_parameter[0]; + char_req.wEndHandle = (uint16_t)pparse_value->dw_parameter[1]; + if (char_req.wStartHandle > char_req.wEndHandle) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + data_uart_debug("Char Discoverying\r\n"); + clientAPI_AllCharDiscovery(AppProcessGeneralClientMsgID, char_req); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_character_descriptor_discover( + user_cmd_parse_value_t *pparse_value) +{ + TCharDescriptorDiscReq charDescriptorReq; + charDescriptorReq.wStartHandle = (uint16_t)pparse_value->dw_parameter[0]; + charDescriptorReq.wEndHandle = (uint16_t)pparse_value->dw_parameter[1]; + if (charDescriptorReq.wStartHandle > charDescriptorReq.wEndHandle) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + data_uart_debug("Descriptor Discoverying\r\n"); + clientAPI_AllCharDescriptorDiscovery(AppProcessGeneralClientMsgID, charDescriptorReq); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_attribute_read(user_cmd_parse_value_t *pparse_value) +{ + TReadHandleReq readHandle; + + data_uart_debug("Attrib Read\r\n"); + readHandle.wHandle = (uint16_t)pparse_value->dw_parameter[0]; + clientAPI_AttribRead(AppProcessGeneralClientMsgID, readHandle); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_attribute_read_by_uuid(user_cmd_parse_value_t *pparse_value) +{ + TReadUUIDReq readUUIDReq; + readUUIDReq.UUID16 = (uint16_t)pparse_value->dw_parameter[2]; + readUUIDReq.wStartHandle = (uint16_t)pparse_value->dw_parameter[0]; + readUUIDReq.wEndHandle = (uint16_t)pparse_value->dw_parameter[1]; + if (readUUIDReq.wStartHandle > readUUIDReq.wEndHandle) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + data_uart_debug("Attrib Read by UUID\r\n"); + clientAPI_AttribReadUsingUUID(AppProcessGeneralClientMsgID, readUUIDReq); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_tx_power_set(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char to be written. */ + TBLE_TX_POWER_INDEX tx_power_index = (TBLE_TX_POWER_INDEX)pparse_value->dw_parameter[0]; + data_uart_debug("Tx Power Set\r\n"); + gap_set_tx_power(tx_power_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_rssi_read(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Rssi Read\r\n"); + gap_read_rssi(); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_patch_version_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t patchVersion; + blueAPI_ReadPatchVersion(&patchVersion); + data_uart_debug("Patch Ver Get: version = %d\r\n", patchVersion); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_channel_class_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t chanMap[5] = {0}; + uint8_t i; + for (i = 0; i < 5; i++) + { + chanMap[i] = (uint8_t)pparse_value->dw_parameter[i]; + } + data_uart_debug("Chan Class Set\r\n"); + chanMap[4] = chanMap[4] & 0x1F; + gap_set_host_channel_class(chanMap); + return USER_CMD_RESULT_OK; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/misc_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/misc_cmd.h new file mode 100644 index 00000000..d4cfe2d4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/misc_cmd.h @@ -0,0 +1,146 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file misc_cmd.h + * @brief Head file for miscellaneous cmd. + * @details User command interfaces. + * @author bill + * @date 2017-12-18 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MISC_CMD_H +#define _MISC_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +/** + * @addtogroup MISC_CMD + * @{ + */ + +/** + * @defgroup Misc_Cmd_Exported_Macros Miscellaneous Command Exported Macros + * @brief + * @{ + */ +#define MISC_CMD \ + {\ + "iocapset",\ + "iocapset [iocap]\n\r",\ + "choose io capability.\n\r",\ + user_cmd_io_capa_set\ + },\ + {\ + "sauth",\ + "sauth\n\r",\ + "bond manager authentication request.\n\r",\ + user_cmd_security_req\ + },\ + {\ + "conupdreq",\ + "conupdreq \n\r",\ + "LE connection update request\n\r",\ + user_cmd_con_update_req\ + },\ + {\ + "txpwrset",\ + "txpwrset [txpwridx]\n\r",\ + "Set the TX Power of BLE RF\n\r",\ + user_cmd_tx_power_set\ + },\ + {\ + "rssiread",\ + "rssiread\n\r",\ + "Read the RSSI value of this local MDL ID\n\r",\ + user_cmd_rssi_read\ + },\ + {\ + "patchver",\ + "patchver\n\r",\ + "Get the patch Version\n\r",\ + user_cmd_patch_version_get\ + },\ + {\ + "chanclassset",\ + "chanclassset [idx0] [idx1] [idx2] [idx3] [idx4]\n\r",\ + "Set Host Channel Classification\n\r",\ + user_cmd_channel_class_set\ + },\ + {\ + "srvdis",\ + "srvdis \n\r",\ + "Service discovery, discover all primary services.\n\r",\ + user_cmd_service_discover\ + },\ + {\ + "reldis",\ + "reldis [start] [end]\n\r",\ + "Relationship discovery\n\r",\ + user_cmd_relation_discover\ + },\ + {\ + "chardis",\ + "chardis [start] [end]\n\r",\ + "Characteristic discovery\n\r",\ + user_cmd_character_discover\ + },\ + {\ + "charddis",\ + "charddis [start] [end]\n\r",\ + "Characteristic descriptor discovery\n\r",\ + user_cmd_character_descriptor_discover\ + },\ + {\ + "read",\ + "read [handle] \n\r",\ + "Read attribute\n\r",\ + user_cmd_attribute_read\ + },\ + {\ + "readu",\ + "readu [start] [end] [UUID16]\n\r",\ + "Read attribute using UUID16\n\r",\ + user_cmd_attribute_read_by_uuid\ + } +/** @} */ + +/** + * @defgroup Misc_Cmd_Exported_Functions Miscellaneous Command Exported Functions + * @brief + * @{ + */ +user_cmd_parse_result_t user_cmd_io_capa_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_security_req(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_con_update_req(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_service_discover(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_relation_discover(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_character_discover(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_character_descriptor_discover(user_cmd_parse_value_t + *pparse_value); +user_cmd_parse_result_t user_cmd_attribute_read(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_attribute_read_by_uuid(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_tx_power_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_rssi_read(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_patch_version_get(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_channel_class_set(user_cmd_parse_value_t *pparse_value); +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _MISC_CMD_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c new file mode 100644 index 00000000..754994e8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c @@ -0,0 +1,276 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file test_cmd.h + * @brief Head file for test cmd. + * @details User command interfaces. + * @author bill + * @date 2017-12-18 + * @version v1.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include "test_cmd.h" +#include "mesh_api.h" + +user_cmd_parse_result_t user_cmd_node_state_set(user_cmd_parse_value_t *pparse_value) +{ + mesh_node_state_t node_state = pparse_value->dw_parameter[0] == 0 ? UNPROV_DEVICE : PROV_NODE; + mesh_node.node_state = node_state; + data_uart_debug("Node State:\t%d\r\n", mesh_node.node_state); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_node_addr_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 1) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t addr = pparse_value->dw_parameter[0]; + mesh_node.unicast_addr = addr & 0x7fff; + data_uart_debug("NodeAddr:\t0x%04x\r\n", mesh_node.unicast_addr); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_net_key_set(user_cmd_parse_value_t *pparse_value) +{ + uint16_t net_key_index = pparse_value->dw_parameter[0]; + uint16_t net_key_index_g = pparse_value->dw_parameter[1]; + uint8_t net_key[16]; + plt_hex_to_bin(net_key, (uint8_t *)pparse_value->pparameter[2], sizeof(net_key)); + net_key_update(net_key_index, net_key_index_g, net_key); + data_uart_debug("NetKey:\t\t"); + data_uart_dump(mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_tx_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key, 16); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_net_key_refresh(user_cmd_parse_value_t *pparse_value) +{ + uint16_t net_key_index = pparse_value->dw_parameter[0]; + uint8_t phase_old, phase_new; + phase_old = key_state_to_key_refresh_phase(mesh_node.net_key_list[net_key_index].key_state); + net_key_refresh(net_key_index); + phase_new = key_state_to_key_refresh_phase(mesh_node.net_key_list[net_key_index].key_state); + data_uart_debug("NetKey %d: phase %d -> %d\r\n", net_key_index, phase_old, phase_new); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_app_key_set(user_cmd_parse_value_t *pparse_value) +{ + uint16_t app_key_index = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index_g = pparse_value->dw_parameter[2]; + uint8_t app_key[16]; + plt_hex_to_bin(app_key, (uint8_t *)pparse_value->pparameter[3], sizeof(app_key)); + app_key_update(app_key_index, net_key_index, app_key_index_g, app_key); + data_uart_debug("AppKey:\t\t"); + data_uart_dump(mesh_node.app_key_list[app_key_index].papp_key[key_state_to_tx_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key, 16); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_dev_key_set(user_cmd_parse_value_t *pparse_value) +{ + uint8_t index = pparse_value->dw_parameter[0]; + uint8_t unicast_addr = pparse_value->dw_parameter[1]; + uint8_t element_num = pparse_value->dw_parameter[2]; + uint8_t dev_key[16]; + plt_hex_to_bin(dev_key, (uint8_t *)pparse_value->pparameter[3], sizeof(dev_key)); + dev_key_set(index, unicast_addr, element_num, dev_key); + data_uart_debug("DevKey:\t\t%d-0x%04x-%d-", index, mesh_node.dev_key_list[index].unicast_addr, + mesh_node.dev_key_list[index].element_num); + data_uart_dump(mesh_node.dev_key_list[index].dev_key, 16); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_seq_set(user_cmd_parse_value_t *pparse_value) +{ + uint32_t seq = pparse_value->dw_parameter[0]; + mesh_seq_set(seq); + data_uart_debug("Seq:\t\t0x%06x\r\n", mesh_node.seq); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_iv_index_set(user_cmd_parse_value_t *pparse_value) +{ + uint32_t iv_index = pparse_value->dw_parameter[0]; + iv_index_set(iv_index); + data_uart_debug("IVindex:\t0x%x\r\n", mesh_node.iv_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_iv_index_transit(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("IVindex:\t%d-0x%x\r\n", mesh_node.iv_update_flag, mesh_node.iv_index); + if (pparse_value->dw_parameter[0]) + { + iv_index_transit_to_iv_update(); + } + else + { + iv_index_transit_to_normal(); + } + data_uart_debug("IVindex:\t%d-0x%x\r\n", mesh_node.iv_update_flag, mesh_node.iv_index); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_iv_index_mode(user_cmd_parse_value_t *pparse_value) +{ + iv_index_test_mode_set(pparse_value->dw_parameter[0]); + data_uart_debug("IVindex mode: %s\r\n", pparse_value->dw_parameter[0] ? "Test" : "Normal"); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_nmc_clear(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + nmc_init(); + data_uart_debug("Net Msg Cache are cleared.\r\n"); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_rpl_clear(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + rpl_clear(); + rpl_clear(); + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_subscribe(user_cmd_parse_value_t *pparse_value) +{ + uint8_t element_index = pparse_value->dw_parameter[0]; + uint8_t model_index = pparse_value->dw_parameter[1]; + uint16_t addr = pparse_value->dw_parameter[2]; + mesh_model_p pmodel = mesh_model_get(element_index, model_index); + if (pmodel == NULL || MESH_NOT_SUBSCRIBE_ADDR(addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + else + { + mesh_model_sub(pmodel, addr); + return USER_CMD_RESULT_OK; + } +} + +user_cmd_parse_result_t user_cmd_test_send(user_cmd_parse_value_t *pparse_value) +{ + uint16_t addr = pparse_value->dw_parameter[0]; + uint8_t ttl = pparse_value->dw_parameter[1]; + uint8_t len = pparse_value->dw_parameter[2]; + uint8_t app_msg[20]; + for (uint8_t loop = 0; loop < len && loop < sizeof(app_msg); loop++) + { + app_msg[loop] = loop; + } + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = NULL; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = app_msg; + mesh_msg.msg_len = len; + mesh_msg.akf = pparse_value->dw_parameter[3] != 0xff; + mesh_msg.app_key_index = pparse_value->dw_parameter[3]; + mesh_msg.dst = addr; + mesh_msg.ttl = ttl; + return access_send(&mesh_msg) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : + USER_CMD_RESULT_ERROR; +} + +user_cmd_parse_result_t user_cmd_test_data(user_cmd_parse_value_t *pparse_value) +{ + uint8_t test_case = pparse_value->dw_parameter[0]; + //uint8_t app_msg[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0, 0, 0, 0}; + uint8_t app_msg[] = {0x01, 0x02, 0, 0, 0, 0}; + uint8_t app_msg1[] = {0x80, 0x11, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0, 0, 0, 0}; + uint8_t app_msg2[] = {0x80, 0x11, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0, 0, 0, 0}; + uint8_t app_msg3[] = {0x01, 0x02, 0, 0, 0, 0, 0, 0, 0, 0}; + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = NULL; + mesh_msg.msg_offset = 0; + + if (test_case == 3 || test_case == 4) + { + mesh_msg.pbuffer = app_msg1; + mesh_msg.msg_len = sizeof(app_msg1); + iv_index_set(0x01020304); + mesh_seq_set(0x08090a); + } + else if (test_case == 5) + { + mesh_msg.pbuffer = app_msg2; + mesh_msg.msg_len = sizeof(app_msg2); + iv_index_set(0x01020304); + mesh_seq_set(0x08090a); + } + else if (test_case == 6) + { + mesh_msg.pbuffer = app_msg3; + mesh_msg.msg_len = sizeof(app_msg3); + iv_index_set(0x01020304); + mesh_seq_set(0x08090a); + } + else + { + mesh_msg.pbuffer = app_msg; + mesh_msg.msg_len = sizeof(app_msg); + iv_index_set(2); + mesh_seq_set(0x010203); + } + + access_cfg(&mesh_msg); + if (test_case == 1) + { + mesh_msg.akf = 0; + } + + if (test_case == 2) + { + mesh_msg.ttl = 6; + } + else if (test_case == 3 || test_case == 4) + { + mesh_msg.ttl = 0x1a; + } + else if (test_case == 5 || test_case == 6) + { + mesh_msg.ttl = 0x12; + } + else + { + mesh_msg.ttl = 7; + } + if (test_case == 2 || test_case == 3 || test_case == 4) + { + //mesh_msg.frnd = 1; + } + if (test_case == 3 || test_case == 4 || test_case == 5 || test_case == 6) + { + mesh_msg.src = 0x0b0c; + mesh_msg.dst = 0x0d0e; + mesh_msg.app_key_index = 1; + } + else + { + mesh_msg.src = 0x0405; + mesh_msg.dst = 0x0607; + mesh_msg.app_key_index = 0; + } + + if (test_case == 6) + { + mesh_msg.szmic = 1; + mesh_msg.ctl = 1; + } + access_send(&mesh_msg); + return USER_CMD_RESULT_OK; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.h new file mode 100644 index 00000000..15427fd8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.h @@ -0,0 +1,159 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file misc_cmd.h + * @brief Head file for miscellaneous cmd. + * @details User command interfaces. + * @author bill + * @date 2017-12-18 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _TEST_CMD_H +#define _TEST_CMD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +/** + * @addtogroup TEST_CMD + * @{ + */ + +/** + * @defgroup Test_Cmd_Exported_Macros Test Command Exported Macros + * @brief + * @{ + */ +#define TEST_CMD \ + {\ + "nss",\ + "nss [node state]\n\r",\ + "node state set\n\r",\ + user_cmd_node_state_set\ + },\ + {\ + "nas",\ + "nas [unicast addr]\n\r",\ + "node addr set\n\r",\ + user_cmd_node_addr_set\ + },\ + {\ + "nks",\ + "nks [index] [index_g] [key]\n\r",\ + "net key set\n\r",\ + user_cmd_net_key_set\ + },\ + {\ + "nkr",\ + "nkr [index]\n\r",\ + "net key refresh\n\r",\ + user_cmd_net_key_refresh\ + },\ + {\ + "aks",\ + "aks [index] [index_n] [index_g] [key]\n\r",\ + "app key set\n\r",\ + user_cmd_app_key_set\ + },\ + {\ + "dks",\ + "dks [index] [address] [element_num] [key]\n\r",\ + "dev key set\n\r",\ + user_cmd_dev_key_set\ + },\ + {\ + "ss",\ + "ss [seq]\n\r",\ + "seq set\n\r",\ + user_cmd_seq_set\ + },\ + {\ + "iis",\ + "iis [iv index]\n\r",\ + "iv index set\n\r",\ + user_cmd_iv_index_set\ + },\ + {\ + "iit",\ + "iit [1: update, 0: normal]\n\r",\ + "iv index transit\n\r",\ + user_cmd_iv_index_transit\ + },\ + {\ + "iim",\ + "iim [1: on, 0: off]\n\r",\ + "iv index mode\n\r",\ + user_cmd_iv_index_mode\ + },\ + {\ + "nmcc",\ + "nmcc\n\r",\ + "net msg cache clear\n\r",\ + user_cmd_nmc_clear\ + },\ + {\ + "rplc",\ + "rplc\n\r",\ + "replay protect list clear\n\r",\ + user_cmd_rpl_clear\ + },\ + {\ + "subscribe",\ + "subscribe [element index] [model index] [addr]\n\r",\ + "subscribe\n\r",\ + user_cmd_subscribe\ + },\ + {\ + "ts",\ + "ts [dst] [ttl] [len] [app key index(0xff:DevKey)]\n\r",\ + "test send\n\r",\ + user_cmd_test_send\ + },\ + {\ + "testdata",\ + "testdata [test case]\n\r",\ + "test sample mesh pkt\n\r",\ + user_cmd_test_data\ + } +/** @} */ + +/** + * @defgroup Test_Cmd_Exported_Functions Test Command Exported Functions + * @brief + * @{ + */ +user_cmd_parse_result_t user_cmd_node_state_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_node_addr_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_net_key_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_net_key_refresh(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_app_key_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_dev_key_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_seq_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_iv_index_set(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_iv_index_transit(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_iv_index_mode(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_nmc_clear(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_rpl_clear(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_subscribe(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_test_send(user_cmd_parse_value_t *pparse_value); +user_cmd_parse_result_t user_cmd_test_data(user_cmd_parse_value_t *pparse_value); +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _TEST_CMD_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c new file mode 100644 index 00000000..32d40147 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * Copyright(c) 2019 - 2021 Realtek Corporation. All rights reserved. + * + ******************************************************************************/ +#include "dfudep_service.h" +#include "os_sched.h" +#include +#include +#include + +#if defined(MESH_DFU) && MESH_DFU +uint8_t customer_dfu_metadata_check(void *pmetadata, uint32_t len) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_resources_check(void) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_init_dfu_resources(void) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_block_verify(uint8_t *data ,uint16_t len, uint8_t signature_size) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_verify(uint16_t image_id) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_cancel(void) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_verify_cancel(void) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_apply(uint8_t reason, uint32_t delay_ms) +{ + os_delay(delay_ms); + //reboot + + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_block_data_restore(uint8_t *data , uint32_t len, uint8_t signature_size) +{ + return DFU_RESULT_FAIL; +} + +void customer_dfu_failsafe(void) +{ + return; +} + +uint8_t customer_is_dfu_enabled(void) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_get_fw_info(fw_info_t *pfw_info) +{ + return DFU_RESULT_FAIL; +} + +uint32_t customer_dfu_fw_image_data_get(uint32_t len, uint8_t *pout) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_block_signature(uint8_t *data ,uint16_t len, uint8_t signature_size) +{ + return DFU_RESULT_FAIL; +} + +uint8_t customer_dfu_check_fw_info(fw_info_t *pfw_info) +{ + return DFU_RESULT_FAIL; +} + +const struct dfudep_service_ops dfudep_service = { + /* updater server api */ + customer_dfu_metadata_check, //dfu_metadata_check + customer_dfu_resources_check, //dfu_resources_check + customer_dfu_init_dfu_resources, //dfu_init_dfu_resources + customer_dfu_block_verify, //dfu_block_verify + customer_dfu_verify, //dfu_verify + customer_dfu_cancel, //dfu_cancel + customer_dfu_verify_cancel, //dfu_verify_cancel + customer_dfu_apply, //dfu_apply + customer_dfu_block_data_restore, //dfu_block_data_restore + customer_dfu_failsafe, //dfu_failsafe + customer_is_dfu_enabled, //is_dfu_enabled + customer_dfu_get_fw_info, //dfu_get_fw_info + /* updater client api */ + customer_dfu_fw_image_data_get, //dfu_fw_image_data_get + customer_dfu_block_signature, //dfu_block_signature + customer_dfu_check_fw_info //dfu_check_fw_info +}; +#endif \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c new file mode 100644 index 00000000..5e4a264f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c @@ -0,0 +1,123 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file datatrans_client_app.c + * @brief Source file for data transmission client model. + * @details Data types and external functions declaration. + * @author hector_huang + * @date 2018-10-30 + * @version v1.0 + * ************************************************************************************* + */ +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#include "datatrans_app.h" +#include "datatrans_model.h" +#if ((defined CONFIG_BT_MESH_PROVISIONER && CONFIG_BT_MESH_PROVISIONER) || \ + (defined CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE)) +#include "bt_mesh_provisioner_api.h" +#endif +#if ((defined CONFIG_BT_MESH_DEVICE && CONFIG_BT_MESH_DEVICE) || \ + (defined CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE)) +#include "bt_mesh_device_api.h" +#endif + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#include "bt_mesh_device_test.h" +#include "bt_mesh_receive_response.h" +#endif + +mesh_model_info_t datatrans; +static uint8_t sample_data[16]; + +static int32_t datatrans_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case DATATRANS_SERVER_WRITE: + { + datatrans_server_write_t *pdata = pargs; + data_uart_debug("remote write %d bytes: ", pdata->data_len); + data_uart_dump(pdata->data, pdata->data_len); + } + break; + case DATATRANS_SERVER_READ: + { + datatrans_server_read_t *pdata = pargs; + if (pdata->data_len > 16) + { + pdata->data_len = 16; + } + + for (uint8_t i = 0; i < pdata->data_len; ++i) + { + sample_data[i] = i; + } + pdata->data = sample_data; + } + break; + case DATATRANS_CLIENT_STATUS: + { + datatrans_client_status_t *pdata = pargs; + data_uart_debug("written %d bytes, status: %d\r\n", pdata->written_len, pdata->status); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (!pdata->status) { + if (bt_mesh_indication(GEN_MESH_CODE(_datatrans_write), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_datatrans_write)); + } + } else { + if (bt_mesh_indication(GEN_MESH_CODE(_datatrans_write), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_datatrans_write)); + } + } +#endif + } + break; + case DATATRANS_CLIENT_DATA: + { + datatrans_client_data_t *pdata = pargs; + data_uart_debug("read %d data from remote: ", pdata->data_len); + data_uart_dump(pdata->data, pdata->data_len); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (pdata->data_len) { + if (bt_mesh_indication(GEN_MESH_CODE(_datatrans_read), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_datatrans_read)); + } + } else { + if (bt_mesh_indication(GEN_MESH_CODE(_datatrans_read), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_datatrans_read)); + } + } +#endif + } + break; + default: + break; + } + + return 0; +} + +void datatrans_model_init(void) +{ +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + /* register data transmission model */ +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) + datatrans.model_data_cb = common_receive_response; +#endif + +#if (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) + datatrans.model_data_cb = cmd_data_receive; +#endif +#else + /* register data transmission model */ + datatrans.model_data_cb = datatrans_data; +#endif + datatrans_reg(0, &datatrans); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.h new file mode 100644 index 00000000..00692887 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_client_app.h +* @brief Source file for data transmission client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-10-30 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _DATATRANS_APP_H_ +#define _DATATRANS_APP_H_ + +#include "mesh_api.h" +#include "platform_types.h" + +BEGIN_DECLS +/** + * @addtogroup DATATRANS_CLIENT_APP + * @{ + */ + +/** + * @defgroup Datatrans_Client_Exported_Types Datatrans Client Exported Types + * @brief + * @{ + */ +extern mesh_model_info_t datatrans; +/** @} */ + +/** + * @defgroup Datatrans_Client_Exported_Functions Datatrans Client Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize data transmission client model + */ +void datatrans_model_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _DATATRANS_CLIENT_APP_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.c new file mode 100644 index 00000000..22f8cb19 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.c @@ -0,0 +1,1237 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file dfu_distributor_app.c +* @brief Smart mesh dfu application +* @details +* @author hector_huang +* @date 2020-11-06 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#define MM_ID MM_MODEL + +#include +#include "dfu_distributor_app.h" +#include "generic_types.h" +#include "app_msg.h" +#include "bt_mesh_provisioner_api.h" + +#if MESH_DFU + +#define DFU_DIST_NODE_NUM_MAX 5 +#define DFU_DIST_RETRY_TIMES 5 +#define DFU_DIST_UPDATE_RETRY_PERIOD 2000 +#define DFU_DIST_BLOB_TRANSFER_START_RETRY_PERIOD 2000 +#define DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD 2000 +#define DFU_DIST_BLOB_CHUNK_TRANSFER_RETRY_PERIOD 3000 +#define DFU_DIST_BLOB_BLOCK_GET_RETRY_PERIOD 3000 +#define DFU_DIST_BLOB_NEW_BLOCK_PERIOD 8000 + +/* transfer capabilites */ +#define DFU_BLOCK_SIZE_LOG 10 +#define DFU_BLOCK_SIZE 1024 +#define DFU_CHUNK_SIZE 128 +#define DFU_CLIENT_MTU 256 +#define DFU_CHUNK_NUM (DFU_BLOCK_SIZE / DFU_CHUNK_SIZE) + +typedef enum +{ + DFU_DIST_PHASE_IDLE, + DFU_DIST_PHASE_UPDATE_START, + DFU_DIST_PHASE_BLOB_TRANSFER_START, + DFU_DIST_PHASE_BLOB_BLOCK_START, + DFU_DIST_PHASE_BLOB_CHUNK_TRANSFER, + DFU_DIST_PHASE_VERIFY, +} dfu_dist_phase_t; + +typedef enum +{ + DFU_NODE_PHASE_IDLE, + DFU_NODE_PHASE_UPDATE_STARTING, + DFU_NODE_PHASE_UPDATE_STARTED, + DFU_NODE_PHASE_BLOB_TRANSFER_STARTING, + DFU_NODE_PHASE_BLOB_TRANSFER_STARTED, + DFU_NODE_PHASE_BLOB_BLOCK_STARTING, + DFU_NODE_PHASE_BLOB_BLOCK_STARTED, + DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERING, + DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERED, + DFU_NODE_PHASE_FAILED, +} dfu_node_phase_t; + +typedef struct +{ + uint16_t addr; + fw_update_phase_t phase; +} dfu_dist_node_info_t; + +typedef struct _dfu_update_node_e_t +{ + struct _dfu_update_node_e_t *pnext; + /* node information */ + uint16_t addr; + uint8_t update_fw_image_idx; + /* node update status */ + //uint8_t transfer_progress; + dfu_node_phase_t node_phase; +} dfu_update_node_e_t; + +typedef enum +{ + DFU_TIMER_IDLE, + DFU_TIMER_FW_UPDATE_CLIENT_STATUS, + DFU_TIMER_BLOB_TRANSFER_START, + DFU_TIMER_BLOB_BLOCK_START, + DFU_TIMER_BLOB_BLOCK_GET, + DFU_TIMER_BLOB_CHUNK_TRANSFER +} dfu_timer_state_t; + +struct +{ + plt_timer_t timer; + dfu_timer_state_t timer_state; + dfu_dist_phase_t dist_phase; + uint8_t dist_retry_count; + fw_image_data_get_t fw_image_data_get; + uint32_t fw_image_size; + uint32_t fw_image_left_size; + plt_list_t dfu_update_node_list; + dfu_update_node_e_t *pcur_update_node; + uint8_t blob_id[8]; + uint16_t dist_app_key_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + blob_transfer_mode_t dist_transfer_mode; + fw_update_policy_t update_policy; + uint16_t dist_multicast_addr; + uint8_t fw_metadata[255]; + uint8_t metadata_len; + /* current transfer data */ + uint16_t block_num; + uint16_t total_blocks; + uint8_t *pblock_data; + uint16_t block_size; + uint16_t block_left_size; + uint16_t chunk_num; + uint16_t total_chunks; + uint8_t *pchunk_data; + uint16_t chunk_size; +} dfu_dist_ctx; + + +int32_t dfu_transfer_client_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + switch (type) + { + case BLOB_TRANSFER_CLIENT_TRANSFER_STATUS: + { + if (dfu_dist_ctx.timer_state == DFU_TIMER_BLOB_TRANSFER_START) { + plt_timer_stop(dfu_dist_ctx.timer, 0); + } else { + printf("dfu_update_client_data %d, timer state %d \r\n", __LINE__, dfu_dist_ctx.timer_state); + } + blob_transfer_client_transfer_status_t *pdata = (blob_transfer_client_transfer_status_t *)pargs; + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + if (pdata->status == BLOB_TRANSFER_STATUS_SUCCESS) + { + while (NULL != pentry) + { + if (pentry->addr == pdata->src) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTING) { + pentry->node_phase = DFU_NODE_PHASE_BLOB_TRANSFER_STARTED; + printf("dfu_transfer_client_data: node 0x%04x blob transfer start success \r\n", pdata->src); + break; + } else { + printf("dfu_transfer_client_data: node 0x%04x is not DFU_NODE_PHASE_BLOB_TRANSFER_STARTING, current state is %d \r\n", + pdata->src, pentry->node_phase); + return MODEL_SUCCESS; + } + } + pentry = pentry->pnext; + } + if (pentry == NULL) { + printf("dfu_transfer_client_data: node 0x%04x is not in the update list \r\n", pdata->src); + return MODEL_SUCCESS; + } + } + else + { + dfu_dist_ctx.pcur_update_node->node_phase = DFU_NODE_PHASE_FAILED; + printf("dfu_transfer_client_data: node 0x%04x transfer start failed, reason %d \r\n", pdata->src, + pdata->status); + dfu_dist_receiver_remove(pdata->src); + } + + /* find active node and send blob transfer start */ + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_UPDATE_STARTED) + { + blob_transfer_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, BLOB_TRANSFER_MODE_PUSH, + dfu_dist_ctx.blob_id, dfu_dist_ctx.fw_image_size, DFU_BLOCK_SIZE_LOG, DFU_CLIENT_MTU); + dfu_dist_ctx.dist_retry_count = 0; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_TRANSFER_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_TRANSFER_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_TRANSFER_STARTING; + dfu_dist_ctx.pcur_update_node = pentry; + return MODEL_SUCCESS; + } + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTING) + { + return MODEL_SUCCESS; + } + pentry = pentry->pnext; + } + + /* all node received blob transfer start message, begin blob block start */ + printf("dfu_transfer_client_data: block start, num %d \r\n", dfu_dist_ctx.block_num); + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_BLOCK_START; + /* get block data */ + dfu_dist_ctx.block_size = (dfu_dist_ctx.fw_image_left_size >= DFU_BLOCK_SIZE) ? DFU_BLOCK_SIZE : + dfu_dist_ctx.fw_image_left_size; + printf("dfu_transfer_client_data: fetch firmware, dfu_dist_ctx.block_size = %d \r\n", dfu_dist_ctx.block_size); + dfu_dist_ctx.fw_image_data_get(dfu_dist_ctx.block_size - DFU_BLOCK_SIGNATURE_SIZE, + dfu_dist_ctx.pblock_data); + dfu_block_signature(dfu_dist_ctx.pblock_data, dfu_dist_ctx.block_size - DFU_BLOCK_SIGNATURE_SIZE, + DFU_BLOCK_SIGNATURE_SIZE); + dfu_dist_ctx.block_left_size = dfu_dist_ctx.block_size; + printf("dfu_transfer_client_data: ========Sending one block========= \r\n"); + // for (uint32_t i = 0; i < dfu_dist_ctx.block_size; i++) { + // if (i % 12 == 0) { + // printf("\r\n"); + // } + // printf(" 0x%02x ", dfu_dist_ctx.pblock_data[i]); + // } + // printf("\r\n"); + /* block start */ + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTED) + { + blob_block_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.block_num, + DFU_CHUNK_SIZE); + dfu_dist_ctx.dist_retry_count = 0; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_BLOCK_STARTING; + return MODEL_SUCCESS; + } + pentry = pentry->pnext; + } + } + break; + case BLOB_TRANSFER_CLIENT_BLOCK_STATUS: + { + blob_transfer_client_block_status_t *pdata = (blob_transfer_client_block_status_t *)pargs; + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + if (dfu_dist_ctx.dist_phase == DFU_DIST_PHASE_BLOB_BLOCK_START) + { + if (dfu_dist_ctx.timer_state == DFU_TIMER_BLOB_BLOCK_START) { + plt_timer_stop(dfu_dist_ctx.timer, 0); + } else { + printf("dfu_update_client_data %d, timer state %d \r\n", __LINE__, dfu_dist_ctx.timer_state); + } + if (pdata->status == BLOB_TRANSFER_STATUS_SUCCESS) + { + while (NULL != pentry) + { + if (pentry->addr == pdata->src) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_BLOCK_STARTING) { + pentry->node_phase = DFU_NODE_PHASE_BLOB_BLOCK_STARTED; + printf("dfu_transfer_client_data: node 0x%04x blob block start success \r\n", pdata->src); + break; + } else { + printf("dfu_transfer_client_data: node 0x%04x is not DFU_NODE_PHASE_BLOB_BLOCK_STARTING, current state is %d \r\n", + pdata->src, pentry->node_phase); + return MODEL_SUCCESS; + } + } + pentry = pentry->pnext; + } + if (pentry == NULL) { + printf("dfu_transfer_client_data: node 0x%04x is not in the update list \r\n", pdata->src); + return MODEL_SUCCESS; + } + } + else + { + dfu_dist_ctx.pcur_update_node->node_phase = DFU_NODE_PHASE_FAILED; + printf("dfu_transfer_client_data: node 0x%04x block start failed, reason %d \r\n", pdata->src, + pdata->status); + dfu_dist_receiver_remove(pdata->src); + } + + /* find active node and send blob transfer start */ + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTED) + { + blob_block_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.block_num, + DFU_CHUNK_SIZE); + dfu_dist_ctx.dist_retry_count = 0; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_BLOCK_STARTING; + dfu_dist_ctx.pcur_update_node = pentry; + return MODEL_SUCCESS; + } + pentry = pentry->pnext; + } + + /* check chun transfer */ + bool need_chunk_transfer = false; + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_BLOCK_STARTED) + { + pentry->node_phase = DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERING; + need_chunk_transfer = true; + } + pentry = pentry->pnext; + } + if (!need_chunk_transfer) + { + /* no node need to update */ + printf("dfu_update_client_data: no node need chunk transfer, dfu procedure finish \r\n"); + dfu_dist_clear(); + return MODEL_SUCCESS; + } + + /* all node received blob block start message, start chunk transfer */ + printf("dfu_transfer_client_data: chunk transfer \r\n"); + dfu_dist_ctx.pcur_update_node = NULL; + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_CHUNK_TRANSFER; + /* set chunk data */ + dfu_dist_ctx.chunk_num = 0; + dfu_dist_ctx.pchunk_data = dfu_dist_ctx.pblock_data; + dfu_dist_ctx.chunk_size = (dfu_dist_ctx.block_left_size >= DFU_CHUNK_SIZE) ? DFU_CHUNK_SIZE : + dfu_dist_ctx.block_left_size; + dfu_dist_ctx.total_chunks = dfu_dist_ctx.block_size / dfu_dist_ctx.chunk_size; + if (dfu_dist_ctx.block_size % dfu_dist_ctx.chunk_size) + { + dfu_dist_ctx.total_chunks += 1; + } + /* chunk transfer start */ + dfu_dist_ctx.dist_retry_count = 0; + if (dfu_dist_ctx.chunk_num == (DFU_CHUNK_NUM - 1)) { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_NEW_BLOCK_PERIOD, 0); + } else { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_CHUNK_TRANSFER_RETRY_PERIOD, 0); + } + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_GET; + printf("dfu_transfer_client_data: blob_chunk_transfer, dst 0x%04x, chunk num %d, chunk size %d, retry count %d \r\n", + dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.chunk_num, dfu_dist_ctx.chunk_size, + dfu_dist_ctx.dist_retry_count); + blob_chunk_transfer(dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.dist_app_key_index, + dfu_dist_ctx.chunk_num, dfu_dist_ctx.pchunk_data, dfu_dist_ctx.chunk_size); + } + else + { + /* this case is for BLOB Block Get Message (BLOB Block Status ack to BLOB Block Get)*/ + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->addr == pdata->src) + { + if (pdata->status == BLOB_TRANSFER_STATUS_SUCCESS) + { + printf("dfu_transfer_client_data: get node 0x%04x block status success \r\n", pdata->src); + switch (pdata->missing_format) + { + case BLOB_CHUNK_MISSING_FORMAT_ALL: + break; + case BLOB_CHUNK_MISSING_FORMAT_NONE: + pentry->node_phase = DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERED; + break; + case BLOB_CHUNK_MISSING_FORMAT_SOME: + for (uint16_t i = 0; i < pdata->missing_chunks_len; ++i) + { + if (pdata->pmissing_chunks[i] == dfu_dist_ctx.chunk_num) + { + printf("missing chunk num %d \r\n", dfu_dist_ctx.chunk_num); + return MODEL_SUCCESS; + } + } + printf("dfu_transfer_client_data: node 0x%04x receive block %d, chunk %d \r\n", pdata->src, + dfu_dist_ctx.block_num, dfu_dist_ctx.chunk_num); + pentry->node_phase = DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERED; + break; + default: + break; + } + } + else + { + pentry->node_phase = DFU_NODE_PHASE_FAILED; + printf("dfu_transfer_client_data: node 0x%04x get block status failed, reason %d \r\n", pdata->src, + pdata->status); + dfu_dist_receiver_remove(pdata->src); + } + return MODEL_SUCCESS; + } + pentry = pentry->pnext; + } + } + } + break; + case BLOB_TRANSFER_CLIENT_PARTIAL_BLOCK_REPORT: + { + /* this is for trunk transfer mode : PULL MODE (indicate server is ready to receive a chunk)*/ + //blob_transfer_client_partial_block_report_t *pdata = (blob_transfer_client_partial_block_report_t *)pargs; + } + break; + case BLOB_TRANSFER_CLIENT_INFO_STATUS: + { + /* this is the ack message to BLOB information Get message */ + //blob_transfer_client_info_status_t *pdata = (blob_transfer_client_info_status_t *)pargs; + } + break; + default: + break; + } + return MODEL_SUCCESS; +} + +int32_t dfu_update_client_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + switch (type) + { + case FW_UPDATE_CLIENT_INFO_STATUS: + { + /* get firmware update information status in response to Firmware Update Information Get Message */ + fw_update_client_info_status_t *pdata = (fw_update_client_info_status_t *)pargs; + fw_dist_receiver_t recv; + + if (dfu_check_fw_info(pdata->pfw_info) == DFU_RESULT_OK) { + recv.addr = pdata->src; + recv.update_fw_image_idx = pdata->first_index; + printf("%s:get firmware information for node 0x%04x and first index is 0x%02x! \r\n", __func__, recv.addr, recv.update_fw_image_idx); + dfu_dist_receiver_add(&recv); + } + } + break; + case FW_UPDATE_CLIENT_FW_METADATA_STATUS: + { + fw_update_client_fw_metadata_status_t *pdata = (fw_update_client_fw_metadata_status_t *)pargs; + if (pdata->status == FW_UPDATE_STATUS_SUCCESS) { + printf("%s:Metadata check success for node 0x%04x !\r\n", __func__, pdata->src); + } else { + printf("%s:Metadata check fail for node 0x%04x !\r\n", __func__, pdata->src); + dfu_dist_receiver_remove(pdata->src); + } + } + break; + case FW_UPDATE_CLIENT_STATUS: + { + fw_update_client_status_t *pdata = (fw_update_client_status_t *)pargs; + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + switch (dfu_dist_ctx.dist_phase) + { + case DFU_DIST_PHASE_UPDATE_START: + { + if (dfu_dist_ctx.timer_state == DFU_TIMER_FW_UPDATE_CLIENT_STATUS) { + plt_timer_stop(dfu_dist_ctx.timer, 0); + } else { + printf("dfu_update_client_data %d, timer state %d \r\n", __LINE__, dfu_dist_ctx.timer_state); + } + if (pdata->status == FW_UPDATE_STATUS_SUCCESS) + { + while (NULL != pentry) + { + if (pentry->addr == pdata->src) + { + if (pentry->node_phase == DFU_NODE_PHASE_IDLE \ + || pentry->node_phase == DFU_NODE_PHASE_UPDATE_STARTING) { + pentry->node_phase = DFU_NODE_PHASE_UPDATE_STARTED; + printf("dfu_update_client_data: node 0x%04x update start success \r\n", pdata->src); + break; + } else { + printf("dfu_update_client_data: node 0x%04x is not idle, current state is \r\n", + pdata->src, pentry->node_phase); + return MODEL_SUCCESS; + } + } + pentry = pentry->pnext; + } + if (pentry == NULL) { + printf("dfu_transfer_client_data: node 0x%04x is not in the update list \r\n", pdata->src); + return MODEL_SUCCESS; + } + } + else + { + dfu_dist_ctx.pcur_update_node->node_phase = DFU_NODE_PHASE_FAILED; + printf("dfu_update_client_data: node 0x%04x update start failed, reason %d \r\n", pdata->src, + pdata->status); + dfu_dist_receiver_remove(pdata->src); + } + + /* find idle node and send update start */ + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_IDLE \ + || pentry->node_phase == DFU_NODE_PHASE_UPDATE_STARTING) + { + fw_update_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.dist_ttl, + dfu_dist_ctx.dist_timeout_base, dfu_dist_ctx.blob_id, + pentry->update_fw_image_idx, dfu_dist_ctx.fw_metadata, dfu_dist_ctx.metadata_len); + dfu_dist_ctx.dist_retry_count = 0; + pentry->node_phase = DFU_NODE_PHASE_UPDATE_STARTING; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_UPDATE_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_FW_UPDATE_CLIENT_STATUS; + dfu_dist_ctx.pcur_update_node = pentry; + return MODEL_SUCCESS; + } + pentry = pentry->pnext; + } + + /* all node received update start message, begin blob transfer start */ + printf("dfu_update_client_data: start firmware blob transfer start \r\n"); + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_TRANSFER_START; + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_UPDATE_STARTED) + { + blob_transfer_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, BLOB_TRANSFER_MODE_PUSH, + dfu_dist_ctx.blob_id, dfu_dist_ctx.fw_image_size, DFU_BLOCK_SIZE_LOG, DFU_CLIENT_MTU); + dfu_dist_ctx.dist_retry_count = 0; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_TRANSFER_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_TRANSFER_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_TRANSFER_STARTING; + dfu_dist_ctx.pcur_update_node = pentry; + return MODEL_SUCCESS; + } + pentry = pentry->pnext; + } + + /* no node need to update */ + printf("dfu_update_client_data: no node need to firmware blob transfer start, dfu procedure finish \r\n"); + dfu_dist_clear(); + } + break; + default: + break; + } + } + break; + default: + break; + } + + return MODEL_SUCCESS; +} + +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER +extern void *bt_mesh_provisioner_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_io_queue_handle; //!< IO queue handle +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +extern void *bt_mesh_provisioner_ota_client_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_ota_client_io_queue_handle; //!< IO queue handle +#else +extern void *bt_mesh_provisioner_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_multiple_profile_io_queue_handle; //!< IO queue handle +#endif +#endif + +static void dfu_timeout(void *ptimer) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = DFU_DIST_APP_TIMEOUT_MSG; + msg.u.buf = ptimer; +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER + if (os_msg_send(bt_mesh_provisioner_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_evt_queue_handle, &event, 0) == false) + { + } +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT + if (os_msg_send(bt_mesh_provisioner_ota_client_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) + { + } +#else + if (os_msg_send(bt_mesh_provisioner_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +#endif +#endif +} + +void dfu_dist_handle_timeout(void) +{ + switch (dfu_dist_ctx.dist_phase) + { + case DFU_DIST_PHASE_UPDATE_START: + { + if (dfu_dist_ctx.pcur_update_node->node_phase == DFU_NODE_PHASE_UPDATE_STARTING) + { + if (dfu_dist_ctx.dist_retry_count >= DFU_DIST_RETRY_TIMES) + { + /* update start failed, skip this node or generate dfu failed? */ + printf("dfu_timeout_handle: node 0x%04x update start failed \r\n", dfu_dist_ctx.pcur_update_node->addr); + dfu_dist_ctx.pcur_update_node->node_phase = DFU_NODE_PHASE_FAILED; + dfu_dist_receiver_remove(dfu_dist_ctx.pcur_update_node->addr); + } + else + { + fw_update_start(dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.dist_app_key_index, + dfu_dist_ctx.dist_ttl, dfu_dist_ctx.dist_timeout_base, dfu_dist_ctx.blob_id, + dfu_dist_ctx.pcur_update_node->update_fw_image_idx, dfu_dist_ctx.fw_metadata, + dfu_dist_ctx.metadata_len); + dfu_dist_ctx.dist_retry_count ++; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_UPDATE_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_FW_UPDATE_CLIENT_STATUS; + printf("dfu_dist_timeout_handle: fw_update_start, dst 0x%04x, retry count %d \r\n", + dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.dist_retry_count); + return ; + } + } + + dfu_dist_ctx.dist_retry_count = 0; + /* find idle node and send update start */ + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_IDLE) + { + fw_update_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.dist_ttl, + dfu_dist_ctx.dist_timeout_base, dfu_dist_ctx.blob_id, pentry->update_fw_image_idx, + dfu_dist_ctx.fw_metadata, dfu_dist_ctx.metadata_len); + pentry->node_phase = DFU_NODE_PHASE_UPDATE_STARTING; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_UPDATE_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_FW_UPDATE_CLIENT_STATUS; + dfu_dist_ctx.pcur_update_node = pentry; + printf("dfu_dist_timeout_handle: fw_update_start, dst 0x%04x, retry count %d \r\n", + dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.dist_retry_count); + return ; + } + + pentry = pentry->pnext; + } + + /* all node received update start message, begin blob transfer start */ + printf("dfu_timeout_handle: start firmware blob transfer start \r\n"); + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_TRANSFER_START; + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_UPDATE_STARTED) + { + blob_transfer_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, BLOB_TRANSFER_MODE_PUSH, + dfu_dist_ctx.blob_id, dfu_dist_ctx.fw_image_size, DFU_BLOCK_SIZE_LOG, DFU_CLIENT_MTU); + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_TRANSFER_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_TRANSFER_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_TRANSFER_STARTING; + dfu_dist_ctx.pcur_update_node = pentry; + printf("dfu_dist_timeout_handle: blob_transfer_start, dst 0x%04x, retry count %d \r\n", pentry->addr, + dfu_dist_ctx.dist_retry_count); + return ; + } + pentry = pentry->pnext; + } + + /* no node need to update */ + printf("dfu_update_client_data: no node need to firmware blob transfer start, dfu procedure finish \r\n"); + dfu_dist_clear(); + } + case DFU_DIST_PHASE_BLOB_TRANSFER_START: + { + if (dfu_dist_ctx.pcur_update_node->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTING) + { + if (dfu_dist_ctx.dist_retry_count >= DFU_DIST_RETRY_TIMES) + { + /* transfer start failed, skip this node or generate dfu failed? */ + printf("dfu_timeout_handle: node 0x%04x blob transfer start failed \r\n", + dfu_dist_ctx.pcur_update_node->addr); + dfu_dist_ctx.pcur_update_node->node_phase = DFU_NODE_PHASE_FAILED; + dfu_dist_receiver_remove(dfu_dist_ctx.pcur_update_node->addr); + } + else + { + blob_transfer_start(dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.dist_app_key_index, + BLOB_TRANSFER_MODE_PUSH, dfu_dist_ctx.blob_id, dfu_dist_ctx.fw_image_size, DFU_BLOCK_SIZE_LOG, + DFU_CLIENT_MTU); + dfu_dist_ctx.dist_retry_count ++; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_TRANSFER_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_TRANSFER_START; + printf("dfu_dist_timeout_handle: blob_transfer_start, dst 0x%04x, retry count %d \r\n", + dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.dist_retry_count); + return ; + } + } + + dfu_dist_ctx.dist_retry_count = 0; + /* find active node and send blob transfer start */ + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_UPDATE_STARTED) + { + blob_transfer_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, BLOB_TRANSFER_MODE_PUSH, + dfu_dist_ctx.blob_id, dfu_dist_ctx.fw_image_size, DFU_BLOCK_SIZE_LOG, DFU_CLIENT_MTU); + pentry->node_phase = DFU_NODE_PHASE_BLOB_TRANSFER_STARTING; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_TRANSFER_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_TRANSFER_START; + dfu_dist_ctx.pcur_update_node = pentry; + printf("dfu_dist_timeout_handle: blob_transfer_start, dst 0x%04x, retry count %d \r\n", pentry->addr, + dfu_dist_ctx.dist_retry_count); + return ; + } + + pentry = pentry->pnext; + } + + /* all node received blob transfer start message, begin blob block start */ + printf("blob_transfer_client_data: block start \r\n"); + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_BLOCK_START; + /* get block data */ + dfu_dist_ctx.block_size = (dfu_dist_ctx.fw_image_left_size >= DFU_BLOCK_SIZE) ? DFU_BLOCK_SIZE : + dfu_dist_ctx.fw_image_left_size; + dfu_dist_ctx.fw_image_data_get(dfu_dist_ctx.block_size - DFU_BLOCK_SIGNATURE_SIZE, dfu_dist_ctx.pblock_data); + dfu_block_signature(dfu_dist_ctx.pblock_data, dfu_dist_ctx.block_size - DFU_BLOCK_SIGNATURE_SIZE, + DFU_BLOCK_SIGNATURE_SIZE); + dfu_dist_ctx.block_left_size = dfu_dist_ctx.block_size; + /* block start */ + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTED) + { + blob_block_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.block_num, + DFU_CHUNK_SIZE); + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_BLOCK_STARTING; + dfu_dist_ctx.pcur_update_node = pentry; + printf("dfu_dist_timeout_handle: blob_block_start, dst 0x%04x, block num %d, retry count %d \r\n", + pentry->addr, dfu_dist_ctx.block_num, dfu_dist_ctx.dist_retry_count); + return ; + } + pentry = pentry->pnext; + } + + /* no node need to update */ + printf("dfu_update_client_data: no node need to blob block start, dfu procedure finish \r\n"); + dfu_dist_clear(); + } + break; + case DFU_DIST_PHASE_BLOB_BLOCK_START: + { + if (dfu_dist_ctx.pcur_update_node->node_phase == DFU_NODE_PHASE_BLOB_BLOCK_STARTING) + { + if (dfu_dist_ctx.dist_retry_count >= DFU_DIST_RETRY_TIMES) + { + /* transfer start failed, skip this node or generate dfu failed? */ + printf("dfu_timeout_handle: node 0x%04x blob block start failed \r\n", + dfu_dist_ctx.pcur_update_node->addr); + dfu_dist_ctx.pcur_update_node->node_phase = DFU_NODE_PHASE_FAILED; + dfu_dist_receiver_remove(dfu_dist_ctx.pcur_update_node->addr); + } + else + { + blob_block_start(dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.dist_app_key_index, + dfu_dist_ctx.block_num, DFU_CHUNK_SIZE); + dfu_dist_ctx.dist_retry_count ++; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_START; + printf("dfu_dist_timeout_handle: blob_block_start, dst 0x%04x, block num %d, retry count %d \r\n", + dfu_dist_ctx.pcur_update_node->addr, dfu_dist_ctx.block_num, dfu_dist_ctx.dist_retry_count); + return ; + } + } + + dfu_dist_ctx.dist_retry_count = 0; + /* find active node and send blob block start */ + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTED) + { + blob_block_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.block_num, + DFU_CHUNK_SIZE); + pentry->node_phase = DFU_NODE_PHASE_BLOB_BLOCK_STARTING; + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_START; + dfu_dist_ctx.pcur_update_node = pentry; + printf("dfu_dist_timeout_handle: blob_block_start, dst 0x%04x, block num %d, retry count %d \r\n", + pentry->addr, dfu_dist_ctx.block_num, dfu_dist_ctx.dist_retry_count); + return ; + } + + pentry = pentry->pnext; + } + + + /* check chun transfer */ + bool need_chunk_transfer = false; + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_BLOCK_STARTED) + { + pentry->node_phase = DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERING; + need_chunk_transfer = true; + } + pentry = pentry->pnext; + } + if (!need_chunk_transfer) + { + /* no node need to update */ + printf("dfu_update_client_data: no node need chunk transfer, dfu procedure finish \r\n"); + dfu_dist_clear(); + return ; + } + + /* all node received blob block start message, start chunk transfer */ + printf("dfu_dist_timeout_handle: chunk transfer \r\n"); + dfu_dist_ctx.pcur_update_node = NULL; + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_CHUNK_TRANSFER; + /* set chunk data */ + dfu_dist_ctx.chunk_num = 0; + dfu_dist_ctx.pchunk_data = dfu_dist_ctx.pblock_data; + dfu_dist_ctx.chunk_size = (dfu_dist_ctx.block_left_size >= DFU_CHUNK_SIZE) ? DFU_CHUNK_SIZE : + dfu_dist_ctx.block_left_size; + dfu_dist_ctx.total_chunks = dfu_dist_ctx.block_size / dfu_dist_ctx.chunk_size; + if (dfu_dist_ctx.block_size % dfu_dist_ctx.chunk_size) + { + dfu_dist_ctx.total_chunks += 1; + } + /* chunk transfer start */ + if (dfu_dist_ctx.chunk_num == (DFU_CHUNK_NUM - 1)) { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_NEW_BLOCK_PERIOD, 0); + } else { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_CHUNK_TRANSFER_RETRY_PERIOD, 0); + } + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_GET; + blob_chunk_transfer(dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.dist_app_key_index, + dfu_dist_ctx.chunk_num, dfu_dist_ctx.pchunk_data, dfu_dist_ctx.chunk_size); + printf("dfu_dist_timeout_handle: blob_chunk_transfer, dst 0x%04x, chunk num %d, chunk size %d, retry count %d \r\n", + dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.chunk_num, dfu_dist_ctx.chunk_size, + dfu_dist_ctx.dist_retry_count); + } + break; + case DFU_DIST_PHASE_BLOB_CHUNK_TRANSFER: + { + if (dfu_dist_ctx.timer_state == DFU_TIMER_BLOB_BLOCK_GET) + { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_GET_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_CHUNK_TRANSFER; + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERING) + { + printf("dfu_dist_timeout_handle: blob_block_get, dst 0x%04x \r\n", pentry->addr); + blob_block_get(pentry->addr, dfu_dist_ctx.dist_app_key_index); + } + pentry = pentry->pnext; + } + } + else if (dfu_dist_ctx.timer_state == DFU_TIMER_BLOB_CHUNK_TRANSFER) + { + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERING) + { + if (dfu_dist_ctx.dist_retry_count >= DFU_DIST_RETRY_TIMES) + { + printf("dfu_timeout_handle: node 0x%04x receive chunk %d failed \r\n", pentry->addr, dfu_dist_ctx.chunk_num); + pentry->node_phase = DFU_NODE_PHASE_FAILED; + dfu_dist_receiver_remove(dfu_dist_ctx.pcur_update_node->addr); + } + else + { + dfu_dist_ctx.dist_retry_count ++; + if (dfu_dist_ctx.chunk_num == (DFU_CHUNK_NUM - 1)) { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_NEW_BLOCK_PERIOD, 0); + } else { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_CHUNK_TRANSFER_RETRY_PERIOD, 0); + } + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_GET; + printf("dfu_dist_timeout_handle: blob_chunk_transfer, dst 0x%04x, chunk num %d, chunk size %d, retry count %d \r\n", + dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.chunk_num, dfu_dist_ctx.chunk_size, + dfu_dist_ctx.dist_retry_count); + blob_chunk_transfer(dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.dist_app_key_index, + dfu_dist_ctx.chunk_num, dfu_dist_ctx.pchunk_data, dfu_dist_ctx.chunk_size); + return ; + } + } + pentry = pentry->pnext; + } + + /* all node receive this chunk, send next chunk or block start */ + dfu_dist_ctx.dist_retry_count = 0; + dfu_dist_ctx.block_left_size -= dfu_dist_ctx.chunk_size; + if (dfu_dist_ctx.block_left_size == 0) + { + printf("dfu_timeout_handle: block %d send complete \r\n", dfu_dist_ctx.block_num); + dfu_dist_ctx.block_num ++; + dfu_dist_ctx.fw_image_left_size = dfu_dist_ctx.fw_image_left_size - dfu_dist_ctx.block_size; + if (dfu_dist_ctx.fw_image_left_size == 0) + { + /* image send complete */ + printf("dfu_timeout_handle: firmware send complete \r\n"); + /* start apply */ + printf("dfu_timeout_handle: start firmware apply \r\n"); + fw_update_apply(dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.dist_app_key_index); + /* clear state */ + dfu_dist_clear(); + } + else + { + /* block send complete */ + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_BLOCK_START; + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase != DFU_NODE_PHASE_FAILED) + { + pentry->node_phase = DFU_NODE_PHASE_BLOB_TRANSFER_STARTED; + } + pentry = pentry->pnext; + } + + /* all node received blob transfer start message, begin blob block start */ + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_BLOB_BLOCK_START; + /* get block data */ + dfu_dist_ctx.block_size = (dfu_dist_ctx.fw_image_left_size >= DFU_BLOCK_SIZE) ? DFU_BLOCK_SIZE : + dfu_dist_ctx.fw_image_left_size; + dfu_dist_ctx.fw_image_data_get(dfu_dist_ctx.block_size - DFU_BLOCK_SIGNATURE_SIZE, dfu_dist_ctx.pblock_data); + dfu_block_signature(dfu_dist_ctx.pblock_data, dfu_dist_ctx.block_size - DFU_BLOCK_SIGNATURE_SIZE, + DFU_BLOCK_SIGNATURE_SIZE); + dfu_dist_ctx.block_left_size = dfu_dist_ctx.block_size; + // printf("dfu_transfer_client_data: ========Sending one block========= \r\n"); + // for (uint32_t i = 0; i < dfu_dist_ctx.block_size; i++) { + // if (i % 12 == 0) { + // printf("\r\n"); + // } + // printf(" 0x%02x ", dfu_dist_ctx.pblock_data[i]); + // } + // printf("\r\n"); + /* block start */ + printf("dfu_timeout_handle: block start %d/%d, size %d \r\n", dfu_dist_ctx.block_num, + dfu_dist_ctx.total_blocks, dfu_dist_ctx.block_size); + pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_TRANSFER_STARTED) + { + blob_block_start(pentry->addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.block_num, + DFU_CHUNK_SIZE); + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_BLOCK_START_RETRY_PERIOD, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_START; + pentry->node_phase = DFU_NODE_PHASE_BLOB_BLOCK_STARTING; + dfu_dist_ctx.pcur_update_node = pentry; + return ; + } + pentry = pentry->pnext; + } + + /* no node need to update */ + printf("dfu_update_client_data: no node need to blob block start, dfu procedure finish \r\n"); + dfu_dist_clear(); + } + } + else + { + printf("dfu_timeout_handle: chunk %d send complete \r\n", dfu_dist_ctx.chunk_num); + /* set chunk data */ + dfu_dist_ctx.chunk_num ++; + dfu_dist_ctx.pchunk_data = dfu_dist_ctx.pchunk_data + dfu_dist_ctx.chunk_size; + dfu_dist_ctx.chunk_size = (dfu_dist_ctx.block_left_size >= DFU_CHUNK_SIZE) ? DFU_CHUNK_SIZE : + dfu_dist_ctx.block_left_size; + dfu_dist_ctx.dist_retry_count = 0; + /* start chunk transfer */ + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->node_phase == DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERED) + { + pentry->node_phase = DFU_NODE_PHASE_BLOB_CHUNK_TRANSFERING; + } + pentry = pentry->pnext; + } + if (dfu_dist_ctx.chunk_num == (DFU_CHUNK_NUM - 1)) { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_NEW_BLOCK_PERIOD, 0); + } else { + plt_timer_change_period(dfu_dist_ctx.timer, DFU_DIST_BLOB_CHUNK_TRANSFER_RETRY_PERIOD, 0); + } + dfu_dist_ctx.timer_state = DFU_TIMER_BLOB_BLOCK_GET; + printf("dfu_timeout_handle: chunk transfer %d:%d/%d, size %d \r\n", dfu_dist_ctx.block_num, + dfu_dist_ctx.chunk_num, dfu_dist_ctx.total_chunks, dfu_dist_ctx.chunk_size); + blob_chunk_transfer(dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.dist_app_key_index, + dfu_dist_ctx.chunk_num, dfu_dist_ctx.pchunk_data, dfu_dist_ctx.chunk_size); + } + } else { + printf("dfu_dist_handle_timeout %d, wrong timer state %d \r\n", __LINE__, dfu_dist_ctx.timer_state); + } + } + break; + default: + break; + } +} + +bool dfu_dist_receiver_add(fw_dist_receiver_t *precv) +{ + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + if (pentry->addr == precv->addr) + { + printw("dfu_dist_receiver_add: receiver entry(0x%04x) already exists \r\n", precv->addr, + precv->update_fw_image_idx); + return true; + } + pentry = pentry->pnext; + } + + pentry = plt_zalloc(sizeof(dfu_update_node_e_t), RAM_TYPE_DATA_ON); + if (NULL == pentry) + { + printf("dfu_dist_receiver_add: add receiver failed, out of memory \r\n"); + return false; + } + + pentry->addr = precv->addr; + pentry->update_fw_image_idx = precv->update_fw_image_idx; + plt_list_push(&dfu_dist_ctx.dfu_update_node_list, pentry); + printf("dfu_dist_receiver_add: index %d, addr 0x%04x, update image index %d \r\n", + dfu_dist_ctx.dfu_update_node_list.count - 1, precv->addr, precv->update_fw_image_idx); + + return true; +} + +void dfu_dist_receiver_remove(uint16_t addr) +{ + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + dfu_update_node_e_t *pentry_prev = NULL; + while (NULL != pentry) + { + if (pentry->addr == addr) + { + plt_list_delete(&dfu_dist_ctx.dfu_update_node_list, pentry_prev, pentry); + plt_free(pentry, RAM_TYPE_DATA_ON); + printf("dfu_dist_receiver_remove: delete receiver, address 0x%04x \r\n", addr); + return ; + } + pentry_prev = pentry; + pentry = pentry->pnext; + } +} + +void dfu_dist_receiver_remove_by_index(uint16_t index) +{ + if (index >= dfu_dist_ctx.dfu_update_node_list.count) + { + printf("dfu_dist_receiver_remove_by_index: invalid index %d-%d \r\n", index, + dfu_dist_ctx.dfu_update_node_list.count); + return ; + } + + uint16_t cur_idx = 0; + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + dfu_update_node_e_t *pentry_prev = NULL; + while (NULL != pentry) + { + if (cur_idx == index) + { + printf("dfu_dist_receiver_remove_by_index: delete receiver, index %d, addr 0x%04x \r\n", index, + pentry->addr); + plt_list_delete(&dfu_dist_ctx.dfu_update_node_list, pentry_prev, pentry); + plt_free(pentry, RAM_TYPE_DATA_ON); + return ; + } + pentry_prev = pentry; + pentry = pentry->pnext; + cur_idx ++; + } +} + +void dfu_dist_receiver_remove_all(void) +{ + dfu_update_node_e_t *pentry; + uint32_t count = dfu_dist_ctx.dfu_update_node_list.count; + for (uint8_t i = 0; i < count; ++i) + { + pentry = plt_list_pop(&dfu_dist_ctx.dfu_update_node_list); + if (NULL != pentry) + { + plt_free(pentry, RAM_TYPE_DATA_ON); + } + } + printf("dfu_dist_receiver_remove_all: remove all receivers \r\n"); +} + +extern mesh_node_t mesh_node; + +void dfu_dist_clear(void) +{ + printf("dfu_dist_clear \r\n"); + if (NULL != dfu_dist_ctx.timer) + { + plt_timer_delete(dfu_dist_ctx.timer, 0); + } + + if (NULL != dfu_dist_ctx.pblock_data) + { + plt_free(dfu_dist_ctx.pblock_data, RAM_TYPE_DATA_ON); + } + + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + while (NULL != pentry) + { + pentry->node_phase = DFU_NODE_PHASE_IDLE; + pentry = pentry->pnext; + } + + memset(&dfu_dist_ctx, 0, sizeof(dfu_dist_ctx)); + + mesh_node.trans_tx_queue_size = 3; +} + +bool dfu_dist_start(uint16_t dst, uint16_t app_key_index, uint16_t update_timeout_base, + uint8_t *pfw_metadata, uint8_t metadata_len, + uint32_t fw_image_size, fw_image_data_get_t fw_image_data_get) +{ + // fw_image_start_addr delete + if (DFU_DIST_PHASE_IDLE != dfu_dist_ctx.dist_phase) + { + printf("dfu_dist_start: busy, phase %d \r\n", dfu_dist_ctx.dist_phase); + return false; + } + + if (0 == dfu_dist_ctx.dfu_update_node_list.count) + { + printf("dfu_dist_start: there is no node need to update \r\n"); + return false; + } + + if (NULL == fw_image_data_get) + { + printf("dfu_dist_start: firmware image data callback shall exist! \r\n"); + return false; + } + + if (fw_image_size == 0) { + printf("dfu_dist_start: firmware size is 0 ! \r\n"); + return false; + } + + /* start timeout timer */ + if (NULL == dfu_dist_ctx.timer) + { + dfu_dist_ctx.timer = plt_timer_create("dfu", DFU_DIST_UPDATE_RETRY_PERIOD, false, 0, dfu_timeout); + if (NULL == dfu_dist_ctx.timer) + { + printf("dfu_dist_start: create timer failed \r\n"); + return false; + } + dfu_dist_ctx.timer_state = DFU_TIMER_IDLE; + } + + if (NULL == dfu_dist_ctx.pblock_data) + { + dfu_dist_ctx.pblock_data = plt_malloc(DFU_BLOCK_SIZE, RAM_TYPE_DATA_ON); + if (NULL == dfu_dist_ctx.pblock_data) + { + printf("dfu_dist_start: create block data buffer failed \r\n"); + return false; + } + } + + dfu_dist_ctx.dist_phase = DFU_DIST_PHASE_UPDATE_START; + dfu_dist_ctx.dist_multicast_addr = dst; + dfu_dist_ctx.dist_app_key_index = app_key_index; + dfu_dist_ctx.dist_timeout_base = update_timeout_base; + dfu_dist_ctx.dist_ttl = mesh_node.ttl; + /* if use block signature, total transfer blob = image file + block num * DFU_BLOCK_SIGNATURE_SIZE */ + dfu_dist_ctx.total_blocks = fw_image_size / (DFU_BLOCK_SIZE - DFU_BLOCK_SIGNATURE_SIZE); + if (fw_image_size % (DFU_BLOCK_SIZE - DFU_BLOCK_SIGNATURE_SIZE)) + { + dfu_dist_ctx.total_blocks += 1; + } + /* dfu_dist_ctx.fw_image_size should be firmware image + total block signature size */ + dfu_dist_ctx.fw_image_size = fw_image_size + dfu_dist_ctx.total_blocks * DFU_BLOCK_SIGNATURE_SIZE; + dfu_dist_ctx.fw_image_left_size = dfu_dist_ctx.fw_image_size; + dfu_dist_ctx.fw_image_data_get = fw_image_data_get; + dfu_dist_ctx.dist_retry_count = 0; + memcpy(dfu_dist_ctx.fw_metadata, pfw_metadata, metadata_len); + dfu_dist_ctx.metadata_len = metadata_len; + uint32_t *pid = (uint32_t *)dfu_dist_ctx.blob_id; + *pid ++ = rand(); + *pid ++ = rand(); + + dfu_update_node_e_t *pentry = (dfu_update_node_e_t *)dfu_dist_ctx.dfu_update_node_list.pfirst; + pentry->node_phase = DFU_NODE_PHASE_UPDATE_STARTING; + mesh_node.trans_tx_queue_size = 1; + /*_fw_update_start */ + { + PUSER_ITEM puserItem = NULL; + uint8_t ret; + puserItem = bt_mesh_alloc_hdl(USER_API_ASYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return false; + } + puserItem->pparseValue->dw_parameter[0] = dst; + puserItem->pparseValue->dw_parameter[1] = app_key_index; + puserItem->pparseValue->dw_parameter[2] = mesh_node.ttl; + puserItem->pparseValue->dw_parameter[3] = update_timeout_base; + puserItem->pparseValue->pparameter[4] = dfu_dist_ctx.blob_id; + puserItem->pparseValue->dw_parameter[5] = pentry->update_fw_image_idx; + puserItem->pparseValue->pparameter[6] = dfu_dist_ctx.fw_metadata; + puserItem->pparseValue->dw_parameter[7] = metadata_len; + puserItem->pparseValue->dw_parameter[8] = 0; //indicate blob_id and metadata is not string type + puserItem->pparseValue->para_count = 9; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_fw_update_start), puserItem->pparseValue, NULL, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return false; + } + } + plt_timer_start(dfu_dist_ctx.timer, 0); + dfu_dist_ctx.timer_state = DFU_TIMER_FW_UPDATE_CLIENT_STATUS; + dfu_dist_ctx.pcur_update_node = pentry; + + printf("dfu_dist_start: dst 0x%04x, app_key_index %d, update_timeout_base %d, fw_image_size %d, total blocks %d \r\n", + dfu_dist_ctx.dist_multicast_addr, dfu_dist_ctx.dist_app_key_index, dfu_dist_ctx.dist_timeout_base, + dfu_dist_ctx.fw_image_size, dfu_dist_ctx.total_blocks); + printf("dfu_dist_start: firmware metadata = 0x%02x, 0x%02x \r\n", dfu_dist_ctx.fw_metadata[0], dfu_dist_ctx.fw_metadata[1]); + printf("dfu_dist_start: blob id = "); + for (uint8_t i = 0; i < 8; i++) { + printf(" 0x%02x ", dfu_dist_ctx.blob_id[i]); + } + + return true; +} + +uint8_t dfu_dist_model_enabled = 0; + +void dfu_dist_models_init(void) +{ + dfu_dist_model_enabled = 1; + fw_update_client_reg(0, dfu_update_client_data); + blob_transfer_client_reg(0, dfu_transfer_client_data); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.h new file mode 100644 index 00000000..1447bf00 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.h @@ -0,0 +1,59 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file dfu_distributor_app.h +* @brief Smart mesh dfu application +* @details +* @author bill +* @date 2018-6-6 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _DFU_DIST_MODELS_H +#define _DFU_DIST_MODELS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mesh_api.h" +#include "firmware_distribution.h" +#include "firmware_update.h" +#include "blob_transfer.h" +#include "dfudep_service.h" + +#if MESH_DFU +/** + * @addtogroup DFU_DISTRIBUTOR_APP + * @{ + */ + +/** + * @defgroup Dfu_Distributor_Exported_Functions Dfu Distributor Exported Functions + * @brief + * @{ + */ +#define DFU_DIST_APP_TIMEOUT_MSG 121 + +typedef uint32_t (*fw_image_data_get_t)(uint32_t len, uint8_t *pout); +void dfu_dist_models_init(void); +bool dfu_dist_receiver_add(fw_dist_receiver_t *precv); +void dfu_dist_receiver_remove(uint16_t addr); +void dfu_dist_receiver_remove_by_index(uint16_t index); +void dfu_dist_receiver_remove_all(void); +bool dfu_dist_start(uint16_t dst, uint16_t app_key_index, uint16_t update_timeout_base, + uint8_t *pfw_metadata, uint8_t metadata_len, + uint32_t fw_image_size, fw_image_data_get_t fw_image_data_get); +void dfu_dist_clear(void); +void dfu_dist_handle_timeout(void); +/** @} */ +/** @} */ +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _DFU_DIST_MODELS_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.c new file mode 100644 index 00000000..a277ebc1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.c @@ -0,0 +1,304 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file dfu_updater_app.c +* @brief Smart mesh dfu application +* @details +* @author bill +* @date 2018-6-5 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#include "dfu_updater_app.h" +#include "ftl.h" +#include "generic_types.h" +#include "dfudep_service.h" +#include +#include +#include + +uint8_t metadata_server[] = { + 0x1F, + 0xEE +}; + +#if MESH_DFU + +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON /* used for device power off but client is alive */ +typedef struct +{ + uint8_t blob_id[8]; + uint32_t blob_size; + uint32_t block_size; + uint32_t current_block_num; /**< shall be 4 bytes alligned */ + uint16_t transfer_timeout_base; + uint16_t transfer_ttl; + uint16_t transfer_mtu_size; + uint16_t updater_addr; + uint16_t updater_app_key_index; + uint16_t image_id; + uint8_t transfer_mode; + uint8_t padding[3]; +} dfu_updater_nvm_info_t; +static dfu_updater_nvm_info_t dfu_updater_nvm_info; + +void dfu_updater_nvm_load(void) +{ + uint32_t ret = ftl_load(&dfu_updater_nvm_info, DFU_UPDATER_NVM_OFFSET, + sizeof(dfu_updater_nvm_info)); + if (ret == 0 && dfu_updater_nvm_info.blob_size != 0) + { + printf("dfu_updater: power on go on! \r\n"); + } + else + { + dfu_updater_nvm_info.blob_size = 0; + } +} + +void dfu_updater_nvm_clear(void) +{ + uint32_t ret; + ret = ftl_load(&dfu_updater_nvm_info.blob_size, + DFU_UPDATER_NVM_OFFSET + MEMBER_OFFSET(dfu_updater_nvm_info_t, blob_size), 4); + if (ret == 0 && dfu_updater_nvm_info.blob_size != 0) + { + dfu_updater_nvm_info.blob_size = 0; + ftl_save(&dfu_updater_nvm_info.blob_size, + DFU_UPDATER_NVM_OFFSET + MEMBER_OFFSET(dfu_updater_nvm_info_t, blob_size), 4); + } +} +#endif + +struct +{ + uint16_t image_id; +} dfu_updater_app_ctx; + + +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON +void dfu_updater_load(void) +{ + if (UNPROV_DEVICE == mesh_node_state_restore()) + { + dfu_updater_nvm_clear(); + } + else + { + dfu_updater_nvm_load(); + if (dfu_updater_nvm_info.blob_size != 0) + { + dfu_updater_app_ctx.image_id = dfu_updater_nvm_info.image_id; + if (fw_update_server_load(NULL, 0, 0, dfu_updater_nvm_info.transfer_ttl, + dfu_updater_nvm_info.transfer_timeout_base, dfu_updater_nvm_info.blob_id)) + { + blob_transfer_server_load(dfu_updater_nvm_info.blob_size, dfu_updater_nvm_info.block_size, + dfu_updater_nvm_info.current_block_num, + dfu_updater_nvm_info.transfer_mode, dfu_updater_nvm_info.transfer_mtu_size, + dfu_updater_nvm_info.updater_addr, + dfu_updater_nvm_info.updater_app_key_index); + } + } + } +} + +void dfu_updater_clear(void) +{ + dfu_updater_nvm_clear(); + fw_update_server_clear(); + blob_transfer_server_clear(); +} +#endif + +static int32_t dfu_update_server_data(const mesh_model_info_p pmodel_info, uint32_t type, + void *pargs) +{ + switch (type) + { + case FW_UPDATE_SERVER_METADATA_CHECK: + { + /* check whether metadata received is matched with local one*/ + /* return value + check fail: FW_UPDATE_STATUS_METADATA_CHECK_FAILED + check success: FW_UPDATE_STATUS_SUCCESS + invalid index: this case has been checked within mesh stack*/ + fw_update_server_metadata_check_t *pdata = (fw_update_server_metadata_check_t *)pargs; + { + uint8_t *pmetadata = pdata->pmetadata; + *(pdata->pstatus) = FW_UPDATE_STATUS_SUCCESS; + + if (pmetadata == NULL) { + printf("%s:Metadata is not present!\r\n", __func__); + *(pdata->pstatus) = FW_UPDATE_STATUS_METADATA_CHECK_FAILED; + break; + } + + if (dfu_metadata_check(pmetadata, pdata->metadata_len) != DFU_RESULT_OK) { + printf("%s:Metadata check fail!\r\n", __func__); + *(pdata->pstatus) = FW_UPDATE_STATUS_METADATA_CHECK_FAILED; + break; + } else { + printf("%s:Metadata check success!\r\n", __func__); + } + } + } + break; + case FW_UPDATE_SERVER_START: + { + fw_update_server_start_t *pdata = (fw_update_server_start_t *)pargs; + + /* A condition on the server is preventing the update (e.g., low battery level)*/ + /* return value + check fail: DFU_RESULT_FAIL + check success: DFU_RESULT_OK */ + if (is_dfu_enabled() != DFU_RESULT_OK) { + printf("%s:Currently is unavailable\r\n", __func__); + *(pdata->pcan_update) = false; + break; + } + + /* check whether there is sufficient resources to store the firmware*/ + /* return value + check fail: DFU_RESULT_FAIL + check success: DFU_RESULT_OK */ + if (dfu_resources_check() != DFU_RESULT_OK) { + printf("%s:There is insufficient resources to store the firmware \r\n", __func__); + *(pdata->pcan_update) = false; + break; + } + +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON + memcpy(dfu_updater_nvm_info.blob_id, blob_transfer_server_ctx.blob_id, 8); + dfu_updater_nvm_info.blob_size = blob_transfer_server_ctx.blob_size; + dfu_updater_nvm_info.block_size = blob_transfer_server_ctx.block_size; + dfu_updater_nvm_info.current_block_num = 0; + dfu_updater_nvm_info.transfer_timeout_base = blob_transfer_server_ctx.transfer_timeout_base; + dfu_updater_nvm_info.transfer_ttl = blob_transfer_server_ctx.transfer_ttl; + dfu_updater_nvm_info.transfer_mtu_size = blob_transfer_server_ctx.transfer_mtu_size; + dfu_updater_nvm_info.updater_addr = blob_transfer_server_ctx.updater_addr; + dfu_updater_nvm_info.updater_app_key_index = blob_transfer_server_ctx.updater_app_key_index; + dfu_updater_nvm_info.transfer_mode = blob_transfer_server_ctx.mode; + ftl_save(&dfu_updater_nvm_info, DFU_UPDATER_NVM_OFFSET, sizeof(dfu_updater_nvm_info)); +#endif + } + break; + case FW_UPDATE_SERVER_VERIFY: + { + /* check firmware specific action*/ + bool check_result = false; + + if (dfu_verify(dfu_updater_app_ctx.image_id) == DFU_RESULT_OK) { + check_result = true; + } + +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON + dfu_updater_nvm_clear(); +#endif + if (check_result) + { + printf("dfu_update_server_data: update success, verify pass! \r\n"); + } + else + { + printf("dfu_update_server_data: verify fail! \r\n"); + } + fw_update_server_set_verify_result(check_result); + } + break; + case FW_UPDATE_SERVER_VERIFY_CANCEL: + /* mesh stack will operate the specific actions */ + dfu_verify_cancel(); + break; + case FW_UPDATE_SERVER_APPLY: + /* operate the reload latest firmware action*/ + printf("dfu_update_server_data: FW update Apply! \r\n"); + dfu_apply(0, 4000); + break; + case FW_UPDATE_SERVER_BLOCK_DATA: + { + fw_update_server_block_data_t *pdata = (fw_update_server_block_data_t *)pargs; + + if (pdata->block_num == 0) { + /* maybe do some firmware update resouces initialization*/ + if (dfu_init_dfu_resources() != DFU_RESULT_OK) { + printf("%s:Initialization of dfu resources fail \r\n", __func__); + fw_update_server_clear(); + dfu_failsafe(); + break; + } + } + + /* saving the block image file*/ + /* firstly, if necessary, check block integrity */ + if (dfu_block_verify(pdata->pdata, pdata->data_len, DFU_BLOCK_SIGNATURE_SIZE) != DFU_RESULT_OK) { + printf("dfu_update_server_data: block check fail ! \r\n"); + fw_update_server_clear(); + dfu_failsafe(); + break; + } + /* flash image file */ + if (dfu_block_data_restore(pdata->pdata, pdata->data_len, DFU_BLOCK_SIGNATURE_SIZE) != DFU_RESULT_OK) { + printf("dfu_update_server_data: flash block %d fail ! \r\n", pdata->block_num); + fw_update_server_clear(); + dfu_failsafe(); + break; + } + + if (pdata->block_num == 0) + { + printf("dfu_update_server_data: Received the first block data! \r\n"); + dfu_updater_app_ctx.image_id = 0x0001; +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON + dfu_updater_nvm_info.current_block_num = 1; + dfu_updater_nvm_info.image_id = dfu_updater_app_ctx.image_id; + ftl_save(&dfu_updater_nvm_info, DFU_UPDATER_NVM_OFFSET, sizeof(dfu_updater_nvm_info)); +#endif + } + else + { + printf("dfu_update_server_data: ========Received one block %d ========= \r\n", pdata->block_num); +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON + dfu_updater_nvm_info.current_block_num = pdata->block_num + 1; + ftl_save(&dfu_updater_nvm_info.current_block_num, + DFU_UPDATER_NVM_OFFSET + MEMBER_OFFSET(dfu_updater_nvm_info_t, current_block_num), 4); +#endif + } + } + break; + case FW_UPDATE_SERVER_FAIL: + { + dfu_failsafe(); +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON + dfu_updater_nvm_clear(); +#endif + } + break; + default: + break; + } + + return MODEL_SUCCESS; +} + +void dfu_updater_models_init(void) +{ + fw_update_server_reg(0, dfu_update_server_data); + blob_transfer_server_reg(0, fw_update_handle_blob_server_data); + + /* Firstly, read firmware info from specific flash room and call fw_update_server_add_info to notify the mesh stack*/ + { + fw_info_t fw_info; + + dfu_get_fw_info(&fw_info); + if (fw_info.update_uri_len) { + fw_update_server_add_info(&fw_info.fw_id, fw_info.fw_id_len, fw_info.update_uri, fw_info.update_uri_len); + } else { + fw_update_server_add_info(&fw_info.fw_id, fw_info.fw_id_len, NULL, 0); + } + + } +} + +#endif /* MESH_DFU */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.h new file mode 100644 index 00000000..b61edc4b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.h @@ -0,0 +1,57 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file dfu_updater_app.h +* @brief Smart mesh dfu application +* @details +* @author bill +* @date 2018-6-5 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _DFU_UPDATER_APP_H +#define _DFU_UPDATER_APP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mesh_api.h" +#include "firmware_update.h" +#include "blob_transfer.h" + +#if MESH_DFU + +/** + * @addtogroup DFU_UPDATER_APP + * @{ + */ +#define DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON 0 + +/* Attention: shall not be overlapped with other datas */ +#define DFU_UPDATER_NVM_OFFSET FTL_MAP_MESH_DFU_UPDATER_OFFSET + +/** + * @defgroup Dfu_Updater_Exported_Functions Dfu Updater Exported Functions + * @brief + * @{ + */ +void dfu_updater_models_init(void); + +#if DFU_UPDATER_SUPPORT_POWER_OFF_GO_ON +void dfu_updater_load(void); +void dfu_updater_clear(void); +#endif + +/** @} */ +/** @} */ + +#endif /* MESH_DFU */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DFU_UPDATER_APP_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c new file mode 100644 index 00000000..8dcb83b7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c @@ -0,0 +1,180 @@ +/****************************************************************************** + * + * Copyright(c) 2019 - 2021 Realtek Corporation. All rights reserved. + * + ******************************************************************************/ +#include "dfudep_service.h" + +#define DFUDEP_DBG(x, ...) do {} while(0) + +#if defined(MESH_DFU) && MESH_DFU + +extern struct dfudep_service_ops dfudep_service; + +//server dfu service +uint8_t dfu_metadata_check(void *pmetadata, uint32_t len) +{ + if (dfudep_service.dfu_metadata_check) { + return dfudep_service.dfu_metadata_check(pmetadata, len); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_metadata_check"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_resources_check(void) +{ + if (dfudep_service.dfu_resources_check) { + return dfudep_service.dfu_resources_check(); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_resources_check"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_init_dfu_resources(void) +{ + if (dfudep_service.dfu_init_dfu_resources) { + return dfudep_service.dfu_init_dfu_resources(); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_init_dfu_resources"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_block_verify(uint8_t *data ,uint16_t len, uint8_t signature_size) +{ + if (dfudep_service.dfu_block_verify) { + return dfudep_service.dfu_block_verify(data, len, signature_size); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_block_verify"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_verify(uint16_t image_id) +{ + if (dfudep_service.dfu_verify) { + return dfudep_service.dfu_verify(image_id); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_verify"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_cancel(void) +{ + if (dfudep_service.dfu_cancel) { + return dfudep_service.dfu_cancel(); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_cancel"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_verify_cancel(void) +{ + if (dfudep_service.dfu_verify_cancel) { + return dfudep_service.dfu_verify_cancel(); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_verify_cancel"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_apply(uint8_t reason, uint32_t delay_ms) +{ + if (dfudep_service.dfu_apply) { + return dfudep_service.dfu_apply(reason, delay_ms); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_apply"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_block_data_restore(uint8_t * data , uint32_t len, uint8_t signature_size) +{ + if (dfudep_service.dfu_block_data_restore) { + return dfudep_service.dfu_block_data_restore(data, len, signature_size); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_block_data_restore"); + } + + return DFU_RESULT_FAIL; +} + +void dfu_failsafe(void) +{ + if (dfudep_service.dfu_failsafe) { + dfudep_service.dfu_failsafe(); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_failsafe"); + } + + return; +} + +uint8_t is_dfu_enabled(void) +{ + if (dfudep_service.is_dfu_enabled) { + return dfudep_service.is_dfu_enabled(); + } else { + DFUDEP_DBG("Not implement dfu service: is_dfu_enabled"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_get_fw_info(fw_info_t *pfw_info) +{ + if (dfudep_service.dfu_get_fw_info) { + return dfudep_service.dfu_get_fw_info(pfw_info); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_get_fw_info"); + } + + return DFU_RESULT_FAIL; +} + +//client dfu service +uint32_t dfu_fw_image_data_get(uint32_t len, uint8_t *pout) +{ + if (dfudep_service.dfu_fw_image_data_get) { + return dfudep_service.dfu_fw_image_data_get(len, pout); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_fw_image_data_get"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_block_signature(uint8_t *data ,uint16_t len, uint8_t signature_size) +{ + if (dfudep_service.dfu_block_signature) { + return dfudep_service.dfu_block_signature(data, len, signature_size); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_block_signature"); + } + + return DFU_RESULT_FAIL; +} + +uint8_t dfu_check_fw_info(fw_info_t *pfw_info) +{ + if (dfudep_service.dfu_check_fw_info) { + return dfudep_service.dfu_check_fw_info(pfw_info); + } else { + DFUDEP_DBG("Not implement dfu service: dfu_check_fw_info"); + } + + return DFU_RESULT_FAIL; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.h new file mode 100644 index 00000000..431104f7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.h @@ -0,0 +1,166 @@ +/****************************************************************************** + * + * Copyright(c) 2019 - 2021 Realtek Corporation. All rights reserved. + * + ******************************************************************************/ +#ifndef __DFUDEP_SERVICE_H_ +#define __DFUDEP_SERVICE_H_ + +#include "generic_types.h" +#include "ftl.h" +#include "firmware_update.h" + +#if defined(MESH_DFU) && MESH_DFU + +#define DFU_BLOCK_SIGNATURE_SIZE 0 +#define FW_VERSION_MAX_LEN 106 + +/** @brief Indicate the result of dfu api */ +typedef enum +{ + DFU_RESULT_OK, + DFU_RESULT_FAIL +} dfu_result_t; + +/** + * @brief check whether metadata received from update client is acceptable + * + * @param[in] pmetadata: metadata pointer of the received metadata from update client + * @param[in] len: metadata length + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_metadata_check(void *pmetadata, uint32_t len); + +/** + * @brief check if there is sufficient resources for the device firmware update + * + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_resources_check(void); + +/** + * @brief init dfu resources + * + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_init_dfu_resources(void); + +/** + * @brief image block file received check action(which is specific defined by upper layer) + * + * @param[in] data: pointer to the received block file + * @param[in] len: image file length within the received block filename + * @param[in] signature_size: signature length + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_block_verify(uint8_t *data ,uint16_t len, uint8_t signature_size); + +/** + * @brief whole image file received check action + * + * @param[in] image_id: the image id of the verifying image + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_verify(uint16_t image_id); + +/** + * @brief after received the cancel request from client, free and deinit some flash resources + * + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_cancel(void); + +/** + * @brief after received the verify cancel request from client, free and deinit some flash resources + * + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_verify_cancel(void); + +/** + * @brief apply the received latest image + * + * @param[in] reason: reboot reason + * @param[in] delay_ms: reboot after delay ms + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_apply(uint8_t reason, uint32_t delay_ms); + +/** + * @brief save the received block image file to flash + * + * @param[in] len: block image file length + * @param[in] data: pointer to the block image file + * @param[in] signature_size: signature length + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_block_data_restore(uint8_t * data , uint32_t len, uint8_t signature_size); + +/** + * @brief when dfu fails, free and deinit flash resources + * + * @return None + */ +void dfu_failsafe(void); + +/** + * @brief check whether dfu is enable + * + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t is_dfu_enabled(void); + +/** + * @brief get the current firmware information + * + * @param[in] pfw_info: pointer to fw_info + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_get_fw_info(fw_info_t *pfw_info); + +/** + * @brief fetch the image file, which is going to be sent by the dfu client + * + * @param[in] len: image block file length + * @param[in] pout: the destination address. where the image block will be buffed for transmitting + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint32_t dfu_fw_image_data_get(uint32_t len, uint8_t *pout); + +/** + * @brief sign the block data + * + * @param[in] data: pointer to the image file + * @param[in] len: image block file length + * @param[in] signature_size: signature length + * @return DFU_RESULT_OK for success, DFU_RESULT_FAIL for fail + */ +uint8_t dfu_block_signature(uint8_t *data ,uint16_t len, uint8_t signature_size); + +/** + * @brief check whether the received node's firmware info needs firmware update + * + * @param[in] pfw_info: pointer to fw_info + * @return DFU_RESULT_OK for Nedd Update, DFU_RESULT_FAIL for No + */ +uint8_t dfu_check_fw_info(fw_info_t *pfw_info); + +struct dfudep_service_ops { + uint8_t (*dfu_metadata_check)(void *pmetadata, uint32_t len); + uint8_t (*dfu_resources_check)(void); + uint8_t (*dfu_init_dfu_resources)(void); + uint8_t (*dfu_block_verify)(uint8_t *data ,uint16_t len, uint8_t signature_size); + uint8_t (*dfu_verify)(uint16_t image_id); + uint8_t (*dfu_cancel)(void); + uint8_t (*dfu_verify_cancel)(void); + uint8_t (*dfu_apply)(uint8_t reason, uint32_t delay_ms); + uint8_t (*dfu_block_data_restore)(uint8_t * data , uint32_t len, uint8_t signature_size); + void (*dfu_failsafe)(void); + uint8_t (*is_dfu_enabled)(void); + uint8_t (*dfu_get_fw_info)(fw_info_t *pfw_info); + uint32_t (*dfu_fw_image_data_get)(uint32_t len, uint8_t *pout); + uint8_t (*dfu_block_signature)(uint8_t *data ,uint16_t len, uint8_t signature_size); + uint8_t (*dfu_check_fw_info)(fw_info_t *pfw_info); +}; +#endif +#endif \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.c new file mode 100644 index 00000000..afe0f01f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.c @@ -0,0 +1,804 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file generic_client_app.c + * @brief Source file for generic models application. + * @details User command interfaces. + * @author hector_huang + * @date 2018-7-24 + * @version v1.0 + * ************************************************************************************* + */ +#include "provisioner_app.h" +#include "generic_client_app.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#if ((defined CONFIG_BT_MESH_PROVISIONER && CONFIG_BT_MESH_PROVISIONER) || \ + (defined CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE)) +#include "bt_mesh_provisioner_api.h" +#endif +#if ((defined CONFIG_BT_MESH_DEVICE && CONFIG_BT_MESH_DEVICE) || \ + (defined CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE)) +#include "bt_mesh_device_api.h" +#endif + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO +#include "bt_mesh_app_list_intf.h" +#endif + +mesh_model_info_t model_gdtt_client; +mesh_model_info_t model_goo_client; +mesh_model_info_t model_gl_client; +mesh_model_info_t model_gpoo_client; +mesh_model_info_t model_gpl_client; +mesh_model_info_t model_gb_client; +mesh_model_info_t model_health_client; +mesh_model_info_t model_time_client; +mesh_model_info_t model_scene_client; +mesh_model_info_t model_sensor_client; +mesh_model_info_t model_scheduler_client; +mesh_model_info_t model_generic_location_client; +mesh_model_info_t model_gp_client; + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO +#include "bt_mesh_app_lib_intf.h" +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; +#endif + +static int32_t generic_on_off_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_ON_OFF_CLIENT_STATUS: + { + generic_on_off_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("goo client receive: src = %d, present = %d, target = %d, remain time = step(%d), \ +resolution(%d)\r\n", pdata->src, pdata->present_on_off, pdata->target_on_off, + pdata->remaining_time.num_steps, pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("goo client receive: src = %d, present = %d\r\n", pdata->src, + pdata->present_on_off); +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + update_proed_dev(pdata->src, pdata->present_on_off); +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + { + uint8_t ret = USER_API_RESULT_ERROR; + if (pdata->present_on_off) { +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + bt_mesh_lib_priv.connect_device_goog_light_state = BT_MESH_GOO_ON; +#endif + ret = bt_mesh_indication(GEN_MESH_CODE(_generic_on_off_set), BT_MESH_GOO_ON, (void *)pdata); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_generic_on_off_set)); + break; + } + } else { + break; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_generic_on_off_get), BT_MESH_GOO_ON, (void *)pdata); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_generic_on_off_get)); + break; + } + } else { + break; + } + } else { +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + bt_mesh_lib_priv.connect_device_goog_light_state = BT_MESH_GOO_OFF; +#endif + ret = bt_mesh_indication(GEN_MESH_CODE(_generic_on_off_set), BT_MESH_GOO_OFF, (void *)pdata); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_generic_on_off_set)); + break; + } + } else { + break; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_generic_on_off_get), BT_MESH_GOO_OFF, (void *)pdata); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_generic_on_off_get)); + break; + } + } else { + break; + } + } + } +#endif + } + } + break; + default: + break; + } + + return 0; +} + +#if !defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) || !CONFIG_BT_MESH_PROVISIONER_RTK_DEMO +static int32_t generic_default_transition_time_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_DEFAULT_TRANSITION_TIME_CLIENT_STATUS: + { + generic_default_transition_time_client_status_t *pdata = pargs; + data_uart_debug("gdtt client receive: src = %d, steps = %d, resolution = %d\r\n", + pdata->src, pdata->trans_time.num_steps, pdata->trans_time.step_resolution); + } + break; + default: + break; + } + + return 0; +} + +static int32_t generic_level_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_LEVEL_CLIENT_STATUS: + { + generic_level_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("genric level client receive: src = %d, present = %d, target = %d, remain time = step(%d), \ +resolution(%d)\r\n", pdata->src, pdata->present_level, pdata->target_level, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("generic level client receive: src = %d, present = %d\r\n", pdata->src, + pdata->present_level); + } + } + break; + default: + break; + } + + return 0; +} + +static int32_t generic_battery_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_BATTERY_CLIENT_STATUS: + { + generic_battery_client_status_t *pdata = pargs; + data_uart_debug("genric battery client receive: src = %d, battery level = %d, time to discharge = %d, \ +time to charge = %d, presence = %d, indicator = %d, charging = %d, serviceability = %d\r\n", + pdata->src, + pdata->battery_level, + pdata->time_to_discharge, pdata->time_to_charge, + pdata->flags.presence, pdata->flags.indicator, pdata->flags.charging, + pdata->flags.serviceability); + } + break; + default: + break; + } + + return 0; +} + +static int32_t generic_power_on_off_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_POWER_ON_OFF_CLIENT_STATUS: + { + generic_power_on_off_client_status_t *pdata = pargs; + data_uart_debug("generic power on/off receive: src = %d, power = %d\r\n", pdata->src, + pdata->on_power_up); + } + break; + default: + break; + } + + return 0; +} + +static int32_t generic_power_level_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_POWER_LEVEL_CLIENT_STATUS: + { + generic_power_level_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("genric power level client receive: src = %d, present = %d, target = %d, remain time = step(%d), \ +resolution(%d)\r\n", pdata->src, pdata->present_power, pdata->target_power, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("generic power level client receive: src = %d, present = %d\r\n", pdata->src, + pdata->present_power); + } + } + break; + case GENERIC_POWER_LEVEL_CLIENT_STATUS_LAST: + { + generic_power_level_client_status_simple_t *pdata = pargs; + data_uart_debug("generic power level client receive: power = %d\r\n", pdata->power); + } + break; + case GENERIC_POWER_LEVEL_CLIENT_STATUS_DEFAULT: + { + generic_power_level_client_status_simple_t *pdata = pargs; + data_uart_debug("generic power level client receive: power = %d\r\n", pdata->power); + } + break; + case GENERIC_POWER_LEVEL_CLIENT_STATUS_RANGE: + { + generic_power_level_client_status_range_t *pdata = pargs; + data_uart_debug("generic power level client receive: status = %d, min = %d, max = %d\r\n", + pdata->stat, pdata->range_min, pdata->range_max); + } + break; + default: + break; + } + + return 0; +} + +static int32_t health_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case HEALTH_CLIENT_STATUS_CURRENT: + case HEALTH_CLIENT_STATUS_REGISTERED: + { + health_client_status_t *pdata = pargs; + data_uart_debug("health client receive: src = %d, test id = %d, company id = %d, fault = ", + pdata->src, + pdata->test_id, pdata->company_id); + for (int i = 0; i < pdata->fault_array_len; ++i) + { + data_uart_debug("%d ", pdata->fault_array[i]); + } + data_uart_debug("\r\n"); + } + break; + case HEALTH_CLIENT_STATUS_PERIOD: + { + health_client_status_period_t *pdata = pargs; + data_uart_debug("health client receive: fast period divisor = %d\r\n", pdata->fast_period_divisor); + } + break; + case HEALTH_CLIENT_STATUS_ATTENTION: + { + health_client_status_attention_t *pdata = pargs; + data_uart_debug("health client receive: attention = %d\r\n", pdata->attention); + } + break; + default: + break; + } + + return 0; +} + +static int32_t time_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case TIME_CLIENT_STATUS: + { + time_client_status_t *pdata = pargs; + data_uart_debug("time client receive: src = %d, tai_seconds = 0x%02x%02x%02x%02x%02x, \ +subsecond = %d, uncertainty = %d, time_authority = %d, tai_utc_delta = %d, \ +time_zone_offset = %d\r\n", pdata->src, pdata->tai_time.tai_seconds[4], + pdata->tai_time.tai_seconds[3], pdata->tai_time.tai_seconds[2], + pdata->tai_time.tai_seconds[1], pdata->tai_time.tai_seconds[0], pdata->tai_time.subsecond, + pdata->tai_time.uncertainty, + pdata->tai_time.time_authority, pdata->tai_time.tai_utc_delta, pdata->tai_time.time_zone_offset); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_time_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_time_get)); + } +#endif + } + break; + case TIME_CLIENT_STATUS_ZONE: + { + time_client_status_zone_t *pdata = pargs; + data_uart_debug("time client receive: time_zone_offset_current = %d, \ +time_zone_offset_new = %d, tai_of_zone_change = 0x%02x%02x%02x%02x%02x\r\n", + pdata->time_zone_offset_current, pdata->time_zone_offset_new, pdata->tai_of_zone_change[4], + pdata->tai_of_zone_change[3], pdata->tai_of_zone_change[2], pdata->tai_of_zone_change[1], + pdata->tai_of_zone_change[0]); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_time_zone_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_time_zone_get)); + } +#endif + } + break; + case TIME_CLIENT_STATUS_TAI_UTC_DELTA: + { + time_client_status_tai_utc_delta_t *pdata = pargs; + data_uart_debug("time client receive: tai_utc_delta_current = %d, tai_utc_delta_new = %d, \ +tai_of_delta_change = 0x%02x%02x%02x%02x%02x\r\n", pdata->tai_utc_delta_current, + pdata->tai_utc_delta_new, + pdata->tai_of_delta_change[4], pdata->tai_of_delta_change[3], pdata->tai_of_delta_change[2], + pdata->tai_of_delta_change[1], pdata->tai_of_delta_change[0]); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_time_tai_utc_delta_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_time_tai_utc_delta_get)); + } +#endif + } + break; + case TIME_CLIENT_STATUS_ROLE: + { + time_client_status_role_t *pdata = pargs; + data_uart_debug("time client receive: role = %d\r\n", pdata->role); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_time_role_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_time_role_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t scene_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case SCENE_CLIENT_STATUS: + { + scene_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("scene client receive: src = %d, status = %d, current = %d, target = %d, \ +remain time = step(%d), resolution(%d)\r\n", pdata->src, pdata->status, pdata->current_scene, + pdata->target_scene, + pdata->remaining_time.num_steps, pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("scene client receive: status = %d, current = %d\r\n", pdata->status, + pdata->current_scene); + } + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_scene_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_scene_get)); + } +#endif + } + break; + case SCENE_CLIENT_REGISTER_STATUS: + { + scene_client_register_status_t *pdata = pargs; + data_uart_debug("scene client receive: status = %d, current scene = %d, scene = ", pdata->status, + pdata->current_scene); + for (int i = 0; i < pdata->scene_array_len; ++i) + { + data_uart_debug("%d ", pdata->scene_array[i]); + } + data_uart_debug("\r\n"); + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_scene_register_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_scene_register_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t sensor_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case SENSOR_CLIENT_STATUS_DESCRIPTOR: + { + sensor_client_status_descriptor_t *pdata = pargs; + if (0 == pdata->num_descriptors) + { + data_uart_debug("sensor client receive: property id = %d\r\n", pdata->property_id); + } + else + { + for (uint16_t i = 0; i < pdata->num_descriptors; ++i) + { + data_uart_debug("sensor client receive: property id = %d, positive rolerance = %d, negative tolerance = %d, sampling function = %d, measurement period = %d, updata_interval = %d\r\n", + pdata->descriptors[i].property_id, pdata->descriptors[i].positive_tolerance, + pdata->descriptors[i].negative_tolerance, pdata->descriptors[i].sampling_function, + pdata->descriptors[i].measurement_period, pdata->descriptors[i].update_interval); + } + } + } + break; + case SENSOR_CLIENT_STATUS_CADENCE: + { + sensor_client_status_cadence_t *pdata = pargs; + data_uart_debug("sensor client receive: src = %d, property id = %d, divisor = %d, trigger type = %d, ", + pdata->src, + pdata->property_id, + pdata->cadence->fast_cadence_period_divisor, pdata->cadence->status_trigger_type); + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == pdata->cadence->status_trigger_type) + { + data_uart_debug("trigger delta down = "); + data_uart_dump((uint8_t *)pdata->cadence->status_trigger_delta_down, pdata->cadence->raw_value_len); + data_uart_debug(", "); + data_uart_debug("trigger delta up = "); + data_uart_dump((uint8_t *)pdata->cadence->status_trigger_delta_up, pdata->cadence->raw_value_len); + data_uart_debug(", "); + } + else + { + data_uart_debug("trigger delta down = "); + data_uart_dump((uint8_t *)pdata->cadence->status_trigger_delta_down, 2); + data_uart_debug(", "); + data_uart_debug("trigger delta up = "); + data_uart_dump((uint8_t *)pdata->cadence->status_trigger_delta_up, 2); + data_uart_debug(", "); + } + + data_uart_debug("min interval = %d, ", pdata->cadence->status_min_interval); + + data_uart_debug("fast cadence low = "); + data_uart_dump((uint8_t *)pdata->cadence->fast_cadence_low, pdata->cadence->raw_value_len); + data_uart_debug(", "); + data_uart_debug("fast cadence high = "); + data_uart_dump((uint8_t *)pdata->cadence->fast_cadence_high, pdata->cadence->raw_value_len); + } + break; + case SENSOR_CLIENT_STATUS_SETTINGS: + { + sensor_client_status_settings_t *pdata = pargs; + data_uart_debug("sensor client receive: property id = %d, setting ids = ", pdata->property_id); + for (uint16_t i = 0; i < pdata->num_ids; ++i) + { + data_uart_debug("0x%x ", pdata->setting_ids[i]); + } + data_uart_debug("\r\n"); + } + break; + case SENSOR_CLIENT_STATUS_SETTING: + { + sensor_client_status_setting_t *pdata = pargs; + data_uart_debug("sensor client receive: src = %d, property id = %d, setting property id = %d", + pdata->src, + pdata->property_id, + pdata->setting_property_id); + if (NULL != pdata->setting) + { + data_uart_debug(", access = %d", pdata->setting->setting_access); + if (pdata->setting->setting_raw_len > 0) + { + data_uart_debug(", setting raw = "); + data_uart_dump((uint8_t *)pdata->setting->setting_raw, pdata->setting->setting_raw_len); + } + } + data_uart_debug("\r\n"); + } + break; + case SENSOR_CLIENT_STATUS: + { + sensor_client_status_t *pdata = pargs; + data_uart_debug("sensor client receive: marshalled sensor data src = %d, ", pdata->src); + data_uart_dump((uint8_t *)pdata->marshalled_sensor_data, pdata->marshalled_sensor_data_len); + data_uart_debug("\r\n"); + } + break; + case SENSOR_CLIENT_STATUS_COLUMN: + { + sensor_client_status_column_t *pdata = pargs; + data_uart_debug("sensor client receive: property id = %d, column raw data = ", pdata->property_id); + data_uart_dump((uint8_t *)pdata->column_raw_value, pdata->column_raw_value_len); + } + break; + case SENSOR_CLIENT_STATUS_SERIES: + { + sensor_client_status_series_t *pdata = pargs; + data_uart_debug("sensor client receive: property id = %d, series raw data = ", pdata->property_id); + data_uart_dump((uint8_t *)pdata->series_raw_value, pdata->series_raw_value_len); + } + break; + default: + break; + } + + return 0; +} + +static int32_t scheduler_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case SCHEDULER_CLIENT_STATUS: + { + scheduler_client_status_t *pdata = pargs; + data_uart_debug("scheduler client receive: schedulers = %d\r\n", pdata->schedulers); + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_scheduler_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_scheduler_get)); + } +#endif + } + break; + case SCHEDULER_CLIENT_STATUS_ACTION: + { + scheduler_client_status_action_t *pdata = pargs; + data_uart_debug("scheduler client receive: src = %d, index = %d, year = %d, month = %d, day = %d, hour = %d, minute = %d, second = %d, \ +day_of_week = %d, action = %d, num_steps = %d, step_resolution = %d, scene_number = %d\r\n", + pdata->src, + pdata->scheduler.index, pdata->scheduler.year, pdata->scheduler.month, pdata->scheduler.day, + pdata->scheduler.hour, pdata->scheduler.minute, pdata->scheduler.second, + pdata->scheduler.day_of_week, pdata->scheduler.action, pdata->scheduler.num_steps, + pdata->scheduler.step_resolution, pdata->scheduler.scene_number); + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_scheduler_action_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_scheduler_action_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t generic_location_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_LOCATION_CLIENT_STATUS_GLOBAL: + { + generic_location_client_status_global_t *pdata = pargs; + data_uart_debug("generic location client receive: src = %d, latitude = %d, longitude = %d, altitude = %d\r\n", + pdata->src, + pdata->global.global_latitude, pdata->global.global_longitude, pdata->global.global_altitude); + } + break; + case SCHEDULER_CLIENT_STATUS_ACTION: + { + generic_location_client_status_local_t *pdata = pargs; + data_uart_debug("generic location client receive: src = %d, north = %d, east = %d, altitude = %d, floor = %d, stationary = %d, updata time = %d, precision = %d\r\n", + pdata->src, pdata->local.local_north, pdata->local.local_east, pdata->local.local_altitude, + pdata->local.floor_num, + pdata->local.uncertainty.stationary, pdata->local.uncertainty.update_time, + pdata->local.uncertainty.precision); + } + break; + default: + break; + } + + return 0; + +} + +static int32_t generic_property_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case GENERIC_USER_PROPERIES_CLIENT_STATUS: + { + generic_properties_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d", pdata->src); + if (pdata->num_ids > 0) + { + data_uart_debug(", user property ids = "); + for (uint8_t i = 0; i < pdata->num_ids; ++i) + { + data_uart_debug("%x ", pdata->pproperty_ids[i]); + } + } + data_uart_debug("\r\n"); + } + break; + case GENERIC_USER_PROPERTY_CLIENT_STATUS: + { + generic_property_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d, property id = 0x%x, property access = %d", + pdata->src, pdata->property_id, pdata->property_access); + if (pdata->value_len > 0) + { + data_uart_debug(", user property values = "); + for (uint8_t i = 0; i < pdata->value_len; ++i) + { + data_uart_debug("%d ", pdata->pproperty_value[i]); + } + } + data_uart_debug("\r\n"); + } + break; + case GENERIC_ADMIN_PROPERTIES_CLIENT_STATUS: + { + generic_properties_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d", pdata->src); + if (pdata->num_ids > 0) + { + data_uart_debug(", admin property ids = "); + for (uint8_t i = 0; i < pdata->num_ids; ++i) + { + data_uart_debug("%x ", pdata->pproperty_ids[i]); + } + } + data_uart_debug("\r\n"); + } + break; + case GENERIC_ADMIN_PROPERTY_CLIENT_STATUS: + { + generic_property_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d, property id = 0x%x, property access = %d", + pdata->src, pdata->property_id, pdata->property_access); + if (pdata->value_len > 0) + { + data_uart_debug(", admin property values = "); + for (uint8_t i = 0; i < pdata->value_len; ++i) + { + data_uart_debug("%d ", pdata->pproperty_value[i]); + } + } + data_uart_debug("\r\n"); + } + break; + case GENERIC_MANUFACTURER_PROPERTIES_CLIENT_STATUS: + { + generic_properties_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d", pdata->src); + if (pdata->num_ids > 0) + { + data_uart_debug(", manufacturer property ids = "); + for (uint8_t i = 0; i < pdata->num_ids; ++i) + { + data_uart_debug("%4x ", pdata->pproperty_ids[i]); + } + } + data_uart_debug("\r\n"); + } + break; + case GENERIC_MANUFACTURER_PROPERTY_CLIENT_STATUS: + { + generic_property_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d, property id = 0x%x, property access = %d", + pdata->src, pdata->property_id, pdata->property_access); + if (pdata->value_len > 0) + { + data_uart_debug(", manufacturer property values = "); + for (uint8_t i = 0; i < pdata->value_len; ++i) + { + data_uart_debug("%d ", pdata->pproperty_value[i]); + } + } + data_uart_debug("\r\n"); + } + break; + case GENERIC_CLIENT_PROPERTIES_CLIENT_STATUS: + { + generic_properties_client_status_t *pdata = pargs; + data_uart_debug("generic property client receive: src = %d", pdata->src); + if (pdata->num_ids > 0) + { + data_uart_debug(", client property ids = "); + for (uint8_t i = 0; i < pdata->num_ids; ++i) + { + data_uart_debug("%x ", pdata->pproperty_ids[i]); + } + } + data_uart_debug("\r\n"); + } + break; + default: + break; + } + + return 0; +} +#endif + +void generic_client_models_init(void) +{ +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + model_goo_client.model_data_cb = generic_on_off_client_data; + generic_on_off_client_reg(0, &model_goo_client); +#else + model_gdtt_client.model_data_cb = generic_default_transition_time_client_data; + generic_default_transition_time_client_reg(0, &model_gdtt_client); + + model_goo_client.model_data_cb = generic_on_off_client_data; + generic_on_off_client_reg(0, &model_goo_client); + + model_gl_client.model_data_cb = generic_level_client_data; + generic_level_client_reg(0, &model_gl_client); + + model_gpoo_client.model_data_cb = generic_power_on_off_client_data; + generic_power_on_off_client_reg(0, &model_gpoo_client); + + model_gpl_client.model_data_cb = generic_power_level_client_data; + generic_power_level_client_reg(0, &model_gpl_client); + + model_gb_client.model_data_cb = generic_battery_client_data; + generic_battery_client_reg(0, &model_gb_client); + + model_health_client.model_data_cb = health_client_data; + health_client_reg(0, &model_health_client); + + model_time_client.model_data_cb = time_client_data; + time_client_reg(1, &model_time_client); + + model_scene_client.model_data_cb = scene_client_data; + scene_client_reg(0, &model_scene_client); + + model_sensor_client.model_data_cb = sensor_client_data; + sensor_client_reg(0, &model_sensor_client); + + model_scheduler_client.model_data_cb = scheduler_client_data; + scheduler_client_reg(0, &model_scheduler_client); + + model_generic_location_client.model_data_cb = generic_location_client_data; + generic_location_client_reg(0, &model_generic_location_client); + + model_gp_client.model_data_cb = generic_property_client_data; + generic_property_client_reg(0, &model_gp_client); +#endif +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.h new file mode 100644 index 00000000..6a6d5d3c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.h @@ -0,0 +1,74 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file generic_client_app.h +* @brief Smart mesh generic models demo application +* @details +* @author bill +* @date 2018-1-10 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _GENERIC_CLIENT_APP_H +#define _GENERIC_CLIENT_APP_H + +#include "generic_default_transition_time.h" +#include "generic_on_off.h" +#include "generic_level.h" +#include "generic_power_level.h" +#include "generic_power_on_off.h" +#include "generic_battery.h" +#include "health.h" +#include "time_model.h" +#include "scene.h" +#include "sensor.h" +#include "scheduler.h" +#include "generic_location.h" +#include "generic_property.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_CLIENTS_APP + * @{ + */ + +/** + * @defgroup Generic_Clients_Exported_Types Generic Clients Exported Types + * @brief + * @{ + */ +extern mesh_model_info_t model_gdtt_client; +extern mesh_model_info_t model_goo_client; +extern mesh_model_info_t model_gl_client; +extern mesh_model_info_t model_gpoo_client; +extern mesh_model_info_t model_gpl_client; +extern mesh_model_info_t model_gb_client; +extern mesh_model_info_t model_health_client; +extern mesh_model_info_t model_time_client; +extern mesh_model_info_t model_scene_client; +extern mesh_model_info_t model_sensor_client; +extern mesh_model_info_t model_scheduler_client; +extern mesh_model_info_t model_generic_location_client; +extern mesh_model_info_t model_gp_client; +/** @} */ + +/** + * @defgroup Generic_Clients_Exported_Functions Generic Clients Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize generic client models + */ +void generic_client_models_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_CLIENT_APP_H */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.c new file mode 100644 index 00000000..8c03396a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.c @@ -0,0 +1,528 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file light_client_app.c + * @brief Source file for light client application. + * @details User command interfaces. + * @author bill + * @date 2018-1-4 + * @version v1.0 + * ************************************************************************************* + */ +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#include "light_client_app.h" +#if ((defined CONFIG_BT_MESH_PROVISIONER && CONFIG_BT_MESH_PROVISIONER) || \ + (defined CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE)) +#include "bt_mesh_provisioner_api.h" +#endif +#if ((defined CONFIG_BT_MESH_DEVICE && CONFIG_BT_MESH_DEVICE) || \ + (defined CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE)) +#include "bt_mesh_device_api.h" +#endif + +mesh_model_info_t light_cwrgb_client; +mesh_model_info_t light_lightness_client; +mesh_model_info_t light_ctl_client; +mesh_model_info_t light_hsl_client; +mesh_model_info_t light_xyl_client; +mesh_model_info_t light_lc_client; + +static bool light_cwrgb_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CWRGB_STAT: + if (pmesh_msg->msg_len == sizeof(light_cwrgb_stat_t)) + { + light_cwrgb_stat_t *pmsg = (light_cwrgb_stat_t *)pbuffer; + data_uart_debug("light 0x%04x cwrgb %d-%d-%d-%d-%d\r\n", pmesh_msg->src, pmsg->cwrgb[0], + pmsg->cwrgb[1], pmsg->cwrgb[2], pmsg->cwrgb[3], pmsg->cwrgb[4]); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_lightness_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case LIGHT_LIGHTNESS_CLIENT_STATUS: + { + light_lightness_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light lightness client receive: src %d, present %d, target %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->present_lightness, + pdata->target_lightness, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light lightness client receive: src %d, present %d\r\n", pdata->src, + pdata->present_lightness); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_lightness_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_lightness_get)); + } +#endif + } + break; + case LIGHT_LIGHTNESS_CLIENT_STATUS_LINEAR: + { + light_lightness_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light lightness client receive: src %d, present %d, target %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->present_lightness, + pdata->target_lightness, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light lightness client receive: src %d, present %d\r\n", pdata->src, + pdata->present_lightness); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_lightness_linear_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_lightness_linear_get)); + } +#endif + } + break; + case LIGHT_LIGHTNESS_CLIENT_STATUS_LAST: + { + light_lightness_client_status_last_t *pdata = pargs; + data_uart_debug("light lightness client receive: src %d, lightness %d\r\n", pdata->src, + pdata->lightness); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_lightness_last_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_lightness_last_get)); + } +#endif + } + break; + case LIGHT_LIGHTNESS_CLIENT_STATUS_DEFAULT: + { + light_lightness_client_status_default_t *pdata = pargs; + data_uart_debug("light lightness client receive: src %d, lightness %d\r\n", pdata->src, + pdata->lightness); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_lightness_default_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_lightness_default_get)); + } +#endif + } + break; + case LIGHT_LIGHTNESS_CLIENT_STATUS_RANGE: + { + light_lightness_client_status_range_t *pdata = pargs; + data_uart_debug("light lightness client receive: src %d, status %d, min %d, max %d\r\n", + pdata->src, pdata->status, pdata->range_min, pdata->range_max); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_lightness_range_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_lightness_range_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t light_ctl_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case LIGHT_CTL_CLIENT_STATUS: + { + light_ctl_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light ctl client receive: src %d, present lightness %d, present temperature %d, target lightness %d, target temperature %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->present_lightness, + pdata->present_temperature, + pdata->target_lightness, pdata->target_temperature, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light ctl client receive: src %d, present lightness %d, present temperature %d\r\n", + pdata->src, pdata->present_lightness, pdata->present_temperature); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_ctl_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_ctl_get)); + } +#endif + } + break; + case LIGHT_CTL_CLIENT_STATUS_TEMPERATURE: + { + light_ctl_client_status_temperature_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light ctl client receive: src %d, present temperature %d, present delta_uv %d, target temperature %d, target delta_uv %d, remain time step(%d), resolution(%d)\r\n", + pdata->src, + pdata->present_temperature, + pdata->present_delta_uv, + pdata->target_temperature, pdata->target_delta_uv, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light ctl client receive: src %d, present temperature %d, present delta_uv %d\r\n", + pdata->src, pdata->present_temperature, pdata->present_delta_uv); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_ctl_temperature_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_ctl_temperature_get)); + } +#endif + } + break; + case LIGHT_CTL_CLIENT_STATUS_DEFAULT: + { + light_ctl_client_status_default_t *pdata = pargs; + data_uart_debug("light ctl client receive: src %d, lightness %d, temperature %d, delta_uv %d\r\n", + pdata->src, pdata->lightness, pdata->temperature, pdata->delta_uv); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_ctl_default_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_ctl_default_get)); + } +#endif + } + break; + case LIGHT_CTL_CLIENT_STATUS_TEMPERATURE_RANGE: + { + light_ctl_client_status_temperature_range_t *pdata = pargs; + data_uart_debug("light ctl client receive: status %d, min %d, max %d\r\n", + pdata->src, pdata->status, pdata->range_min, pdata->range_max); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_ctl_temperature_range_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_ctl_temperature_range_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t light_hsl_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case LIGHT_HSL_CLIENT_STATUS: + { + light_hsl_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light hsl client receive: src %d, present lightness %d, present hue %d, present saturation %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->lightness, + pdata->hue, pdata->saturation, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light hsl client receive: src %d, present lightness %d, present hue %d, presnet saturation %d\r\n", + pdata->src, pdata->lightness, pdata->hue, pdata->saturation); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_hsl_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_hsl_get)); + } +#endif + } + break; + case LIGHT_HSL_CLIENT_STATUS_TARGET: + { + light_hsl_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light hsl client receive: src %d, target lightness %d, target hue %d, target saturation %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->lightness, + pdata->hue, pdata->saturation, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light hsl client receive: src %d, target lightness %d, target hue %d, target saturation %d\r\n", + pdata->src, pdata->lightness, pdata->hue, pdata->saturation); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_hsl_target_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_hsl_target_get)); + } +#endif + } + break; + case LIGHT_HSL_CLIENT_STATUS_HUE: + { + light_hsl_client_status_hue_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light hsl client receive: src %d, present hue %d, target hue %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->present_hue, + pdata->target_hue, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light hsl client receive: src %d, present hue %d\r\n", + pdata->src, pdata->present_hue); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_hsl_hue_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_hsl_hue_get)); + } +#endif + } + break; + case LIGHT_HSL_CLIENT_STATUS_SATURATION: + { + light_hsl_client_status_saturation_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light hsl client receive: src %d, present saturation %d, target saturation %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->present_saturation, + pdata->target_saturation, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light hsl client receive: src %d, present saturation %d\r\n", + pdata->src, pdata->present_saturation); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_hsl_saturation_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_hsl_saturation_get)); + } +#endif + } + break; + case LIGHT_HSL_CLIENT_STATUS_DEFAULT: + { + light_hsl_client_status_default_t *pdata = pargs; + data_uart_debug("light hsl client receive: src %d, lightness %d, hue %d, saturation %d\r\n", + pdata->src, pdata->lightness, pdata->hue, pdata->saturation); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_hsl_default_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_hsl_default_get)); + } +#endif + } + break; + case LIGHT_HSL_CLIENT_STATUS_RANGE: + { + light_hsl_client_status_range_t *pdata = pargs; + data_uart_debug("light hsl client receive: src %d, status %d, hue min %d, hue max %d, saturation min %d, saturation max %d\r\n", + pdata->src, pdata->status, pdata->hue_range_min, pdata->hue_range_max, + pdata->saturation_range_min, pdata->saturation_range_max); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_hsl_range_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_hsl_range_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t light_xyl_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case LIGHT_XYL_CLIENT_STATUS: + { + light_xyl_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light xyl client receive: src %d, present lightness %d, present xyl_x %d, present xyl_y %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->xyl.xyl_lightness, + pdata->xyl.xyl_x, pdata->xyl.xyl_y, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light xyl client receive: src %d, present lightness %d, present hue %d, presnet saturation %d\r\n", + pdata->src, pdata->xyl.xyl_lightness, pdata->xyl.xyl_x, pdata->xyl.xyl_y); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_xyl_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_xyl_get)); + } +#endif + } + break; + case LIGHT_XYL_CLIENT_STATUS_TARGET: + { + light_xyl_client_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light xyl client receive: src %d, target lightness %d, target xyl_x %d, target xyl_y %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->xyl.xyl_lightness, + pdata->xyl.xyl_x, pdata->xyl.xyl_y, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light xyl client receive: src %d, target lightness %d, target xyl_x %d, target xyl_y %d\r\n", + pdata->src, pdata->xyl.xyl_lightness, pdata->xyl.xyl_x, pdata->xyl.xyl_y); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_xyl_target_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_xyl_target_get)); + } +#endif + } + break; + case LIGHT_XYL_CLIENT_STATUS_DEFAULT: + { + light_xyl_client_status_default_t *pdata = pargs; + data_uart_debug("light xyl client receive: src %d, lightness %d, xyl_x %d, xyl_y %d\r\n", + pdata->src, pdata->xyl.xyl_lightness, pdata->xyl.xyl_x, pdata->xyl.xyl_y); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_xyl_default_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_xyl_default_get)); + } +#endif + } + break; + case LIGHT_XYL_CLIENT_STATUS_RANGE: + { + light_xyl_client_status_range_t *pdata = pargs; + data_uart_debug("light xyl client receive: src %d, status %d, xyl_x min %d, xyl_x max %d, xyl_y min %d, xyl_y max %d\r\n", + pdata->src, pdata->status, pdata->xyl_x_range_min, pdata->xyl_x_range_max, + pdata->xyl_y_range_min, pdata->xyl_y_range_max); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_light_xyl_range_get), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_light_xyl_range_get)); + } +#endif + } + break; + default: + break; + } + + return 0; +} + +static int32_t light_lc_client_data(const mesh_model_info_p pmodel_info, + uint32_t type, void *pargs) +{ + UNUSED(pmodel_info); + switch (type) + { + case LIGHT_LC_CLIENT_MODE_STATUS: + { + light_lc_client_mode_status_t *pdata = pargs; + data_uart_debug("light lc client receive: src %d, mode %d\r\n", pdata->src, pdata->mode); + } + break; + case LIGHT_LC_CLIENT_OM_STATUS: + { + light_lc_client_om_status_t *pdata = pargs; + data_uart_debug("light lc client receive: src %d, occupancy mode %d\r\n", pdata->src, pdata->mode); + } + break; + case LIGHT_LC_CLIENT_LIGHT_ON_OFF_STATUS: + { + light_lc_client_light_on_off_status_t *pdata = pargs; + if (pdata->optional) + { + data_uart_debug("light lc client receive: src %d, present on off %d, target on off %d, remain time step(%d) resolution(%d)\r\n", + pdata->src, + pdata->present_on_off, + pdata->target_on_off, + pdata->remaining_time.num_steps, + pdata->remaining_time.step_resolution); + } + else + { + data_uart_debug("light lc client receive: src %d, present on off %d\r\n", + pdata->src, pdata->present_on_off); + } + } + break; + case LIGHT_LC_CLIENT_PROPERTY_STATUS: + { + light_lc_client_property_status_t *pdata = pargs; + data_uart_debug("light lc client receive: src %d, property id 0x%x, property value %d", + pdata->src, pdata->property_id, pdata->property_value); + } + break; + default: + break; + } + + return 0; +} +void light_client_models_init(void) +{ + light_cwrgb_client.model_receive = light_cwrgb_client_receive; + light_cwrgb_client_reg(0, &light_cwrgb_client); + + light_lightness_client.model_data_cb = light_lightness_client_data; + light_lightness_client_reg(0, &light_lightness_client); + + light_ctl_client.model_data_cb = light_ctl_client_data; + light_ctl_client_reg(0, &light_ctl_client); + + light_hsl_client.model_data_cb = light_hsl_client_data; + light_hsl_client_reg(0, &light_hsl_client); + + light_xyl_client.model_data_cb = light_xyl_client_data; + light_xyl_client_reg(0, &light_xyl_client); + + light_lc_client.model_data_cb = light_lc_client_data; + light_lc_client_reg(0, &light_lc_client); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.h new file mode 100644 index 00000000..8da19918 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.h @@ -0,0 +1,61 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file light_client_app.h +* @brief Smart mesh light demo application +* @details +* @author bill +* @date 2018-1-4 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _LIGHT_CLIENT_APP_H +#define _LIGHT_CLIENT_APP_H + +#include "mesh_api.h" +#include "light_cwrgb.h" +#include "light_lightness.h" +#include "light_ctl.h" +#include "light_hsl.h" +#include "light_xyl.h" +#include "light_lc.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_CLIENTS_APP + * @{ + */ + +/** + * @defgroup Light_Clients_Exported_Types Light Clients Exported Types + * @brief + * @{ + */ +extern mesh_model_info_t light_cwrgb_client; +extern mesh_model_info_t light_lightness_client; +extern mesh_model_info_t light_ctl_client; +extern mesh_model_info_t light_hsl_client; +extern mesh_model_info_t light_xyl_client; +extern mesh_model_info_t light_lc_client; +/** @} */ + +/** + * @defgroup Light_Clients_Exported_Functions Light Clients Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize light client models + */ +void light_client_models_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_CLIENT_APP_H */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.c new file mode 100644 index 00000000..50326267 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.c @@ -0,0 +1,758 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file light_server_app.c + * @brief Source file for light client application. + * @details User command interfaces. + * @author + * @date 2020-3-25 + * @version v1.0 + * ************************************************************************************* + */ + +#include "light_server_app.h" + +mesh_model_info_t lighting_lightness_server_model; +mesh_model_info_t lighting_lightness_setup_server_model; +mesh_model_info_t lighting_ctl_server_model; +mesh_model_info_t lighting_ctl_setup_server_model; +mesh_model_info_t lighting_ctl_temperature_server_model; +mesh_model_info_t lighting_hsl_server_model; +mesh_model_info_t lighting_hsl_hue_server_model; +mesh_model_info_t lighting_hsl_saturation_server_model; +mesh_model_info_t lighting_hsl_setup_server_model; +mesh_model_info_t lighting_xyl_server_model; +mesh_model_info_t lighting_xyl_setup_server_model; + + +uint16_t cur_lightness = 0; +uint16_t cur_linear_lightness = 0; +uint16_t default_lightness = 0; +uint16_t last_lightness = 0; + +light_lightness_server_get_range_t lightness_range = {0}; +generic_transition_time_t lightness_transition_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; +light_lightness_server_set_t lightness_set_buffer = {0}; +light_lightness_server_set_t linear_lightness_setting_buffer = {0}; + +light_ctl_server_get_t cur_light_ctl = {0}; +light_ctl_server_get_default_t default_light_ctl = {0}; +light_ctl_server_get_temperature_range_t light_ctl_temperature_range = {0}; +generic_transition_time_t light_ctl_trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; +light_ctl_server_set_t light_ctl_set_buffer = {0}; +light_ctl_server_get_temperature_t light_ctl_temperature = {0}; +light_ctl_server_set_temperature_t light_ctl_temperature_buffer = {0}; +light_ctl_server_set_temperature_range_t light_ctl_temperature_set_range_buffer = {0}; +light_ctl_server_set_default_t light_ctl_default = {0}; + +light_hsl_server_get_t cur_light_hsl = {0}; +light_hsl_server_get_default_t default_light_hsl = {0}; +light_hsl_server_get_range_t light_hsl_range = {0}; +generic_transition_time_t light_hsl_trans_time = {0}; +light_hsl_server_set_t light_hsl_trans_set_buffer = {0}; + +light_hsl_server_get_hue_t cur_light_hsl_hue = {0}; +light_hsl_server_set_hue_t light_hsl_hue_set_buffer = {0}; + +light_hsl_server_get_saturation_t cur_light_hsl_saturation = {0}; +light_hsl_server_set_saturation_t light_hsl_trans_set_saturation_buffer = {0}; + +light_hsl_server_set_default_t light_hsl_default = {0}; +light_hsl_server_set_range_t light_hsl_set_range_buffer = {0}; + +light_xyl_server_get_t cur_light_xyl = {0}; +light_xyl_server_get_default_t default_light_xyl = {0}; +light_xyl_server_get_range_t light_xyl_range = {0}; +generic_transition_time_t light_xyl_trans_time = {0}; + +light_xyl_server_set_t light_xyl_set_buffer = {0}; +light_xyl_server_set_default_t light_xyl_default = {0}; +light_xyl_server_set_range_t light_xyl_set_range_buffer = {0}; + + + +static int32_t lighting_lightness_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_LIGHTNESS_SERVER_GET: + { + light_lightness_server_get_t *p_get_data = NULL; + p_get_data = (light_lightness_server_get_t *)pargs; + if (p_get_data) { + p_get_data->lightness = cur_lightness; + } + data_uart_debug("light lightness server receive: lightness %d \r\n", cur_lightness); + } + break; + case LIGHT_LIGHTNESS_SERVER_GET_LINEAR: + { + light_lightness_server_get_t *p_get_data = NULL; + p_get_data = (light_lightness_server_get_t *)pargs; + if (p_get_data) { + p_get_data->lightness = cur_linear_lightness; + } + data_uart_debug("light lightness server receive: linear lightness %d \r\n", cur_linear_lightness); + } + break; + case LIGHT_LIGHTNESS_SERVER_GET_DEFAULT: + { + light_lightness_server_get_t *p_get_data = NULL; + p_get_data = (light_lightness_server_get_t *)pargs; + if (p_get_data) { + p_get_data->lightness = default_lightness; + } + data_uart_debug("light lightness server receive: default lightness %d \r\n", default_lightness); + } + break; + case LIGHT_LIGHTNESS_SERVER_GET_LAST: + { + light_lightness_server_get_t *p_get_data = NULL; + p_get_data = (light_lightness_server_get_t *)pargs; + if (p_get_data) { + p_get_data->lightness = last_lightness; + } + data_uart_debug("light lightness server receive: last lightness %d \r\n", last_lightness); + } + break; + case LIGHT_LIGHTNESS_SERVER_GET_RANGE: + { + light_lightness_server_get_range_t *p_get_data = NULL; + p_get_data = (light_lightness_server_get_range_t *)pargs; + if (p_get_data) { + p_get_data->range_max = lightness_range.range_max; + p_get_data->range_min = lightness_range.range_min; + } + data_uart_debug("light lightness server receive: lightness_max %d, lightness_min %d \r\n", + lightness_range.range_max, + lightness_range.range_min); + } + break; + case LIGHT_LIGHTNESS_SERVER_GET_DEFAULT_TRANSITION_TIME: + { + } + break; + case LIGHT_LIGHTNESS_SERVER_SET: + { + light_lightness_server_set_t *p_get_data = NULL; + p_get_data = (light_lightness_server_set_t *)pargs; + if (p_get_data) { + lightness_set_buffer.lightness = p_get_data->lightness; + lightness_set_buffer.total_time = p_get_data->total_time; + lightness_set_buffer.remaining_time = p_get_data->remaining_time; + } + data_uart_debug("light lightness server receive: set lightness %d, total_time %d, remaining_time %d \r\n", + lightness_set_buffer.lightness, + lightness_set_buffer.total_time, + lightness_set_buffer.remaining_time); + } + break; + case LIGHT_LIGHTNESS_SERVER_SET_LINEAR: + { + light_lightness_server_set_t * p_get_data = NULL; + p_get_data = (light_lightness_server_set_t *)pargs; + if (p_get_data) { + linear_lightness_setting_buffer.lightness = p_get_data->lightness; + linear_lightness_setting_buffer.total_time = p_get_data->total_time; + linear_lightness_setting_buffer.remaining_time = p_get_data->remaining_time; + } + data_uart_debug("light lightness server receive: set linear lightness %d, total_time %d, remaining_time %d \r\n", + linear_lightness_setting_buffer.lightness, + linear_lightness_setting_buffer.total_time, + linear_lightness_setting_buffer.remaining_time); + } + break; + case LIGHT_LIGHTNESS_SERVER_SET_LAST: + { + light_lightness_server_get_t *p_get_data = NULL; + p_get_data = (light_lightness_server_get_t *)pargs; + if (p_get_data) { + last_lightness = p_get_data->lightness; + } + data_uart_debug("light lightness server receive: set last lightness %d \r\n", last_lightness); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_lightness_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_LIGHTNESS_SERVER_SET_DEFAULT: + { + light_lightness_server_set_default_t *p_get_data = NULL; + p_get_data = (light_lightness_server_set_default_t *)pargs; + if (p_get_data) { + default_lightness = p_get_data->lightness; + } + data_uart_debug("light lightness server receive: set default lightness %d \r\n", default_lightness); + } + break; + case LIGHT_LIGHTNESS_SERVER_SET_RANGE: + { + light_lightness_server_set_range_t *p_get_data = NULL; + p_get_data = (light_lightness_server_set_range_t *)pargs; + if (p_get_data) { + lightness_range.range_max = p_get_data->range_max; + lightness_range.range_min = p_get_data->range_min; + } + data_uart_debug("light lightness server receive: set lightness_max %d, lightness_min %d \r\n", + lightness_range.range_max, + lightness_range.range_min); + } + break; + default: + break; + } + + return 0; +} + + +static int32_t lighting_ctl_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_CTL_SERVER_GET: + { + light_ctl_server_get_t *p_get_data = NULL; + p_get_data = (light_ctl_server_get_t *)pargs; + if (p_get_data) { + p_get_data->lightness = cur_light_ctl.lightness; + p_get_data->temperature = cur_light_ctl.temperature; + } + data_uart_debug("lighting ctl server receive: lightness %d, temperature %d \r\n", + cur_light_ctl.lightness, + cur_light_ctl.temperature); + } + break; + case LIGHT_CTL_SERVER_GET_DEFAULT: + { + light_ctl_server_get_default_t *p_get_data = NULL; + p_get_data = (light_ctl_server_get_default_t *)pargs; + if (p_get_data) { + p_get_data->lightness = default_light_ctl.lightness; + p_get_data->temperature = default_light_ctl.temperature; + p_get_data->delta_uv = default_light_ctl.delta_uv; + } + data_uart_debug("lighting ctl server receive: lightness %d, temperature %d, delta_uv %d \r\n", + default_light_ctl.lightness, + default_light_ctl.temperature, + default_light_ctl.delta_uv); + } + break; + case LIGHT_CTL_SERVER_GET_TEMPERATURE_RANGE: + { + light_ctl_server_get_temperature_range_t *p_get_data = NULL; + p_get_data = (light_ctl_server_get_temperature_range_t *)pargs; + if (p_get_data) { + p_get_data->range_max = light_ctl_temperature_range.range_max; + p_get_data->range_min = light_ctl_temperature_range.range_min; + } + data_uart_debug("lighting ctl server receive: temperature range_max %d, range_min %d \r\n", + light_ctl_temperature_range.range_max, + light_ctl_temperature_range.range_min); + } + break; + case LIGHT_CTL_SERVER_GET_DEFAULT_TRANSITION_TIME: + { + } + break; + case LIGHT_CTL_SERVER_SET: + { + light_ctl_server_set_t light_ctl_set_buffer; + light_ctl_server_set_t *p_get_data = NULL; + p_get_data = (light_ctl_server_set_t *)pargs; + if (p_get_data) { + light_ctl_set_buffer.delta_uv = p_get_data->delta_uv; + light_ctl_set_buffer.lightness = p_get_data->lightness; + light_ctl_set_buffer.remaining_time = p_get_data->remaining_time; + light_ctl_set_buffer.temperature = p_get_data->temperature; + light_ctl_set_buffer.total_time = p_get_data->total_time; + } + data_uart_debug("lighting ctl server receive: set delta_uv %d, lightness %d, remaining_time %d, temperature %d, total_time %d \r\n", + light_ctl_set_buffer.delta_uv, + light_ctl_set_buffer.lightness, + light_ctl_set_buffer.remaining_time, + light_ctl_set_buffer.temperature, + light_ctl_set_buffer.total_time); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_ctl_temperature_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_CTL_SERVER_GET_TEMPERATURE: + { + light_ctl_server_get_temperature_t *p_get_data = NULL; + p_get_data = (light_ctl_server_get_temperature_t *)pargs; + if (p_get_data) { + p_get_data->temperature = light_ctl_temperature.temperature; + p_get_data->delta_uv = light_ctl_temperature.delta_uv; + } + data_uart_debug("lighting ctl temperature server receive: set temperature %d, delta_uv %d \r\n", + light_ctl_temperature.temperature, + light_ctl_temperature.delta_uv); + } + break; + case LIGHT_CTL_SERVER_SET_TEMPERATURE: + { + light_ctl_server_set_temperature_t *p_get_data = NULL; + p_get_data = (light_ctl_server_set_temperature_t *)pargs; + if (p_get_data) { + light_ctl_temperature_buffer.temperature = p_get_data->temperature; + light_ctl_temperature_buffer.delta_uv = p_get_data->delta_uv; + light_ctl_temperature_buffer.total_time = p_get_data->total_time; + light_ctl_temperature_buffer.remaining_time = p_get_data->remaining_time; + } + data_uart_debug("lighting ctl temperature server receive: set temperature %d, delta_uv %d, total_time %d, remaining_time %d \r\n", + light_ctl_temperature_buffer.temperature, + light_ctl_temperature_buffer.delta_uv, + light_ctl_temperature_buffer.total_time, + light_ctl_temperature_buffer.remaining_time); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_ctl_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_CTL_SERVER_SET_TEMPERATURE_RANGE: + { + light_ctl_server_set_temperature_range_t *p_get_data = NULL; + p_get_data = (light_ctl_server_set_temperature_range_t *)pargs; + if (p_get_data) { + light_ctl_temperature_set_range_buffer.range_max = p_get_data->range_max; + light_ctl_temperature_set_range_buffer.range_min = p_get_data->range_min; + } + data_uart_debug("lighting ctl setup server receive: set temperature range_max %d, range_min %d \r\n", + light_ctl_temperature_set_range_buffer.range_max, + light_ctl_temperature_set_range_buffer.range_min); + } + break; + case LIGHT_CTL_SERVER_SET_DEFAULT: + { + light_ctl_server_set_default_t *p_get_data = NULL; + p_get_data = (light_ctl_server_set_default_t *)pargs; + if (p_get_data) { + light_ctl_default.delta_uv = p_get_data->delta_uv; + light_ctl_default.lightness = p_get_data->lightness; + light_ctl_default.temperature = p_get_data->temperature; + } + data_uart_debug("lighting ctl setup server receive: set default delta_uv %d, lightness %d, temperature %d \r\n", + light_ctl_default.delta_uv, + light_ctl_default.lightness, + light_ctl_default.temperature); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_hsl_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_HSL_SERVER_GET: + { + light_hsl_server_get_t *p_get_data = NULL; + p_get_data = (light_hsl_server_get_t *)pargs; + if (p_get_data) { + p_get_data->hue = cur_light_hsl.hue; + p_get_data->lightness = cur_light_hsl.lightness; + p_get_data->saturation = cur_light_hsl.saturation; + } + data_uart_debug("lighting hsl server receive: hue %d, lightness %d, saturation %d \r\n", + cur_light_hsl.hue, + cur_light_hsl.lightness, + cur_light_hsl.saturation); + } + break; + case LIGHT_HSL_SERVER_GET_DEFAULT: + { + light_hsl_server_get_default_t *p_get_data = NULL; + p_get_data = (light_hsl_server_get_default_t *)pargs; + if (p_get_data) { + p_get_data->hue = default_light_hsl.hue; + p_get_data->lightness = default_light_hsl.lightness; + p_get_data->saturation = default_light_hsl.saturation; + } + data_uart_debug("lighting hsl server receive: default hue %d, lightness %d, saturation %d \r\n", + default_light_hsl.hue, + default_light_hsl.lightness, + default_light_hsl.saturation); + } + break; + case LIGHT_HSL_SERVER_GET_RANGE: + { + light_hsl_server_get_range_t *p_get_data = NULL; + p_get_data = (light_hsl_server_get_range_t *)pargs; + if (p_get_data) { + p_get_data->hue_range_min = light_hsl_range.hue_range_min; + p_get_data->hue_range_max = light_hsl_range.hue_range_max; + p_get_data->saturation_range_min = light_hsl_range.saturation_range_min; + p_get_data->saturation_range_max = light_hsl_range.saturation_range_max; + } + data_uart_debug("lighting hsl server receive: hue_range_min %d, hue_range_max %d, saturation_range_min %d, saturation_range_max %d \r\n", + light_hsl_range.hue_range_min, + light_hsl_range.hue_range_max, + light_hsl_range.saturation_range_min, + light_hsl_range.saturation_range_max); + } + break; + case LIGHT_HSL_SERVER_GET_DEFAULT_TRANSITION_TIME: + { + } + break; + case LIGHT_HSL_SERVER_SET: + { + light_hsl_server_set_t *p_get_data = NULL; + p_get_data = (light_hsl_server_set_t *)pargs; + if (p_get_data) { + light_hsl_trans_set_buffer.hue = p_get_data->hue; + light_hsl_trans_set_buffer.lightness = p_get_data->lightness; + light_hsl_trans_set_buffer.remaining_time = p_get_data->remaining_time; + light_hsl_trans_set_buffer.saturation = p_get_data->saturation; + light_hsl_trans_set_buffer.total_time = p_get_data->total_time; + } + data_uart_debug("lighting hsl server receive: set hue %d, lightness %d, remaining_time %d, saturation %d, total_time %d \r\n", + light_hsl_trans_set_buffer.hue, + light_hsl_trans_set_buffer.lightness, + light_hsl_trans_set_buffer.remaining_time, + light_hsl_trans_set_buffer.saturation, + light_hsl_trans_set_buffer.total_time); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_hsl_hue_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_HSL_SERVER_GET_HUE: + { + light_hsl_server_get_hue_t *p_get_data = NULL; + p_get_data = (light_hsl_server_get_hue_t *)pargs; + if (p_get_data) { + p_get_data->hue = cur_light_hsl_hue.hue; + } + data_uart_debug("lighting hsl hue server receive: hue %d \r\n", cur_light_hsl_hue.hue); + } + break; + case LIGHT_HSL_SERVER_SET_HUE: + { + light_hsl_server_set_hue_t *p_get_data = NULL; + p_get_data = (light_hsl_server_set_hue_t *)pargs; + if (p_get_data) { + light_hsl_hue_set_buffer.hue = p_get_data->hue; + light_hsl_hue_set_buffer.remaining_time = p_get_data->remaining_time; + light_hsl_hue_set_buffer.total_time = p_get_data->total_time; + } + data_uart_debug("lighting hsl hue server receive: set hue %d, remaining_time %d, total_time %d \r\n", + light_hsl_hue_set_buffer.hue, + light_hsl_hue_set_buffer.remaining_time, + light_hsl_hue_set_buffer.total_time); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_hsl_saturation_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_HSL_SERVER_GET_SATURATION: + { + light_hsl_server_get_saturation_t *p_get_data = NULL; + p_get_data = (light_hsl_server_get_saturation_t *)pargs; + if (p_get_data) { + p_get_data->saturation = cur_light_hsl_saturation.saturation; + } + data_uart_debug("lighting hsl saturation server receive: saturation %d \r\n", cur_light_hsl_saturation.saturation); + } + break; + case LIGHT_HSL_SERVER_SET_SATURATION: + { + light_hsl_server_set_saturation_t *p_get_data = NULL; + p_get_data = (light_hsl_server_set_saturation_t *)pargs; + if (p_get_data) { + light_hsl_trans_set_saturation_buffer.saturation = p_get_data->saturation; + light_hsl_trans_set_saturation_buffer.remaining_time = p_get_data->remaining_time; + light_hsl_trans_set_saturation_buffer.total_time = p_get_data->total_time; + } + data_uart_debug("lighting hsl saturation server receive: set saturation %d, remaining_time %d, total_time %d \r\n", + light_hsl_trans_set_saturation_buffer.saturation, + light_hsl_trans_set_saturation_buffer.remaining_time, + light_hsl_trans_set_saturation_buffer.total_time); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_hsl_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_HSL_SERVER_SET_DEFAULT: + { + light_hsl_server_set_default_t *p_get_data = NULL; + p_get_data = (light_hsl_server_set_default_t *)pargs; + if (p_get_data) { + light_hsl_default.lightness = p_get_data->lightness; + light_hsl_default.hue = p_get_data->hue; + light_hsl_default.saturation = p_get_data->saturation; + } + data_uart_debug("lighting hsl setup server receive: set default lightness %d, hue %d, saturation %d \r\n", + light_hsl_default.lightness, + light_hsl_default.hue, + light_hsl_default.saturation); + } + break; + case LIGHT_HSL_SERVER_SET_RANGE: + { + light_hsl_server_set_range_t *p_get_data = NULL; + p_get_data = (light_hsl_server_set_range_t *)pargs; + if (p_get_data) { + light_hsl_set_range_buffer.hue_range_min = p_get_data->hue_range_min; + light_hsl_set_range_buffer.hue_range_max = p_get_data->hue_range_max; + light_hsl_set_range_buffer.saturation_range_min = p_get_data->saturation_range_min; + light_hsl_set_range_buffer.saturation_range_max = p_get_data->saturation_range_max; + } + data_uart_debug("lighting hsl setup server receive: set hue_range_min %d, hue_range_max %d, saturation_range_min %d, saturation_range_max %d \r\n", + light_hsl_set_range_buffer.hue_range_min, + light_hsl_set_range_buffer.hue_range_max, + light_hsl_set_range_buffer.saturation_range_min, + light_hsl_set_range_buffer.saturation_range_max); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_xyl_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_XYL_SERVER_GET: + { + light_xyl_server_get_t *p_get_data = NULL; + p_get_data = (light_xyl_server_get_t *)pargs; + if (p_get_data) { + p_get_data->xyl_lightness = cur_light_xyl.xyl_lightness; + p_get_data->xyl_x = cur_light_xyl.xyl_x; + p_get_data->xyl_y = cur_light_xyl.xyl_y; + } + data_uart_debug("lighting xyl server receive: xyl_lightness %d, xyl_x %d, xyl_y %d \r\n", + cur_light_xyl.xyl_lightness, + cur_light_xyl.xyl_x, + cur_light_xyl.xyl_y); + } + break; + case LIGHT_XYL_SERVER_GET_DEFAULT: + { + light_xyl_server_get_default_t *p_get_data = NULL; + p_get_data = (light_xyl_server_get_default_t *)pargs; + if (p_get_data) { + p_get_data->xyl_lightness = default_light_xyl.xyl_lightness; + p_get_data->xyl_x = default_light_xyl.xyl_x; + p_get_data->xyl_y = default_light_xyl.xyl_y; + } + data_uart_debug("lighting xyl server receive: default xyl_lightness %d, xyl_x %d, xyl_y %d \r\n", + default_light_xyl.xyl_lightness, + default_light_xyl.xyl_x, + default_light_xyl.xyl_y); + } + break; + case LIGHT_XYL_SERVER_GET_RANGE: + { + light_xyl_server_get_range_t *p_get_data = NULL; + p_get_data = (light_xyl_server_get_range_t *)pargs; + if (p_get_data) { + p_get_data->xyl_x_range_max = light_xyl_range.xyl_x_range_max; + p_get_data->xyl_x_range_min = light_xyl_range.xyl_x_range_min; + p_get_data->xyl_y_range_max = light_xyl_range.xyl_y_range_max; + p_get_data->xyl_y_range_min = light_xyl_range.xyl_y_range_min; + } + data_uart_debug("lighting xyl server receive: xyl_x_range_max %d, xyl_x_range_min %d, xyl_y_range_max %d, xyl_y_range_min %d \r\n", + light_xyl_range.xyl_x_range_max, + light_xyl_range.xyl_x_range_min, + light_xyl_range.xyl_y_range_max, + light_xyl_range.xyl_y_range_min); + } + break; + case LIGHT_XYL_SERVER_GET_DEFAULT_TRANSITION_TIME: + { + } + break; + case LIGHT_XYL_SERVER_SET: + { + light_xyl_server_set_t light_xyl_set_buffer; + light_xyl_server_set_t *p_get_data = NULL; + p_get_data = (light_xyl_server_set_t *)pargs; + if (p_get_data) { + light_xyl_set_buffer.xyl = p_get_data->xyl; + light_xyl_set_buffer.total_time = p_get_data->total_time; + light_xyl_set_buffer.remaining_time = p_get_data->remaining_time; + } + data_uart_debug("lighting xyl server receive: set xyl %d, total_time %d, remaining_time %d \r\n", + light_xyl_set_buffer.xyl, + light_xyl_set_buffer.total_time, + light_xyl_set_buffer.remaining_time); + } + break; + default: + break; + } + + return 0; +} + +static int32_t lighting_xyl_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case LIGHT_XYL_SERVER_SET_DEFAULT: + { + light_xyl_server_set_default_t *p_get_data = NULL; + p_get_data = (light_xyl_server_set_default_t *)pargs; + if (p_get_data) { + p_get_data->xyl_lightness = light_xyl_default.xyl_lightness; + p_get_data->xyl_x = light_xyl_default.xyl_x; + p_get_data->xyl_y = light_xyl_default.xyl_y; + } + data_uart_debug("lighting xyl server receive: default xyl_lightness %d, xyl_x %d, xyl_y %d \r\n", + light_xyl_default.xyl_lightness, + light_xyl_default.xyl_x, + light_xyl_default.xyl_y); + } + break; + case LIGHT_XYL_SERVER_SET_RANGE: + { + light_xyl_server_set_range_t *p_get_data = NULL; + p_get_data = (light_xyl_server_set_range_t *)pargs; + if (p_get_data) { + light_xyl_set_range_buffer.xyl_x_range_max = p_get_data->xyl_x_range_max; + light_xyl_set_range_buffer.xyl_x_range_min = p_get_data->xyl_x_range_min; + light_xyl_set_range_buffer.xyl_y_range_max = p_get_data->xyl_y_range_max; + light_xyl_set_range_buffer.xyl_y_range_min = p_get_data->xyl_y_range_min; + } + data_uart_debug("lighting xyl setup server receive: set xyl_x_range_max %d, xyl_x_range_min %d, xyl_y_range_max %d, xyl_y_range_min %d \r\n", + light_xyl_set_range_buffer.xyl_x_range_max, + light_xyl_set_range_buffer.xyl_x_range_min, + light_xyl_set_range_buffer.xyl_y_range_max, + light_xyl_set_range_buffer.xyl_y_range_min); + } + break; + default: + break; + } + + return 0; +} + +void light_server_models_init(void) +{ + lighting_lightness_server_model.model_data_cb = lighting_lightness_server_data; + light_lightness_server_reg(0, &lighting_lightness_server_model); + + lighting_lightness_setup_server_model.model_data_cb = lighting_lightness_setup_server_data; + light_lightness_setup_server_reg(0, &lighting_lightness_setup_server_model); + + lighting_ctl_server_model.model_data_cb = lighting_ctl_server_data; + light_ctl_server_reg(0, &lighting_ctl_server_model); + + lighting_ctl_temperature_server_model.model_data_cb = lighting_ctl_temperature_server_data; + light_ctl_temperature_server_reg(0, &lighting_ctl_temperature_server_model); + + lighting_ctl_setup_server_model.model_data_cb = lighting_ctl_setup_server_data; + light_ctl_setup_server_reg(0, &lighting_ctl_setup_server_model); + + lighting_hsl_server_model.model_data_cb = lighting_hsl_server_data; + light_hsl_server_reg(0, &lighting_hsl_server_model); + + lighting_hsl_hue_server_model.model_data_cb = lighting_hsl_hue_server_data; + light_hsl_hue_server_reg(0, &lighting_hsl_hue_server_model); + + lighting_hsl_saturation_server_model.model_data_cb = lighting_hsl_saturation_server_data; + light_hsl_saturation_server_reg(0, &lighting_hsl_saturation_server_model); + + lighting_hsl_setup_server_model.model_data_cb = lighting_hsl_setup_server_data; + light_hsl_setup_server_reg(0, &lighting_hsl_setup_server_model); + + lighting_xyl_server_model.model_data_cb = lighting_xyl_server_data; + light_xyl_server_reg(0, &lighting_xyl_server_model); + + lighting_xyl_setup_server_model.model_data_cb = lighting_xyl_setup_server_data; + light_xyl_setup_server_reg(0, &lighting_xyl_setup_server_model); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.h new file mode 100644 index 00000000..e060f626 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.h @@ -0,0 +1,44 @@ +/** +********************************************************************************************************* +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file light_server_app.h +* @brief Smart mesh light demo application +* @details +* @author +* @date 2020-3-25 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _LIGHT_SERVER_APP_H +#define _LIGHT_SERVER_APP_H + +#include "light_lightness.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif +#include "light_ctl.h" +#include "light_hsl.h" +#include "light_lightness.h" +#include "light_xyl.h" + +BEGIN_DECLS +/** + * @defgroup Light_Clients_Exported_Functions Light Clients Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize light server models + */ +void light_server_models_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_CLIENT_APP_H */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c new file mode 100644 index 00000000..b89cf2fd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c @@ -0,0 +1,169 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ping_app.c + * @brief Source file for ping app. + * @details Data types and external functions declaration. + * @author bill + * @date 2018-4-2 + * @version v1.0 + * ************************************************************************************* + */ + +/* Add Includes here */ +#include +#include "trace.h" +#include "app_msg.h" +#include "ping_app.h" + +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER +extern void *bt_mesh_provisioner_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_io_queue_handle; //!< IO queue handle +#elif defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE +extern void *bt_mesh_device_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_device_io_queue_handle; //!< IO queue handle +#elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +extern void *bt_mesh_device_matter_evt_queue_handle; +extern void *bt_mesh_device_matter_io_queue_handle; +#else +extern void *bt_mesh_device_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_device_multiple_profile_io_queue_handle; //!< IO queue handle +#endif +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +extern void *bt_mesh_provisioner_ota_client_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_ota_client_io_queue_handle; //!< IO queue handle +#else +extern void *bt_mesh_provisioner_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_multiple_profile_io_queue_handle; //!< IO queue handle +#endif +#endif +static plt_timer_t pong_timer; +static uint16_t pong_dst; +static uint8_t pong_ttl; +static uint8_t pong_key_index; +static uint8_t pong_hops_forward; +static ping_pong_type_t pong_type; +static uint16_t pong_delay; + +static void ping_app_timeout_cb(void *ptimer) +{ + /* avoid gcc compile warning */ + (void)ptimer; + + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = PING_APP_TIMEOUT_MSG; +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER + if (os_msg_send(bt_mesh_provisioner_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_evt_queue_handle, &event, 0) == false) + { + } +#elif defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE + if (os_msg_send(bt_mesh_device_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_evt_queue_handle, &event, 0) == false) + { + } +#elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER + if (os_msg_send(bt_mesh_device_matter_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_matter_evt_queue_handle, &event, 0) == false) + { + } +#else + if (os_msg_send(bt_mesh_device_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +#endif +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT + if (os_msg_send(bt_mesh_provisioner_ota_client_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) + { + } +#else + if (os_msg_send(bt_mesh_provisioner_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +#endif +#endif +} + +void ping_app_handle_timeout(void) +{ + plt_timer_delete(pong_timer, 0); + pong_timer = 0; + printi("pong_timeout_process: delayed %d0ms pong right now!", pong_delay); + switch (pong_type) + { + case PING_PONG_TYPE_TRANSPORT: + trans_pong(pong_dst, pong_ttl, pong_key_index, pong_hops_forward, pong_delay); + break; + case PING_PONG_TYPE_ACCESS: + pong(pong_dst, pong_ttl, pong_key_index, pong_hops_forward, pong_delay); + break; + case PING_PONG_TYPE_ACCESS_BIG: + big_pong(pong_dst, pong_ttl, pong_key_index, pong_hops_forward, pong_delay); + break; + default: + break; + } +} + +void ping_app_ping_cb(uint16_t src, uint16_t dst, uint8_t hops_forward, ping_pong_type_t type, + uint8_t init_ttl, uint8_t key_index, uint16_t pong_max_delay) +{ + /* avoid gcc compile warning */ + (void)dst; + + if (pong_max_delay == 0 || pong_timer) + { + switch (type) + { + case PING_PONG_TYPE_TRANSPORT: + trans_pong(src, init_ttl, key_index, hops_forward, 0); + break; + case PING_PONG_TYPE_ACCESS: + pong(src, init_ttl, key_index, hops_forward, 0); + break; + case PING_PONG_TYPE_ACCESS_BIG: + big_pong(src, init_ttl, key_index, hops_forward, 0); + break; + default: + break; + } + } + else + { + pong_dst = src; + pong_ttl = init_ttl; + pong_key_index = key_index; + pong_hops_forward = hops_forward; + pong_type = type; + uint16_t rand_delay; + plt_rand((uint8_t *)&rand_delay, sizeof(rand_delay)); + rand_delay = ((rand_delay * pong_max_delay) >> 16) + 1; + pong_delay = rand_delay; + pong_timer = plt_timer_create("pong", rand_delay * 10, false, 0, ping_app_timeout_cb); + if (pong_timer) + { + plt_timer_start(pong_timer, 0); + } + } +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.h new file mode 100644 index 00000000..bf2ee53f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.h @@ -0,0 +1,53 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ping_app.h + * @brief Head file for ping app. + * @details Data types and external functions declaration. + * @author bill + * @date 2018-4-2 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PING_APP_H +#define _PING_APP_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "ping.h" + +/** + * @addtogroup PING_SERVER_APP + * @{ + */ + +/** + * @defgroup Ping_Exported_Macros Ping Exported Macros + * @brief + * @{ + */ +#define PING_APP_TIMEOUT_MSG 100 +/** @} */ + +/** + * @defgroup Ping_Exported_Functions Ping Exported Functions + * @brief + * @{ + */ +void ping_app_ping_cb(uint16_t src, uint16_t dst, uint8_t hops_forward, ping_pong_type_t type, + uint8_t init_ttl, uint8_t key_index, uint16_t pong_max_delay); +void ping_app_handle_timeout(void); +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _PING_APP_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.c new file mode 100644 index 00000000..c730219f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.c @@ -0,0 +1,145 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file rm_prov_client_app.c +* @brief remote provision application +* @details +* @author hector huang +* @date 2020-11-30 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#include "mesh_api.h" +#include "rmt_prov_client_app.h" +#include "remote_provisioning.h" +#include "generic_types.h" +#include "bt_mesh_provisioner_api.h" + +#if MESH_RPR + +static int32_t rmt_prov_client_data(const mesh_model_info_p pmodel_info, uint32_t type, + void *pargs) +{ + int32_t ret = MODEL_SUCCESS; + switch (type) + { + case RMT_PROV_CLIENT_SCAN_CAPS_STATUS: + { + rmt_prov_client_scan_caps_status_t *pdata = (rmt_prov_client_scan_caps_status_t *)pargs; + data_uart_debug("rmt_prov_scan_caps_status: src 0x%04x, max scanned items %d, support active scan %d\r\n", + pdata->src, pdata->max_scanned_items, pdata->support_active_scan); + } + break; + case RMT_PROV_CLIENT_SCAN_STATUS: + { + rmt_prov_client_scan_status_t *pdata = (rmt_prov_client_scan_status_t *)pargs; + data_uart_debug("rmt_prov_scan_status: src 0x%04x, status %d, scan state %d, scanned items limit %d, timeout %d\r\n", + pdata->src, pdata->status, pdata->scan_state, pdata->scanned_items_limit, pdata->timeout); + } + break; + case RMT_PROV_CLIENT_SCAN_REPORT: + { + rmt_prov_client_scan_report_t *pdata = (rmt_prov_client_scan_report_t *)pargs; + uint16_t oob = 0xffff; + if (pdata->poob) + { + oob = (pdata->poob[1] << 8) + pdata->poob[0]; + } + uint32_t uri_hash = 0; + if (pdata->puri_hash) + { + uri_hash = (pdata->puri_hash[3] << 24) + (pdata->puri_hash[2] << 16) + + (pdata->puri_hash[1] << 8) + pdata->puri_hash[0]; + } + data_uart_debug("rmt_prov_scan_report: rssi %d, oob %d, uri hash %d, uuid ", + pdata->rssi, oob, uri_hash); + data_uart_dump(pdata->uuid, 16); + } + break; + case RMT_PROV_CLIENT_EXTENED_SCAN_REPORT: + { + rmt_prov_client_extened_scan_report_t *pdata = (rmt_prov_client_extened_scan_report_t *)pargs; + uint16_t oob = 0xffff; + if (pdata->poob) + { + oob = (pdata->poob[1] << 8) + pdata->poob[0]; + } + data_uart_debug("rmt_prov_extened_scan_report: oob %d, uuid ", oob); + data_uart_dump(pdata->uuid, 16); + if (pdata->adv_structs_len > 0) + { + data_uart_debug("rmt_prov_extened_scan_report: adv structs "); + data_uart_dump(pdata->padv_structs, pdata->adv_structs_len); + } + } + break; + case RMT_PROV_CLIENT_LINK_STATUS: + { + rmt_prov_client_link_status_t *pdata = (rmt_prov_client_link_status_t *)pargs; + data_uart_debug("rmt_prov_link_status: src 0x%04x, status %d, link state %d\r\n", + pdata->src, pdata->status, pdata->link_state); + } + break; + case RMT_PROV_CLIENT_LINK_REPORT: + { + rmt_prov_client_link_report_t *pdata = (rmt_prov_client_link_report_t *)pargs; + data_uart_debug("rmt_prov_link_report: src 0x%04x, status %d, link state %d, reason %d\r\n", + pdata->src, pdata->status, pdata->link_state, pdata->preason ? *pdata->preason : -1); + if ((pdata->status == RMT_PROV_SUCCESS) && (pdata->link_state == RMT_PROV_LINK_STATE_LINK_ACTIVE)) + { + data_uart_debug("\r\nLink Open Success!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_rmt_prov_client_link_open_prov), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_rmt_prov_client_link_open_prov)); + } +#endif + break; + } else if ((pdata->status != RMT_PROV_SUCCESS) && (pdata->status < RMT_PROV_LINK_CLOSED_BY_DEVICE)) + { + data_uart_debug("\r\nLink Open Fail!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_rmt_prov_client_link_open_prov), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_rmt_prov_client_link_open_prov)); + } +#endif + break; + } + + if ((pdata->status >= RMT_PROV_LINK_CLOSED_BY_DEVICE) && + (pdata->status <= RMT_PROV_LINK_CLOSED_BY_CLIENT)) + { + data_uart_debug("\r\nClose Link Success!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_rmt_prov_client_close), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_rmt_prov_client_close)); + } +#endif + break; + } else if ((pdata->status >= RMT_PROV_LINK_CLOSED_AS_CANNOT_RECEIVE_PDU) && + (pdata->status <= RMT_PROV_LINK_CLOSED_AS_CANNOT_DELIVER_PDU_REPORT)) + { + data_uart_debug("\r\nClose Link Fail!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_rmt_prov_client_close), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_rmt_prov_client_close)); + } +#endif + break; + } + } + break; + default: + break; + } + + return ret; +} + +void rmt_prov_client_init(void) +{ + /* register remote client model */ + rmt_prov_client_reg(0, rmt_prov_client_data); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.h new file mode 100644 index 00000000..70154afd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.h @@ -0,0 +1,36 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file rmt_prov_client_app.h +* @brief remote provision application +* @details +* @author hector_huang +* @date 2020-11-30 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _RMT_PROV_CLIENT_APP_H +#define _RMT_PROV_CLIENT_APP_H + +#include "platform_types.h" + +BEGIN_DECLS + +/** + * @addtogroup RMT_PROV_CLIENT_APP + * @{ + */ + +/** + * @brief initialize remote provision client model + */ +void rmt_prov_client_init(void); +/** @} */ + + +END_DECLS + +#endif /** _RMT_PROV_CLIENT_APP_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.c new file mode 100644 index 00000000..b7339c64 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.c @@ -0,0 +1,145 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file scene_server_app.c + * @brief Source file for scene client application. + * @details User command interfaces. + * @author + * @date 2020-4-1 + * @version v1.0 + * ************************************************************************************* + */ +#include "scene_server_app.h" +#include "scene.h" + +uint16_t cur_scene = 0; +uint16_t deleted_scene = 0; +scene_status_code_t cur_status = 0; + +scene_server_recall_t cur_scene_recall = {0}; +generic_transition_time_t scene_trans_time = {0}; +scene_server_store_t scene_store_buffer = {0}; + +mesh_model_info_t scene_server_model; +mesh_model_info_t scene_setup_server_model; + +static scene_storage_memory_t scene_storage_memory[] = +{ + {3, NULL}, + {4, NULL}, + {5, NULL}, + {6, NULL} +}; + +static int32_t scene_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case SCENE_SERVER_GET: + { + scene_server_get_t *p_get_data = NULL; + + p_get_data = (scene_server_get_t *)pargs; + + if (p_get_data) { + p_get_data->current_scene = cur_scene; + } + data_uart_debug("scene server receive: current_scene = %d\r\n", cur_scene); + } + break; + case SCENE_SERVER_RECALL: + { + scene_server_recall_t *p_get_data = NULL; + p_get_data = (scene_server_recall_t *)pargs; + + if (p_get_data) { + p_get_data->scene_number = cur_scene_recall.scene_number; + (p_get_data->total_time).num_steps = cur_scene_recall.total_time.num_steps; + (p_get_data->total_time).step_resolution = cur_scene_recall.total_time.step_resolution; + (p_get_data->remaining_time).num_steps = cur_scene_recall.remaining_time.num_steps; + (p_get_data->remaining_time).step_resolution = cur_scene_recall.remaining_time.step_resolution; + } + data_uart_debug( + "scene server receive: scene_number = %d, total time = step(%d), resolution(%d)," \ + "remaining time = step(%d), resolution(%d)\r\n", \ + cur_scene_recall.scene_number, cur_scene_recall.total_time.num_steps, cur_scene_recall.total_time.step_resolution, \ + cur_scene_recall.remaining_time.num_steps, cur_scene_recall.remaining_time.step_resolution); + } + break; + case SCENE_SERVER_GET_DEFAULT_TRANSITION_TIME: + { + } + break; + case SCENE_SERVER_GET_REGISTER_STATUS: + { + scene_server_get_register_status_t *p_get_data = NULL; + p_get_data = (scene_server_get_register_status_t *)pargs; + + if (p_get_data) { + p_get_data->status = cur_status; + } + data_uart_debug("scene server receive: status = %d\r\n", cur_status); + } + break; + default: + break; + } + + return 0; +} + +static int32_t scene_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case SCENE_SERVER_STORE: + { + scene_server_store_t *p_get_data = NULL; + p_get_data = (scene_server_store_t *)pargs; + + if (p_get_data) { + scene_store_buffer.status = p_get_data->status; + scene_store_buffer.scene_number = p_get_data->scene_number; + } + data_uart_debug("scene setup server receive: status = %d, scene number = %d\r\n", \ + scene_store_buffer.status, scene_store_buffer.scene_number); + } + break; + case SCENE_SERVER_DELETE: + { + scene_server_delete_t *p_get_data = pargs; + p_get_data = (scene_server_delete_t *)pargs; + + if (p_get_data) { + p_get_data->scene_number = deleted_scene; + } + data_uart_debug("scene setup server receive: scene number = %d\r\n", deleted_scene); + } + break; + default: + break; + } + + return 0; +} + +void scene_server_model_init(void) +{ + scene_setup_server_model.model_data_cb = scene_setup_server_data; + scene_setup_server_reg(0, &scene_setup_server_model); + + scene_server_model.model_data_cb = scene_server_data; + scene_server_reg(0, &scene_server_model); + + scene_server_set_storage_memory(&scene_server_model, scene_storage_memory, + sizeof(scene_storage_memory) / sizeof(scene_storage_memory_t)); + scene_setup_server_set_storage_memory(&scene_setup_server_model, scene_storage_memory, + sizeof(scene_storage_memory) / sizeof(scene_storage_memory_t)); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.h new file mode 100644 index 00000000..2a1ccee0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.h @@ -0,0 +1,34 @@ +/** +********************************************************************************************************* +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file scene_server_app.h +* @brief Smart mesh scene demo application +* @details +* @author +* @date 2020-4-1 +* @version v1.0 +* ********************************************************************************************************* +*/ +#ifndef _SCENE_SERVER_APP_H_ +#define _SCENE_SERVER_APP_H_ + +#include "mesh_api.h" +#include "platform_types.h" + +BEGIN_DECLS +/** + * @defgroup Scene_Clients_Exported_Functions Scene Clients Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize scene server models + */ +void scene_server_model_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _SCENE_SERVER_APP_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.c new file mode 100644 index 00000000..ba36771a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.c @@ -0,0 +1,158 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file scheduler_server_app.c + * @brief Source file for scheduler client application. + * @details User command interfaces. + * @author + * @date 2020-4-1 + * @version v1.0 + * ************************************************************************************* + */ +#include "scheduler_server_app.h" +#include "scheduler.h" + +uint16_t cur_schedulers = 0; +scheduler_server_get_action_t scheduler_action = {0}; +scheduler_server_set_action_t scheduler_action_set_buffer = {0}; + +mesh_model_info_t scheduler_server_model; +mesh_model_info_t scheduler_setup_server_model; + +static int32_t scheduler_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case SCHEDULER_SERVER_GET: + { + scheduler_server_get_t *p_get_data = NULL; + p_get_data = (scheduler_server_get_t *)pargs; + + if (p_get_data) { + p_get_data->schedulers = cur_schedulers; + } + data_uart_debug("scheduler server receive: schedulers = %d\r\n", cur_schedulers); + } + break; + case SCHEDULER_SERVER_GET_ACTION: + { + scheduler_server_get_action_t *p_get_data = NULL; + p_get_data = (scheduler_server_get_action_t *)pargs; + + if (p_get_data) { + p_get_data->index = scheduler_action.index; + (p_get_data->scheduler).index = scheduler_action.scheduler.index; + (p_get_data->scheduler).year = scheduler_action.scheduler.year; + (p_get_data->scheduler).month = scheduler_action.scheduler.month; + (p_get_data->scheduler).day = scheduler_action.scheduler.day; + (p_get_data->scheduler).hour = scheduler_action.scheduler.hour; + (p_get_data->scheduler).minute = scheduler_action.scheduler.minute; + (p_get_data->scheduler).second = scheduler_action.scheduler.second; + (p_get_data->scheduler).day_of_week = scheduler_action.scheduler.day_of_week; + (p_get_data->scheduler).action = scheduler_action.scheduler.action; + (p_get_data->scheduler).num_steps = scheduler_action.scheduler.num_steps; + (p_get_data->scheduler).step_resolution = scheduler_action.scheduler.step_resolution; + (p_get_data->scheduler).scene_number = scheduler_action.scheduler.scene_number; + } + data_uart_debug( + "scheduler server receive: index = %d, " \ + "index = %d, year = %d, month = %d, day = %d, hour = %d, minute = %d, second = %d, " \ + "day_of_week = %d, action = %d, num_steps = %d, step_resolution = %d, scene_number = %d\r\n", \ + scheduler_action.index, scheduler_action.scheduler.index, scheduler_action.scheduler.year, scheduler_action.scheduler.month, \ + scheduler_action.scheduler.day, scheduler_action.scheduler.hour, scheduler_action.scheduler.minute, scheduler_action.scheduler.second, \ + scheduler_action.scheduler.day_of_week, scheduler_action.scheduler.action, scheduler_action.scheduler.num_steps, \ + scheduler_action.scheduler.step_resolution, scheduler_action.scheduler.scene_number); + } + break; + default: + break; + } + + return 0; +} + +static int32_t scheduler_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case SCHEDULER_SERVER_SET_ACTION: + { + scheduler_server_set_action_t *p_get_data = pargs; + p_get_data = (scheduler_server_set_action_t *)pargs; + + if (p_get_data) { + scheduler_action_set_buffer.index = p_get_data->index; + scheduler_action_set_buffer.year = p_get_data->year; + scheduler_action_set_buffer.month = p_get_data->month; + scheduler_action_set_buffer.day = p_get_data->day; + scheduler_action_set_buffer.hour = p_get_data->hour; + scheduler_action_set_buffer.minute = p_get_data->minute; + scheduler_action_set_buffer.second = p_get_data->second; + scheduler_action_set_buffer.day_of_week = p_get_data->day_of_week; + scheduler_action_set_buffer.action = p_get_data->action; + scheduler_action_set_buffer.num_steps = p_get_data->num_steps; + scheduler_action_set_buffer.step_resolution = p_get_data->step_resolution; + scheduler_action_set_buffer.scene_number = p_get_data->scene_number; + } + data_uart_debug( + "scheduler setup server receive: index = %d, " \ + "index = %d, year = %d, month = %d, day = %d, hour = %d, minute = %d, second = %d, " \ + "day_of_week = %d, action = %d, num_steps = %d, step_resolution = %d, scene_number = %d\r\n", \ + scheduler_action_set_buffer.index, scheduler_action_set_buffer.year, scheduler_action_set_buffer.month, \ + scheduler_action_set_buffer.day, scheduler_action_set_buffer.hour, scheduler_action_set_buffer.minute, \ + scheduler_action_set_buffer.second, scheduler_action_set_buffer.day_of_week, scheduler_action_set_buffer.action, \ + scheduler_action_set_buffer.num_steps, scheduler_action_set_buffer.step_resolution, scheduler_action_set_buffer.scene_number); + } + break; + case SCHEDULER_SERVER_GET_ACTION: + { + scheduler_server_get_action_t *p_get_data = NULL; + p_get_data = (scheduler_server_get_action_t *)pargs; + + if (p_get_data) { + p_get_data->index = scheduler_action.index; + (p_get_data->scheduler).index = scheduler_action.scheduler.index; + (p_get_data->scheduler).year = scheduler_action.scheduler.year; + (p_get_data->scheduler).month = scheduler_action.scheduler.month; + (p_get_data->scheduler).day = scheduler_action.scheduler.day; + (p_get_data->scheduler).hour = scheduler_action.scheduler.hour; + (p_get_data->scheduler).minute = scheduler_action.scheduler.minute; + (p_get_data->scheduler).second = scheduler_action.scheduler.second; + (p_get_data->scheduler).day_of_week = scheduler_action.scheduler.day_of_week; + (p_get_data->scheduler).action = scheduler_action.scheduler.action; + (p_get_data->scheduler).num_steps = scheduler_action.scheduler.num_steps; + (p_get_data->scheduler).step_resolution = scheduler_action.scheduler.step_resolution; + (p_get_data->scheduler).scene_number = scheduler_action.scheduler.scene_number; + } + data_uart_debug( + "scheduler server receive: index = %d, " \ + "index = %d, year = %d, month = %d, day = %d, hour = %d, minute = %d, second = %d, " \ + "day_of_week = %d, action = %d, num_steps = %d, step_resolution = %d, scene_number = %d\r\n", \ + scheduler_action.index, scheduler_action.scheduler.index, scheduler_action.scheduler.year, scheduler_action.scheduler.month, \ + scheduler_action.scheduler.day, scheduler_action.scheduler.hour, scheduler_action.scheduler.minute, scheduler_action.scheduler.second, \ + scheduler_action.scheduler.day_of_week, scheduler_action.scheduler.action, scheduler_action.scheduler.num_steps, \ + scheduler_action.scheduler.step_resolution, scheduler_action.scheduler.scene_number); + } + break; + default: + break; + } + + return 0; +} + +void scheduler_server_model_init(void) +{ + scheduler_setup_server_model.model_data_cb = scheduler_setup_server_data; + scheduler_setup_server_reg(0, &scheduler_setup_server_model); + + scheduler_server_model.model_data_cb = scheduler_server_data; + scheduler_server_reg(0, &scheduler_server_model); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.h new file mode 100644 index 00000000..dbe96228 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.h @@ -0,0 +1,34 @@ +/** +********************************************************************************************************* +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file scheduler_server_app.h +* @brief Smart mesh scheduler demo application +* @details +* @author +* @date 2020-4-1 +* @version v1.0 +* ********************************************************************************************************* +*/ +#ifndef _SCHEDULER_SERVER_APP_H_ +#define _SCHEDULER_SERVER_APP_H_ + +#include "mesh_api.h" +#include "platform_types.h" + +BEGIN_DECLS +/** + * @defgroup Scheduler_Clients_Exported_Functions Scheduler Clients Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize scheduler server models + */ +void scheduler_server_model_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _SCHEDULER_SERVER_APP_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.c new file mode 100644 index 00000000..3d91c484 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.c @@ -0,0 +1,214 @@ +/** +***************************************************************************************** +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file time_server_app.c + * @brief Source file for time client application. + * @details User command interfaces. + * @author + * @date 2020-3-30 + * @version v1.0 + * ************************************************************************************* + */ + +#include "time_server_app.h" + +mesh_model_info_t time_server_model; +mesh_model_info_t time_setup_server_model; + + +time_server_get_t cur_time = {0}; +time_server_get_zone_t time_zone = {0}; +time_server_get_tai_utc_delta_t time_tai_utc_delta = {0}; +time_server_get_role_t time_role = {0}; +time_server_set_t time_set_buffer = {0}; +time_server_set_zone_t time_zone_buffer = {0}; +time_server_set_tai_utc_delta_t time_tai_utc_delta_buffer = {0}; +time_server_set_role_t time_role_buffer = {0}; +time_server_status_set_t time_status_buffer ={0}; + + +static int32_t time_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case TIME_SERVER_GET: + { + time_server_get_t *p_get_data = NULL; + p_get_data = (time_server_get_t *)pargs; + if (p_get_data) { + p_get_data->tai_seconds[4] = cur_time.tai_seconds[4]; + p_get_data->subsecond = cur_time.subsecond; + p_get_data->uncertainty = cur_time.uncertainty; + p_get_data->time_authority = cur_time.time_authority; + p_get_data->tai_utc_delta = cur_time.tai_utc_delta; + p_get_data->time_zone_offset = cur_time.time_zone_offset; + } + data_uart_debug("time server receive: tai seconds %d, subsecond %d, uncertainty %d, time authority %d, tai utc delta %d, time zone offset %d \r\n", + cur_time.tai_seconds[4], + cur_time.subsecond, + cur_time.uncertainty, + cur_time.time_authority, + cur_time.tai_utc_delta, + cur_time.time_zone_offset); + } + break; + case TIME_SERVER_GET_ZONE: + { + time_server_get_zone_t *p_get_data = NULL; + p_get_data = (time_server_get_zone_t *)pargs; + if (p_get_data) { + p_get_data->time_zone_offset_current = time_zone.time_zone_offset_current; + p_get_data->time_zone_offset_new = time_zone.time_zone_offset_new; + p_get_data->tai_of_zone_change[4] = time_zone.tai_of_zone_change[4]; + } + data_uart_debug("time server receive: current time zone offset %d, new time zone offset %d, tai of zone change %d \r\n", + time_zone.time_zone_offset_current, + time_zone.time_zone_offset_new, + time_zone.tai_of_zone_change[4]); + } + break; + case TIME_SERVER_GET_TAI_UTC_DELTA: + { + time_server_get_tai_utc_delta_t *p_get_data = NULL; + p_get_data = (time_server_get_tai_utc_delta_t *)pargs; + if (p_get_data) { + p_get_data->tai_utc_delta_current = time_tai_utc_delta.tai_utc_delta_current, + p_get_data->padding1 = time_tai_utc_delta.padding1, + p_get_data->tai_utc_delta_new = time_tai_utc_delta.tai_utc_delta_new, + p_get_data->padding2 = time_tai_utc_delta.padding2, + p_get_data->tai_of_delta_change[4] = time_tai_utc_delta.tai_of_delta_change[4]; + + } + data_uart_debug("time server receive: current tai utc delta %d, padding1 %d, new tai utc delta %d, padding2 %d, tai of delta change %d \r\n", + time_tai_utc_delta.tai_utc_delta_current, + time_tai_utc_delta.padding1, + time_tai_utc_delta.tai_utc_delta_new, + time_tai_utc_delta.padding2, + time_tai_utc_delta.tai_of_delta_change[4]); + } + break; + case TIME_SERVER_STATUS_SET: + { + time_server_status_set_t *p_get_data = NULL; + p_get_data = (time_server_status_set_t *)pargs; + if (p_get_data) { + time_status_buffer.tai_seconds[4] = p_get_data->tai_seconds[4]; + time_status_buffer.subsecond = p_get_data->subsecond; + time_status_buffer.uncertainty = p_get_data->uncertainty; + time_status_buffer.tai_utc_delta = p_get_data->tai_utc_delta; + time_status_buffer.time_zone_offset = p_get_data->time_zone_offset; + } + data_uart_debug("time server receive: tai seconds %d, subsecond %d, uncertainty %d, tai utc delta %d, time zone offset %d \r\n", + time_status_buffer.tai_seconds[4], + time_status_buffer.subsecond, + time_status_buffer.uncertainty, + time_status_buffer.tai_utc_delta, + time_status_buffer.time_zone_offset); + } + break; + default: + break; + } + + return 0; +} + +static int32_t time_setup_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case TIME_SERVER_SET: + { + time_server_set_t *p_get_data = NULL; + p_get_data = (time_server_set_t *)pargs; + if (p_get_data) { + time_set_buffer.tai_seconds[4] = p_get_data->tai_seconds[4]; + time_set_buffer.subsecond = p_get_data->subsecond ; + time_set_buffer.uncertainty = p_get_data->uncertainty; + time_set_buffer.time_authority = p_get_data->time_authority; + time_set_buffer.tai_utc_delta = p_get_data->tai_utc_delta; + time_set_buffer.time_zone_offset = p_get_data->time_zone_offset; + } + data_uart_debug("time server receive: set tai seconds %d, subsecond %d, uncertainty %d, time authority %d, tai utc delta %d, time zone offset %d \r\n", + time_set_buffer.tai_seconds[4], + time_set_buffer.subsecond, + time_set_buffer.uncertainty, + time_set_buffer.time_authority, + time_set_buffer.tai_utc_delta, + time_set_buffer.time_zone_offset); + } + break; + case TIME_SERVER_SET_ZONE: + { + time_server_set_zone_t *p_get_data = NULL; + p_get_data = (time_server_set_zone_t *)pargs; + if (p_get_data) { + time_zone_buffer.tai_of_zone_change[4] = p_get_data->tai_of_zone_change[4]; + time_zone_buffer.time_zone_offset_new = p_get_data->time_zone_offset_new; + } + data_uart_debug("time setup server receive: set tai of zone change %d, new time zone offset new %d \r\n", + time_zone_buffer.tai_of_zone_change[4], + time_zone_buffer.time_zone_offset_new); + } + break; + case TIME_SERVER_GET_ROLE: + { + time_server_get_role_t *p_get_data = NULL; + p_get_data = (time_server_get_role_t *)pargs; + if (p_get_data) { + p_get_data->role = time_role.role; + } + data_uart_debug("time setup server receive: role %d \r\n", + time_role.role); + } + break; + case TIME_SERVER_SET_ROLE: + { + time_server_set_role_t *p_get_data = NULL; + p_get_data = (time_server_set_role_t *)pargs; + if (p_get_data) { + time_role_buffer.role = p_get_data->role; + } + data_uart_debug("time setup server receive: set role %d \r\n", + time_role_buffer.role); + } + break; + case TIME_SERVER_SET_TAI_UTC_DELTA: + { + time_server_set_tai_utc_delta_t *p_get_data = NULL; + p_get_data = (time_server_set_tai_utc_delta_t *)pargs; + if (p_get_data) { + time_tai_utc_delta_buffer.tai_of_delta_change[4] = p_get_data->tai_of_delta_change[4]; + time_tai_utc_delta_buffer.tai_utc_delta_new = p_get_data->tai_utc_delta_new; + time_tai_utc_delta_buffer.padding = p_get_data->padding; + } + data_uart_debug("time setup server receive: set tai of delta change %d, new time utc delta %d, padding %d \r\n", + time_tai_utc_delta_buffer.tai_of_delta_change[4], + time_tai_utc_delta_buffer.tai_utc_delta_new, + time_tai_utc_delta_buffer.padding); + } + break; + default: + break; + } + + return 0; +} + + + +void time_server_models_init(void) +{ + time_server_model.model_data_cb = time_server_data; + time_server_reg(0, &time_server_model); + + time_setup_server_model.model_data_cb = time_setup_server_data; + time_setup_server_reg(0, &time_setup_server_model); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.h new file mode 100644 index 00000000..a5681e9a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.h @@ -0,0 +1,41 @@ +/** +********************************************************************************************************* +* Copyright(c) 2020, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file time_server_app.h +* @brief Smart mesh time demo application +* @details +* @author +* @date 2020-3-30 +* @version v1.0 +* ********************************************************************************************************* +*/ + +#ifndef _TIME_SERVER_APP_H +#define _TIME_SERVER_APP_H + +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif +#include "time_model.h" + + +BEGIN_DECLS +/** + * @defgroup TIME_Clients_Exported_Functions Time Clients Exported Functions + * @brief + * @{ + */ +/** + * @brief initialize time server models + */ +void time_server_models_init(void); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _TIME_CLIENT_APP_H */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_manufacture_adv.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_manufacture_adv.h new file mode 100644 index 00000000..38d0c8c1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_manufacture_adv.h @@ -0,0 +1,78 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_manufacture_adv.h + * @brief Head file for GAP manufacture adv used by RTK. + * @details Data types and external functions declaration. + * @author bill + * @date 2018-10-10 + * @version v1.0 + * ************************************************************************************* + */ + +#ifndef _GAP_MANUFACTURE_ADV_H +#define _GAP_MANUFACTURE_ADV_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "gap.h" +#include "gap_conn_le.h" + +BEGIN_DECLS + +/** @addtogroup Gap_Manufacture_Adv + * @{ + */ + +/** @defgroup Gap_Manufacture_Adv_Exported_Macros Exported Macros + * @brief + * @{ + */ +#define MANUFACTURE_ADV_DATA_COMPANY_ID 0x005d //!< Realtek + +#define MANUFACTURE_ADV_DATA_TYPE_BT_ADDR 0x00 +#define MANUFACTURE_ADV_DATA_TYPE_DFU 0x01 +#define MANUFACTURE_ADV_DATA_TYPE_GROUP 0x02 + +/* For Bee2 Bcut */ +#define DFU_PRODUCT_ID_TEST 0x00000000 +#define DFU_PRODUCT_ID_MESH_PROVISIONER 0x00000001 +#define DFU_PRODUCT_ID_MESH_DEVICE 0x00000002 +#define DFU_PRODUCT_ID_MESH_LIGHT 0x00000003 +#define DFU_PRODUCT_ID_MESH_ALI_LIGHT 0x00000004 +#define DFU_PRODUCT_ID_MESH_SINGLE_FIRE_SWITCH 0x00000005 +#define DFU_PRODUCT_ID_MESH_UNKNOWN 0x00000006 +#define DFU_PRODUCT_ID_GROUP_RCU 0x00000007 +/** @} */ + +/** @defgroup Gap_Manufacture_Adv_Exported_Types Exported Types + * @brief + * @{ + */ +typedef struct +{ + uint32_t product_id; + uint32_t app_version; + uint32_t patch_version; +} _PACKED4_ manufacture_adv_data_dfu_t; + +typedef struct +{ + uint16_t company_id; + uint8_t type; + union + { + uint8_t data[1]; //!< fake + /* MANUFACTURE_ADV_DATA_TYPE_BT_ADDR */ + uint8_t bt_addr[6]; + /* MANUFACTURE_ADV_DATA_TYPE_DFU */ + manufacture_adv_data_dfu_t dfu; + }; +} _PACKED4_ manufacture_adv_data_t; +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GAP_MANUFACTURE_ADV_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_scheduler.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_scheduler.h new file mode 100644 index 00000000..63a93675 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_scheduler.h @@ -0,0 +1,420 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_scheduler.h + * @brief Head file for mesh gap scheduler. + * @details The dedicated gap layer designed for mesh. + * @author bill + * @date 2019-7-22 + * @version v2.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion **/ +#ifndef GAP_SCHEDULER_H +#define GAP_SCHEDULER_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "platform_list.h" +#include "platform_os.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_adv.h" +#include "gap_scan.h" +#include "gap_conn_le.h" +#include "gap_callback_le.h" +#include "gatt.h" +#include "mesh_config.h" + +BEGIN_DECLS + +/** @addtogroup Gap_Scheduler + * @{ + */ + +/** @defgroup Gap_Scheduler_Exported_Macros Exported Macros + * @brief + * @{ + */ + +#define GAP_ADTYPE_MESH_MSG GAP_ADTYPE_MESH_PACKET +#define GAP_ADTYPE_PB_ADV GAP_ADTYPE_MESH_PB_ADV + +#define GAP_SCHED_ADV_PARALLEL 1 +#define GAP_SCHED_TASK_GUARD 1 + +#define GAP_SCHED_SCAN_ALL_THE_TIME 1 +#define GAP_SCHED_ONE_SHOT_ADV 1 //!< adv +#define GAP_SCHED_BT5_AE 0 +#if GAP_SCHED_BT5_AE +#ifndef F_BT_LE_5_0_AE_ADV_SUPPORT +#define F_BT_LE_5_0_AE_ADV_SUPPORT 1 +#endif +#ifndef F_BT_LE_5_0_AE_SCAN_SUPPORT +#define F_BT_LE_5_0_AE_SCAN_SUPPORT 1 +#endif +#include "gap_ext_adv.h" +#include "gap_ext_scan.h" +#endif +/** Advertising interval (units of 625us, 160=100ms), Value range: 0x0020 - 0x4000 (20ms - 10240ms 0.625ms/step) */ +#define GAP_SCHED_ADV_INTERVAL_MIN 0x20 /* 20ms */ +#define GAP_SCHED_ADV_INTERVAL_MAX 0x20 /* 20ms */ + +/** Scan interval and window (units of 625us, 160=100ms), Value range: 0x0004 - 0x4000 (2.5ms - 10240ms, 0.625ms/step) */ +#define GAP_SCHED_SCAN_INTERVAL 160 /* 100ms */ +#define GAP_SCHED_SCAN_WINDOW 158 /* 98.75ms */ +#define GAP_SCHED_INTERWAVE_SCAN_INTERVAL 160 /* 100ms */ +#define GAP_SCHED_INTERWAVE_SCAN_WINDOW 158 /* 98.75ms */ + +/** Connection interval, slave latency, supervision timeout */ +#define GAP_SCHED_LE_LINK_NUM 1 +#define GAP_SCHED_CONN_INTERVAL_MIN 0x0006 /* 100 milliseconds */ +#define GAP_SCHED_CONN_INTERVAL_MAX 0x0C80 /* 4 seconds */ +#define GAP_SCHED_SLAVE_LATENCY 0 +#define GAP_SCHED_SUPERVISION_TIMEOUT 1000 /* unit: 10ms */ +#define GAP_SCHED_CONN_SCAN_TIMEOUT 1000 /* unit: 10ms */ + +/** Gap scheduler parameters */ +#define GAP_SCHED_TASK_NUM 15 //!< The max number of buffered GAP task + +/** @} */ + +/** @defgroup Gap_Scheduler_Exported_Types Exported Types + * @brief + * @{ + */ +typedef enum +{ + GAP_SCHED_BT5_AE_ADV_TYPE_LEGACY_ON_1M, + GAP_SCHED_BT5_AE_ADV_TYPE_LEGACY_ON_C2, + GAP_SCHED_BT5_AE_ADV_TYPE_LEGACY_ON_C8, + GAP_SCHED_BT5_AE_ADV_TYPE_EXTEND_ON_1M_1M, + GAP_SCHED_BT5_AE_ADV_TYPE_EXTEND_ON_1M_2M, +} gap_sched_bt5_ae_adv_type_t; + +typedef enum +{ + GAP_SCHED_PARAMS_DEVICE_NAME, + GAP_SCHED_PARAMS_APPEARANCE, + GAP_SCHED_PARAMS_TX_POWER, + GAP_SCHED_PARAMS_BG_SCAN, + GAP_SCHED_PARAMS_SCAN_INTERVAL, + GAP_SCHED_PARAMS_SCAN_WINDOW, + GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, + GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, + GAP_SCHED_PARAMS_TASK_NUM, + GAP_SCHED_PARAMS_LINK_NUM, + GAP_SCHED_PARAMS_SCAN_MODE, + GAP_SCHED_PARAMS_BT5_AE, /**< Shall be configured before mesh_node_cfg invoked */ + GAP_SCHED_PARAMS_BT5_AE_ADV_TYPE, +} gap_sched_params_type_t; + +typedef enum +{ + GAP_SCHED_TYPE_IDLE, //!< idle + GAP_SCHED_TYPE_SCAN, //!< background scan + GAP_SCHED_TYPE_ADV, //!< idle delay(random or zero) + one shot adv + GAP_SCHED_TYPE_LPN_ADV, //!< one shot adv + reserved idle + scan a little while(scan maybe stopped in advance) + GAP_SCHED_TYPE_FN_ADV //!< reserverd idle + one shot adv +} gap_sched_type_t; + +typedef enum +{ + GAP_SCHED_RUN_TYPE_UNKNOWN, + GAP_SCHED_RUN_TYPE_SWITCH, + GAP_SCHED_RUN_TYPE_ADV_CHANGE, + GAP_SCHED_RUN_TYPE_SCAN_CHANGE, + GAP_SCHED_RUN_TYPE_TIMEOUT +} gap_sched_run_type_t; + +typedef enum +{ + GAP_SCHED_TASK_STATE_FREE, + GAP_SCHED_TASK_STATE_OUT, + GAP_SCHED_TASK_STATE_ADV, + GAP_SCHED_TASK_STATE_SCAN, + GAP_SCHED_TASK_STATE_IDLE +} gap_sched_task_state_t; + +typedef enum +{ + GAP_SCHED_STATE_IDLE, + GAP_SCHED_STATE_START, + GAP_SCHED_STATE_STOP, + GAP_SCHED_STATE_ACTIVE +} gap_sched_noncon_state_t; + +typedef enum +{ + GAP_SCHED_LINK_ROLE_IDLE, + GAP_SCHED_LINK_ROLE_SLAVE, + GAP_SCHED_LINK_ROLE_MASTER, + GAP_SCHED_LINK_ROLE_DISCONNECTING +} gap_sched_link_role_t; + +typedef struct +{ + union + { + uint8_t device_state; + struct + { + uint8_t scan: 2; + uint8_t adv: 2; + uint8_t initiator: 2; + uint8_t rfu: 2; + }; + }; + gap_sched_link_role_t *link; +} gap_sched_state_t, *gap_sched_state_p; + +typedef enum +{ + GAP_SCHED_ADV_TYPE_IND = 0, + GAP_SCHED_ADV_TYPE_DIRECT_IND_HIGH = 1, + GAP_SCHED_ADV_TYPE_SCAN_IND = 2, + GAP_SCHED_ADV_TYPE_NONCONN_IND = 3, + GAP_SCHED_ADV_TYPE_DIRECT_IND_LOW = 4, + GAP_SCHED_ADV_TYPE_UNKNOWN_IND = 0xff +} gap_sched_adv_type_t; + +typedef enum +{ + GAP_SCHED_ADV_END_TYPE_SUCCESS, + GAP_SCHED_ADV_END_TYPE_CONNECTED, + GAP_SCHED_ADV_END_TYPE_FAIL +} gap_sched_adv_end_type_t; + +typedef enum +{ + GAP_SCHED_ADV_REPORT_TYPE_UNDIRECTED = 0, + GAP_SCHED_ADV_REPORT_TYPE_DIRECTED = 1, + GAP_SCHED_ADV_REPORT_TYPE_SCANNABLE = 2, + GAP_SCHED_ADV_REPORT_TYPE_NONCONNECTABLE = 3, + GAP_SCHED_ADV_REPORT_TYPE_SCAN_RESPONSE = 4, + GAP_SCHED_ADV_REPORT_TYPE_UNKNOWN_IND = 0xff +} gap_sched_adv_report_type_t; + +typedef enum _mesh_msg_send_stat_t mesh_msg_send_stat_t; +typedef void (*gap_sched_send_cb_pf)(void *cb_params, mesh_msg_send_stat_t stat, uint32_t cb_data); +typedef struct _gap_sched_task_t +{ + struct _gap_sched_task_t *pnext; + uint32_t idle_time; + uint32_t scan_time; //!< 0xffffffff denotes going to stop scan + gap_sched_type_t type; + gap_sched_task_state_t state; + gap_sched_send_cb_pf pf_cb; + void *cb_params; + uint32_t cb_data; + uint8_t retrans_count; + uint16_t retrans_interval; //!< ms + gap_sched_adv_type_t adv_type; + uint8_t adv_len; + uint8_t adv_data[31]; + uint32_t last_adv_time; +} gap_sched_task_t, *gap_sched_task_p; + +#define GAP_SCHED_LINK_INVALID 0xff +#define GAP_SCHED_LINK_ALL 0xfe +typedef uint8_t gap_sched_link_t; + +typedef void (*gap_sched_link_disc_cb_t)(gap_sched_link_t link); +typedef struct _gap_sched_link_disc_cb_e_t +{ + struct _gap_sched_link_disc_cb_e_t *pnext; + gap_sched_link_disc_cb_t disc_cb; +} gap_sched_link_disc_cb_e_t; + +typedef struct _mesh_inner_msg_t mesh_inner_msg_t; + +/** @} */ + +/** @defgroup Gap_Scheduler_Exported_Functions Exported Functions + * @brief + * @{ + */ + +///@cond +void gap_sched_cfg(void); +void gap_sched_init(void); +void gap_sched_deinit(void); +void gap_sched_task_free(void *pbuffer); +void gap_sched_try(gap_sched_task_t *ptask); +void gap_sched_quit(gap_sched_task_t *ptask); +bool gap_sched_disc_cb_reg(gap_sched_link_disc_cb_t pf); +void gap_sched_timer_timeout(void *ptimer); +#if GAP_SCHED_ONE_SHOT_ADV +void gap_sched_adv_params_set_done(void); +void gap_sched_adv_done(gap_sched_adv_end_type_t type); +#else +#define gap_sched_adv_params_set_done(...) +#define gap_sched_adv_done(...) +#endif +///@endcond + +/** + * @brief set the parameters of gap scheduler + * + * @param[in] param_type: the supported parameter type + * @param[in] pvalue: the parameter value pointer + * @param[in] len: the parameter value length + * @return operation result + * @retval true: success + * @retval false: fail + */ +bool gap_sched_params_set(gap_sched_params_type_t param_type, void *pvalue, uint16_t len); + +/** + * @brief get the parameters of gap scheduler + * + * @param[in] param_type: the supported parameter type + * @param[out] pvalue: the parameter value pointer + * @param[in] len: the parameter value length + * @return operation result + * @retval true: success + * @retval false: fail + */ +bool gap_sched_params_get(gap_sched_params_type_t param_type, void *pvalue, uint16_t len); + +/** + * @brief get the advertising buffer from the gap scheduler + * + * All advertising must be sent by the gap scheduler, and shall be allocated with the buffer first. + * + * @return the advertising buffer + * @retval 0: allocate fail due to the limited resource + */ +void *gap_sched_task_get(void); + +#if GAP_SCHED_TASK_GUARD +/** + * @brief enable/disable the task guard function + * + * The mesh stack will start a timer of period guard_time_ms to monitor the operation. If there is still + * no task available when timer timeout, the stack will callback to the app to notify the exception. + * + * @param[in] pf_cb: the callback pointer provided by the app + * @param[in] guard_time_ms: the timer period, 0 means to stop the function + * @return none + */ +void gap_sched_task_guard_set(void (*pf_cb)(void), uint32_t guard_time_ms); + +/** + * @brief enable/disable the task guard test function + * + * When the test function is enabled, the gap scheduer won't schedule the task to simulate the operation exception. + * If the task guard function is also enabled, the app will be notified of the exception. + * + * @param[in] enable: enable or disable the function + * @return none + */ +void gap_sched_task_guard_test(bool enable); + +#endif + +/** + * @brief enable/disable scan of the gap scheduler + * + * The scan is background. + * + * @param[in] on_off: the scan state, true - on, false - off + * @return none + */ +void gap_sched_scan(bool on_off); + +/** + * @brief handle the bt status message + * + * The gap sheduler need process the bt messages. + * + * @param[in] pmsg: the bt status msg + * @return none + */ +void gap_sched_handle_bt_status_msg(mesh_inner_msg_t *pmsg); + +/** + * @brief handle the adv report + * + * The gap sheduler need process the adv report. + * + * @param[in] ple_scan_info: the adv report + * @return none + */ +void gap_sched_handle_adv_report(T_LE_SCAN_INFO *ple_scan_info); + +/** + * @brief check if there is link related activities + * + * To avoid complicated link situation, link activities contains + * try to connect or being connected. + * @param[in] ple_scan_info: the adv report + * @return the check result + * @retval true: yes + * @retval false: no + */ +bool gap_sched_link_check(void); + +#if GAP_SCHED_BT5_AE +/** + * @brief dump all adv set state + * @return none + */ +void gap_sched_ext_adv_state_dump(void); + +/** + * @brief process the extended adv procedure + * @param[in] handle: the extended adv handle + * @return the result + */ +T_GAP_CAUSE gap_sched_ext_adv_step(uint8_t handle); + +/** + * @brief process the extended adv state change event + * @param[in] handle: the extended adv handle + * @param[in] new_state: the new state of the extended adv set + * @param[in] cause: the cause the state change + * @return none + */ +void gap_sched_handle_ext_adv_state_evt(uint8_t handle, T_GAP_EXT_ADV_STATE new_state, + uint16_t cause); + +/** + * @brief process the extended adv state change event + * @param[in] pext_adv_report: the extended adv report + * @return none + */ +void gap_sched_handle_ext_adv_report(T_LE_EXT_ADV_REPORT_INFO *pext_adv_report); + +/** + * @brief start the extended adv without worry about collision with other adv set + * @param[in] handle: the extended adv handle + * @return the result + */ +T_GAP_CAUSE gap_sched_ext_adv_start(uint8_t handle); + +/** + * @brief stop the extended adv without worry about collision with other adv set + * @param[in] handle: the extended adv handle + * @return the result + */ +T_GAP_CAUSE gap_sched_ext_adv_stop(uint8_t handle); + +/** + * @brief set the extend adv parameter flag to enable the setting flow + * @param[in] handle: the extended adv handle + * @param[in] param_flag: the adv setting parameters flag @ref EXT_ADV_PARAM + * @return the result + */ +bool gap_sched_ext_adv_set_param_flag(uint8_t handle, uint8_t param_flag); + +#endif + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* GAP_SCHEDULER_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_wrapper.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_wrapper.h new file mode 100644 index 00000000..895d1a4e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap/gap_wrapper.h @@ -0,0 +1,74 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_wrapper.h + * @brief Head file for GAP roles used in mesh. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-10-28 + * @version v1.0 + * ************************************************************************************* + */ + +#ifndef _GAP_WRAPPER_H +#define _GAP_WRAPPER_H + +/* Add Includes here */ +#include "platform_types.h" +#include "gap.h" +#include "gap_conn_le.h" + +BEGIN_DECLS + +/** @addtogroup Gap_Wrapper + * @{ + */ + +/** @defgroup Gap_Wrapper_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief Get the MTU size of the link + * @param[in] conn_id: the link handle + * @param[out] pvalue: the pointer of output mtu size + * @return operation result + */ +#define gap_get_att_mtu_size(conn_id, pvalue) le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, pvalue, conn_id) + +/** @defgroup BT_Addr_Type BT Addr Type + * @{ + */ +#define GAP_BT_ADDR_TYPE_LE_PUBLIC GAP_LOCAL_ADDR_LE_PUBLIC +#define GAP_BT_ADDR_TYPE_LE_RANDOM GAP_LOCAL_ADDR_LE_RANDOM +/** @} */ + +/** + * @brief Get the MTU size of the link + * @param[in] random_addr: the random addr with the length of 6 Bytes + * @return operation result + */ +#define gap_set_random_addr(random_addr) le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr) + +/** + * @brief Set the adv addr type + * @param[in] addr_type: @ref BT_Addr_Type + * @return operation result + */ +#define gap_adv_set_addr_type(addr_type) le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, 1, &addr_type); + +/** + * @brief disconnect the le link + * @param[in] conn_id: the link handle + * @return operation result + */ +#define gap_disc(conn_id) le_disconnect(conn_id) //GAP_CAUSE_SUCCESS == + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GAP_WRAPPER_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebad/mesh_config.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebad/mesh_config.h new file mode 100644 index 00000000..943cdc19 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebad/mesh_config.h @@ -0,0 +1,224 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_config.h + * @brief Head file for mesh configuration. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_CONFIG_H +#define _MESH_CONFIG_H + +/* Add Includes here */ +#include "platform_types.h" +#include "platform_opts_bt.h" + +BEGIN_DECLS + +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#define MESH_PROVISIONER 1 +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) +#define MESH_DEVICE 1 +#endif + +/** setting */ +#define MESH_USE_RANDOM_ADDR 0 //!< random bt address +#define MESH_SUPPORT_TRANS_PING 1 //!< transport layer ping +#define MESH_CENTRAL_ROLE_SUPPORT 1 //!< central role +#define MESH_CONFIGURATION_MODEL_USE_APP_KEY 1 //!< violate the spec to use app key, shall also set mesh_node.features.cfg_model_use_app_key. +#define MESH_PROXY_ADV_WITH_BT_ADDR 1 //!< adv +#define MESH_PARAM_CONFIGURABLE 0 //!< configurable parameters + +/** !!! For test purpose. If don't know well, please do not modify in case of wrong operation !!! */ +#define MESH_MUTE_MODE 0 //!< just scan to Receive all mesh data pkts even not sent to me playing a role as a monitor. +#define MESH_TRANSCEIVER_MODE 0 //!< Disable duplicate pkts and src address check in network layer. +#define MESH_PROVISIONING_SAMPLE_DATA 0 //!< Provisioning Protocol +#define MESH_UNPROVISIONING_SUPPORT 0 //!< Support unprovisioning cmd in pb-gatt + +/* mesh features */ +#define MESH_DATA_UART_DEBUG 1 //!< Data uart debug +#define MESH_FN 1 //!< friend relay +#define MESH_BEARER_ADV 1 +#define MESH_BEARER_GATT 1 + +/* mesh profile 1.1 */ +#define MESH_1_1_SUPPORT 1 +#define MESH_PRB (MESH_1_1_SUPPORT && 0) +#define MESH_BLOB (MESH_1_1_SUPPORT && 1) +#define MESH_DFU (MESH_1_1_SUPPORT && MESH_BLOB && 1) +#define MESH_RPR (MESH_1_1_SUPPORT && 1) + +#if defined(MESH_DEVICE) && MESH_DEVICE +//#warning "current project is device lib" +#define MESH_LPN 1 //!< low power node +#define MESH_GENERATE_ECC_KEY_PAIR_EACH_SESSION 1 //!< only mandatory in the device? +#define MESH_DEVICE_ONLY_ONE_DEV_KEY 0 //!< Device may send configuration client msgs using other device's DevKey +#define MESH_DEVICE_PROV_PROXY_SERVER_COEXIST 1 //!< Why not? +#endif + +#if defined(MESH_PROVISIONER) && MESH_PROVISIONER +//#warning "current project is provisioner lib" +#define MESH_PROV_WO_AUTH_VALUE 0 +#endif + +#if MESH_DATA_UART_DEBUG +#include "mesh_data_uart.h" +#else +#define data_uart_debug(...) +#define data_uart_dump(...) +#endif + +#if ((defined(MESH_FN) && MESH_FN) && \ + (defined(MESH_LPN) && MESH_LPN)) +//#error "Can't support both Friend Node and Low Power Node at the same time!" +#endif + +/** Networking parameters */ +#define MESH_UDB_PERIOD 3000 //!< in units of millisecond +#define MESH_SNB_PERIOD 10000 //!< in units of millisecond +#define MESH_PROV_ADV_PERIOD 3000 //!< in units of millisecond +#define MESH_PROXY_ADV_PERIOD 3000 //!< in units of millisecond +#define MESH_ID_ADV_PERIOD 300 //!< in units of millisecond +#if MESH_PRB +#define MESH_PRB_PERIOD 10000 //!< in units of millisecond +#define MESH_PRB_RANDOM_UPDATE_PERIOD 600 //!< in units of seconds +#define MESH_PID_ADV_PERIOD 300 //!< in units of millisecond +#endif + +/** Mesh stored message parameters */ +#define MESH_NET_MSG_CACHE_SIZE 30 //!< The number of devices to check duplicate packets +#define MESH_INNER_MSG_NUM 16 //!< The number of mesh inner msg + +/** PB-ADV Generic Provisioning Layer */ +#define MESH_PB_GENERIC_TIMEOUT_PERIOD 30000 //!< 30s transaction timeout +#define MESH_PB_ADV_LINK_IDLE_TIMEOUT 80000 //!< 80s link idle +#define MESH_PB_ADV_RETRY_PERIOD 200 //!< ms +//#define MESH_PB_GENERIC_RETRY_TIMES 15 + +/** Prov */ +#define MESH_PROV_TIMEOUT_PERIOD 60000 //!< 60s protocol timeout + +/** Proxy */ +#define MESH_PROXY_SAR_TIMEOUT_PERIOD 20000 +#define MESH_PROXY_SAR_BUFFER_LEN 65 + +/** Network layer */ +#define MESH_NET_RETRANSMIT_TIMES 1 +#define MESH_RELAY_RETRANSMIT_TIMES 1 + +/** Transport layer */ +#define MESH_TRANS_TX_WAIT_ACK_PERIOD 500 +#define MESH_TRANS_RX_ACK_PERIOD 400 +#define MESH_TRANS_RETRANSMIT_TIMES 2 +#define MESH_TRANS_TX_QUEUE_SIZE 3 +#define MESH_TRANS_RX_CTX_COUNT 2 + +/** FN parameters */ +#define MESH_FRIENDSHIP_SUB_LIST_SIZE 10 +#define MESH_FRIENDSHIP_RX_WINDOW (1 * GAP_SCHED_SCAN_INTERVAL * 625 / 1000) //!< ms, set according to scan interval +#define MESH_FN_TX_AHEAD 15 //!< in units of millisecond +#define MESH_FRIENDSHIP_TIMEOUT_PERIOD 1000 //!< in units of millisecond +#define MESH_FRND_QUEUE_MIN_TTL 2 + +/** LPN parameters */ +#define MESH_LPN_RX_DELAY 10 +#define MESH_LPN_RX_WIDEN 0 +#define MESH_LPN_FRND_OFFER_RX_DELAY 90 //!< 100ms defined by spec +#define MESH_LPN_FRND_WAIT_PERIOD 1100 //!< offer range +#define MESH_LPN_FRND_OFFER_CHOOSE_DELAY 400 //!< 6 times, total 1s +#define MESH_LPN_FRND_POLL_RETRY_INTERVAL 300 +#define MESH_LPN_FRND_POLL_RETRY_TIMES 8 +#define MESH_LPN_FRND_POLL_FAILED_TIMES 1 +#define MESH_LPN_FRND_SCAN_DELAY_TIME 0 + +/** Remote Provisioning server parameters */ +#define MESH_RMT_PRO_SERVER_UNPRO_DEVICE_NUM 3 //!< +#define MESH_RMT_PRO_SERVER_SCAN_TIMEOUT_PERIOD 10000 //!< +#define MESH_RMT_PRO_SERVER_SCAN_REPORT_PERIOD 3000 //!< +#define MESH_RMT_PRO_SERVER_LINK_OPEN_INTERVAL 2000 //!< +#define MESH_RMT_PRO_SERVER_LINK_OPEN_RETRY_TIMES 3 //!< + +/** device uuid */ +#define MESH_DEVICE_UUID {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f} + +/** application key default value */ +#define MESH_APP_KEY {0x63, 0x96, 0x47, 0x71, 0x73, 0x4f, 0xbd, 0x76, 0xe3, 0xb4, 0x05, 0x19, 0xd1, 0xd9, 0x4a, 0x48} +#define MESH_APP_KEY1 {0xf1, 0xa2, 0x4a, 0xbe, 0xa9, 0xb8, 0x6c, 0xd3, 0x33, 0x80, 0xa2, 0x4c, 0x4d, 0xfb, 0xe7, 0x43} + +/** net key default value */ +#define MESH_NET_KEY {0x7d, 0xd7, 0x36, 0x4c, 0xd8, 0x42, 0xad, 0x18, 0xc1, 0x7c, 0x2b, 0x82, 0x0c, 0x84, 0xc3, 0xd6} +#define MESH_NET_KEY1 {0xef, 0xb2, 0x25, 0x5e, 0x64, 0x22, 0xd3, 0x30, 0x08, 0x8e, 0x09, 0xbb, 0x01, 0x5e, 0xd7, 0x07} + +#define MESH_IDENTITY_CREDIT 2 //!< shall be >= 1 && <= mesh_node.net_key_num + +/** network source address default value */ +#if MESH_MUTE_MODE +#define MESH_SRC 0x0000 +#else +#define MESH_SRC 0x0001 +#endif + +/** network sequence number default value */ +#define MESH_SEQ 0 //0x010203 +//#define MESH_SEQ_NUM_OVERFLOW_ERROR (0x00ffffff - 100) //!< Sequence number error range in case of overflow +#define MESH_SEQ_NUM_MAX 0xffffff //!< 16777216 +#define MESH_SEQ_START_IV_UPDATE (MESH_SEQ_NUM_MAX - 144 * 3600 / 5) //!< 144 * 3600 / 5 = 103680 +#define MESH_SEQ_NUM_STEP 100 // greater than or equal to 1, less than MESH_SEQ_NUM_MAX +#if MESH_SEQ_NUM_STEP == 0 || MESH_SEQ_NUM_STEP > MESH_SEQ_NUM_MAX +#error "Wrong seq step setting!" +#endif + +/** network iv index */ +#define MESH_IV_INDEX 0 +#define MESH_IV_INDEX_TIMER_PERIOD 600 //!< second +#define MESH_IV_INDEX_96H (96 * 3600 / MESH_IV_INDEX_TIMER_PERIOD) +#define MESH_IV_INDEX_144H (144 * 3600 / MESH_IV_INDEX_TIMER_PERIOD) +#define MESH_IV_INDEX_192H (2 * MESH_IV_INDEX_96H) +#define MESH_IV_INDEX_48W (42 * MESH_IV_INDEX_192H) + +/** network TTL default value */ +#define MESH_TTL_MAX 0x7f +#define MESH_TTL_DEFAULT 7 + +/** provisioning parameters */ +#if MESH_PROVISIONING_SAMPLE_DATA +#define MESH_PROVISIONER_PUBLIC_KEY {0x2c, 0x31, 0xa4, 0x7b, 0x57, 0x79, 0x80, 0x9e, 0xf4, 0x4c, 0xb5, 0xea, 0xaf, 0x5c, 0x3e, 0x43, 0xd5, 0xf8, 0xfa, 0xad, 0x4a, 0x87, 0x94, 0xcb, 0x98, 0x7e, 0x9b, 0x03, 0x74, 0x5c, 0x78, 0xdd, 0x91, 0x95, 0x12, 0x18, 0x38, 0x98, 0xdf, 0xbe, 0xcd, 0x52, 0xe2, 0x40, 0x8e, 0x43, 0x87, 0x1f, 0xd0, 0x21, 0x10, 0x91, 0x17, 0xbd, 0x3e, 0xd4, 0xea, 0xf8, 0x43, 0x77, 0x43, 0x71, 0x5d, 0x4f} +#define MESH_PROVISIONER_PRIVATE_KEY {0x06, 0xa5, 0x16, 0x69, 0x3c, 0x9a, 0xa3, 0x1a, 0x60, 0x84, 0x54, 0x5d, 0x0c, 0x5d, 0xb6, 0x41, 0xb4, 0x85, 0x72, 0xb9, 0x72, 0x03, 0xdd, 0xff, 0xb7, 0xac, 0x73, 0xf7, 0xd0, 0x45, 0x76, 0x63} +#define MESH_PROVISIONER_RANDOM {0x8b, 0x19, 0xac, 0x31, 0xd5, 0x8b, 0x12, 0x4c, 0x94, 0x62, 0x09, 0xb5, 0xdb, 0x10, 0x21, 0xb9} +#define MESH_DEVICE_PUBLIC_KEY {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79} +#define MESH_DEVICE_PRIVATE_KEY {0x52, 0x9a, 0xa0, 0x67, 0x0d, 0x72, 0xcd, 0x64, 0x97, 0x50, 0x2e, 0xd4, 0x73, 0x50, 0x2b, 0x03, 0x7e, 0x88, 0x03, 0xb5, 0xc6, 0x08, 0x29, 0xa5, 0xa3, 0xca, 0xa2, 0x19, 0x50, 0x55, 0x30, 0xba} +#define MESH_DEVICE_RANDOM {0x55, 0xa2, 0xa2, 0xbc, 0xa0, 0x4c, 0xd3, 0x2f, 0xf6, 0xf3, 0x46, 0xbd, 0x0a, 0x0c, 0x1a, 0x3a} +#define MESH_PROVISIONING_NET_KEY MESH_NET_KEY1 +#define MESH_PROVISIONING_NET_KEY_INDEX 0x0567 +#define MESH_PROVISIONING_IV_INDEX 0x01020304 +#define MESH_PROVISIONING_UNICAST_ADDRESS 0x0b0c +#else +#define MESH_PROVISIONER_PUBLIC_KEY {0} +#define MESH_PROVISIONER_PRIVATE_KEY {0} +#define MESH_PROVISIONER_RANDOM {0} +#define MESH_DEVICE_PUBLIC_KEY {0} +#define MESH_DEVICE_PRIVATE_KEY {0} +#define MESH_DEVICE_RANDOM {0} +#define MESH_PROVISIONING_NET_KEY MESH_NET_KEY +#define MESH_PROVISIONING_NET_KEY_INDEX 0 +#define MESH_PROVISIONING_IV_INDEX MESH_IV_INDEX +#define MESH_PROVISIONING_UNICAST_ADDRESS 0x0100//MESH_SRC +#endif + +/* model configuration */ +#define MESH_MODEL_ENABLE_DEINIT 1 + +#define MESH_SUPPORT_CHECK 0 + +END_DECLS + +#endif /* _MESH_CONFIG_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebaz2/mesh_config.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebaz2/mesh_config.h new file mode 100644 index 00000000..c2c9ed07 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebaz2/mesh_config.h @@ -0,0 +1,225 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_config.h + * @brief Head file for mesh configuration. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_CONFIG_H +#define _MESH_CONFIG_H + +/* Add Includes here */ +#include "platform_types.h" +#include "platform_opts_bt.h" + +BEGIN_DECLS + +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE +#define MESH_PROVISIONER 1 +#elif (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) +#define MESH_DEVICE 1 +#endif + +/** setting */ +#define MESH_USE_RANDOM_ADDR 0 //!< random bt address +#define MESH_SUPPORT_TRANS_PING 1 //!< transport layer ping +#define MESH_CENTRAL_ROLE_SUPPORT 1 //!< central role +#define MESH_CONFIGURATION_MODEL_USE_APP_KEY 1 //!< violate the spec to use app key, shall also set mesh_node.features.cfg_model_use_app_key. +#define MESH_PROXY_ADV_WITH_BT_ADDR 1 //!< adv +#define MESH_PARAM_CONFIGURABLE 0 //!< configurable parameters +#define MESH_HB_SUB_UNCHECK_SRC 1 //!< transport layer uncheck the source address of the received heartbeat message + +/** !!! For test purpose. If don't know well, please do not modify in case of wrong operation !!! */ +#define MESH_MUTE_MODE 0 //!< just scan to Receive all mesh data pkts even not sent to me playing a role as a monitor. +#define MESH_TRANSCEIVER_MODE 0 //!< Disable duplicate pkts and src address check in network layer. +#define MESH_PROVISIONING_SAMPLE_DATA 0 //!< Provisioning Protocol +#define MESH_UNPROVISIONING_SUPPORT 0 //!< Support unprovisioning cmd in pb-gatt + +/* mesh features */ +#define MESH_DATA_UART_DEBUG 1 //!< Data uart debug +#define MESH_FN 1 //!< friend relay +#define MESH_BEARER_ADV 1 +#define MESH_BEARER_GATT 1 + +/* mesh profile 1.1 */ +#define MESH_1_1_SUPPORT 1 +#define MESH_PRB (MESH_1_1_SUPPORT && 0) +#define MESH_BLOB (MESH_1_1_SUPPORT && 1) +#define MESH_DFU (MESH_1_1_SUPPORT && MESH_BLOB && 1) +#define MESH_RPR (MESH_1_1_SUPPORT && 1) + +#if defined(MESH_DEVICE) && MESH_DEVICE +//#warning "current project is device lib" +#define MESH_LPN 1 //!< low power node +#define MESH_GENERATE_ECC_KEY_PAIR_EACH_SESSION 1 //!< only mandatory in the device? +#define MESH_DEVICE_ONLY_ONE_DEV_KEY 0 //!< Device may send configuration client msgs using other device's DevKey +#define MESH_DEVICE_PROV_PROXY_SERVER_COEXIST 1 //!< Why not? +#endif + +#if defined(MESH_PROVISIONER) && MESH_PROVISIONER +//#warning "current project is provisioner lib" +#define MESH_PROV_WO_AUTH_VALUE 1 +#endif + +#if MESH_DATA_UART_DEBUG +#include "mesh_data_uart.h" +#else +#define data_uart_debug(...) +#define data_uart_dump(...) +#endif + +#if ((defined(MESH_FN) && MESH_FN) && \ + (defined(MESH_LPN) && MESH_LPN)) +//#error "Can't support both Friend Node and Low Power Node at the same time!" +#endif + +/** Networking parameters */ +#define MESH_UDB_PERIOD 3000 //!< in units of millisecond +#define MESH_SNB_PERIOD 10000 //!< in units of millisecond +#define MESH_PROV_ADV_PERIOD 3000 //!< in units of millisecond +#define MESH_PROXY_ADV_PERIOD 3000 //!< in units of millisecond +#define MESH_ID_ADV_PERIOD 300 //!< in units of millisecond +#if MESH_PRB +#define MESH_PRB_PERIOD 10000 //!< in units of millisecond +#define MESH_PRB_RANDOM_UPDATE_PERIOD 600 //!< in units of seconds +#define MESH_PID_ADV_PERIOD 300 //!< in units of millisecond +#endif + +/** Mesh stored message parameters */ +#define MESH_NET_MSG_CACHE_SIZE 30 //!< The number of devices to check duplicate packets +#define MESH_INNER_MSG_NUM 16 //!< The number of mesh inner msg + +/** PB-ADV Generic Provisioning Layer */ +#define MESH_PB_GENERIC_TIMEOUT_PERIOD 30000 //!< 30s transaction timeout +#define MESH_PB_ADV_LINK_IDLE_TIMEOUT 80000 //!< 80s link idle +#define MESH_PB_ADV_RETRY_PERIOD 200 //!< ms +//#define MESH_PB_GENERIC_RETRY_TIMES 15 + +/** Prov */ +#define MESH_PROV_TIMEOUT_PERIOD 60000 //!< 60s protocol timeout + +/** Proxy */ +#define MESH_PROXY_SAR_TIMEOUT_PERIOD 20000 +#define MESH_PROXY_SAR_BUFFER_LEN 65 + +/** Network layer */ +#define MESH_NET_RETRANSMIT_TIMES 1 +#define MESH_RELAY_RETRANSMIT_TIMES 1 + +/** Transport layer */ +#define MESH_TRANS_TX_WAIT_ACK_PERIOD 500 +#define MESH_TRANS_RX_ACK_PERIOD 400 +#define MESH_TRANS_RETRANSMIT_TIMES 2 +#define MESH_TRANS_TX_QUEUE_SIZE 3 +#define MESH_TRANS_RX_CTX_COUNT 2 + +/** FN parameters */ +#define MESH_FRIENDSHIP_SUB_LIST_SIZE 10 +#define MESH_FRIENDSHIP_RX_WINDOW (1 * GAP_SCHED_SCAN_INTERVAL * 625 / 1000) //!< ms, set according to scan interval +#define MESH_FN_TX_AHEAD 15 //!< in units of millisecond +#define MESH_FRIENDSHIP_TIMEOUT_PERIOD 1000 //!< in units of millisecond +#define MESH_FRND_QUEUE_MIN_TTL 2 + +/** LPN parameters */ +#define MESH_LPN_RX_DELAY 10 +#define MESH_LPN_RX_WIDEN 0 +#define MESH_LPN_FRND_OFFER_RX_DELAY 90 //!< 100ms defined by spec +#define MESH_LPN_FRND_WAIT_PERIOD 1100 //!< offer range +#define MESH_LPN_FRND_OFFER_CHOOSE_DELAY 400 //!< 6 times, total 1s +#define MESH_LPN_FRND_POLL_RETRY_INTERVAL 300 +#define MESH_LPN_FRND_POLL_RETRY_TIMES 8 +#define MESH_LPN_FRND_POLL_FAILED_TIMES 1 +#define MESH_LPN_FRND_SCAN_DELAY_TIME 0 + +/** Remote Provisioning server parameters */ +#define MESH_RMT_PRO_SERVER_UNPRO_DEVICE_NUM 3 //!< +#define MESH_RMT_PRO_SERVER_SCAN_TIMEOUT_PERIOD 10000 //!< +#define MESH_RMT_PRO_SERVER_SCAN_REPORT_PERIOD 3000 //!< +#define MESH_RMT_PRO_SERVER_LINK_OPEN_INTERVAL 2000 //!< +#define MESH_RMT_PRO_SERVER_LINK_OPEN_RETRY_TIMES 3 //!< + +/** device uuid */ +#define MESH_DEVICE_UUID {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f} + +/** application key default value */ +#define MESH_APP_KEY {0x63, 0x96, 0x47, 0x71, 0x73, 0x4f, 0xbd, 0x76, 0xe3, 0xb4, 0x05, 0x19, 0xd1, 0xd9, 0x4a, 0x48} +#define MESH_APP_KEY1 {0xf1, 0xa2, 0x4a, 0xbe, 0xa9, 0xb8, 0x6c, 0xd3, 0x33, 0x80, 0xa2, 0x4c, 0x4d, 0xfb, 0xe7, 0x43} + +/** net key default value */ +#define MESH_NET_KEY {0x7d, 0xd7, 0x36, 0x4c, 0xd8, 0x42, 0xad, 0x18, 0xc1, 0x7c, 0x2b, 0x82, 0x0c, 0x84, 0xc3, 0xd6} +#define MESH_NET_KEY1 {0xef, 0xb2, 0x25, 0x5e, 0x64, 0x22, 0xd3, 0x30, 0x08, 0x8e, 0x09, 0xbb, 0x01, 0x5e, 0xd7, 0x07} + +#define MESH_IDENTITY_CREDIT 2 //!< shall be >= 1 && <= mesh_node.net_key_num + +/** network source address default value */ +#if MESH_MUTE_MODE +#define MESH_SRC 0x0000 +#else +#define MESH_SRC 0x0001 +#endif + +/** network sequence number default value */ +#define MESH_SEQ 0 //0x010203 +//#define MESH_SEQ_NUM_OVERFLOW_ERROR (0x00ffffff - 100) //!< Sequence number error range in case of overflow +#define MESH_SEQ_NUM_MAX 0xffffff //!< 16777216 +#define MESH_SEQ_START_IV_UPDATE (MESH_SEQ_NUM_MAX - 144 * 3600 / 5) //!< 144 * 3600 / 5 = 103680 +#define MESH_SEQ_NUM_STEP 100 // greater than or equal to 1, less than MESH_SEQ_NUM_MAX +#if MESH_SEQ_NUM_STEP == 0 || MESH_SEQ_NUM_STEP > MESH_SEQ_NUM_MAX +#error "Wrong seq step setting!" +#endif + +/** network iv index */ +#define MESH_IV_INDEX 0 +#define MESH_IV_INDEX_TIMER_PERIOD 600 //!< second +#define MESH_IV_INDEX_96H (96 * 3600 / MESH_IV_INDEX_TIMER_PERIOD) +#define MESH_IV_INDEX_144H (144 * 3600 / MESH_IV_INDEX_TIMER_PERIOD) +#define MESH_IV_INDEX_192H (2 * MESH_IV_INDEX_96H) +#define MESH_IV_INDEX_48W (42 * MESH_IV_INDEX_192H) + +/** network TTL default value */ +#define MESH_TTL_MAX 0x7f +#define MESH_TTL_DEFAULT 7 + +/** provisioning parameters */ +#if MESH_PROVISIONING_SAMPLE_DATA +#define MESH_PROVISIONER_PUBLIC_KEY {0x2c, 0x31, 0xa4, 0x7b, 0x57, 0x79, 0x80, 0x9e, 0xf4, 0x4c, 0xb5, 0xea, 0xaf, 0x5c, 0x3e, 0x43, 0xd5, 0xf8, 0xfa, 0xad, 0x4a, 0x87, 0x94, 0xcb, 0x98, 0x7e, 0x9b, 0x03, 0x74, 0x5c, 0x78, 0xdd, 0x91, 0x95, 0x12, 0x18, 0x38, 0x98, 0xdf, 0xbe, 0xcd, 0x52, 0xe2, 0x40, 0x8e, 0x43, 0x87, 0x1f, 0xd0, 0x21, 0x10, 0x91, 0x17, 0xbd, 0x3e, 0xd4, 0xea, 0xf8, 0x43, 0x77, 0x43, 0x71, 0x5d, 0x4f} +#define MESH_PROVISIONER_PRIVATE_KEY {0x06, 0xa5, 0x16, 0x69, 0x3c, 0x9a, 0xa3, 0x1a, 0x60, 0x84, 0x54, 0x5d, 0x0c, 0x5d, 0xb6, 0x41, 0xb4, 0x85, 0x72, 0xb9, 0x72, 0x03, 0xdd, 0xff, 0xb7, 0xac, 0x73, 0xf7, 0xd0, 0x45, 0x76, 0x63} +#define MESH_PROVISIONER_RANDOM {0x8b, 0x19, 0xac, 0x31, 0xd5, 0x8b, 0x12, 0x4c, 0x94, 0x62, 0x09, 0xb5, 0xdb, 0x10, 0x21, 0xb9} +#define MESH_DEVICE_PUBLIC_KEY {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79} +#define MESH_DEVICE_PRIVATE_KEY {0x52, 0x9a, 0xa0, 0x67, 0x0d, 0x72, 0xcd, 0x64, 0x97, 0x50, 0x2e, 0xd4, 0x73, 0x50, 0x2b, 0x03, 0x7e, 0x88, 0x03, 0xb5, 0xc6, 0x08, 0x29, 0xa5, 0xa3, 0xca, 0xa2, 0x19, 0x50, 0x55, 0x30, 0xba} +#define MESH_DEVICE_RANDOM {0x55, 0xa2, 0xa2, 0xbc, 0xa0, 0x4c, 0xd3, 0x2f, 0xf6, 0xf3, 0x46, 0xbd, 0x0a, 0x0c, 0x1a, 0x3a} +#define MESH_PROVISIONING_NET_KEY MESH_NET_KEY1 +#define MESH_PROVISIONING_NET_KEY_INDEX 0x0567 +#define MESH_PROVISIONING_IV_INDEX 0x01020304 +#define MESH_PROVISIONING_UNICAST_ADDRESS 0x0b0c +#else +#define MESH_PROVISIONER_PUBLIC_KEY {0} +#define MESH_PROVISIONER_PRIVATE_KEY {0} +#define MESH_PROVISIONER_RANDOM {0} +#define MESH_DEVICE_PUBLIC_KEY {0} +#define MESH_DEVICE_PRIVATE_KEY {0} +#define MESH_DEVICE_RANDOM {0} +#define MESH_PROVISIONING_NET_KEY MESH_NET_KEY +#define MESH_PROVISIONING_NET_KEY_INDEX 0 +#define MESH_PROVISIONING_IV_INDEX MESH_IV_INDEX +#define MESH_PROVISIONING_UNICAST_ADDRESS 0x0100//MESH_SRC +#endif + +/* model configuration */ +#define MESH_MODEL_ENABLE_DEINIT 1 + +#define MESH_SUPPORT_CHECK 1 + +END_DECLS + +#endif /* _MESH_CONFIG_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/friendship_fn.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/friendship_fn.h new file mode 100644 index 00000000..4bc80e51 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/friendship_fn.h @@ -0,0 +1,80 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file friendship_fn.h + * @brief Head file for friendship friend node. + * @details Data types and external functions declaration. + * @author bill + * @date 2016-4-29 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _FRIENDSHIP_FN_H +#define _FRIENDSHIP_FN_H + +/* Add Includes here */ +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup FN + * @{ + */ + +/** @defgroup FN_Exported_Types Exported Types + * @brief + * @{ + */ +typedef struct +{ + uint8_t queue_size; +} fn_params_t; + +typedef enum +{ + FN_CB_TYPE_ESTABLISHING, + FN_CB_TYPE_ESTABLISH_FAIL_NO_POLL, + FN_CB_TYPE_ESTABLISH_SUCCESS, + FN_CB_TYPE_FRND_LOST //!< FN_CB_TYPE_FRND_CLEAR, FN_CB_TYPE_CFG_DISABLE +} fn_cb_type_t; + +typedef void (*pf_fn_cb_t)(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +/** @} */ + +/** @defgroup FN_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief initialize the friend node + * @param[in] lpn_num: the maxium supported lpn number + * @param[in] fn_params_t: fn parameters + * @param[in] pf_fn_cb: fn friendship info callback + * @return operation result + * @retval true: operation success + * @retval false: operation failure + */ +bool fn_init(uint8_t lpn_num, fn_params_t *pfn_params, pf_fn_cb_t pf_fn_cb); + +/** + * @brief deinitialize the friend node to release resources + * @return none + */ +void fn_deinit(void); + +/** + * @brief clear all the existing lpn + * @return none + */ +void fn_clear(void); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _FRIENDSHIP_FN_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/friendship_lpn.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/friendship_lpn.h new file mode 100644 index 00000000..cfe3e0fe --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/friendship_lpn.h @@ -0,0 +1,172 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file friendship_lpn.h + * @brief Head file for lpn. + * @details Data types and external functions declaration. + * @author bill + * @date 2016-4-29 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _FRIENDSHIP_LPN_H +#define _FRIENDSHIP_LPN_H + +/* Add Includes here */ +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup LPN LPN + * @{ + */ + +/** @defgroup LPN_Exported_Types Exported Types + * @{ + */ +/* lpn node offer choose algorithm function */ +typedef bool (*pf_lpn_offer_choose_t)(uint16_t frnd_addr, uint8_t frnd_index, + frnd_offer_t *pfrnd_offer, int8_t rssi); +typedef struct +{ + uint32_t poll_interval; //!< in units of 100 milliseconds, little than poll_timeout + uint32_t poll_timeout; //!< in units of 100 milliseconds, range 0x00000A - C0x34BBFF + frnd_criteria_t criteria; + pf_lpn_offer_choose_t + offer_choose; /* user can define offer choose algorithm or set to NULL to use stack's default offer choose algorithm */ +} lpn_req_params_t; + +typedef enum +{ + LPN_REQ_REASON_SUCCESS, + LPN_REQ_REASON_REQ_PARAMS_INVALID, + LPN_REQ_REASON_NET_KEY_INDEX_INVALID, + LPN_REQ_REASON_FRND_ON_SAME_NET_KEY_INDEX, + LPN_REQ_REASON_FRND_INDEX_INVALID, + LPN_REQ_REASON_FRND_ALREADY_EXIST_OR_ESTABLISING, + LPN_REQ_REASON_RESOURCE_INSUFFICIENT +} lpn_req_reason_t; + +typedef enum +{ + LPN_CB_TYPE_ESTABLISH_SUCCESS, + LPN_CB_TYPE_ESTABLISH_FAIL_NO_OFFER, + LPN_CB_TYPE_ESTABLISH_FAIL_NO_UPDATE, + LPN_CB_TYPE_FRIENDSHIP_LOST //!< LPN_CB_TYPE_FRIENDSHIP_CLEAR +} lpn_cb_type_t; + +typedef void (*pf_lpn_cb_t)(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +/** @} */ + +/** @defgroup LPN_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief initialize the lpn + * + * A lpn may establish multiple friendships on different NetKeys. + * @param[in] fn_num: the maxium supported fn number + * @param[in] pf_lpn_cb: lpn friendship info callback + * @return operation result + * @retval true: operation success + * @retval false: operation failure + */ +bool lpn_init(uint8_t fn_num, pf_lpn_cb_t pf_lpn_cb); + +/** + * @brief deinitialize the lpn to release resources + * @return none + */ +void lpn_deinit(void); + +/** + * @brief start to establish the friendship on the desired Netkey + * + * The app shall manage the fn index. At most one friendship can be established on + * a NetKey by the lpn. + * + * @param[in] frnd_index: the fn index + * @param[in] net_key_index: the net key index to establish + * @param[in] p_req_params: the friendship requirements + * @return operation result + */ +lpn_req_reason_t lpn_req(uint8_t frnd_index, uint16_t net_key_index, + lpn_req_params_t *p_req_params); + +/** + * @brief clear the friendship + * @param[in] fn_index: the fn index + * @return operation result + * @retval true: operation success when the friendship exists + * @retval false: operation failure + */ +bool lpn_clear(uint8_t fn_index); + +/** + * @brief get friend offer information + * @param[in] fn_index: the fn index + * @return friend offer information + */ +frnd_offer_t lpn_get_frnd_offer(uint8_t fn_index); + +/** + * @brief set friend offer information + * @param[in] fn_index: the fn index + * @param[in] friend offer information + * @return TRUE: local set friend offer success + * FALSE: local set friend offer failed + */ +bool lpn_set_frnd_offer(uint8_t fn_index, uint16_t net_key_index, uint16_t fn_addr, + frnd_offer_t frnd_offer); + +/** + * @brief get lpn counter + * @param[in] fn_index: the fn index + * @return lpn counter + */ +uint16_t lpn_get_counter(uint8_t fn_index); + +/** + * @brief set lpn counter + * @param[in] fn_index: the fn index + * @param[in] lpn_counter: lpn counter + * @return TRUE: local set lpn counter success + * FALSE: local set lpn counter failed + */ +bool lpn_set_counter(uint8_t fn_index, uint16_t lpn_counter); + +/** + * @brief start friend poll + * @param[in] poll_interval: friend poll interval, in unit of 100 milliseconds + */ +bool lpn_poll(uint8_t fn_index, uint32_t poll_interval); + +/** + * @brief get friend index of established friendship from network key index + * @param[in] net_key_index: the network key index + * @return friend index + * @retval >=0: friend index + * @retval <0: friend not found + */ +int16_t lpn_get_frnd_idx(uint16_t net_key_index); + +/** + * @brief add or remove the subscribe list when the friendship exists + * @param[in] fn_index: the fn index + * @param[in] addr: the subscribe address list + * @param[in] addr_num: the number of addresses in the list + * @param[in] add_rm: add or remove flag + * @return none + */ +void frnd_sub_list_add_rm(uint8_t fn_index, uint16_t addr[], uint8_t addr_num, bool add_rm); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _FRIENDSHIP_LPN_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/heartbeat.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/heartbeat.h new file mode 100644 index 00000000..6f87c157 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/heartbeat.h @@ -0,0 +1,301 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file heartbeat.h + * @brief Head file for heartbeat. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-7-17 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _HEARTBEAT_H +#define _HEARTBEAT_H + +/* Add Includes here */ +#include "mesh_access.h" + +BEGIN_DECLS + +/** @addtogroup HB HB + * @{ + */ + +/** @defgroup HB_Exported_Macros Exported Macros + * @{ + */ +#define HB_COUNT_LOG_NOT_PERIODICALLY 0 +#define HB_COUNT_LOG_MAX 0x11 +#define HB_COUNT_LOG_INDEFINITELY 0xFF +#define HB_COUNT_INDEFINITELY 0xFFFF +#define HB_PERIOD_LOG_MAX 0x11 +#define HB_TTL_MAX 0x7F + +#define HB_TIMER_PUB 0 +#define HB_TIMER_SUB 1 +/** @} */ + +/** @defgroup HB_Exported_Types Exported Types + * @{ + */ +typedef enum +{ + HB_TRIGGER_RELAY, + HB_TRIGGER_PROXY, + HB_TRIGGER_FN, + HB_TRIGGER_LPN, + HB_TRIGGER_ALL +} hb_trigger_type_t; + +typedef union +{ + uint16_t raw; + struct + { + uint16_t relay: 1; + uint16_t proxy: 1; + uint16_t frnd: 1; + uint16_t lpn: 1; + uint16_t rfu: 12; + }; +} _PACKED4_ hb_pub_features_t; + +typedef struct +{ + /** + * @brief publish destination address + */ + uint16_t dst; + /** + * @brief publish count, value range is 0-0xffff + * 0: heartbeat messages are not being send periodically + * 1-0xfffe: number of heartbeat messages that remain to be sent + * 0xffff: heartbeat messages are being sent indefinitely + */ + uint16_t count; + /** + * @brief publish period, value range is 0-0xffff, unit is second + * 0: heartbeat messages are not being sent periodically + * 1-0xffff: period in seconds for sending periodical heartbeat messages + */ + uint16_t period; + /** + * @brief publish initialize ttl + */ + uint8_t ttl; + /** + * @brief publish trigger feature + */ + hb_pub_features_t features; + /** + * @brief net key index that publish use + */ + uint16_t net_key_index; +} hb_pub_t; + +typedef struct +{ + /** + * @brief source address for heartbeat messages a node shall process + */ + uint16_t src; + /** + * @brief determines the destination address for heartbeat messages + */ + uint16_t dst; + /** + * @brief preiod for processing periodical heartbeat transport control messages + * 0: heartbeat messages are not being processed + * 1-0xffff: remaining period in seconds for processing periodical heartbeat message + */ + uint16_t period; + /** + * @brief number of heartbeat messages that received + * 0-0xfffe: number of heartbeat messages received + * 0xffff: more than 0xfffe messages have been received + */ + uint16_t count; + /** + * @brief minimum hops in received heartbeat messages + */ + uint8_t min_hops; + /** + * @brief maximum hops in received heartbeat messages + */ + uint8_t max_hops; +} hb_sub_t; +/** @} */ + +/** @defgroup HB_DATA_CALLBACKS Data Callbacks + * @{ + */ +typedef enum +{ + HB_DATA_PUB_TIMER_STATE, //!< @ref hb_data_timer_state_t + HB_DATA_SUB_TIMER_STATE, //!< @ref hb_data_timer_state_t + HB_DATA_PUB_COUNT_UPDATE, //!< @ref hb_data_pub_count_update_t + HB_DATA_SUB_PERIOD_UPDATE, //!< @ref hb_data_sub_period_update_t + HB_DATA_SUB_RECEIVE, //!< @ref hb_data_sub_receive_t +} hb_data_type_t; + +typedef enum +{ + HB_TIMER_STATE_START, + HB_TIMER_STATE_STOP +} hb_timer_state_t; + +typedef struct +{ + hb_timer_state_t state; + uint16_t period; +} hb_data_timer_state_t; + +typedef struct +{ + uint16_t count; +} hb_data_pub_count_update_t; + +typedef struct +{ + uint16_t period; +} hb_data_sub_period_update_t; + +typedef struct +{ + uint16_t src; + uint8_t init_ttl; + hb_pub_features_t features; + uint8_t ttl; +} hb_data_sub_receive_t; + +typedef void (*hb_data_cb)(hb_data_type_t type, void *pargs); +/** @} */ + +/** @defgroup HB_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief initialize heartbeat module + * @param[in] pcb: heartbeat callback function + */ +bool hb_init(hb_data_cb pcb); + +///@cond +void hb_run(void); +///@endcond + +/** + * @brief deinitialize heartbeat module + */ +void hb_deinit(void); + +/** + * @brief start the heartbeat timer + * @param[in] timer: HB_TIMER_PUB or HB_TIMER_SUB + * @return none + */ +void hb_timer_start(uint8_t timer); + +/** + * @brief stop the heartbeat timer + * @param[in] timer: HB_TIMER_PUB or HB_TIMER_SUB + * @return none + */ +void hb_timer_stop(uint8_t timer); + +/** + * @brief detect if the messggage need be processed + * @param[in] src: message source addr + * @param[in] dst: message destination addr + * @return operation result + * @retval true: need process + * @retval false: do not process + */ +bool hb_receive_filter(uint16_t src, uint16_t dst); + +/** + * @brief process the message + * @param[in] pmesh_msg: mesh message + * @return operation result + * @retval true: processed + * @retval false: not processed + */ +bool hb_handle_msg(mesh_msg_p pmesh_msg); + +/** + * @brief send hb message + * @param[in] type: the trigger source type + * @return none + */ +void hb_msg_send(hb_trigger_type_t type); + +/** + * @brief timeout handler + * @param[in] timer: publish or subscribe + * @return none + */ +void hb_handle_timeout(uint8_t timer); + +/** + * @brief set heartbeat publication parameter + * @param[in] pub: hearbeat publication parameter + */ +void hb_publication_set(hb_pub_t pub); + +/** + * @brief get heartbeat publication parameter + * @return heartbeat publication parameter + */ +hb_pub_t hb_publication_get(void); + +/** + * @brief set heartbeat subscription parameter + * @param[in] sub: hearbeat subscription parameter + */ +void hb_subscription_set(hb_sub_t sub); + +#if MESH_HB_SUB_UNCHECK_SRC +/** + * @brief enable the customized feature to uncheck the source address when receiving heartbeat message + * @param[in] enable: true or flase to uncheck + */ +void hb_subscription_uncheck_src(bool enable); +#endif + +/** + * @brief get heartbeat subscription parameter + * @return heartbeat subscription parameter + */ +hb_sub_t hb_subscription_get(void); + +/** + * @brief log value + * @param[in] value: value to log, 2exp(n-1) is greater than or equal to value + * @return log value + */ +uint8_t hb_log2_greater(uint16_t value); + +/** + * @brief log value + * @param[in] value: value to log, 2exp(n-1) is less than or equal to value + * @return log value + */ +uint8_t hb_log2_less(uint16_t value); + +/** + * @brief exp value + * @param[in] log_value: value to exp + * @return exp value + */ +uint16_t hb_exp2(uint8_t log_value); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _HEARTBEAT_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_access.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_access.h new file mode 100644 index 00000000..67ee2b40 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_access.h @@ -0,0 +1,220 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_access.h + * @brief Head file for mesh access layer. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_ACCESS_H +#define _MESH_ACCESS_H + +/* Add Includes here */ +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Access + * @{ + */ + +/** @defgroup Mesh_Access_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/** @brief the length includes the length of the access opcode + * @{ + */ +#define ACCESS_PAYLOAD_UNSEG_MAX_SIZE 11 +#define ACCESS_PAYLOAD_SEG_ONE_MAX_SIZE 8 +#define ACCESS_PAYLOAD_SEG_TWO_MAX_SIZE 20 +#define ACCESS_PAYLOAD_SEG_THREE_MAX_SIZE 32 +#define ACCESS_PAYLOAD_MAX_SIZE 380 //!< segmented +/** @} */ + +/** @defgroup Access_Opcode Access Opcode + * @brief + * @{ + */ +/** #pragma diag_suppress 175 */ +#define ACCESS_OPCODE_SIZE(opcode) ((opcode) >= 0xc00000 ? 3 : ((opcode) >= 0x8000 ? 2 : 1)) +#define ACCESS_OPCODE_BYTE(pbuffer, opcode)\ + do\ + {\ + if(ACCESS_OPCODE_SIZE(opcode) == 1)\ + {\ + *((uint8_t *)(pbuffer)) = (opcode) & 0xff;\ + }\ + else if(ACCESS_OPCODE_SIZE(opcode) == 2)\ + {\ + *((uint8_t *)(pbuffer)) = ((opcode) >> 8) & 0xff;\ + *((uint8_t *)(pbuffer) + 1) = (opcode) & 0xff;\ + }\ + else\ + {\ + *((uint8_t *)(pbuffer)) = ((opcode) >> 16) & 0xff;\ + *((uint8_t *)(pbuffer) + 1) = ((opcode) >> 8) & 0xff;\ + *((uint8_t *)(pbuffer) + 2) = (opcode) & 0xff;\ + }\ + } while(0) +/** @} End of Access_Opcode */ + +/** @} */ + +/** @defgroup Mesh_Access_Exported_Types Exported Types + * @brief + * @{ + */ + +/** @brief synchronized return value when send a mesh message */ +typedef enum +{ + /* The access msg is successfully processed by the stack! */ + MESH_MSG_SEND_CAUSE_SUCCESS, + /* The access msg shall be formatted with a valid access opcode as defined in the spec */ + MESH_MSG_SEND_CAUSE_INVALID_ACCESS_OPCODE, + /* + * The model send the access msg with an invalid element index. + * It maybe due to the model is unregistered. + */ + MESH_MSG_SEND_CAUSE_INVALID_ELEMENT, + /* + * The model send the access msg with an invalid model index. + * It maybe due to the model is unregistered. + */ + MESH_MSG_SEND_CAUSE_INVALID_MODEL, + /* Unprovisioned device can't send access msg! */ + MESH_MSG_SEND_CAUSE_NODE_UNPROVISIONED, + /* + * The app may send an access msg without a model, so it need appoint the src itself. + * In this case, the stack will check the validity of the src address. + */ + MESH_MSG_SEND_CAUSE_INVALID_SRC, + /* + * The dst address is assigned by the app. + * The stack will check the validity of the dst address. + * -# The dst addr can't be the unassigned address. + * -# When the message is encrypted by the device key, the device key shall exist. + */ + MESH_MSG_SEND_CAUSE_INVALID_DST, + /* + * Depending on the msg size, the access msg is send by unsegmented or segmented. + * The maximum size of the access pdu is @ref ACCESS_PAYLOAD_MAX_SIZE. + */ + MESH_MSG_SEND_CAUSE_PAYLOAD_SIZE_EXCEED, + /* + * If the SZMIC bit is set to 0, the TransMIC is a 32-bit value. + * If the SZMIC bit is set to 1, the TransMIC is a 64-bit value. + * When the SZMIC bit is set to 1 then the maximum payload size of + * segmented access pdu has to minus 4. + */ + MESH_MSG_SEND_CAUSE_PAYLOAD_SIZE_EXCEED1, //!< 8 + /* The virtual address is invalid. */ + MESH_MSG_SEND_CAUSE_INVALID_VIR_ADDR, + /* the index exceeds the upper limit @ref mesh_node.app_key_num */ + MESH_MSG_SEND_CAUSE_INVALID_APP_KEY_INDEX, + /* The key hasn't been added */ + MESH_MSG_SEND_CAUSE_INVALID_APP_KEY_STATE, + /* The key hasn't been bound to the model when sending the msg with model. */ + MESH_MSG_SEND_CAUSE_APP_KEY_NOT_BOUND_TO_MODEL, + /* the index exceeds the upper limit @ref mesh_node.net_key_num */ + MESH_MSG_SEND_CAUSE_INVALID_NET_KEY_INDEX, + /* The key hasn't been added. */ + MESH_MSG_SEND_CAUSE_INVALID_NET_KEY_STATE, + /* + * The mesh msg is send via the adverting channel, which takes some resource and time. + * When the resource is exhausted currently, the msg can't be send. + */ + MESH_MSG_SEND_CAUSE_NO_BUFFER_AVAILABLE, + /* The heap space is exhausted which need be allocated in some cases. */ + MESH_MSG_SEND_CAUSE_NO_MEMORY, //!< 16 + /* + * The segmented msg need to be buffered at the transport layer to retransmit. + * The buffer size at the transport layer is limited so that a new segmented msg + * can't be send when the buffer is full. + */ + MESH_MSG_SEND_CAUSE_TRANS_TX_BUSY, + MESH_MSG_SEND_CAUSE_INVALID_ACCESS_PARAMETER +} mesh_msg_send_cause_t; + +/** @brief asynchronized callback value after sending a mesh message */ +typedef enum _mesh_msg_send_stat_t +{ + MESH_MSG_SEND_STAT_FAIL, + MESH_MSG_SEND_STAT_SENT, //!< unseg access msg + MESH_MSG_SEND_STAT_ACKED, //!< seg access msg + MESH_MSG_SEND_STAT_ACKED_CANCEL, + MESH_MSG_SEND_STAT_ACKED_OBO, //!< seg access msg acked by fn + MESH_MSG_SEND_STAT_ACKED_OBO_CANCEL, + MESH_MSG_SEND_STAT_TIMEOUT, //!< seg access msg + MESH_MSG_SEND_STAT_CANCEL //!< seg msg canceled by myself due to some reasons like seq run out etc. +} mesh_msg_send_stat_t; + +/** @brief the access layer pdu */ +typedef struct +{ + /** variable length access message, composed of Operation Code and Parameters */ + uint8_t payload[ACCESS_PAYLOAD_MAX_SIZE]; +} access_msg_t; + +typedef struct _mesh_msg_t *mesh_msg_p; + +/** @} */ + +/** @defgroup Mesh_Access_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief cfg the mesh message use the default or the publishing parameters + * + * The caller may change any parameters later if she isn't satisfied with the default values. + * @param[in] pmesh_msg: the mesh message + * @return operation result + */ +mesh_msg_send_cause_t access_cfg(mesh_msg_p pmesh_msg); + +/** + * @brief send the mesh message to the access layer + * + * @param[in] pmesh_msg: the mesh message + * @return operation result + */ +mesh_msg_send_cause_t access_send(mesh_msg_p pmesh_msg); + +/** + * @brief dispatch the mesh message at the access layer + * + * @param[in] pmesh_msg: the mesh message + * @return none + */ +void access_dispatch(mesh_msg_p pmesh_msg); + +/** + * @brief access dispatch preprocess function type definition + * @param[in] pmesh_msg: mesh message need to process + * @return process result + */ +typedef int32_t (*dispatch_preprocess_t)(mesh_msg_p pmesh_msg); + +/** + * @brief set access dispatch preprocess function + * @param[in] process: preprocess function + */ +void access_set_dispatch_preprocess(dispatch_preprocess_t process); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_ACCESS_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_api.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_api.h new file mode 100644 index 00000000..824bea51 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_api.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_api.h + * @brief Head file for mesh application interface. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-10-19 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_API_H +#define _MESH_API_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "platform_diagnose.h" +#include "platform_os.h" +#include "platform_list.h" +#include "mesh_config.h" +#include "model_config.h" +#include "mesh_access.h" +#include "heartbeat.h" +#include "configuration.h" +#include "gap_scheduler.h" +#include "mesh_beacon.h" +#include "mesh_service.h" +#include "mesh_common.h" +#include "mesh_provision.h" +#include "mesh_node.h" +#include "mesh_bearer.h" +#include "mesh_network.h" +#include "mesh_transport.h" +#include "friendship_fn.h" +#include "friendship_lpn.h" +#include "provision_adv.h" +#include "mesh_flash.h" +#include "private_beacon_model.h" + +BEGIN_DECLS +END_DECLS + +#endif /* _MESH_API_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_beacon.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_beacon.h new file mode 100644 index 00000000..5a0e3759 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_beacon.h @@ -0,0 +1,240 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_beacon.h + * @brief Head file for mesh beacon. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_BEACON_H +#define _MESH_BEACON_H + +/* Add Includes here */ +#include "platform_types.h" +#include "mesh_config.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Beacon + * @{ + */ + +/** @defgroup Mesh_Beacon_Exported_Types Exported Types + * @{ + */ +enum +{ + MESH_BEACON_TYPE_UNB = 0, //!< Unprovisioned Node Broadcast Beacon + MESH_BEACON_TYPE_SNB = 1, //!< Secure Network Broadcast Beacon +#if MESH_PRB + MESH_BEACON_TYPE_PRB = 2, //!< Private Beacon +#endif +} _SHORT_ENUM_; +typedef uint8_t beacon_type_t; + +typedef struct +{ + uint8_t dev_uuid[16]; + uint8_t oob_info[2]; // @ref prov_oob_info_t + uint8_t uri_hash[4]; //!< optional field +} _PACKED4_ beacon_udb_t, *beacon_udb_p; + +typedef struct +{ + /* + * phase 1: old NetKey + Key Refresh flag set to 0 + * phase 2: new NetKey + Key Refresh flag set to 1 + * phase 3: new NetKey + Key Refresh flag set to 0 + */ + uint8_t key_refresh_flag: 1; //!< bit0: key refresh flag + /* + * normal: new iv index + iv_update_flag set to 0 + * update: old iv index + iv_update_flag set to 1 + */ + uint8_t iv_update_flag: 1; //!< bit1: IV update flag + uint8_t rfu: 6; //!< reserved for future use + uint8_t net_id[8]; //!< Network ID + uint8_t iv_index[4]; //!< IV Index + uint8_t auth[8]; //!< Authenticates the packet contents, computed with the Network Key over the [KR, NID, CIVI] fields +} _PACKED4_ beacon_snb_t, *beacon_snb_p; + +#if MESH_PRB +typedef struct +{ + /* + * phase 1: old NetKey + Key Refresh flag set to 0 + * phase 2: new NetKey + Key Refresh flag set to 1 + * phase 3: new NetKey + Key Refresh flag set to 0 + */ + uint8_t key_refresh_flag: 1; //!< bit0: key refresh flag + /* + * normal: new iv index + iv_update_flag set to 0 + * update: old iv index + iv_update_flag set to 1 + */ + uint8_t iv_update_flag: 1; //!< bit1: IV update flag + uint8_t rfu: 6; //!< reserved for future use +} _PACKED4_ beacon_flags_t; + +typedef union +{ + struct + { + beacon_flags_t flags; + uint8_t iv_index[4]; + }; + uint8_t obfuscated_data[5]; +} _PACKED4_ beacon_prb_data_t; + +typedef struct +{ + uint8_t random[13]; + beacon_prb_data_t prb; + uint8_t auth[8]; +} _PACKED4_ beacon_prb_t; +#endif + +typedef struct +{ + beacon_type_t beacon_type; + union + { + beacon_udb_t udb; + beacon_snb_t snb; +#if MESH_PRB + beacon_prb_t prb; +#endif + }; +} _PACKED4_ beacon_t, *beacon_p; + +typedef enum +{ + BEACON_CFG_TYPE_UDB_RETRANS_COUNT = 0, //!< uint8_t + BEACON_CFG_TYPE_UDB_RETRANS_INTERVAL = 1, //!< uint16_t, unit: ms + BEACON_CFG_TYPE_SNB_RETRANS_COUNT = 2, //!< uint8_t + BEACON_CFG_TYPE_SNB_RETRANS_INTERVAL = 3, //!< uint16_t, unit: ms +#if MESH_PRB + BEACON_CFG_TYPE_PRB_RETRANS_COUNT = 4, //!< uint8_t + BEACON_CFG_TYPE_PRB_RETRANS_INTERVAL = 5, //!< uint16_t, unit: ms +#endif +} beacon_cfg_type_t; +/** @} */ + +/** @defgroup Mesh_Beacon_Exported_Functions Exported Functions + * @{ + */ + +///@cond +void beacon_deinit(void); +///@endcond + +/** + * @brief generate uri hash + * @param[in] uri_data: uri + * @param[in] len: uri length + * @return none + */ +void beacon_uri_hash_gen(uint8_t uri_data[], uint16_t len); + +/** + * @brief calculate uri hash + * @param[in] uri_data: uri + * @param[in] len: uri length + * @param[in] uri_hash: uri hash value + */ +void beacon_uri_hash_calc(uint8_t uri_data[], uint16_t len, uint8_t uri_hash[4]); + +/** + * @brief send snb via proxy + * @return none + */ +void beacon_snb_send_via_proxy(void); + +/** + * @brief send beacon + * @return none + */ +void beacon_send(void); + +/** + * @brief start beacon + * @return none + */ +void beacon_start(void); + +/** + * @brief stop beacon + * @return none + */ +void beacon_stop(void); + +#if MESH_PRB +/** + * @brief send private beacon + * @return none + */ +void private_beacon_send(void); + +/** + * @brief start private beacon + * @return none + */ +void private_beacon_start(void); + +/** + * @brief stop private beacon + * @return none + */ +void private_beacon_stop(void); + +/** + * @brief update private beacon random + * @return none + */ +void private_beacon_random_udpate(void); + +/** + * @brief update private beacon random timer + * @param[in] new_interval: new timer interval, unit is second + */ +void private_beacon_random_timer_update(uint32_t new_interval); + +/** + * @brief send private beacon in gatt bearer + */ +void beacon_prb_send_via_proxy(void); +#endif + +/** + * @brief recevie beacon + * @param[in] bt_addr: bt addr + * @param[in] bt_addr_type: bt addr type + * @param[in] rssi: rssi + * @param[in] pbuffer: beacon + * @param[in] len: beacon length + * @return none + */ +void beacon_receive(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, uint8_t *pbuffer, + uint8_t len); + +/** + * @brief configure the mesh service adv + * @param[in] type: the parameter type, @ref beacon_cfg_type_t + * @param[in] param: the parameter pointer + * @param[in] param_len: the parameter length + * @return operation result + */ +bool beacon_cfg(beacon_cfg_type_t type, uint8_t *param, uint16_t param_len); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_BEACON_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_bearer.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_bearer.h new file mode 100644 index 00000000..09d7672b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_bearer.h @@ -0,0 +1,184 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_bearer.h + * @brief Head file for mesh bearer layer. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_BEARER_H +#define _MESH_BEARER_H + +/* Add Includes here */ +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Bearer + * @{ + */ + +/** @defgroup Mesh_Bearer_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/* Add all public types here */ +/** advertising bearer params */ +#define BEARER_ADV_LEN_OFFSET 0 +#define BEARER_ADV_TYPE_OFFSET 1 +#define BEARER_ADV_HEADER_SIZE 2 //!< length + flag +#define BEARER_ADV_PDU_OFFSET BEARER_ADV_HEADER_SIZE + +#define RSSI_NOT_AVAILABLE 0x7F +/** @} */ + +/** @defgroup Mesh_Bearer_Exported_Types Exported Types + * @brief + * @{ + */ + +/** mesh bearer type */ +typedef enum +{ + BEARER_TYPE_LOOPBACK, + BEARER_TYPE_ADV, + BEARER_TYPE_GATT, + BEARER_TYPE_OTHER +} bearer_type_t; + +typedef enum +{ + BEARER_FIELD_LOOPBACK = BIT0, + BEARER_FIELD_ADV = BIT1, + BEARER_FIELD_GATT = BIT2, + BEARER_FIELD_OTHER = BIT3, + BEARER_FIELD_ALL = BIT0 | BIT1 | BIT2 | BIT3 +} bearer_field_t; + +typedef enum +{ + BEARER_PKT_TYPE_MESH_PKT, + BEARER_PKT_TYPE_MESH_BEACON, + BEARER_PKT_TYPE_MESH_PB_ADV, + BEARER_PKT_TYPE_GATT_SERVICE_ADV, //!< connectable + BEARER_PKT_TYPE_OTHER //!< default non-connectable +} bearer_pkt_type_t; + +typedef enum +{ + BEARER_MESH_PKT_TYPE_NORMAL, + BEARER_MESH_PKT_TYPE_RELAY +} bearer_mesh_pkt_type_t; + +typedef struct +{ + uint8_t length; //!< just include flag + uint8_t flag; + uint8_t pdu[29]; +} _PACKED4_ bearer_adv_pkt_t, *bearer_adv_pkt_p; + +typedef bool (*pf_bearer_other_send_t)(bearer_pkt_type_t pkt_type, uint16_t dst, uint8_t *pbuffer, + uint16_t len); + +/** @} */ + +/** @defgroup Mesh_Bearer_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief reg the send api of the other bearer + * + * The other bearer extends the mesh network. + * @param[in] send: send api + * @return none + */ +void bearer_other_reg(pf_bearer_other_send_t send); + +/** + * @brief receive from the other bearer + * + * The other bearer extends the mesh network. + * @param[in] pkt_type: packet type + * @param[in] pbuffer: packet + * @param[in] len: packet length + * @return none + */ +void bearer_other_receive(bearer_pkt_type_t pkt_type, uint8_t *pbuffer, uint16_t len); + +/** + * @brief receive from the loopback bearer + * @param[in] pbuffer: packet + * @param[in] len: packet length + * @return none + */ +void bearer_loopback_receive(uint8_t *pbuffer, uint16_t len); + +/** + * @brief receive from the adv bearer + * @param[in] adv_report_type: packet type + * @param[in] bt_addr: packet + * @param[in] addr_type: packet length + * @param[in] rssi: rssi + * @param[in] pbuffer: packet + * @param[in] len: packet length + * @return none + */ +void bearer_adv_receive(gap_sched_adv_report_type_t adv_report_type, uint8_t bt_addr[6], + uint8_t addr_type, int8_t rssi, uint8_t *pbuffer, uint16_t len); + +/** + * @brief get the state of the adv bearer + * + * The adv bearer is default on after initialization in @ref mesh_init. + * @return the adv bearer state + * @retval true: on + * @retval false: off + */ +bool bearer_adv_get(void); + +/** + * @brief open or close the adv bearer + * @param[in] on_off: the adv bearer state + * @return none + */ +void bearer_adv_set(bool on_off); + +/** + * @brief send to the bearer layer + * @param[in] pkt_type: packet type + * @param[in] pbuffer: packet + * @param[in] len: packet length + * @return none + */ +void bearer_send(bearer_pkt_type_t pkt_type, uint8_t *pbuffer, uint16_t data_len); + +/** + * @brief send mesh msg to the bearer layer + * @param[in] pkt_type: packet type + * @param[in] pmesh_msg: mesh msg + * @return none + */ +void bearer_send_mesh_msg(bearer_mesh_pkt_type_t pkt_type, mesh_msg_p pmesh_msg); + +/** + * @brief initialize the bearer + * @return none + */ +void bearer_init(void); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_BEARER_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_common.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_common.h new file mode 100644 index 00000000..22c0f196 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_common.h @@ -0,0 +1,261 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_common.h + * @brief Head file for mesh common part. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-9-14 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_COMMON_H +#define _MESH_COMMON_H + +/* Add Includes here */ +#include "mesh_api.h" +#include "mesh_config.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Common + * @{ + */ + +/** @defgroup Mesh_Common_Exported_Types Exported Types + * @{ + */ + +/** @brief Timers used by the mesh stack */ +typedef enum +{ + MESH_IV_INDEX_TIMER_ID = 0, + MESH_SCAN_TIMER_ID = 1, + MESH_ADV_TIMER_ID = 2, + MESH_FORWORD_TABLE_REFRESH_TIMER_ID = 3, + MESH_BEACON_TIMER_ID = 4, + MESH_SERVICE_TIMER_ID = 5, + MESH_SERVICE_ID_TIMER_ID = 6, + MESH_PROVISIONING_TIMER_ID = 7, + MESH_ATTN_TIMER_ID = 8, + MESH_PB_ADV_TIMER_ID = 9, + MESH_TRANS_TX_TIMER_ID = 10, + MESH_TRANS_RX_TIMER_ID = 11, + MESH_TRANS_RX_INCOMPLETE_TIMER_ID = 12, + MESH_FRIENDSHIP_TIMER_ID = 13, + MESH_PB_MESH_TIMER_ID = 14, + MESH_HB_TIMER_ID = 15, + MESH_TICK_TIMER_ID = 16, + MESH_TRANS_LPN_POLL_ACK_TIMER_ID = 17, +#if MESH_PRB + MESH_PRIVATE_BEACON_TIMER_ID = 100, + MESH_PRIVATE_BEACON_RANDOM_UPDATE_TIMER_ID, + MESH_PRIVATE_SERVICE_TIMER_ID, + MESH_PRIVATE_SERVICE_ID_TIMER_ID, +#endif +} mesh_timer_id_t; + +typedef enum +{ + MESH_REBOOT = 0, + MESH_BT_STATUS_UPDATE = 1, + MESH_GAP_SCHEDULER_TIMEOUT = 2, + MESH_IV_TIMEOUT = 3, + MESH_BEACON_TIMEOUT = 4, + MESH_SERVICE_TIMEOUT = 5, + MESH_SERVICE_ID_TIMEOUT = 6, + MESH_PROVISIONING_TIMEOUT = 7, + MESH_ATTN_TIMEOUT = 8, + MESH_PB_ADV_TIMEOUT = 9, + MESH_TRANS_TRX_TIMEOUT = 10, + MESH_GAP_SCHEDULER_TASK_AVAILABLE = 11, + MESH_GAP_SCHEDULER_TASK_FREE = 12, + MESH_FN_TIMEOUT = 13, + MESH_LPN_TIMEOUT = 14, + MESH_RMT_PRO_TIMEOUT = 15, + MESH_PROV_SRV_PDU_TX_DONE = 16, + MESH_PROXY_CTX_RX_TIMEOUT = 17, + MESH_HB_TIMEOUT = 18, + MESH_MODEL_PUB_TIMEOUT = 19, + MESH_BEARER_LOCAL_LOOPBACK = 20, + MESH_TICK_TIMEOUT = 21, + MESH_MODEL_DELAY_EXECUTION_TIMEOUT = 22, + MESH_TRANS_LPN_POLL_ACK_TIMEOUT = 23, +#if MESH_PRB + MESH_PRIVATE_BEACON_TIMEOUT = 100, + MESH_PRIVATE_BEACON_RANDOM_UPDATE_TIMEOUT, + MESH_PRIVATE_SERVICE_TIMEOUT, + MESH_PRIVATE_SERVICE_ID_TIMEOUT, +#endif +#if MESH_BLOB + MESH_BLOB_SERVER_TRANSFER_TIMEOUT = 110, + MESH_BLOB_SERVER_PARTIAL_REPORT_TIMEOUT, +#endif +#if MESH_RPR + MESH_REMOTE_PROV_TIMEOUT = 120, +#endif +} mesh_inner_msg_type_t; + +typedef enum +{ + MESH_UNKNOWN, + MESH_PROVED, + MESH_NODE_RESET, + MESH_OTA +} mesh_reboot_reason_t; + +typedef struct _mesh_inner_msg_t +{ + uint16_t type; //!< @ref mesh_inner_msg_type_t + uint16_t sub_type; + union + { + uint32_t parm; + void *pbuf; + }; +} mesh_inner_msg_t; + +/* + * udb/provision adv/proxy adv callback + */ +typedef enum +{ + DEVICE_INFO_UDB, + DEVICE_INFO_PROV_ADV, + DEVICE_INFO_PROXY_ADV +} device_info_type_t; + +typedef struct +{ + device_info_type_t type; + uint16_t len; + union + { + beacon_udb_t *pbeacon_udb; + mesh_service_data_t *pservice_data; + }; +} device_info_t; + +typedef void (*device_info_cb_pf)(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, + device_info_t *pinfo); +extern device_info_cb_pf pf_device_info_cb; + +typedef void (*tick_timeout_cb)(void); + +typedef void (*model_delay_execution_timeout_cb)(void *pargs); + +/** @} */ + +/** @defgroup Mesh_Common_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief reg the callback to indicate the information of neighbor mesh devices + * @param[in] cb: callback + * @return none + */ +void device_info_cb_reg(device_info_cb_pf cb); + +/** + * @brief init the mesh stack + * @return none + */ +void mesh_init(void); + +/** + * @brief start the mesh stack + * @param[in] event_mesh: the event type of the mesh inner msg + * @param[in] event_app: the event type sent to app by the mesh stack + * @param[in] event_queue: the event queue to send event + * @param[in] app_queue: the app queue to send message + * @return none + */ +void mesh_start(uint8_t event_mesh, uint8_t event_app, void *event_queue, void *app_queue); + +///@cond +void mesh_run(void); +///@endcond + +/** + * @brief deinit the mesh stack + * + * release all the resources and reset the global variables + * @return none + */ +void mesh_deinit(void); + +/** + * @brief reboot with delay + * @param[in] reason: reboot reason + * @param[in] delay_ms: if it is 0, reboot right now + * @return none + */ +void mesh_reboot(mesh_reboot_reason_t reason, uint32_t delay_ms); + +/** + * @brief send the mesh inner msg + * @param[in] pmsg: message + * @return operation result + */ +bool mesh_inner_msg_send(mesh_inner_msg_t *pmsg); + +/** + * @brief handle the mesh inner message + * @param[in] event: mesh event + * @return none + */ +void mesh_inner_msg_handle(uint8_t event); + +/** + * @brief start the tick timer + * + * The mesh stack provides a gerneral tick timer + * @param[in] tick_ms: tick + * @param[in] tick_cb: timeout callback + * @return none + */ +void mesh_tick_timer_start(uint32_t tick_ms, tick_timeout_cb tick_cb); + +/** + * @brief stop the tick timer + * @return none + */ +void mesh_tick_timer_stop(void); + +/** + * @brief get the tick timer state + * @return tick timer state + * @retval true: running + * @retval false: not running + */ +bool mesh_tick_timer_is_running(void); + +/** + * @brief initialize model delay execution + * @param[in] delay_cb: delay execution timeout callback function + * @return none + */ +void mesh_model_delay_execution_init(model_delay_execution_timeout_cb delay_cb); + +/** + * @brief check the compatibility between the sdk and lib + * @param[in] sdk_ver: the sdk version + * @param[in] gcid: the git commit id + * @return the compatibility + * @retval 0: compatible + * @retval >0: incompatible due to the lib is old + * @retval <0: incompatible due to the sdk is old + */ +int mesh_version_check(const char *sdk_ver, uint32_t gcid); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_COMMON_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_flash.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_flash.h new file mode 100644 index 00000000..f7d9c174 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_flash.h @@ -0,0 +1,144 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_flash.h + * @brief Head file for mesh flash storage. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-2-21 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_FLASH_H +#define _MESH_FLASH_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "ftl.h" +#include "mesh_api.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Flash + * @{ + */ + +/** @defgroup Mesh_Flash_Exported_Macros Exported Macros + * @{ + */ + +/** fake num */ +#ifdef MESH_PROVISIONER +#define MESH_DEV_KEY_NUM_MAX 3 +#else +#define MESH_DEV_KEY_NUM_MAX 1 +#endif +#define MESH_NET_KEY_NUM_MAX 3 +#define MESH_APP_KEY_NUM_MAX 3 +#define MESH_VIR_ADDR_NUM_MAX 3 +#define MESH_RPL_ENTRY_NUM_MAX 20 +#define MESH_MODEL_NUM_MAX 1 +#define MESH_MODEL_SUB_ADDR_NUM_MAX 10 + +// Flash Storage Offset +#define MESH_FLASH_OFFSET mesh_node.flash_offset +#define MESH_FLASH_SIZE_MAX mesh_node.flash_size + +/** @} */ + +/** @defgroup Mesh_Flash_Exported_Types Exported Types + * @{ + */ + +typedef enum +{ + MESH_FLASH_PARAMS_NODE_INFO, + MESH_FLASH_PARAMS_IV_INDEX, + MESH_FLASH_PARAMS_IV_UPDATE_FLAG, + MESH_FLASH_PARAMS_SEQ, + MESH_FLASH_PARAMS_TTL, + MESH_FLASH_PARAMS_FEATURES, + MESH_FLASH_PARAMS_NWK_TX_PARAMS, + MESH_FLASH_PARAMS_HB_PARAMS, + MESH_FLASH_PARAMS_DEV_KEY, + MESH_FLASH_PARAMS_NET_KEY, + MESH_FLASH_PARAMS_APP_KEY, + MESH_FLASH_PARAMS_VIR_ADDR, + MESH_FLASH_PARAMS_RPL, + MESH_FLASH_PARAMS_RPL_ENTRY, + MESH_FLASH_PARAMS_RPL_SEQ, + MESH_FLASH_PARAMS_MODEL_PUB_PARAMS, + MESH_FLASH_PARAMS_MODEL_APP_KEY_BINDING, + MESH_FLASH_PARAMS_MODEL_SUBSCRIBE_ADDR +} flash_params_type_t; + +typedef struct +{ + uint8_t rpl_loop; + uint16_t entry_loop; +} rpl_entry_info_t; + +/** @} */ + +/** @defgroup Mesh_Flash_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief save the data to the Flash just like the RAM + * + * There is no need to worry about the read/erase/write operation of the flash + * @param[in] pdata: the data pointer + * @param[in] size: the data size + * @param[in] offset: the data offset + * @return the operation result + * @retval 0: success + * @retval !0: fail + */ +#define mesh_flash_save(pdata, size, offset) ftl_save(pdata, offset, size) + +/** + * @brief load the data to the Flash just like the RAM + * + * There is no need to worry about the read/erase/write operation of the flash + * @param[out] pdata: the data pointer + * @param[in] size: the data size + * @param[in] offset: the data offset + * @return the operation result + * @retval 0: success + * @retval !0: fail + */ +#define mesh_flash_load(pdata, size, offset) ftl_load(pdata, offset, size) + +/** + * @brief load the node state from the NVM + * + * It can be usde to get the node state in advance of mesh_init. + * !!!Attention: the API shall be called after all the models have bee registered!!! + * + * @return the node state + */ +mesh_node_state_t mesh_flash_restore_node_state(void); +#define mesh_node_state_restore mesh_flash_restore_node_state + +///@cond +void mesh_flash_store(flash_params_type_t param_type, void *param); +void mesh_flash_restore(void); +void mesh_flash_clear(void); +bool mesh_flash_restore_msg_id(uint16_t *unicast_addr, uint32_t *iv_index, uint32_t *seq, + bool *iv_update_flag); +bool mesh_flash_retore_net_key(uint16_t net_key_index, uint16_t *net_key_index_g, + uint8_t key[MESH_COMMON_KEY_SIZE]); +uint32_t mesh_flash_total_size(void); +///@endcond + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_FLASH_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_network.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_network.h new file mode 100644 index 00000000..6efd8cbe --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_network.h @@ -0,0 +1,101 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_network.h + * @brief Head file for mesh network layer. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_NETWORK_H +#define _MESH_NETWORK_H + +/* Add Includes here */ +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Network + * @{ + */ + +/** @defgroup Mesh_Network_Exported_Macros Exported Macros + * @brief + * @{ + */ +#define MESH_NWK_HEADER_SIZE 9 +#define MESH_NWK_ENC_OFFSET 7 //!< The encryption of network layer starts from the destincation address! +#define MESH_NWK_PRIVACY_HEADER_OFFSET 1 +#define MESH_NWK_PRIVACY_HEADER_SIZE 6 +#define MESH_NWK_PKT_MIN_SIZE (MESH_NWK_HEADER_SIZE + 4) //!< open interval +#define MESH_NWK_PKT_MIN_SIZE1 (MESH_NWK_HEADER_SIZE + 8) + +#define MESH_RELAY_MIN_TTL 2 +/** @} */ + +/** @defgroup Mesh_Network_Exported_Types Exported Types + * @brief + * @{ + */ + +/** @brief mesh network packet format */ +typedef struct +{ + uint8_t nid: 7; //!< least significant 7 bits of network identity + uint8_t ivi: 1; //!< least significant bit of initialization vector index + uint8_t ttl: 7; //!< time to live + uint8_t ctl: 1; //!< Network Control, NetMIC size & Access Message/Control Message indicator + uint8_t seq[3]; //!< sequence number + uint16_t src; //!< source address + uint16_t dst; //!< destination address + /** trans payload with a varying length of 1 ~ 16 bytes, + * and 4 or 8 bytes network message integrity check (NetMIC) + */ + uint8_t trans_payload[16 + 4]; +} _PACKED4_ net_pkt_t; + +/** @} */ + +/** @defgroup Mesh_Network_Exported_Functions Exported Functions + * @brief + * @{ + */ + +///@cond +void nmc_init(void); +void nmc_deinit(void); +void nmc_clear(void); +bool nmc_check(uint32_t iv_index, uint16_t src, uint32_t seq); +void nmc_update(uint32_t iv_index, uint16_t src, uint32_t seq); +///@endcond + +/** + * @brief send mesh msg to the network layer + * @param[in] pmesh_msg: mesh msg + * @return send result + */ +mesh_msg_send_cause_t net_send(mesh_msg_p pmesh_msg); + +/** + * @brief send mesh msg to the bearer layer + * @param[in] bearer_type: packet type + * @param[in] pbuffer: mesh msg + * @param[in] len: mesh msg length + * @param[in] rssi: valid at the adv bearer + * @return source address + * @retval MESH_UNASSIGNED_ADDR: something wrong + */ +uint16_t net_receive(bearer_type_t bearer_type, uint8_t *pbuffer, uint16_t len, int8_t rssi); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_NETWORK_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_node.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_node.h new file mode 100644 index 00000000..3ea83044 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_node.h @@ -0,0 +1,981 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_node.h + * @brief Head file for mesh node management. + * @details Data types and external functions declaration. + * @author bill + * @date 2016-1-20 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_NODE_H +#define _MESH_NODE_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "mesh_config.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Node + * @{ + */ + +/** @defgroup Mesh_Node_Exported_Types Exported Types + * @{ + */ + +typedef enum +{ + MESH_ROLE_DEVICE, + MESH_ROLE_PROVISIONER +} mesh_role_t; + +enum +{ + UNPROV_DEVICE, + PROV_NODE +} _SHORT_ENUM_; +typedef uint8_t mesh_node_state_t; + +/* + * used in composition data page0 (little endian) & heartbeat msg (big endian) + */ +typedef struct +{ + uint16_t relay: 1; + uint16_t proxy: 1; + uint16_t fn: 1; + uint16_t lpn: 1; + uint16_t rfu: 12; +} _PACKED4_ mesh_features_t, *mesh_features_p; + +typedef struct +{ + //uint8_t element_num; + //uint8_t model_num; + uint16_t dev_key_num; + uint16_t net_key_num; + uint16_t app_key_num; + uint16_t vir_addr_num; //!< the number of virtual address + uint16_t rpl_num; //!< the number of replay protection list entries + uint8_t sub_addr_num; //!< the number of subscribe address per model + uint8_t proxy_num; //!< the number of proxy server, only support at most one now + + uint16_t udb_interval; //!< unit: 100 millisecond, 0: use stack default value + uint16_t snb_interval; //!< unit: 100 millisecond, 0: use stack default value + uint16_t prov_interval; //!< unit: 100 millisecond, 0: use stack default value + uint16_t proxy_interval; //!< unit: 100 millisecond, 0: use stack default value + uint16_t identity_interval; //!< unit: 100 millisecond, 0: use stack default value +#if MESH_PRB + uint16_t prb_interval; //!< unit: 100 millisecond, 0: use stack default value + uint32_t prb_random_update_interval; //!< unit: 100 millisecond, 0: use stack default value +#endif +} mesh_node_cfg_t, *mesh_node_cfg_p; + +typedef struct +{ + uint32_t used: 1; //!< flag used for flash + uint32_t role: 1; //!< 1: provisioner, 0: node @ref mesh_role_t + + /** + * 0x00 Feature or Service is supported but disabled + * 0x01 Feature or Service is supported and enabled + * 0x02 Feature or Service is not supported + */ + uint32_t relay: 2; //!< relay + uint32_t proxy: 2; //!< Mesh Proxy Service & Proxy feature, binding with node identity + uint32_t fn: 2; //!< friend feature + uint32_t lpn: 2; //!< low power feature + uint32_t prov: 2; //!< 1: start sending prov adv (pb-gatt) at first + + uint32_t udb: 1; //!< 1: start udb at first + uint32_t snb: 1; //!< state can be changed by Config Beacon Set + uint32_t bg_scan: 1; //!< 1: start background scan at first + + uint32_t cfg_model_use_app_key: 1;//!< 1: can use app key in configuration models + + uint32_t flash: 1; //!< enable/disable flash storage + uint32_t flash_rpl: 1; //!< rpl has an cascade flash storage control above flash bit + + uint32_t prb : 1; //!< state can be changed by private beacon set + uint32_t private_proxy: 2; //!< Mesh Private Proxy + + uint32_t rfu: 11; +} mesh_node_features_t; + +/** @defgroup Mesh_Address Mesh Address + * @brief Mesh Address definition. + * @{ + */ +typedef enum +{ + MESH_ADDR_TYPE_UNASSIGNED, + MESH_ADDR_TYPE_UNICAST, + MESH_ADDR_TYPE_VIRTUAL, + MESH_ADDR_TYPE_GROUP +} mesh_addr_type_t; + +#define MESH_UNICAST_ADDR_MASK 0x7FFF +#define MESH_VIRTUAL_ADDR_MASK 0x3FFF +#define MESH_GROUP_ADDR_MASK 0x3FFF + +#define MESH_UNASSIGNED_ADDR 0x0000 +#define MESH_GROUP_ADDR_DYNAMIC_START 0xC000 +#define MESH_GROUP_ADDR_DYNAMIC_END 0xFEFF +#define MESH_GROUP_ADDR_FIX_START 0xFF00 +#define MESH_GROUP_ADDR_ALL_PROXY 0xFFFC +#define MESH_GROUP_ADDR_ALL_FRND 0xFFFD +#define MESH_GROUP_ADDR_ALL_RELAY 0xFFFE +#define MESH_GROUP_ADDR_ALL_NODE 0xFFFF + +#define MESH_IS_UNASSIGNED_ADDR(addr) ((addr) == MESH_UNASSIGNED_ADDR) +#define MESH_NOT_UNASSIGNED_ADDR(addr) ((addr) != MESH_UNASSIGNED_ADDR) +#define MESH_IS_UNICAST_ADDR(addr) ((addr) != MESH_UNASSIGNED_ADDR && ((addr) & 0x8000) == 0x0000) +#define MESH_NOT_UNICAST_ADDR(addr) ((addr) == MESH_UNASSIGNED_ADDR || ((addr) & 0x8000) != 0x0000) +#define MESH_IS_VIRTUAL_ADDR(addr) (((addr) & 0xC000) == 0x8000) +#define MESH_NOT_VIRTUAL_ADDR(addr) (((addr) & 0xC000) != 0x8000) +#define MESH_IS_GROUP_ADDR(addr) (((addr) & 0xC000) == 0xC000) +#define MESH_NOT_GROUP_ADDR(addr) (((addr) & 0xC000) != 0xC000) +#define MESH_IS_RFU_GROUP_ADDR(addr) ((addr) >= MESH_GROUP_ADDR_FIX_START && (addr) < MESH_GROUP_ADDR_ALL_PROXY) +#define MESH_IS_BROADCAST_ADDR(addr) ((addr) == MESH_GROUP_ADDR_ALL_NODE) +#define MESH_NOT_BROADCAST_ADDR(addr) ((addr) != MESH_GROUP_ADDR_ALL_NODE) +#define MESH_IS_SUBSCRIBE_ADDR(addr) ((addr) != MESH_GROUP_ADDR_ALL_NODE && ((addr) & 0x8000) == 0x8000) +#define MESH_NOT_SUBSCRIBE_ADDR(addr) ((addr) == MESH_GROUP_ADDR_ALL_NODE || ((addr) & 0x8000) != 0x8000) +#define MESH_IS_MY_ADDR(addr) ((addr) >= mesh_node.unicast_addr && (addr) - mesh_node.unicast_addr < mesh_node.element_queue.count) +#define MESH_NOT_MY_ADDR(addr) ((addr) < mesh_node.unicast_addr || (addr) - mesh_node.unicast_addr >= mesh_node.element_queue.count) + +typedef struct _mesh_addr_member_t +{ + struct _mesh_addr_member_t *pnext; + uint16_t mesh_addr; +} mesh_addr_member_t, *mesh_addr_member_p; +/** @} End of Mesh_Address */ + +/** @defgroup Model Model + * @brief types used for model. + * @{ + */ + +/** @defgroup Model_ID Model ID + * @brief + * @{ + */ +#define MESH_IS_SIG_MODEL(model_id) (((model_id) & 0xffff) == 0xffff) +#define MESH_IS_VENDOR_MODEL(model_id) (((model_id) & 0xffff) != 0xffff) +/* from spec to implement */ +#define MESH_MODEL_TRANSFORM(model_id) (0xffff + ((model_id) << 16)) //LE_EXTRN2WORD((uint8_t *)&(model_id)) +/* from implement to spec */ +#define MESH_MODEL_CONVERT(model_id) (MESH_IS_SIG_MODEL(model_id) ? ((model_id) >> 16) : (model_id)) +/** @} End of Model_ID */ + +typedef struct _mesh_msg_t *mesh_msg_p; +typedef struct _mesh_model_info_t *mesh_model_info_p; +typedef enum _mesh_msg_send_stat_t mesh_msg_send_stat_t; +typedef bool (*model_receive_pf)(mesh_msg_p pmesh_msg); +typedef int32_t (*model_pub_cb_pf)(mesh_model_info_p pmodel_info, bool retrans); +typedef void (*model_send_cb_pf)(mesh_model_info_p pmodel_info, mesh_msg_send_stat_t stat, + uint32_t access_opcode); +typedef int32_t (*model_data_cb_pf)(const mesh_model_info_p pmodel_info, uint32_t type, + void *pargs); +#if MESH_MODEL_ENABLE_DEINIT +typedef void (*model_deinit_cb_pf)(mesh_model_info_p pmodel_info); +#endif +typedef struct _mesh_model_info_t +{ + /** provided by application */ + uint32_t model_id; //!< being equal or greater than 0xffff0000 means that the model is a sig model. + /** callback to receive related access msg + If the model don't recognise the access opcode, it should return false! */ + model_receive_pf model_receive; + model_send_cb_pf model_send_cb; //!< indicates the msg transmitted state + model_pub_cb_pf model_pub_cb; //!< indicates it is time to publishing + model_data_cb_pf model_data_cb; +#if MESH_MODEL_ENABLE_DEINIT + model_deinit_cb_pf model_deinit; +#endif + /** point to the bound model, sharing the subscription list with the binding model */ + struct _mesh_model_info_t *pmodel_bound; + /** configured by stack */ + uint8_t element_index; + uint8_t model_index; + void *pelement; + void *pmodel; + void *pargs; +} mesh_model_info_t; + +typedef struct +{ + uint16_t pub_addr; + pub_key_info_t pub_key_info; + uint8_t pub_ttl; + pub_period_t pub_period; + pub_retrans_info_t pub_retrans_info; +} mesh_model_pub_params_t; + +typedef struct _mesh_model_t +{ + struct _mesh_model_t *pnext; + mesh_model_info_p pmodel_info; + uint8_t model_index; //!< global index + mesh_model_pub_params_t pub_params; + plt_timer_t pub_timer; + uint8_t retrans_count; //!< counter + //uint16_t app_key_index; //key maybe deleted + uint8_t *app_key_binding; //!< dumm... + plt_list_t sub_queue; //!< subscribe addr list +} mesh_model_t, *mesh_model_p; + +/** @} End of Model */ + +/** @defgroup Element Element + * @brief + * @{ + */ +typedef enum +{ + GATT_NS_DESC_UNKNOWN = 0x0000, + GATT_NS_DESC_FIRST = 0x0001, + GATT_NS_DESC_SECOND = 0x0002, + GATT_NS_DESC_THIRD = 0x0003, + GATT_NS_DESC_255 = 0x00ff, + GATT_NS_DESC_FRONT = 0x0100, + GATT_NS_DESC_BACK = 0x0101, + GATT_NS_DESC_TOP = 0x0102, + GATT_NS_DESC_BOTTOM = 0x0103, + GATT_NS_DESC_UPPER = 0x0104, + GATT_NS_DESC_LOWER = 0x0105, + GATT_NS_DESC_MAIN = 0x0106, + GATT_NS_DESC_BACKUP = 0x0107, + GATT_NS_DESC_AUXILIARY = 0x0108, + GATT_NS_DESC_SUPPLEMENTARY = 0x0109, + GATT_NS_DESC_FLASH = 0x010A, + GATT_NS_DESC_INSIDE = 0x010B, + GATT_NS_DESC_OUTSIDE = 0x010C, + GATT_NS_DESC_LEFT = 0x010D, + GATT_NS_DESC_RIGHT = 0x010E, + GATT_NS_DESC_INTERNAL = 0x010F, + GATT_NS_DESC_EXTERNAL = 0x0110 +} gatt_ns_desc_t; //!< GATT namespace description + +typedef void (*mesh_attn_cb_pf)(uint8_t element_index, uint32_t timer_ms); + +typedef struct _mesh_element_t +{ + struct _mesh_element_t *pnext; + uint8_t element_index; + uint16_t loc; //!< element location @ref gatt_ns_desc_t + plt_list_t model_queue; //!< @ref mesh_model_t + uint32_t attn_timer; //!< in unit of millisecond +} mesh_element_t, *mesh_element_p; +/** @} End of Element */ + +#define MESH_COMMON_KEY_SIZE 16 +typedef struct +{ + uint8_t key[MESH_COMMON_KEY_SIZE]; +} mesh_key_t, *mesh_key_p; + +typedef enum +{ + MESH_KEY_STATE_INVALID, //!< invalid state + /** current 0, old 0, new 1 */ + MESH_KEY_STATE_NORMAL1, //!< phase 0: Normal state, Tx is the same as Rx + MESH_KEY_STATE_UPDATE1, //!< phase 1: Tx old, Rx old & new + MESH_KEY_STATE_REFRESH1, //!< phase 2: Tx new, Rx old & new + /** current 1, old 1, new 0 */ + MESH_KEY_STATE_NORMAL2, //!< Normal state, Tx is the same as Rx + MESH_KEY_STATE_UPDATE2, //!< Tx old, Rx old & new + MESH_KEY_STATE_REFRESH2 //!< Tx new, Rx old & new +} mesh_key_state_t; + +typedef struct +{ + /** origin NetKey */ + uint8_t net_key[MESH_COMMON_KEY_SIZE]; + /** keys used to secure nwk pdu */ + uint8_t nid; //!< 7 bit value + uint8_t encrypt_key[MESH_COMMON_KEY_SIZE]; + uint8_t privacy_key[MESH_COMMON_KEY_SIZE]; + /** keys used in snb & proxy adv */ + uint8_t net_id[8]; + uint8_t beacon_key[MESH_COMMON_KEY_SIZE]; + uint8_t identity_key[MESH_COMMON_KEY_SIZE]; +#if MESH_PRB + /** keys used in prb */ + uint8_t private_beacon_key[MESH_COMMON_KEY_SIZE]; +#endif +} net_key_t, *net_key_p; + +typedef struct +{ + mesh_key_state_t key_state; + uint8_t identity; //!< Binding with GATT Proxy state +#if MESH_PRB + uint8_t private_identity; //!< Binding with GATT Pirvate Proxy state +#endif + uint16_t net_key_index_g; //!< index of global NetKey list, bit15 represent wheather it is a frnd key + net_key_p pnet_key[2]; +} net_key_list_t, *net_key_list_p; + +typedef struct +{ + uint8_t app_key[MESH_COMMON_KEY_SIZE]; + uint8_t aid; //!< the least significant 6 bits +} app_key_t, *app_key_p; + +typedef struct +{ + mesh_key_state_t key_state; + uint16_t net_key_binding; //!< index of local NetKey list + uint16_t app_key_index_g; //!< index of global AppKey list + app_key_p papp_key[2]; +} app_key_list_t, *app_key_list_p; + +typedef struct +{ + uint16_t unicast_addr; + uint8_t element_num; + uint8_t used; + uint8_t dev_key[MESH_COMMON_KEY_SIZE]; +} _PACKED4_ dev_key_t; + +typedef struct +{ + uint16_t vir_addr; //!< used when bigger than 0 + uint16_t count; //!< in case reuse + uint8_t label_uuid[MESH_COMMON_KEY_SIZE]; +} _PACKED4_ vir_addr_t; + +/** @defgroup Compo_Data_Page0 Composition Data Page 0 + * @brief + * @{ + */ +typedef struct +{ + uint16_t company_id; + uint16_t product_id; + uint16_t version_id; + //uint16_t rpl_num; //!< the number of replay protection list entries + //mesh_features_t features; +} _PACKED4_ compo_data_page0_header_t, *compo_data_page0_header_p; +/** @} End of Compo_Data_Page0 */ + +#define MESH_MSG_RESERVED_NET_TRANS_COUNT 0xFF +#define MESH_MSG_RESERVED_NET_TRANS_STEPS 0xFF +#define MESH_MSG_RESERVED_DELAY_TIME 0xFFFFFFFF + +typedef struct _mesh_msg_t +{ + mesh_model_info_p pmodel_info; //!< indicate which model is sending/receiving this msg + uint8_t *pbuffer; //!< pointer to the msg + uint16_t msg_offset; + uint16_t msg_len; + uint32_t access_opcode; //!< opcode of access layer msg used when rx, access opcode is parsed by stack + uint16_t src; + uint16_t dst; + uint32_t seq; + uint32_t iv_index; + uint8_t ttl: 7; //!< Time To Live + uint8_t ctl: 1; //!< Access/Control Message Type & NetMIC Size Indicator + uint8_t aid: 6; //!< Least significant 6 bits of application key identifier + uint8_t akf: 1; //!< Application Key Flag + uint8_t seg: 1; //!< Transport Segment Flag + uint8_t trans_opcode: 7; //!< Opcode of the Transport Control message + uint8_t szmic: 1; //!< Size of TransMIC bit + uint8_t net_key_loop: 1; //!< old or new key, used in lpn frnd update + uint8_t frnd_flag: 1; //!< controlling the credentials when publish by lpn + uint8_t rfu : 6; + uint8_t trans_mic[8]; //!< 4 or 8 bytes according to szmic field + uint16_t app_key_index; + uint16_t net_key_index; + int8_t rssi; //!< used when rx in adv bearer + uint8_t net_trans_count; + uint8_t net_trans_steps; + uint32_t delay_time; //!< message send delay time, unit is ms + bearer_field_t bearer_field; //!< indicate which bearers sending to, or which bearer receiving from + gap_sched_link_t link; //!< indicate which links sending to, or which link receiving from +} mesh_msg_t; + +typedef struct +{ + /** network keys */ + net_key_list_p net_key_list; + uint16_t net_key_num; //!< 12 valid bits + uint16_t frnd_key_num; //!< save for frnd + /** application keys */ + app_key_list_p app_key_list; + uint16_t app_key_num; //!< 12 valid bits + /** device key */ + dev_key_t *dev_key_list; + uint16_t dev_key_num; //!< 15 valid bits + /** virtual address */ + vir_addr_t *vir_addr_list; + uint16_t vir_addr_num; //!< 14 valid bits + /** misc parameters */ + uint32_t seq; //!< 3 bytes used, unique per node + uint32_t seq_siv; //!< default value @ref MESH_SEQ_START_IV_UPDATE + uint32_t iv_index; + plt_timer_t iv_timer; + uint32_t iv_timer_count; + uint8_t ttl; + uint8_t dev_uuid[16]; + mesh_node_state_t node_state; + mesh_node_features_t features; + uint16_t udb_interval; //!< 100ms + uint16_t snb_interval; //!< 100ms + uint16_t prov_interval; //!< 100ms + uint16_t proxy_interval; //!< 100ms + uint16_t identity_interval; //!< 100ms + uint16_t identity_credit; //!< identity times in each interval +#if MESH_PRB + uint16_t prb_interval; //!< unit: 100 millisecond, 0: use stack default value + uint32_t prb_random_update_interval; //!< unit: 1 second, 0: use stack default value + uint16_t private_proxy_interval; //!< 100ms + uint16_t private_identity_interval; //!< 100ms +#endif + uint16_t unicast_addr; + plt_list_t element_queue; //!< @ref mesh_element_t + uint8_t model_num; + uint8_t sub_addr_num; //!< per model + uint8_t *compo_data[3]; //!< 0: page 0, 1: page 1, 2: page 128 + uint16_t compo_data_size[3]; + /** element attention */ + plt_timer_t attn_timer; + uint32_t attn_interval; //!< ms, range of 10ms ~ 1000ms + mesh_attn_cb_pf attn_cb; + /** bearer paramemeters */ + uint8_t pb_adv_retrans_count; //!< transmit (pb_adv_retrans_count + 1) times + uint8_t pb_adv_retrans_steps; //!< retransmission interval = (pb_adv_retrans_steps + 1) * 10ms + /** net parameters */ + uint8_t net_trans_count_base; //!< can't be modified by the cfg client + uint8_t net_trans_count; //!< :3 transmit (net_trans_count + net_trans_count_base + 1) times + uint8_t net_trans_steps; //!< :5 retransmission interval = (net_trans_steps + 1) * 10ms + uint8_t relay_retrans_count_base; //!< can't be modified by the cfg client + uint8_t relay_retrans_count; //!< :3 transmit (relay_retrans_count + relay_retrans_count_base + 1) times + uint8_t relay_retrans_steps; //!< :5 retransmission interval = (relay_retrans_steps + 1) * 10ms + uint16_t nmc_size; //!< net msg cache size default value @ref MESH_NET_MSG_CACHE_SIZE + uint8_t relay_parallel_num; + uint8_t relay_parallel_max; //!< default 3 + /** trans parameters */ + uint8_t trans_tx_queue_size; //!< the cache size of tx seg msgs, default value @ref MESH_TRANS_TX_QUEUE_SIZE + uint8_t trans_rx_ctx_count; //!< the count of seg msgs rx simultaneously, default value @ref MESH_TRANS_RX_CTX_COUNT + uint8_t trans_retrans_count; //!< the retransmit times of seg msg, default value @ref MESH_TRANS_RETRANSMIT_TIMES + uint16_t trans_retrans_base; //!< segment transmission timer base, unit is ms, default value 200ms + uint16_t trans_retrans_ttl_factor; //!< segment transmission timer ttl factor, uinit is ms, default value 50ms + uint16_t trans_retrans_seg_factor; //!< segment transmission timer seg num factor, uiit is ms, default value 30ms + uint16_t trans_ack_base; //!< segment transmission timer base, unit is ms, default value 150ms + uint16_t trans_ack_ttl_factor; //!< segment transmission timer ttl factor, uinit is ms, default value 50ms + uint16_t trans_ack_seg_factor; //!< segment transmission timer seg num factor, uiit is ms, default value 30ms + /** friendship parameters */ + uint8_t frnd_rx_window; //!< range: 0x01–0xFF ms (default 20ms), set by the fn + uint8_t frnd_rx_delay; //!< range: 0x0A–0xFF ms (default 10ms), set by the lpn + uint8_t frnd_rx_widen; //!< range: 0x00–0xFF ms (default 0ms), set by the lpn + uint8_t frnd_tx_ahead; //!< range: 0x00–0xFF ms (default 15ms), set by the fn + uint8_t frnd_poll_times; //!< default 1 times, set by the lpn + uint8_t frnd_upd_times; //!< default 11 times, set by the fn + uint16_t frnd_offer_rx_delay; //!< range: 0x01-0xFFFF ms (default 90ms), set by the lpn + uint16_t frnd_offer_wait_period; //!< range: 0x01-0xFFFF ms (default 1100ms), set by the lpn + uint16_t frnd_offer_choose_delay; //!< range: 0x01-0xFFFF ms (default 400ms), set by the lpn + uint16_t frnd_poll_retry_interval; //!< range: 0x01-0xFFFF ms (default 300ms), set by the lpn + uint8_t frnd_poll_retry_times; //!< range: 0x01-0xFF times (default 8times), set by the lpn + uint8_t frnd_poll_failed_times; //!< range: 0x01-0xFF times (default 1times), set by the lpn + uint32_t frnd_scan_delay_time; //!< range: 0x00-0xFFFFFFFF us (default 0 us), set by the lpn + /** beacon params */ + union + { + uint16_t oob_info_alias; + prov_oob_info_t oob_info; + }; + uint8_t uri_hash[4]; + /** platform params */ + uint32_t flash_offset; + uint32_t flash_size; + /** flags */ + /* Normal Operation: IV Update Flag = 0, IV Update in Progress: IV Update Flag = 1 */ + uint8_t iv_update_flag : 1; + uint8_t iv_pend_flag : 1; //!< pend state change from update to normal + uint8_t iv_test_flag : 1; + uint8_t uri_flag : 1; //!< flag to indicate URI Hash field in udb + uint8_t adv_bearer: 1; //!< default on + uint8_t node_uncheck_group_addr: 1; //!< default off + uint8_t check_reprov: 1; //!< default off + uint8_t cccd_not_check: 1; //!< default off + + /* configurable parameters */ +#if MESH_PARAM_CONFIGURABLE + uint16_t inner_msg_num; + uint32_t pb_generic_timeout; + uint32_t pb_adv_link_idle_timeout; + uint16_t pb_adv_retry_period; + uint32_t prov_timeout; + uint32_t proxy_sar_timeout; + uint8_t proxy_sar_buffer_len; + uint8_t frnd_queue_min_ttl; + uint8_t frnd_sub_list_size; + uint16_t frnd_timeout_period; + uint16_t seq_num_step; +#endif +} mesh_node_t, *mesh_node_p; + +extern mesh_node_t mesh_node; + +/** @} */ + +/** @defgroup Mesh_Node_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief set the device uuid + * @param[in] dev_uuid: the device uuid + * @return none + */ +void device_uuid_set(const uint8_t dev_uuid[16]); + +/** @brief + * @{ + */ +mesh_addr_type_t mesh_addr_type_classify(uint16_t addr); + +bool fixed_group_addr_check_by_model(uint16_t addr, mesh_model_p pmodel); +bool fixed_group_addr_check_by_node(uint16_t addr); + +uint16_t vir_addr_get_index(const uint8_t label_uuid[16]); +uint16_t vir_addr_get(uint16_t va_index); +bool vir_addr_available(void); +uint16_t vir_addr_add(const uint8_t label_uuid[16]); +void vir_addr_delete(uint16_t va_index); +/** @} */ + +/** @brief + * @{ + */ + +/** + * @brief set the device key + * @param[in] dev_key_index: the dev key index + * @param[in] unicast_addr: the node primary address + * @param[in] element_num: the element num of the node + * @param[in] pdev_key: the device key + * @return none + */ +void dev_key_set(uint16_t dev_key_index, uint16_t unicast_addr, uint8_t element_num, + uint8_t *pdev_key); +/** + * @brief get the device key + * @param[in] dev_key_index: the dev key index + * @param[out] pdev_key: the device key + * @return none + */ +void dev_key_get(uint16_t dev_key_index, uint8_t *pdev_key); + +/** + * @brief get the available device key index + * @return operation result + * @retval >=0: the dev key index + * @retval -1: not availabe + */ +int dev_key_get_available_idx(void); + +/** + * @brief find the device key of the node with the addr + * @param[in] unicast_addr: the node primary address + * @return operation result + * @retval >=0: the dev key index + * @retval -1: not found + */ +int dev_key_find(uint16_t unicast_addr); + +/** + * @brief add a device key + * @param[in] unicast_addr: the node primary address + * @param[in] element_num: the element num of the node + * @param[in] pdev_key: the device key + * @return operation result + * @retval >=0: the dev key index + * @retval -1: address collision + * @retval -2: no space for the new key + */ +int dev_key_add(uint16_t unicast_addr, uint8_t element_num, uint8_t *pdev_key); + +/** + * @brief delete the device key + * @param[in] dev_key_index: the dev key index + * @return none + */ +void dev_key_delete(uint16_t dev_key_index); + +/** @} */ + +/** @brief + * @{ + */ +uint8_t key_state_to_tx_loop(mesh_key_state_t key_state); +uint8_t key_state_to_new_loop(mesh_key_state_t key_state); +uint8_t key_state_to_frnd_key_loop(mesh_key_state_t key_state); +bool key_state_to_key_refresh_flag(mesh_key_state_t key_state); +uint8_t key_state_to_key_refresh_phase(mesh_key_state_t key_state); +/** @} */ + +/** @brief + * @{ + */ +uint16_t net_key_valid_num(void); +uint16_t net_key_index_to_global(uint16_t net_key_index); +uint16_t net_key_index_from_global(uint16_t net_key_index_g); +bool net_key_update(uint16_t net_key_index, uint16_t net_key_index_g, const uint8_t net_key[16]); +bool net_key_refresh(uint16_t net_key_index); +uint8_t net_key_refresh_check(uint16_t net_key_index, uint8_t net_key_loop, bool key_refresh_flag); +uint16_t net_key_available(void); +uint16_t net_key_add(uint16_t net_key_index_g, const uint8_t net_key[16]); +void net_key_delete(uint16_t net_key_index); +uint16_t net_key_dump(uint16_t net_key_indexes[]); +bool net_key_primary_subnet_check(void); +bool net_key_is_frnd_key(uint16_t net_key_index); +/** @} */ + +/** @brief + * @{ + */ +bool frnd_key_update(uint16_t frnd_key_index, uint16_t master_key_index, uint8_t p[9]); +bool frnd_key_check(uint16_t net_key_index); +/** @} */ + +/** @brief + * @{ + */ +uint16_t app_key_index_to_global(uint16_t app_key_index); +uint16_t app_key_index_from_global(uint16_t app_key_index_g); +bool app_key_update(uint16_t app_key_index, uint16_t net_key_index, uint16_t app_key_index_g, + const uint8_t app_key[16]); +bool app_key_refresh(uint16_t app_key_index); +uint16_t app_key_add(uint16_t net_key_index, uint16_t app_key_index_g, const uint8_t app_key[16]); +void app_key_delete(uint16_t app_key_index); +uint16_t app_key_dump(uint16_t net_key_index, uint16_t app_key_index_g[]); +/** @} */ + +/** + * @brief key refresh + * @param[in] key_refresh: step + * @param[in] net_key_index: key index + * @return none + */ +void mesh_key_refresh(uint8_t key_refresh, uint16_t net_key_index); + +/** + * @brief generate the composition data page 0 + * @param[in] pcompo_data_page0_header: info provided by app + * @return operation result + * @retval true: success + * @retval false: fail + */ +bool compo_data_page0_gen(compo_data_page0_header_p pcompo_data_page0_header); +bool compo_data_page128_gen(compo_data_page0_header_t *pcompo_data_page0_header); +bool compo_data_page128_valid(void); +bool compo_data_page128_to_page0(void); + +/** @brief + * @{ + */ +void mesh_seq_set(uint32_t seq); +void mesh_seq_clear(void); +uint32_t mesh_seq_use(void); +/** @} */ + +/** @brief + * @{ + */ +static inline uint32_t iv_index_get_tx_value(void) +{ + return mesh_node.iv_index - (mesh_node.iv_update_flag ? 1 : 0); +} +uint32_t iv_index_get(void); +void iv_index_set(uint32_t iv_index); +void iv_index_update(uint32_t iv_index, bool iv_update_flag); +uint32_t iv_index_update_try(uint32_t iv_index, bool iv_update_flag); +void iv_index_transit_to_iv_update(void); +void iv_index_transit_to_normal(void); +void iv_index_handle_timeout(void); +void iv_index_test_mode_set(bool test); +void iv_index_timer_start(void); +void iv_index_timer_stop(void); +/** @} */ + +void rpl_clear(void); + +/** @brief + * @{ + */ +void attn_timer_set(uint32_t interval_ms, mesh_attn_cb_pf attn_cb); +uint8_t attn_timer_get(uint8_t element_index); +void attn_timer_start(uint8_t element_index, uint8_t second); +void attn_timer_stop(void); +void attn_timer_handle_timeout(void); +/** @} */ + +/** @brief + * @{ + */ + +///@cond +bool mesh_node_sub_check(uint16_t addr); +void mesh_node_init(void); +void mesh_node_deinit(void); +bool mesh_node_check_reprov(uint16_t unicast_address, uint32_t iv_index, bool iv_update_flag, + uint16_t net_key_index_g, uint8_t key[MESH_COMMON_KEY_SIZE]); +///@endcond + +/** + * @brief clear the mesh parameters stored in the nvm + * @param[in] features: the supported mesh features + * @param[in] pnode_cfg: the configurable device parameters + * @return none + */ +void mesh_node_cfg(mesh_node_features_t features, mesh_node_cfg_p pnode_cfg); + +/** + * @brief clear the mesh parameters stored in the nvm + * @return none + */ +void mesh_node_clear(void); + +/** + * @brief clear the mesh parameters stored in the ram + * + * It may reboot the system. + * @return none + */ +void mesh_node_clean(void); + +/** + * @brief clear all the mesh parameters in the nvm and ram + * + * It may reboot the system. + * @return none + */ +void mesh_node_reset(void); + +/** + * @brief restore the node after @ref mesh_node_clean has been invoked + * + * The node may restore the provisioned state. + * @return none + */ +void mesh_node_restore(void); + +/** + * @brief When the feature is enabled, the node will receive all group messages even the models haven't + * subscribe the group address. + * + * @return none + */ +void mesh_node_unckeck_group_addr(bool enable); + +/** + * @brief When the feature is enabled, the node will reuse the old mesh parameters if it is reprovisioned. + * + * The device can be reprovisioned with the same mesh address without worry about the seq number is duplicate so that + * the message is filtered by other device. + * The api shall be called after @ref mesh_node_cfg. + * @return none + */ +void mesh_node_set_reprov(bool enable); + +void mesh_node_set_cccd_not_check(bool enable); +/** @} */ + +/** @brief + * @{ + */ + +/** + * @brief create a new element + * @param[in] loc: the element location + * @return operation result + */ +bool mesh_element_create(uint16_t loc); +mesh_element_p mesh_element_get(uint8_t element_index); +mesh_element_p mesh_element_get_by_addr(uint16_t addr); +/** @} */ + +/** @brief + * @{ + */ + +/** + * @brief register a model to the addressed element + * @param[in] element_index: the element index + * @param[in] pmodel_info: model info provided by the upper layer + * @return operation result + */ +bool mesh_model_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief bind/unbind one app key to the specific model + * @param[in] pmodel_info: pointer of the model info + * @param[in] app_key_index: the local index of the app key + * @param[in] bind: bind or unbind + * @return none + */ +void mesh_model_bind_one(mesh_model_info_t *pmodel_info, uint16_t app_key_index, bool bind); + +/** + * @brief bind/unbind all app keys to the specific model + * @param[in] pmodel_info: pointer of the model info + * @param[in] bind: bind or unbind + * @return none + */ +void mesh_model_bind_all(mesh_model_info_t *pmodel_info, bool bind); + +/** + * @brief bind/unbind all app keys to all models + * @param[in] bind: bind or unbind + * @return none + */ +void mesh_model_bind(bool bind); +#define mesh_model_bind_all_key() mesh_model_bind(true) + +/** + * @brief dump all app keys binded by the model + * @param[in] pmodel_info: pointer of the model info + * @param[out] app_key_index_g: the global indexes of app keys + * @param[in] max_count: the size of app_key_index_g to put the indexes + * @return the realistic count of dumped app keys + */ +uint16_t mesh_model_bind_dump(mesh_model_info_t *pmodel_info, uint16_t app_key_index_g[], + uint16_t max_count); + +/** + * @brief get the index of the first availabel app key of the model + * @param[in] pmodel_info: pointer of model info + * @return the local app key index + * @retval >=0: the available app key index + * @retval <0: no available app key + */ +int mesh_model_get_available_key(mesh_model_info_p pmodel_info); + +/** + * @brief subscribe the group address of the model + * @param[in] pmodel: pointer of model + * @param[in] addr: the group address + * @return operation result + */ +bool mesh_model_sub(mesh_model_p pmodel, uint16_t addr); + +/** + * @brief unsubscribe the group address of the model + * @param[in] pmodel: pointer of model + * @param[in] addr: the group address + * @return operation result + */ +bool mesh_model_unsub(mesh_model_p pmodel, uint16_t addr); + +/** + * @brief all the models subscribe the group address + * + * Some models may subscribe fail due to the subcribe list is full or other reasons. + * @param[in] addr: the group address + * @return the successed model num + */ +uint8_t mesh_model_sub_all(uint16_t addr); + +/** + * @brief check wheather the group address is subscribed by the model + * @param[in] pmodel: pointer of model + * @param[in] addr: the group address + * @return operation result + */ +bool mesh_model_sub_check(mesh_model_p pmodel, uint16_t addr); + +/** + * @brief dump the group addresses subscribed by the model + * @param[in] pmodel: pointer of model + * @param[out] addr: the group addresses + * @param[in] max_count: the count of addr to put the group address + * @return the realistic count of group addresses subscribed + */ +uint16_t mesh_model_sub_dump(mesh_model_p pmodel, uint16_t addr[], uint16_t max_count); +uint16_t mesh_model_sub_dump_internal(mesh_model_p pmodel, uint16_t addr[], uint16_t max_count); + +/** + * @brief subscribe many group addresses of the model + * @param[in] pmodel: pointer of model + * @param[in] addr: the group addresses + * @param[in] num: the number of addreses + * @return none + */ +void mesh_model_sub_load(mesh_model_p pmodel, uint16_t addr[], uint16_t num); + +/** + * @brief clear all group addresses subscribed by the model + * @param[in] pmodel: pointer of model + * @return none + */ +void mesh_model_sub_clear(mesh_model_p pmodel); + +/** + * @brief start the publishment of the model + * @param[in] pmodel: pointer of model + * @return none + */ +void mesh_model_pub_start(mesh_model_p pmodel); + +/** + * @brief get the publish period of the model + * @param[in] pmodel: pointer of model + * @return publish period in millisecond + */ +uint32_t mesh_model_pub_period_get(mesh_model_p pmodel); + +/** + * @brief set the publish parameters + * @param[in] pmodel: pointer of model + * @param[in] pub_params: the publish parameters + * @return operation result + */ +void mesh_model_pub_params_set(mesh_model_t *pmodel, mesh_model_pub_params_t pub_params); + +/** + * @brief get the publish parameters + * @param[in] pmodel: pointer of model + * @return the publish parameters + */ +mesh_model_pub_params_t mesh_model_pub_params_get(const mesh_model_t *pmodel); + +/** + * @brief check wheather the publish addr is set + * @param[in] pmodel_info: pointer of model info + * @return operation result + */ +bool mesh_model_pub_check(mesh_model_info_p pmodel_info); + +mesh_model_p mesh_model_get(uint8_t element_index, uint8_t model_index); +mesh_model_p mesh_model_get_by_model_id(mesh_element_p pelement, uint32_t model_id); +mesh_model_p mesh_model_get_by_num(uint8_t model_num); +mesh_model_info_p mesh_model_info_get_by_model_id(uint8_t element_index, uint32_t model_id); +uint8_t mesh_model_get_index(mesh_model_p pmodel_in); +uint8_t mesh_model_num(void); +void mesh_model_handle_pub_timeout(mesh_model_p pmodel); +bool mesh_model_sub_check_internal(mesh_model_p pmodel, uint16_t addr); +bool mesh_model_sub_vir_addr_available(mesh_model_p pmodel); + +/** + * @brief configure mesh message + * @param[in out] pmsg: mesh message need to configured + */ +void mesh_msg_cfg(mesh_msg_t *pmsg); + +/** @} */ + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_NODE_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_provision.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_provision.h new file mode 100644 index 00000000..d0af05cf --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_provision.h @@ -0,0 +1,492 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_provision.h + * @brief Head file for mesh provision. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_PROVISION_H +#define _MESH_PROVISION_H + +/* Add Includes here */ +#include "platform_types.h" +#include "platform_os.h" +#include "mesh_bearer.h" +#include "provision_adv.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Prov_Common + * @{ + */ + +/** @defgroup Mesh_Prov_Common_Exported_Types Exported Types + * @brief + * @{ + */ + +/** @defgroup Provision_Parameters + * @brief parameters used by upper layers + * @{ + */ +typedef enum +{ + PROV_PARAMS_CAPABILITIES, //!< @ref prov_capabilities_t + PROV_PARAMS_OOB_INFO, //!< @ref prov_oob_info_t + PROV_PARAMS_CALLBACK_FUN, //!< @ref prov_cb_pf + PROV_PARAMS_PUBLIC_KEY, //!< set by device when provisioning + PROV_PARAMS_PRIVATE_KEY //!< set by device when provisioning +} prov_params_t, *PProvParams; + +enum +{ + PROV_OOB_INFO_OTHER = BIT0, + PROV_OOB_INFO_ELECTRONIC_URI = BIT1, + PROV_OOB_INFO_2D_CODE = BIT2, + PROV_OOB_INFO_BAR_CODE = BIT3, + PROV_OOB_INFO_NFC = BIT4, + PROV_OOB_INFO_NUMBER = BIT5, + PROV_OOB_INFO_STRING = BIT6, + PROV_OOB_INFO_ON_BOX = BIT11, + PROV_OOB_INFO_INSIDE_BOX = BIT12, + PROV_OOB_INFO_ON_PAPER = BIT13, + PROV_OOB_INFO_INSIDE_MANUAL = BIT14, + PROV_OOB_INFO_ON_DEVICE = BIT15 +}; + +typedef struct +{ + uint16_t other: 1; + uint16_t electronic_uri: 1; + uint16_t qr_code: 1; //!< 2D machine-readable code + uint16_t bar_code: 1; + uint16_t nfc: 1; //!< Near Field Communication (NFC) + uint16_t number: 1; + uint16_t string: 1; + uint16_t rfu: 4; + uint16_t on_box: 1; + uint16_t inside_box: 1; + uint16_t on_paper: 1; + uint16_t inside_manual: 1; + uint16_t on_device: 1; +} _PACKED4_ prov_oob_info_t, *prov_oob_info_p; +/** @} End of Provision_Parameters */ + +/** @defgroup Provision_PDU Provision PDU + * @brief PDU used for provisioning procedure + * @{ + */ +enum +{ + PROV_INVITE = 0, + PROV_CAPABILITIES, + PROV_START, + PROV_PUBLIC_KEY, + PROV_INPUT_COMPLETE, + PROV_CONFIRMATION, + PROV_RANDOM, + PROV_DATA, + PROV_COMPLETE, + PROV_FAILED, +#if MESH_UNPROVISIONING_SUPPORT + UNPROV_CMD, + UNPROV_COMPLETE +#endif +} _SHORT_ENUM_; +typedef uint8_t prov_pdu_type_t; + +typedef struct +{ + uint8_t attn_dur; +} _PACKED4_ prov_invite_t, *prov_invite_p; + +typedef enum +{ + PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE = BIT0 +} prov_cap_algorithm_t; + +enum +{ + PROV_START_FIPS_P256_ELLIPTIC_CURVE +} _SHORT_ENUM_; +typedef uint8_t prov_start_algorithm_t; + +typedef enum +{ + PROV_CAP_PUBLIC_KEY_OOB = BIT0 +} prov_cap_public_key_t; + +enum +{ + PROV_START_NO_OOB_PUBLIC_KEY, + PROV_START_OOB_PUBLIC_KEY +} _SHORT_ENUM_; +typedef uint8_t prov_start_public_key_t; + +typedef enum +{ + PROV_CAP_STATIC_OOB = BIT0 +} prov_cap_static_oob_t; + +#define OUTPUT_OOB_SIZE_MAX 8 +typedef enum +{ + PROV_CAP_OUTPUT_OOB_ACTION_BLINK = BIT0, + PROV_CAP_OUTPUT_OOB_ACTION_BEEP = BIT1, + PROV_CAP_OUTPUT_OOB_ACTION_VIBRATE = BIT2, + PROV_CAP_OUTPUT_OOB_ACTION_OUTPUT_NUMERIC = BIT3, + PROV_CAP_OUTPUT_OOB_ACTION_OUTPUT_ALPHANUMERIC = BIT4 +} prov_cap_output_oob_action_t; + +enum +{ + PROV_START_OUTPUT_OOB_ACTION_BLINK, + PROV_START_OUTPUT_OOB_ACTION_BEEP, + PROV_START_OUTPUT_OOB_ACTION_VIBRATE, + PROV_START_OUTPUT_OOB_ACTION_OUTPUT_NUMERIC, + PROV_START_OUTPUT_OOB_ACTION_OUTPUT_ALPHANUMERIC +} _SHORT_ENUM_; +typedef uint8_t prov_start_output_oob_action_t; + +#define INPUT_OOB_SIZE_MAX 8 +typedef enum +{ + PROV_CAP_INPUT_OOB_ACTION_BIT_PUSH = BIT0, + PROV_CAP_INPUT_OOB_ACTION_BIT_TWIST = BIT1, + PROV_CAP_INPUT_OOB_ACTION_BIT_INPUT_NUMERIC = BIT2, + PROV_CAP_INPUT_OOB_ACTION_BIT_INPUT_ALPHANUMERIC = BIT3 +} prov_cap_input_oob_action_t; + +enum +{ + PROV_START_INPUT_OOB_ACTION_PUSH, + PROV_START_INPUT_OOB_ACTION_TWIST, + PROV_START_INPUT_OOB_ACTION_INPUT_NUMERIC, + PROV_START_INPUT_OOB_ACTION_INPUT_ALPHANUMERIC +} _SHORT_ENUM_; +typedef uint8_t prov_start_input_oob_action_t; + +typedef struct +{ + uint8_t element_num; + uint16_t algorithm; //!< @ref prov_cap_algorithm_t + uint8_t public_key; //!< @ref prov_cap_public_key_t + uint8_t static_oob; //!< @ref prov_cap_static_oob_t + uint8_t output_oob_size; //!< @ref OUTPUT_OOB_SIZE_MAX + uint16_t output_oob_action; //!< @ref prov_cap_output_oob_action_t + uint8_t input_oob_size; //!< @ref INPUT_OOB_SIZE_MAX + uint16_t input_oob_action; //!< @ref prov_cap_input_oob_action_t +} _PACKED4_ prov_capabilities_t, *prov_capabilities_p; + +enum +{ + PROV_AUTH_METHOD_NO_OOB, + PROV_AUTH_METHOD_STATIC_OOB, + PROV_AUTH_METHOD_OUTPUT_OOB, + PROV_AUTH_METHOD_INPUT_OOB +} _SHORT_ENUM_; +typedef uint8_t prov_auth_method_t; + +typedef enum +{ + PROV_AUTH_VALUE_TYPE_NONE, + PROV_AUTH_VALUE_TYPE_BINARY, + PROV_AUTH_VALUE_TYPE_NUMERIC, + PROV_AUTH_VALUE_TYPE_ALPHANUMERIC +} prov_auth_value_type_t; + +typedef union +{ + uint8_t oob_action; + prov_start_output_oob_action_t output_oob_action; + prov_start_input_oob_action_t input_oob_action; +} _PACKED4_ prov_auth_action_t; + +typedef union +{ + uint8_t oob_size; + uint8_t output_oob_size; + uint8_t input_oob_size; +} _PACKED4_ prov_auth_size_t; + +typedef struct +{ + prov_start_algorithm_t algorithm; + prov_start_public_key_t public_key; + prov_auth_method_t auth_method; + prov_auth_action_t auth_action; + prov_auth_size_t auth_size; +} _PACKED4_ prov_start_t, *prov_start_p; + +typedef struct +{ + uint8_t public_key[64]; +} _PACKED4_ prov_public_key_t, *prov_public_key_p; + +typedef struct +{ + uint8_t confirmation[16]; +} _PACKED4_ prov_confirmation_t, *prov_confirmation_p; + +typedef struct +{ + uint8_t rand[16]; +} _PACKED4_ prov_random_t, *prov_random_p; + +typedef struct +{ + uint8_t net_key[16]; + uint16_t net_key_index; + uint8_t flags; //!< bit0: key refresh, bit1: iv update + uint32_t iv_index; + uint16_t unicast_address; + uint8_t mic[8]; +} _PACKED4_ prov_data_t, *prov_data_p; //!< big endian + +enum +{ + PROV_VALID, + PROV_FAILED_INVALID_PDU = 0x01, + PROV_FAILED_INVALID_FORMAT, + PROV_FAILED_UNEXPECTED_PDU, + PROV_FAILED_CONFIRMATION_FAILED, + PROV_FAILED_OUT_OF_RESOURCE, + PROV_FAILED_DECRYPTION_FAILED, + PROV_FAILED_UNEXPECTED_ERROR, + PROV_FAILED_CANNOT_ASSIGN_ADDR, + /* The Data block contains values that cannot be accepted. (Used by RPR) */ + PROV_FAILED_INVALID_DATA +} _SHORT_ENUM_; +typedef uint8_t prov_result_t; + +typedef struct +{ + prov_result_t failed_reason; +} _PACKED4_ prov_failed_t, *prov_failed_p; + +typedef struct +{ + uint8_t type : 6; //!< @ref prov_pdu_type_t + uint8_t padding : 2; + union + { + prov_invite_t prov_invite; + prov_capabilities_t prov_capabilities; + prov_start_t prov_start; + prov_public_key_t prov_public_key; + prov_confirmation_t prov_confirmation; + prov_random_t prov_random; + prov_data_t prov_data; + prov_failed_t prov_failed; + }; +} _PACKED4_ prov_pdu_t, *prov_pdu_p; +/** @} End of Provision_PDU */ + +#define CONFIRMATION_INPUTS_LENGTH (sizeof(prov_invite_t) + sizeof(prov_capabilities_t) + sizeof(prov_start_t) + sizeof(prov_public_key_t) + sizeof(prov_public_key_t)) +typedef struct +{ + uint8_t public_key[64]; + uint8_t private_key[32]; + uint8_t random[16]; + uint8_t ecdh_secrect[32]; + uint8_t conf[16]; + uint8_t conf_salt[16]; + uint8_t conf_key[16]; + uint8_t prov_salt[16]; + uint8_t conf_inputs[CONFIRMATION_INPUTS_LENGTH]; + uint8_t auth_value[16]; + bool auth_value_flag; + bool confirm_rx_flag; + prov_start_t prov_start; +} prov_ctx_tmp_t, *prov_ctx_tmp_p; + +/** @defgroup Provision_Callback Provision Callback + * @brief Callback types used for provisioning procedure. + * @{ + */ +typedef enum +{ + PROV_CB_TYPE_PB_ADV_LINK_STATE, + PROV_CB_TYPE_UNPROV, /**< notified when the stack is ready */ + PROV_CB_TYPE_START, /**< used by device */ + PROV_CB_TYPE_PATH_CHOOSE, /**< used by provisioner */ + PROV_CB_TYPE_PUBLIC_KEY, + PROV_CB_TYPE_AUTH_DATA, + PROV_CB_TYPE_RANDOM, /* notified when receive remote random value */ + PROV_CB_TYPE_COMPLETE, /**< only notified in the prov procedure */ + PROV_CB_TYPE_FAIL, + PROV_CB_TYPE_PROV, /**< added to notify the stack is ready */ +#if defined(MESH_PROV_WO_AUTH_VALUE) && MESH_PROV_WO_AUTH_VALUE + PROV_CB_TYPE_CONF_CHECK, +#endif +} prov_cb_type_t; + +typedef enum +{ + PROV_CB_FAIL_TYPE_BEARER_LOSS, //!< pb-adv link close & le link disconnect + PROV_CB_FAIL_TYPE_BEARER_TIMEOUT, //!< pb-adv transaction timeout @ref MESH_PB_GENERIC_TIMEOUT_PERIOD + PROV_CB_FAIL_TYPE_BEARER_IDLE, //!< pb-adv link idle timeout @ref MESH_PB_ADV_LINK_IDLE_TIMEOUT + PROV_CB_FAIL_TYPE_PROCEDURE_TIMEOUT, //!< prov procedure timeout @ref MESH_PROV_TIMEOUT_PERIOD + PROV_CB_FAIL_TYPE_PROCEDURE_ABNORMAL //!< prov procedure fail @ref prov_result_t +} prov_cb_fail_type_t; + +typedef struct +{ + prov_cb_fail_type_t fail_type; + union + { + bearer_type_t bearer_type; + prov_result_t prov_result; + }; +} prov_cb_fail_t; + +#if defined(MESH_PROV_WO_AUTH_VALUE) && MESH_PROV_WO_AUTH_VALUE +typedef struct +{ + uint8_t *rand; + uint8_t *conf; +} prov_check_conf_t; +#endif + +/** little endian interfaced with app */ +typedef union +{ + prov_generic_cb_type_t pb_generic_cb_type; //!< used in PROV_CB_TYPE_PB_ADV_LINK_STATE + prov_capabilities_t *pprov_capabilities; //!< used in PROV_CB_TYPE_PATH_CHOOSE by provisioner + prov_start_t *pprov_start; //!< used in PROV_CB_TYPE_AUTH_DATA by device + prov_data_t *pprov_data; //!< used in PROV_CB_TYPE_COMPLETE + prov_random_t *pprov_random; //!< used in PROV_CB_TYPE_RANDOM by device and provisioner + prov_cb_fail_t prov_fail; //!< used in PROV_CB_TYPE_FAIL +#if defined(MESH_PROV_WO_AUTH_VALUE) && MESH_PROV_WO_AUTH_VALUE + prov_check_conf_t prov_check_conf; +#endif +} prov_cb_data_t; + +typedef bool (*prov_cb_pf)(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +typedef bool (*prov_send_t)(uint8_t *pdata, uint16_t len); + +typedef struct +{ + prov_pdu_type_t fsm; + bool fsm_flag; //!< TRUE: tx, False: Rx. Assisting to determine the FSM when there is ambiguity tx/rx the same msgs. + prov_capabilities_t prov_cap; + prov_cb_pf pf_prov_cb; + plt_timer_t timer; + prov_ctx_tmp_p pctx_tmp; + prov_send_t prov_send; +} prov_ctx_t, *prov_ctx_p; + +extern prov_ctx_t prov_ctx; +/** @} */ + +/** @} */ + +/** @defgroup Mesh_Prov_Common_Exported_Functions Exported Functions + * @brief + * @{ + */ + +///@cond +void prov_init(void); +uint32_t prov_cap_check(void); +uint32_t prov_start_check(void); +void prov_timer_restart(void); +void prov_timer_stop(void); +void prov_allocate(void); +void prov_free(void); +bool prov_ecc_key_gen(void); +bool prov_ecc_key_validate(uint8_t public_key[64]); +bool prov_ecdh_secret_gen(uint8_t public_key[64], uint8_t private_key[32], uint8_t secret[32]); +void prov_conf_keys_gen(void); +bool prov_conf_key_get(uint8_t conf_key[16]); +void prov_confirmation_gen(uint8_t confirmation[16], uint8_t rand[16], uint8_t auth_value[16]); +void prov_data_keys_gen(uint8_t random_provisioner[16], uint8_t random_device[16]); +bool prov_data_crypto(uint8_t dev_key[16], uint8_t data[38], bool encrypt_decrypt); +void prov_handle_disconnect(void); +void prov_handle_timeout(void); +void prov_set_send_cb(prov_send_t pcb); +uint16_t prov_dev_key_idx(uint16_t addr); +bool prov_replace(uint16_t old_idx, uint16_t new_idx); +///@endcond + +/** + * @brief get the provision parameters + * @param[in] params: type + * @param[in] pvalue: value + * @param[in] len: length + * @return operation result + */ +bool prov_params_get(prov_params_t params, void *pvalue, uint8_t len); + +/** + * @brief set the provision parameters + * @param[in] params: type + * @param[in] pvalue: value + * @param[in] len: length + * @return operation result + */ +bool prov_params_set(prov_params_t params, void *pvalue, uint8_t len); + +/** + * @brief set the auth value + * + * The function shall be called at the appropriate time. The auth value shall be + * set with the appropriate length and data format. + * @param[in] pvalue: auth value + * @param[in] len: value length + * @return operation result + */ +bool prov_auth_value_set(uint8_t *pvalue, uint8_t len); + +/** + * @brief change the auth value + * + * The function shall be called at the appropriate time. The auth value will changed immediately + * @param[in] pvalue: auth value + * @param[in] len: value length + * @return operation result + */ +bool prov_auth_value_change(uint8_t *pvalue, uint8_t len); + +/** + * @brief set the auth random value + * + * The function shall be called at the appropriate time. + * @param[in] random: random value + * @return operation result + */ +bool prov_auth_random_set(uint8_t random[16]); + +/** + * @brief get the auth value type + * + * Different type of auth value is formatted differently according to the spec. + * @param[in] pprov_start: prov start pdu + * @return auth value type + */ +prov_auth_value_type_t prov_auth_value_type_get(prov_start_t *pprov_start); + +/** + * @brief disconnect the prov bearer + * + * The spec requires the provisioner to disconnect the bearer after the provision procedure. + * The mesh stack leaves the app to decide whether to disconnect at the case @ref PROV_CB_TYPE_COMPLETE. + * @param[in] reason: pb-adv bearer need the disconnect reason + * @return operation result + */ +bool prov_disconnect(pb_adv_link_close_reason_t reason); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_PROVISION_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_service.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_service.h new file mode 100644 index 00000000..ec86df0d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_service.h @@ -0,0 +1,158 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_service.h + * @brief Head file for mesh service. + * @details Data types and external functions declaration. + * @author bill + * @date 2016-3-14 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_SERVICE_H +#define _MESH_SERVICE_H + +/* Add Includes here */ +#include "mesh_provision.h" +#include "mesh_config.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Service + * @{ + */ + +/** @defgroup Mesh_Service_Exported_Macros Exported Macros + * @{ + */ +#if defined(MESH_DEVICE) && MESH_DEVICE +#if MESH_DEVICE_PROV_PROXY_SERVER_COEXIST +#define MESH_GATT_SERVER_COUNT 2 +#else +#define MESH_GATT_SERVER_COUNT 1 +#endif +#else +#define MESH_GATT_SERVER_COUNT 0 +#endif + +#if defined(MESH_PROVISIONER) && MESH_PROVISIONER +#define MESH_GATT_CLIENT_COUNT 2 +#else +#define MESH_GATT_CLIENT_COUNT 1 //!< or 0 ? +#endif + +#define MESH_SERVICE_ADV_DATA_HEADER_SERVICE_DATA_OFFSET 7 +/** @} */ + +/** @defgroup Mesh_Service_Exported_Types Exported Types + * @{ + */ + +/** little endian */ +typedef struct +{ + uint8_t dev_uuid[16]; + prov_oob_info_t oob_info; +} _PACKED4_ mesh_service_data_provision_t; + +enum +{ + PROXY_ADV_TYPE_NET_ID = 0, + PROXY_ADV_TYPE_NODE_IDENTITY = 1, +#if MESH_PRB + PROXY_ADV_TYPE_PRIVATE_NET_ID = 2, + PROXY_ADV_TYPE_PRIVATE_NODE_IDENTITY = 3, +#endif +} _SHORT_ENUM_; +typedef uint8_t proxy_adv_type_t; + +typedef struct +{ + proxy_adv_type_t type; + union + { + uint8_t net_id[8]; + struct + { + uint8_t hash[8]; + uint8_t random[8]; + }; + }; +} _PACKED4_ mesh_service_data_proxy_t; + +typedef union +{ + mesh_service_data_provision_t provision; + mesh_service_data_proxy_t proxy; +} _PACKED4_ mesh_service_data_t, *mesh_service_data_p; + +typedef enum +{ + MESH_SERVCIE_ADV_CFG_TYPE_PROV_RETRANS_COUNT = 0, //!< uint8_t + MESH_SERVCIE_ADV_CFG_TYPE_PROV_RETRANS_INTERVAL = 1, //!< uint16_t, unit: ms + MESH_SERVCIE_ADV_CFG_TYPE_PROXY_RETRANS_COUNT = 2, //!< uint8_t + MESH_SERVCIE_ADV_CFG_TYPE_PROXY_RETRANS_INTERVAL = 3, //!< uint16_t, unit: ms + MESH_SERVCIE_ADV_CFG_TYPE_PROXY_WITH_BT_ADDR = 4, //!< bool +#if MESH_PRB + MESH_SERVCIE_ADV_CFG_TYPE_PRIVATE_PROXY_RETRANS_COUNT = 5, //!< uint8_t + MESH_SERVCIE_ADV_CFG_TYPE_PRIVATE_PROXY_RETRANS_INTERVAL = 6, //!< uint16_t, unit: ms +#endif +} mesh_service_adv_cfg_type_t; +/** @} */ + +/** @defgroup Mesh_Service_Exported_Functions Exported Functions + * @{ + */ + +///@cond +void mesh_service_adv_send(void); +void mesh_service_adv_receive(uint8_t bt_addr[6], uint8_t addr_type, int8_t rssi, uint8_t *pbuffer, + uint16_t len); +void mesh_service_identity_adv_send(uint16_t net_key_index); +void mesh_service_identity_adv_rr(void); +void mesh_service_identity_adv_start(void); +void mesh_service_identity_adv_trigger(bool on_off); +#if MESH_PRB +void mesh_private_service_adv_start(void); +void mesh_private_service_adv_stop(void); +void mesh_private_service_adv_send(void); +void mesh_private_service_identity_adv_send(uint16_t net_key_index); +void mesh_private_service_identity_adv_rr(void); +void mesh_private_service_identity_adv_start(void); +void mesh_private_service_identity_adv_trigger(bool on_off); +#endif +void mesh_service_init(void); +void mesh_service_deinit(void); +///@endcond + +/** + * @brief start the mesh service adv + * @return none + */ +void mesh_service_adv_start(void); + +/** + * @brief stop the mesh service adv + * @return none + */ +void mesh_service_adv_stop(void); + +/** + * @brief configure the mesh service adv + * @param[in] type: the parameter type, @ref mesh_service_adv_cfg_type_t + * @param[in] param: the parameter pointer + * @param[in] param_len: the parameter length + * @return operation result + */ +bool mesh_service_adv_cfg(mesh_service_adv_cfg_type_t type, uint8_t *param, uint16_t param_len); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_SERVICE_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_transport.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_transport.h new file mode 100644 index 00000000..72ac9483 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/mesh_transport.h @@ -0,0 +1,348 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file mesh_transport.h + * @brief Head file for mesh transport layer. + * @details Data types and external functions declaration. + * @author bill + * @date 2015-8-27 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _MESH_TRANSPORT_H +#define _MESH_TRANSPORT_H + +/* Add Includes here */ +#include "platform_types.h" +#include "mesh_config.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Transport + * @{ + */ + +/** @defgroup Mesh_Transport_Exported_Macros Exported Macros + * @brief + * @{ + */ +#define TRANS_PDU_OFFSET (BEARER_ADV_HEADER_SIZE + MESH_NWK_HEADER_SIZE) +/** @} */ + +/** @defgroup Mesh_Transport_Exported_Types Exported Types + * @brief + * @{ + */ +typedef enum +{ + TRANS_MSG_TYPE_UNSEG_ACCESS, //!< Unsegmented Access message + TRANS_MSG_TYPE_SEG_ACCESS, //!< Segmented Access message + TRANS_MSG_TYPE_UNSEG_CTL, + TRANS_MSG_TYPE_SEG_CTL +} trans_msg_type_t; + +typedef enum +{ + TRANS_SEG_ACK, + TRANS_FRND_POLL, + TRANS_FRND_UPDATE, + TRANS_FRND_REQ, + TRANS_FRND_OFFER, + TRANS_FRND_CLEAR, + TRANS_FRND_CLEAR_CONF, + TRANS_FRND_SUB_LIST_ADD, + TRANS_FRND_SUB_LIST_RM, + TRANS_FRND_SUB_LIST_CONF, + TRANS_HB, +#if MESH_SUPPORT_TRANS_PING + TRANS_PING = 0x50, + TRANS_PONG, +#endif +} trans_opcode_t; + +typedef struct +{ + uint8_t aid: 6; //!< Least significant 6 bits of application key identifier + uint8_t akf: 1; //!< Application Key Flag + uint8_t seg: 1; + uint8_t app_payload[15]; +} _PACKED4_ trans_unseg_access_t, *trans_unseg_access_p; + +typedef struct +{ + uint32_t seg_n: 5; + uint32_t seg_o: 5; + uint32_t seq_zero: 13; + uint32_t szmic: 1; //!< Size of TransMIC bit +} _PACKED4_ trans_seg_msc_t, *trans_seg_msc_p; + +typedef struct +{ + uint8_t aid: 6; //!< Least significant 5 bits of application key identifier + uint8_t akf: 1; //!< Application Key Flag + uint8_t seg: 1; + union + { + trans_seg_msc_t msc; // shall be changed to big endian + uint8_t msc_alias[3]; //!< miscellaneous @ref trans_seg_msc_t + }; + uint8_t app_payload[12]; +} _PACKED4_ trans_seg_access_t, *trans_seg_access_p; + +typedef struct +{ + uint8_t opcode: 7; //!< Reserved for future use + uint8_t seg: 1; + uint8_t params[11]; +} _PACKED4_ trans_unseg_ctl_t, *trans_unseg_ctl_p; + +typedef struct +{ + uint32_t seg_n: 5; + uint32_t seg_o: 5; + uint32_t seq_zero: 13; + uint32_t rfu: 1; +} _PACKED4_ trans_seg_ctl_msc_t, *trans_seg_ctl_msc_p; + +typedef struct +{ + uint8_t opcode: 7; //!< Transport Layer Control PDU Operation Code, @ref trans_opcode_t + uint8_t seg: 1; + uint8_t msc[3]; //!< miscellaneous @ref trans_seg_ctl_msc_t + uint8_t params[8]; +} _PACKED4_ trans_seg_ctl_t, *trans_seg_ctl_p; + +typedef struct +{ + uint16_t rfu: 2; + uint16_t seq_zero: 13; + uint16_t obo: 1; //!< Friend on behalf of a LPN + uint8_t block_ack[4]; +} _PACKED4_ trans_seg_ack_t, *trans_seg_ack_p; + +typedef struct +{ + uint8_t fsn: 1; //!< Friend Sequence Number + uint8_t rfu: 7; +} _PACKED4_ frnd_poll_t, *frnd_poll_p; + +typedef struct +{ + union + { + struct + { + uint8_t key_refresh: 1; + uint8_t iv_update: 1; + uint8_t rfu: 6; + } flags; + uint8_t flags_alias; + }; + uint8_t iv_index[4]; + uint8_t md; //!< More Data bit +} _PACKED4_ frnd_update_t, *frnd_update_p; + +/** @defgroup FRIENDSHIP_MSG Friendship Msg + * @brief Msg types used by friendship models + * @{ + */ +typedef struct +{ + uint8_t min_queue_size_log: 3; //!< N = 2^cache_size + uint8_t rx_window_factor: 2; + uint8_t rssi_factor: 2; + uint8_t rfu: 1; //!< Reserved for Future Use +} _PACKED4_ frnd_criteria_t, *frnd_criteria_p; + +typedef struct +{ + frnd_criteria_t criteria; //!< Friend Minimum Requirements + uint8_t rx_delay; //!< Friend Receive Delay + uint8_t poll_to[3]; //!< Friend Poll Timeout + uint16_t pr_addr; //!< Previous Friend node's Unicast Address + uint8_t element_num; //!< Number of Elements on the Low Power node + uint16_t lpn_counter; +} _PACKED4_ frnd_req_t, *frnd_req_p; + +typedef struct +{ + uint8_t rx_window; //!< Receive Window value supported by the Friend node. + uint8_t queue_size; + uint8_t sub_list_size; + int8_t rssi; + uint16_t frnd_counter; +} _PACKED4_ frnd_offer_t, *frnd_offer_p; + +typedef struct +{ + uint16_t lpn_addr; //!< Low Power Node Unicast Address + uint16_t lpn_counter; +} _PACKED4_ frnd_clear_t, *frnd_clear_p; + +typedef struct +{ + uint16_t lpn_addr; //!< Low Power Node Unicast Address + uint16_t lpn_counter; +} _PACKED4_ frnd_clear_conf_t, *frnd_clear_conf_p; + +typedef struct +{ + uint8_t tran_num; + uint16_t group_addr[5]; //!< List of Group Addresses and Virtual Addresses. +} _PACKED4_ frnd_sub_list_add_t, *frnd_sub_list_add_p; + +typedef struct +{ + uint8_t tran_num; + uint16_t group_addr[5]; //!< List of Group Addresses and Virtual Addresses. +} _PACKED4_ frnd_sub_list_remove_t, *frnd_sub_list_remove_p; + +typedef struct +{ + uint8_t tran_num; +} _PACKED4_ frnd_sub_list_conf_t, *frnd_sub_list_conf_p; +/** @} */ + +typedef struct +{ + uint8_t init_ttl: 7; + uint8_t rfu: 1; + uint16_t features; //!< @ref mesh_features_t +} _PACKED4_ trans_hb_t, *trans_hb_p; + +#if MESH_SUPPORT_TRANS_PING +typedef struct +{ + uint8_t init_ttl; //!< Initial TTL value used when sending this message. + uint16_t pong_max_delay; //!< unit: 10ms +} _PACKED4_ trans_ping_t, *trans_ping_p; + +typedef struct +{ + uint8_t init_ttl; //!< Initial TTL value used when sending this message. + uint8_t hops_forward; //!< Hops in the forward direction. + uint16_t pong_delay; //!< unit: 10ms +} _PACKED4_ trans_pong_t, *trans_pong_p; +#endif + +typedef enum +{ + TRANS_SEG_MSG_SEND_STAT_GOING, + TRANS_SEG_MSG_SEND_STAT_ACKED, + TRANS_SEG_MSG_SEND_STAT_TO, + TRANS_SEG_MSG_SEND_STAT_CANCEL +} trans_seg_msg_send_stat_t; + +typedef struct +{ + uint8_t *pbuffer; //!< cache of msg + uint16_t len; //!< length of seg msg + mesh_msg_t seg_msg; //!< save origin seg msg info + uint32_t seq_origin; //!< save origin seq + plt_timer_t timer; //!< used to retransimit +#if MESH_LPN + plt_timer_t timer_lpa; //!< lpn poll ack +#endif + uint8_t times[32]; //!< tx times of each seg + uint32_t send; //!< need tx flag of each seg + uint32_t send_first; //!< need tx first time flag of each seg + uint32_t ack; //!< seg acked info + uint8_t seg_num; +} trans_tx_ctx_t, *trans_tx_ctx_p; + +typedef struct +{ + uint8_t *pbuffer; //!< cache of msg + uint16_t len; //!< length of seg msg + mesh_msg_t seg_msg; //!< origin seg msg info + //uint32_t seq_origin; //!< origin seq + plt_timer_t timer; //!< ack timer, used to retransimit + plt_timer_t timer1; //!< incomplete timer + //uint8_t times[32]; //!< tx times of each seg + uint32_t receive; //!< flag of each received seg + //uint32_t ack; //!< seg acked info + bool obo; //!< rx for lpn + uint8_t seg_num; +} trans_rx_ctx_t, *trans_rx_ctx_p; + +typedef enum +{ + PING_PONG_TYPE_TRANSPORT, + PING_PONG_TYPE_ACCESS, + PING_PONG_TYPE_ACCESS_BIG +} ping_pong_type_t; + +typedef void (*pf_ping_cb_t)(uint16_t src, uint16_t dst, uint8_t hops_forward, + ping_pong_type_t type, uint8_t init_ttl, uint8_t key_index, uint16_t pong_max_delay); +typedef void (*pf_pong_cb_t)(uint16_t src, uint16_t dst, uint8_t hops_forward, + ping_pong_type_t type, uint8_t hops_reverse, uint16_t pong_delay); + +/** @} */ + +/** @defgroup Mesh_Transport_Exported_Functions Exported Functions + * @brief + * @{ + */ + +///@cond +void trans_init(void); +void trans_deinit(void); +mesh_msg_send_cause_t trans_send(mesh_msg_p pmesh_msg); +bool trans_send_check(void); +void trans_receive(mesh_msg_p pmesh_msg); +void trans_handle_timeout(uint8_t type, void *pctx); +bool trans_handle_ping_pong_msg(mesh_msg_p pmesh_msg); +mesh_msg_send_cause_t trans_hb(uint16_t dst, uint16_t net_key_index, uint8_t init_ttl, + mesh_features_t features); +void trans_rx_ctx_clear(void); +#if MESH_LPN +void trans_lpn_poll_ack_handle_timeout(void); +#endif +///@endcond + +/** + * @brief send the transport ping + * + * The ping msg can be customized with the dst/ttl/net_key_index/pong_max_delay. + * Take the concurrence of multiple devices into consideration, the pong_max_delay parameter is designed. + * @param[in] dst: the destination address + * @param[in] ttl: the initial ttl + * @param[in] net_key_index: the net key index + * @param[in] pong_max_delay: the max delay of correponded pong msg + * @return send result + */ +mesh_msg_send_cause_t trans_ping(uint16_t dst, uint8_t ttl, uint16_t net_key_index, + uint16_t pong_max_delay); + +/** + * @brief send the transport pong + * @param[in] dst: the destination address + * @param[in] ttl: the initial ttl + * @param[in] net_key_index: the net key index + * @param[in] hops_forward: the calculated hops in the forward direction + * @param[in] pong_delay: the actual delay of the pong msg + * @return send result + */ +mesh_msg_send_cause_t trans_pong(uint16_t dst, uint8_t ttl, uint16_t net_key_index, + uint8_t hops_forward, uint16_t pong_delay); + +/** + * @brief initialize the transport ping pong + * + * Register the callback. + * @param[in] pf_ping_cb: the ping callback + * @param[in] pf_pong_cb: the pong callback + * @return none + */ +void trans_ping_pong_init(pf_ping_cb_t pf_ping_cb, pf_pong_cb_t pf_pong_cb); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _MESH_TRANSPORT_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/model_config.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/model_config.h new file mode 100644 index 00000000..52200d5b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/model_config.h @@ -0,0 +1,41 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file model_config.h +* @brief Head file for model configuration. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-12-4 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _MODEL_CONFIG_H_ +#define _MODEL_CONFIG_H_ + +#include "mesh_config.h" + +/* always publish regardless of state change */ +#define MODEL_ENABLE_PUBLISH_ALL_TIME 1 + +/* enable delay message response */ +#define MODEL_ENABLE_DELAY_MSG_RSP 1 + +/* enable parallel adv */ +#define MODEL_ENABLE_PARALLEL_ADV 1 + +/* set this value to 1 if need to notify application when user stop transition */ +#define MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION 0 + +/* set this value to 1 if need to notify model when user stop delay execution */ +#define MODEL_ENABLE_USER_STOP_DELAY_NOTIFICATION 0 +#if MODEL_ENABLE_USER_STOP_DELAY_NOTIFICATION && MESH_MODEL_ENABLE_DEINIT +#error must NOT enable both of MODEL_ENABLE_USER_STOP_DELAY_NOTIFICATION and MESH_MODEL_ENABLE_DEINIT +#endif + +/* do not modify this field */ +#define MODEL_ENABLE_MULTI_THREAD 0 + +#endif /* _MODEL_CONFIG_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_adv.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_adv.h new file mode 100644 index 00000000..d49e4e98 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_adv.h @@ -0,0 +1,196 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provision_adv.h + * @brief Head file for provision adv bearer. + * @details + * @author bill + * @date 2016-2-24 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROVISION_ADV_H_ +#define _PROVISION_ADV_H_ + +/* Add Includes here */ +#include "platform_os.h" +#include "provision_generic.h" + +BEGIN_DECLS + +/** @addtogroup PB_Adv + * @brief + * @{ + */ + +/** @defgroup PB_Adv_Exported_Macros Exported Macros + * @{ + */ +#define MESH_PB_ADV_PKT_OFFSET (2) //!< Length + AD type +#define MESH_PB_ADV_PKT_HEADER_SIZE (6) //!< linkId(4) + transNum(1) + Control(1) +#define MESH_PB_ADV_START_DATA_SIZE (20) //!< excluding the length and fcs field +#define MESH_PB_ADV_CONTINUE_DATA_SIZE (23) +/** @} */ + +/** @defgroup Pb_Adv_Exported_Types Exported Types + * @{ + */ +typedef enum +{ + PB_ADV_LINK_STATE_CLOSED, + PB_ADV_LINK_STATE_OPENING, + PB_ADV_LINK_STATE_OPENED +} pb_adv_link_state_t; + +typedef enum +{ + PB_ADV_RX_STATE_IDLE, + PB_ADV_RX_STATE_START, + PB_ADV_RX_STATE_CONTINUE +} pb_adv_rx_state_t; + +typedef enum +{ + PB_ADV_TX_STATE_IDLE, + PB_ADV_TX_STATE_SENDING //!< Wait for acknowledge +} pb_adv_tx_state_t; + +typedef enum +{ + PB_ADV_ROLE_PROVISIONER, + PB_ADV_ROLE_DEVICE +} pb_adv_role_t; + +typedef enum +{ + PB_ADV_CB_TYPE_LINK_OPEN, + PB_ADV_CB_TYPE_LINK_CLOSED, + PB_ADV_CB_TYPE_TX_COMPLETE, + PB_ADV_CB_TYPE_RX_COMPLETE +} pb_adv_cb_type_t; + +typedef struct +{ + uint8_t total_length[2]; + uint8_t fcs; + uint8_t data[MESH_PB_ADV_START_DATA_SIZE]; +} _PACKED4_ pb_adv_start_t, *pb_adv_start_p; + +typedef struct +{ + uint8_t data[MESH_PB_ADV_CONTINUE_DATA_SIZE]; // variable length +} _PACKED4_ pb_adv_continue_t, *pb_adv_continue_p; + +typedef enum +{ + PB_ADV_LINK_OPEN, + PB_ADV_LINK_ACK, + PB_ADV_LINK_CLOSE +} pb_adv_opcode_t; + +typedef struct +{ + uint8_t dev_uuid[16]; +} _PACKED4_ pb_adv_link_open_t, *pb_adv_link_open_p; + +enum +{ + PB_ADV_LINK_CLOSE_SUCCESS, //!< link idle + PB_ADV_LINK_CLOSE_TRANSACTION_TIMEOUT, + PB_ADV_LINK_CLOSE_PROVISIONING_FAIL +} _SHORT_ENUM_; +typedef uint8_t pb_adv_link_close_reason_t; + +typedef struct +{ + pb_adv_link_close_reason_t reason; +} _PACKED4_ pb_adv_link_close_t, *pb_adv_link_close_p; + +typedef union +{ + pb_adv_link_open_t link_open; + // link_ack + pb_adv_link_close_t link_close; +} _PACKED4_ pb_adv_bearer_ctrl_t, *pb_adv_bearer_ctrl_p; + +typedef struct +{ + prov_generic_ctrl_t control; + union + { + pb_adv_start_t start; + // ack + pb_adv_continue_t conti; // continue: c keyword... + pb_adv_bearer_ctrl_t bearer_ctrl; + }; +} _PACKED4_ pb_adv_payload_t, *pb_adv_payload_p; + +typedef struct +{ + uint8_t link_id[4]; + uint8_t trans_num; + pb_adv_payload_t payload; +} _PACKED4_ pb_adv_pkt_t, *pb_adv_pkt_p; + +typedef struct +{ + pb_adv_link_state_t fsm; + plt_timer_t timer; //!< multiple used for re-tx and supervision link idle (no tx, reset when rx) + uint32_t timer_period; + uint32_t timer_count; + prov_bearer_cb_pf pf_cb; + uint32_t link_id; + uint8_t tx_trans_num; + uint8_t *tx_buffer; + uint16_t tx_len; + uint8_t rx_trans_num; + bool rx_first; //!< just for the iop with invalid trans implement + uint8_t rx_fcs; + uint8_t *rx_buffer; + uint16_t rx_len; + bool rx_frag_disorder; //!< PB_ADV_REQUIRE_FRAG_START + uint8_t rx_frag_num; + uint8_t rx_frag_buffer[8]; //!< only add 4 bytes from uint8_t *rx_frag_buffer + uint8_t rmt_dev_uuid[16]; + bool ack_sending_flag; +} pb_adv_ctx_t, *pb_adv_ctx_p; +extern pb_adv_ctx_t pb_adv_ctx[1]; +/** @} */ + +/** @defgroup Pb_Adv_Exported_Functions Exported Functions + * @{ + */ +///@cond +uint8_t pb_adv_init(prov_bearer_cb_pf pf_cb); +void pb_adv_deinit(void); +bool pb_adv_send(uint8_t ctx_index, uint8_t *pvalue, uint16_t len); +void pb_adv_receive(uint8_t *pdata, uint8_t len); +bool pb_adv_link_check(void); +void pb_adv_handle_timeout(uint32_t period); +///@endcond + +/** + * @brief open the pb adv link + * @param[in] ctx_index: the ctx idx + * @param[in] dev_uuid: remote device uuid + * @return send result + */ +bool pb_adv_link_open(uint8_t ctx_index, uint8_t dev_uuid[16]); + +/** + * @brief close the pb adv link + * @param[in] ctx_index: the ctx idx + * @param[in] reason: close reason + * @return send result + */ +bool pb_adv_link_close(uint8_t ctx_index, pb_adv_link_close_reason_t reason); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROVISION_ADV_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_device.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_device.h new file mode 100644 index 00000000..5700da6f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_device.h @@ -0,0 +1,99 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provision_device.h + * @brief Head file for mesh device. + * @details + * @author bill + * @date 2015-11-09 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROVISION_DEVICE_H_ +#define _PROVISION_DEVICE_H_ + +/* Add Includes here */ +#include "provision_generic.h" +#include "provision_adv.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Prov_Device + * @brief + * @{ + */ + +/** @defgroup Mesh_Prov_Device_Exported_Functions Exported Functions + * @brief + * @{ + */ + + +/** + * @brief disconnect the prov bearer + * + * The spec requires the provisioner to disconnect the bearer after the provision procedure. + * The mesh stack leaves the app to decide whether to disconnect at the case @ref PROV_CB_TYPE_COMPLETE. + * @param[in] reason: pb-adv bearer need the disconnect reason + * @return operation result + */ +bool prov_disconnect_dev(pb_adv_link_close_reason_t reason); + +/** + * @brief set the auth random value + * + * The function shall be called at the appropriate time. + * @param[in] random: random value + * @return operation result + */ +bool prov_auth_random_set_dev(uint8_t random[16]); + +/** + * @brief change the auth value + * + * The function shall be called at the appropriate time. The auth value will changed immediately + * @param[in] pvalue: auth value + * @param[in] len: value length + * @return operation result + */ +bool prov_auth_value_change_dev(uint8_t *pvalue, uint8_t len); + +/** + * @brief set the auth value + * + * The function shall be called at the appropriate time. The auth value shall be + * set with the appropriate length and data format. + * @param[in] pvalue: auth value + * @param[in] len: value length + * @return operation result + */ +bool prov_auth_value_set_dev(uint8_t *pvalue, uint8_t len); + +/** + * @brief device process provision data + * @param[in] pdata: provision data + * @param[in] len: provision data length + */ +void device_receive(uint8_t *pdata, uint16_t len); + +/** + * @brief device send data + * @param[in] pdata: provision data + * @param[in] len: provision data length + */ +bool prov_send_dev(uint8_t *pdata, uint16_t len); + +/** + * @brief initialize provision resources + */ +void prov_init_dev(void); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROVISION_DEVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_generic.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_generic.h new file mode 100644 index 00000000..5d419ad9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_generic.h @@ -0,0 +1,61 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provision_generic.h + * @brief Head file for provision generic layer. + * @details + * @author bill + * @date 2016-2-24 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROVISION_GENERIC_H_ +#define _PROVISION_GENERIC_H_ + +/* Add Includes here */ +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Prov_Generic + * @{ + */ + +/** @defgroup Mesh_Prov_Generic_Exported_Types Exported Types + * @{ + */ +typedef enum +{ + PB_GENERIC_TRANSACTION_START, + PB_GENERIC_TRANSACTION_ACK, + PB_GENERIC_TRANSACTION_CONTINUE, + PB_GENERIC_BEARER_CTRL +} prov_generic_ctrl_format_t; + +typedef struct +{ + uint8_t gpcf: 2; //!< Generic Provisioning Control Format @ref prov_generic_ctrl_format_t + uint8_t info: 6; +} _PACKED4_ prov_generic_ctrl_t; + +typedef enum +{ + PB_GENERIC_CB_LINK_OPENED, + PB_GENERIC_CB_LINK_OPEN_FAILED, + PB_GENERIC_CB_LINK_CLOSED, + PB_GENERIC_CB_MSG_ACKED, + PB_GENERIC_CB_MSG, + //todo: PB_GENERIC_CB_MSG_TRANSMITED maybe usefull calc ecdh secret after send public key to save time +} prov_generic_cb_type_t; + +typedef void (*prov_bearer_cb_pf)(prov_generic_cb_type_t type, uint8_t *pbuffer, + uint16_t len); //todo: add ctx index & ctx type when use multiple bearer +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROVISION_GENERIC_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_provisioner.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_provisioner.h new file mode 100644 index 00000000..d0b11920 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/provision_provisioner.h @@ -0,0 +1,167 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provision_provisioner.h + * @brief Head file for provisioner. + * @details Data structs and external functions declaration. + * @author bill + * @date 2015-11-09 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROVISION_PROVISIONER_H_ +#define _PROVISION_PROVISIONER_H_ + +/* Add Includes here */ +#include "provision_generic.h" +#include "mesh_api.h" +#include "mesh_provision.h" + +BEGIN_DECLS + +/** @addtogroup Mesh_Prov_Provisioner + * @brief + * @{ + */ + +/** @defgroup Mesh_Prov_Provisioner_Exported_Types Exported Types + * @brief + * @{ + */ +extern uint16_t assign_net_key_index; +extern uint16_t assign_addr; +extern int16_t assign_idx; +/** @} */ + +/** @defgroup Mesh_Prov_Provisioner_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief start the provisionging + * + * The function shall be called at the appropriate timing. + * @param[in] attn_dur: attention duration + * @return operation result + */ +bool prov_invite(uint8_t attn_dur); + +/** + * @brief assign the idx and addr to the new device + * + * The function can be called after @ref prov_invite and before @ref prov_send_prov_data, + * normally at the @ref PROV_CB_TYPE_PATH_CHOOSE case handler. + * The default idx assign scheme is to find the unused entry or the least addr entry. + * The default addr assign scheme is the maximum address of all devices plus 1. + * @param[in] idx: the entry index, < 0 represents to use the default assign scheme + * @param[in] addr: the address, 0 represents to use the default assign scheme + * @return the assign index + */ +uint16_t prov_assign(int16_t idx, uint16_t addr); + +/** + * @brief stop the provisioning + * @return operation result + */ +bool prov_reject(void); + +/** + * @brief unprov the device in the pb-gatt + * @deprecated + * @return operation result + */ +bool prov_unprovisioning(void); + +/** + * @brief choose one path from the eight prov pathes + * + * publick key: no oob publick key & oob publick key + * auth data: no oob & input & output & static + * @param[in] pprov_start: using the start pdu to choose + * @return operation result + */ +bool prov_path_choose(prov_start_p pprov_start); + +/** + * @brief set the public key of the provisioning device + * + * The function shall be called at the appropriate timing. + * @param[in] public_key: the ecc public key of the device + * @return operation result + */ +bool prov_device_public_key_set(uint8_t public_key[64]); + +/** + * @brief set the random and confirmation without the knownledge of auth value + * + * The app has no need to provide the auth value to the stack. + * @param[in] random: the random + * @param[in] conf: the confirmation + * @return operation result + */ +bool prov_auth_random_conf_set(uint8_t random[16], uint8_t conf[16]); + +/** + * @brief disconnect the prov bearer + * + * The spec requires the provisioner to disconnect the bearer after the provision procedure. + * The mesh stack leaves the app to decide whether to disconnect at the case @ref PROV_CB_TYPE_COMPLETE. + * @param[in] reason: pb-adv bearer need the disconnect reason + * @return operation result + */ +bool prov_disconnect_prov(pb_adv_link_close_reason_t reason); + +/** + * @brief set the auth random value + * + * The function shall be called at the appropriate time. + * @param[in] random: random value + * @return operation result + */ +bool prov_auth_random_set_prov(uint8_t random[16]); + +/** + * @brief change the auth value + * + * The function shall be called at the appropriate time. The auth value will changed immediately + * @param[in] pvalue: auth value + * @param[in] len: value length + * @return operation result + */ +bool prov_auth_value_change_prov(uint8_t *pvalue, uint8_t len); + +/** + * @brief set the auth value + * + * The function shall be called at the appropriate time. The auth value shall be + * set with the appropriate length and data format. + * @param[in] pvalue: auth value + * @param[in] len: value length + * @return operation result + */ +bool prov_auth_value_set_prov(uint8_t *pvalue, uint8_t len); + +/** + * @brief provisioner send data + * @param[in] pdata: provision data to send + * @param[in] len: provision data length + * @return send result + */ +bool prov_send_prov(uint8_t *pdata, uint16_t len); + +/** + * @brief initialize provision resources + */ +void prov_init_prov(void); + + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROVISION_PROVISIONER_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/proxy_protocol.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/proxy_protocol.h new file mode 100644 index 00000000..069f8cbd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/proxy_protocol.h @@ -0,0 +1,196 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file proxy_protocol.h + * @brief Head file for proxy protocol. + * @details + * @author bill + * @date 2016-11-26 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROXY_PROTOCOL_H_ +#define _PROXY_PROTOCOL_H_ + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** @addtogroup Proxy_Protocol + * @{ + */ + +/** @defgroup Proxy_Protocol_Exported_Macros Exported Macros + * @{ + */ +#define MESH_PROXY_PKT_OFFSET 3 //!< opcode + handle +#define MESH_PROXY_PKT_HEADER_SIZE 1 //!< @ref proxy_pkt_header_t +/** @} */ + +/** @defgroup Proxy_Protocol_Exported_Types Exported Types + * @{ + */ +typedef enum +{ + PROXY_PDU_TYPE_NET_PDU, + PROXY_PDU_TYPE_MESH_BEACON, + PROXY_PDU_TYPE_PROXY_CFG, + PROXY_PDU_TYPE_PROV_PDU +} proxy_pdu_type_t; + +typedef enum +{ + PROXY_SAR_COMPLETE, + PROXY_SAR_FIRST, + PROXY_SAR_CONTINUATE, + PROXY_SAR_LAST +} proxy_sar_t; + +typedef struct +{ + uint8_t type: 6; //!< @ref proxy_pdu_type_t + uint8_t sar: 2; //!< @ref proxy_sar_t +} _PACKED4_ proxy_pkt_header_t, *proxy_pkt_header_p; + +enum +{ + PROXY_CFG_OPCODE_SET_FILTER_TYPE, + PROXY_CFG_OPCODE_ADD_ADDR, + PROXY_CFG_OPCODE_REMOVE_ADDR, + PROXY_CFG_OPCODE_FILTER_STAT +} _SHORT_ENUM_; +typedef uint8_t proxy_cfg_opcode_t; + +enum +{ + PROXY_CFG_FILTER_TYPE_WHITE_LIST, + PROXY_CFG_FILTER_TYPE_BLACK_LIST +} _SHORT_ENUM_; +typedef uint8_t proxy_cfg_filter_type_t; + +typedef struct +{ + proxy_cfg_filter_type_t filter_type; +} _PACKED4_ proxy_cfg_set_filter_type_t, *proxy_cfg_set_filter_type_p; + +typedef struct +{ + uint8_t addr[2]; //!< variable length +} _PACKED4_ proxy_cfg_add_addr_t, *proxy_cfg_add_addr_p; + +typedef struct +{ + uint8_t addr[2]; //!< variable length +} _PACKED4_ proxy_cfg_remove_addr_t, *proxy_cfg_remove_addr_p; + +typedef struct +{ + proxy_cfg_filter_type_t filter_type; + uint8_t list_size[2]; +} _PACKED4_ proxy_cfg_filter_stat_t, *proxy_cfg_filter_stat_p; + +typedef struct +{ + proxy_cfg_opcode_t opcode; + union + { + proxy_cfg_set_filter_type_t set_filter_type; + proxy_cfg_add_addr_t add_addr; + proxy_cfg_remove_addr_t remove_addr; + proxy_cfg_filter_stat_t filter_stat; + }; +} _PACKED4_ proxy_cfg_msg_t, *proxy_cfg_msg_p; + +#define MESH_PROXY_PROTOCOL_ALL_CTX_ID 0xFF +#define MESH_PROXY_PROTOCOL_RSVD_CTX_ID 0xFE +typedef bool (*proxy_send_sar_pf)(gap_sched_link_t link, uint8_t *pvalue, uint16_t len); +typedef bool (*proxy_receive_cb_pf)(uint8_t ctx_id, proxy_pdu_type_t type, uint8_t *pvalue, + uint16_t len); + +typedef enum +{ + PROXY_CTX_TYPE_INVALID, + PROXY_CTX_TYPE_PROV, + PROXY_CTX_TYPE_PROXY, +} proxy_ctx_type_t; + +typedef struct +{ + proxy_ctx_type_t ctx_type; + bool data_out_cccd_enabled; + gap_sched_link_t link; + uint16_t net_key_index; + uint16_t rx_len; + uint8_t *rx_buffer; + plt_timer_t rx_timer; + proxy_receive_cb_pf pf_rx; + proxy_send_sar_pf pf_tx; + proxy_cfg_filter_type_t filter_type; + uint16_t addr_count; + mesh_addr_member_p addr_list; +} proxy_ctx_t, *proxy_ctx_p; +/** @} */ + +/** @defgroup Proxy_Protocol_Exported_Functions Exported Functions + * @{ + */ + +///@cond +void proxy_send(uint8_t ctx_id, proxy_pdu_type_t type, uint8_t *pvalue, uint16_t len); +bool proxy_receive(uint8_t ctx_id, uint8_t *pvalue, uint16_t len); +bool proxy_cfg_receive(uint8_t ctx_id, uint8_t *pbuffer, uint16_t len); +bool proxy_cfg_handle_msg(uint8_t ctx_id, uint8_t *pvalue, uint16_t len); + +void proxy_ctx_init(uint8_t proxy_count); +void proxy_ctx_deinit(void); + +uint8_t proxy_ctx_allocate(proxy_send_sar_pf proxy_send_sar, proxy_receive_cb_pf proxy_receive_cb, + proxy_ctx_type_t ctx_type); +bool proxy_ctx_set_filter_type(uint8_t ctx_id, proxy_cfg_filter_type_t filter_type); +bool proxy_ctx_set_cb(uint8_t ctx_id, proxy_send_sar_pf proxy_send_sar, + proxy_receive_cb_pf proxy_receive_cb); +bool proxy_ctx_set_link(uint8_t ctx_id, gap_sched_link_t link_id); +gap_sched_link_t proxy_ctx_get_link(uint8_t ctx_id); +bool proxy_ctx_enable_data_out_cccd(uint8_t ctx_id, bool enable); +bool proxy_ctx_is_data_out_cccd_enabled(uint8_t ctx_id); +uint8_t proxy_ctx_id_get(gap_sched_link_t link, proxy_ctx_type_t ctx_type); +void proxy_ctx_disconnect_all(proxy_ctx_type_t ctx_type); +uint8_t proxy_ctx_active_count(proxy_ctx_type_t ctx_type); +uint8_t proxy_ctx_idle_count(void); +bool proxy_ctx_free(uint8_t ctx_id); + +void proxy_filter_free(uint8_t ctx_id); +bool proxy_filter(uint8_t ctx_id, uint16_t addr); +void proxy_filter_update(uint8_t ctx_id, uint16_t addr); + +void proxy_handle_timeout(uint8_t ctx_id); +///@endcond + +/** + * @brief set the proxy filter type + * @param[in] ctx_id: the context idx + * @param[in] filter_type: the filter type + * @return send result + */ +bool proxy_cfg_set_filter_type(uint8_t ctx_id, proxy_cfg_filter_type_t filter_type); + +/** + * @brief set the proxy filter type + * @param[in] ctx_id: the context idx + * @param[in] add_remove: 1 - add, 0 - remove + * @param[in] addr: the address list + * @param[in] count: the address count + * @return send result + */ +bool proxy_cfg_add_remove_addr(uint8_t ctx_id, bool add_remove, uint16_t addr[], uint16_t count); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROXY_PROTOCOL_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_dev.a b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_dev.a new file mode 100644 index 00000000..e1a94bb8 Binary files /dev/null and b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_dev.a differ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_prov.a b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_prov.a new file mode 100644 index 00000000..ecb7402c Binary files /dev/null and b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_prov.a differ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/ali/ali_model.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/ali/ali_model.c new file mode 100644 index 00000000..826c50e4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/ali/ali_model.c @@ -0,0 +1,163 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file ali_model.c +* @brief Source file for ali model. +* @details Data types and external functions declaration. +* @author bill +* @date 2019-3-25 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "ali_model.h" + +typedef struct +{ + uint8_t tid_rx; + uint8_t tid_tx; +} ali_model_ctx_t; + +mesh_msg_send_cause_t ali_attr_get(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t tid, ali_attr_type_t attr_type[], uint8_t type_num) +{ + mesh_msg_send_cause_t ret; + ali_attr_get_t *pmsg; + uint16_t msg_len = MEMBER_OFFSET(ali_attr_get_t, attr_type) + type_num * sizeof(ali_attr_type_t); + pmsg = (ali_attr_get_t *)plt_malloc(msg_len, RAM_TYPE_DATA_OFF); + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_ALI_ATTR_GET); + pmsg->tid = tid; + memcpy(pmsg->attr_type, attr_type, type_num * sizeof(ali_attr_type_t)); + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + ret = access_send(&mesh_msg); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +mesh_msg_send_cause_t ali_attr_conf(mesh_model_info_t *pmodel_info, const mesh_msg_t *pmesh_msg, + uint8_t tid) +{ + ali_attr_conf_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_ALI_ATTR_CONF); + msg.tid = tid; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = sizeof(msg); + mesh_msg.dst = pmesh_msg->dst; + mesh_msg.app_key_index = pmesh_msg->app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t ali_attr_msg_raw(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint32_t ali_opcode, uint8_t tid, uint8_t raw_data[], uint16_t data_len) +{ + mesh_msg_send_cause_t ret; + ali_attr_set_t *pmsg; + uint16_t msg_len = MEMBER_OFFSET(ali_attr_set_t, attr_type) + data_len; + pmsg = (ali_attr_set_t *)plt_malloc(msg_len, RAM_TYPE_DATA_OFF); + ACCESS_OPCODE_BYTE(pmsg->opcode, ali_opcode); + pmsg->tid = tid; + memcpy(&pmsg->attr_type, raw_data, data_len); + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + ret = access_send(&mesh_msg); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +static uint16_t ali_attr_len(ali_attr_t attr[1], uint16_t attr_num) +{ + uint16_t len = 0; + for (uint16_t loop = 0; loop < attr_num; loop++) + { + len += sizeof(ali_attr_type_t) + attr[loop].param_len; + } + return len; +} + +mesh_msg_send_cause_t ali_attr_msg(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint32_t ali_opcode, uint8_t tid, ali_attr_t attr[1], uint16_t attr_num) +{ + mesh_msg_send_cause_t ret; + ali_attr_set_t *pmsg; + uint16_t msg_len = MEMBER_OFFSET(ali_attr_set_t, attr_type) + ali_attr_len(attr, attr_num); + pmsg = (ali_attr_set_t *)plt_malloc(msg_len, RAM_TYPE_DATA_OFF); + ACCESS_OPCODE_BYTE(pmsg->opcode, ali_opcode); + pmsg->tid = tid; + uint8_t *pdata = (uint8_t *)&pmsg->attr_type; + for (uint16_t loop = 0; loop < attr_num; loop++) + { + LE_WORD2EXTRN(pdata, attr[loop].attr_type); + pdata += sizeof(ali_attr_type_t); + memcpy(pdata, attr[loop].attr_param, attr[loop].param_len); + pdata += attr[loop].param_len; + } + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + ret = access_send(&mesh_msg); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +mesh_msg_send_cause_t ali_transparent_msg(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t transparent_msg[1], uint16_t msg_len) +{ + mesh_msg_send_cause_t ret; + ali_transparent_msg_t *pmsg; + msg_len += MEMBER_OFFSET(ali_transparent_msg_t, transparent_msg); + pmsg = (ali_transparent_msg_t *)plt_malloc(msg_len, RAM_TYPE_DATA_OFF); + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_ALI_TRANSPARENT_MSG); + memcpy(pmsg->transparent_msg, transparent_msg, msg_len); + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + ret = access_send(&mesh_msg); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +bool ali_model_reg(uint8_t element_index, mesh_model_info_p pmodel_info, bool server) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + /* ali model server & client can't exist at the same element due to the transparent msg */ + if (NULL != mesh_model_info_get_by_model_id(element_index, + server ? MESH_MODEL_ALI_VENDOR_CLIENT : MESH_MODEL_ALI_VENDOR_SERVER)) + { + return FALSE; + } + pmodel_info->model_id = server ? MESH_MODEL_ALI_VENDOR_SERVER : MESH_MODEL_ALI_VENDOR_CLIENT; + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/ali/ali_model.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/ali/ali_model.h new file mode 100644 index 00000000..0ef04f13 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/ali/ali_model.h @@ -0,0 +1,486 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ali_model.h + * @brief Head file for ali model. + * @details Data types and external functions declaration. + * @author bill + * @date 2019-3-25 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _ALI_MODEL_H +#define _ALI_MODEL_H + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup ALI + * @{ + */ + +/** + * @defgroup ALI_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_ALI_TRANSPARENT_MSG 0xCFA801 +#define MESH_MSG_ALI_ATTR_GET 0xD0A801 +#define MESH_MSG_ALI_ATTR_SET 0xD1A801 +#define MESH_MSG_ALI_ATTR_SET_UNACK 0xD2A801 +#define MESH_MSG_ALI_ATTR_STAT 0xD3A801 +#define MESH_MSG_ALI_ATTR_IND 0xD4A801 +#define MESH_MSG_ALI_ATTR_CONF 0xD5A801 +#define MESH_MSG_ALI_ATTR_REQ 0xDEA801 +#define MESH_MSG_ALI_ATTR_RESP 0xDFA801 +/** @} */ + +/** + * @defgroup ALI_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_ALI_VENDOR_SERVER 0x000001A8 +#define MESH_MODEL_ALI_VENDOR_CLIENT 0x000101A8 +/** @} */ + +/** + * @defgroup ALI_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +enum +{ + /* system attr */ + ALI_ATTR_TYPE_ERROR = 0x0000, + ALI_ATTR_TYPE_VERSION = 0xFF01, + ALI_ATTR_TYPE_DEVICE_FEATRUE = 0xFF02, + ALI_ATTR_TYPE_FLASH_TOTAL_SIZE = 0xFF03, + ALI_ATTR_TYPE_FLASH_USED_SIZE = 0xFF04, + ALI_ATTR_TYPE_FLASH_UNUSED_SIZE = 0xFF05, + ALI_ATTR_TYPE_ENGINEER_MODE = 0xFF06, + /* generic attr */ + ALI_ATTR_TYPE_WORK_STAT = 0xF001, + ALI_ATTR_TYPE_USER_ID = 0xF002, + ALI_ATTR_TYPE_DEVICE_NAME = 0xF003, + ALI_ATTR_TYPE_SCENE_MODE = 0xF004, + ALI_ATTR_TYPE_ON_OFF_SCHED = 0xF008, + ALI_ATTR_TYPE_EVENT = 0xF009, + ALI_ATTR_TYPE_SIGNAL_STRENGTH = 0xF00A, + ALI_ATTR_TYPE_STEP_MOVE = 0xF00B, + ALI_ATTR_TYPE_ELEMENT_NUM = 0xF00C, + ALI_ATTR_TYPE_ATTR_SWITCH = 0xF00D, + ALI_ATTR_TYPE_RMT_ADDR = 0xF00E, + ALI_ATTR_TYPE_NEIGHBOR_DEVICE_SIGNAL_STRENGTH = 0xF00F, + ALI_ATTR_TYPE_TIMING_SETTING = 0xF010, + ALI_ATTR_TYPE_PERIODIC_SETTING = 0xF011, + ALI_ATTR_TYPE_REMOVE_TIMING = 0xF012, + ALI_ATTR_TYPE_REQ_UPD_TIMING = 0xF013, + ALI_ATTR_TYPE_TIME_SYNC = 0xF01D, + ALI_ATTR_TYPE_TIMEZONE_SETTING = 0xF01E, + ALI_ATTR_TYPE_UNIX_TIME = 0xF01F, + ALI_ATTR_TYPE_POWER_OFF_STORE = 0xF021, + /* generic physical */ + ALI_ATTR_TYPE_ON_OFF = 0x0100, + ALI_ATTR_TYPE_DATE = 0x0101, + ALI_ATTR_TYPE_TIME = 0x0102, + ALI_ATTR_TYPE_UNIX_TIMESTAMP = 0x0103, + ALI_ATTR_TYPE_BATTERY_PERCENTAGE = 0x0104, + ALI_ATTR_TYPE_VOLTAGE = 0x0105, + ALI_ATTR_TYPE_CURRENT = 0x0106, + ALI_ATTR_TYPE_POWER = 0x0107, + ALI_ATTR_TYPE_POWER_CONSUMPTION = 0x0108, + ALI_ATTR_TYPE_VOLUME = 0x0109, + ALI_ATTR_TYPE_LEVEL = 0x010A, + ALI_ATTR_TYPE_UNIT = 0x010B, + ALI_ATTR_TYPE_TARGET_TEMPERATURE = 0x010C, + ALI_ATTR_TYPE_PRESENT_TEMPERATURE = 0x010D, + ALI_ATTR_TYPE_TARGET_HUMIDITY = 0x010E, + ALI_ATTR_TYPE_PRESENT_HUMIDITY = 0x010F, + ALI_ATTR_TYPE_FB_POSITION = 0x0110, + ALI_ATTR_TYPE_LR_POSITION = 0x0111, + ALI_ATTR_TYPE_UD_POSITION = 0x0112, + ALI_ATTR_TYPE_FL_POSITION = 0x0113, + ALI_ATTR_TYPE_BL_POSITION = 0x0114, + ALI_ATTR_TYPE_LL_POSITION = 0x0115, + ALI_ATTR_TYPE_RL_POSITION = 0x0116, + ALI_ATTR_TYPE_UL_POSITION = 0x0117, + ALI_ATTR_TYPE_DL_POSITION = 0x0118, + ALI_ATTR_TYPE_UD_ANGLE = 0x0119, + ALI_ATTR_TYPE_LR_ANGLE = 0x011A, + ALI_ATTR_TYPE_UL_ANGLE = 0x011B, + ALI_ATTR_TYPE_DL_ANGLE = 0x011C, + ALI_ATTR_TYPE_LL_ANGLE = 0x011D, + ALI_ATTR_TYPE_RL_ANGLE = 0x011E, + ALI_ATTR_TYPE_POSITION_CALIBRATION = 0x011F, + ALI_ATTR_TYPE_WATER_LEVEL = 0x0120, + ALI_ATTR_TYPE_LIGHTNESS_LEVEL = 0x0121, + ALI_ATTR_TYPE_COLOR_TEMPERATURE = 0x0122, + ALI_ATTR_TYPE_HSL_COLOR = 0x0123, + ALI_ATTR_TYPE_SECONDARY_ON_OFF = 0x0124, + ALI_ATTR_TYPE_TERTIARY_ON_OFF = 0x0125, + ALI_ATTR_TYPE_SECONDARY_LEVEL = 0x0128, + ALI_ATTR_TYPE_TERTIARY_LEVEL = 0x0129, + /* sport & health */ + ALI_ATTR_TYPE_WEIGHT = 0x0200, + ALI_ATTR_TYPE_IMPEDANCE = 0x0201, + ALI_ATTR_TYPE_BODY_FAT_PERCENTAGE = 0x0202, + ALI_ATTR_TYPE_BMI = 0x0203, + ALI_ATTR_TYPE_MUSCLE_MASS = 0x0204, + ALI_ATTR_TYPE_MUSCLE_PERCENTAGE = 0x0205, + ALI_ATTR_TYPE_FATFREE_MASS = 0x0206, + ALI_ATTR_TYPE_HEIGHT = 0x0207, + ALI_ATTR_TYPE_BODY_WATER_MASS = 0x0208, + ALI_ATTR_TYPE_BASAL_METABOLISM = 0x0209, + ALI_ATTR_TYPE_SPO2 = 0x020A, + ALI_ATTR_TYPE_SYSTOLIC_PRESSURE = 0x020B, + ALI_ATTR_TYPE_DIASTOLIC_PRESSURE = 0x020C, + ALI_ATTR_TYPE_BLUOD_GLUCOSE = 0x020D, + ALI_ATTR_TYPE_SPEED = 0x020E, + ALI_ATTR_TYPE_PACE = 0x020F, + ALI_ATTR_TYPE_SLOPE = 0x0210, + ALI_ATTR_TYPE_MOTION_RESISTANCE_LEVEL = 0x0211, + ALI_ATTR_TYPE_SPORT_COUNT = 0x0212, + ALI_ATTR_TYPE_SPORT_START_TIME = 0x0213, + ALI_ATTR_TYPE_SPORTING_TIME = 0x0214, + ALI_ATTR_TYPE_SPORT_TARGET_TIME = 0x0215, + ALI_ATTR_TYPE_DISTANCE = 0x0216, + ALI_ATTR_TYPE_TARGET_DISTANCE = 0x0217, + ALI_ATTR_TYPE_HEARTRATE = 0x0218, + ALI_ATTR_TYPE_TACHOGRAPHS = 0x0219, + ALI_ATTR_TYPE_TOTAL_STEP = 0x021A, + ALI_ATTR_TYPE_SITTING_TIME = 0x021B, + ALI_ATTR_TYPE_SPORT_TIME = 0x021C, + ALI_ATTR_TYPE_SLEEP_TIME = 0x021D, + ALI_ATTR_TYPE_LIGHT_SLEEP_TIME = 0x021E, + ALI_ATTR_TYPE_DEEP_SLEEP_TIME = 0x021F, + ALI_ATTR_TYPE_TURN_OVER = 0x0220, + ALI_ATTR_TYPE_TOTAL_CALORIES = 0x0221, + ALI_ATTR_TYPE_CURRENT_STEP = 0x0222, + /* air quality */ + ALI_ATTR_TYPE_PM2_5 = 0x0300, + ALI_ATTR_TYPE_PM10 = 0x0301, + ALI_ATTR_TYPE_SO2 = 0x0302, + ALI_ATTR_TYPE_NO2 = 0x0303, + ALI_ATTR_TYPE_CO = 0x0304, + ALI_ATTR_TYPE_CO2 = 0x0305, + ALI_ATTR_TYPE_O3 = 0x0306, + ALI_ATTR_TYPE_HCHO = 0x0307, + ALI_ATTR_TYPE_TVOC = 0x0308, + ALI_ATTR_TYPE_AQI = 0x0309, + /* water quality */ + ALI_ATTR_TYPE_PH = 0x030A, + ALI_ATTR_TYPE_DISSOLVED_OXYGEN = 0x030B, + ALI_ATTR_TYPE_TDS = 0x030C, + /* device state */ + ALI_ATTR_TYPE_DOOR_STATE = 0x0400, + ALI_ATTR_TYPE_HUMAN_ACTIVITY = 0x0401, + /* device function */ + ALI_ATTR_TYPE_ANGLE_AUTO_LR_ONOFF = 0x0500, + ALI_ATTR_TYPE_ANGLE_AUTO_UD_ONOFF = 0x0501, + ALI_ATTR_TYPE_POSITION_AUTO_LR_ONOFF = 0x0502, + ALI_ATTR_TYPE_POSITION_AUTO_FB_ONOFF = 0x0503, + ALI_ATTR_TYPE_POSITION_AUTO_UD_ONOFF = 0x0504, + ALI_ATTR_TYPE_ANION_ONOFF = 0x0505, + ALI_ATTR_TYPE_CONSTANT_HUMIDITY_ONOFF = 0x0506, + ALI_ATTR_TYPE_SLEEP_ONOFF = 0x0507, + ALI_ATTR_TYPE_ECO_ONOFF = 0x0508, + ALI_ATTR_TYPE_STRONG_ONOFF = 0x0509, + ALI_ATTR_TYPE_AUTO_ONOFF = 0x050A, + ALI_ATTR_TYPE_CHILD_LOCK_ONOFF = 0x050C, + ALI_ATTR_TYPE_DISPLAY_ONOFF = 0x050D, + ALI_ATTR_TYPE_GREEN_ONOFF = 0x050E, + ALI_ATTR_TYPE_NO_STRAIGHT_BLOWING_ONOFF = 0x050F, + ALI_ATTR_TYPE_HEATING = 0x0510, + ALI_ATTR_TYPE_COOLING_ONOFF = 0x0511, + ALI_ATTR_TYPE_MASSAGE_ONOFF = 0x0512, + ALI_ATTR_TYPE_BUBBLE_ONOFF = 0x0513, + ALI_ATTR_TYPE_AIR_PRESSURE_ONOFF = 0x0514, + ALI_ATTR_TYPE_VIBRATING_ONOFF = 0x0515, + ALI_ATTR_TYPE_UP_TUBE_BAKING_ONOFF = 0x0516, + ALI_ATTR_TYPE_BOTTOM_TUBE_BAKING_ONOFF = 0x0517, + ALI_ATTR_TYPE_BOTH_TUBE_BAKING_ONOFF = 0x0518, + ALI_ATTR_TYPE_HEAT_POWER = 0x0519, + ALI_ATTR_TYPE_PRESERVE_HEAT_ONOFF = 0x051A, + ALI_ATTR_TYPE_TASTE = 0x051B, + ALI_ATTR_TYPE_RICE_TYPE = 0x051C, + ALI_ATTR_TYPE_SWEET_TASTE = 0x051D, + ALI_ATTR_TYPE_MICRO_WAVE = 0x051E, + ALI_ATTR_TYPE_LIGHT_WAVE = 0x051F, + ALI_ATTR_TYPE_DEODORIZATION_ONOFF = 0x0520, + ALI_ATTR_TYPE_FAN_DIRECTION = 0x0521, + ALI_ATTR_TYPE_STEP_ACTION_ONOFF = 0x0522, + ALI_ATTR_TYPE_HUMAN_DETECT_ONOFF = 0x0523, + ALI_ATTR_TYPE_IR_ONOFF = 0x0524, + ALI_ATTR_TYPE_QUICK_FRONZEN_ONOFF = 0x0525, + ALI_ATTR_TYPE_DEFROST_ONOFF = 0x0526, + ALI_ATTR_TYPE_ANTIBIOSIS_ONOFF = 0x0527, + ALI_ATTR_TYPE_SILVER_ION_ONOFF = 0x0528, + ALI_ATTR_TYPE_STRONG_WASHING_ONOFF = 0x0529, + ALI_ATTR_TYPE_QUICK_WASHING_ONOFF = 0x052A, + ALI_ATTR_TYPE_OFF_PEAK_ONOFF = 0x052B, + ALI_ATTR_TYPE_LOW_TEMPERATURE_ONOFF = 0x052C, + ALI_ATTR_TYPE_IRON_FREE_ONOFF = 0x052D, + ALI_ATTR_TYPE_ULTRAVIOLET_ONOFF = 0x052E, + ALI_ATTR_TYPE_AIR_DRY_ONOFF = 0x052F, + ALI_ATTR_TYPE_CONSTANT_TEMPERATURE_ONOFF = 0x0530, + ALI_ATTR_TYPE_QUICK_STEW_ONOFF = 0x0531, + ALI_ATTR_TYPE_SHOCK_ABSORBTION_ONOFF = 0x0532, + ALI_ATTR_TYPE_BACKGROUND_LIGHT_ONOFF = 0x0533, + ALI_ATTR_TYPE_MAIN_LIGHT_ONOFF = 0x0534, + ALI_ATTR_TYPE_MUTE_ONOFF = 0x0535, + ALI_ATTR_TYPE_HUMIDIFICATION_ONOFF = 0x0536, + ALI_ATTR_TYPE_CLEAN_ONOFF = 0x0537, + ALI_ATTR_TYPE_COOL_WIND_ONOFF = 0x0538, + ALI_ATTR_TYPE_HOT_WIND_ONOFF = 0x0539, + ALI_ATTR_TYPE_SMART_WIND = 0x053A, + ALI_ATTR_TYPE_EIGHT_DEGREE_HEATING = 0x053B, + ALI_ATTR_TYPE_NOBODY_SAVE = 0x053C, + ALI_ATTR_TYPE_LOW_TEM_DRY = 0x053D, + ALI_ATTR_TYPE_MILDEW_PROOF = 0x053E, + ALI_ATTR_TYPE_ELECTRIC_HEATING = 0x053F, + ALI_ATTR_TYPE_CURRENT_POWER = 0x0540, + ALI_ATTR_TYPE_HEALTH_FUNCTION = 0x0541, + ALI_ATTR_TYPE_ANGLE = 0x0542, + ALI_ATTR_TYPE_WIND_SPEED = 0x0543, + ALI_ATTR_TYPE_TEMP_SWTICH = 0x0544, + ALI_ATTR_TYPE_MUSIC_SWTICH = 0x0545, + ALI_ATTR_TYPE_MASSAGE_AIR_STRENGTH = 0x0546 +} _SHORT_ENUM_; +typedef uint16_t ali_attr_type_t; + +enum +{ + ALI_EVENT_ID_LOW_POWER = 0x01, + ALI_EVENT_ID_DEVICE_CRASH, + ALI_EVENT_ID_DEVICE_POWER_ON, + ALI_EVENT_ID_KEY_CLICK = 0x05, + ALI_EVENT_ID_KEY_DOUBLE_CLICK, + ALI_EVENT_ID_KEY_LONG_PRESS, + ALI_EVENT_ID_WATER_LEVEL_TOO_HIGH, + ALI_EVENT_ID_WATER_LEVEL_TOO_LOW, + ALI_EVENT_ID_TEMPERATURE_TOO_HIGH, + ALI_EVENT_ID_TEMPERATURE_TOO_LOW, + ALI_EVENT_ID_COMPONENT_MISS, + ALI_EVENT_ID_GAS_ALERT, + ALI_EVENT_ID_SMOG_ALERT, + ALI_EVENT_ID_FIRE_ALERT, + ALI_EVENT_ID_BREAK_IN_ALERT, + ALI_EVENT_ID_TIMING_COMPLETE, + ALI_EVENT_ID_DEVICE_NETWORKING, + ALI_EVENT_ID_CHARGING_START, + ALI_EVENT_ID_CHARGING_COMPLETE +} _SHORT_ENUM_; +typedef uint8_t ali_event_id_t; + +enum +{ + ALI_SCENE_NUM_DEFAULT = 0x0001, + ALI_SCENE_NUM_AUTO, + ALI_SCENE_NUM_READ, + ALI_SCENE_NUM_CINEMA, + ALI_SCENE_NUM_WARMTH, + ALI_SCENE_NUM_NIGHT_LIGHT, + ALI_SCENE_NUM_HELP_SLEEP, + ALI_SCENE_NUM_GET_UP, + ALI_SCENE_NUM_REFRIGERATION, + ALI_SCENE_NUM_HEATING, + ALI_SCENE_NUM_VENTILATE, + ALI_SCENE_NUM_BLOWING_IN, + ALI_SCENE_NUM_DEHUMIDIFICATION, + ALI_SCENE_NUM_SLEEP, + ALI_SCENE_NUM_LIVING, + ALI_SCENE_NUM_MANUAL = 0x0010, + ALI_SCENE_NUM_MUTE, + ALI_SCENE_NUM_POWER_SAVING, + ALI_SCENE_NUM_WIND_NORMAL, + ALI_SCENE_NUM_WIND_NATUAL, + ALI_SCENE_NUM_WIND_SLEEP, + ALI_SCENE_NUM_WIND_MUTE, + ALI_SCENE_NUM_WIND_COMFORT, + ALI_SCENE_NUM_WIND_BABY, + ALI_SCENE_NUM_COTTON, + ALI_SCENE_NUM_CHEMICAL_FIBER, + ALI_SCENE_NUM_WOOL, + ALI_SCENE_NUM_DEGERMING, + ALI_SCENE_NUM_CUBE_CLEAN, + ALI_SCENE_NUM_SILK, + ALI_SCENE_NUM_HOLIDAY, + ALI_SCENE_NUM_SMART = 0x0020, + ALI_SCENE_NUM_MUSIC, + ALI_SCENE_NUM_ZERO_G, + ALI_SCENE_NUM_ANTI_SNORE, + ALI_SCENE_NUM_MULTI_PLAYER, + ALI_SCENE_NUM_WOBBLING, + ALI_SCENE_NUM_STRONG, + ALI_SCENE_NUM_NORMAL, + ALI_SCENE_NUM_WORK, + ALI_SCENE_NUM_QUICK_COOL, + ALI_SCENE_NUM_QUICK_FREEZE, + ALI_SCENE_NUM_MICRO_DRY, + ALI_SCENE_NUM_FULL_DRY, + ALI_SCENE_NUM_SUPER_DRY, + ALI_SCENE_NUM_SUMMER, + ALI_SCENE_NUM_WINTER, + ALI_SCENE_NUM_STANDARD = 0x0030, + ALI_SCENE_NUM_QUICK_WASH, + ALI_SCENE_NUM_BABY_WASH, + ALI_SCENE_NUM_ONLY_DEHYDRATION, + ALI_SCENE_NUM_POWER_SAVING_WASH, + ALI_SCENE_NUM_INTELLIGENT_LIGHT, + ALI_SCENE_NUM_LEARN, + ALI_SCENE_NUM_BEFORE_SLEEP, + ALI_SCENE_NUM_EYE_PROTECT_INTELLIGENT, + ALI_SCENE_NUM_EYE_PROTECT, + ALI_SCENE_NUM_SMASH, + ALI_SCENE_NUM_VACUUM, + ALI_SCENE_NUM_STIR, + ALI_SCENE_NUM_WARM, + ALI_SCENE_NUM_UNFREEZE, + ALI_SCENE_NUM_FERMENTATION, + ALI_SCENE_NUM_OPEN_COOK = 0x0040, + ALI_SCENE_NUM_BAKE, + ALI_SCENE_NUM_STEAM, + ALI_SCENE_NUM_STEW, + ALI_SCENE_NUM_STEAM_STEW, + ALI_SCENE_NUM_NO_WATER_BAKE, + ALI_SCENE_NUM_FRYING, + ALI_SCENE_NUM_HOT_POT, + ALI_SCENE_NUM_FRIED_DISH, + ALI_SCENE_NUM_HEAT_UP_WATER, + ALI_SCENE_NUM_SWEETMEATS, + ALI_SCENE_NUM_EGG_CUSTARD, + ALI_SCENE_NUM_POTATO_STEW, + ALI_SCENE_NUM_MEAT, + ALI_SCENE_NUM_CHICKEN_DUCK, + ALI_SCENE_NUM_COW_SHEEP, + ALI_SCENE_NUM_FISH = 0x0050, + ALI_SCENE_NUM_BIG_BONES, + ALI_SCENE_NUM_RIBS, + ALI_SCENE_NUM_TENDON_BEAN, + ALI_SCENE_NUM_SEASONAL_VEGETABLE, + ALI_SCENE_NUM_FROZEN_FOODS, + ALI_SCENE_NUM_PASTRY, + ALI_SCENE_NUM_PIZZA, + ALI_SCENE_NUM_ROAST_PORK, +} _SHORT_ENUM_; +typedef uint16_t ali_scene_num_t; + +enum +{ + ALI_ERROR_CODE_NOT_READY = 0x80, //!< @ref HEALTH_FAULT_VENDOR_START + ALI_ERROR_CODE_NOT_SUPPORTED_ATTR, + ALI_ERROR_CODE_NOT_SUPPORTED_OPERATION, + ALI_ERROR_CODE_INVALID_PARAMETER, + ALI_ERROR_CODE_INVALID_STATE, + ALI_ERROR_CODE_NOT_FOUND_INDEX, + ALI_ERROR_CODE_FULL_STORAGE, + ALI_ERROR_CODE_WRONG_FORMAT +} _SHORT_ENUM_; +typedef uint8_t ali_error_code_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_ALI_ATTR_GET)]; + uint8_t tid; + ali_attr_type_t attr_type[1]; //!< variable number +} _PACKED4_ ali_attr_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_ALI_ATTR_SET)]; + uint8_t tid; + ali_attr_type_t attr_type[1]; //!< variable number + uint8_t attr_param[1]; //!< variable length +} _PACKED4_ ali_attr_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_ALI_ATTR_STAT)]; + uint8_t tid; + ali_attr_type_t attr_type[1]; //!< variable number + uint8_t attr_param[1]; //!< variable length +} _PACKED4_ ali_attr_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_ALI_ATTR_IND)]; + uint8_t tid; + ali_attr_type_t attr_type[1]; //!< variable number + uint8_t attr_param[1]; //!< variable length +} _PACKED4_ ali_attr_ind_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_ALI_ATTR_CONF)]; + uint8_t tid; +} _PACKED4_ ali_attr_conf_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_ALI_TRANSPARENT_MSG)]; + uint8_t transparent_msg[1]; //!< variable length +} _PACKED4_ ali_transparent_msg_t; +/** @} */ + +/** + * @defgroup ALI_ATTR_DATA Attr Definition + * @brief attribute data struct + * @{ + */ +typedef struct +{ + ali_attr_type_t attr_type; + ali_error_code_t error_code; +} _PACKED4_ ali_attr_error_t; + +typedef struct +{ + ali_attr_type_t attr_type; + uint16_t param_len; + uint8_t *attr_param; +} ali_attr_t; +/** @} */ + +/** + * @defgroup ALI_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +typedef enum +{ + ALI_SERVER_DATA_TYPE_ATTR_GET, //!< @ref + ALI_SERVER_DATA_TYPE_ATTR_SET, //!< @ref + ALI_SERVER_DATA_TYPE_ATTR_INDICATION_RESULT, //!< @ref + ALI_SERVER_DATA_TYPE_TRANSPARENT //!< @ref +} ali_server_data_type_t; +/** @} */ + +/** + * @defgroup ALI_MODEL_API MODEL API + * @brief Functions declaration + * @{ + */ +mesh_msg_send_cause_t ali_attr_get(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t tid, ali_attr_type_t attr_type[], uint8_t type_num); +mesh_msg_send_cause_t ali_attr_conf(mesh_model_info_t *pmodel_info, const mesh_msg_t *pmesh_msg, + uint8_t tid); +mesh_msg_send_cause_t ali_attr_msg_raw(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint32_t ali_opcode, uint8_t tid, uint8_t raw_data[], uint16_t data_len); +mesh_msg_send_cause_t ali_attr_msg(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint32_t ali_opcode, uint8_t tid, ali_attr_t attr[1], uint16_t attr_num); +mesh_msg_send_cause_t ali_transparent_msg(mesh_model_info_t *pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t transparent_msg[1], uint16_t msg_len); +bool ali_model_reg(uint8_t element_index, mesh_model_info_p pmodel_info, bool server); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _ALI_MODEL_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer.h new file mode 100644 index 00000000..4d3d1f0b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer.h @@ -0,0 +1,581 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file blob_transfer.h +* @brief Head file for blob transfer models. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-5-21 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _BLOB_TRANSFER_H +#define _BLOB_TRANSFER_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "mesh_api.h" + +#if MESH_BLOB + +BEGIN_DECLS + +/** + * @addtogroup BLOB_TRANSFER + * @{ + */ + +/* blob server capabilites */ +#define BLOB_TRANSFER_CPAS_MIN_BLOCK_SIZE_LOG 6 +#define BLOB_TRANSFER_CPAS_MAX_BLOCK_SIZE_LOG 12 +#define BLOB_TRANSFER_CPAS_MAX_TOTAL_CHUNKS 20 +#define BLOB_TRANSFER_CPAS_MAX_CHUNK_SIZE 256 +#define BLOB_TRANSFER_CPAS_MAX_BLOB_SIZE 5000 +#define BLOB_TRANSFER_CPAS_SERVER_MTU_SIZE 350 +#define BLOB_TRANSFER_CPAS_MODE_PULL_SUPPORT 1 +#define BLOB_TRANSFER_CPAS_MODE_PUSH_SUPPORT 1 + +/** + * @defgroup BLOB_TRANSFER_ACCESS_OPCODE Access Opcode + * @brief Mesh messsage access opcode + * @{ + */ +#define MESH_MSG_BLOB_TRANSFER_GET 0xB701 +#define MESH_MSG_BLOB_TRANSFER_START 0xB702 +#define MESH_MSG_BLOB_TRANSFER_CANCEL 0xB703 +#define MESH_MSG_BLOB_TRANSFER_STATUS 0xB704 +#define MESH_MSG_BLOB_BLOCK_GET 0xB707 +#define MESH_MSG_BLOB_BLOCK_START 0xB705 +#define MESH_MSG_BLOB_BLOCK_STATUS 0x7E +#define MESH_MSG_BLOB_PARTIAL_BLOCK_REPORT 0x4F +#define MESH_MSG_BLOB_CHUNK_TRANSFER 0x7D +#define MESH_MSG_BLOB_INFO_GET 0xB70A +#define MESH_MSG_BLOB_INFO_STATUS 0xB70B +/** @} */ + +/** + * @defgroup BLOB_TRANSFER_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_BLOB_TRANSFER_SERVER 0xBF42FFFF +#define MESH_MODEL_BLOB_TRANSFER_CLIENT 0xBF43FFFF +/** @} */ + +/** + * @defgroup BLOB_TRANSFER_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +enum +{ + BLOB_TRANSFER_PHASE_IDLE, + BLOB_TRANSFER_PHASE_WAITING_START, + BLOB_TRANSFER_PHASE_WAITING_BLOCK, + BLOB_TRANSFER_PHASE_WAITING_CHUNK, + BLOB_TRANSFER_PHASE_COMPLETE, + BLOB_TRANSFER_PHASE_SUSPENDED, +} _SHORT_ENUM_; +typedef uint8_t blob_transfer_phase_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_TRANSFER_GET)]; +} _PACKED4_ blob_transfer_get_t; + +#define BLOB_BLOCK_SIZE_LOG_MIN 0x6 +#define BLOB_BLOCK_SIZE_LOG_MAX 0x20 + +enum +{ + BLOB_TRANSFER_MODE_IDLE, //!< No active transfer + BLOB_TRANSFER_MODE_PUSH, //!< Push BLOB transfer mode + BLOB_TRANSFER_MODE_PULL, //!< Pull BlOB transfer mode +} _SHORT_ENUM_; +typedef uint8_t blob_transfer_mode_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_TRANSFER_START)]; + uint8_t rfu : 6; + uint8_t transfer_mode : 2; + uint8_t blob_id[8]; + uint32_t blob_size; + uint8_t block_size_log; //!< limited range + uint16_t client_mtu_size; +} _PACKED4_ blob_transfer_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_TRANSFER_CANCEL)]; + uint8_t blob_id[8]; +} _PACKED4_ blob_transfer_cancel_t; + +enum +{ + BLOB_TRANSFER_STATUS_SUCCESS, + BLOB_TRANSFER_STATUS_INVALID_BLOCK_NUM, + BLOB_TRANSFER_STATUS_INVALID_BLOCK_SIZE, + BLOB_TRANSFER_STATUS_INVALID_CHUNK_SIZE, + BLOB_TRANSFER_STATUS_WRONG_PHASE, + BLOB_TRANSFER_STATUS_INVALID_PARAMETER, + BLOB_TRANSFER_STATUS_WRONG_ID, + BLOB_TRANSFER_STATUS_TOO_LARGE, + BLOB_TRANSFER_STATUS_UNSUPPORTED_MODE, + BLOB_TRANSFER_STATUS_INTERNAL_ERR, + BLOB_TRANSFER_STATUS_INFO_UNAVAILABLE, +} _SHORT_ENUM_; +typedef uint8_t blob_transfer_status_code_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_TRANSFER_STATUS)]; + uint8_t status : 4; + uint8_t rfu : 2; + uint8_t transfer_mode : 2; + blob_transfer_phase_t transfer_phase; + uint8_t blob_id[8]; + uint32_t blob_size; + uint8_t block_size_log; //!< limited range + uint16_t transfer_mtu_size; + uint8_t blocks_not_received[0]; +} _PACKED4_ blob_transfer_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_BLOCK_GET)]; +} _PACKED4_ blob_block_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_BLOCK_START)]; + uint16_t block_num; + uint16_t chunk_size; +} _PACKED4_ blob_block_start_t; + +enum +{ + BLOB_CHUNK_MISSING_FORMAT_ALL, + BLOB_CHUNK_MISSING_FORMAT_NONE, + BLOB_CHUNK_MISSING_FORMAT_SOME, + BLOB_CHUNK_MISSING_FORMAT_ENCODED, +} _SHORT_ENUM_; +typedef uint8_t blob_chunk_missing_format_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_BLOCK_STATUS)]; + uint8_t status : 4; + uint8_t rfu : 2; + uint8_t format : 2; + uint16_t block_num; + uint16_t chunk_size; + uint8_t missing_chunks[0]; +} _PACKED4_ blob_block_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_PARTIAL_BLOCK_REPORT)]; + uint8_t encoded_missing_chunks[0]; +} _PACKED4_ blob_partial_block_report_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_CHUNK_TRANSFER)]; + uint16_t chunk_num; + uint8_t data[0]; //!< variable length +} _PACKED4_ blob_chunk_transfer_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_INFO_GET)]; +} _PACKED4_ blob_info_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BLOB_INFO_STATUS)]; + uint8_t min_block_size_log; + uint8_t max_block_size_log; + uint16_t max_total_chunks; + uint16_t max_chunk_size; + uint32_t max_blob_size; + uint16_t server_mtu_size; + uint8_t supported_transfer_mode; +} _PACKED4_ blob_info_status_t; +/** @} */ + +#define BLOB_BLOCK_NUM_NOT_SET 0xFFFF +#define BLOB_CHUNK_SIZE_NOT_SET 0xFFFF + +/** + * @defgroup BLOB_TRANSFER_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +typedef struct +{ + uint8_t min_block_size_log; + uint8_t max_block_size_log; + uint16_t max_total_chunks; + uint16_t max_chunk_size; + uint32_t max_blob_size; //!< supported max size + uint16_t server_mtu_size; + uint8_t mode_pull_support : 1; + uint8_t mode_push_support : 1; + uint8_t mode_support_rfu : 6; +} blob_server_capabilites_t; + +typedef struct +{ + blob_server_capabilites_t caps; + + blob_transfer_mode_t mode; + blob_transfer_phase_t phase; + uint8_t blob_id[8]; + uint32_t blob_size; + uint32_t block_size; + uint16_t client_mtu_size; + uint16_t transfer_mtu_size; + uint16_t transfer_timeout_base; + uint8_t transfer_ttl; + + uint8_t *block_data; + uint8_t *blocks_not_recv; + uint16_t blocks_not_recv_len; + uint16_t current_block_num; + uint32_t current_block_size; + uint16_t total_blocks; + + uint16_t current_chunk_size; //!< maybe different in different blocks + uint16_t current_total_chunks; + uint8_t *missing_chunks; + uint8_t current_missing_chunks_len; //!< in bytes + + /* pull mode */ + uint16_t updater_addr; + uint16_t updater_app_key_index; + + plt_timer_t transfer_timer; + plt_timer_t partial_report_timer; + uint8_t partial_report_retry_times; + uint32_t partial_report_timeout_time; + uint8_t partial_report_max_retry_times; +} blob_transfer_server_ctx_t; + +extern blob_transfer_server_ctx_t blob_transfer_server_ctx; + +#define BLOB_TRANSFER_SERVER_BLOCK_DATA 0 //!< @ref blob_transfer_server_block_data_t +#define BLOB_TRANSFER_SERVER_COMPLETE 1 //!< @ref blob_transfer_server_complete_t +#define BLOB_TRANSFER_SERVER_SUSPEND 2 //!< @ref blob_transfer_server_suspend_t +#define BLOB_TRANSFER_SERVER_CANCEL 3 //!< @ref blob_transfer_server_cancel_t +#define BLOB_TRANSFER_SERVER_FAIL 4 //!< @ref blob_transfer_server_fail_t + + +typedef struct +{ + uint16_t block_num; + uint8_t *pdata; + uint16_t data_len; +} blob_transfer_server_block_data_t; + +typedef struct +{ + uint8_t blob_id[8]; +} blob_transfer_server_complete_t; + +typedef struct +{ + uint8_t blob_id[8]; +} blob_transfer_server_suspend_t; + +typedef struct +{ + uint8_t blob_id[8]; +} blob_transfer_server_cancel_t; + +typedef struct +{ + blob_transfer_status_code_t status; + uint8_t blob_id[8]; +} blob_transfer_server_fail_t; +/** @} */ + +/** + * @defgroup BLOB_TRANSFER_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define BLOB_TRANSFER_CLIENT_TRANSFER_STATUS 0 //!< @ref blob_transfer_client_transfer_status_t +#define BLOB_TRANSFER_CLIENT_BLOCK_STATUS 1 //!< @ref blob_transfer_client_block_status_t +#define BLOB_TRANSFER_CLIENT_PARTIAL_BLOCK_REPORT 2 //!< @ref blob_transfer_client_partial_block_report_t +#define BLOB_TRANSFER_CLIENT_INFO_STATUS 3 //!< @ref blob_transfer_client_info_status_t + +typedef struct +{ + uint16_t src; + uint16_t app_key_index; + blob_transfer_status_code_t status; + blob_transfer_mode_t transfer_mode; + blob_transfer_phase_t transfer_phase; + uint8_t blob_id[8]; + uint32_t blob_size; + uint8_t block_size_log; + uint16_t transfer_mtu_size; + uint16_t *pmissing_blocks; + uint16_t missing_blocks_len; +} blob_transfer_client_transfer_status_t; + +typedef struct +{ + uint16_t src; + uint16_t app_key_index; + blob_transfer_status_code_t status; + uint16_t block_num; + uint16_t chunk_size; + blob_chunk_missing_format_t missing_format; + uint16_t *pmissing_chunks; + uint16_t missing_chunks_len; +} blob_transfer_client_block_status_t; + +typedef struct +{ + uint16_t src; + uint16_t app_key_index; + uint16_t *pmissing_chunks; + uint16_t missing_chunks_len; +} blob_transfer_client_partial_block_report_t; + +typedef struct +{ + uint16_t src; + uint16_t app_key_index; + uint8_t min_block_size_log; + uint8_t max_block_size_log; + uint16_t max_total_chunks; + uint16_t max_chunk_size; + uint32_t max_blob_size; + uint16_t server_mtu_size; + uint8_t supported_transfer_mode; +} blob_transfer_client_info_status_t; +/** @} */ + +/** + * @defgroup BLOB_TRANSFER_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief blob transfer server register + * @param[in] element_index: element index + * @param[in] model_data_cb: model data callback function + * @return register status + */ +bool blob_transfer_server_reg(uint8_t element_index, model_data_cb_pf model_data_cb); + +/** + * @brief set blob transfer server model data callback function + * @param[in] model_data_cb: model data callback function + */ +void blob_transfer_server_set_data_cb(model_data_cb_pf model_data_cb); + +/** + * @brief set blob transfer server capabilites + * @param[in] pcaps: server capabilites + */ +void blob_transfer_server_caps_set(blob_server_capabilites_t *pcaps); + +/** + * @brief get blob transfer server capabilites + * @return server capabilites + */ +blob_server_capabilites_t blob_transfer_server_caps_get(void); + +/** + * @brief initialize blob transfer server + * @param[in] blob_id: blob id + * @param[in] transfer_timeout: transfer timeout time + * @param[in] transfer_ttl: transfer ttl value + * @return initialize status + */ +bool blob_transfer_server_init(uint8_t blob_id[8], uint16_t transfer_timeout, uint8_t transfer_ttl); + +/** + * @brief load blob transfer procedure + * @param[in] blob_size: blob size + * @param[in] block_size: block size + * @param[in] start_block_num: start block number + * @param[in] transfer_mode: transfer mode + * @param[in] transfer_mtu_size: transfer mtu size + * @param[in] updater_addr: updater address + * @param[in] updater_app_key_index: updater app key index + * @return load status + */ +bool blob_transfer_server_load(uint32_t blob_size, uint32_t block_size, uint16_t start_block_num, + blob_transfer_mode_t transfer_mode, uint16_t transfer_mtu_size, uint16_t updater_addr, + uint16_t updater_app_key_index); + +/** + * @brief clear blob transfer server + */ +void blob_transfer_server_clear(void); + +/** + * @brief get blob transfer server phase + * @return blob transfer server phase + */ +blob_transfer_phase_t blob_transfer_server_phase_get(void); + +/** + * @brief check whether blob transfer server is busy or not + * @return TRUE: busy + * FALSE: idle + */ +bool blob_transfer_server_busy(void); + +/** + * @brief handle blob transfer server timeout + */ +void blob_transfer_handle_transfer_timeout(void); + +/** + * @brief handle blob transfer partial report timeout + */ +void blob_transfer_handle_partial_report_timeout(void); + +/** + * @brief send blob transfer status + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] status: blob transfer status + * @param[in] delay_time: message delay time + * @return send status + */ +mesh_msg_send_cause_t blob_transfer_status(uint16_t dst, uint16_t app_key_index, + blob_transfer_status_code_t status, uint32_t delay_time); + +/** + * @brief send blob block status + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] status: blob transfer status + * @param[in] delay_time: message delay time + * @return send status + */ +mesh_msg_send_cause_t blob_block_status(uint16_t dst, uint16_t app_key_index, + blob_transfer_status_code_t status, uint32_t delay_time); + +/** + * @brief send blob partial block report + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t blob_partial_block_report(uint16_t dst, uint16_t app_key_index); + +/** + * @brief send blob information status + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] delay_time: message delay time + * @return send status + */ +mesh_msg_send_cause_t blob_info_status(uint16_t dst, uint16_t app_key_index, uint32_t delay_time); +/** @} */ + +/** + * @defgroup BLOB_TRANSFER_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief blob transfer client register + * @param[in] element_index: element index + * @param[in] model_data_cb: model data callback function + * @return register status + */ +void blob_transfer_client_reg(uint8_t element_index, model_data_cb_pf model_data_cb); + +/** + * @brief get blob transfer + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t blob_transfer_get(uint16_t dst, uint16_t app_key_index); + +/** + * @brief blob transfer start + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] mode: blob transfer mode + * @param[in] blob_id: blob id value + * @param[in] blob_size: blob size value + * @param[in] block_size_log: block size log value + * @param[in] client_mtu_size: client mtu size + * @return send status + */ +mesh_msg_send_cause_t blob_transfer_start(uint16_t dst, uint16_t app_key_index, + blob_transfer_mode_t mode, uint8_t blob_id[8], uint32_t blob_size, uint8_t block_size_log, + uint16_t client_mtu_size); + +/** + * @brief cancel blob transfer + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] blob_id: blob id value + * @return send status + */ +mesh_msg_send_cause_t blob_transfer_cancel(uint16_t dst, uint16_t app_key_index, + uint8_t blob_id[8]); + +/** + * @brief get blob block status + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] blob_id: blob id value + * @return send status + */ +mesh_msg_send_cause_t blob_block_get(uint16_t dst, uint16_t app_key_index); + +/** + * @brief blob block transfer start + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] block_num: total block number + * @param[in] chunk_size: transfer chunk size + * @return send status + */ +mesh_msg_send_cause_t blob_block_start(uint16_t dst, uint16_t app_key_index, uint16_t block_num, + uint16_t chunk_size); + +/** + * @brief blob chunk transfer start + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] chunk_num: total chunk number + * @param[in] pdata: chunk data + * @param[in] len: chunk data length + * @return send status + */ +mesh_msg_send_cause_t blob_chunk_transfer(uint16_t dst, uint16_t app_key_index, uint16_t chunk_num, + uint8_t *pdata, uint16_t len); + +/** + * @brief get blob transfer information + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t blob_info_get(uint16_t dst, uint16_t app_key_index); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* MESH_BLOB */ + +#endif /* _BLOB_TRANSFER_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer_client.c new file mode 100644 index 00000000..b04fc975 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer_client.c @@ -0,0 +1,380 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file blob_transfer.c +* @brief Source file for blob transfer client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-5-21 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "mesh_api.h" +#include "blob_transfer.h" + +#if MESH_BLOB + +mesh_model_info_t blob_transfer_client; + +static mesh_msg_send_cause_t blob_transfer_client_send(uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = &blob_transfer_client; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t blob_transfer_get(uint16_t dst, uint16_t app_key_index) +{ + blob_transfer_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_BLOB_TRANSFER_GET); + return blob_transfer_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(blob_transfer_get_t)); +} + +mesh_msg_send_cause_t blob_transfer_start(uint16_t dst, uint16_t app_key_index, + blob_transfer_mode_t mode, uint8_t blob_id[8], uint32_t blob_size, uint8_t block_size_log, + uint16_t client_mtu_size) +{ + blob_transfer_start_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_BLOB_TRANSFER_START); + msg.rfu = 0; + msg.transfer_mode = mode; + memcpy(msg.blob_id, blob_id, 8); + msg.blob_size = blob_size; + msg.block_size_log = block_size_log; + msg.client_mtu_size = client_mtu_size; + return blob_transfer_client_send(dst, app_key_index, (uint8_t *)&msg, + sizeof(blob_transfer_start_t)); +} + +mesh_msg_send_cause_t blob_transfer_cancel(uint16_t dst, uint16_t app_key_index, uint8_t blob_id[8]) +{ + blob_transfer_cancel_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_BLOB_TRANSFER_CANCEL); + memcpy(msg.blob_id, blob_id, sizeof(msg.blob_id)); + return blob_transfer_client_send(dst, app_key_index, (uint8_t *)&msg, + sizeof(blob_transfer_cancel_t)); +} + +mesh_msg_send_cause_t blob_block_get(uint16_t dst, uint16_t app_key_index) +{ + blob_block_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_BLOB_BLOCK_GET); + return blob_transfer_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(blob_block_get_t)); +} + +mesh_msg_send_cause_t blob_block_start(uint16_t dst, uint16_t app_key_index, uint16_t block_num, + uint16_t chunk_size) +{ + blob_block_start_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_BLOB_BLOCK_START); + msg.block_num = block_num; + msg.chunk_size = chunk_size; + return blob_transfer_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(blob_block_start_t)); +} + +mesh_msg_send_cause_t blob_chunk_transfer(uint16_t dst, uint16_t app_key_index, uint16_t chunk_num, + uint8_t *pdata, uint16_t len) +{ + mesh_msg_send_cause_t ret; + blob_chunk_transfer_t *pmsg = (blob_chunk_transfer_t *)plt_malloc(sizeof( + blob_chunk_transfer_t) + len, RAM_TYPE_DATA_ON); + if (pmsg == NULL) + { + printe("blob_chunk_transfer: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_BLOB_CHUNK_TRANSFER); + pmsg->chunk_num = chunk_num; + memcpy(pmsg->data, pdata, len); + ret = blob_transfer_client_send(dst, app_key_index, (uint8_t *)pmsg, + sizeof(blob_chunk_transfer_t) + len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t blob_info_get(uint16_t dst, uint16_t app_key_index) +{ + blob_info_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_BLOB_INFO_GET); + return blob_transfer_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(blob_info_get_t)); +} + +static uint16_t utf8_to_num(uint8_t *putf8, uint8_t *len) +{ + uint16_t data = 0; + if (*putf8 >= 0xc0) + { + data = putf8[0] - 0xc0; + data <<= 6; + data += (putf8[1] - 0x80); + *len = 2; + } + else + { + data = putf8[0]; + *len = 1; + } + + return data; +} + +bool blob_transfer_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_BLOB_TRANSFER_STATUS: + { + blob_transfer_status_t *pmsg = (blob_transfer_status_t *)pbuffer; + blob_transfer_client_transfer_status_t status_data; + memset(&status_data, 0, sizeof(blob_transfer_client_transfer_status_t)); + status_data.src = pmesh_msg->src; + status_data.app_key_index = pmesh_msg->app_key_index; + status_data.status = pmsg->status; + status_data.transfer_mode = pmsg->transfer_mode; + status_data.transfer_phase = pmsg->transfer_phase; + uint16_t *pmissing_blocks = NULL; + uint16_t missing_blocks_len = 0; + + if (pmesh_msg->msg_len == MEMBER_OFFSET(blob_transfer_status_t, blob_id)) + { + data_uart_debug("receive blob transfer status: status %d, mode %d, phase %d\r\n", + pmsg->status, pmsg->transfer_mode, pmsg->transfer_phase); + } + else if (pmesh_msg->msg_len == MEMBER_OFFSET(blob_transfer_status_t, blob_size)) + { + memcpy(status_data.blob_id, pmsg->blob_id, 8); + data_uart_debug("receive blob transfer status: status %d, mode %d, phase %d, blob_id \r\n", + pmsg->status, pmsg->transfer_mode, pmsg->transfer_phase); + data_uart_dump(pmsg->blob_id, 8); + } + else + { + memcpy(status_data.blob_id, pmsg->blob_id, 8); + status_data.blob_size = pmsg->blob_size; + status_data.block_size_log = pmsg->block_size_log; + status_data.transfer_mtu_size = pmsg->transfer_mtu_size; + + data_uart_debug("receive blob transfer status: status %d, mode %d, phase %d, blob_size %d, block_size_log %d, transfer_mtu_size %d, blob_id \r\n", + pmsg->status, pmsg->transfer_mode, pmsg->transfer_phase, pmsg->blob_size, pmsg->block_size_log, + pmsg->transfer_mtu_size); + data_uart_dump(pmsg->blob_id, 8); + if (pmesh_msg->msg_len > sizeof(blob_transfer_status_t)) + { + uint16_t data_len = pmesh_msg->msg_len - sizeof(blob_transfer_status_t); + uint8_t *pdata = pmsg->blocks_not_received; + pmissing_blocks = plt_malloc(data_len * 8 * 2, RAM_TYPE_DATA_ON); + uint16_t *pbuffer = pmissing_blocks; + if (NULL == pmissing_blocks) + { + printe("receive blob transfer status: out of memory!"); + return true; + } + for (uint16_t i = 0; i < data_len * 8; ++i) + { + if (plt_bit_pool_get(pdata, i)) + { + *pbuffer ++ = i; + missing_blocks_len ++; + } + } + data_uart_debug("blocks_not_received = "); + data_uart_dump((uint8_t *)pmissing_blocks, missing_blocks_len * 2); + } + } + + if (NULL != blob_transfer_client.model_data_cb) + { + status_data.pmissing_blocks = pmissing_blocks; + status_data.missing_blocks_len = missing_blocks_len; + blob_transfer_client.model_data_cb(&blob_transfer_client, BLOB_TRANSFER_CLIENT_TRANSFER_STATUS, + &status_data); + } + + if (NULL != pmissing_blocks) + { + plt_free(pmissing_blocks, RAM_TYPE_DATA_ON); + } + } + break; + case MESH_MSG_BLOB_BLOCK_STATUS: + { + blob_block_status_t *pmsg = (blob_block_status_t *)pbuffer; + data_uart_debug("receive blob block status: status %d, format %d, block_num %d, chunk_size %d", + pmsg->status, pmsg->format, pmsg->block_num, pmsg->chunk_size); + uint16_t *pmissing_chunks = NULL; + uint16_t missing_chunks_len = 0; + uint16_t data_len = pmesh_msg->msg_len - sizeof(blob_block_status_t); + uint8_t *pdata = pmsg->missing_chunks; + if (pmsg->format == BLOB_CHUNK_MISSING_FORMAT_ENCODED) + { + data_uart_debug(" ,missing_chunks = "); + uint8_t convert_len; + uint16_t *pmissing_chunks = NULL; + uint16_t missing_chunks_len = 0; + if (data_len > 0) + { + pmissing_chunks = plt_malloc(data_len * 2, RAM_TYPE_DATA_ON); + uint16_t *pbuffer = pmissing_chunks; + if (NULL == pmissing_chunks) + { + printe("receive partial block report: out of memory!"); + return true; + } + + while ((pdata - pmsg->missing_chunks) < data_len) + { + *pbuffer ++ = utf8_to_num(pdata, &convert_len); + pdata += convert_len; + missing_chunks_len ++; + } + data_uart_dump((uint8_t *)pmissing_chunks, missing_chunks_len * 2); + } + } + else if (pmsg->format == BLOB_CHUNK_MISSING_FORMAT_SOME) + { + data_uart_debug(" ,missing_chunks = "); + if (data_len > 0) + { + pmissing_chunks = plt_malloc(data_len * 8 * 2, RAM_TYPE_DATA_ON); + if (NULL == pmissing_chunks) + { + printe("receive partial block report: out of memory!"); + return true; + } + uint16_t *pbuffer = pmissing_chunks; + for (uint16_t i = 0; i < data_len * 8; ++i) + { + if (plt_bit_pool_get(pdata, i)) + { + *pbuffer ++ = i; + missing_chunks_len ++; + } + } + data_uart_dump((uint8_t *)pmissing_chunks, missing_chunks_len * 2); + } + } + data_uart_debug("\r\n"); + + if (NULL != blob_transfer_client.model_data_cb) + { + blob_transfer_client_block_status_t block_data; + block_data.src = pmesh_msg->src; + block_data.app_key_index = pmesh_msg->app_key_index; + block_data.status = pmsg->status; + block_data.block_num = pmsg->block_num; + block_data.missing_format = pmsg->format; + if (BLOB_CHUNK_MISSING_FORMAT_ENCODED == pmsg->format) + { + block_data.missing_format = BLOB_CHUNK_MISSING_FORMAT_SOME; + } + block_data.pmissing_chunks = pmissing_chunks; + block_data.missing_chunks_len = missing_chunks_len; + blob_transfer_client.model_data_cb(&blob_transfer_client, BLOB_TRANSFER_CLIENT_BLOCK_STATUS, + &block_data); + } + + if (NULL != pmissing_chunks) + { + plt_free(pmissing_chunks, RAM_TYPE_DATA_ON); + } + } + break; + case MESH_MSG_BLOB_PARTIAL_BLOCK_REPORT: + { + blob_partial_block_report_t *pmsg = (blob_partial_block_report_t *)pbuffer; + data_uart_debug("receive partial block report: encoded missing chunks = "); + uint8_t *pdata = pmsg->encoded_missing_chunks; + uint16_t data_len = pmesh_msg->msg_len - sizeof(blob_partial_block_report_t); + uint8_t convert_len; + uint16_t *pmissing_chunks = NULL; + uint16_t missing_chunks_len = 0; + if (data_len > 0) + { + pmissing_chunks = plt_malloc(data_len * 2, RAM_TYPE_DATA_ON); + uint16_t *pbuffer = pmissing_chunks; + if (NULL == pmissing_chunks) + { + printe("receive partial block report: out of memory!"); + return true; + } + + while ((pdata - pmsg->encoded_missing_chunks) < data_len) + { + *pbuffer ++ = utf8_to_num(pdata, &convert_len); + pdata += convert_len; + missing_chunks_len ++; + } + data_uart_dump((uint8_t *)pmissing_chunks, missing_chunks_len * 2); + } + data_uart_debug("\r\n"); + + if (NULL != blob_transfer_client.model_data_cb) + { + blob_transfer_client_partial_block_report_t report_data; + report_data.src = pmesh_msg->src; + report_data.app_key_index = pmesh_msg->app_key_index; + report_data.pmissing_chunks = pmissing_chunks; + report_data.missing_chunks_len = missing_chunks_len; + blob_transfer_client.model_data_cb(&blob_transfer_client, BLOB_TRANSFER_CLIENT_PARTIAL_BLOCK_REPORT, + &report_data); + } + + if (NULL != pmissing_chunks) + { + plt_free(pmissing_chunks, RAM_TYPE_DATA_ON); + } + } + break; + case MESH_MSG_BLOB_INFO_STATUS: + { + blob_info_status_t *pmsg = (blob_info_status_t *)pbuffer; + if (NULL != blob_transfer_client.model_data_cb) + { + blob_transfer_client_info_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.app_key_index = pmesh_msg->app_key_index; + status_data.min_block_size_log = pmsg->min_block_size_log; + status_data.max_block_size_log = pmsg->max_block_size_log; + status_data.max_total_chunks = pmsg->max_total_chunks; + status_data.max_chunk_size = pmsg->max_chunk_size; + status_data.max_blob_size = pmsg->max_blob_size; + status_data.server_mtu_size = pmsg->server_mtu_size; + status_data.supported_transfer_mode = pmsg->supported_transfer_mode; + blob_transfer_client.model_data_cb(&blob_transfer_client, BLOB_TRANSFER_CLIENT_INFO_STATUS, + &status_data); + } + data_uart_debug("receive blob info status: min_block_size_log %d, max_block_size_log %d, max_total_chunks %d, max_chunk_size %d, max_blob_size %d, server_mtu_size %d, supported_transfer_mode %d\r\n", + pmsg->min_block_size_log, pmsg->max_block_size_log, pmsg->max_total_chunks, pmsg->max_chunk_size, + pmsg->max_blob_size, pmsg->server_mtu_size, pmsg->supported_transfer_mode); + } + break; + default: + ret = false; + break; + } + + return ret; +} + +void blob_transfer_client_reg(uint8_t element_index, model_data_cb_pf model_data_cb) +{ + blob_transfer_client.model_id = MESH_MODEL_BLOB_TRANSFER_CLIENT; + blob_transfer_client.model_receive = blob_transfer_client_receive; + blob_transfer_client.model_data_cb = model_data_cb; + mesh_model_reg(element_index, &blob_transfer_client); +} + +#endif /* MESH_BLOB */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration.h new file mode 100644 index 00000000..c895e940 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration.h @@ -0,0 +1,777 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file configuration.h +* @brief Head file for configuration models. +* @details Data types and external functions declaration. +* @author bill +* @date 2016-3-24 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _CONFIGURATION_H +#define _CONFIGURATION_H + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup CONFIGURATION + * @{ + */ + +/** + * @defgroup CONFIGURATION_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_CFG_APP_KEY_ADD 0x00 +#define MESH_MSG_CFG_APP_KEY_UPDATE 0x01 +#define MESH_MSG_CFG_APP_KEY_DELETE 0x8000 +#define MESH_MSG_CFG_APP_KEY_GET 0x8001 +#define MESH_MSG_CFG_APP_KEY_LIST 0x8002 +#define MESH_MSG_CFG_APP_KEY_STAT 0x8003 +#define MESH_MSG_CFG_COMPO_DATA_GET 0x8008 +#define MESH_MSG_CFG_COMPO_DATA_STAT 0x02 +#define MESH_MSG_CFG_BEACON_GET 0x8009 +#define MESH_MSG_CFG_BEACON_SET 0x800A +#define MESH_MSG_CFG_BEACON_STAT 0x800B +#define MESH_MSG_CFG_DEFAULT_TTL_GET 0x800C +#define MESH_MSG_CFG_DEFAULT_TTL_SET 0x800D +#define MESH_MSG_CFG_DEFAULT_TTL_STAT 0x800E +#define MESH_MSG_CFG_FRND_GET 0x800F +#define MESH_MSG_CFG_FRND_SET 0x8010 +#define MESH_MSG_CFG_FRND_STAT 0x8011 +#define MESH_MSG_CFG_PROXY_GET 0x8012 +#define MESH_MSG_CFG_PROXY_SET 0x8013 +#define MESH_MSG_CFG_PROXY_STAT 0x8014 +#define MESH_MSG_CFG_KEY_REFRESH_PHASE_GET 0x8015 +#define MESH_MSG_CFG_KEY_REFRESH_PHASE_SET 0x8016 +#define MESH_MSG_CFG_KEY_REFRESH_PHASE_STAT 0x8017 +#define MESH_MSG_CFG_MODEL_PUB_GET 0x8018 +#define MESH_MSG_CFG_MODEL_PUB_SET 0x03 +#define MESH_MSG_CFG_MODEL_PUB_STAT 0x8019 +#define MESH_MSG_CFG_MODEL_PUB_VA_SET 0x801A +#define MESH_MSG_CFG_MODEL_SUB_ADD 0x801B +#define MESH_MSG_CFG_MODEL_SUB_DELETE 0x801C +#define MESH_MSG_CFG_MODEL_SUB_DELETE_ALL 0x801D +#define MESH_MSG_CFG_MODEL_SUB_OVERWRITE 0x801E +#define MESH_MSG_CFG_MODEL_SUB_STAT 0x801F +#define MESH_MSG_CFG_MODEL_SUB_VA_ADD 0x8020 +#define MESH_MSG_CFG_MODEL_SUB_VA_DELETE 0x8021 +#define MESH_MSG_CFG_MODEL_SUB_VA_OVERWRITE 0x8022 +#define MESH_MSG_CFG_NET_TRANS_GET 0x8023 +#define MESH_MSG_CFG_NET_TRANS_SET 0x8024 +#define MESH_MSG_CFG_NET_TRANS_STAT 0x8025 +#define MESH_MSG_CFG_RELAY_GET 0x8026 +#define MESH_MSG_CFG_RELAY_SET 0x8027 +#define MESH_MSG_CFG_RELAY_STAT 0x8028 +#define MESH_MSG_CFG_SIG_MODEL_SUB_GET 0x8029 +#define MESH_MSG_CFG_SIG_MODEL_SUB_LIST 0x802A +#define MESH_MSG_CFG_VENDOR_MODEL_SUB_GET 0x802B +#define MESH_MSG_CFG_VENDOR_MODEL_SUB_LIST 0x802C +#define MESH_MSG_CFG_LPN_POLL_TO_GET 0x802D +#define MESH_MSG_CFG_LPN_POLL_TO_STAT 0x802E +#define MESH_MSG_CFG_HB_PUB_GET 0x8038 +#define MESH_MSG_CFG_HB_PUB_SET 0x8039 +#define MESH_MSG_CFG_HB_PUB_STAT 0x06 +#define MESH_MSG_CFG_HB_SUB_GET 0x803A +#define MESH_MSG_CFG_HB_SUB_SET 0x803B +#define MESH_MSG_CFG_HB_SUB_STAT 0x803C +#define MESH_MSG_CFG_MODEL_APP_BIND 0x803D +#define MESH_MSG_CFG_MODEL_APP_STAT 0x803E +#define MESH_MSG_CFG_MODEL_APP_UNBIND 0x803F +#define MESH_MSG_CFG_NET_KEY_ADD 0x8040 +#define MESH_MSG_CFG_NET_KEY_DELETE 0x8041 +#define MESH_MSG_CFG_NET_KEY_GET 0x8042 +#define MESH_MSG_CFG_NET_KEY_LIST 0x8043 +#define MESH_MSG_CFG_NET_KEY_STAT 0x8044 +#define MESH_MSG_CFG_NET_KEY_UPDATE 0x8045 +#define MESH_MSG_CFG_NODE_IDENTITY_GET 0x8046 +#define MESH_MSG_CFG_NODE_IDENTITY_SET 0x8047 +#define MESH_MSG_CFG_NODE_IDENTITY_STAT 0x8048 +#define MESH_MSG_CFG_NODE_RESET 0x8049 +#define MESH_MSG_CFG_NODE_RESET_STAT 0x804A +#define MESH_MSG_CFG_SIG_MODEL_APP_GET 0x804B +#define MESH_MSG_CFG_SIG_MODEL_APP_LIST 0x804C +#define MESH_MSG_CFG_VENDOR_MODEL_APP_GET 0x804D +#define MESH_MSG_CFG_VENDOR_MODEL_APP_LIST 0x804E +/** @} */ + +/** + * @defgroup CONFIGURATION_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_CFG_SERVER 0x0000FFFF +#define MESH_MODEL_CFG_CLIENT 0x0001FFFF +/** @} */ + +/** + * @defgroup CONFIGURATION_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ + +/** @brief message status */ +enum +{ + MESH_MSG_STAT_SUCCESS, + MESH_MSG_STAT_INVALID_ADDR, + MESH_MSG_STAT_INVALID_MODEL, + MESH_MSG_STAT_INVALID_APP_KEY_INDEX, + MESH_MSG_STAT_INVALID_NET_KEY_INDEX, + MESH_MSG_STAT_INSUFFICIENT_RESOURCES, + MESH_MSG_STAT_KEY_INDEX_ALREADY_STORED, + MESH_MSG_STAT_INVALID_PUB_PARAMS, + MESH_MSG_STAT_NOT_SUB_MODEL, //8, TODO: What is not a sub model? + MESH_MSG_STAT_STORAGE_FAIL, + MESH_MSG_STAT_FEATURE_NOT_SUPPORTED, + MESH_MSG_STAT_CANNOT_UPDATE, + MESH_MSG_STAT_CANNOT_REMOVE, + MESH_MSG_STAT_CANNOT_BIND, + MESH_MSG_STAT_TEMP_UNABLE_CHANGE_STATE, + MESH_MSG_STAT_CANNOT_SET, + MESH_MSG_STAT_UNSPECIFIED_ERROR, //16 + MESH_MSG_STAT_INVALID_BINDING, +} _SHORT_ENUM_; +typedef uint8_t mesh_msg_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_BEACON_GET)]; +} _PACKED4_ cfg_beacon_get_t, *cfg_beacon_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_BEACON_SET)]; + uint8_t state; +} _PACKED4_ cfg_beacon_set_t, *cfg_beacon_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_BEACON_STAT)]; + uint8_t state; +} _PACKED4_ cfg_beacon_stat_t, *cfg_beacon_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_COMPO_DATA_GET)]; + uint8_t page; +} _PACKED4_ cfg_compo_data_get_t, *cfg_compo_data_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_COMPO_DATA_STAT)]; + uint8_t page; + uint8_t data[2]; //!< variable length +} _PACKED4_ cfg_compo_data_stat_t, *cfg_compo_data_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_DEFAULT_TTL_GET)]; +} _PACKED4_ cfg_default_ttl_get_t, *cfg_default_ttl_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_DEFAULT_TTL_SET)]; + uint8_t ttl; +} _PACKED4_ cfg_default_ttl_set_t, *cfg_default_ttl_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_DEFAULT_TTL_STAT)]; + uint8_t ttl; +} _PACKED4_ cfg_default_ttl_stat_t, *cfg_default_ttl_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_PROXY_GET)]; +} _PACKED4_ cfg_proxy_get_t, *cfg_proxy_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_PROXY_SET)]; + uint8_t state; +} _PACKED4_ cfg_proxy_set_t, *cfg_proxy_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_PROXY_STAT)]; + uint8_t state; +} _PACKED4_ cfg_proxy_stat_t, *cfg_proxy_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_RELAY_GET)]; +} _PACKED4_ cfg_relay_get_t, *cfg_relay_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_RELAY_SET)]; + uint8_t state; + uint8_t count : 3; + uint8_t steps : 5; +} _PACKED4_ cfg_relay_set_t, *cfg_relay_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_RELAY_STAT)]; + uint8_t state; + uint8_t count : 3; + uint8_t steps : 5; +} _PACKED4_ cfg_relay_stat_t, *cfg_relay_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_TRANS_GET)]; + +} _PACKED4_ cfg_net_transmit_get_t, *cfg_net_transmit_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_TRANS_SET)]; + uint8_t count : 3; + uint8_t steps : 5; +} _PACKED4_ cfg_net_transmit_set_t, *cfg_net_transmit_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_TRANS_STAT)]; + uint8_t count : 3; + uint8_t steps : 5; +} _PACKED4_ cfg_net_transmit_stat_t, *cfg_net_transmit_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_PUB_GET)]; + uint16_t element_addr; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_pub_get_t, *cfg_model_pub_get_p; + +typedef struct +{ + uint16_t app_key_index: 12; //!< global index + uint16_t frnd_flag: 1; + uint16_t rfu: 3; +} _PACKED4_ pub_key_info_t, *pub_key_info_p; + +typedef struct +{ + uint8_t steps : 6; //!< 0x00 Publish Period is disabled + uint8_t resol : 2; //!< The resolution of the Number of Steps field +} _PACKED4_ pub_period_t; + +typedef struct +{ + uint8_t count : 3; + uint8_t steps : 5; +} _PACKED4_ pub_retrans_info_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_PUB_SET)]; + uint16_t element_addr; + uint16_t pub_addr; + pub_key_info_t pub_key_info; + uint8_t pub_ttl; + pub_period_t pub_period; + pub_retrans_info_t pub_retrans_info; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_pub_set_t, *cfg_model_pub_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_PUB_VA_SET)]; + uint16_t element_addr; + uint8_t pub_addr[16]; + pub_key_info_t pub_key_info; + uint8_t pub_ttl; + pub_period_t pub_period; + pub_retrans_info_t pub_retrans_info; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_pub_va_set_t, *cfg_model_pub_va_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_PUB_STAT)]; + mesh_msg_stat_t stat; + uint16_t element_addr; + uint16_t pub_addr; + pub_key_info_t pub_key_info; + uint8_t pub_ttl; + pub_period_t pub_period; + pub_retrans_info_t pub_retrans_info; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_pub_stat_t, *cfg_model_pub_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_SUB_ADD)]; + uint16_t element_addr; + uint16_t addr; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_add_t, *cfg_model_sub_add_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_SUB_VA_ADD)]; + uint16_t element_addr; + uint8_t addr[16]; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_va_add_t, *cfg_model_sub_va_add_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_SUB_DELETE_ALL)]; + uint16_t element_addr; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_delete_all_t, *cfg_model_sub_delete_all_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_SUB_VA_DELETE)]; + uint16_t element_addr; + uint8_t addr[16]; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_delete_t, *cfg_model_sub_delete_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_SUB_VA_OVERWRITE)]; + uint16_t element_addr; + uint8_t addr[16]; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_overwrite_t, *cfg_model_sub_overwrite_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_SUB_STAT)]; + mesh_msg_stat_t stat; + uint16_t element_addr; + uint16_t addr; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_stat_t, *cfg_model_sub_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_SIG_MODEL_SUB_GET)]; + uint16_t element_addr; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_sub_get_t, *cfg_model_sub_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_SIG_MODEL_SUB_LIST)]; + mesh_msg_stat_t stat; + uint16_t element_addr; + uint32_t model_id; //!< 2 bytes or 4 bytes + uint8_t data[2]; //!< variable length +} _PACKED4_ cfg_model_sub_list_t, *cfg_model_sub_list_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_KEY_ADD)]; + uint16_t net_key_index; + uint8_t net_key[16]; +} _PACKED4_ cfg_net_key_add_t, *cfg_net_key_add_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_KEY_UPDATE)]; + uint16_t net_key_index; + uint8_t net_key[16]; +} _PACKED4_ cfg_net_key_update_t, *cfg_net_key_update_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_KEY_DELETE)]; + uint16_t net_key_index; +} _PACKED4_ cfg_net_key_delete_t, *cfg_net_key_delete_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_KEY_STAT)]; + mesh_msg_stat_t stat; + uint16_t net_key_index; +} _PACKED4_ cfg_net_key_stat_t, *cfg_net_key_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_KEY_GET)]; +} _PACKED4_ cfg_net_key_get_t, *cfg_net_key_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NET_KEY_LIST)]; + uint8_t net_key_indexes[2]; //!< variable length +} _PACKED4_ cfg_net_key_list_t, *cfg_net_key_list_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_APP_KEY_ADD)]; + uint8_t key_index[3]; //!< NetKeyIndex, AppKeyIndex + uint8_t app_key[16]; +} _PACKED4_ cfg_app_key_add_t, *cfg_app_key_add_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_APP_KEY_UPDATE)]; + uint8_t key_index[3]; //!< NetKeyIndex, AppKeyIndex + uint8_t app_key[16]; +} _PACKED4_ cfg_app_key_update_t, *cfg_app_key_update_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_APP_KEY_DELETE)]; + uint8_t key_index[3]; //!< NetKeyIndex, AppKeyIndex +} _PACKED4_ cfg_app_key_delete_t, *cfg_app_key_delete_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_APP_KEY_STAT)]; + mesh_msg_stat_t stat; + uint8_t key_index[3]; //!< NetKeyIndex, AppKeyIndex +} _PACKED4_ cfg_app_key_stat_t, *cfg_app_key_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_APP_KEY_GET)]; + uint16_t net_key_index; +} _PACKED4_ cfg_app_key_get_t, *cfg_app_key_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_APP_KEY_LIST)]; + mesh_msg_stat_t stat; + uint16_t net_key_index; + uint8_t app_key_indexes[2]; //!< variable length +} _PACKED4_ cfg_app_key_list_t, *cfg_app_key_list_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NODE_IDENTITY_GET)]; + uint16_t net_key_index; +} _PACKED4_ cfg_node_identity_get_t, *cfg_node_identity_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NODE_IDENTITY_SET)]; + uint16_t net_key_index; + uint8_t identity; +} _PACKED4_ cfg_node_identity_set_t, *cfg_node_identity_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NODE_IDENTITY_STAT)]; + mesh_msg_stat_t stat; + uint16_t net_key_index; + uint8_t identity; +} _PACKED4_ cfg_node_identity_stat_t, *cfg_node_identity_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_APP_BIND)]; + uint16_t element_addr; + uint16_t app_key_index; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_app_bind_t, *cfg_model_app_bind_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_APP_UNBIND)]; + uint16_t element_addr; + uint16_t app_key_index; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_app_unbind_t, *cfg_model_app_unbind_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_APP_STAT)]; + mesh_msg_stat_t stat; + uint16_t element_addr; + uint16_t app_key_index; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_app_stat_t, *cfg_model_app_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_SIG_MODEL_APP_GET)]; + uint16_t element_addr; + uint32_t model_id; //!< 2 bytes or 4 bytes +} _PACKED4_ cfg_model_app_get_t, *cfg_model_app_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_SIG_MODEL_APP_LIST)]; + mesh_msg_stat_t stat; + uint16_t element_addr; + uint32_t model_id; //!< 2 bytes or 4 bytes + uint8_t app_key_indexes[3]; //!< variable length +} _PACKED4_ cfg_model_app_list_t, *cfg_model_app_list_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NODE_RESET)]; +} _PACKED4_ cfg_node_reset_t, *cfg_node_reset_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_NODE_RESET_STAT)]; +} _PACKED4_ cfg_node_reset_stat_t, *cfg_node_reset_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_FRND_GET)]; +} _PACKED4_ cfg_frnd_get_t, *cfg_frnd_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_FRND_SET)]; + uint8_t state; +} _PACKED4_ cfg_frnd_set_t, *cfg_frnd_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_FRND_STAT)]; + uint8_t state; +} _PACKED4_ cfg_frnd_stat_t, *cfg_frnd_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_LPN_POLL_TO_GET)]; + uint16_t lpn_addr; +} _PACKED4_ cfg_lpn_poll_timeout_get_t, *cfg_lpn_poll_timeout_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_LPN_POLL_TO_STAT)]; + uint16_t lpn_addr; + uint8_t poll_to[3]; +} _PACKED4_ cfg_lpn_poll_timeout_stat_t, *cfg_lpn_poll_timeout_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_KEY_REFRESH_PHASE_GET)]; + uint16_t net_key_index; +} _PACKED4_ cfg_key_refresh_phase_get_t, *cfg_key_refresh_phase_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_KEY_REFRESH_PHASE_SET)]; + uint16_t net_key_index; + uint8_t state; +} _PACKED4_ cfg_key_refresh_phase_set_t, *cfg_key_refresh_phase_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_KEY_REFRESH_PHASE_STAT)]; + mesh_msg_stat_t stat; + uint16_t net_key_index; + uint8_t state; +} _PACKED4_ cfg_key_refresh_phase_stat_t, *cfg_key_refresh_phase_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_HB_PUB_GET)]; +} _PACKED4_ cfg_hb_pub_get_t, *cfg_hb_pub_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_HB_PUB_SET)]; + uint16_t dst; + uint8_t count_log; + uint8_t period_log; + uint8_t ttl; + hb_pub_features_t features; + uint16_t net_key_index; +} _PACKED4_ cfg_hb_pub_set_t, *cfg_hb_pub_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_HB_PUB_STAT)]; + mesh_msg_stat_t stat; + uint16_t dst; + uint8_t count_log; + uint8_t period_log; + uint8_t ttl; + hb_pub_features_t features; + uint16_t net_key_index; +} _PACKED4_ cfg_hb_pub_stat_t, *cfg_hb_pub_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_HB_SUB_GET)]; +} _PACKED4_ cfg_hb_sub_get_t, *cfg_hb_sub_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_HB_SUB_SET)]; + uint16_t src; + uint16_t dst; + uint8_t period_log; +} _PACKED4_ cfg_hb_sub_set_t, *cfg_hb_sub_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_CFG_HB_SUB_STAT)]; + mesh_msg_stat_t stat; + uint16_t src; + uint16_t dst; + uint8_t period_log; + uint8_t count_log; + uint8_t min_hops; + uint8_t max_hops; +} _PACKED4_ cfg_hb_sub_stat_t, *cfg_hb_sub_stat_p; + +/** @} */ + +/** + * @defgroup CONFIGURATION_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register the configuration server. It is invoked by the stack itself. + * @return operation result + * @retval true: success + * @retval false: fail + */ +bool cfg_server_reg(void); + +/** + * @brief the receive callback of the configuration server model + * @param[in] pmesh_msg: the received mesh message + * @return operation result + * @retval true: the msg is processed by the configuration server model + * @retval false: the msg isn't processed by the configuration server model + */ +bool cfg_server_receive(mesh_msg_p pmesh_msg); + +/** + * @brief the cfg server may response all status msgs via segmented transport msgs + * to add the reliability of the response + * @param[in] seg: the seg flag value + * @return none + */ +void cfg_server_resp_with_seg_msg(bool seg); + +/** + * @brief the cfg server may response need to use seperated network transimit + * @param[in] count: retransimit count + * @param[in] steps: retransmit steps + * @return none + */ +void cfg_server_set_net_trans(uint8_t count, uint8_t steps); + +/* + * @brief The configuration server model is implemented in the mesh stack. + * But the application can still get the configuration message from the server + * by patch the model receive function. For example, the application can attain + * the source address of the configuration client. + * + * Example usage + * \code{.c} + bool cfg_server_receive_peek(mesh_msg_p pmesh_msg) + { + bool ret = cfg_server_receive(pmesh_msg); + if(ret) + { + // The configuration client message can be peeked now! + printi("cfg_server_receive_peek: cfg client addr = 0x%04x", pmesh_msg->src);} + } + return ret; + } + + void mesh_stack_init(void) + { + ... + mesh_element_create(GATT_NS_DESC_UNKNOWN); + cfg_server.model_receive = cfg_server_receive_peek; + ... + } + * \endcode + */ +typedef struct _mesh_model_info_t mesh_model_info_t; +extern mesh_model_info_t cfg_server; + +/** @} */ + +/** + * @defgroup CONFIGURATION_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ +bool cfg_client_reg(void); +bool cfg_client_key_set(uint16_t key_index); +mesh_msg_send_cause_t cfg_compo_data_get(uint16_t dst, uint8_t page); +mesh_msg_send_cause_t cfg_beacon_get(uint16_t dst); +mesh_msg_send_cause_t cfg_beacon_set(uint16_t dst, uint8_t state); +mesh_msg_send_cause_t cfg_default_ttl_get(uint16_t dst); +mesh_msg_send_cause_t cfg_default_ttl_set(uint16_t dst, uint8_t ttl); +mesh_msg_send_cause_t cfg_proxy_get(uint16_t dst); +mesh_msg_send_cause_t cfg_proxy_set(uint16_t dst, uint8_t state); +mesh_msg_send_cause_t cfg_relay_get(uint16_t dst); +mesh_msg_send_cause_t cfg_relay_set(uint16_t dst, uint8_t state, uint8_t count, uint8_t steps); +mesh_msg_send_cause_t cfg_net_transmit_get(uint16_t dst); +mesh_msg_send_cause_t cfg_net_transmit_set(uint16_t dst, uint8_t count, uint8_t steps); +mesh_msg_send_cause_t cfg_model_pub_get(uint16_t dst, uint16_t element_addr, uint32_t model_id); +mesh_msg_send_cause_t cfg_model_pub_set(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *pub_addr, pub_key_info_t pub_key_info, uint8_t pub_ttl, pub_period_t pub_period, + pub_retrans_info_t pub_retrans_info, uint32_t model_id); +mesh_msg_send_cause_t cfg_model_sub_add(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *addr, uint32_t model_id); +mesh_msg_send_cause_t cfg_model_sub_delete(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *addr, uint32_t model_id); +mesh_msg_send_cause_t cfg_model_sub_delete_all(uint16_t dst, uint16_t element_addr, + uint32_t model_id); +mesh_msg_send_cause_t cfg_model_sub_overwrite(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *addr, uint32_t model_id); +mesh_msg_send_cause_t cfg_model_sub_get(uint16_t dst, uint16_t element_addr, uint32_t model_id); +mesh_msg_send_cause_t cfg_net_key_add(uint16_t dst, uint16_t net_key_index, uint8_t net_key[16]); +mesh_msg_send_cause_t cfg_net_key_update(uint16_t dst, uint16_t net_key_index, uint8_t net_key[16]); +mesh_msg_send_cause_t cfg_net_key_delete(uint16_t dst, uint16_t net_key_index); +mesh_msg_send_cause_t cfg_net_key_get(uint16_t dst); +mesh_msg_send_cause_t cfg_app_key_add(uint16_t dst, uint16_t net_key_index, uint16_t app_key_index, + uint8_t app_key[16]); +mesh_msg_send_cause_t cfg_app_key_update(uint16_t dst, uint16_t net_key_index, + uint16_t app_key_index, uint8_t app_key[16]); +mesh_msg_send_cause_t cfg_app_key_delete(uint16_t dst, uint16_t net_key_index, + uint16_t app_key_index); +mesh_msg_send_cause_t cfg_app_key_get(uint16_t dst, uint16_t net_key_index); +mesh_msg_send_cause_t cfg_node_identity_get(uint16_t dst, uint16_t net_key_index); +mesh_msg_send_cause_t cfg_node_identity_set(uint16_t dst, uint16_t net_key_index, uint8_t identity); +mesh_msg_send_cause_t cfg_model_app_bind(uint16_t dst, uint16_t element_addr, + uint16_t app_key_index, + uint32_t model_id); +mesh_msg_send_cause_t cfg_model_app_unbind(uint16_t dst, uint16_t element_addr, + uint16_t app_key_index, + uint32_t model_id); +mesh_msg_send_cause_t cfg_model_app_get(uint16_t dst, uint16_t element_addr, uint32_t model_id); +mesh_msg_send_cause_t cfg_node_reset(uint16_t dst); +mesh_msg_send_cause_t cfg_frnd_get(uint16_t dst); +mesh_msg_send_cause_t cfg_frnd_set(uint16_t dst, uint8_t state); +mesh_msg_send_cause_t cfg_lpn_poll_timeout_get(uint16_t dst, uint16_t lpn_addr); +mesh_msg_send_cause_t cfg_key_refresh_phase_get(uint16_t dst, uint16_t net_key_index); +mesh_msg_send_cause_t cfg_key_refresh_phase_set(uint16_t dst, uint16_t net_key_index, + uint8_t state); +mesh_msg_send_cause_t cfg_hb_pub_get(uint16_t dst); +mesh_msg_send_cause_t cfg_hb_pub_set(uint16_t dst, uint16_t dst_pub, uint8_t count_log, + uint8_t period_log, + uint8_t ttl, + hb_pub_features_t features, uint16_t net_key_index); +mesh_msg_send_cause_t cfg_hb_sub_get(uint16_t dst); +mesh_msg_send_cause_t cfg_hb_sub_set(uint16_t dst, uint16_t src, uint16_t dst_set, + uint8_t period_log); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _CONFIGURATION_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration_client.c new file mode 100644 index 00000000..c2d34c2e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration_client.c @@ -0,0 +1,1142 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file configuration_client.c +* @brief Source file for configuration client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2016-3-24 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "provisioner_app.h" +#include "mesh_api.h" +#include "configuration.h" +#include "platform_opts.h" + +mesh_model_info_t cfg_client; +uint16_t cfg_client_key_index; //!< NetKey or AppKey depends on the mesh_node.features.cfg_model_use_app_key + +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO +#include "bt_mesh_app_lib_intf.h" +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; +#endif + +static mesh_msg_send_cause_t cfg_client_send(uint16_t dst, uint8_t *pmsg, uint16_t len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = &cfg_client; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = len; +#if MESH_CONFIGURATION_MODEL_USE_APP_KEY + if (mesh_node.features.cfg_model_use_app_key) + { + mesh_msg.app_key_index = cfg_client_key_index; + } + else +#endif + { + mesh_msg.akf = 0; + mesh_msg.net_key_index = cfg_client_key_index; + } + mesh_msg.dst = dst; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t cfg_compo_data_get(uint16_t dst, uint8_t page) +{ + cfg_compo_data_get_t msg; + msg.page = page; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_COMPO_DATA_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_beacon_get(uint16_t dst) +{ + cfg_beacon_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_BEACON_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_beacon_set(uint16_t dst, uint8_t state) +{ + cfg_beacon_set_t msg; + msg.state = state; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_BEACON_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_default_ttl_get(uint16_t dst) +{ + cfg_default_ttl_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_DEFAULT_TTL_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_default_ttl_set(uint16_t dst, uint8_t ttl) +{ + cfg_default_ttl_set_t msg; + msg.ttl = ttl; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_DEFAULT_TTL_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_proxy_get(uint16_t dst) +{ + cfg_proxy_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_PROXY_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_proxy_set(uint16_t dst, uint8_t state) +{ + cfg_proxy_set_t msg; + msg.state = state; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_PROXY_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_relay_get(uint16_t dst) +{ + cfg_relay_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_RELAY_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_relay_set(uint16_t dst, uint8_t state, uint8_t count, uint8_t steps) +{ + cfg_relay_set_t msg; + msg.state = state; + msg.count = count; + msg.steps = steps; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_RELAY_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_net_transmit_get(uint16_t dst) +{ + cfg_net_transmit_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NET_TRANS_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_net_transmit_set(uint16_t dst, uint8_t count, uint8_t steps) +{ + cfg_net_transmit_set_t msg; + msg.count = count; + msg.steps = steps; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NET_TRANS_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_model_pub_get(uint16_t dst, uint16_t element_addr, uint32_t model_id) +{ + cfg_model_pub_get_t msg; + msg.element_addr = element_addr; + msg.model_id = MESH_MODEL_CONVERT(model_id); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_MODEL_PUB_GET); + return cfg_client_send(dst, (uint8_t *)&msg, + sizeof(msg) - (MESH_IS_VENDOR_MODEL(model_id) ? 0 : 2)); +} + +mesh_msg_send_cause_t cfg_model_pub_set(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *pub_addr, pub_key_info_t pub_key_info, uint8_t pub_ttl, pub_period_t pub_period, + pub_retrans_info_t pub_retrans_info, uint32_t model_id) +{ + cfg_model_pub_va_set_t pub_set; + uint8_t *pbuffer = (uint8_t *)&pub_set; + uint8_t index; + if (va_flag) + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_PUB_VA_SET); + index = ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_PUB_VA_SET); + } + else + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_PUB_SET); + index = ACCESS_OPCODE_SIZE(MESH_MSG_CFG_MODEL_PUB_SET); + } + LE_WORD2EXTRN(pbuffer + index, element_addr); + index += 2; + memcpy(pbuffer + index, pub_addr, va_flag ? 16 : 2); + index += va_flag ? 16 : 2; + pub_key_info.rfu = 0; + /* to avoid gcc compile warning */ + pub_key_info_p temp = &pub_key_info; + LE_WORD2EXTRN(pbuffer + index, *(uint16_t *)temp); + pbuffer[index + 2] = pub_ttl; + pbuffer[index + 3] = *(uint8_t *)&pub_period; + pbuffer[index + 4] = *(uint8_t *)&pub_retrans_info; + index += 5; + if (MESH_IS_VENDOR_MODEL(model_id)) + { + LE_DWORD2EXTRN(pbuffer + index, model_id); + index += 4; + } + else + { + LE_WORD2EXTRN(pbuffer + index, model_id >> 16); + index += 2; + } + return cfg_client_send(dst, pbuffer, index); +} + +mesh_msg_send_cause_t cfg_model_sub_add(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *addr, uint32_t model_id) +{ + cfg_model_sub_va_add_t sub_add; + uint8_t *pbuffer = (uint8_t *)&sub_add; + if (va_flag) + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_SUB_VA_ADD); + } + else + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_SUB_ADD); + } + LE_WORD2EXTRN(pbuffer + 2, element_addr); + memcpy(pbuffer + 4, addr, va_flag ? 16 : 2); + uint8_t index = 4 + (va_flag ? 16 : 2); + if (MESH_IS_VENDOR_MODEL(model_id)) + { + LE_DWORD2EXTRN(pbuffer + index, model_id); + index += 4; + } + else + { + LE_WORD2EXTRN(pbuffer + index, model_id >> 16); + index += 2; + } + return cfg_client_send(dst, pbuffer, index); +} + +mesh_msg_send_cause_t cfg_model_sub_delete(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *addr, uint32_t model_id) +{ + cfg_model_sub_delete_t sub_delete; + uint8_t *pbuffer = (uint8_t *)&sub_delete; + if (va_flag) + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_SUB_VA_DELETE); + } + else + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_SUB_DELETE); + } + LE_WORD2EXTRN(pbuffer + 2, element_addr); + memcpy(pbuffer + 4, addr, va_flag ? 16 : 2); + uint8_t index = 4 + (va_flag ? 16 : 2); + if (MESH_IS_VENDOR_MODEL(model_id)) + { + LE_DWORD2EXTRN(pbuffer + index, model_id); + index += 4; + } + else + { + LE_WORD2EXTRN(pbuffer + index, model_id >> 16); + index += 2; + } + return cfg_client_send(dst, pbuffer, index); +} + +mesh_msg_send_cause_t cfg_model_sub_delete_all(uint16_t dst, uint16_t element_addr, + uint32_t model_id) +{ + cfg_model_sub_delete_all_t msg; + msg.element_addr = element_addr; + msg.model_id = MESH_MODEL_CONVERT(model_id); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_MODEL_SUB_DELETE_ALL); + return cfg_client_send(dst, (uint8_t *)&msg, + sizeof(msg) - (MESH_IS_VENDOR_MODEL(model_id) ? 0 : 2)); +} + +mesh_msg_send_cause_t cfg_model_sub_overwrite(uint16_t dst, uint16_t element_addr, bool va_flag, + uint8_t *addr, uint32_t model_id) +{ + cfg_model_sub_overwrite_t sub_overwrite; + uint8_t *pbuffer = (uint8_t *)&sub_overwrite; + if (va_flag) + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_SUB_VA_OVERWRITE); + } + else + { + ACCESS_OPCODE_BYTE(pbuffer, MESH_MSG_CFG_MODEL_SUB_OVERWRITE); + } + LE_WORD2EXTRN(pbuffer + 2, element_addr); + memcpy(pbuffer + 4, addr, va_flag ? 16 : 2); + uint8_t index = 4 + (va_flag ? 16 : 2); + if (MESH_IS_VENDOR_MODEL(model_id)) + { + LE_DWORD2EXTRN(pbuffer + index, model_id); + index += 4; + } + else + { + LE_WORD2EXTRN(pbuffer + index, model_id >> 16); + index += 2; + } + return cfg_client_send(dst, pbuffer, index); +} + +mesh_msg_send_cause_t cfg_model_sub_get(uint16_t dst, uint16_t element_addr, uint32_t model_id) +{ + cfg_model_sub_get_t msg; + if (MESH_IS_VENDOR_MODEL(model_id)) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_VENDOR_MODEL_SUB_GET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_SIG_MODEL_SUB_GET); + } + msg.element_addr = element_addr; + msg.model_id = MESH_MODEL_CONVERT(model_id); + return cfg_client_send(dst, (uint8_t *)&msg, + sizeof(msg) - (MESH_IS_VENDOR_MODEL(model_id) ? 0 : 2)); +} + +mesh_msg_send_cause_t cfg_net_key_add(uint16_t dst, uint16_t net_key_index, uint8_t net_key[16]) +{ + cfg_net_key_add_t msg; + msg.net_key_index = net_key_index; + memcpy(msg.net_key, net_key, 16); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NET_KEY_ADD); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_net_key_update(uint16_t dst, uint16_t net_key_index, uint8_t net_key[16]) +{ + cfg_net_key_update_t msg; + msg.net_key_index = net_key_index; + memcpy(msg.net_key, net_key, 16); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NET_KEY_UPDATE); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_net_key_delete(uint16_t dst, uint16_t net_key_index) +{ + cfg_net_key_delete_t msg; + msg.net_key_index = net_key_index; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NET_KEY_DELETE); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_net_key_get(uint16_t dst) +{ + cfg_net_key_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NET_KEY_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_app_key_add(uint16_t dst, uint16_t net_key_index, uint16_t app_key_index, + uint8_t app_key[16]) +{ + cfg_app_key_add_t msg; + msg.key_index[0] = net_key_index & 0xff; + msg.key_index[1] = ((net_key_index >> 8) & 0x0f) + ((app_key_index & 0x0f) << 4); + msg.key_index[2] = (app_key_index >> 4) & 0xff; + memcpy(msg.app_key, app_key, 16); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_APP_KEY_ADD); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_app_key_update(uint16_t dst, uint16_t net_key_index, + uint16_t app_key_index, uint8_t app_key[16]) +{ + cfg_app_key_update_t msg; + msg.key_index[0] = net_key_index & 0xff; + msg.key_index[1] = ((net_key_index >> 8) & 0x0f) + ((app_key_index & 0x0f) << 4); + msg.key_index[2] = (app_key_index >> 4) & 0xff; + memcpy(msg.app_key, app_key, 16); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_APP_KEY_UPDATE); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_app_key_delete(uint16_t dst, uint16_t net_key_index, + uint16_t app_key_index) +{ + cfg_app_key_delete_t msg; + msg.key_index[0] = net_key_index & 0xff; + msg.key_index[1] = ((net_key_index >> 8) & 0x0f) + ((app_key_index & 0x0f) << 4); + msg.key_index[2] = (app_key_index >> 4) & 0xff; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_APP_KEY_DELETE); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_app_key_get(uint16_t dst, uint16_t net_key_index) +{ + cfg_app_key_get_t msg; + msg.net_key_index = net_key_index; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_APP_KEY_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_node_identity_get(uint16_t dst, uint16_t net_key_index) +{ + cfg_node_identity_get_t msg; + msg.net_key_index = net_key_index; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NODE_IDENTITY_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_node_identity_set(uint16_t dst, uint16_t net_key_index, uint8_t identity) +{ + cfg_node_identity_set_t msg; + msg.net_key_index = net_key_index; + msg.identity = identity; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NODE_IDENTITY_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_model_app_bind(uint16_t dst, uint16_t element_addr, + uint16_t app_key_index, + uint32_t model_id) +{ + cfg_model_app_bind_t msg; + msg.element_addr = element_addr; + msg.app_key_index = app_key_index; + msg.model_id = MESH_MODEL_CONVERT(model_id); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_MODEL_APP_BIND); + return cfg_client_send(dst, (uint8_t *)&msg, + sizeof(msg) - (MESH_IS_VENDOR_MODEL(model_id) ? 0 : 2)); +} + +mesh_msg_send_cause_t cfg_model_app_unbind(uint16_t dst, uint16_t element_addr, + uint16_t app_key_index, + uint32_t model_id) +{ + cfg_model_app_unbind_t msg; + msg.element_addr = element_addr; + msg.app_key_index = app_key_index; + msg.model_id = MESH_MODEL_CONVERT(model_id); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_MODEL_APP_UNBIND); + return cfg_client_send(dst, (uint8_t *)&msg, + sizeof(msg) - (MESH_IS_VENDOR_MODEL(model_id) ? 0 : 2)); +} + +mesh_msg_send_cause_t cfg_model_app_get(uint16_t dst, uint16_t element_addr, uint32_t model_id) +{ + cfg_model_app_get_t msg; + if (MESH_IS_VENDOR_MODEL(model_id)) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_VENDOR_MODEL_APP_GET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_SIG_MODEL_APP_GET); + } + msg.element_addr = element_addr; + msg.model_id = MESH_MODEL_CONVERT(model_id); + return cfg_client_send(dst, (uint8_t *)&msg, + sizeof(msg) - (MESH_IS_VENDOR_MODEL(model_id) ? 0 : 2)); +} + +mesh_msg_send_cause_t cfg_node_reset(uint16_t dst) +{ + cfg_node_reset_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_NODE_RESET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_frnd_get(uint16_t dst) +{ + cfg_frnd_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_FRND_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_frnd_set(uint16_t dst, uint8_t state) +{ + cfg_frnd_set_t msg; + msg.state = state; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_FRND_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_lpn_poll_timeout_get(uint16_t dst, uint16_t lpn_addr) +{ + cfg_lpn_poll_timeout_get_t msg; + msg.lpn_addr = lpn_addr; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_LPN_POLL_TO_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_key_refresh_phase_get(uint16_t dst, uint16_t net_key_index) +{ + cfg_key_refresh_phase_get_t msg; + msg.net_key_index = net_key_index; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_KEY_REFRESH_PHASE_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_key_refresh_phase_set(uint16_t dst, uint16_t net_key_index, uint8_t state) +{ + cfg_key_refresh_phase_set_t msg; + msg.net_key_index = net_key_index; + msg.state = state; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_KEY_REFRESH_PHASE_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_hb_pub_get(uint16_t dst) +{ + cfg_hb_pub_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_HB_PUB_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_hb_pub_set(uint16_t dst, uint16_t dst_pub, uint8_t count_log, + uint8_t period_log, + uint8_t ttl, hb_pub_features_t features, uint16_t net_key_index) +{ + cfg_hb_pub_set_t msg; + msg.dst = dst_pub; + msg.count_log = count_log; + msg.period_log = period_log; + msg.ttl = ttl; + msg.features = features; + msg.net_key_index = net_key_index; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_HB_PUB_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_hb_sub_get(uint16_t dst) +{ + cfg_hb_sub_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_HB_SUB_GET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t cfg_hb_sub_set(uint16_t dst, uint16_t src, uint16_t dst_set, + uint8_t period_log) +{ + cfg_hb_sub_set_t msg; + msg.src = src; + msg.dst = dst_set; + msg.period_log = period_log; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_CFG_HB_SUB_SET); + return cfg_client_send(dst, (uint8_t *)&msg, sizeof(msg)); +} + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO +#include "bt_mesh_app_lib_intf.h" +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; +extern void update_node_group(uint16_t mesh_addr, uint16_t group_addr); +#endif + +bool cfg_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + bool parse = FALSE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_CFG_BEACON_STAT: + { + parse = TRUE; + cfg_beacon_stat_t *pmsg = (cfg_beacon_stat_t *)pbuffer; + data_uart_debug("beacon state: %d\r\n", pmsg->state); + } + break; + case MESH_MSG_CFG_COMPO_DATA_STAT: + { + cfg_compo_data_stat_t *pmsg = (cfg_compo_data_stat_t *)pbuffer; + if (pmsg->page == 0) + { + parse = TRUE; + uint8_t element_index = 0; + uint8_t *pdata = pmsg->data; + uint8_t *pend = pbuffer + pmesh_msg->msg_len; + if (pmesh_msg->msg_len < (MEMBER_OFFSET(cfg_compo_data_stat_t, data) + 10)) + { + goto compo_data_end; + } + data_uart_debug("cdp0 parsed: src=0x%04x cid=0x%04x pid=0x%04x vid=0x%04x rpl=%d features=0x%04x\r\n", + pmesh_msg->src, LE_EXTRN2WORD(pdata), LE_EXTRN2WORD(pdata + 2), + LE_EXTRN2WORD(pdata + 4), LE_EXTRN2WORD(pdata + 6), LE_EXTRN2WORD(pdata + 8)); + pdata += 10; + while (pdata < pend) + { + if (pend - pdata < 4) + { + goto compo_data_end; + } + uint8_t sig_model_num = pdata[2]; + uint8_t vendor_model_num = pdata[3]; + uint8_t model_num; + data_uart_debug("element %d: loc=%d sig=%d vendor=%d\r\n", element_index, LE_EXTRN2WORD(pdata), + sig_model_num, vendor_model_num); + pdata += 4; + if (sig_model_num) + { + if (pend - pdata < (sig_model_num << 1)) + { + goto compo_data_end; + } + data_uart_debug("\ts:"); + for (model_num = 0; model_num < sig_model_num; model_num++, pdata += 2) + { + data_uart_debug(" 0x%04xffff", LE_EXTRN2WORD(pdata)); + } + data_uart_debug("\r\n"); + } + if (vendor_model_num) + { + if (pend - pdata < (vendor_model_num << 2)) + { + goto compo_data_end; + } + data_uart_debug("\tv:"); + for (model_num = 0; model_num < vendor_model_num; model_num++, pdata += 4) + { + data_uart_debug(" 0x%08x", LE_EXTRN2DWORD(pdata)); + } + data_uart_debug("\r\n"); + } + element_index++; + } + break; +compo_data_end: + parse = FALSE; + data_uart_debug("cdp0 of 0x%04x invalid!\r\n", pmesh_msg->src); + } + } + break; + case MESH_MSG_CFG_DEFAULT_TTL_STAT: + { + parse = TRUE; + cfg_default_ttl_stat_t *pmsg = (cfg_default_ttl_stat_t *)pbuffer; + data_uart_debug("default ttl: %d\r\n", pmsg->ttl); + } + break; + case MESH_MSG_CFG_PROXY_STAT: + { + parse = TRUE; + cfg_proxy_stat_t *pmsg = (cfg_proxy_stat_t *)pbuffer; + data_uart_debug("proxy state: %d\r\n", pmsg->state); + } + break; + case MESH_MSG_CFG_RELAY_STAT: + { + parse = TRUE; + cfg_relay_stat_t *pmsg = (cfg_relay_stat_t *)pbuffer; + data_uart_debug("relay state: %d, count = %d step = %d\r\n", pmsg->state, pmsg->count, pmsg->steps); + } + break; + case MESH_MSG_CFG_NET_TRANS_STAT: + { + parse = TRUE; + cfg_net_transmit_stat_t *pmsg = (cfg_net_transmit_stat_t *)pbuffer; + data_uart_debug("net transmit state: count = %d step = %d\r\n", pmsg->count, pmsg->steps); + } + break; + case MESH_MSG_CFG_MODEL_PUB_STAT: + { + cfg_model_pub_stat_t *pmsg = (cfg_model_pub_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + data_uart_debug("Pub stat: pub addr = 0x%04x ttl = %d!\r\n", pmsg->pub_addr, pmsg->pub_ttl); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema && bt_mesh_lib_priv.connect_device_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.connect_device_flag = 1; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_model_pub_set), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_pub_set)); + } +#endif + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema && bt_mesh_lib_priv.connect_device_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.connect_device_flag = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_model_pub_set), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_pub_set)); + } +#endif + } + } + break; + case MESH_MSG_CFG_MODEL_SUB_STAT: + { + cfg_model_sub_stat_t *pmsg = (cfg_model_sub_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + data_uart_debug("Success!\r\n"); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.set_node_group_sema && bt_mesh_lib_priv.set_node_group_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.set_node_group_flag = 1; + rtw_up_sema(&bt_mesh_lib_priv.set_node_group_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + { + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_model_sub_add), BT_MESH_USER_CMD_SUCCESS, (void *)&pmesh_msg->src); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_sub_add)); + break; + } + } else { + break; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_model_sub_delete), BT_MESH_USER_CMD_SUCCESS, (void *)&pmesh_msg->src); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_sub_delete)); + break; + } + } else { + break; + } + } +#endif + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.set_node_group_sema && bt_mesh_lib_priv.set_node_group_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.set_node_group_flag = 0; + rtw_up_sema(&bt_mesh_lib_priv.set_node_group_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + { + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_model_sub_add), BT_MESH_USER_CMD_FAIL, (void *)&pmesh_msg->src); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_sub_add)); + break; + } + } else { + break; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_model_sub_delete), BT_MESH_USER_CMD_FAIL, (void *)&pmesh_msg->src); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_sub_delete)); + break; + } + } else { + break; + } + } +#endif + } + } + break; + case MESH_MSG_CFG_SIG_MODEL_SUB_LIST: + case MESH_MSG_CFG_VENDOR_MODEL_SUB_LIST: + { + cfg_model_sub_list_t *pmsg = (cfg_model_sub_list_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + uint32_t model_id = pmesh_msg->access_opcode == MESH_MSG_CFG_SIG_MODEL_SUB_LIST ? + MESH_MODEL_TRANSFORM(pmsg->model_id) : pmsg->model_id; + data_uart_debug("Model sub list: sr 0x%04x element idx %d model id 0x%08x\r\n\t", pmesh_msg->src, + pmsg->element_addr - pmesh_msg->src, model_id); + uint16_t len = MEMBER_OFFSET(cfg_model_sub_list_t, + model_id) + (pmesh_msg->access_opcode == MESH_MSG_CFG_SIG_MODEL_SUB_LIST ? 2 : 4); + pbuffer += len; + for (uint8_t loop = 0; loop < pmesh_msg->msg_len - len; loop += 2) + { + data_uart_debug(" 0x%04x", LE_EXTRN2WORD(pbuffer + loop)); + } +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + { + uint16_t mesh_addr = pmesh_msg->src; + uint16_t group_addr = 0; + if (pmesh_msg->msg_len - len != 0) + group_addr = LE_EXTRN2WORD(pbuffer + 0); + update_node_group(mesh_addr, group_addr); + } +#endif + data_uart_debug("\r\n"); + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); + } + } + break; + case MESH_MSG_CFG_NET_KEY_STAT: + { + if (pmesh_msg->msg_len == sizeof(cfg_net_key_stat_t)) + { + cfg_net_key_stat_t *pmsg = (cfg_net_key_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + data_uart_debug("Success!\r\n"); + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); + } + } + } + break; + case MESH_MSG_CFG_NET_KEY_LIST: + { + pbuffer += MEMBER_OFFSET(cfg_net_key_list_t, net_key_indexes); + uint16_t len = pmesh_msg->msg_len - MEMBER_OFFSET(cfg_net_key_list_t, net_key_indexes); + uint8_t remainder = len % 3; + if (remainder == 0 || remainder == 2) + { + parse = TRUE; + uint16_t key_count = len / 3 * 2 + (remainder != 0); + data_uart_debug("NetKey List: num = %d!\r\n\t", key_count); + for (uint16_t loop = 0; loop < key_count; loop++) + { + uint16_t offset = (loop >> 1) * 3; + uint16_t key_index; + if (loop % 2 == 0) + { + key_index = 0xfff & LE_EXTRN2WORD(pbuffer + offset); + } + else + { + key_index = LE_EXTRN2WORD(pbuffer + offset + 1) >> 4; + } + data_uart_debug(" 0x%03x", key_index); + } + data_uart_debug("\r\n"); + } + else + { + data_uart_debug("Fail, len = %d!\r\n", len); + } + } + break; + case MESH_MSG_CFG_APP_KEY_STAT: + { + if (pmesh_msg->msg_len == sizeof(cfg_app_key_stat_t)) + { + cfg_app_key_stat_t *pmsg = (cfg_app_key_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + data_uart_debug("Success!\r\n"); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema && bt_mesh_lib_priv.connect_device_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.connect_device_flag = 1; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_app_key_add), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_app_key_add)); + } +#endif + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema && bt_mesh_lib_priv.connect_device_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.connect_device_flag = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_app_key_add), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_app_key_add)); + } +#endif + } + } + } + + break; + case MESH_MSG_CFG_APP_KEY_LIST: + { + cfg_app_key_list_t *pmsg = (cfg_app_key_list_t *)pbuffer; + pbuffer += MEMBER_OFFSET(cfg_app_key_list_t, app_key_indexes); + uint16_t len = pmesh_msg->msg_len - MEMBER_OFFSET(cfg_app_key_list_t, app_key_indexes); + uint8_t remainder = len % 3; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS && (remainder == 0 || remainder == 2)) + { + parse = TRUE; + uint16_t key_count = len / 3 * 2 + (remainder != 0); + data_uart_debug("AppKey List: NetKeyIndex = 0x%03x num = %d!\r\n\t", pmsg->net_key_index, + key_count); + for (uint16_t loop = 0; loop < key_count; loop++) + { + uint16_t offset = (loop >> 1) * 3; + uint16_t key_index; + if (loop % 2 == 0) + { + key_index = 0xfff & LE_EXTRN2WORD(pbuffer + offset); + } + else + { + key_index = LE_EXTRN2WORD(pbuffer + offset + 1) >> 4; + } + data_uart_debug(" 0x%03x", key_index); + } + data_uart_debug("\r\n"); + } + else + { + data_uart_debug("Fail, stat = %d len = %d!\r\n", pmsg->stat, len); + } + } + break; + case MESH_MSG_CFG_NODE_IDENTITY_STAT: + { + cfg_node_identity_stat_t *pmsg = (cfg_node_identity_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + data_uart_debug("node identity state: %d on NetKeyIndex 0x%03x\r\n", pmsg->identity, + pmsg->net_key_index); + } + else + { + data_uart_debug("Fail, stat = %d!\r\n", pmsg->stat); + } + } + break; + case MESH_MSG_CFG_MODEL_APP_STAT: + { + cfg_model_app_stat_t *pmsg = (cfg_model_app_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + data_uart_debug("Success!\r\n"); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema && bt_mesh_lib_priv.connect_device_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.connect_device_flag = 1; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_model_app_bind), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_app_bind)); + } +#endif + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema && bt_mesh_lib_priv.connect_device_mesh_addr == pmesh_msg->src) { + bt_mesh_lib_priv.connect_device_flag = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_model_app_bind), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_model_app_bind)); + } +#endif + } + } + break; + case MESH_MSG_CFG_SIG_MODEL_APP_LIST: + case MESH_MSG_CFG_VENDOR_MODEL_APP_LIST: + { + cfg_model_app_list_t *pmsg = (cfg_model_app_list_t *)pbuffer; + uint32_t model_id = pmesh_msg->access_opcode == MESH_MSG_CFG_SIG_MODEL_APP_LIST ? + MESH_MODEL_TRANSFORM(pmsg->model_id) : pmsg->model_id; + uint8_t header_len = MEMBER_OFFSET(cfg_model_app_list_t, + model_id) + (pmesh_msg->access_opcode == MESH_MSG_CFG_SIG_MODEL_APP_LIST ? 2 : 4); + pbuffer += header_len; + uint16_t len = pmesh_msg->msg_len - header_len; + uint8_t remainder = len % 3; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS && (remainder == 0 || remainder == 2)) + { + parse = TRUE; + uint16_t key_count = len / 3 * 2 + (remainder != 0); + data_uart_debug("Model AppKey List: Element Index = %d model id = 0x%08x num = %d!\r\n\t", + pmsg->element_addr - pmesh_msg->src, model_id, key_count); + for (uint16_t loop = 0; loop < key_count; loop++) + { + uint16_t offset = (loop >> 1) * 3; + uint16_t key_index; + if (loop % 2 == 0) + { + key_index = 0xfff & LE_EXTRN2WORD(pbuffer + offset); + } + else + { + key_index = LE_EXTRN2WORD(pbuffer + offset + 1) >> 4; + } + data_uart_debug(" 0x%03x", key_index); + } + data_uart_debug("\r\n"); + } + else + { + data_uart_debug("Fail, stat = %d len = %d!\r\n", pmsg->stat, len); + } + } + break; + case MESH_MSG_CFG_NODE_RESET_STAT: + { + parse = TRUE; + data_uart_debug("Node 0x%04x reseted!\r\n", pmesh_msg->src); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_nr_sema && bt_mesh_lib_priv.connect_device_nr_mesh_addr == pmesh_msg->src) { + rtw_up_sema(&bt_mesh_lib_priv.connect_device_nr_sema); + } + if (bt_mesh_lib_priv.delete_node_sema && bt_mesh_lib_priv.delete_node_mesh_addr == pmesh_msg->src) { + rtw_up_sema(&bt_mesh_lib_priv.delete_node_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + if (bt_mesh_lib_priv.connect_device_nr_mesh_addr == pmesh_msg->src) { + if (bt_mesh_indication(GEN_MESH_CODE(_node_reset), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_node_reset)); + } + break; + } + if (bt_mesh_lib_priv.delete_node_mesh_addr == pmesh_msg->src) { + if (bt_mesh_indication(GEN_MESH_CODE(_node_reset), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_node_reset)); + } + break; + } + if (bt_mesh_indication(GEN_MESH_CODE(_node_reset), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_node_reset)); + } +#else + if (bt_mesh_indication(GEN_MESH_CODE(_node_reset), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_node_reset)); + } +#endif +#endif + } + break; + case MESH_MSG_CFG_FRND_STAT: + { + parse = TRUE; + cfg_frnd_stat_t *pmsg = (cfg_frnd_stat_t *)pbuffer; + data_uart_debug("frnd state: %d\r\n", pmsg->state); + } + break; + case MESH_MSG_CFG_LPN_POLL_TO_STAT: + { + parse = TRUE; + cfg_lpn_poll_timeout_stat_t *pmsg = (cfg_lpn_poll_timeout_stat_t *)pbuffer; + data_uart_debug("fn = 0x%04x lpn = 0x%04x poll_timeout = %d00ms\r\n", pmsg->lpn_addr, + pmsg->poll_to[0] + (pmsg->poll_to[1] << 8) + (pmsg->poll_to[2] << 16)); + } + break; + case MESH_MSG_CFG_KEY_REFRESH_PHASE_STAT: + { + cfg_key_refresh_phase_stat_t *pmsg = (cfg_key_refresh_phase_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + + data_uart_debug("Node 0x%04x: NetKeyIndex = 0x%03x state = %d\r\n", pmesh_msg->src, + pmsg->net_key_index, pmsg->state); + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); + } + } + break; + case MESH_MSG_CFG_HB_PUB_STAT: + { + cfg_hb_pub_stat_t *pmsg = (cfg_hb_pub_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + + data_uart_debug("Hb: pub dst = 0x%04x ttl = %d NetKeyIndex = 0x%03x\r\n", pmsg->dst, pmsg->ttl, + pmsg->net_key_index); + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); + } + } + break; + case MESH_MSG_CFG_HB_SUB_STAT: + { + cfg_hb_sub_stat_t *pmsg = (cfg_hb_sub_stat_t *)pbuffer; + if (pmsg->stat == MESH_MSG_STAT_SUCCESS) + { + parse = TRUE; + + data_uart_debug("Hb: sub src = 0x%04x dst = 0x%04x hops range = [%d, %d]r\n", pmsg->src, pmsg->dst, + pmsg->min_hops, pmsg->max_hops); + } + else + { + data_uart_debug("Fail, status = %d!\r\n", pmsg->stat); + } + } + break; + default: + ret = FALSE; + break; + } + + if (ret == TRUE) + { + if (parse == FALSE) + { + data_uart_debug("cfg_client_receive: opcode = 0x%x, len = %d, value = ", pmesh_msg->access_opcode, + pmesh_msg->msg_len); + data_uart_dump(pbuffer, pmesh_msg->msg_len); + } + printi("cfg_client_receive: opcode = 0x%x, len = %d, value = ", pmesh_msg->access_opcode, + pmesh_msg->msg_len); + dprintt(pbuffer, pmesh_msg->msg_len); + } + return ret; +} + +bool cfg_client_reg(void) +{ + if (NULL != mesh_model_info_get_by_model_id(0, MESH_MODEL_CFG_CLIENT)) + { + return FALSE; + } + + cfg_client.model_id = MESH_MODEL_CFG_CLIENT; + cfg_client.model_receive = cfg_client_receive; + return mesh_model_reg(0, &cfg_client); +} + +bool cfg_client_key_set(uint16_t key_index) +{ + if (mesh_node.features.cfg_model_use_app_key && key_index >= mesh_node.app_key_num) + { + return false; + } + else if (mesh_node.features.cfg_model_use_app_key == 0 && key_index >= mesh_node.net_key_num) + { + return false; + } + else + { + cfg_client_key_index = key_index; + return true; + } +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.c new file mode 100644 index 00000000..482c8a7b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.c @@ -0,0 +1,205 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file delay_execution.c +* @brief Source file for delay execution. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-11-29 +* @version v1.0 +* ************************************************************************************* +*/ +#include "delay_execution.h" + + +#define DELAY_EXECUTION_TIMER_ID 100 + +typedef struct _delay_list +{ + struct _delay_list *next; +} delay_list_t; + +typedef struct _delay_execution_t +{ + plt_timer_t delay_timer; + const mesh_model_info_t *pmodel_info; + uint32_t delay_type; + delay_execution_cb delay_execution; + delay_list_t node; +} delay_execution_t; + +static delay_list_t delay_list_head; + + +#if MODEL_ENABLE_MULTI_THREAD +#define DELAY_INFINITE_WAIT 0xffffffff +plt_mutex_t delay_mutex; +#endif + +void delay_execution_handler(void *pargs) +{ + delay_execution_t *pexecute = pargs; + /* free expired delay and notify model */ + if (NULL != pexecute->delay_execution) + { + pexecute->delay_execution((mesh_model_info_t *)(pexecute->pmodel_info), pexecute->delay_type); + } + plt_timer_delete(pexecute->delay_timer, 0); + plt_free(pexecute, RAM_TYPE_DATA_ON); +} + +static void delay_execution_timeout_handle(void *ptimer) +{ +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(delay_mutex, DELAY_INFINITE_WAIT); +#endif + + delay_list_t *pcur = delay_list_head.next; + delay_list_t *pprev = &delay_list_head; + delay_execution_t *pexecute = NULL; + for (; pcur != &delay_list_head; pprev = pcur, pcur = pcur->next) + { + pexecute = CONTAINER_OF(pcur, delay_execution_t, node); + if (pexecute->delay_timer == ptimer) + { + pprev->next = pcur->next; + break; + } + } + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(delay_mutex); +#endif + + if (pcur != &delay_list_head) + { + mesh_inner_msg_t msg; + msg.type = MESH_MODEL_DELAY_EXECUTION_TIMEOUT; + msg.pbuf = pexecute; + if (!mesh_inner_msg_send(&msg)) + { + printe("delay_execution_timeout_handle: send message failed!"); + } + } +} + +bool delay_execution_timer_start(const mesh_model_info_t *pmodel_info, + uint32_t delay_type, uint32_t delay_time, + delay_execution_cb delay_execution) +{ + delay_list_t *pcur = delay_list_head.next; + delay_execution_t *pexecute = NULL; + for (; pcur != &delay_list_head; pcur = pcur->next) + { + pexecute = CONTAINER_OF(pcur, delay_execution_t, node); + if ((pexecute->pmodel_info == pmodel_info) && (pexecute->delay_type == delay_type)) + { + /* find same delay execution, update it */ + pexecute->delay_execution = delay_execution; + plt_timer_change_period(pexecute->delay_timer, delay_time, 0); + printi("delay_execution_timer_start: update timer"); + return TRUE; + } + } + + /* new delay execution */ + pexecute = plt_malloc(sizeof(delay_execution_t), RAM_TYPE_DATA_ON); + if (NULL == pexecute) + { + printe("delay_execution_timer_start: allocate delay execution structure failed!"); + return FALSE; + } + pexecute->delay_timer = plt_timer_create("delay", delay_time, FALSE, DELAY_EXECUTION_TIMER_ID, + delay_execution_timeout_handle); + if (NULL == pexecute->delay_timer) + { + printe("delay_execution_timer_start: allocate delay execution timer failed!"); + plt_free(pexecute, RAM_TYPE_DATA_ON); + return FALSE; + } + pexecute->pmodel_info = pmodel_info; + pexecute->delay_type = delay_type; + pexecute->delay_execution = delay_execution; + pexecute->node.next = NULL; + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(delay_mutex, DELAY_INFINITE_WAIT); +#endif + + /* prepend node */ + pcur = delay_list_head.next; + pexecute->node.next = pcur; + delay_list_head.next = &pexecute->node; + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(delay_mutex); +#endif + + /* start delay execution */ + plt_timer_start(pexecute->delay_timer, 0); + + return TRUE; +} + +void delay_execution_timer_stop(const mesh_model_info_t *pmodel_info, + uint32_t delay_type) +{ + /* remove specified model delay */ +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(delay_mutex, DELAY_INFINITE_WAIT); +#endif + + delay_list_t *pcur = delay_list_head.next; + delay_list_t *pprev = &delay_list_head; + delay_execution_t *pexecute = NULL; + for (; pcur != &delay_list_head; pprev = pcur, pcur = pcur->next) + { + delay_execution_t *pexecute = CONTAINER_OF(pcur, delay_execution_t, node); + if ((pexecute->pmodel_info == pmodel_info) && + (pexecute->delay_type == delay_type)) + { + pprev->next = pcur->next; + break; + } + } + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(delay_mutex); +#endif + + if (pcur != &delay_list_head) + { + /* free expired delay and notify model */ +#if MODEL_ENABLE_USER_STOP_DELAY_NOTIFICATION + if (NULL != pexecute->delay_execution) + { + pexecute->delay_execution((mesh_model_info_t *)(pexecute->pmodel_info), pexecute->delay_type); + } +#endif + plt_timer_delete(pexecute->delay_timer, 0); + plt_free(pexecute, RAM_TYPE_DATA_ON); + } +} + +bool delay_execution_init(void) +{ +#if MODEL_ENABLE_MULTI_THREAD + if (NULL == delay_mutex) + { + delay_mutex = plt_mutex_create(); + if (NULL == delay_mutex) + { + return FALSE; + } + } +#endif + + if (NULL == delay_list_head.next) + { + delay_list_head.next = &delay_list_head; + } + + mesh_model_delay_execution_init(delay_execution_handler); + return TRUE; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.h new file mode 100644 index 00000000..9af6fdd2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.h @@ -0,0 +1,77 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file delay_execution.h +* @brief Head file for delay execution. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-11-29 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _DELAY_EXECUTION_H_ +#define _DELAY_EXECUTION_H_ + +#include "platform_types.h" +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup DELAY_EXECUTION + * @{ + */ + +/** @defgroup DELAY_EXECUTION_DATA Delay Execution Data + * @brief Delay execution data and structure definition + * @{ + */ +#define DELAY_EXECUTION_STEP_RESOLUTION 5 //!< unit is ms + +typedef int32_t (*delay_execution_cb)(mesh_model_info_t *pmodel_info, + uint32_t data_type); +/** @} */ + +/** @defgroup DELAY_EXECUTION_API Delay Execution Api + * @brief Functions declaration + * @{ + */ + +/** + * @brief initialize delay execution + * @retval TRUE: initialize success + * @retval FALSE: initialize failed + */ +bool delay_execution_init(void); + +/** + * @brief start model delay execution timer + * @param[in] pmodel_info: pointer to model information context that need to delay + * @param[in] delay_type: delay execution type + * @param[in] delay_time: delay execution total time + * @param[in] delay_execution: delay execution callback function + * @retval TRUE: start delay execution success + * @retval FALSE: start delay execution failed + */ +bool delay_execution_timer_start(const mesh_model_info_t *pmodel_info, + uint32_t delay_type, uint32_t delay_time, + delay_execution_cb delay_execution); + +/** + * @brief stop model delay execution timer + * @param[in] pmodel_info: pointer to model information context that need to stop delay + * @param[in] delay_type: delay execution type + */ +void delay_execution_timer_stop(const mesh_model_info_t *pmodel_info, + uint32_t delay_type); +/** @} */ +/** @} */ + + +END_DECLS + + +#endif /** _DELAY_EXECUTION_H_ */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c new file mode 100644 index 00000000..aaf9423d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c @@ -0,0 +1,107 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file delay_msg_resp.c +* @brief Source file for delay message response. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-05-20 +* @version v1.0 +* ************************************************************************************* +*/ +#include +#include "delay_msg_rsp.h" +#include "mesh_node.h" +#include "model_config.h" + +#define DELAY_MSG_TRANS_DELAY_MIN 200 /* 200ms */ + +#define DELAY_MSG_UNICAST_ADDR_MIN 10 +#define DELAY_MSG_UNICAST_ADDR_MAX 50 +#define DELAY_MSG_GROUP_ADDR_MIN 500 +#define DELAY_MSG_GROUP_ADDR_MAX 2000 + +uint32_t delay_msg_get_rsp_delay(uint16_t dst_addr) +{ + int delay = rand(); + uint32_t real_delay = delay; + if (MESH_IS_UNICAST_ADDR(dst_addr)) + { + /* random delay 10-50ms */ + real_delay %= (DELAY_MSG_UNICAST_ADDR_MAX - DELAY_MSG_UNICAST_ADDR_MIN); + real_delay += DELAY_MSG_UNICAST_ADDR_MIN; + } + else + { + /* random delay 50-1000ms */ + real_delay %= (DELAY_MSG_GROUP_ADDR_MAX - DELAY_MSG_GROUP_ADDR_MIN); + real_delay += DELAY_MSG_GROUP_ADDR_MIN; + } + + return real_delay; +} + +uint32_t delay_msg_get_trans_delay(uint32_t delay_time, generic_transition_time_t trans_time, + uint32_t delay_rsp_time, bool send_immediately, bool ack) +{ + uint32_t delay_pub_time = delay_time + generic_transition_time_convert(trans_time); + +#if MODEL_ENABLE_PARALLEL_ADV + UNUSED(ack); + if (send_immediately) + { + if (delay_pub_time < DELAY_MSG_TRANS_DELAY_MIN) + { + delay_pub_time = DELAY_MSG_TRANS_DELAY_MIN; + } + delay_pub_time += delay_rsp_time; + } + else + { + uint32_t temp = delay_rsp_time; + if (delay_pub_time < DELAY_MSG_TRANS_DELAY_MIN) + { + temp += (DELAY_MSG_TRANS_DELAY_MIN - delay_pub_time); + } + delay_pub_time = temp; + } +#else + if (send_immediately) + { + if (delay_pub_time < DELAY_MSG_TRANS_DELAY_MIN) + { + delay_pub_time = DELAY_MSG_TRANS_DELAY_MIN; + } + if (!ack) + { + delay_pub_time += delay_rsp_time; + } + } + else + { + if (delay_pub_time < delay_rsp_time) + { + if (delay_pub_time < DELAY_MSG_TRANS_DELAY_MIN) + { + delay_pub_time = DELAY_MSG_TRANS_DELAY_MIN; + } + if (!ack) + { + delay_pub_time += delay_rsp_time; + } + } + else + { + uint32_t temp = delay_rsp_time; + if (delay_pub_time < DELAY_MSG_TRANS_DELAY_MIN) + { + temp += (DELAY_MSG_TRANS_DELAY_MIN - delay_pub_time); + } + delay_pub_time = temp; + } + } +#endif + + return delay_pub_time; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.h new file mode 100644 index 00000000..35887c63 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.h @@ -0,0 +1,43 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file delay_msg_rsp.h +* @brief Head file for delay message response +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-05-20 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _DELAY_MSG_RSP_H_ +#define _DELAY_MSG_RSP_H_ + +#include "platform_types.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @brief get message response delay time + * @param[in] dst_addr: destination address + * @return delay time, unit is ms + */ +uint32_t delay_msg_get_rsp_delay(uint16_t dst_addr); + +/** + * @brief get transition delay time + * @param[in] delay_time: delay execution time + * @param[in] trans_time: generic transition time + * @param[in] delay_rsp_time: message response delay time + * @param[in] send_immediately: whether message shall send immediately + * @param[in] ack: whether message is acknowledge message + * @return transition delay time, unit is ms + */ +uint32_t delay_msg_get_trans_delay(uint32_t delay_time, generic_transition_time_t trans_time, + uint32_t delay_rsp_time, bool send_immediately, bool ack); + +END_DECLS + +#endif /* _DELAY_MSG_RSP_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution.h new file mode 100644 index 00000000..6b2f6269 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution.h @@ -0,0 +1,812 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file firmware_distribution.h +* @brief Head file for firmware distribution models. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-5-21 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _FIRMWARE_DISTRIBUTION_H +#define _FIRMWARE_DISTRIBUTION_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "mesh_api.h" +#include "blob_transfer.h" +#include "firmware_update.h" + +#if MESH_DFU + +BEGIN_DECLS + +/** + * @addtogroup FIRMWARE_DISTRIBUTION + * @{ + */ + +/* firmware distribution server capabilites */ +#define FW_DIST_CPAS_MAX_DIST_RECVS_LIST_SIZE 2 +#define FW_DIST_CPAS_MAX_FW_IMAGES_LIST_SIZE 2 +#define FW_DIST_CPAS_MAX_FW_IMAGE_SIZE 5000 +#define FW_DIST_CPAS_MAX_UPLOAD_SPACE 10000 +#define FW_DIST_CPAS_OOB_RETRIEVAL_SUPPORTED 1 + + +/** + * @defgroup FIRMWARE_DISTRIBUTION_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_FW_DIST_RECVS_ADD 0x6F +#define MESH_MSG_FW_DIST_RECVS_DELETE_ALL 0xB720 +#define MESH_MSG_FW_DIST_RECVS_STATUS 0xB721 +#define MESH_MSG_FW_DIST_RECVS_GET 0xB722 +#define MESH_MSG_FW_DIST_RECVS_LIST 0x6E +#define MESH_MSG_FW_DIST_CAPS_GET 0xB723 +#define MESH_MSG_FW_DIST_CAPS_STATUS 0x6D +#define MESH_MSG_FW_DIST_GET 0xB724 +#define MESH_MSG_FW_DIST_START 0x6C +#define MESH_MSG_FW_DIST_CANCEL 0xB725 +#define MESH_MSG_FW_DIST_APPLY 0xB726 +#define MESH_MSG_FW_DIST_STATUS 0x6B +#define MESH_MSG_FW_DIST_UPLOAD_GET 0xB727 +#define MESH_MSG_FW_DIST_UPLOAD_START 0x6A +#define MESH_MSG_FW_DIST_UPLOAD_OOB_START 0x60 +#define MESH_MSG_FW_DIST_UPLOAD_CANCEL 0xB728 +#define MESH_MSG_FW_DIST_UPLOAD_STATUS 0x5F +#define MESH_MSG_FW_DIST_FW_GET 0x5E +#define MESH_MSG_FW_DIST_FW_GET_BY_INDEX 0xB729 +#define MESH_MSG_FW_DIST_FW_DELETE 0x5D +#define MESH_MSG_FW_DIST_FW_DELETE_ALL 0xB72A +#define MESH_MSG_FW_DIST_FW_STATUS 0x5C +/** @} */ + +/** + * @defgroup FIRMWARE_DISTRIBUTION_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_FW_DIST_SERVER 0xBF46FFFF +#define MESH_MODEL_FW_DIST_CLIENT 0xBF47FFFF +/** @} */ + +/** + * @defgroup FIRMWARE_DISTRIBUTION_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define FW_IMAGE_INDEX_INVALID 0xFFFF + +typedef struct +{ + uint8_t fw_id_len; + fw_id_t fw_id; + uint8_t metadata_len; + uint8_t metadata[255]; +} _PACKED4_ fw_image_t; + +enum +{ + FW_DIST_PHASE_IDLE, + FW_DIST_PHASE_TRANSFER_ACTIVE, + FW_DIST_PHASE_TRANSFER_SUCCESS, + FW_DIST_PHASE_APPLYING_UPDATE, + FW_DIST_PHASE_COMPLETED, + FW_DIST_PHASE_FAILED, + FW_DIST_PHASE_CANCELING_UPDATE, +} _SHORT_ENUM_; +typedef uint8_t fw_dist_phase_t; + +enum +{ + FW_UPLOAD_PHASE_IDLE, + FW_UPLOAD_PHASE_TRANSFER_ACTIVE, + FW_UPLOAD_PHASE_OOB_TRANSFER_ACTIVE, + FW_UPLOAD_PHASE_TRANSFER_ERR, + FW_UPLOAD_PHASE_TRANSFER_SUCCESS, +} _SHORT_ENUM_; +typedef uint8_t fw_upload_phase_t; + +enum +{ + FW_DIST_STATUS_SUCCESS, + FW_DIST_STATUS_INSUFFICIENT_RESOURCES, + FW_DIST_STATUS_WRONG_PHASE, + FW_DIST_STATUS_INTERNAL_ERR, + FW_DIST_STATUS_FW_NOT_FOUND, + FW_DIST_STATUS_INVALID_APP_KEY_INDEX, + FW_DIST_STATUS_RECEIVERS_LIST_EMPTY, + FW_DIST_STATUS_BUSY_WITH_DIST, + FW_DIST_STATUS_BUSY_WITH_UPLOAD, + FW_DIST_STATUS_URI_NOT_SUPPORTED, + FW_DIST_STATUS_URI_MALFORMED, +} _SHORT_ENUM_; +typedef uint8_t fw_dist_status_code_t; + +enum +{ + FW_UPDATE_POLICY_VERIFY_ONLY, + FW_UPDATE_POLICY_VERIFY_AND_UPDATE, +} _SHORT_ENUM_; +typedef uint8_t fw_update_policy_t; + +typedef struct +{ + uint16_t addr; + uint8_t update_fw_image_idx; +} _PACKED4_ fw_dist_receiver_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_RECVS_ADD)]; + fw_dist_receiver_t entries[0]; +} _PACKED4_ fw_dist_recvs_add_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_RECVS_DELETE_ALL)]; +} _PACKED4_ fw_dist_recvs_delete_all_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_RECVS_STATUS)]; + fw_dist_status_code_t status; + uint16_t recvs_list_cnt; +} _PACKED4_ fw_dist_recvs_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_RECVS_GET)]; + uint16_t first_index; + uint16_t entries_limit; +} _PACKED4_ fw_dist_recvs_get_t; + +typedef struct +{ + uint32_t addr : 15; + uint32_t retrieved_update_phase : 4; + uint32_t update_status : 3; + uint32_t transfer_status : 4; + uint32_t transfer_progress : 6; + uint8_t update_fw_image_idx; +} _PACKED4_ fw_update_node_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_RECVS_LIST)]; + uint16_t recvs_list_cnt; + uint16_t first_index; + fw_update_node_t entries[0]; +} _PACKED4_ fw_dist_recvs_list_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_CAPS_GET)]; +} _PACKED4_ fw_dist_caps_get_t; + +typedef struct +{ + uint16_t max_dist_recvs_list_size; + uint16_t max_fw_images_list_size; + uint32_t max_fw_image_size; + uint32_t max_upload_spcace; + uint32_t remaining_upload_space; + uint8_t oob_retrieval_supported; +} _PACKED4_ fw_dist_caps_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_CAPS_STATUS)]; + fw_dist_caps_t dist_caps; + uint8_t supported_uri_scheme_names[0]; +} _PACKED4_ fw_dist_caps_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_GET)]; +} _PACKED4_ fw_dist_get_t; + +typedef struct +{ + uint16_t dist_app_key_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + uint8_t dist_transfer_mode : 2; + uint8_t update_policy : 1; + uint8_t rfu : 5; + uint16_t dist_fw_image_idx; + uint8_t dist_multicast_addr[16]; +} _PACKED4_ fw_dist_start_data_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_START)]; + uint16_t dist_app_key_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + uint8_t dist_transfer_mode : 2; + uint8_t update_policy : 1; + uint8_t rfu : 5; + uint16_t dist_fw_image_idx; + uint8_t dist_multicast_addr[16]; +} _PACKED4_ fw_dist_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_CANCEL)]; +} _PACKED4_ fw_dist_cancel_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_APPLY)]; +} _PACKED4_ fw_dist_apply_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_STATUS)]; + fw_dist_status_code_t status; + fw_dist_phase_t phase; + uint16_t dist_multicast_addr; + uint16_t dist_appkey_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + uint8_t dist_transfer_mode : 2; + uint8_t update_policy : 1; + uint8_t rfu : 5; + uint16_t dist_fw_image_idx; +} _PACKED4_ fw_dist_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_UPLOAD_GET)]; +} _PACKED4_ fw_dist_upload_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_UPLOAD_START)]; + uint8_t upload_ttl; + uint16_t upload_timeout_base; + uint8_t blob_id[8]; + uint32_t upload_fw_size; + uint8_t upload_fw_metadata_len; + uint8_t upload_fw_info[0]; +} _PACKED4_ fw_dist_upload_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_UPLOAD_OOB_START)]; + uint8_t upload_uri_len; + uint8_t upload_fw_info[0]; +} _PACKED4_ fw_dist_upload_oob_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_UPLOAD_CANCEL)]; +} _PACKED4_ fw_dist_upload_cancel_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_UPLOAD_STATUS)]; + uint8_t status; + fw_upload_phase_t phase; + uint8_t upload_progress; + uint8_t upload_fw_id[0]; +} _PACKED4_ fw_dist_upload_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_FW_GET)]; + uint8_t fw_id[0]; +} _PACKED4_ fw_dist_fw_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_FW_GET_BY_INDEX)]; + uint16_t dist_fw_image_idx; +} _PACKED4_ fw_dist_fw_get_by_index_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_FW_DELETE)]; + uint8_t fw_id[0]; +} _PACKED4_ fw_dist_fw_delete_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_FW_DELETE_ALL)]; +} _PACKED4_ fw_dist_fw_delete_all_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_DIST_FW_STATUS)]; + uint8_t status; + uint16_t entry_cnt; + uint16_t dist_fw_image_idx; + uint8_t fw_id[0]; +} _PACKED4_ fw_dist_fw_status_t; +/** @} */ + +/** + * @defgroup FIRMWARE_DISTRIBUTION_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ + +typedef struct +{ + fw_dist_caps_t caps; + uint8_t *psupported_uri_scheme_names; + uint16_t uri_scheme_names_len; + plt_list_t dist_update_node_list; + plt_list_t dist_fw_image_list; + fw_dist_phase_t dist_phase; + /* distribution parameters */ + uint16_t dist_multicast_addr; + uint16_t dist_app_key_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + uint8_t dist_transfer_mode; + fw_update_policy_t dist_update_policy; + uint16_t dist_fw_image_index; + /* upload parameters */ + fw_upload_phase_t upload_phase; + uint8_t upload_ttl; + uint16_t upload_timeout_base; + uint8_t upload_blob_id[8]; + uint32_t upload_fw_size; + uint32_t upload_recvd_size; + fw_image_t upload_fw_image; + uint8_t upload_uri[255]; + uint8_t upload_uri_len; +} fw_dist_server_ctx_t; + +extern fw_dist_server_ctx_t fw_dist_server_ctx; + + +#define FW_DIST_SERVER_START 0 //!< @ref fw_dist_server_start_t +#define FW_DIST_SERVER_CANCEL 1 //!< @ref NULL +#define FW_DIST_SERVER_APPLY 2 //!< @ref NULL +#define FW_DIST_SERVER_UPLOAD_START 3 //!< @ref fw_dist_server_upload_start_t +#define FW_DIST_SERVER_UPLOAD_OOB_START 4 //!< @ref fw_dist_server_upload_oob_start_t +#define FW_DIST_SERVER_UPLOAD_BLOCK_DATA 5 //!< @ref fw_dist_server_upload_block_data_t +#define FW_DIST_SERVER_UPLOAD_COMPLETE 6 //!< @ref NULL +#define FW_DIST_SERVER_UPLOAD_FAIL 7 //!< @ref fw_dist_server_upload_fail_t +#define FW_DIST_SERVER_FW_DELETE 8 //!< @ref fw_dist_server_fw_delete_t +#define FW_DIST_SERVER_FW_DELETE_ALL 9 //!< @ref NULL +#define FW_DIST_SERVER_URI_CHECK 10 //!< @ref fw_dist_server_uri_check_t + +typedef struct +{ + uint16_t dist_app_key_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + uint8_t dist_transfer_mode; + uint8_t dist_update_policy; + uint16_t dist_fw_image_index; + uint16_t dist_multicast_addr; +} fw_dist_server_start_t; + +typedef struct +{ + uint8_t upload_ttl; + uint16_t upload_timeout_base; + uint8_t upload_blob_id[8]; + uint32_t upload_fw_size; + uint8_t upload_fw_metadata_len; + uint8_t *pupload_metadata; + uint8_t upload_fw_id_len; + uint8_t *pupload_fw_id; +} fw_dist_server_upload_start_t; + +typedef struct +{ + uint8_t *pupload_uri; + uint8_t upload_uri_len; + uint8_t *pfw_id; + uint8_t fw_id_len; +} fw_dist_server_upload_oob_start_t; + +typedef struct +{ + uint16_t block_num; + uint8_t *pdata; + uint16_t data_len; +} fw_dist_server_upload_block_data_t; + +typedef enum +{ + FW_UPLOAD_FAIL_REASON_USER_CANCEL, + FW_UPLOAD_FAIL_REASON_TRANSFER_TIMEOUT, + FW_UPLOAD_FAIL_REASON_TRANSFER_ERR, +} fw_upload_fail_reason_t; + +typedef struct +{ + fw_image_t upload_fw_image; + fw_upload_fail_reason_t reason; +} fw_dist_server_upload_fail_t; + +typedef struct +{ + uint8_t *pfw_id; + uint8_t fw_id_len; +} fw_dist_server_fw_delete_t; + +typedef struct +{ + uint8_t *puri; + uint8_t uri_len; + /* app should modify this filed */ + fw_dist_status_code_t *pstatus; +} fw_dist_server_uri_check_t; + +/** @} */ + +/** + * @defgroup FIRMWARE_DISTRIBUTION_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define FW_DIST_CLIENT_RECVS_STATUS 0 //!< @ref fw_dist_client_recvs_status_t +#define FW_DIST_CLIENT_RECVS_LIST 1 //!< @ref fw_dist_client_recvs_list_t +#define FW_DIST_CLIENT_CAPS_STATUS 2 //!< @ref fw_dist_client_caps_status_t +#define FW_DIST_CLIENT_STATUS 3 //!< @ref fw_dist_client_status_t +#define FW_DIST_CLIENT_UPLOAD_STATUS 4 //!< @ref fw_dist_client_upload_status_t +#define FW_DIST_CLIENT_FW_STATUS 5 //!< @ref fw_dist_client_fw_status_t + +typedef struct +{ + uint16_t src; + fw_dist_status_code_t status; + uint16_t recvs_list_cnt; +} fw_dist_client_recvs_status_t; + +typedef struct +{ + uint16_t src; + uint16_t recvs_list_cnt; + uint16_t first_index; + fw_update_node_t *pentries; + uint8_t entries_cnt; +} fw_dist_client_recvs_list_t; + +typedef struct +{ + uint16_t src; + fw_dist_caps_t dist_caps; + uint8_t *psupported_uri_scheme_names; + uint8_t names_len; +} fw_dist_client_caps_status_t; + +typedef struct +{ + uint16_t src; + fw_dist_status_code_t status; + fw_dist_phase_t phase; + uint16_t dist_multicast_addr; + uint16_t dist_appkey_index; + uint8_t dist_ttl; + uint16_t dist_timeout_base; + uint8_t dist_transfer_mode : 2; + uint8_t update_policy : 1; + uint8_t rfu : 5; + uint16_t dist_fw_image_idx; +} fw_dist_client_dist_status_t; + +typedef struct +{ + uint16_t src; + uint8_t status; + fw_upload_phase_t phase; + uint8_t upload_progress; + uint8_t *pupload_fw_id; + uint8_t upload_fw_id_len; +} fw_dist_client_upload_status_t; + +typedef struct +{ + uint16_t src; + uint8_t status; + uint16_t entry_cnt; + uint16_t dist_fw_image_idx; + uint8_t *pfw_id; + uint8_t fw_id_len; +} fw_dist_client_fw_status_t; + +/** @} */ + +/** + * @defgroup FIRMWARE_DISTRIBUTION_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief firmware distribution server register + * @param[in] element_index: element index + * @param[in] model_data_cb: model data callback function + * @return register status + */ +bool fw_dist_server_reg(uint8_t element_index, model_data_cb_pf model_data_cb); + +/** + * @brief add receiver to firmware distribution server + * @param[in] preceiver: receiver to add + * @return add status + */ +bool fw_dist_server_add_receiver(fw_dist_receiver_t *preceiver); + +/** + * @brief check whether receiver is empty + * @return TRUE: empty + * FALSE: not empty + */ +bool fw_dist_server_is_receiver_empty(void); + +/** + * @brief delete all receivers + */ +void fw_dist_server_delete_all_receiver(void); + +/** + * @brief add distribution image + * @return add status + */ +bool fw_dist_server_add_image(fw_image_t *pimage); + +/** + * @brief delete all distribution images + */ +void fw_dist_server_delete_all_image(void); + +/** + * @brief delete distribution image + * @param[in] pfw_id: firmware id + * @param[in] fw_id_len: firmware id length + * @return delete image status + */ +bool fw_dist_server_delete_image(uint8_t *pfw_id, uint8_t fw_id_len); + +/** + * @brief finish cancel firmware distribution server + */ +void fw_dist_server_cancel_done(void); + +/** + * @brief handle blob transfer server data + * @param[in] pmodel_info: pointer to blob transfer server model + * @param[in] type: data callback message type + * @param[in] pargs: data callback values + * @return return value + */ +int32_t fw_dist_handle_blob_server_data(const mesh_model_info_p pmodel_info, uint32_t type, + void *pargs); + +/** + * @brief start firmware distribution + * @param[in] app_key_index: app key index + * @param[in] updata_ttl: update ttl + * @param[in] update_timeout_base: update timeout base value + * @param[in] blob_id: blob id value + * @param[in] pfw_metadata: firmware metadata + * @param[in] metadata_len: metadata length + */ +void fw_dist_server_start(uint16_t app_key_index, uint8_t update_ttl, uint16_t update_timeout_base, + uint8_t blob_id[8], uint8_t *pfw_metadata, uint8_t metadata_len); + +/** + * @brief notify firmware distribution failed + */ +void fw_dist_server_dist_failed(void); + +/** + * @brief set upload received firmware size + * @param[in] upload_recvd_size: upload received firmware size +*/ +void fw_dist_server_set_upload_recvd_size(uint32_t upload_recvd_size); + +/** + * @brief upload firmware use oob done + * @param[in] success: download firmware status + */ +void fw_dist_server_upload_oob_done(bool success); + +/** + * @brief set node updating status + * @param[in] precv: node + * @param[in] update_phase: node update phase + * @param[in] update_status: node update status + * @param[in] trans_status: node transfer status + * @param[in] progress: node update progress, range is 0-100 +*/ +void fw_dist_server_set_updating_status(fw_dist_receiver_t *precv, fw_update_phase_t update_phase, + fw_update_status_code_t update_status, blob_transfer_status_code_t trans_status, + uint8_t trans_progres); +/** @} */ + +/** + * @defgroup FIRMWARE_DISTRIBUTION_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief firmware distribution client register + * @param[in] element_index: element index + * @param[in] model_data_cb: model data callback function + * @return register status + */ +bool fw_dist_client_reg(uint8_t element_index, model_data_cb_pf model_data_cb); + +/** + * @brief add firmware distribution server receivers + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] precvs: receivers need to add + * @param[in] recvs_len: receivers length + * @return send status + */ +mesh_msg_send_cause_t fw_dist_recvs_add(uint16_t dst, uint16_t app_key_index, + fw_dist_receiver_t *precvs, uint8_t recvs_len); + +/** + * @brief delete all firmware distribution server receivers + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_recvs_delete_all(uint16_t dst, uint16_t app_key_index); + +/** + * @brief get firmware distribution server receivers + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] first_index: first index + * @param[in] entries_limit: entries limit + * @return send status + */ +mesh_msg_send_cause_t fw_dist_recvs_get(uint16_t dst, uint16_t app_key_index, uint16_t first_index, + uint16_t entries_limit); + +/** + * @brief get firmware distribution server capabilites + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_caps_get(uint16_t dst, uint16_t app_key_index); + +/** + * @brief get firmware distribution status + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_get(uint16_t dst, uint16_t app_key_index); + +/** + * @brief start firmware distribution + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] start: start parameters + * @param[in] dist_dst_len: distribution destination length + * @return send status + */ +mesh_msg_send_cause_t fw_dist_start(uint16_t dst, uint16_t app_key_index, + fw_dist_start_data_t start, uint8_t dist_dst_len); + +/** + * @brief cancel firmware distribution + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_cancel(uint16_t dst, uint16_t app_key_index); + +/** + * @brief apply firmware distribution + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_apply(uint16_t dst, uint16_t app_key_index); + +/** + * @brief get firmware upload status + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_upload_get(uint16_t dst, uint16_t app_key_index); + +/** + * @brief start firmware upload + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] upload_ttl: upload ttl + * @param[in] upload_timeout_base: upload timeout base + * @param[in] blob_id: blob id + * @param[in] upload_fw_size: upload firmware size + * @param[in] pmetadata: firmware metadata + * @param[in] metadata_len: metadata length + * @param[in] pfw_id: firmware id + * @param[in] fw_id_len: firmware id length + * @return send status + */ +mesh_msg_send_cause_t fw_dist_upload_start(uint16_t dst, uint16_t app_key_index, uint8_t upload_ttl, + uint16_t upload_timeout_base, uint8_t blob_id[8], uint32_t upload_fw_size, uint8_t *pmetadata, + uint8_t metadata_len, uint8_t *pfw_id, uint8_t fw_id_len); +/** + * @brief start firmware oob upload + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] pupload_uri: upload uri + * @param[in] upload_uri_len: upload uri length + * @param[in] pfw_id: firmware id + * @param[in] fw_id_len: firmware id length + * @return send status + */ +mesh_msg_send_cause_t fw_dist_upload_oob_start(uint16_t dst, uint16_t app_key_index, + uint8_t *pupload_uri, uint8_t upload_uri_len, uint8_t *pfw_id, uint8_t fw_id_len); + +/** + * @brief cancel firmware upload + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_upload_cancel(uint16_t dst, uint16_t app_key_index); + +/** + * @brief get firmware + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] pfw_id: firmware id + * @param[in] fw_id_len: firmware id length + * @return send status + */ +mesh_msg_send_cause_t fw_dist_fw_get(uint16_t dst, uint16_t app_key_index, uint8_t *pfw_id, + uint8_t fw_id_len); + +/** + * @brief get firmware by index + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] dist_fw_image_index: firmware index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_fw_get_by_index(uint16_t dst, uint16_t app_key_index, + uint16_t dist_fw_image_index); + +/** + * @brief delete firmware image + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] pfw_id: firmware id + * @param[in] fw_id_len: firmware id length + * @return send status + */ +mesh_msg_send_cause_t fw_dist_fw_delete(uint16_t dst, uint16_t app_key_index, uint8_t *pfw_id, + uint8_t fw_id_len); + +/** + * @brief delete all firmware images + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_dist_fw_delete_all(uint16_t dst, uint16_t app_key_index); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* MESH_DFU */ + +#endif /* _FIRMWARE_DISTRIBUTION_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution_client.c new file mode 100644 index 00000000..8f8e0608 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution_client.c @@ -0,0 +1,406 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file firmware_distribution_client.c +* @brief Source file for firmware distribution client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-5-21 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "mesh_api.h" +#include "firmware_distribution.h" + +#if MESH_DFU +mesh_model_info_t fw_dist_client; + +static mesh_msg_send_cause_t fw_dist_server_send(uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = &fw_dist_client; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t fw_dist_recvs_add(uint16_t dst, uint16_t app_key_index, + fw_dist_receiver_t *precvs, uint8_t recvs_len) +{ + uint16_t msg_len = sizeof(fw_dist_recvs_add_t) + sizeof(fw_dist_receiver_t) * recvs_len; + fw_dist_recvs_add_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + printe("fw_dist_recvs_add: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_DIST_RECVS_ADD); + memcpy(pmsg->entries, precvs, recvs_len); + mesh_msg_send_cause_t ret = fw_dist_server_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_dist_recvs_delete_all(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_recvs_delete_all_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_RECVS_DELETE_ALL); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_recvs_get(uint16_t dst, uint16_t app_key_index, uint16_t first_index, + uint16_t entries_limit) +{ + fw_dist_recvs_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_RECVS_GET); + msg.first_index = first_index; + msg.entries_limit = entries_limit; + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_caps_get(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_caps_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_CAPS_GET); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_get(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_GET); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_start(uint16_t dst, uint16_t app_key_index, + fw_dist_start_data_t start, uint8_t dist_dst_len) +{ + fw_dist_start_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_START); + msg.dist_app_key_index = start.dist_app_key_index; + msg.dist_ttl = start.dist_ttl; + msg.dist_timeout_base = start.dist_timeout_base; + msg.dist_transfer_mode = start.dist_transfer_mode; + msg.update_policy = start.update_policy; + msg.rfu = 0; + msg.dist_fw_image_idx = start.dist_fw_image_idx; + memcpy(msg.dist_multicast_addr, start.dist_multicast_addr, dist_dst_len); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, MEMBER_OFFSET(fw_dist_start_t, + dist_multicast_addr) + dist_dst_len); +} + +mesh_msg_send_cause_t fw_dist_cancel(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_cancel_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_CANCEL); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_apply(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_apply_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_APPLY); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_upload_get(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_upload_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_UPLOAD_GET); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_upload_start(uint16_t dst, uint16_t app_key_index, uint8_t upload_ttl, + uint16_t upload_timeout_base, uint8_t blob_id[8], uint32_t upload_fw_size, uint8_t *pmetadata, + uint8_t metadata_len, uint8_t *pfw_id, uint8_t fw_id_len) +{ + uint16_t msg_len = sizeof(fw_dist_upload_start_t) + metadata_len + fw_id_len; + fw_dist_upload_start_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + printe("fw_dist_upload_start: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_DIST_UPLOAD_START); + pmsg->upload_ttl = upload_ttl; + pmsg->upload_timeout_base = upload_timeout_base; + memcpy(pmsg->blob_id, blob_id, 8); + pmsg->upload_fw_size = upload_fw_size; + pmsg->upload_fw_metadata_len = metadata_len; + uint8_t *pdata = pmsg->upload_fw_info; + memcpy(pdata, pmetadata, metadata_len); + pdata += metadata_len; + memcpy(pdata, pfw_id, fw_id_len); + + mesh_msg_send_cause_t ret = fw_dist_server_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_dist_upload_oob_start(uint16_t dst, uint16_t app_key_index, + uint8_t *pupload_uri, uint8_t upload_uri_len, uint8_t *pfw_id, uint8_t fw_id_len) +{ + uint16_t msg_len = sizeof(fw_dist_upload_oob_start_t) + upload_uri_len + fw_id_len; + fw_dist_upload_oob_start_t *pmsg = plt_malloc(msg_len, RAM_TYPE_BUFFER_ON); + if (NULL == pmsg) + { + printe("fw_dist_upload_oob_start: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_DIST_UPLOAD_OOB_START); + pmsg->upload_uri_len = upload_uri_len; + uint8_t *pdata = pmsg->upload_fw_info; + memcpy(pdata, pupload_uri, upload_uri_len); + pdata += upload_uri_len; + memcpy(pdata, pfw_id, fw_id_len); + + mesh_msg_send_cause_t ret = fw_dist_server_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_dist_upload_cancel(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_upload_cancel_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_UPLOAD_CANCEL); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_fw_get(uint16_t dst, uint16_t app_key_index, uint8_t *pfw_id, + uint8_t fw_id_len) +{ + uint16_t msg_len = sizeof(fw_dist_fw_get_t) + fw_id_len; + fw_dist_fw_get_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + printe("fw_dist_fw_get: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_DIST_FW_GET); + memcpy(pmsg->fw_id, pfw_id, fw_id_len); + + mesh_msg_send_cause_t ret = fw_dist_server_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_dist_fw_get_by_index(uint16_t dst, uint16_t app_key_index, + uint16_t dist_fw_image_index) +{ + fw_dist_fw_get_by_index_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_FW_GET_BY_INDEX); + msg.dist_fw_image_idx = dist_fw_image_index; + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_dist_fw_delete(uint16_t dst, uint16_t app_key_index, uint8_t *pfw_id, + uint8_t fw_id_len) +{ + uint16_t msg_len = sizeof(fw_dist_fw_delete_t) + fw_id_len; + fw_dist_fw_delete_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + printe("fw_dist_fw_delete: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_DIST_FW_DELETE); + memcpy(pmsg->fw_id, pfw_id, fw_id_len); + + mesh_msg_send_cause_t ret = fw_dist_server_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_dist_fw_delete_all(uint16_t dst, uint16_t app_key_index) +{ + fw_dist_fw_delete_all_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_DIST_FW_DELETE_ALL); + + return fw_dist_server_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +bool fw_dist_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_FW_DIST_RECVS_STATUS: + { + fw_dist_recvs_status_t *pmsg = (fw_dist_recvs_status_t *)pbuffer; + if (NULL != fw_dist_client.model_data_cb) + { + fw_dist_client_recvs_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.status = pmsg->status; + status_data.recvs_list_cnt = pmsg->recvs_list_cnt; + fw_dist_client.model_data_cb(&fw_dist_client, FW_DIST_CLIENT_RECVS_STATUS, &status_data); + } + data_uart_debug("receive fw dist recivers status: src 0x%04x, status %d, list count %d", + pmesh_msg->src, pmsg->status, pmsg->recvs_list_cnt); + } + break; + case MESH_MSG_FW_DIST_RECVS_LIST: + { + fw_dist_recvs_list_t *pmsg = (fw_dist_recvs_list_t *)pbuffer; + if (NULL != fw_dist_client.model_data_cb) + { + fw_dist_client_recvs_list_t list_data; + list_data.src = pmesh_msg->src; + list_data.recvs_list_cnt = pmsg->recvs_list_cnt; + list_data.first_index = pmsg->first_index; + list_data.pentries = pmsg->entries; + list_data.entries_cnt = (pmesh_msg->msg_len - sizeof(fw_dist_recvs_list_t)) / sizeof( + fw_update_node_t); + fw_dist_client.model_data_cb(&fw_dist_client, FW_DIST_CLIENT_RECVS_LIST, &list_data); + } + data_uart_debug("receive fw dist receivers list: src 0x%04x, recvs_list_cnt %d, first_index %d\r\n", + pmesh_msg->src, pmsg->recvs_list_cnt, pmsg->first_index); + + fw_update_node_t *pentries = pmsg->entries; + for (uint8_t i = 0; + i < (pmesh_msg->msg_len - sizeof(fw_dist_recvs_list_t)) / sizeof(fw_update_node_t); ++i) + { + data_uart_debug("addr 0x%04x, retrieved_update_phase %d, update_status %d, transfer_status %d, transfer_progress %d, update_fw_image_idx %d\r\n", + pentries->addr, pentries->retrieved_update_phase, pentries->update_status, + pentries->transfer_status, pentries->transfer_progress, pentries->update_fw_image_idx); + pentries ++; + } + } + break; + case MESH_MSG_FW_DIST_CAPS_STATUS: + { + fw_dist_caps_status_t *pmsg = (fw_dist_caps_status_t *)pbuffer; + if (NULL != fw_dist_client.model_data_cb) + { + fw_dist_client_caps_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.dist_caps = pmsg->dist_caps; + status_data.psupported_uri_scheme_names = pmsg->supported_uri_scheme_names; + status_data.names_len = pmesh_msg->msg_len - sizeof(fw_dist_caps_status_t); + fw_dist_client.model_data_cb(&fw_dist_client, FW_DIST_CLIENT_CAPS_STATUS, &status_data); + } + + data_uart_debug("receive fw dist capabilites: src 0x%04x max_dist_recvs_list_size %d, max_fw_images_list_size %d, max_fw_image_size %d, max_upload_spcace %d, remaining_upload_space %d, oob_retrieval_supported %d, supported_uri_scheme_names = \r\n", + pmesh_msg->src, pmsg->dist_caps.max_dist_recvs_list_size, pmsg->dist_caps.max_fw_images_list_size, + pmsg->dist_caps.max_fw_image_size, pmsg->dist_caps.max_upload_spcace, + pmsg->dist_caps.remaining_upload_space, pmsg->dist_caps.oob_retrieval_supported); + + data_uart_dump(pmsg->supported_uri_scheme_names, + pmesh_msg->msg_len - sizeof(fw_dist_caps_status_t)); + } + break; + case MESH_MSG_FW_DIST_STATUS: + { + fw_dist_status_t *pmsg = (fw_dist_status_t *)pbuffer; + if (NULL != fw_dist_client.model_data_cb) + { + fw_dist_client_dist_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.status = pmsg->status; + status_data.phase = pmsg->phase; + status_data.dist_multicast_addr = pmsg->dist_multicast_addr; + status_data.dist_appkey_index = pmsg->dist_appkey_index; + status_data.dist_ttl = pmsg->dist_ttl; + status_data.dist_timeout_base = pmsg->dist_timeout_base; + status_data.dist_transfer_mode = pmsg->dist_transfer_mode; + status_data.update_policy = pmsg->update_policy; + status_data.rfu = 0; + status_data.dist_fw_image_idx = pmsg->dist_fw_image_idx; + fw_dist_client.model_data_cb(&fw_dist_client, FW_DIST_CLIENT_STATUS, &status_data); + } + + data_uart_debug("receive fw dist status: src 0x%04x, status %d, phase %d, dist_multicast_addr 0x%04x, dist_appkey_index 0x%04x, dist_ttl %d, dist_timeout_base %d, dist_transfer_mode %d, update_policy %d, dist_fw_image_idx %d\r\n", + pmesh_msg->src, pmsg->status, pmsg->phase, pmsg->dist_multicast_addr, pmsg->dist_appkey_index, + pmsg->dist_ttl, pmsg->dist_timeout_base, pmsg->dist_transfer_mode, pmsg->update_policy, + pmsg->dist_fw_image_idx); + } + break; + case MESH_MSG_FW_DIST_UPLOAD_STATUS: + { + fw_dist_upload_status_t *pmsg = (fw_dist_upload_status_t *)pbuffer; + if (NULL != fw_dist_client.model_data_cb) + { + fw_dist_client_upload_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.status = pmsg->status; + status_data.phase = pmsg->phase; + status_data.upload_progress = pmsg->upload_progress; + status_data.pupload_fw_id = pmsg->upload_fw_id; + status_data.upload_fw_id_len = pmesh_msg->msg_len - sizeof(fw_dist_upload_status_t); + + fw_dist_client.model_data_cb(&fw_dist_client, FW_DIST_CLIENT_UPLOAD_STATUS, &status_data); + } + + data_uart_debug("receive fw dist upload status: src 0x%04x, status %d, phase %d, upload_progress %d, upload_fw_id = ", + pmesh_msg->src, pmsg->status, pmsg->phase, pmsg->upload_progress); + data_uart_dump(pmsg->upload_fw_id, pmesh_msg->msg_len - sizeof(fw_dist_upload_status_t)); + } + break; + case MESH_MSG_FW_DIST_FW_STATUS: + { + fw_dist_fw_status_t *pmsg = (fw_dist_fw_status_t *)pbuffer; + if (NULL != fw_dist_client.model_data_cb) + { + fw_dist_client_fw_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.status = pmsg->status; + status_data.entry_cnt = pmsg->entry_cnt; + status_data.dist_fw_image_idx = pmsg->dist_fw_image_idx; + status_data.pfw_id = pmsg->fw_id; + status_data.fw_id_len = pmesh_msg->msg_len - sizeof(fw_dist_fw_status_t); + + fw_dist_client.model_data_cb(&fw_dist_client, FW_DIST_CLIENT_FW_STATUS, &status_data); + } + + data_uart_debug("receive fw dist fw status: src 0x%04x, status %d, entry_cnt %d, dw_fw_image_idx %d, fw_id = ", + pmesh_msg->src, pmsg->status, pmsg->entry_cnt, pmsg->dist_fw_image_idx); + data_uart_dump(pmsg->fw_id, pmesh_msg->msg_len - sizeof(fw_dist_fw_status_t)); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool fw_dist_client_reg(uint8_t element_index, model_data_cb_pf model_data_cb) +{ + fw_dist_client.model_id = MESH_MODEL_FW_DIST_CLIENT; + fw_dist_client.model_receive = fw_dist_client_receive; + fw_dist_client.model_data_cb = model_data_cb; + return mesh_model_reg(element_index, &fw_dist_client); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update.h new file mode 100644 index 00000000..57a3d15b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update.h @@ -0,0 +1,462 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file firmware_update.h +* @brief Head file for firmware update models. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-5-21 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _FIRMWARE_UPDATE_H +#define _FIRMWARE_UPDATE_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "mesh_api.h" + +#if MESH_DFU + +BEGIN_DECLS + +/** + * @addtogroup FIRMWARE_UPDATE + * @{ + */ + +/** + * @defgroup FIRMWARE_UPDATE_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_FW_UPDATE_INFO_GET 0xB71B +#define MESH_MSG_FW_UPDATE_INFO_STATUS 0x7C +#define MESH_MSG_FW_UPDATE_FW_METADATA_CHECK 0x7B +#define MESH_MSG_FW_UPDATE_FW_METADATA_STATUS 0x7A +#define MESH_MSG_FW_UPDATE_GET 0xB71C +#define MESH_MSG_FW_UPDATE_START 0xB71D +#define MESH_MSG_FW_UPDATE_CANCEL 0xB71E +#define MESH_MSG_FW_UPDATE_APPLY 0xB71F +#define MESH_MSG_FW_UPDATE_STATUS 0x70 +/** @} */ + +/** + * @defgroup FIRMWARE_UPDATE_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_FW_UPDATE_SERVER 0xBF44FFFF +#define MESH_MODEL_FW_UPDATE_CLIENT 0xBF45FFFF +/** @} */ + +/** + * @defgroup FIRMWARE_UPDATE_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define FW_VERSION_MAX_LEN 106 + +typedef struct +{ + uint16_t company_id; + uint8_t version[FW_VERSION_MAX_LEN]; +} _PACKED4_ fw_id_t; + +typedef struct +{ + fw_id_t fw_id; + uint8_t fw_id_len; + uint8_t update_uri_len; + uint8_t update_uri[255]; +} fw_info_t; + +enum +{ + FW_UPDATE_PHASE_IDLE, + FW_UPDATE_PHASE_TRANSFER_ERR, + FW_UPDATE_PHASE_TRANSFER_ACTIVE, + FW_UPDATE_PHASE_VERIFYING_UPDATE, + FW_UPDATE_PHASE_VERIFICATION_SUCCEEDED, + FW_UPDATE_PHASE_VERIFICATION_FAILED, + FW_UPDATE_PHASE_APPLYING_UPDATE, +} _SHORT_ENUM_; +typedef uint8_t fw_update_phase_t; + +enum +{ + FW_UPDATE_ADDI_INFO_COMP_NO_CHANGE, + FW_UPDATE_ADDI_INFO_COMP_CHANGED_AND_NOT_SUPPORTED_RMT_PROV, + FW_UPDATE_ADDI_INFO_COMP_CHANGED_AND_SUPPORT_RMT_PROV, + FW_UPDATE_ADDI_INFO_NODE_UNPROVED, +} _SHORT_ENUM_; +typedef uint8_t fw_update_addi_info_t; + +enum +{ + FW_RETRIEVED_UPDATE_PHASE_IDLE, + FW_RETRIEVED_UPDATE_PHASE_TRANSFER_ERR, + FW_RETRIEVED_UPDATE_PHASE_TRANSFER_ACTIVE, + FW_RETRIEVED_UPDATE_PHASE_VERIFYING_UPDATE, + FW_RETRIEVED_UPDATE_PHASE_VERIFICATION_SUCCEEDED, + FW_RETRIEVED_UPDATE_PHASE_VERIFICATION_FAILED, + FW_RETRIEVED_UPDATE_PHASE_APPLYING_UPDATE, + FW_RETRIEVED_UPDATE_PHASE_TRANSFER_CANCELED, + FW_RETRIEVED_UPDATE_PHASE_APPLY_SUCCESS, + FW_RETRIEVED_UPDATE_PHASE_APPLY_FAILED, + FW_RETRIEVED_UPDATE_PHASE_APPLY_UNKNOWN, +} _SHORT_ENUM_; +typedef uint8_t fw_retrieved_update_phase_t; + +enum +{ + FW_UPDATE_STATUS_SUCCESS, + FW_UPDATE_STATUS_INSUFFICIENT_RESOURCES, + FW_UPDATE_STATUS_WRONG_PHASE, + FW_UPDATE_STATUS_INTERNAL_ERR, + FW_UPDATE_STATUS_WRONG_FW_INDEX, + FW_UPDATE_STATUS_METADATA_CHECK_FAILED, + FW_UPDATE_STATUS_TEMP_UNAVAIL, + FW_UPDATE_STATUS_BLOB_TRANSFER_BUSY, +} _SHORT_ENUM_; +typedef uint8_t fw_update_status_code_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_INFO_GET)]; + uint8_t first_index; + uint8_t entries_limit; +} _PACKED4_ fw_update_info_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_INFO_STATUS)]; + uint8_t fw_info_list_cnt; + uint8_t first_index; + uint8_t fw_info_list[0]; +} _PACKED4_ fw_update_info_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_FW_METADATA_CHECK)]; + uint8_t fw_image_idx; + uint8_t fw_metadata[0]; +} _PACKED4_ fw_update_fw_metadata_check_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_FW_METADATA_STATUS)]; + uint8_t status : 3; + uint8_t addi_info : 5; + uint8_t fw_image_idx; +} _PACKED4_ fw_update_fw_metadata_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_GET)]; +} _PACKED4_ fw_update_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_START)]; + uint8_t update_ttl; + uint16_t update_timeout_base; + uint8_t blob_id[8]; + uint8_t fw_image_idx; + uint8_t fw_metadata[0]; +} _PACKED4_ fw_update_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_CANCEL)]; +} _PACKED4_ fw_update_cancel_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_APPLY)]; +} _PACKED4_ fw_update_apply_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_FW_UPDATE_STATUS)]; + uint8_t status : 3; + uint8_t rfu1 : 2; + uint8_t update_phase : 3; + uint8_t update_ttl; + uint8_t addi_info : 5; + uint8_t rfu2 : 3; + uint16_t update_timeout_base; + uint8_t blob_id[8]; + uint8_t update_fw_image_idx; +} _PACKED4_ fw_update_status_t; +/** @} */ + +/** + * @defgroup FIRMWARE_UPDATE_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +typedef struct +{ + plt_list_t fw_info_list; + fw_update_phase_t update_phase; + uint8_t update_ttl; + fw_update_addi_info_t addi_info; + uint16_t update_timeout_base; + uint8_t blob_id[8]; + uint8_t update_fw_image_idx; + uint8_t fw_metadata[255]; +} fw_update_server_ctx_t; + +extern fw_update_server_ctx_t fw_update_server_ctx; + +#define FW_UPDATE_SERVER_METADATA_CHECK 0 //!< @ref fw_update_server_metadata_check_t +#define FW_UPDATE_SERVER_START 1 //!< @ref fw_update_server_start_t +#define FW_UPDATE_SERVER_VERIFY 2 //!< @ref fw_update_server_verify_t +#define FW_UPDATE_SERVER_VERIFY_CANCEL 3 //!< @ref fw_update_server_verify_cancel_t +#define FW_UPDATE_SERVER_APPLY 4 //!< @ref fw_update_server_apply_t +#define FW_UPDATE_SERVER_BLOCK_DATA 5 //!< @ref fw_update_server_block_data_t +#define FW_UPDATE_SERVER_FAIL 6 //!< @ref fw_update_server_fail_t + + +typedef struct +{ + uint8_t fw_image_idx; + uint8_t *pmetadata; + uint8_t metadata_len; + /* upper layer should set these field */ + fw_update_status_code_t *pstatus; + fw_update_addi_info_t *paddi_info; +} fw_update_server_metadata_check_t; + +typedef struct +{ + uint8_t fw_image_idx; + /* upper layer should set these field */ + bool *pcan_update; +} fw_update_server_start_t; + +typedef struct +{ + uint8_t fw_image_idx; +} fw_update_server_verify_t; + +typedef struct +{ + uint8_t fw_image_idx; +} fw_update_server_verify_cancel_t; + +typedef struct +{ + uint8_t fw_image_idx; + /* upper layer should set these field */ + bool *pcan_apply; +} fw_update_server_apply_t; + +typedef struct +{ + uint16_t block_num; + uint8_t *pdata; + uint16_t data_len; +} fw_update_server_block_data_t; + +typedef enum +{ + FW_UPDATE_FAIL_REASON_USER_CANCEL, + FW_UPDATE_FAIL_REASON_TRANSFER_TIMEOUT, + FW_UPDATE_FAIL_REASON_TRANSFER_ERR, +} fw_update_fail_reason_t; + +typedef struct +{ + uint8_t fw_image_index; + fw_update_fail_reason_t reason; +} fw_update_server_fail_t; +/** @} */ + +/** + * @defgroup FIRMWARE_UPDATE_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define FW_UPDATE_CLIENT_INFO_STATUS 0 //!< @ref fw_update_client_info_status_t +#define FW_UPDATE_CLIENT_FW_METADATA_STATUS 1 //!< @ref fw_update_client_fw_metadata_status_t +#define FW_UPDATE_CLIENT_STATUS 2 //!< @ref fw_update_client_status_t + +typedef struct +{ + uint16_t src; + uint8_t fw_info_list_cnt; + uint8_t first_index; + fw_info_t *pfw_info; + uint8_t fw_info_cnt; +} fw_update_client_info_status_t; + +typedef struct +{ + uint16_t src; + fw_update_status_code_t status; + fw_update_addi_info_t addi_info; + uint8_t update_fw_image_index; +} fw_update_client_fw_metadata_status_t; + +typedef struct +{ + uint16_t src; + uint16_t app_key_index; + fw_update_status_code_t status; + fw_update_phase_t update_phase; + uint8_t update_ttl; + fw_update_addi_info_t addi_info; + uint16_t update_timeout_base; + uint8_t blob_id[8]; + uint8_t update_fw_image_index; +} fw_update_client_status_t; +/** @} */ + +/** + * @defgroup FIRMWARE_UPDATE_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief firmware update server register + * @param[in] element_index: element index + * @param[in] model_data_cb: model data callback function + * @return register status + */ +bool fw_update_server_reg(uint8_t element_index, model_data_cb_pf model_data_cb); + +/** + * @brief load firmware update server + * @param[in] pfw_metadata: firmware metadata + * @param[in] metadata_len: firmware metadata length + * @param[in] fw_image_index: firmware image index + * @param[in] update_ttl: update ttl + * @param[in] update_timeout_base: update timeout base + * @param[in] blob_id: blob id + * @return load status + */ +bool fw_update_server_load(uint8_t *pfw_metadata, uint8_t metadata_len, uint8_t fw_image_index, + uint8_t update_ttl, uint8_t update_timeout_base, uint8_t blob_id[8]); +/** + * @brief add firmware update information + * @param[in] pfw_id: firmware id + * @param[in] fw_id_len: firmware id length + * @param[in] pupdate_uri: update uri value + * @param[in] update_uri_len: update uri length + * @return add status + */ +bool fw_update_server_add_info(fw_id_t *pfw_id, uint8_t fw_id_len, + uint8_t *pupdate_uri, uint8_t update_uri_len); + +/** + * @brief set firmware verify result + * @param[in] success: TRUE: verify success + * FALSE: verify failed + */ +void fw_update_server_set_verify_result(bool success); + +/** + * @brief clear firmware update server + */ +void fw_update_server_clear(void); + +/** + * @brief handle blob server data + * @param[in] pmodel_info: blob transfer server model + * @param[in] type: data callback message type + * @param[in] pargs: data callback value + * @return handle result + */ +int32_t fw_update_handle_blob_server_data(const mesh_model_info_p pmodel_info, uint32_t type, + void *pargs); +/** @} */ + +/** + * @defgroup FIRMWARE_UPDATE_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ +/** + * @brief firmware update client register + * @param[in] element_index: element index + * @param[in] model_data_cb: model data callback function + * @return register status + */ +bool fw_update_client_reg(uint8_t element_index, model_data_cb_pf model_data_cb); + +/** + * @brief get firmware update information + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] first_index: first index + * @param[in] entries_limit: entries limit + * @return send status + */ +mesh_msg_send_cause_t fw_update_info_get(uint16_t dst, uint16_t app_key_index, uint8_t first_index, + uint8_t entries_limit); + +/** + * @brief check firmware metadata + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] update_fw_image_idx: update firmware image index + * @param[in] pfw_metadata: firmware metadata + * @param[in] metadata_len: firmware metadata length + * @return send status + */ +mesh_msg_send_cause_t fw_update_fw_metadata_check(uint16_t dst, uint16_t app_key_index, + uint8_t update_fw_image_idx, uint8_t *pfw_metadata, uint8_t metadata_len); + +/** + * @brief get firmware update status + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_update_get(uint16_t dst, uint16_t app_key_index); + +/** + * @brief start firmware update + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @param[in] update_ttl: update ttl value + * @param[in] update_timeout_base: update timeout base + * @param[in] blob_id: blob id + * @param[in] update_fw_image_idx: update firmware image index + * @param[in] pfw_metadata: firmware metadata + * @param[in] metadata_len: firmware metadata length + * @return send status + */ +mesh_msg_send_cause_t fw_update_start(uint16_t dst, uint16_t app_key_index, uint8_t update_ttl, + uint16_t update_timeout_base, uint8_t blob_id[8], uint8_t update_fw_image_idx, + uint8_t *pfw_metadata, uint8_t metadata_len); + +/** + * @brief cancel firmware update + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_update_cancel(uint16_t dst, uint16_t app_key_index); + +/** + * @brief apply firmware update + * @param[in] dst: remote address + * @param[in] app_key_index: app key index + * @return send status + */ +mesh_msg_send_cause_t fw_update_apply(uint16_t dst, uint16_t app_key_index); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* MESH_DFU */ + +#endif /* _FIRMWARE_UPDATE_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update_client.c new file mode 100644 index 00000000..5977f4ab --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update_client.c @@ -0,0 +1,257 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file firmware_update_client.c +* @brief Source file for firmware update client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-5-21 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "mesh_api.h" +#include "firmware_update.h" + +#if MESH_DFU +mesh_model_info_t fw_update_client; + +static mesh_msg_send_cause_t fw_update_client_send(uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = &fw_update_client; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t fw_update_info_get(uint16_t dst, uint16_t app_key_index, uint8_t first_index, + uint8_t entries_limit) +{ + fw_update_info_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_UPDATE_INFO_GET); + msg.first_index = first_index; + msg.entries_limit = entries_limit; + return fw_update_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_update_fw_metadata_check(uint16_t dst, uint16_t app_key_index, + uint8_t update_fw_image_idx, uint8_t *pfw_metadata, uint8_t metadata_len) +{ + uint16_t msg_len = sizeof(fw_update_fw_metadata_check_t) + metadata_len; + fw_update_fw_metadata_check_t *pmsg = (fw_update_fw_metadata_check_t *)plt_malloc(msg_len, + RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + printe("fw_update_fw_metadata_check: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_UPDATE_FW_METADATA_CHECK); + pmsg->fw_image_idx = update_fw_image_idx; + memcpy(pmsg->fw_metadata, pfw_metadata, metadata_len); + mesh_msg_send_cause_t ret = fw_update_client_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_update_get(uint16_t dst, uint16_t app_key_index) +{ + fw_update_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_UPDATE_GET); + return fw_update_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(fw_update_get_t)); +} + +mesh_msg_send_cause_t fw_update_start(uint16_t dst, uint16_t app_key_index, uint8_t update_ttl, + uint16_t update_timeout_base, uint8_t blob_id[8], uint8_t update_fw_image_idx, + uint8_t *pfw_metadata, uint8_t metadata_len) +{ + uint16_t msg_len = sizeof(fw_update_start_t) + metadata_len; + fw_update_start_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + printe("fw_update_start: failed, out of memory"); + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_FW_UPDATE_START); + pmsg->update_ttl = update_ttl; + pmsg->update_timeout_base = update_timeout_base; + memcpy(pmsg->blob_id, blob_id, 8); + pmsg->fw_image_idx = update_fw_image_idx; + if (metadata_len > 0) + { + memcpy(pmsg->fw_metadata, pfw_metadata, metadata_len); + } + mesh_msg_send_cause_t ret = fw_update_client_send(dst, app_key_index, (uint8_t *)pmsg, msg_len); + + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t fw_update_cancel(uint16_t dst, uint16_t app_key_index) +{ + fw_update_cancel_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_UPDATE_CANCEL); + return fw_update_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t fw_update_apply(uint16_t dst, uint16_t app_key_index) +{ + fw_update_apply_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_FW_UPDATE_APPLY); + return fw_update_client_send(dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +bool fw_update_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_FW_UPDATE_INFO_STATUS: + { + fw_update_info_status_t *pmsg = (fw_update_info_status_t *)pbuffer; + uint8_t *pdata = (uint8_t *)pmsg->fw_info_list; + data_uart_debug("receive fw update info status: src 0x%04x, fw_info_list_count %d, first_index %d\r\n", + pmesh_msg->src, pmsg->fw_info_list_cnt, pmsg->first_index); + uint8_t fw_info_cnt = 0; + fw_info_t *pfw_info = NULL; + uint16_t data_len = pmesh_msg->msg_len - sizeof(fw_update_info_status_t); + if (data_len > 0) + { + while ((pdata - pmsg->fw_info_list) < data_len) + { + uint8_t fw_id_len = *pdata++; + pdata += fw_id_len; + uint8_t uri_len = *pdata ++; + pdata += uri_len; + fw_info_cnt ++; + } + } + + if (fw_info_cnt > 0) + { + pdata = pmsg->fw_info_list; + pfw_info = plt_malloc(fw_info_cnt * sizeof(fw_info_t), RAM_TYPE_DATA_ON); + if (NULL == pfw_info) + { + printe("receive fw update info status: out of memory"); + return true; + } + + for (uint8_t i = 0; i < fw_info_cnt; ++i) + { + pfw_info[i].fw_id_len = *pdata++; + // pdata += 2; + data_uart_debug("entry\r\n"); + memcpy(&pfw_info[i].fw_id, pdata, pfw_info[i].fw_id_len); + data_uart_debug(" firmware id 0x"); + data_uart_dump(pdata, pfw_info[i].fw_id_len); + pdata += pfw_info[i].fw_id_len; + pfw_info[i].update_uri_len = *pdata ++; + memcpy(pfw_info[i].update_uri, pdata, pfw_info[i].update_uri_len); + data_uart_debug(" update uri 0x"); + data_uart_dump(pdata, pfw_info[i].update_uri_len); + pdata += pfw_info[i].update_uri_len; + } + } + + if (NULL != fw_update_client.model_data_cb) + { + fw_update_client_info_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.fw_info_list_cnt = pmsg->fw_info_list_cnt; + status_data.first_index = pmsg->first_index; + status_data.pfw_info = pfw_info; + status_data.fw_info_cnt = fw_info_cnt; + fw_update_client.model_data_cb(&fw_update_client, FW_UPDATE_CLIENT_INFO_STATUS, &status_data); + } + + if (NULL != pfw_info) + { + plt_free(pfw_info, RAM_TYPE_DATA_ON); + } + } + break; + case MESH_MSG_FW_UPDATE_FW_METADATA_STATUS: + if (pmesh_msg->msg_len == sizeof(fw_update_fw_metadata_status_t)) + { + fw_update_fw_metadata_status_t *pmsg = (fw_update_fw_metadata_status_t *)pbuffer; + if (NULL != fw_update_client.model_data_cb) + { + fw_update_client_fw_metadata_status_t metadata_data; + metadata_data.src = pmesh_msg->src; + metadata_data.status = pmsg->status; + metadata_data.addi_info = pmsg->addi_info; + metadata_data.update_fw_image_index = pmsg->fw_image_idx; + fw_update_client.model_data_cb(&fw_update_client, FW_UPDATE_CLIENT_FW_METADATA_STATUS, + &metadata_data); + } + data_uart_debug("receive fw metadata status: src 0x%04x, status %d, addi_info %d, fw_image_idx %d\r\n", + pmesh_msg->src, pmsg->status, pmsg->addi_info, pmsg->fw_image_idx); + } + break; + case MESH_MSG_FW_UPDATE_STATUS: + { + fw_update_status_t *pmsg = (fw_update_status_t *)pbuffer; + fw_update_client_status_t status_data; + memset(&status_data, 0, sizeof(status_data)); + status_data.src = pmesh_msg->src; + status_data.app_key_index = pmesh_msg->app_key_index; + status_data.status = pmsg->status; + + if (pmesh_msg->msg_len == sizeof(fw_update_status_t)) + { + status_data.update_phase = pmsg->update_phase; + status_data.update_ttl = pmsg->update_ttl; + status_data.addi_info = pmsg->addi_info; + status_data.update_timeout_base = pmsg->update_timeout_base; + memcpy(status_data.blob_id, pmsg->blob_id, 8); + status_data.update_fw_image_index = pmsg->update_fw_image_idx; + data_uart_debug("receive fw update status: src 0x%04x, status %d, update_phase %d, update_ttl %d, addi_info %d, update_timeout_base %d, update_fw_image_idx %d, blob_id 0x", + pmesh_msg->src, pmsg->status, pmsg->update_phase, pmsg->update_ttl, pmsg->addi_info, + pmsg->update_timeout_base, + pmsg->update_fw_image_idx); + data_uart_dump(pmsg->blob_id, 8); + } + else + { + data_uart_debug("receive fw update status: src 0x%04x, status %d, update_phase %d", pmsg->status, + pmesh_msg->src, pmsg->update_phase); + } + + if (NULL != fw_update_client.model_data_cb) + { + fw_update_client.model_data_cb(&fw_update_client, FW_UPDATE_CLIENT_STATUS, &status_data); + } + } + break; + default: + ret = false; + break; + } + + return ret; +} + +bool fw_update_client_reg(uint8_t element_index, model_data_cb_pf model_data_cb) +{ + fw_update_client.model_id = MESH_MODEL_FW_UPDATE_CLIENT; + fw_update_client.model_receive = fw_update_client_receive; + fw_update_client.model_data_cb = model_data_cb; + return mesh_model_reg(element_index, &fw_update_client); +} +#endif /* MESH_DFU */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_admin_property_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_admin_property_server.c new file mode 100644 index 00000000..6f008df1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_admin_property_server.c @@ -0,0 +1,308 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_admin_property_server.c +* @brief Source file for generic admin property server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-06-28 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_property.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +typedef struct +{ + generic_property_db_t *pproperties; + uint16_t num_properties; +} generic_admin_property_info_t; + +void generic_admin_property_server_set_db(mesh_model_info_t *pmodel_info, + generic_property_db_t *pproperties, uint16_t num_properties) +{ + generic_admin_property_info_t *pinfo = pmodel_info->pargs; + pinfo->pproperties = pproperties; + pinfo->num_properties = num_properties; +} + +static mesh_msg_send_cause_t generic_admin_property_send(mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len, uint16_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t generic_admin_properties_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + const generic_property_db_t *pproperties, + uint16_t num_properties, uint16_t delay_time) +{ + uint16_t msg_len = sizeof(generic_admin_properties_status_t) + 2 * num_properties; + generic_admin_properties_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_ADMIN_PROPERTIES_STATUS); + for (uint16_t i = 0; i < num_properties; ++i) + { + pmsg->property_ids[i] = pproperties[i].property_id; + } + mesh_msg_send_cause_t ret = generic_admin_property_send(pmodel_info, dst, app_key_index, + (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +generic_property_db_t *generic_admin_property_find(mesh_model_info_p pmodel_info, + uint16_t property_id) +{ + generic_admin_property_info_t *pinfo = pmodel_info->pargs; + generic_property_db_t *pdb = NULL; + for (uint16_t i = 0; i < pinfo->num_properties; ++i) + { + if (pinfo->pproperties[i].property_id == property_id) + { + pdb = &pinfo->pproperties[i]; + } + } + + return pdb; +} + +static mesh_msg_send_cause_t generic_admin_property_status_internal(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, + const generic_property_db_t *pdb, + uint16_t delay_time) +{ + mesh_msg_send_cause_t ret; + if (NULL != pdb) + { + uint16_t msg_len = 0; + msg_len = sizeof(generic_admin_property_status_t) + pdb->value_len; + + generic_admin_property_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_ADMIN_PROPERTY_STATUS); + pmsg->property_id = property_id; + pmsg->property_access = pdb->property_access; + for (uint16_t i = 0; i < pdb->value_len; ++i) + { + pmsg->property_value[i] = pdb->pproperty_value[i]; + } + ret = generic_admin_property_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + } + else + { + generic_admin_property_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ADMIN_PROPERTY_STATUS); + msg.property_id = property_id; + ret = generic_admin_property_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + MEMBER_OFFSET(generic_admin_property_status_t, property_access), delay_time); + } + + return ret; +} + +static mesh_msg_send_cause_t generic_admin_property_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, uint16_t delay_time) +{ + generic_property_db_t *pdb = generic_admin_property_find(pmodel_info, property_id); + return generic_admin_property_status_internal(pmodel_info, dst, app_key_index, property_id, pdb, + delay_time); +} + +static mesh_msg_send_cause_t generic_admin_property_delay_publish(const mesh_model_info_p + pmodel_info, + const generic_property_db_t *pdb, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_admin_property_status_internal(pmodel_info, 0, 0, pdb->property_id, pdb, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t generic_admin_property_publish(const mesh_model_info_p pmodel_info, + const generic_property_db_t *pdb) +{ + return generic_admin_property_delay_publish(pmodel_info, pdb, 0); +} + +static bool generic_admin_property_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_ADMIN_PROPERTIES_GET: + if (pmesh_msg->msg_len == sizeof(generic_admin_properties_get_t)) + { + generic_admin_property_info_t *pinfo = pmodel_info->pargs; + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_admin_properties_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->pproperties, pinfo->num_properties, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_ADMIN_PROPERTY_GET: + if (pmesh_msg->msg_len == sizeof(generic_admin_property_get_t)) + { + generic_admin_property_get_t *pmsg = (generic_admin_property_get_t *)pbuffer; + if (pmsg->property_id != GENERIC_PROPERTY_ID_PROHIBITED) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_admin_property_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, delay_rsp_time); + } + } + break; + case MESH_MSG_GENERIC_ADMIN_PROPERTY_SET: + case MESH_MSG_GENERIC_ADMIN_PROPERTY_SET_UNACK: + { + generic_admin_property_set_t *pmsg = (generic_admin_property_set_t *)pbuffer; + generic_property_db_t *pdb = generic_admin_property_find(pmodel_info, pmsg->property_id); + bool valid = TRUE; + if (NULL != pdb) + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_admin_property_set_t, + property_value); + if ((pdb->value_len != value_len) || + (pmsg->property_access > GENERIC_PROPERTY_ACCESS_READ_AND_WRITE)) + { + /* invalid parameters */ + valid = FALSE; + } + else + { + pdb->property_access = pmsg->property_access; + memcpy(pdb->pproperty_value, pmsg->property_value, value_len); + pdb->value_len = value_len; + /* notify app admin property changed */ + generic_admin_property_server_set_t set_data; + set_data.property_id = pmsg->property_id; + set_data.property_access = pmsg->property_access; + set_data.pproperty_value = pdb->pproperty_value; + set_data.value_len = pdb->value_len; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_ADMIN_PROPERTY_SERVER_SET, &set_data); + } + } + } + + if (valid) + { + uint32_t delay_rsp_time = 0; + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_ADMIN_PROPERTY_SET) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_admin_property_status_internal(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, pdb, delay_rsp_time); + } + + uint32_t delay_pub_time = 0; + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_ADMIN_PROPERTY_SET_UNACK) ? FALSE : TRUE; + generic_transition_time_t trans_time = {0, 0}; + delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, ack); +#endif + if (NULL != pdb) + { + generic_admin_property_delay_publish(pmodel_info, pdb, delay_pub_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void generic_admin_property_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == generic_admin_property_server_receive) + { + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool generic_admin_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_ADMIN_PROPERTY_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(generic_admin_property_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("generic_admin_property_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(generic_admin_property_info_t)); + + pmodel_info->model_receive = generic_admin_property_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_admin_property_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = generic_admin_property_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery.h new file mode 100644 index 00000000..e7f01207 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery.h @@ -0,0 +1,201 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_battery.h +* @brief Head file for generic battery models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-25 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_BATTERY_H +#define _GENERIC_BATTERY_H + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_BATTERY + * @{ + */ + +/** + * @defgroup GENERIC_BATTERY_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_BATTERY_GET 0x8223 +#define MESH_MSG_GENERIC_BATTERY_STAT 0x8224 +/** @} */ + +/** + * @defgroup GENERIC_BATTERY_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_BATTERY_SERVER 0x100CFFFF +#define MESH_MODEL_GENERIC_BATTERY_CLIENT 0x100DFFFF +/** @} */ + +/** + * @defgroup GENERIC_BATTERY_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define GENERIC_BATTERY_TIME_UNKNOWN 0xFFFFFF + +#define GENERIC_BATTERY_LEVEL_100 = 0x64, //!< 0x65-0xFE Prohibited +#define GENERIC_BATTERY_LEVEL_UNKNOWN = 0xFF + +typedef enum +{ + GENERIC_BATTERY_FLAGS_NOT_PRESENT, + GENERIC_BATTERY_FLAGS_PRESENT_AND_REMOVABLE, + GENERIC_BATTERY_FLAGS_PRESENT_AND_NON_REMOVABLE, + GENERIC_BATTERY_FLAGS_PRESENCE_UNKNOWN +} generic_battery_flags_presence_t; + +typedef enum +{ + GENERIC_BATTERY_FLAGS_CHARGE_CRITICALLY_LOW_LEVEL, + GENERIC_BATTERY_FLAGS_CHARGE_LOW_LEVEL, + GENERIC_BATTERY_FLAGS_CHARGE_GOOD_LEVEL, + GENERIC_BATTERY_FLAGS_CHARGE_UNKNOWN +} generic_battery_flags_indicator_t; + +typedef enum +{ + GENERIC_BATTERY_FLAGS_NOT_CHARGEABLE, + GENERIC_BATTERY_FLAGS_CHARGEABLE_AND_NOT_CHARGING, + GENERIC_BATTERY_FLAGS_CHARGEABLE_AND_CHARGING, + GENERIC_BATTERY_FLAGS_CHARGING_STATE_UNKNOWN +} generic_battery_flags_charging_t; + +typedef enum +{ + GENERIC_BATTERY_FLAGS_NOT_REQUIRE_SERVICE = 0x1, + GENERIC_BATTERY_FLAGS_REQUIRE_SERVICE, + GENERIC_BATTERY_FLAGS_SERVICEABILITY_UNKNOWN +} generic_battery_flags_serviceability_t; + +typedef struct +{ + uint8_t presence: 2; + uint8_t indicator: 2; + uint8_t charging: 2; + uint8_t serviceability: 2; +} generic_battery_flags_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_BATTERY_GET)]; +} generic_battery_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_BATTERY_STAT)]; + uint8_t battery_level; //!< @ref GENERIC_BATTERY_LEVEL_100 + uint8_t time_to_discharge[3]; //!< @ref GENERIC_BATTERY_TIME_UNKNOWN + uint8_t time_to_charge[3]; //!< @ref GENERIC_BATTERY_TIME_UNKNOWN + generic_battery_flags_t flags; +} _PACKED4_ generic_battery_stat_t, *generic_battery_stat_p; +/** @} */ + +/** + * @defgroup GENERIC_BATTERY_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_BATTERY_SERVER_GET 0 //!< @ref generic_battery_server_get_t + +typedef struct +{ + uint8_t battery_level; + uint32_t time_to_discharge; + uint32_t time_to_charge; + generic_battery_flags_t flags; +} generic_battery_server_get_t; +/** @} */ + +/** + * @defgroup GENERIC_BATTERY_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_BATTERY_CLIENT_STATUS 0 //!< @ref generic_battery_client_status_t + +typedef struct +{ + uint16_t src; + uint8_t battery_level; + uint32_t time_to_discharge; + uint32_t time_to_charge; + generic_battery_flags_t flags; +} generic_battery_client_status_t; +/** @} */ + +/** + * @defgroup GENERIC_BATTERY_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic battery server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic battery server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_battery_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic battery status + * @param[in] pmodel_info: pointer to generic battery server model context + * @param[in] battery_level: battery level status need to publish + * @param[in] time_to_discharge: battery discharge time + * @param[in] time_to_charge: battery charge time + * @param[in] flags: battery flags + * @return publish status + */ +mesh_msg_send_cause_t generic_battery_publish(const mesh_model_info_p pmodel_info, + uint8_t battery_level, + uint32_t time_to_discharge, uint32_t time_to_charge, + generic_battery_flags_t flags); +/** @} */ + +/** + * @defgroup GENERIC_BATTERY_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic battery client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic battery client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_battery_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get generic battery status + * @param[in] pmodel_info: pointer to generic battery client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_battery_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_BATTERY_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_client.c new file mode 100644 index 00000000..5160c8ed --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_client.c @@ -0,0 +1,107 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_battery_client.c +* @brief Source file for generic battery client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-6-26 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_battery.h" + +/** + * @brief convert array to time + * @param buf - array to convert + * @return time converted + */ +static __INLINE uint32_t array_to_time(uint8_t *buf) +{ + diag_assert(NULL != buf); + uint32_t time = 0; + for (int i = 2; i >= 0; --i) + { + time <<= 8; + time |= buf[i]; + } + + return time; +} + +static mesh_msg_send_cause_t generic_battery_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_battery_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_battery_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_BATTERY_GET); + return generic_battery_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool generic_battery_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_BATTERY_STAT: + if (pmesh_msg->msg_len == sizeof(generic_battery_stat_t)) + { + generic_battery_stat_p pmsg = (generic_battery_stat_p)pbuffer; + uint32_t discharge = array_to_time(pmsg->time_to_discharge); + uint32_t charge = array_to_time(pmsg->time_to_charge); + + generic_battery_client_status_t status_data = {pmesh_msg->src, 0, 0, 0, {0, 0, 0, 0}}; + status_data.battery_level = pmsg->battery_level; + status_data.time_to_discharge = discharge; + status_data.time_to_charge = charge; + status_data.flags = pmsg->flags; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_BATTERY_CLIENT_STATUS, + &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_battery_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_BATTERY_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_battery_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_battery_client_reg: missing model data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_server.c new file mode 100644 index 00000000..aa033997 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_server.c @@ -0,0 +1,157 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_battery_server.c +* @brief Source file for generic battery server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-6-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_battery.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +/** + * @brief convert time to array + * @param buf - convert result output + * @param time - time to convert + */ +static __INLINE void time_to_array(uint8_t *buf, uint32_t time) +{ + for (int i = 2; i >= 0; --i) + { + buf[i] = (uint8_t)(time & 0xff); + time >>= 8; + } +} + +static mesh_msg_send_cause_t generic_battery_stat(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t battery_level, + uint32_t time_to_discharge, uint32_t time_to_charge, + generic_battery_flags_t flags, uint32_t delay_time) +{ + generic_battery_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_BATTERY_STAT); + uint16_t msg_len = sizeof(generic_battery_stat_t); + uint8_t discharge[4], charge[4]; + msg.battery_level = battery_level; + time_to_array(discharge, time_to_discharge); + time_to_array(charge, time_to_charge); + memcpy(msg.time_to_discharge, discharge, 3); + memcpy(msg.time_to_charge, charge, 3); + msg.flags = flags; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_battery_publish(const mesh_model_info_p pmodel_info, + uint8_t battery_level, + uint32_t time_to_discharge, uint32_t time_to_charge, + generic_battery_flags_t flags) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_battery_stat(pmodel_info, 0, 0, battery_level, time_to_discharge, time_to_charge, + flags, 0); + } + + return ret; +} + + +/** + * @brief default generic battery server receive function + * @param pmesh_msg - received mesh message + * @return process result + */ +static bool generic_battery_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + //uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_BATTERY_GET: + if (pmesh_msg->msg_len == sizeof(generic_battery_get_t)) + { + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + generic_battery_server_get_t get_data = {0, 0, 0, {0, 0, 0, 0}}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_BATTERY_SERVER_GET, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_battery_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_data.battery_level, + get_data.time_to_discharge, get_data.time_to_charge, get_data.flags, delay_rsp_time); + + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t generic_battery_server_publish(const mesh_model_info_p pmodel_info, bool retrans) +{ + generic_battery_server_get_t get_data = {0, 0, 0, {0, 0, 0, 0}}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_BATTERY_SERVER_GET, &get_data); + } + + generic_battery_stat(pmodel_info, 0, 0, get_data.battery_level, get_data.time_to_discharge, + get_data.time_to_charge, + get_data.flags, 0); + + return 0; +} + +bool generic_battery_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_BATTERY_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_battery_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_battery_server_reg: missing model data process callback!"); + } + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_battery_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_client_property_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_client_property_server.c new file mode 100644 index 00000000..6152e6ac --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_client_property_server.c @@ -0,0 +1,115 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_client_property_server.c +* @brief Source file for generic client property server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-06-28 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_property.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +static mesh_msg_send_cause_t generic_client_property_send(mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len, uint16_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t generic_client_properties_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + const uint16_t *pproperty_ids, + uint16_t num_ids, uint16_t delay_time) +{ + uint16_t msg_len = sizeof(generic_client_properties_status_t) + 2 * num_ids; + generic_client_properties_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_CLIENT_PROPERTIES_STATUS); + for (uint16_t i = 0; i < num_ids; ++i) + { + pmsg->property_ids[i] = pproperty_ids[i]; + } + mesh_msg_send_cause_t ret = generic_client_property_send(pmodel_info, dst, app_key_index, + (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +static bool generic_client_property_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_CLIENT_PROPERTIES_GET: + if (pmesh_msg->msg_len == sizeof(generic_client_properties_get_t)) + { + generic_client_properties_get_t *pmsg = (generic_client_properties_get_t *)pbuffer; + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_client_property_server_get_t get_data = {pmsg->property_id, NULL, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_CLIENT_PROPERTY_SERVER_GET, &get_data); + } + generic_client_properties_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_data.pproperty_ids, get_data.num_ids, delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_client_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_CLIENT_PROPERTY_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_client_property_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_admin_property_server_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + + + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time.h new file mode 100644 index 00000000..050c9c99 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time.h @@ -0,0 +1,175 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_default_transition_time.h +* @brief Head file for generic default transition time models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-25 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_DEFAULT_TRANSITION_TIME_H +#define _GENERIC_DEFAULT_TRANSITION_TIME_H + +/* Add Includes here */ +#include "mesh_api.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_DEFAULT_TRANSITION_TIME + * @{ + */ + +/** + * @defgroup GENERIC_DEFAULT_TRANSITION_TIME_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_GET 0x820D +#define MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET 0x820E +#define MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET_UNACK 0x820F +#define MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_STAT 0x8210 +/** @} */ + +/** + * @defgroup GENERIC_DEFAULT_TRANSITION_TIME_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_DEFAULT_TRANSITION_TIME_SERVER 0x1004FFFF +#define MESH_MODEL_GENERIC_DEFAULT_TRANSITION_TIME_CLIENT 0x1005FFFF +/** @} */ + +/** + * @defgroup GENERIC_DEFAULT_TRANSITION_TIME_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_GET)]; +} _PACKED4_ generic_default_transition_time_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET)]; + generic_transition_time_t trans_time; +} _PACKED4_ generic_default_transition_time_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_STAT)]; + generic_transition_time_t trans_time; +} _PACKED4_ generic_default_transition_time_stat_t; +/** @} */ + +/** + * @defgroup GENERIC_DEFAULT_TRANSITION_TIME_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_DEFAULT_TRANSITION_TIME_SERVER_GET 0 //!< @ref generic_default_transition_time_server_set_t +#define GENERIC_DEFAULT_TRANSITION_TIME_SERVER_SET 1 //!< @ref generic_default_transition_time_server_get_t + +typedef struct +{ + generic_transition_time_t trans_time; +} generic_default_transition_time_server_set_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} generic_default_transition_time_server_get_t; +/** @} */ + +/** + * @defgroup GENERIC_DEFAULT_TRANSITION_TIME_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_DEFAULT_TRANSITION_TIME_CLIENT_STATUS 0 //!< @ref generic_default_transition_time_client_status_t + +typedef struct +{ + uint16_t src; + generic_transition_time_t trans_time; +} generic_default_transition_time_client_status_t; +/** @} */ + +/** + * @defgroup GENERIC_DEFAULT_TRANSITION_TIME_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic default transition time server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic default transition server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_default_transition_time_server_reg(uint8_t element_index, + mesh_model_info_p pmodel_info); +/** + * @brief publish generic default transition time + * @param[in] pmodel_info: pointer to generic default transition server model context + * @param[in] trans_time: transition time need to publish + * @return publish status + */ +mesh_msg_send_cause_t generic_default_transition_time_publish(const mesh_model_info_p pmodel_info, + generic_transition_time_t trans_time); +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic default transition time client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic default transition client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_default_transition_time_client_reg(uint8_t element_index, + mesh_model_info_p pmodel_info); + +/** + * @brief get generic default tarnsition time + * @param[in] pmodel_info: pointer to generic default transition client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_default_transition_time_get(const mesh_model_info_p + pmodel_info, + uint16_t dst, uint16_t app_key_index); + +/** + * @brief set generic default tarnsition time + * @param[in] pmodel_info: pointer to generic default transition client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] trans_time: new transition time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_default_transition_time_set(const mesh_model_info_p + pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_transition_time_t trans_time, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_DEFAULT_TRANSITION_TIME_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_client.c new file mode 100644 index 00000000..11814c72 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_client.c @@ -0,0 +1,107 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_default_transition_time_client.c +* @brief Source file for generic default transition time client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-9 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_default_transition_time.h" + +mesh_msg_send_cause_t generic_default_transition_time_client_send(const mesh_model_info_p + pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_default_transition_time_get(const mesh_model_info_p + pmodel_info, + uint16_t dst, uint16_t app_key_index) +{ + generic_default_transition_time_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_GET); + return generic_default_transition_time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_default_transition_time_set(const mesh_model_info_p + pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_transition_time_t trans_time, bool ack) +{ + generic_default_transition_time_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET_UNACK); + } + msg.trans_time = trans_time; + return generic_default_transition_time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +static bool generic_default_transition_time_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_STAT: + if (pmesh_msg->msg_len == sizeof(generic_default_transition_time_stat_t)) + { + generic_default_transition_time_stat_t *pmsg = (generic_default_transition_time_stat_t *)pbuffer; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + generic_default_transition_time_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.trans_time = pmsg->trans_time; + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + GENERIC_DEFAULT_TRANSITION_TIME_CLIENT_STATUS, &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_default_transition_time_client_reg(uint8_t element_index, + mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_DEFAULT_TRANSITION_TIME_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_default_transition_time_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_default_transition_time_client_reg: missing data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_server.c new file mode 100644 index 00000000..720ff9e9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_server.c @@ -0,0 +1,161 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_default_transition_time_server.c +* @brief Source file for generic default transition time server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-9 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_default_transition_time.h" + + +/** + * @brief replay generic default transition time status + * @param[in] pmodel_info: gdtt server model information + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] trans_time: curent transition time + * @return send status + */ +static mesh_msg_send_cause_t generic_default_transition_time_stat(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_transition_time_t trans_time) +{ + generic_default_transition_time_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_STAT); + msg.trans_time = trans_time; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = sizeof(generic_default_transition_time_stat_t); + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_default_transition_time_publish(const mesh_model_info_p pmodel_info, + generic_transition_time_t trans_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_default_transition_time_stat(pmodel_info, 0, 0, trans_time); + } + + return ret; +} + +static generic_transition_time_t get_present_transition_time(mesh_model_info_p pmodel_info) +{ + generic_default_transition_time_server_get_t get_data = {{0, 0}}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_DEFAULT_TRANSITION_TIME_SERVER_GET, &get_data); + } + + return get_data.trans_time; +} + +/** + * @brief generic default transition time receive callback + * @param[in] pmesh_msg: received mesh message + * @return process status + */ +static bool generic_default_transition_time_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_t *pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_GET: + if (pmesh_msg->msg_len == sizeof(generic_default_transition_time_get_t)) + { + generic_default_transition_time_stat(pmesh_msg->pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, get_present_transition_time(pmodel_info)); + } + break; + case MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET: + case MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_default_transition_time_set_t)) + { + generic_default_transition_time_set_t *pmsg = (generic_default_transition_time_set_t *)pbuffer; + if (IS_GENERIC_TRANSITION_STEPS_VALID(pmsg->trans_time.num_steps)) + { + generic_default_transition_time_server_set_t get_data = {{0, 0}}; + if (NULL != pmodel_info->model_data_cb) + { + generic_default_transition_time_server_set_t set_data; + set_data.trans_time = pmsg->trans_time; + pmodel_info->model_data_cb(pmodel_info, + GENERIC_DEFAULT_TRANSITION_TIME_SERVER_GET, &get_data); + pmodel_info->model_data_cb(pmodel_info, + GENERIC_DEFAULT_TRANSITION_TIME_SERVER_SET, &set_data); + } + if (MESH_MSG_GENERIC_DEFAULT_TRANSITION_TIME_SET == pmesh_msg->access_opcode) + { + generic_default_transition_time_stat(pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, pmsg->trans_time); + } + + if ((get_data.trans_time.num_steps != pmsg->trans_time.num_steps) || + (get_data.trans_time.step_resolution != pmsg->trans_time.step_resolution)) + { + /* state change publish */ + generic_default_transition_time_publish(pmodel_info, pmsg->trans_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t generic_default_transition_time_server_publish(mesh_model_info_p pmodel_info, + bool retrans) +{ + generic_default_transition_time_stat(pmodel_info, 0, 0, get_present_transition_time(pmodel_info)); + return 0; +} + +bool generic_default_transition_time_server_reg(uint8_t element_index, + mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_DEFAULT_TRANSITION_TIME_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_default_transition_time_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_default_transition_time_server_reg: missing data process callback!"); + } + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_default_transition_time_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level.h new file mode 100644 index 00000000..434f3f62 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level.h @@ -0,0 +1,267 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_level.h +* @brief Head file for generic level models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-25 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_LEVEL_H +#define _GENERIC_LEVEL_H + +#include "mesh_api.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_LEVEL + * @{ + */ + +/** + * @defgroup GENERIC_LEVEL_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_LEVEL_GET 0x8205 +#define MESH_MSG_GENERIC_LEVEL_SET 0x8206 +#define MESH_MSG_GENERIC_LEVEL_SET_UNACK 0x8207 +#define MESH_MSG_GENERIC_LEVEL_STAT 0x8208 +#define MESH_MSG_GENERIC_DELTA_SET 0x8209 +#define MESH_MSG_GENERIC_DELTA_SET_UNACK 0x820A +#define MESH_MSG_GENERIC_MOVE_SET 0x820B +#define MESH_MSG_GENERIC_MOVE_SET_UNACK 0x820C +/** @} */ + +/** + * @defgroup GENERIC_LEVEL_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_LEVEL_SERVER 0x1002FFFF +#define MESH_MODEL_GENERIC_LEVEL_CLIENT 0x1003FFFF +/** @} */ + +/** + * @defgroup GENERIC_LEVEL_MESH_MSG Mesh Msg + * @brief Mesh mesage types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LEVEL_GET)]; +} _PACKED4_ generic_level_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LEVEL_SET)]; + int16_t level; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ generic_level_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LEVEL_STAT)]; + int16_t present_level; + int16_t target_level; //!< optional + generic_transition_time_t remaining_time; +} _PACKED4_ generic_level_stat_t, *generic_level_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_DELTA_SET)]; + int32_t delta_level; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ generic_delta_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_MOVE_SET)]; + int16_t delta_level; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ generic_move_set_t; +/** @} */ + +/** + * @defgroup GENERIC_LEVEL_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_LEVEL 0 +#define DELAY_EXECUTION_TYPE_LEVEL 0 +#define DELAY_EXECUTION_TYPE_LEVEL_MOVE 1 +/** @} */ + +/** + * @defgroup GENERIC_LEVEL_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_LEVEL_SERVER_GET 0 //!< @ref generic_level_server_get_t +#define GENERIC_LEVEL_SERVER_GET_DEFAULT_TRANSITION_TIME 1 //!< @ref generic_level_server_get_default_transition_time_t +#define GENERIC_LEVEL_SERVER_SET 2 //!< @ref generic_level_server_set_t +#define GENERIC_LEVEL_SERVER_SET_MOVE 3 //!< @ref generic_level_server_set_move_t + +typedef struct +{ + int16_t level; +} generic_level_server_get_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} generic_level_server_get_default_transition_time_t; + +typedef struct +{ + int16_t level; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} generic_level_server_set_t; + +typedef struct +{ + int16_t move_delta; + int16_t target_level; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} generic_level_server_set_move_t; +/** @} */ + +/** + * @defgroup GENERIC_LEVEL_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_LEVEL_CLIENT_STATUS 0 //!< @ref generic_level_client_status_t + +typedef struct +{ + uint16_t src; + int16_t present_level; + bool optional; + int16_t target_level; + generic_transition_time_t remaining_time; +} generic_level_client_status_t; +/** @} */ + +/** + * @defgroup GENERIC_LEVEL_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic level server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic level server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_level_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic level status + * @param[in] pmodel_info: pointer to generic level server model context + * @param[in] level: level status need to publish + * @return publish status + */ +mesh_msg_send_cause_t generic_level_publish(const mesh_model_info_p pmodel_info, int16_t level); + +/** @} */ + +/** @defgroup GENERIC_LEVEL_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic level client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic level client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_level_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get generic level status + * @param[in] pmodel_info: pointer to generic level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_level_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set generic level + * @param[in] pmodel_info: pointer to generic level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] level: desired level value + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_level_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + int16_t level, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); +/** + * @brief set generic level delta parameter + * @param[in] pmodel_info: pointer to generic level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] delta_level: desired delta level value + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_delta_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + int32_t delta_level, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); +/** + * @brief set generic level move parameter + * @param[in] pmodel_info: pointer to generic default on off client context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] delta_level: desired delta level value + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_move_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + int16_t delta_level, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_LEVEL_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_client.c new file mode 100644 index 00000000..2b5cc8c2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_client.c @@ -0,0 +1,185 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_level_client.c +* @brief Source file for generic level client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_level.h" + +static mesh_msg_send_cause_t generic_level_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_level_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_level_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LEVEL_GET); + return generic_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_level_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + int16_t level, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + generic_level_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LEVEL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LEVEL_SET_UNACK); + } + + if (optional) + { + len = sizeof(generic_level_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(generic_level_set_t, trans_time); + } + msg.level = level; + msg.tid = tid; + return generic_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t generic_delta_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + int32_t delta_level, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + generic_delta_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_DELTA_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_DELTA_SET_UNACK); + } + + if (optional) + { + len = sizeof(generic_delta_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(generic_delta_set_t, trans_time); + } + msg.delta_level = delta_level; + msg.tid = tid; + return generic_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t generic_move_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + int16_t delta_level, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + generic_move_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MOVE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MOVE_SET_UNACK); + } + + if (optional) + { + len = sizeof(generic_move_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(generic_move_set_t, trans_time); + } + msg.delta_level = delta_level; + msg.tid = tid; + return generic_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +static bool generic_level_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_LEVEL_STAT: + { + generic_level_stat_p pmsg = (generic_level_stat_p)pbuffer; + generic_level_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.present_level = pmsg->present_level; + status_data.optional = FALSE; + if (pmesh_msg->msg_len == sizeof(generic_level_stat_t)) + { + status_data.optional = TRUE; + status_data.target_level = pmsg->target_level; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_LEVEL_CLIENT_STATUS, + &status_data); + } + break; + } + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_level_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_LEVEL_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_level_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_level_client_reg: missing model data process callback!"); + } + + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_server.c new file mode 100644 index 00000000..4dc4ef84 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_server.c @@ -0,0 +1,710 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_level_server.c +* @brief Source file for generic level server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-13 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "generic_level.h" +#include "generic_types.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +typedef struct +{ + uint8_t tid; + int16_t target_level; + generic_transition_time_t trans_time; + uint32_t delay_time; + int16_t move_delta; + int32_t delta_level; + bool max_move; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} generic_level_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} generic_level_process_result_t; + +#define GENERIC_LEVEL_MAX 0x7FFF + +static mesh_msg_send_cause_t generic_level_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, int16_t present_level, + bool optional, int16_t target_level, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + generic_level_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LEVEL_STAT); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(generic_level_stat_t); + msg.target_level = target_level; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(generic_level_stat_t, target_level); + } + msg.present_level = present_level; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_level_delay_publish(const mesh_model_info_p pmodel_info, + int16_t present_level, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = generic_level_stat(pmodel_info, 0, 0, present_level, FALSE, present_level, trans_time, + delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t generic_level_publish(const mesh_model_info_p pmodel_info, + int16_t present_level) +{ + return generic_level_delay_publish(pmodel_info, present_level, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void generic_level_state_change_publish(const mesh_model_info_p pmodel_info, + int16_t present_level, generic_level_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_level_publish(pmodel_info, present_level); + } +} +#endif + +static int16_t get_present_level(const mesh_model_info_p pmodel_info) +{ + generic_level_server_get_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_GET, &get_data); + } + + return get_data.level; +} + +static int32_t generic_level_trans_step_change(const mesh_model_info_p pmodel_info, uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + int32_t ret = MODEL_SUCCESS; + generic_level_server_set_t set_data; + generic_level_info_t *plevel_info = pmodel_info->pargs; + if (NULL == plevel_info) + { + return 0; + } + set_data.level = plevel_info->target_level; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_SET, &set_data); + } + + if (0 == remaining_time.num_steps) + { + int16_t present_level = get_present_level(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + generic_level_delay_publish(pmodel_info, present_level, plevel_info->delay_pub_time); +#else + generic_level_publish(pmodel_info, present_level); +#endif + } + + return ret; +} + +static int16_t generic_level_process(const mesh_model_info_p pmodel_info, uint32_t type, + int16_t move_delta, + int16_t target_level, generic_transition_time_t trans_time, + generic_level_process_result_t *presult) +{ + int16_t level_before_set = 0; + int16_t level_after_set = 0; + + /* get generic level before set */ + level_before_set = get_present_level(pmodel_info); + level_after_set = level_before_set; + + int32_t ret = MODEL_SUCCESS; + generic_level_server_set_t trans_set_data; + generic_level_server_set_move_t move_set_data; + switch (type) + { + case GENERIC_LEVEL_SERVER_SET: + { + trans_set_data.level = target_level; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_SET, &trans_set_data); + } + } + break; + case GENERIC_LEVEL_SERVER_SET_MOVE: + { + move_set_data.move_delta = move_delta; + move_set_data.target_level = target_level; + move_set_data.total_time = trans_time; + move_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_SET_MOVE, &move_set_data); + } + break; + } + default: + break; + } + if ((GENERIC_TRANSITION_NUM_STEPS_UNKNOWN != trans_time.num_steps) && + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps)) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LEVEL, trans_time, + generic_level_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + switch (type) + { + case GENERIC_LEVEL_SERVER_SET: + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_SET, &trans_set_data); + } + } + break; + case GENERIC_LEVEL_SERVER_SET_MOVE: + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_SET_MOVE, &move_set_data); + } + break; + } + default: + break; + } + } +#endif + } + else + { + /* get level after set */ + level_after_set = get_present_level(pmodel_info); + } + + if (level_before_set != level_after_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return level_after_set; +} + +static int32_t generic_level_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LEVEL: + case DELAY_EXECUTION_TYPE_LEVEL_MOVE: + { + generic_level_info_t *plevel_info = pmodel_info->pargs; + if (NULL == plevel_info) + { + return 0; + } + plevel_info->delay_time = 0; + int16_t present_level = 0; + generic_level_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (DELAY_EXECUTION_TYPE_LEVEL == delay_type) + { + present_level = generic_level_process(pmodel_info, GENERIC_LEVEL_SERVER_SET, 0, + plevel_info->target_level, plevel_info->trans_time, &result); + } + else + { + present_level = generic_level_process(pmodel_info, GENERIC_LEVEL_SERVER_SET_MOVE, + plevel_info->move_delta, plevel_info->target_level, + plevel_info->trans_time, &result); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_level_delay_publish(pmodel_info, present_level, plevel_info->delay_pub_time); + } + } +#else + generic_level_state_change_publish(pmodel_info, present_level, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool generic_level_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_LEVEL_GET: + if (pmesh_msg->msg_len == sizeof(generic_level_get_t)) + { + generic_level_info_t *plevel_info = pmodel_info->pargs; + + generic_transition_time_t remaining_time; + if (plevel_info->delay_time > 0) + { + remaining_time = plevel_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_LEVEL); + } + + if (plevel_info->max_move) + { + remaining_time.num_steps = GENERIC_TRANSITION_NUM_STEPS_UNKNOWN; + remaining_time.step_resolution = GENERIC_TRANSITION_STEP_RESOLUTION_10MINUTS; + } + + int16_t present_level = get_present_level(pmodel_info); + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_level_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_level, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + plevel_info->target_level, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_LEVEL_SET: + case MESH_MSG_GENERIC_LEVEL_SET_UNACK: + { + generic_level_set_t *pmsg = (generic_level_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(generic_level_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(generic_level_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + generic_level_info_t *plevel_info = pmodel_info->pargs; + plevel_info->target_level = pmsg->level; + plevel_info->tid = pmsg->tid; + plevel_info->delay_time = delay_time; + plevel_info->trans_time = trans_time; + + int16_t present_level; + generic_level_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_level = get_present_level(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LEVEL, delay_time, + generic_level_delay_execution); + } + else + { + present_level = generic_level_process(pmodel_info, GENERIC_LEVEL_SERVER_SET, 0, + plevel_info->target_level, trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_LEVEL_SET) + { + generic_level_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_level, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + plevel_info->target_level, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_LEVEL_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + generic_level_delay_publish(pmodel_info, present_level, delay_pub_time); + } + } + else + { + plevel_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + generic_level_state_change_publish(pmodel_info, present_level, result); +#endif + } + } + break; + case MESH_MSG_GENERIC_DELTA_SET: + case MESH_MSG_GENERIC_DELTA_SET_UNACK: + { + generic_delta_set_t *pmsg = (generic_delta_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(generic_delta_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(generic_delta_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + generic_level_info_t *plevel_info = pmodel_info->pargs; + generic_level_server_get_t get_data = {0}; + if (plevel_info->tid == pmsg->tid) + { + plevel_info->target_level = plevel_info->target_level - plevel_info->delta_level + + pmsg->delta_level; + } + else + { + /* get level */ + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_GET, &get_data); + } + plevel_info->target_level = get_data.level + pmsg->delta_level; + } + plevel_info->tid = pmsg->tid; + plevel_info->delta_level = pmsg->delta_level; + plevel_info->delay_time = delay_time; + plevel_info->trans_time = trans_time; + int16_t present_level; + generic_level_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_level = get_present_level(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LEVEL, delay_time, + generic_level_delay_execution); + } + else + { + present_level = generic_level_process(pmodel_info, GENERIC_LEVEL_SERVER_SET, 0, + plevel_info->target_level, trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_DELTA_SET) + { + generic_level_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_level, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + plevel_info->target_level, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time = 0; + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_DELTA_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, ack); + generic_level_delay_publish(pmodel_info, present_level, delay_pub_time); + } + } + else + { + plevel_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + generic_level_state_change_publish(pmodel_info, present_level, result); +#endif + } + } + break; + case MESH_MSG_GENERIC_MOVE_SET: + case MESH_MSG_GENERIC_MOVE_SET_UNACK: + { + generic_move_set_t *pmsg = (generic_move_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(generic_move_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(generic_move_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + generic_level_info_t *plevel_info = pmodel_info->pargs; + if (IS_MAX_GENERIC_TRANSITION_TIME(trans_time)) + { + plevel_info->target_level = GENERIC_LEVEL_MAX; + trans_time.num_steps = GENERIC_TRANSITION_NUM_STEPS_UNKNOWN; + plevel_info->max_move = TRUE; + } + else + { + generic_level_server_get_t get_data = {0}; + /* get level */ + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LEVEL_SERVER_GET, &get_data); + } + + plevel_info->target_level = get_data.level + trans_time.num_steps * pmsg->delta_level; + plevel_info->max_move = FALSE; + } + + plevel_info->tid = pmsg->tid; + plevel_info->delay_time = delay_time; + plevel_info->trans_time = trans_time; + plevel_info->move_delta = pmsg->delta_level; + + int16_t present_level; + generic_level_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_level = get_present_level(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LEVEL_MOVE, delay_time, + generic_level_delay_execution); + } + else + { + present_level = generic_level_process(pmodel_info, GENERIC_LEVEL_SERVER_SET_MOVE, + pmsg->delta_level, + plevel_info->target_level, + trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_MOVE_SET) + { + generic_level_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_level, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + plevel_info->target_level, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time = 0; + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_MOVE_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, ack); + generic_level_delay_publish(pmodel_info, present_level, delay_pub_time); + } + } + else + { + plevel_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + generic_level_state_change_publish(pmodel_info, present_level, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t generic_level_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + generic_transition_time_t trans_time = {0, 0}; + generic_level_stat(pmodel_info, 0, 0, get_present_level(pmodel_info), FALSE, 0, trans_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void generic_level_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == generic_level_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LEVEL); + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LEVEL_MOVE); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LEVEL); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool generic_level_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_LEVEL_SERVER; + if (NULL == pmodel_info->model_receive) + { + generic_level_info_t *plevel_info = plt_malloc(sizeof(generic_level_info_t), RAM_TYPE_DATA_ON); + if (NULL == plevel_info) + { + printe("generic_level_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(plevel_info, 0, sizeof(generic_level_info_t)); + pmodel_info->pargs = plevel_info; + + pmodel_info->model_receive = generic_level_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_level_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = generic_level_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_level_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location.h new file mode 100644 index 00000000..7391774c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location.h @@ -0,0 +1,344 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_location.h +* @brief Head file for generic location models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-06-10 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_LOCATION_H +#define _GENERIC_LOCATION_H + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_LOCATION + * @{ + */ + +/** + * @defgroup GENERIC_LOCATION_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_LOCATION_GLOBAL_GET 0x8225 +#define MESH_MSG_GENERIC_LOCATION_GLOBAL_STATUS 0x40 +#define MESH_MSG_GENERIC_LOCATION_LOCAL_GET 0x8226 +#define MESH_MSG_GENERIC_LOCATION_LOCAL_STATUS 0x8227 +#define MESH_MSG_GENERIC_LOCATION_GLOBAL_SET 0x41 +#define MESH_MSG_GENERIC_LOCATION_GLOBAL_SET_UNACK 0x42 +#define MESH_MSG_GENERIC_LOCATION_LOCAL_SET 0x8228 +#define MESH_MSG_GENERIC_LOCATION_LOCAL_SET_UNACK 0x8229 +/** @} */ + +/** + * @defgroup GENERIC_LOCATION_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_LOCATION_SERVER 0x100EFFFF +#define MESH_MODEL_GENERIC_LOCATION_SETUP_SERVER 0x100FFFFF +#define MESH_MODEL_GENERIC_LOCATION_CLIENT 0x1010FFFF +/** @} */ + +/** + * @defgroup GENERIC_LOCATION_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define GENERIC_LOCATION_GLOBAL_LATITUDE_NOT_CONFIGURED 0x80000000 +#define GENERIC_LOCATION_GLOBAL_LONGITUDE_NOT_CONFIGURED 0x80000000 + +#define GENERIC_LOCATION_ALTITUDE_NOT_CONFIGURED 0x7FFF +#define GENERIC_LOCATION_ALTITUDE_UPPER_LIMIT 0x7FFE //!< Altitude is greater than or equal to 32766 meters/decimeters. + +#define GENERIC_LOCATION_LOCAL_NORTH_NOT_CONFIGURED 0x8000 +#define GENERIC_LOCATION_LOCAL_EAST_NOT_CONFIGURED 0x8000 + +#define GENERIC_LOCATION_FLOOR_NUM_LOWER_LIMIT 0x00 //!< Floor -20 or any floor below -20. +#define GENERIC_LOCATION_FLOOR_NUM_UPPER_LIMIT 0xFC //!< Floor 232 or any floor above 232. +#define GENERIC_LOCATION_FLOOR_NUM_GROUND_FLOOR0 0xFD //!< Ground floor. Floor 0. +#define GENERIC_LOCATION_FLOOR_NUM_GROUND_FLOOR1 0xFE //!< Ground floor. Floor 1. +#define GENERIC_LOCATION_FLOOR_NUM_NOT_CONFIGURED 0xFF + +typedef struct +{ + int32_t global_latitude; + int32_t global_longitude; + int16_t global_altitude; +} _PACKED4_ generic_location_global_t; + +typedef union +{ + struct + { + uint16_t stationary: 1; + uint16_t rfu: 7; + uint16_t update_time: 4; + uint16_t precision: 4; + }; + uint16_t uncertainty; +} _PACKED4_ generic_location_uncertainty_t; + +typedef struct +{ + int16_t local_north; + int16_t local_east; + int16_t local_altitude; + uint8_t floor_num; + generic_location_uncertainty_t uncertainty; +} _PACKED4_ generic_location_local_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LOCATION_GLOBAL_GET)]; +} _PACKED4_ generic_location_global_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LOCATION_GLOBAL_SET)]; + generic_location_global_t global; +} _PACKED4_ generic_location_global_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LOCATION_GLOBAL_STATUS)]; + generic_location_global_t global; +} _PACKED4_ generic_location_global_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LOCATION_LOCAL_GET)]; +} _PACKED4_ generic_location_local_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LOCATION_LOCAL_SET)]; + generic_location_local_t local; +} _PACKED4_ generic_location_local_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_LOCATION_LOCAL_STATUS)]; + generic_location_local_t local; +} _PACKED4_ generic_location_local_status_t; + +/** @} */ + +/** + * @defgroup GENERIC_LOCATION_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_LOCATION_SERVER_GET_GLOBAL 0 //!< @ref generic_location_server_get_global_t +#define GENERIC_LOCATION_SERVER_GET_LOCAL 1 //!< @ref generic_location_server_get_local_t +#define GENERIC_LOCATION_SERVER_SET_GLOBAL 2 //!< @ref generic_location_server_set_global_t +#define GENERIC_LOCATION_SERVER_SET_LOCAL 3 //!< @ref generic_location_server_set_local_t + +typedef generic_location_global_t generic_location_server_get_global_t; +typedef generic_location_local_t generic_location_server_get_local_t; +typedef generic_location_global_t generic_location_server_set_global_t; +typedef generic_location_local_t generic_location_server_set_local_t; +/** @} */ + +/** + * @defgroup GENERIC_LOCATION_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_LOCATION_CLIENT_STATUS_GLOBAL 0 //!< @ref generic_location_client_status_global_t +#define GENERIC_LOCATION_CLIENT_STATUS_LOCAL 1 //!< @ref generic_location_client_status_local_t + +typedef struct +{ + uint16_t src; + generic_location_global_t global; +} generic_location_client_status_global_t; + +typedef struct +{ + uint16_t src; + generic_location_local_t local; +} generic_location_client_status_local_t; +/** @} */ + +/** + * @defgroup GENERIC_LOCATION_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic location server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic location server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_location_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register generic location setup server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic location setup server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_location_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief convert latitude based on WGS84 to latitude x in the range [-90, 90] + * @param[in] latitude_g: global latitude based on WGS84 datum + * @return latitude x in the range [-90, 90] + */ +double generic_location_latitude_global_to_x(int32_t latitude_g); + +/** + * @brief convert latitude x in the range [-90, 90] to latitude based on WGS84 + * @param[in] latitude_x: global latitude x in the range [-90, 90] + * @return latitude based on WGS84 + */ +int32_t generic_location_latitude_x_to_global(double latitude_x); + +/** + * @brief convert longitude based on WGS84 to longitude x in the range [-180, 180] + * @param[in] longitude_g: global longitude based on WGS84 datum + * @return longitude x in the range [-180, 180] + */ +double generic_location_longitude_global_to_x(int32_t longitude_g); + +/** + * @brief convert longitude x in the range [-180, 180] to longitude based on WGS84 + * @param[in] longitude_x: global longitude x in the range [-180, 180] + * @return longitude based on WGS84 + */ +int32_t generic_location_longitude_x_to_global(double longitude_x); + +/** + * @brief convert update time to seconds + * @param[in] update_time: update time need to be converted, 0-15 + * @return converted time, 0.125-4096 seconds + */ +double generic_location_update_time_to_seconds(uint8_t update_time); + +/** + * @brief convert seconds to update time + * @param[in] seconds: seconds need to be converted, 0.125-4096 seconds + * @return converted update time, 0-15 + */ +uint8_t generic_location_seconds_to_update_time(double senonds); + +/** + * @brief convert precision to meters + * @param[in] precision: precision need to be converted, 0-15 + * @return converted meters, 0.125-4096 meters + */ +double generic_location_precision_to_meters(uint8_t precision); + +/** + * @brief convert meters to precision + * @param[in] meters: meters need to be converted, 0.125-4096 meters + * @return converted precision, 0-15 + */ +uint8_t generic_location_meters_to_precision(double meters); + +/** + * @brief publish location global value + * @param[in] pmodel_info: pointer to generic location server model context + * @param[in] global: location global value + * @return publish status + */ +mesh_msg_send_cause_t generic_location_global_publish(const mesh_model_info_p pmodel_info, + generic_location_global_t global); + +/** + * @brief publish location local value + * @param[in] pmodel_info: pointer to generic location server model context + * @param[in] local: location local value + * @return publish status + */ +mesh_msg_send_cause_t generic_location_local_publish(const mesh_model_info_p pmodel_info, + generic_location_local_t local); + +/** + * @brief enable or disable period publish + * @param[in] global: enable or diable period publish location global + * @param[in] local: enable or disable period publish location local + */ +void generic_location_period_pub_enable(bool global, bool local); +/** @} */ + +/** + * @defgroup GENERIC_LOCATION_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic location client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic location client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_location_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get localtion global value + * @param[in] pmodel_info: pointer to generic location client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_location_global_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set localtion global value + * @param[in] pmodel_info: pointer to generic location client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] global: desired location global value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_location_global_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_location_global_t global, + bool ack); +/** + * @brief get localtion local value + * @param[in] pmodel_info: pointer to generic location client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_location_local_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set localtion local value + * @param[in] pmodel_info: pointer to generic location client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] local: desired location local value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_location_local_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_location_local_t local, + bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_LOCATION_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_client.c new file mode 100644 index 00000000..83e5fd43 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_client.c @@ -0,0 +1,144 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_location_client.c +* @brief Source file for generic on off client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-06-25 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_location.h" + +static mesh_msg_send_cause_t generic_location_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_location_global_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_location_global_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_GLOBAL_GET); + return generic_location_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_location_global_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_location_global_t global, + bool ack) +{ + generic_location_global_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_GLOBAL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_GLOBAL_SET_UNACK); + } + + msg.global = global; + return generic_location_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_location_local_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_location_local_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_LOCAL_GET); + return generic_location_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_location_local_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_location_local_t local, + bool ack) +{ + generic_location_local_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_LOCAL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_LOCAL_SET_UNACK); + } + + msg.local = local; + return generic_location_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool generic_location_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_LOCATION_GLOBAL_STATUS: + if (pmesh_msg->msg_len == sizeof(generic_location_global_status_t)) + { + generic_location_global_status_t *pmsg = (generic_location_global_status_t *)pbuffer; + generic_location_client_status_global_t status_data; + status_data.src = pmesh_msg->src; + status_data.global = pmsg->global; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_LOCATION_CLIENT_STATUS_GLOBAL, + &status_data); + } + } + break; + case MESH_MSG_GENERIC_LOCATION_LOCAL_STATUS: + if (pmesh_msg->msg_len == sizeof(generic_location_local_status_t)) + { + generic_location_local_status_t *pmsg = (generic_location_local_status_t *)pbuffer; + generic_location_client_status_local_t status_data; + status_data.src = pmesh_msg->src; + status_data.local = pmsg->local; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_LOCATION_CLIENT_STATUS_LOCAL, + &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_location_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_LOCATION_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_location_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_location_client_reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_server.c new file mode 100644 index 00000000..57465fde --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_server.c @@ -0,0 +1,257 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_location_server.c +* @brief Source file for generic location server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-06-10 +* @version v1.0 +* ************************************************************************************* +*/ +#include +#include "generic_location.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#define CONVERT_FACTOR (2147483647.0) + +static bool location_global_period_pub_enabled = TRUE; +static bool location_local_period_pub_enabled = TRUE; + +double generic_location_latitude_global_to_x(int32_t latitude_g) +{ + return latitude_g / CONVERT_FACTOR * 90; +} + +int32_t generic_location_latitude_x_to_global(double latitude_x) +{ + return latitude_x / 90 * CONVERT_FACTOR; +} + +double generic_location_longitude_global_to_x(int32_t longitude_g) +{ + return longitude_g / CONVERT_FACTOR * 180; +} + +int32_t generic_location_longitude_x_to_global(double longitude_x) +{ + return longitude_x / 180 * CONVERT_FACTOR; +} + +double generic_location_update_time_to_seconds(uint8_t update_time) +{ + update_time &= 0x0f; + return pow(2, update_time - 3); +} + +uint8_t generic_location_seconds_to_update_time(double seconds) +{ + int8_t update_time = 0; + update_time = log(seconds) / log(2); + update_time += 3; + if (update_time < 0) + { + update_time = 0; + } + + update_time &= 0x0f; + + return update_time; +} + +double generic_location_precision_to_meters(uint8_t precision) +{ + precision &= 0x0f; + return pow(2, precision - 3); +} + +uint8_t generic_location_meters_to_precision(double meters) +{ + int8_t precision = 0; + precision = log(meters) / log(2); + precision += 3; + if (precision < 0) + { + precision = 0; + } + + precision &= 0x0f; + + return precision; +} + +void generic_location_period_pub_enable(bool global, bool local) +{ + location_global_period_pub_enabled = global; + location_local_period_pub_enabled = local; +} + +static mesh_msg_send_cause_t generic_location_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len, uint16_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_location_global_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_location_global_t global, + uint16_t delay_time) +{ + generic_location_global_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_GLOBAL_STATUS); + msg.global = global; + return generic_location_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg), delay_time); +} + +mesh_msg_send_cause_t generic_location_local_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_location_local_t local, + uint16_t delay_time) +{ + generic_location_local_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_LOCATION_LOCAL_STATUS); + msg.local = local; + return generic_location_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg), delay_time); +} + +generic_location_global_t get_present_global(mesh_model_info_p pmodel_info) +{ + generic_location_server_get_global_t get_data = {0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LOCATION_SERVER_GET_GLOBAL, &get_data); + } + + return get_data; +} + +generic_location_local_t get_present_local(mesh_model_info_p pmodel_info) +{ + generic_location_server_get_local_t get_data; + memset(&get_data, 0, sizeof(generic_location_server_get_local_t)); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LOCATION_SERVER_GET_LOCAL, &get_data); + } + + return get_data; +} + +mesh_msg_send_cause_t generic_location_global_publish(const mesh_model_info_p pmodel_info, + generic_location_global_t global) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_location_global_status(pmodel_info, 0, 0, global, 0); + } + + return ret; +} + +mesh_msg_send_cause_t generic_location_local_publish(const mesh_model_info_p pmodel_info, + generic_location_local_t local) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_location_local_status(pmodel_info, 0, 0, local, 0); + } + + return ret; +} + +static int32_t generic_location_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + if (location_global_period_pub_enabled) + { + generic_location_global_status(pmodel_info, 0, 0, get_present_global(pmodel_info), 0); + } + + if (location_local_period_pub_enabled) + { + generic_location_local_status(pmodel_info, 0, 0, get_present_local(pmodel_info), 0); + } + + return 0; +} + + +static bool generic_location_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_LOCATION_GLOBAL_GET: + if (pmesh_msg->msg_len == sizeof(generic_location_global_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_location_global_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_global(pmodel_info), delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_LOCATION_LOCAL_GET: + if (pmesh_msg->msg_len == sizeof(generic_location_local_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_location_local_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_local(pmodel_info), delay_rsp_time); + + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_location_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_LOCATION_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_location_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_location_server_reg: missing model data process callback!"); + } + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_location_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_setup_server.c new file mode 100644 index 00000000..b55f3fee --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_setup_server.c @@ -0,0 +1,267 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_location_setup_server.c +* @brief Source file for generic location setup server model. +* @details Data types and external functions declaration. +* @author heactor_huang +* @date 2019-06-24 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_location.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t generic_location_global_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_location_global_t global, + uint16_t delay_time); +extern mesh_msg_send_cause_t generic_location_local_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + generic_location_local_t local, + uint16_t delay_time); +extern generic_location_global_t get_present_global(mesh_model_info_p pmodel_info); +extern generic_location_local_t get_present_local(mesh_model_info_p pmodel_info); + +typedef struct +{ + bool state_changed; +} generic_location_process_result_t; + +static generic_location_global_t generic_location_global_process(const mesh_model_info_p + pmodel_info, + generic_location_global_t global, + generic_location_process_result_t *presult) +{ + generic_location_global_t global_before_set; + generic_location_global_t global_after_set; + + /* get generic location before set */ + global_before_set = get_present_global(pmodel_info); + global_after_set = global_before_set; + + generic_location_server_set_global_t set_data; + set_data = global; + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LOCATION_SERVER_SET_GLOBAL, &set_data); + } + + /* get generic location global after set */ + global_after_set = get_present_global(pmodel_info); + + if ((global_before_set.global_latitude != global_after_set.global_latitude) || + (global_before_set.global_longitude != global_after_set.global_longitude) || + (global_before_set.global_altitude != global_after_set.global_altitude)) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return global_after_set; +} + +static generic_location_local_t generic_location_local_process(const mesh_model_info_p pmodel_info, + generic_location_local_t local, + generic_location_process_result_t *presult) +{ + generic_location_local_t local_before_set; + generic_location_local_t local_after_set; + + /* get generic location before set */ + local_before_set = get_present_local(pmodel_info); + local_after_set = local_before_set; + + generic_location_server_set_local_t set_data; + set_data = local; + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_LOCATION_SERVER_SET_LOCAL, &set_data); + } + + /* get generic location local after set */ + local_after_set = get_present_local(pmodel_info); + + if ((local_before_set.local_north != local_after_set.local_north) || + (local_before_set.local_east != local_after_set.local_east) || + (local_before_set.local_altitude != local_after_set.local_altitude) || + (local_before_set.floor_num != local_after_set.floor_num) || + (local_before_set.uncertainty.uncertainty != local_after_set.uncertainty.uncertainty)) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return local_after_set; +} + +static mesh_msg_send_cause_t generic_location_global_delay_publish(const mesh_model_info_p + pmodel_info, + generic_location_global_t global, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_location_global_status(pmodel_info, 0, 0, global, delay_time); + } + + return ret; +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void generic_location_global_state_change_publish(const mesh_model_info_p pmodel_info, + generic_location_global_t global, + generic_location_process_result_t result) +{ +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_location_global_delay_publish(pmodel_info, global, 0); + } +} +#endif + +static mesh_msg_send_cause_t generic_location_local_delay_publish(const mesh_model_info_p + pmodel_info, + generic_location_local_t local, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_location_local_status(pmodel_info, 0, 0, local, delay_time); + } + + return ret; +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void generic_location_local_state_change_publish(const mesh_model_info_p pmodel_info, + generic_location_local_t local, + generic_location_process_result_t result) +{ +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_location_local_delay_publish(pmodel_info, local, 0); + } +} +#endif + +static bool generic_location_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_LOCATION_GLOBAL_SET: + case MESH_MSG_GENERIC_LOCATION_GLOBAL_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_location_global_set_t)) + { + generic_location_global_set_t *pmsg = (generic_location_global_set_t *)pbuffer; + + generic_location_process_result_t result = {FALSE}; + generic_location_global_t global = generic_location_global_process(pmodel_info, pmsg->global, + &result); + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_LOCATION_GLOBAL_SET) + { + generic_location_global_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_global(pmodel_info), delay_rsp_time); + } + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_LOCATION_GLOBAL_SET_UNACK) ? FALSE : TRUE; +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_transition_time_t trans_time = {0, 0}; + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, + ack); + generic_location_global_delay_publish(pmodel_info, global, delay_pub_time); + } +#else + generic_location_global_state_change_publish(pmodel_info, global, result); +#endif + } + break; + case MESH_MSG_GENERIC_LOCATION_LOCAL_SET: + case MESH_MSG_GENERIC_LOCATION_LOCAL_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_location_local_set_t)) + { + generic_location_local_set_t *pmsg = (generic_location_local_set_t *)pbuffer; + + generic_location_process_result_t result = {FALSE}; + generic_location_local_t local = generic_location_local_process(pmodel_info, pmsg->local, &result); + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_LOCATION_LOCAL_SET) + { + generic_location_local_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_local(pmodel_info), delay_rsp_time); + } + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_LOCATION_LOCAL_SET_UNACK) ? FALSE : TRUE; +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_transition_time_t trans_time = {0, 0}; + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, + ack); + generic_location_local_delay_publish(pmodel_info, local, delay_pub_time); + } +#else + generic_location_local_state_change_publish(pmodel_info, local, result); +#endif + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_location_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_LOCATION_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_location_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_location_setup_server_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_manufacturer_property_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_manufacturer_property_server.c new file mode 100644 index 00000000..886c0ee8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_manufacturer_property_server.c @@ -0,0 +1,303 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_manufacturer_property_server.c +* @brief Source file for generic manufacturer property server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-02 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_property.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +typedef struct +{ + generic_property_db_t *pproperties; + uint16_t num_properties; +} generic_manu_property_info_t; + +void generic_manufacturer_property_server_set_db(mesh_model_info_t *pmodel_info, + generic_property_db_t *pproperties, uint16_t num_properties) +{ + generic_manu_property_info_t *pinfo = pmodel_info->pargs; + pinfo->pproperties = pproperties; + pinfo->num_properties = num_properties; +} + +static mesh_msg_send_cause_t generic_manu_property_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len, uint16_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t generic_manu_properties_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + const generic_property_db_t *pproperties, + uint16_t num_properties, uint16_t delay_time) +{ + uint16_t msg_len = sizeof(generic_manufacturer_properties_status_t) + 2 * num_properties; + generic_manufacturer_properties_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_STATUS); + for (uint16_t i = 0; i < num_properties; ++i) + { + pmsg->property_ids[i] = pproperties[i].property_id; + } + mesh_msg_send_cause_t ret = generic_manu_property_send(pmodel_info, dst, app_key_index, + (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +generic_property_db_t *generic_manu_property_find(mesh_model_info_p pmodel_info, + uint16_t property_id) +{ + generic_manu_property_info_t *pinfo = pmodel_info->pargs; + generic_property_db_t *pdb = NULL; + for (uint16_t i = 0; i < pinfo->num_properties; ++i) + { + if (pinfo->pproperties[i].property_id == property_id) + { + pdb = &pinfo->pproperties[i]; + } + } + + return pdb; +} + +static mesh_msg_send_cause_t generic_manu_property_status_internal(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, + const generic_property_db_t *pdb, + uint16_t delay_time) +{ + mesh_msg_send_cause_t ret; + if (NULL != pdb) + { + uint16_t msg_len = 0; + msg_len = sizeof(generic_manufacturer_property_status_t) + pdb->value_len; + + generic_manufacturer_property_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_STATUS); + pmsg->property_id = property_id; + pmsg->property_access = pdb->property_access; + for (uint16_t i = 0; i < pdb->value_len; ++i) + { + pmsg->property_value[i] = pdb->pproperty_value[i]; + } + ret = generic_manu_property_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + } + else + { + generic_manufacturer_property_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_STATUS); + msg.property_id = property_id; + ret = generic_manu_property_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + MEMBER_OFFSET(generic_manufacturer_property_status_t, property_access), delay_time); + } + + return ret; +} + +static mesh_msg_send_cause_t generic_manu_property_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, uint16_t delay_time) +{ + generic_property_db_t *pdb = generic_manu_property_find(pmodel_info, property_id); + return generic_manu_property_status_internal(pmodel_info, dst, app_key_index, property_id, pdb, + delay_time); +} + +static mesh_msg_send_cause_t generic_manu_property_delay_publish(const mesh_model_info_p + pmodel_info, + const generic_property_db_t *pdb, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_manu_property_status_internal(pmodel_info, 0, 0, pdb->property_id, pdb, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t generic_manufacturer_property_publish(const mesh_model_info_p pmodel_info, + const generic_property_db_t *pdb) +{ + return generic_manu_property_delay_publish(pmodel_info, pdb, 0); +} + +static bool generic_manu_property_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_GET: + if (pmesh_msg->msg_len == sizeof(generic_manufacturer_properties_get_t)) + { + generic_manu_property_info_t *pinfo = pmodel_info->pargs; + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_manu_properties_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->pproperties, pinfo->num_properties, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_GET: + if (pmesh_msg->msg_len == sizeof(generic_manufacturer_property_get_t)) + { + generic_manufacturer_property_get_t *pmsg = (generic_manufacturer_property_get_t *)pbuffer; + if (pmsg->property_id != GENERIC_PROPERTY_ID_PROHIBITED) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_manu_property_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, delay_rsp_time); + } + } + break; + case MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET: + case MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_manufacturer_property_set_t)) + { + generic_manufacturer_property_set_t *pmsg = (generic_manufacturer_property_set_t *)pbuffer; + generic_property_db_t *pdb = generic_manu_property_find(pmodel_info, pmsg->property_id); + bool valid = TRUE; + if (NULL != pdb) + { + if (pmsg->property_access > GENERIC_PROPERTY_ACCESS_READ_AND_WRITE) + { + valid = FALSE; + } + else + { + pdb->property_access = pmsg->property_access; + /* notify app manufacturer property changed */ + generic_manufacturer_property_server_set_t set_data; + set_data.property_id = pmsg->property_id; + set_data.property_access = pmsg->property_access; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_MANUFACTURER_PROPERTY_SERVER_SET, &set_data); + } + } + } + + if (valid) + { + uint32_t delay_rsp_time = 0; + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_manu_property_status_internal(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, pdb, delay_rsp_time); + } + + uint32_t delay_pub_time = 0; + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET_UNACK) ? FALSE : + TRUE; + generic_transition_time_t trans_time = {0, 0}; + delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, ack); +#endif + if (NULL != pdb) + { + generic_manu_property_delay_publish(pmodel_info, pdb, delay_pub_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void generic_manu_property_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == generic_manu_property_server_receive) + { + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool generic_manufacturer_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_MANUFACTURER_PROPERTY_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(generic_manu_property_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("generic_manu_property_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(generic_manu_property_info_t)); + + pmodel_info->model_receive = generic_manu_property_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_manu_property_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = generic_manu_property_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + + + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off.h new file mode 100644 index 00000000..90ba42d7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off.h @@ -0,0 +1,218 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_on_off.h +* @brief Head file for generic on off models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_ON_OFF_H +#define _GENERIC_ON_OFF_H + +/* Add Includes here */ +#include "generic_types.h" +#include "mesh_api.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_ON_OFF + * @{ + */ + +/** + * @defgroup GENERIC_ON_OFF_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_ON_OFF_GET 0x8201 +#define MESH_MSG_GENERIC_ON_OFF_SET 0x8202 +#define MESH_MSG_GENERIC_ON_OFF_SET_UNACK 0x8203 +#define MESH_MSG_GENERIC_ON_OFF_STAT 0x8204 +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_ON_OFF_SERVER 0x1000FFFF +#define MESH_MODEL_GENERIC_ON_OFF_CLIENT 0x1001FFFF +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +enum +{ + GENERIC_OFF, + GENERIC_ON +} _SHORT_ENUM_; +typedef uint8_t generic_on_off_t; + +#define IS_GENERIC_ON_OFF_VALID(val) (val <= GENERIC_ON) + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ON_OFF_GET)]; +} _PACKED4_ generic_on_off_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ON_OFF_SET)]; + generic_on_off_t on_off; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ generic_on_off_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ON_OFF_STAT)]; + generic_on_off_t present_on_off; + generic_on_off_t target_on_off; //!< optional + /* If the Target OnOff field is present, the Remaining Time field shall also be present; + otherwise these fields shall not be present. */ + generic_transition_time_t remaining_time; +} _PACKED4_ generic_on_off_stat_t, *generic_on_off_stat_p; +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_ON_OFF 0 +#define DELAY_EXECUTION_TYPE_ON_OFF 0 +/** @} */ + + +/** + * @defgroup GENERIC_ON_OFF_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_ON_OFF_SERVER_GET 0 //!< @ref generic_on_off_server_get_t +#define GENERIC_ON_OFF_SERVER_GET_DEFAULT_TRANSITION_TIME 1 //!< @ref generic_on_off_server_get_default_transition_time_t +#define GENERIC_ON_OFF_SERVER_SET 2 //!< @ref generic_on_off_server_set_t + +typedef struct +{ + generic_on_off_t on_off; +} generic_on_off_server_get_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} generic_on_off_server_get_default_transition_time_t; + +typedef struct +{ + generic_on_off_t on_off; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} generic_on_off_server_set_t; +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_ON_OFF_CLIENT_STATUS 0 //!< @ref generic_on_off_client_status_t + +typedef struct +{ + uint16_t src; + generic_on_off_t present_on_off; + bool optional; + generic_on_off_t target_on_off; + generic_transition_time_t remaining_time; +} generic_on_off_client_status_t; +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic on off server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic on off server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_on_off_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic on off + * @param[in] pmodel_info: pointer to generic on off server model context + * @param[in] on_off: on off status need to publish + * @return publish status + */ +mesh_msg_send_cause_t generic_on_off_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off); + +/** @} */ + +/** + * @defgroup GENERIC_ON_OFF_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic on off client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic on off client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_on_off_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get generic on off status + * @param[in] pmodel_info: pointer to generic on off client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_on_off_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set generic on off + * @param[in] pmodel_info: pointer to generic on off model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] trans_time: new transition time + * @param[in] on_off: desired on/off value + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_on_off_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + generic_on_off_t on_off, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_ON_OFF_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_client.c new file mode 100644 index 00000000..cac7b3cf --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_client.c @@ -0,0 +1,122 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_on_off_client.c +* @brief Source file for generic on off client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_on_off.h" + +static mesh_msg_send_cause_t generic_on_off_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_on_off_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_on_off_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_OFF_GET); + return generic_on_off_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_on_off_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_on_off_t on_off, + uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + generic_on_off_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_OFF_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_OFF_SET_UNACK); + } + + if (optional) + { + len = sizeof(generic_on_off_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(generic_on_off_set_t, trans_time); + } + msg.on_off = on_off; + msg.tid = tid; + return generic_on_off_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +static bool generic_on_off_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_ON_OFF_STAT: + { + generic_on_off_stat_p pmsg = (generic_on_off_stat_p)pbuffer; + generic_on_off_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.present_on_off = pmsg->present_on_off; + status_data.optional = FALSE; + if (pmesh_msg->msg_len == sizeof(generic_on_off_stat_t)) + { + status_data.optional = TRUE; + status_data.target_on_off = pmsg->target_on_off; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_ON_OFF_CLIENT_STATUS, + &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_on_off_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_ON_OFF_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_on_off_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic on off client reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_server.c new file mode 100644 index 00000000..4eed7919 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_server.c @@ -0,0 +1,457 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_on_off_server.c +* @brief Source file for generic on off server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-11 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "generic_on_off.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +typedef struct +{ + uint8_t tid; + generic_on_off_t target_on_off; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} generic_on_off_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} generic_on_off_process_result_t; + + +static mesh_msg_send_cause_t generic_on_off_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_on_off_t present_on_off, bool optional, + generic_on_off_t target_on_off, generic_transition_time_t remaining_time, + uint32_t delay_time) +{ + generic_on_off_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_OFF_STAT); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(generic_on_off_stat_t); + msg.target_on_off = target_on_off; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(generic_on_off_stat_t, target_on_off); + } + msg.present_on_off = present_on_off; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t generic_on_off_delay_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = generic_on_off_stat(pmodel_info, 0, 0, on_off, FALSE, on_off, trans_time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t generic_on_off_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off) +{ + return generic_on_off_delay_publish(pmodel_info, on_off, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void generic_on_off_state_change_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off, generic_on_off_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_on_off_publish(pmodel_info, on_off); + } +} +#endif + +static generic_on_off_t get_present_on_off(const mesh_model_info_p pmodel_info) +{ + generic_on_off_server_get_t get_data = {GENERIC_OFF}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_ON_OFF_SERVER_GET, &get_data); + } + + return get_data.on_off; +} + +static int32_t generic_on_off_trans_step_change(const mesh_model_info_p pmodel_info, uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = MODEL_SUCCESS; + generic_on_off_server_set_t set_data; + generic_on_off_info_t *ponoff_info = pmodel_info->pargs; + if (NULL == ponoff_info) + { + return 0; + } + set_data.on_off = ponoff_info->target_on_off; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_ON_OFF_SERVER_SET, &set_data); + } + + if (0 == remaining_time.num_steps) + { + generic_on_off_t present_on_off = get_present_on_off(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + generic_on_off_delay_publish(pmodel_info, present_on_off, ponoff_info->delay_pub_time); +#else + generic_on_off_publish(pmodel_info, present_on_off); +#endif + } + + return ret; +} + +static generic_on_off_t generic_on_off_process(const mesh_model_info_p pmodel_info, + generic_on_off_t target_on_off, + generic_transition_time_t trans_time, + generic_on_off_process_result_t *presult) +{ + generic_on_off_t on_off_before_set; + generic_on_off_t on_off_after_set; + + /* get generic on/off before set */ + on_off_before_set = get_present_on_off(pmodel_info); + on_off_after_set = on_off_before_set; + + int32_t ret = MODEL_SUCCESS; + generic_on_off_server_set_t trans_set_data; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + trans_set_data.on_off = target_on_off; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_ON_OFF_SERVER_SET, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_ON_OFF, trans_time, + generic_on_off_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_ON_OFF_SERVER_SET, &trans_set_data); + } + } +#endif + } + else + { + /* get on/off after set */ + on_off_after_set = get_present_on_off(pmodel_info); + } + + if (on_off_before_set != on_off_after_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return on_off_after_set; +} + +static int32_t generic_on_off_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_ON_OFF: + { + generic_on_off_info_t *ponoff_info = pmodel_info->pargs; + if (NULL == ponoff_info) + { + return 0; + } + ponoff_info->delay_time = 0; + generic_on_off_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + generic_on_off_t present_on_off = generic_on_off_process(pmodel_info, ponoff_info->target_on_off, + ponoff_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_on_off_delay_publish(pmodel_info, present_on_off, ponoff_info->delay_pub_time); + } + } +#else + generic_on_off_state_change_publish(pmodel_info, present_on_off, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +/** + * @brief default generic on/off server receive function + * @param[in] pmesh_msg: received mesh message + * @return process result + */ +static bool generic_on_off_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_ON_OFF_GET: + if (pmesh_msg->msg_len == sizeof(generic_on_off_get_t)) + { + /* get present on/off status */ + generic_on_off_t present_on_off = get_present_on_off(pmodel_info); + /* get target on/off status*/ + generic_on_off_info_t *ponoff_info = pmodel_info->pargs; + /* get remaining time */ + generic_transition_time_t remaining_time; + if (ponoff_info->delay_time > 0) + { + remaining_time = ponoff_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_ON_OFF); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_on_off_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_on_off, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + ponoff_info->target_on_off, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_ON_OFF_SET: + case MESH_MSG_GENERIC_ON_OFF_SET_UNACK: + { + generic_on_off_set_t *pmsg = (generic_on_off_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(generic_on_off_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_ON_OFF_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(generic_on_off_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_ON_OFF_VALID(pmsg->on_off) && + IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + generic_on_off_info_t *ponoff_info = pmodel_info->pargs; + ponoff_info->tid = pmsg->tid; + ponoff_info->target_on_off = pmsg->on_off; + ponoff_info->trans_time = trans_time; + ponoff_info->delay_time = delay_time; + + generic_on_off_t present_on_off; + generic_on_off_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_on_off = get_present_on_off(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_ON_OFF, delay_time, + generic_on_off_delay_execution); + } + else + { + present_on_off = generic_on_off_process(pmodel_info, ponoff_info->target_on_off, trans_time, + &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_ON_OFF_SET) + { + generic_on_off_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_on_off, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + ponoff_info->target_on_off, trans_time, delay_rsp_time); + } + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_ON_OFF_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + generic_on_off_delay_publish(pmodel_info, present_on_off, delay_pub_time); + } + } + else + { + ponoff_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + generic_on_off_state_change_publish(pmodel_info, present_on_off, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t generic_on_off_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + generic_transition_time_t trans_time = {0, 0}; + generic_on_off_stat(pmodel_info, 0, 0, get_present_on_off(pmodel_info), FALSE, GENERIC_OFF, + trans_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void generic_on_off_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == generic_on_off_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_ON_OFF); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_ON_OFF); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool generic_on_off_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_ON_OFF_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(generic_on_off_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("generic_on_off_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(generic_on_off_info_t)); + + pmodel_info->model_receive = generic_on_off_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_on_off_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = generic_on_off_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_on_off_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level.h new file mode 100644 index 00000000..af914f76 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level.h @@ -0,0 +1,390 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_level.h +* @brief Head file for generic power level models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-25 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_POWER_LEVEL_H +#define _GENERIC_POWER_LEVEL_H + +#include "mesh_api.h" +#include "generic_transition_time.h" +#include "generic_types.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_POWER_LEVEL + * @{ + */ + +/** + * @defgroup GENERIC_POWER_LEVEL_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_POWER_LEVEL_GET 0x8215 +#define MESH_MSG_GENERIC_POWER_LEVEL_SET 0x8216 +#define MESH_MSG_GENERIC_POWER_LEVEL_SET_UNACK 0x8217 +#define MESH_MSG_GENERIC_POWER_LEVEL_STAT 0x8218 +#define MESH_MSG_GENERIC_POWER_LAST_GET 0x8219 +#define MESH_MSG_GENERIC_POWER_LAST_STAT 0x821A +#define MESH_MSG_GENERIC_POWER_DEFAULT_GET 0x821B +#define MESH_MSG_GENERIC_POWER_DEFAULT_STAT 0x821C +#define MESH_MSG_GENERIC_POWER_RANGE_GET 0x821D +#define MESH_MSG_GENERIC_POWER_RANGE_STAT 0x821E +#define MESH_MSG_GENERIC_POWER_DEFAULT_SET 0x821F +#define MESH_MSG_GENERIC_POWER_DEFAULT_SET_UNACK 0x8220 +#define MESH_MSG_GENERIC_POWER_RANGE_SET 0x8221 +#define MESH_MSG_GENERIC_POWER_RANGE_SET_UNACK 0x8222 +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_POWER_LEVEL_SERVER 0x1009FFFF +#define MESH_MODEL_GENERIC_POWER_LEVEL_SETUP_SERVER 0x100AFFFF +#define MESH_MODEL_GENERIC_POWER_LEVEL_CLIENT 0x100BFFFF +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_MESH_MSG Mesh Msg + * @brief Message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_LEVEL_GET)]; +} _PACKED4_ generic_power_level_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_LEVEL_SET)]; + uint16_t power; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ generic_power_level_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_LEVEL_STAT)]; + uint16_t present_power; + uint16_t target_power; //!< optional + /* If the Target Power field is present, the Remaining Time field shall also be present; + otherwise these fields shall not be present. */ + generic_transition_time_t remaining_time; +} _PACKED4_ generic_power_level_stat_t, *generic_power_level_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_LAST_GET)]; +} _PACKED4_ generic_power_last_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_LAST_STAT)]; + uint16_t power; +} _PACKED4_ generic_power_last_stat_t, *generic_power_last_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_DEFAULT_GET)]; +} _PACKED4_ generic_power_default_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_DEFAULT_SET)]; + uint16_t power; +} _PACKED4_ generic_power_default_set_t, *generic_power_default_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_DEFAULT_STAT)]; + uint16_t power; +} _PACKED4_ generic_power_default_stat_t, *generic_power_default_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_RANGE_GET)]; +} _PACKED4_ generic_power_range_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_RANGE_SET)]; + uint16_t range_min; + uint16_t range_max; +} _PACKED4_ generic_power_range_set_t, *generic_power_range_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_POWER_RANGE_STAT)]; + generic_stat_t stat; + uint16_t range_min; + uint16_t range_max; +} _PACKED4_ generic_power_range_stat_t, *generic_power_range_stat_p; +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_POWER_LEVEL 0 +#define DELAY_EXECUTION_TYPE_POWER_LEVEL 0 +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_POWER_LEVEL_SERVER_GET 0 //!< @ref generic_power_level_server_get_t +#define GENERIC_POWER_LEVEL_SERVER_GET_DEFAULT 1 //!< @ref generic_power_level_server_get_t +#define GENERIC_POWER_LEVEL_SERVER_GET_LAST 2 //!< @ref generic_power_level_server_get_t +#define GENERIC_POWER_LEVEL_SERVER_GET_RANGE 3 //!< @ref generic_power_level_server_get_range_t +#define GENERIC_POWER_LEVEL_SERVER_GET_DEFAULT_TRANSITION_TIME 4 //!< @ref generic_power_level_server_get_default_transition_time_t +#define GENERIC_POWER_LEVEL_SERVER_SET 5 //!< @ref generic_power_level_server_set_t +#define GENERIC_POWER_LEVEL_SERVER_SET_LAST 6 //!< @ref generic_power_level_server_set_last_t +#define GENERIC_POWER_LEVEL_SERVER_SET_DEFAULT 7 //!< @ref generic_power_level_server_set_default_t +#define GENERIC_POWER_LEVEL_SERVER_SET_RANGE 8 //!< @ref generic_power_level_server_set_range_t + +typedef struct +{ + uint16_t power; +} generic_power_level_server_get_t; + +typedef struct +{ + uint16_t range_min; + uint16_t range_max; +} generic_power_level_server_get_range_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} generic_power_level_server_get_default_transition_time_t; + +typedef struct +{ + uint16_t power; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} generic_power_level_server_set_t; + +typedef struct +{ + uint16_t power; +} generic_power_level_server_set_last_t; + +typedef struct +{ + uint16_t power; +} generic_power_level_server_set_default_t; + +typedef struct +{ + uint16_t range_min; + uint16_t range_max; +} generic_power_level_server_set_range_t; + +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_POWER_LEVEL_CLIENT_STATUS 0 //!< @ref generic_power_level_client_status_t +#define GENERIC_POWER_LEVEL_CLIENT_STATUS_LAST 1 //!< @ref generic_power_level_client_status_simple_t +#define GENERIC_POWER_LEVEL_CLIENT_STATUS_DEFAULT 2 //!< @ref generic_power_level_client_status_simple_t +#define GENERIC_POWER_LEVEL_CLIENT_STATUS_RANGE 3 //!< @ref generic_power_level_client_status_range_t + +typedef struct +{ + uint16_t src; + uint16_t present_power; + bool optional; + uint16_t target_power; + generic_transition_time_t remaining_time; +} generic_power_level_client_status_t; + +typedef struct +{ + uint16_t src; + uint16_t power; +} generic_power_level_client_status_simple_t; + +typedef struct +{ + uint16_t src; + generic_stat_t stat; + uint16_t range_min; + uint16_t range_max; +} generic_power_level_client_status_range_t; +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic power level server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic power level server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_power_level_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register generic power level setup server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic power level setup server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_power_level_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic power level status + * @param[in] pmodel_info: pointer to generic power level server model context + * @param[in] power: power status need to publish + * @return publish status + */ +mesh_msg_send_cause_t generic_power_level_publish(const mesh_model_info_p pmodel_info, + uint16_t power); + +/** + * @brief convert generic power level value to level value + * @param[in] power: genric power level value + * @return generic level value + */ +int16_t generic_power_level_to_generic_level(uint16_t power); + +/** + * @brief convert generic level value to generic power level value + * @param[in] level: generic level value + * @return generic power level value + */ +uint16_t generic_level_to_power_level(int16_t level); + +/** @} */ + +/** + * @defgroup GENERIC_POWER_LEVEL_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic power level client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic power level client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_power_level_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get generic power level value + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_power_level_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set generic power level + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] power: desired power level value + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_power_level_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint16_t power, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get generic power level last value + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_power_last_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get generic power level default value + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_power_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set generic power level default value + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] power: default power level + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_power_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t power, bool ack); + +/** + * @brief get generic power level range + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_power_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set generic power level range + * @param[in] pmodel_info: pointer to generic power level client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] range_min: power level minimum value + * @param[in] range_max: power level maximum value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_power_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t range_min, uint16_t range_max, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_POWER_LEVEL_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_client.c new file mode 100644 index 00000000..05df10a1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_client.c @@ -0,0 +1,226 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_level_client.c +* @brief Source file for generic power level client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_power_level.h" + +static mesh_msg_send_cause_t generic_power_level_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_power_level_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_power_level_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_LEVEL_GET); + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_power_level_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint16_t power, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + generic_power_level_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_LEVEL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_LEVEL_SET_UNACK); + } + + if (optional) + { + len = sizeof(generic_power_level_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(generic_power_level_set_t, trans_time); + } + msg.power = power; + msg.tid = tid; + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t generic_power_last_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_power_last_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_LAST_GET); + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_power_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_power_default_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_DEFAULT_GET); + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_power_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t power, bool ack) +{ + generic_power_default_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_DEFAULT_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_DEFAULT_SET_UNACK); + } + msg.power = power; + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_power_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_power_range_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_RANGE_GET); + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_power_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t range_min, uint16_t range_max, bool ack) +{ + generic_power_range_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_RANGE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_RANGE_SET_UNACK); + } + msg.range_min = range_min; + msg.range_max = range_max; + return generic_power_level_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +static bool generic_power_level_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_POWER_LEVEL_STAT: + { + generic_power_level_stat_p pmsg = (generic_power_level_stat_p)pbuffer; + generic_power_level_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_power = pmsg->present_power; + if (pmesh_msg->msg_len == sizeof(generic_power_level_stat_t)) + { + status_data.optional = TRUE; + status_data.target_power = pmsg->target_power; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_POWER_LEVEL_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_GENERIC_POWER_LAST_STAT: + if (pmesh_msg->msg_len == sizeof(generic_power_last_stat_t)) + { + generic_power_last_stat_p pmsg = (generic_power_last_stat_p)pbuffer; + generic_power_level_client_status_simple_t status_last = {pmesh_msg->src, pmsg->power}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + GENERIC_POWER_LEVEL_CLIENT_STATUS_LAST, &status_last); + } + + } + break; + case MESH_MSG_GENERIC_POWER_DEFAULT_STAT: + if (pmesh_msg->msg_len == sizeof(generic_power_default_stat_t)) + { + generic_power_default_stat_p pmsg = (generic_power_default_stat_p)pbuffer; + generic_power_level_client_status_simple_t status_default = {pmesh_msg->src, pmsg->power}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + GENERIC_POWER_LEVEL_CLIENT_STATUS_DEFAULT, + &status_default); + } + + } + break; + case MESH_MSG_GENERIC_POWER_RANGE_STAT: + if (pmesh_msg->msg_len == sizeof(generic_power_range_stat_t)) + { + generic_power_range_stat_p pmsg = (generic_power_range_stat_p)pbuffer; + generic_power_level_client_status_range_t status_range = {pmesh_msg->src, pmsg->stat, pmsg->range_min, pmsg->range_max}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + GENERIC_POWER_LEVEL_CLIENT_STATUS_RANGE, + &status_range); + } + + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_power_level_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_POWER_LEVEL_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_power_level_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_power_level_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_server.c new file mode 100644 index 00000000..6e1d45ea --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_server.c @@ -0,0 +1,576 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_level_server.c +* @brief Source file for generic power level server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-27 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_power_level.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +typedef struct +{ + uint8_t tid; + uint16_t target_power; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} generic_power_level_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} generic_power_level_process_result_t; + +int16_t generic_power_level_to_generic_level(uint16_t power) +{ + return power - 32768; +} + +uint16_t generic_level_to_power_level(int16_t level) +{ + return level + 32768; +} + +static mesh_msg_send_cause_t generic_power_level_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, uint8_t *pmsg, uint16_t msg_len, + uint16_t app_key_index, uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (dst != 0) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t generic_power_level_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint16_t present_power, bool optional, uint16_t target_power, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + generic_power_level_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_LEVEL_STAT); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(generic_power_level_stat_t); + msg.target_power = target_power; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(generic_power_level_stat_t, target_power); + } + msg.present_power = present_power; + return generic_power_level_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, + delay_time); +} + +mesh_msg_send_cause_t generic_power_level_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t power, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t remaining_time = {0, 0}; + ret = generic_power_level_stat(pmodel_info, 0, 0, power, FALSE, power, remaining_time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t generic_power_level_publish(const mesh_model_info_p pmodel_info, + uint16_t power) +{ + return generic_power_level_delay_publish(pmodel_info, power, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void generic_power_level_state_change_publish(const mesh_model_info_p pmodel_info, + uint16_t power, generic_power_level_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_power_level_publish(pmodel_info, power); + } +} +#endif + +static mesh_msg_send_cause_t generic_power_last_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t power, uint32_t delay_time) +{ + generic_power_last_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_LAST_STAT); + msg.power = power; + return generic_power_level_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), + app_key_index, delay_time); +} + +mesh_msg_send_cause_t generic_power_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t power, uint32_t delay_time) +{ + generic_power_default_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_DEFAULT_STAT); + msg.power = power; + return generic_power_level_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), + app_key_index, delay_time); +} + +mesh_msg_send_cause_t generic_power_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t range_min, uint16_t range_max, + uint32_t delay_time) +{ + generic_power_range_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_POWER_RANGE_STAT); + msg.stat = stat; + msg.range_min = range_min; + msg.range_max = range_max; + return generic_power_level_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), + app_key_index, delay_time); +} + +static uint16_t get_present_power_level(const mesh_model_info_p pmodel_info) +{ + generic_power_level_server_get_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_GET, &get_data); + } + + return get_data.power; +} + +static int32_t generic_power_level_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + int32_t ret = MODEL_SUCCESS; + generic_power_level_server_set_t set_data; + generic_power_level_info_t *ppower_level_info = pmodel_info->pargs; + if (NULL == ppower_level_info) + { + return 0; + } + set_data.power = ppower_level_info->target_power; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_SET, &set_data); + } + + if (0 == remaining_time.num_steps) + { + uint16_t present_level = get_present_power_level(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + generic_power_level_delay_publish(pmodel_info, present_level, ppower_level_info->delay_pub_time); +#else + generic_power_level_publish(pmodel_info, present_level); +#endif + } + + return ret; +} + +static uint16_t generic_power_level_process(const mesh_model_info_p pmodel_info, + uint16_t target_power, + generic_transition_time_t trans_time, + generic_power_level_process_result_t *presult) +{ + uint16_t power_before_set = 0; + uint16_t power_after_set = 0; + + /* get generic power level before set */ + power_before_set = get_present_power_level(pmodel_info); + power_after_set = power_before_set; + + int32_t ret = MODEL_SUCCESS; + generic_power_level_server_set_t trans_set_data; + trans_set_data.power = target_power; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_SET, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_POWER_LEVEL, trans_time, + generic_power_level_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_SET, &trans_set_data); + } + } +#endif + } + else + { + /* get level after set */ + power_after_set = get_present_power_level(pmodel_info); + } + + if (power_before_set != power_after_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + if (0 != target_power) + { + if (NULL != pmodel_info->model_data_cb) + { + generic_power_level_server_set_last_t set_last = {target_power}; + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_SET_LAST, &set_last); + } + } + + return power_after_set; +} + +static int32_t generic_power_level_delay_execution(mesh_model_info_t *pmodel_info, + uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_POWER_LEVEL: + { + generic_power_level_info_t *ppower_level_info = pmodel_info->pargs; + if (NULL == ppower_level_info) + { + return 0; + } + ppower_level_info->delay_time = 0; + generic_power_level_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + uint16_t present_power = generic_power_level_process(pmodel_info, ppower_level_info->target_power, + ppower_level_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + generic_power_level_delay_publish(pmodel_info, present_power, ppower_level_info->delay_pub_time); + } + } +#else + generic_power_level_state_change_publish(pmodel_info, present_power, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool generic_power_level_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_POWER_LEVEL_GET: + if (pmesh_msg->msg_len == sizeof(generic_power_level_get_t)) + { + generic_power_level_info_t *ppower_level_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (ppower_level_info->delay_time > 0) + { + remaining_time = ppower_level_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_POWER_LEVEL); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_power_level_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_power_level(pmodel_info), + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + ppower_level_info->target_power, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_POWER_LEVEL_SET: + case MESH_MSG_GENERIC_POWER_LEVEL_SET_UNACK: + { + generic_power_level_set_t *pmsg = (generic_power_level_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(generic_power_level_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(generic_power_level_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + generic_power_level_server_get_range_t range = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_GET_RANGE, &range); + } + + generic_power_level_info_t *ppower_level_info = pmodel_info->pargs; + if ((0 != range.range_min) && (0 != range.range_max)) + { + ppower_level_info->target_power = CLAMP(pmsg->power, range.range_min, range.range_max); + } + else + { + ppower_level_info->target_power = pmsg->power; + } + ppower_level_info->tid = pmsg->tid; + ppower_level_info->trans_time = trans_time; + ppower_level_info->delay_time = delay_time; + + uint16_t present_power; + generic_power_level_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_power = get_present_power_level(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_POWER_LEVEL, delay_time, + generic_power_level_delay_execution); + } + else + { + present_power = generic_power_level_process(pmodel_info, + ppower_level_info->target_power, + trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_POWER_LEVEL_SET) + { + generic_power_level_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_power, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + ppower_level_info->target_power, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_POWER_LEVEL_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + generic_power_level_delay_publish(pmodel_info, present_power, delay_pub_time); + } + } + else + { + ppower_level_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, + delay_rsp_time, FALSE, ack); + } +#else + generic_power_level_state_change_publish(pmodel_info, present_power, result); +#endif + } + } + break; + case MESH_MSG_GENERIC_POWER_LAST_GET: + if (pmesh_msg->msg_len == sizeof(generic_power_last_get_t)) + { + generic_power_level_server_get_t last_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_GET_LAST, + &last_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_power_last_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + last_data.power, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_POWER_DEFAULT_GET: + if (pmesh_msg->msg_len == sizeof(generic_power_default_get_t)) + { + generic_power_level_server_get_t default_data = {0}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, + GENERIC_POWER_LEVEL_SERVER_GET_DEFAULT, + &default_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_power_default_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + default_data.power, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_POWER_RANGE_GET: + if (pmesh_msg->msg_len == sizeof(generic_power_range_get_t)) + { + generic_power_level_server_get_range_t range_data = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_LEVEL_SERVER_GET_RANGE, + &range_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_power_range_stat(pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, GENERIC_STAT_SUCCESS, + range_data.range_min, range_data.range_max, delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t generic_power_level_server_publish(const mesh_model_info_p pmodel_info, bool retrans) +{ + generic_transition_time_t remaining_time = {0, 0}; + generic_power_level_stat(pmodel_info, 0, 0, get_present_power_level(pmodel_info), FALSE, 0, + remaining_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void generic_power_level_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == generic_power_level_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_POWER_LEVEL); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_POWER_LEVEL); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool generic_power_level_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_POWER_LEVEL_SERVER; + if (NULL == pmodel_info->model_receive) + { + generic_power_level_info_t *ppower_level_info = plt_malloc(sizeof(generic_power_level_info_t), + RAM_TYPE_DATA_ON); + if (NULL == ppower_level_info) + { + printe("generic_power_level_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(ppower_level_info, 0, sizeof(generic_power_level_info_t)); + pmodel_info->pargs = ppower_level_info; + + pmodel_info->model_receive = generic_power_level_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_power_level_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = generic_power_level_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_power_level_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_setup_server.c new file mode 100644 index 00000000..7fd6477d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_setup_server.c @@ -0,0 +1,110 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_level_setup_server.c +* @brief Source file for generic on off server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-27 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_power_level.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t generic_power_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t power, uint32_t delay_time); +extern mesh_msg_send_cause_t generic_power_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, + uint16_t range_min, uint16_t range_max, uint32_t delay_time); + +static bool generic_power_level_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_POWER_DEFAULT_SET: + case MESH_MSG_GENERIC_POWER_DEFAULT_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_power_default_set_t)) + { + generic_power_default_set_p pmsg = (generic_power_default_set_p)pbuffer; + generic_power_level_server_set_default_t set_default = {pmsg->power}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + GENERIC_POWER_LEVEL_SERVER_SET_DEFAULT, &set_default); + } + + if (MESH_MSG_GENERIC_POWER_DEFAULT_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_power_default_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->power, delay_rsp_time); + } + } + break; + case MESH_MSG_GENERIC_POWER_RANGE_SET: + case MESH_MSG_GENERIC_POWER_RANGE_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_power_range_set_t)) + { + generic_power_range_set_p pmsg = (generic_power_range_set_p)pbuffer; + if ((pmsg->range_min <= pmsg->range_max) && + (0 != pmsg->range_min) && + (0 != pmsg->range_max)) + { + generic_power_level_server_set_range_t set_range = {pmsg->range_min, pmsg->range_max}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_POWER_LEVEL_SERVER_SET_RANGE, + &set_range); + } + + if (MESH_MSG_GENERIC_POWER_RANGE_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_power_range_stat(pmesh_msg->pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, GENERIC_STAT_SUCCESS, + pmsg->range_min, pmsg->range_max, delay_rsp_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_power_level_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_POWER_LEVEL_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_power_level_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_power_level_setup_server_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off.h new file mode 100644 index 00000000..140072e7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off.h @@ -0,0 +1,196 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_on_off.h +* @brief Head file for generic power on off models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-25 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_POWER_ON_OFF_H +#define _GENERIC_POWER_ON_OFF_H + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_ON_POWER_UP + * @{ + */ + +/** + * @defgroup GENERIC_ON_POWER_UP_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_ON_POWER_UP_GET 0x8211 +#define MESH_MSG_GENERIC_ON_POWER_UP_STAT 0x8212 +#define MESH_MSG_GENERIC_ON_POWER_UP_SET 0x8213 +#define MESH_MSG_GENERIC_ON_POWER_UP_SET_UNACK 0x8214 +/** @} */ + +/** + * @defgroup GENERIC_ON_POWER_UP_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_POWER_ON_OFF_SERVER 0x1006FFFF +#define MESH_MODEL_GENERIC_POWER_ON_OFF_SETUP_SERVER 0x1007FFFF +#define MESH_MODEL_GENERIC_POWER_ON_OFF_CLIENT 0x1008FFFF +/** @} */ + +/** + * @defgroup GENERIC_ON_POWER_UP_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +enum +{ + /* After being powered up, the element is in an off state. */ + GENERIC_ON_POWER_UP_OFF, + /* After being powered up, the element is in an On state and uses default state values. */ + GENERIC_ON_POWER_UP_DEFAULT, + /* If a transition was in progress when powered down, the element restores the target state when powered up. + Otherwise the element restores the state it was in when powered down. */ + GENERIC_ON_POWER_UP_RESTORE +} _SHORT_ENUM_; +typedef uint8_t generic_on_power_up_t; + +#define IS_GENERIC_ON_POWER_UP_VALID(power) ((power) <= GENERIC_ON_POWER_UP_RESTORE) + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ON_POWER_UP_GET)]; +} _PACKED4_ generic_on_power_up_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ON_POWER_UP_SET)]; + generic_on_power_up_t on_power_up; +} _PACKED4_ generic_on_power_up_set_t, *generic_on_power_up_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ON_POWER_UP_STAT)]; + generic_on_power_up_t on_power_up; +} _PACKED4_ generic_on_power_up_stat_t, *generic_on_power_up_stat_p; +/** @} */ + +/** + * @defgroup GENERIC_POWER_ON_OFF_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_POWER_ON_OFF_SERVER_GET 0 //!< @ref generic_power_on_off_server_get_t +#define GENERIC_POWER_ON_OFF_SERVER_SET 1 //!< @ref generic_power_on_off_server_set_t + +typedef struct +{ + generic_on_power_up_t on_power_up; +} generic_power_on_off_server_get_t; + +typedef struct +{ + generic_on_power_up_t on_power_up; +} generic_power_on_off_server_set_t; +/** @} */ + +/** + * @defgroup GENERIC_POWER_ON_OFF_CILENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_POWER_ON_OFF_CLIENT_STATUS 0 //!< @ref generic_power_on_off_client_status_t + +typedef struct +{ + uint16_t src; + generic_on_power_up_t on_power_up; +} generic_power_on_off_client_status_t; +/** @} */ + + +/** + * @defgroup GENERIC_POWER_ON_OFF_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic power on/off server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic power on/off server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_power_on_off_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish on power up status + * @param[in] pmodel_info: pointer to generic power on/off server model context + * @param[in] on_power_up: on power up status + * @return send status + */ +mesh_msg_send_cause_t generic_on_power_up_publish(const mesh_model_info_p pmodel_info, + generic_on_power_up_t on_power_up); + +/** + * @brief register generic power on/off setup server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic power on/off setup model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_power_on_off_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); +/** @} */ + +/** + * @defgroup GENERIC_POWER_ON_OFF_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic power on/off client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic power on/off client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool generic_power_on_off_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get generic on power up status + * @param[in] pmodel_info: pointer to generic power on off client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_on_power_up_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index); +/** + * @brief set generic on power up + * @param[in] pmodel_info: pointer to generic power on off client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] on_power_up: desired on power up value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_on_power_up_set(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, + generic_on_power_up_t on_power_up, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_POWER_ON_OFF_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_client.c new file mode 100644 index 00000000..8a5ff4f9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_client.c @@ -0,0 +1,104 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_on_off_client.c +* @brief Source file for generic power on off client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_power_on_off.h" + +static mesh_msg_send_cause_t generic_power_on_off_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_on_power_up_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index) +{ + generic_on_power_up_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_POWER_UP_GET); + return generic_power_on_off_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t generic_on_power_up_set(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, + generic_on_power_up_t on_power_up, bool ack) +{ + generic_on_power_up_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_POWER_UP_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_POWER_UP_SET_UNACK); + } + msg.on_power_up = on_power_up; + return generic_power_on_off_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +static bool generic_power_on_off_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_ON_POWER_UP_STAT: + if (pmesh_msg->msg_len == sizeof(generic_on_power_up_stat_t)) + { + generic_on_power_up_stat_p pmsg = (generic_on_power_up_stat_p)pbuffer; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + generic_power_on_off_client_status_t status_data = {pmesh_msg->src, pmsg->on_power_up}; + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_POWER_ON_OFF_CLIENT_STATUS, + &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool generic_power_on_off_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_POWER_ON_OFF_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_power_on_off_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_power_on_off_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_server.c new file mode 100644 index 00000000..bded3ee6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_server.c @@ -0,0 +1,117 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_on_off_server.c +* @brief Source file for generic power on off server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-17 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_power_on_off.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +mesh_msg_send_cause_t generic_on_power_up_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_on_power_up_t on_power_up, uint32_t delay_time) +{ + generic_on_power_up_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ON_POWER_UP_STAT); + msg.on_power_up = on_power_up; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = sizeof(generic_on_power_up_stat_t); + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_on_power_up_publish(const mesh_model_info_p pmodel_info, + generic_on_power_up_t on_power_up) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_on_power_up_stat(pmodel_info, 0, 0, on_power_up, 0); + } + + return ret; +} + +static generic_on_power_up_t get_present_power_on_off(const mesh_model_info_p pmodel_info) +{ + generic_power_on_off_server_get_t get_data = {GENERIC_ON_POWER_UP_OFF}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_POWER_ON_OFF_SERVER_GET, + &get_data); + } + return get_data.on_power_up; +} + +static bool generic_power_on_off_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + //uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_ON_POWER_UP_GET: + if (pmesh_msg->msg_len == sizeof(generic_on_power_up_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_on_power_up_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_power_on_off(pmesh_msg->pmodel_info), delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t generic_power_on_off_server_publish(const mesh_model_info_p pmodel_info, + bool retrans) +{ + generic_on_power_up_stat(pmodel_info, 0, 0, get_present_power_on_off(pmodel_info), 0); + return 0; +} + +bool generic_power_on_off_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_POWER_ON_OFF_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_power_on_off_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_power_on_off_server_reg: missing model data process callback!"); + } + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = generic_power_on_off_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_setup_server.c new file mode 100644 index 00000000..e682d4a0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_setup_server.c @@ -0,0 +1,84 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_power_on_off_setup_server.c +* @brief Source file for generic power on off setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-17 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "generic_power_on_off.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +extern mesh_msg_send_cause_t generic_on_power_up_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_on_power_up_t on_power_up, uint32_t delay_time); + + +static bool generic_power_on_off_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_ON_POWER_UP_SET: + case MESH_MSG_GENERIC_ON_POWER_UP_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(generic_on_power_up_set_t)) + { + generic_on_power_up_set_p pmsg = (generic_on_power_up_set_p)pbuffer; + if (IS_GENERIC_ON_POWER_UP_VALID(pmsg->on_power_up)) + { + generic_power_on_off_server_set_t set_data = {pmsg->on_power_up}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, GENERIC_POWER_ON_OFF_SERVER_SET, + &set_data); + } + + if (MESH_MSG_GENERIC_ON_POWER_UP_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_on_power_up_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->on_power_up, delay_rsp_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + + +bool generic_power_on_off_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_POWER_ON_OFF_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_power_on_off_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_power_on_off_setup_server_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property.h new file mode 100644 index 00000000..95f881ac --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property.h @@ -0,0 +1,525 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_property.h +* @brief Head file for generic property models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-06-28 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_PROPERTY_H +#define _GENERIC_PROPERTY_H + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_PROPERTY + * @{ + */ + +/** + * @defgroup GENERIC_PROPERTY_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_GET 0x822A +#define MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_STATUS 0x43 +#define MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_GET 0x822B +#define MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET 0x44 +#define MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET_UNACK 0x45 +#define MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_STATUS 0x46 + +#define MESH_MSG_GENERIC_ADMIN_PROPERTIES_GET 0x822C +#define MESH_MSG_GENERIC_ADMIN_PROPERTIES_STATUS 0x47 +#define MESH_MSG_GENERIC_ADMIN_PROPERTY_GET 0x822D +#define MESH_MSG_GENERIC_ADMIN_PROPERTY_SET 0x48 +#define MESH_MSG_GENERIC_ADMIN_PROPERTY_SET_UNACK 0x49 +#define MESH_MSG_GENERIC_ADMIN_PROPERTY_STATUS 0x4A + +#define MESH_MSG_GENERIC_USER_PROPERTIES_GET 0x822E +#define MESH_MSG_GENERIC_USER_PROPERTIES_STATUS 0x4B +#define MESH_MSG_GENERIC_USER_PROPERTY_GET 0x822F +#define MESH_MSG_GENERIC_USER_PROPERTY_SET 0x4C +#define MESH_MSG_GENERIC_USER_PROPERTY_SET_UNACK 0x4D +#define MESH_MSG_GENERIC_USER_PROPERTY_STATUS 0x4E + +#define MESH_MSG_GENERIC_CLIENT_PROPERTIES_GET 0x4F +#define MESH_MSG_GENERIC_CLIENT_PROPERTIES_STATUS 0x50 +/** @} */ + +/** + * @defgroup GENERIC_PROPERTY_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_GENERIC_ADMIN_PROPERTY_SERVER 0x1011FFFF +#define MESH_MODEL_GENERIC_MANUFACTURER_PROPERTY_SERVER 0x1012FFFF +#define MESH_MODEL_GENERIC_USER_PROPERTY_SERVER 0x1013FFFF +#define MESH_MODEL_GENERIC_CLIENT_PROPERTY_SERVER 0x1014FFFF +#define MESH_MODEL_GENERIC_PROPERTY_CLIENT 0x1015FFFF +/** @} */ + +/** + * @defgroup GENERIC_PROPERTY_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define GENERIC_PROPERTY_ID_PROHIBITED 0x00 + +#define GENERIC_PROPERTY_ACCESS_NOT_TO_USER 0 +#define GENERIC_PROPERTY_ACCESS_READ 1 +#define GENERIC_PROPERTY_ACCESS_WRITE 2 +#define GENERIC_PROPERTY_ACCESS_READ_AND_WRITE 3 + + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_USER_PROPERTIES_GET)]; +} _PACKED4_ generic_user_properties_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_USER_PROPERTIES_STATUS)]; + uint16_t property_ids[0]; //!< variable length +} _PACKED4_ generic_user_properties_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_USER_PROPERTY_GET)]; + uint16_t property_id; +} _PACKED4_ generic_user_property_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_USER_PROPERTY_SET)]; + uint16_t property_id; + uint8_t property_value[0]; //!< variable length +} _PACKED4_ generic_user_property_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_USER_PROPERTY_STATUS)]; + uint16_t property_id; + uint8_t property_access; + uint8_t property_value[0]; //!< variable length +} _PACKED4_ generic_user_property_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ADMIN_PROPERTIES_GET)]; +} _PACKED4_ generic_admin_properties_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ADMIN_PROPERTIES_STATUS)]; + uint16_t property_ids[0]; //!< variable length +} _PACKED4_ generic_admin_properties_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ADMIN_PROPERTY_GET)]; + uint16_t property_id; +} _PACKED4_ generic_admin_property_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ADMIN_PROPERTY_SET)]; + uint16_t property_id; + uint8_t property_access; + uint8_t property_value[0]; //!< variable length +} _PACKED4_ generic_admin_property_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_ADMIN_PROPERTY_STATUS)]; + uint16_t property_id; + uint8_t property_access; + uint8_t property_value[0]; //!< variable length +} _PACKED4_ generic_admin_property_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_GET)]; +} _PACKED4_ generic_manufacturer_properties_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_STATUS)]; + uint16_t property_ids[0]; //!< variable length +} _PACKED4_ generic_manufacturer_properties_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_GET)]; + uint16_t property_id; +} _PACKED4_ generic_manufacturer_property_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET)]; + uint16_t property_id; + uint8_t property_access; +} _PACKED4_ generic_manufacturer_property_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_STATUS)]; + uint16_t property_id; + uint8_t property_access; + uint8_t property_value[0]; //!< variable length +} _PACKED4_ generic_manufacturer_property_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_CLIENT_PROPERTIES_GET)]; + uint16_t property_id; //!< A starting Client Property ID present within an element +} _PACKED4_ generic_client_properties_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_GENERIC_CLIENT_PROPERTIES_STATUS)]; + uint16_t property_ids[0]; //!< variable length +} _PACKED4_ generic_client_properties_status_t; + +typedef struct +{ + uint16_t property_id; + uint8_t property_access; + uint8_t *pproperty_value; //!< variable length + uint16_t value_len; +} generic_property_db_t; + +/** @} */ + +/** + * @defgroup GENERIC_PROPERTY_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_USER_PROPERTY_SERVER_SET 0 //!< @ref generic_user_property_server_set_t +#define GENERIC_ADMIN_PROPERTY_SERVER_SET 1 //!< @ref generic_admin_property_server_set_t +#define GENERIC_MANUFACTURER_PROPERTY_SERVER_SET 2 //!< @ref generic_manufacturer_property_server_set_t +#define GENERIC_CLIENT_PROPERTY_SERVER_GET 3 //!< @ref generic_client_property_server_get_t + +typedef struct +{ + uint16_t property_id; + /* + * just notify property value changed in database, + * do not need to modify it, just use it if needed + */ + uint8_t *pproperty_value; + uint16_t value_len; +} generic_user_property_server_set_t; + +typedef struct +{ + uint16_t property_id; + /* + * just notify property value changed in database, + * do not need to modify it, just use it if needed + */ + uint8_t property_access; + uint8_t *pproperty_value; + uint16_t value_len; +} generic_admin_property_server_set_t; + +typedef struct +{ + uint16_t property_id; + /* + * just notify property access changed in database, + * do not need to modify it, just use it if needed + */ + uint8_t property_access; +} generic_manufacturer_property_server_set_t; + +typedef struct +{ + uint16_t property_id_start; + /* + * app modify pproperty_ids and num_ids field + */ + const uint16_t *pproperty_ids; + uint8_t num_ids; +} generic_client_property_server_get_t; +/** @} */ + +/** + * @defgroup GENERIC_PROPERTY_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define GENERIC_USER_PROPERIES_CLIENT_STATUS 0 //!< @ref generic_properties_client_status_t +#define GENERIC_USER_PROPERTY_CLIENT_STATUS 1 //!< @ref generic_property_client_status_t +#define GENERIC_ADMIN_PROPERTIES_CLIENT_STATUS 2 //!< @ref generic_properties_client_status_t +#define GENERIC_ADMIN_PROPERTY_CLIENT_STATUS 3 //!< @ref generic_property_client_status_t +#define GENERIC_MANUFACTURER_PROPERTIES_CLIENT_STATUS 4 //!< @ref generic_properties_client_status_t +#define GENERIC_MANUFACTURER_PROPERTY_CLIENT_STATUS 5 //!< @ref generic_property_client_status_t +#define GENERIC_CLIENT_PROPERTIES_CLIENT_STATUS 6 //!< @ref generic_properties_client_status_t + +typedef struct +{ + uint16_t src; + const uint16_t *pproperty_ids; + uint8_t num_ids; +} generic_properties_client_status_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint8_t property_access; + uint8_t *pproperty_value; + uint16_t value_len; +} generic_property_client_status_t; +/** @} */ + +/** + * @defgroup GENERIC_PROPERTY_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic user property server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic user property server model context + * @retval true: register success + * @retval false: register failed + */ +bool generic_user_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic user property value + * @param[in] pmodel_info: pointer to generic user property server model context + * @param[in] pdb: generic user property + * @return publish status + */ +mesh_msg_send_cause_t generic_user_property_publish(const mesh_model_info_p pmodel_info, + const generic_property_db_t *pdb); + +/** + * @brief set user defined generic user property database + * @param[in] pmodel_info: pointer to generic user property server model context + * @param[in] pproperties: user defined generic user property database + * @param[in] num_properties: generic user property numbers + */ +void generic_user_property_server_set_db(mesh_model_info_p pmodel_info, + generic_property_db_t *pproperties, uint16_t num_properties); + +/** + * @brief register generic admin property server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic admin property server model context + * @retval true: register success + * @retval false: register failed + */ +bool generic_admin_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic admin property value + * @param[in] pmodel_info: pointer to generic admin property server model context + * @param[in] pdb: generic admin property + * @return publish status + */ +mesh_msg_send_cause_t generic_admin_property_publish(const mesh_model_info_p pmodel_info, + const generic_property_db_t *pdb); + +/** + * @brief set user defined generic admin property database + * @param[in] pmodel_info: pointer to generic admin property server model context + * @param[in] pproperties: user defined generic admin property database + * @param[in] num_properties: generic admin property numbers + */ +void generic_admin_property_server_set_db(mesh_model_info_p pmodel_info, + generic_property_db_t *pproperties, uint16_t num_properties); + +/** + * @brief register generic manufacturer property server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic manufacturer property server model context + * @retval true: register success + * @retval false: register failed + */ +bool generic_manufacturer_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish generic manufacturer property value + * @param[in] pmodel_info: pointer to generic manufacturer property server model context + * @param[in] pdb: generic admin property + * @return publish status + */ +mesh_msg_send_cause_t generic_manufacturer_property_publish(const mesh_model_info_p pmodel_info, + const generic_property_db_t *pdb); + +/** + * @brief set user defined generic manufacturer property database + * @param[in] pmodel_info: pointer to generic manufacturer property server model context + * @param[in] pproperties: user defined generic manufacturer property database + * @param[in] num_properties: generic admin property numbers + */ +void generic_manufacturer_property_server_set_db(mesh_model_info_p pmodel_info, + generic_property_db_t *pproperties, uint16_t num_properties); + +/** + * @brief register generic client property server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic client property server model context + * @retval true: register success + * @retval false: register failed + */ +bool generic_client_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** @} */ + +/** + * @defgroup GENERIC_PROPERTY_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic property client server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic property client server model context + * @retval true: register success + * @retval false: register failed + */ +bool generic_property_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get generic user properties + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_user_properties_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get generic user property + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @return send status + */ +mesh_msg_send_cause_t generic_user_property_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief set generic user property + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @param[in] pvalue: property value + * @param[in] value_len: property value length + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_user_property_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, const uint8_t *pvalue, uint8_t value_len, bool ack); + +/** + * @brief get generic admin properties + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_admin_properties_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get generic admin property + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @return send status + */ +mesh_msg_send_cause_t generic_admin_property_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief set generic admin property + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @param[in] pvalue: property value + * @param[in] value_len: property value length + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_admin_property_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t property_access, + const uint8_t *pvalue, uint8_t value_len, bool ack); + +/** + * @brief get generic manufacturer properties + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_manufacturer_properties_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get generic manufacturer properties + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t generic_manufacturer_property_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief set generic manufacturer property + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @param[in] pvalue: property value + * @param[in] value_len: property value length + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t generic_manufacturer_property_set(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t property_access, bool ack); + +/** + * @brief get generic client properties + * @param[in] pmodel_info: pointer to generic property model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: start property id + * @return send status + */ +mesh_msg_send_cause_t generic_client_properties_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_PROPERTY_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property_client.c new file mode 100644 index 00000000..83ecb522 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property_client.c @@ -0,0 +1,357 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_property_client.c +* @brief Source file for generic property client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-03 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_property.h" + +static mesh_msg_send_cause_t generic_property_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t generic_user_properties_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + generic_user_properties_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_USER_PROPERTIES_GET); + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_user_property_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + generic_user_property_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_USER_PROPERTY_GET); + msg.property_id = property_id; + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_user_property_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, + const uint8_t *pvalue, uint8_t value_len, bool ack) +{ + generic_user_property_set_t *pmsg; + uint16_t msg_len = sizeof(generic_user_property_set_t) + value_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + if (ack) + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_USER_PROPERTY_SET); + } + else + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_USER_PROPERTY_SET_UNACK); + } + pmsg->property_id = property_id; + memcpy(pmsg->property_value, pvalue, value_len); + mesh_msg_send_cause_t ret = generic_property_client_send(pmodel_info, dst, app_key_index, + (uint8_t *)pmsg, msg_len); + + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t generic_admin_properties_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index) +{ + generic_admin_properties_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ADMIN_PROPERTIES_GET); + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_admin_property_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + generic_admin_property_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_ADMIN_PROPERTY_GET); + msg.property_id = property_id; + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_admin_property_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t property_access, + const uint8_t *pvalue, uint8_t value_len, bool ack) +{ + generic_admin_property_set_t *pmsg; + uint16_t msg_len = sizeof(generic_admin_property_set_t) + value_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + if (ack) + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_ADMIN_PROPERTY_SET); + } + else + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_ADMIN_PROPERTY_SET_UNACK); + } + + pmsg->property_id = property_id; + pmsg->property_access = property_access; + memcpy(pmsg->property_value, pvalue, value_len); + mesh_msg_send_cause_t ret = generic_property_client_send(pmodel_info, dst, app_key_index, + (uint8_t *)pmsg, msg_len); + + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t generic_manufacturer_properties_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index) +{ + generic_manufacturer_properties_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_GET); + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_manufacturer_property_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + generic_manufacturer_property_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_GET); + msg.property_id = property_id; + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t generic_manufacturer_property_set(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t property_access, + bool ack) +{ + generic_manufacturer_property_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_SET_UNACK); + } + + msg.property_id = property_id; + msg.property_access = property_access; + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(generic_manufacturer_property_set_t)); +} + +mesh_msg_send_cause_t generic_client_properties_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + generic_client_properties_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_CLIENT_PROPERTIES_GET); + msg.property_id = property_id; + return generic_property_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool generic_property_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_USER_PROPERTIES_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_user_properties_status_t, + property_ids); + generic_user_properties_status_t *pmsg = (generic_user_properties_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_properties_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.pproperty_ids = NULL; + status_data.num_ids = 0; + if (value_len > 0) + { + status_data.pproperty_ids = pmsg->property_ids; + status_data.num_ids = value_len / 2; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_USER_PROPERIES_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_GENERIC_USER_PROPERTY_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_user_property_status_t, + property_value); + generic_user_property_status_t *pmsg = (generic_user_property_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_property_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.property_id = pmsg->property_id; + status_data.property_access = pmsg->property_access; + status_data.pproperty_value = NULL; + status_data.value_len = 0; + if (value_len > 0) + { + status_data.pproperty_value = pmsg->property_value; + status_data.value_len = value_len; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_USER_PROPERTY_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_GENERIC_ADMIN_PROPERTIES_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_admin_properties_status_t, + property_ids); + generic_admin_properties_status_t *pmsg = (generic_admin_properties_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_properties_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.pproperty_ids = NULL; + status_data.num_ids = 0; + if (value_len > 0) + { + status_data.pproperty_ids = pmsg->property_ids; + status_data.num_ids = value_len / 2; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_ADMIN_PROPERTIES_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_GENERIC_ADMIN_PROPERTY_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_admin_property_status_t, + property_value); + generic_admin_property_status_t *pmsg = (generic_admin_property_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_property_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.property_id = pmsg->property_id; + status_data.property_access = pmsg->property_access; + status_data.pproperty_value = NULL; + status_data.value_len = 0; + if (value_len > 0) + { + status_data.pproperty_value = pmsg->property_value; + status_data.value_len = value_len; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_ADMIN_PROPERTY_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_GENERIC_MANUFACTURER_PROPERTIES_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_manufacturer_properties_status_t, + property_ids); + generic_manufacturer_properties_status_t *pmsg = (generic_manufacturer_properties_status_t *) + pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_properties_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.pproperty_ids = NULL; + status_data.num_ids = 0; + if (value_len > 0) + { + status_data.pproperty_ids = pmsg->property_ids; + status_data.num_ids = value_len / 2; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_MANUFACTURER_PROPERTIES_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_GENERIC_MANUFACTURER_PROPERTY_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_manufacturer_property_status_t, + property_value); + generic_manufacturer_property_status_t *pmsg = (generic_manufacturer_property_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_property_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.property_id = pmsg->property_id; + status_data.property_access = pmsg->property_access; + status_data.pproperty_value = NULL; + status_data.value_len = 0; + if (value_len > 0) + { + status_data.pproperty_value = pmsg->property_value; + status_data.value_len = value_len; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_MANUFACTURER_PROPERTY_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_GENERIC_CLIENT_PROPERTIES_STATUS: + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_client_properties_status_t, + property_ids); + generic_client_properties_status_t *pmsg = (generic_client_properties_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + generic_properties_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.pproperty_ids = NULL; + status_data.num_ids = 0; + if (value_len > 0) + { + status_data.pproperty_ids = pmsg->property_ids; + status_data.num_ids = value_len / 2; + } + pmodel_info->model_data_cb(pmodel_info, GENERIC_CLIENT_PROPERTIES_CLIENT_STATUS, &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +bool generic_property_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_PROPERTY_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = generic_property_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_location_client_reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.c new file mode 100644 index 00000000..9c42ce4c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.c @@ -0,0 +1,342 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_transition_time.c +* @brief Source file for generic transition time. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-11 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_transition_time.h" +#include "mesh_api.h" +#include "generic_types.h" + +#define TRANS_TICK_PERIOD 50 + +typedef struct _trans_list +{ + struct _trans_list *prev; + struct _trans_list *next; +} trans_list_t, *trans_list_p; + +typedef struct _trans_time_remain +{ + mesh_model_info_p pmodel_info; + uint32_t trans_type; + generic_transition_time_t total_time; + int8_t remain_num_steps; + int16_t remain_step_ticks; + generic_transition_step_change_cb step_change; + trans_list_t node; +} trans_time_remain_t, *trans_time_remain_p; + +static trans_list_t trans_list_head; + +#if MODEL_ENABLE_MULTI_THREAD +#define TRANS_INFINITE_WAIT 0xffffffff +plt_mutex_t trans_mutex; +#endif + +const int16_t tick_map[] = {100 / TRANS_TICK_PERIOD, 1000 / TRANS_TICK_PERIOD, 10000 / TRANS_TICK_PERIOD, 600000 / TRANS_TICK_PERIOD}; +const uint32_t trans_time_map_max[] = {6200, 62000, 620000, 37200000}; +const uint32_t trans_time_tick_map[] = {100, 1000, 10000, 600000}; + +static __INLINE bool trans_time_is_empty(void) +{ + return (trans_list_head.next == &trans_list_head); +} + + +uint32_t generic_transition_time_convert(generic_transition_time_t trans_time) +{ + uint32_t time = tick_map[trans_time.step_resolution]; + time *= TRANS_TICK_PERIOD; + time *= trans_time.num_steps; + + return time; +} + +generic_transition_time_t time_to_generic_transition_time(uint32_t time) +{ + generic_transition_time_t trans_time; + uint8_t index = 0; + for (; index < sizeof(trans_time_map_max) / sizeof(uint32_t); ++index) + { + if (time <= trans_time_map_max[index]) + { + break; + } + } + + uint8_t steps = time / trans_time_tick_map[index]; + if (steps > 0x3e) + { + steps = 0x3e; + } + + trans_time.num_steps = steps; + trans_time.step_resolution = index; + + return trans_time; +} + +static bool trans_time_insert(const mesh_model_info_p pmodel_info, + uint32_t trans_type, + generic_transition_time_t trans_time, + generic_transition_step_change_cb step_change) +{ + trans_list_p pcur = trans_list_head.next; + trans_time_remain_p ptime = NULL; + for (; pcur != &trans_list_head; pcur = pcur->next) + { + ptime = CONTAINER_OF(pcur, trans_time_remain_t, node); + if ((ptime->pmodel_info == pmodel_info) && + (ptime->trans_type == trans_type)) + { + break; + } + } + + if (pcur != &trans_list_head) + { + /* reset transition time */ + ptime->total_time = trans_time; + ptime->remain_num_steps = trans_time.num_steps; + ptime->remain_step_ticks = tick_map[trans_time.step_resolution]; + return TRUE; + } + + trans_time_remain_p premain_time = plt_malloc(sizeof(trans_time_remain_t), RAM_TYPE_DATA_ON); + if (NULL == premain_time) + { + printe("trans_time_insert: allocate transition time memory failed"); + return FALSE; + } + premain_time->pmodel_info = pmodel_info; + premain_time->trans_type = trans_type; + premain_time->total_time = trans_time; + premain_time->remain_num_steps = trans_time.num_steps; + premain_time->remain_step_ticks = tick_map[trans_time.step_resolution]; + premain_time->step_change = step_change; + premain_time->node.next = NULL; + premain_time->node.prev = NULL; + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(trans_mutex, TRANS_INFINITE_WAIT); +#endif + + /* sort insert */ + pcur = trans_list_head.next; + for (; pcur != &trans_list_head; pcur = pcur->next) + { + trans_time_remain_p ptime = CONTAINER_OF(pcur, trans_time_remain_t, node); + int32_t cur_time_tick = ptime->remain_num_steps * tick_map[ptime->total_time.step_resolution]; + int32_t insert_time_tick = premain_time->remain_num_steps * + tick_map[ptime->total_time.step_resolution]; + if (cur_time_tick > insert_time_tick) + { + break; + } + } + + pcur->prev->next = &premain_time->node; + premain_time->node.prev = pcur->prev; + pcur->prev = &premain_time->node; + premain_time->node.next = pcur; + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(trans_mutex); +#endif + + return TRUE; +} + +static bool trans_time_remove_head(void) +{ + trans_list_p pfirst = trans_list_head.next; + if (pfirst == &trans_list_head) + { + return FALSE; + } + + trans_time_remain_p premain_time = CONTAINER_OF(pfirst, trans_time_remain_t, node); + if (premain_time->remain_num_steps <= 0) + { + /* remove first */ + pfirst->prev->next = pfirst->next; + pfirst->next->prev = pfirst->prev; + plt_free(premain_time, RAM_TYPE_DATA_ON); + return TRUE; + } + + return FALSE; +} + +static void trans_time_timeout_handle(void) +{ +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(trans_mutex, TRANS_INFINITE_WAIT); +#endif + + trans_list_p pcur = trans_list_head.next; + trans_time_remain_p ptime = NULL; + for (; pcur != &trans_list_head; pcur = pcur->next) + { + ptime = CONTAINER_OF(pcur, trans_time_remain_t, node); + ptime->remain_step_ticks --; + if (ptime->remain_step_ticks <= 0) + { + if (ptime->remain_num_steps > 0) + { + ptime->remain_num_steps --; + } + + /* reload step tick */ + ptime->remain_step_ticks = tick_map[ptime->total_time.step_resolution]; + if (1 == ptime->remain_num_steps) + { + /* make up for for timer lost(TRANS_TICK_PERIOD) */ + ptime->remain_step_ticks ++; + } + if (NULL != ptime->step_change) + { + int32_t ret = MODEL_SUCCESS; + /* notify remaining step change */ + generic_transition_time_t remaining_time = {ptime->remain_num_steps, ptime->total_time.step_resolution}; + ret = ptime->step_change(ptime->pmodel_info, ptime->trans_type, ptime->total_time, remaining_time); + if ((MODEL_STOP_TRANSITION == ret) && + (ptime->remain_num_steps > 0)) + { + ptime->remain_num_steps = 0; + remaining_time.num_steps = 0; +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + /* notify transition end */ + ptime->step_change(ptime->pmodel_info, ptime->trans_type, ptime->total_time, remaining_time); +#endif + } + } + } + } + + /* remove expired transition */ + while (trans_time_remove_head()); + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(trans_mutex); +#endif + + /* check empty */ + if (trans_time_is_empty()) + { + printi("stop transition timer"); + mesh_tick_timer_stop(); + } +} + +bool generic_transition_timer_start(const mesh_model_info_p pmodel, + uint32_t trans_type, + generic_transition_time_t trans_time, + generic_transition_step_change_cb step_change) +{ + bool ret = FALSE; + if (!mesh_tick_timer_is_running()) + { + if (trans_time_insert(pmodel, trans_type, trans_time, step_change)) + { + mesh_tick_timer_start(TRANS_TICK_PERIOD, trans_time_timeout_handle); + ret = TRUE; + } + } + else + { + ret = trans_time_insert(pmodel, trans_type, trans_time, step_change); + } + + return ret; +} + + +void generic_transition_timer_stop(const mesh_model_info_p pmodel_info, + uint32_t trans_type) +{ + /* remove specified model timer */ +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(trans_mutex, TRANS_INFINITE_WAIT); +#endif + + trans_list_p pcur = trans_list_head.next; + for (; pcur != &trans_list_head; pcur = pcur->next) + { + trans_time_remain_p ptime = CONTAINER_OF(pcur, trans_time_remain_t, node); + if ((ptime->pmodel_info == pmodel_info) && + (ptime->trans_type == trans_type)) + { + ptime->remain_num_steps = 0; + break; + } + } + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(trans_mutex); +#endif +} + + +generic_transition_time_t generic_transition_time_get(const mesh_model_info_p pmodel_info, + uint32_t trans_type) +{ +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_take(trans_mutex, TRANS_INFINITE_WAIT); +#endif + trans_list_p pcur = trans_list_head.next; + trans_time_remain_p ptime = NULL; + for (; pcur != &trans_list_head; pcur = pcur->next) + { + ptime = CONTAINER_OF(pcur, trans_time_remain_t, node); + if ((ptime->pmodel_info == pmodel_info) && + (ptime->trans_type == trans_type)) + { + break; + } + } + + generic_transition_time_t remaining_time = {0, 0}; + if (pcur != &trans_list_head) + { + remaining_time.num_steps = ptime->remain_num_steps; + remaining_time.step_resolution = ptime->total_time.step_resolution; + } + +#if MODEL_ENABLE_MULTI_THREAD + plt_mutex_give(trans_mutex); +#endif + + return remaining_time; +} + + +bool generic_transition_time_init(void) +{ +#if MODEL_ENABLE_MULTI_THREAD + if (NULL == trans_mutex) + { + trans_mutex = plt_mutex_create(); + if (NULL == trans_mutex) + { + return FALSE; + } + } +#endif + + if ((NULL == trans_list_head.prev) && + (NULL == trans_list_head.next)) + { + trans_list_head.prev = &trans_list_head; + trans_list_head.next = &trans_list_head; + } + + return TRUE; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.h new file mode 100644 index 00000000..88261861 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.h @@ -0,0 +1,128 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_transition_time.h +* @brief Head file for generic transition time. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-11 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _GENERIC_TRANSITION_TIME_H_ +#define _GENERIC_TRANSITION_TIME_H_ + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_TRANSITION_TIME + * @{ + */ + + +/** + * @defgroup GENERIC_TRANSITION_TIME_DATA Generic Transition Time Data + * @brief Generic transition data and structure definition + * @{ + */ +#define GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE 0x00 +#define GENERIC_TRANSITION_NUM_STEPS_MAX 0x3E +#define GENERIC_TRANSITION_NUM_STEPS_UNKNOWN 0x3F +#define IS_GENERIC_TRANSITION_STEPS_VALID(step) (step < GENERIC_TRANSITION_NUM_STEPS_UNKNOWN) + + +typedef enum +{ + GENERIC_TRANSITION_STEP_RESOLUTION_100MILLISECONDS, + GENERIC_TRANSITION_STEP_RESOLUTION_1SECOND, + GENERIC_TRANSITION_STEP_RESOLUTION_10SECONDS, + GENERIC_TRANSITION_STEP_RESOLUTION_10MINUTS +} generic_transition_step_resolution_t; + +typedef struct +{ + uint8_t num_steps: 6; + uint8_t step_resolution: 2; //!< @ref generic_transition_step_resolution_t +} _PACKED4_ generic_transition_time_t, *generic_transition_time_p; + + +#define IS_MAX_GENERIC_TRANSITION_TIME(trans_time) \ + ((trans_time.num_steps == GENERIC_TRANSITION_NUM_STEPS_MAX) && \ + (trans_time.step_resolution == GENERIC_TRANSITION_STEP_RESOLUTION_10MINUTS)) + +typedef int32_t (*generic_transition_step_change_cb)(const mesh_model_info_p pmodel_info, + uint32_t trans_type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time); +/** @} */ + +/** + * @defgroup GENERIC_TRANSITION_TIME_API Generic Transition Time API + * @brief Functions declaration + * @{ + */ + +/** + * @brief initialize generic transition + * @retval TRUE: initialize success + * @retval FALSE: initialize failed + */ +bool generic_transition_time_init(void); + +/** + * @brief start mode state transition timer + * @param[in] pmodel_info: pointer to model information context that need to transition + * @param[in] trans_type: transition type + * @param[in] trans_time: transition total time + * @param[in] step_change_cb: step change done callback function + * @retval TRUE: start transition success + * @retval FALSE: start transition failed + */ +bool generic_transition_timer_start(const mesh_model_info_p pmodel_info, + uint32_t trans_type, + generic_transition_time_t trans_time, + generic_transition_step_change_cb step_change_cb); + +/** + * @brief stop model state transition timer + * @param[in] pmodel_info: pointer to model information context that need to stop transition + * @param[in] trans_type: transition type + */ +void generic_transition_timer_stop(const mesh_model_info_p pmodel_info, + uint32_t trans_type); + +/** + * @brief get model transition remaining time + * @param[in] pmodel_info: pointer to model information context that in transition + * @param[in] trans_type: transition type + * @return remaining transition time + */ +generic_transition_time_t generic_transition_time_get(const mesh_model_info_p pmodel_info, + uint32_t trans_type); + +/** + * @brief convert generic transition time to ms + * @param[in] trans_time: generic transition time + * @return converted time, unit is ms + */ +uint32_t generic_transition_time_convert(generic_transition_time_t trans_time); + +/** + * @brief convert ms to generic transition time + * @param[in] time: time ms + * @return converted transition time + */ +generic_transition_time_t time_to_generic_transition_time(uint32_t time); +/** @} */ +/** @} */ + + +END_DECLS + + +#endif /* _GENERIC_TRANSITION_TIME_H_ */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_types.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_types.h new file mode 100644 index 00000000..22f876d0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_types.h @@ -0,0 +1,47 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_types.h +* @brief Head file for types used by generic models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _GENERIC_TYPES_H +#define _GENERIC_TYPES_H + +#include "platform_types.h" + +BEGIN_DECLS + +/** + * @addtogroup GENERIC_TYPES + * @{ + */ + +/** + * @defgroup GENERIC_TYPES_TYPES Generic Types + * @brief Error code for models + * @{ + */ +enum +{ + GENERIC_STAT_SUCCESS, + GENERIC_STAT_CANNOT_SET_RANGE_MIN, + GENERIC_STAT_CANNOT_SET_RANGE_MAX +} _SHORT_ENUM_; +typedef uint8_t generic_stat_t; + +#define MODEL_SUCCESS 0 //!< model data process success +#define MODEL_STOP_TRANSITION 1 //!< stop transition after model data process +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _GENERIC_TYPES_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_user_property_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_user_property_server.c new file mode 100644 index 00000000..4e750652 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_user_property_server.c @@ -0,0 +1,331 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_user_property_server.c +* @brief Source file for generic user property server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-01 +* @version v1.0 +* ************************************************************************************* +*/ +#include "generic_property.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +typedef struct +{ + generic_property_db_t *pproperties; + uint16_t num_properties; +} generic_user_property_info_t; + +void generic_user_property_server_set_db(mesh_model_info_t *pmodel_info, + generic_property_db_t *pproperties, uint16_t num_properties) +{ + generic_user_property_info_t *pinfo = pmodel_info->pargs; + pinfo->pproperties = pproperties; + pinfo->num_properties = num_properties; +} + +static mesh_msg_send_cause_t generic_user_property_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len, uint16_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t generic_user_properties_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + const generic_property_db_t *pproperties, + uint16_t num_properties, uint16_t delay_time) +{ + uint16_t msg_len = sizeof(generic_user_properties_status_t) + 2 * num_properties; + generic_user_properties_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_USER_PROPERTIES_STATUS); + for (uint16_t i = 0; i < num_properties; ++i) + { + if (GENERIC_PROPERTY_ACCESS_NOT_TO_USER != pproperties[i].property_access) + { + pmsg->property_ids[i] = pproperties[i].property_id; + } + else + { + msg_len -= 2; + } + } + mesh_msg_send_cause_t ret = generic_user_property_send(pmodel_info, dst, app_key_index, + (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +generic_property_db_t *generic_user_property_find(mesh_model_info_p pmodel_info, + uint16_t property_id) +{ + generic_user_property_info_t *pinfo = pmodel_info->pargs; + generic_property_db_t *pdb = NULL; + for (uint16_t i = 0; i < pinfo->num_properties; ++i) + { + if (pinfo->pproperties[i].property_id == property_id) + { + pdb = &pinfo->pproperties[i]; + } + } + + return pdb; +} + +static mesh_msg_send_cause_t generic_user_property_status_internal(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, + const generic_property_db_t *pdb, + bool send_value, uint16_t delay_time) +{ + mesh_msg_send_cause_t ret; + if (NULL != pdb) + { + uint16_t msg_len = 0; + if (send_value) + { + msg_len = sizeof(generic_user_property_status_t) + pdb->value_len; + } + else + { + msg_len = sizeof(generic_user_property_status_t); + } + + generic_user_property_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_GENERIC_USER_PROPERTY_STATUS); + pmsg->property_id = property_id; + pmsg->property_access = pdb->property_access; + if (send_value) + { + for (uint16_t i = 0; i < pdb->value_len; ++i) + { + pmsg->property_value[i] = pdb->pproperty_value[i]; + } + } + ret = generic_user_property_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, + msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + } + else + { + generic_user_property_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_GENERIC_USER_PROPERTY_STATUS); + msg.property_id = property_id; + ret = generic_user_property_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + MEMBER_OFFSET(generic_user_property_status_t, property_access), delay_time); + } + + return ret; +} + +static mesh_msg_send_cause_t generic_user_property_status(mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, uint16_t delay_time) +{ + generic_property_db_t *pdb = generic_user_property_find(pmodel_info, property_id); + bool send_value = TRUE; + if (GENERIC_PROPERTY_ACCESS_WRITE == pdb->property_access) + { + send_value = FALSE; + } + return generic_user_property_status_internal(pmodel_info, dst, app_key_index, property_id, pdb, + send_value, delay_time); +} + +static mesh_msg_send_cause_t generic_user_property_delay_publish(const mesh_model_info_p + pmodel_info, + const generic_property_db_t *pdb, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = generic_user_property_status_internal(pmodel_info, 0, 0, pdb->property_id, pdb, TRUE, + delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t generic_user_property_publish(const mesh_model_info_p pmodel_info, + const generic_property_db_t *pdb) +{ + return generic_user_property_delay_publish(pmodel_info, pdb, 0); +} + +static bool generic_user_property_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_GENERIC_USER_PROPERTIES_GET: + if (pmesh_msg->msg_len == sizeof(generic_user_properties_get_t)) + { + generic_user_property_info_t *pinfo = pmodel_info->pargs; + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_user_properties_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->pproperties, pinfo->num_properties, delay_rsp_time); + } + break; + case MESH_MSG_GENERIC_USER_PROPERTY_GET: + if (pmesh_msg->msg_len == sizeof(generic_user_property_get_t)) + { + generic_user_property_get_t *pmsg = (generic_user_property_get_t *)pbuffer; + if (pmsg->property_id != GENERIC_PROPERTY_ID_PROHIBITED) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_user_property_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, delay_rsp_time); + } + } + break; + case MESH_MSG_GENERIC_USER_PROPERTY_SET: + case MESH_MSG_GENERIC_USER_PROPERTY_SET_UNACK: + { + generic_user_property_set_t *pmsg = (generic_user_property_set_t *)pbuffer; + generic_property_db_t *pdb = generic_user_property_find(pmodel_info, pmsg->property_id); + bool send_value = FALSE; + bool valid = TRUE; + if (NULL != pdb) + { + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(generic_user_property_set_t, + property_value); + if (pdb->value_len != value_len) + { + /* invalid parameters */ + valid = FALSE; + } + else + { + if (GENERIC_PROPERTY_ACCESS_READ != pdb->property_access) + { + memcpy(pdb->pproperty_value, pmsg->property_value, value_len); + pdb->value_len = value_len; + /* notify app user property changed */ + generic_user_property_server_set_t set_data; + set_data.property_id = pmsg->property_id; + set_data.pproperty_value = pdb->pproperty_value; + set_data.value_len = pdb->value_len; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, GENERIC_USER_PROPERTY_SERVER_SET, &set_data); + } + send_value = TRUE; + } + } + } + + if (valid) + { + uint32_t delay_rsp_time = 0; + if (pmesh_msg->access_opcode == MESH_MSG_GENERIC_USER_PROPERTY_SET) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + generic_user_property_status_internal(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, pdb, send_value, delay_rsp_time); + } + + uint32_t delay_pub_time = 0; + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_GENERIC_USER_PROPERTY_SET_UNACK) ? FALSE : TRUE; + generic_transition_time_t trans_time = {0, 0}; + delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, ack); +#endif + if ((NULL != pdb) && (GENERIC_PROPERTY_ACCESS_READ != pdb->property_access)) + { + generic_user_property_delay_publish(pmodel_info, pdb, delay_pub_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void generic_user_property_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == generic_user_property_server_receive) + { + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool generic_user_property_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_GENERIC_USER_PROPERTY_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(generic_user_property_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("generic_user_property_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(generic_user_property_info_t)); + + pmodel_info->model_receive = generic_user_property_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("generic_user_property_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = generic_user_property_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health.h new file mode 100644 index 00000000..83ba05ee --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health.h @@ -0,0 +1,434 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file health.h +* @brief Head file for health models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-3-10 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _HEALTH_H +#define _HEALTH_H + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup HEALTH + * @{ + */ + +/** + * @defgroup HEALTH_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_HEALTH_ATTN_GET 0x8004 +#define MESH_MSG_HEALTH_ATTN_SET 0x8005 +#define MESH_MSG_HEALTH_ATTN_SET_UNACK 0x8006 +#define MESH_MSG_HEALTH_ATTN_STAT 0x8007 +#define MESH_MSG_HEALTH_CURT_STAT 0x04 +#define MESH_MSG_HEALTH_FAULT_CLEAR 0x802F +#define MESH_MSG_HEALTH_FAULT_CLEAR_UNACK 0x8030 +#define MESH_MSG_HEALTH_FAULT_GET 0x8031 +#define MESH_MSG_HEALTH_FAULT_STAT 0x05 +#define MESH_MSG_HEALTH_FAULT_TEST 0x8032 +#define MESH_MSG_HEALTH_FAULT_TEST_UNACK 0x8033 +#define MESH_MSG_HEALTH_PERIOD_GET 0x8034 +#define MESH_MSG_HEALTH_PERIOD_SET 0x8035 +#define MESH_MSG_HEALTH_PERIOD_SET_UNACK 0x8036 +#define MESH_MSG_HEALTH_PERIOD_STAT 0x8037 +/** @} */ + +/** + * @defgroup HEALTH_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_HEALTH_SERVER 0x0002FFFF +#define MESH_MODEL_HEALTH_CLIENT 0x0003FFFF +/** @} */ + +/** + * @defgroup HEALTH_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ + +/** standard test id */ +#define HEALTH_STANDARD_TEST_ID 0 + +/** health fault code */ +#define HEALTH_FAULT_NO_FAULT 0x00 +#define HEALTH_FAULT_BATTERY_LOW_WARNING 0x01 +#define HEALTH_FAULT_BATTERY_LOW_ERROR 0x02 +#define HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_LOW_WARNING 0x03 +#define HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_LOW_ERROR 0x04 +#define HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_HIGH_WARNING 0x05 +#define HEALTH_FAULT_SUPPLY_VOLTAGE_TOO_HIGH_ERROR 0x06 +#define HEALTH_FAULT_POWER_SUPPLY_INTERRUPTED_WARNING 0x07 +#define HEALTH_FAULT_POWER_SUPPLY_INTERRUPTED_ERROR 0x08 +#define HEALTH_FAULT_NO_LOAD_WARNING 0x09 +#define HEALTH_FAULT_NO_LOAD_ERROR 0x0a +#define HEALTH_FAULT_OVERLOAD_WARNING 0x0b +#define HEALTH_FAULT_OVERLOAD_ERROR 0x0c +#define HEALTH_FAULT_OVERHEAT_WARNING 0x0d +#define HEALTH_FAULT_OVERHEAT_ERROR 0x0e +#define HEALTH_FAULT_CONDENSATION_WARNING 0x0f +#define HEALTH_FAULT_CONDENSATION_ERROR 0x10 +#define HEALTH_FAULT_VIBRATION_WARNING 0x11 +#define HEALTH_FAULT_VIBRATION_ERROR 0x12 +#define HEALTH_FAULT_CONFIGURATION_WARNING 0x13 +#define HEALTH_FAULT_CONFIGURATION_ERROR 0x14 +#define HEALTH_FAULT_ELEMENT_NOT_CALIBRATED_WARNING 0x15 +#define HEALTH_FAULT_ELEMENT_NOT_CALIBRATED_ERROR 0x16 +#define HEALTH_FAULT_MEMORY_WARNING 0x17 +#define HEALTH_FAULT_MEMORY_ERROR 0x18 +#define HEALTH_FAULT_SELF_TEST_WARNING 0x19 +#define HEALTH_FAULT_SELF_TEST_ERROR 0x1a +#define HEALTH_FAULT_INPUT_TOO_LOW_WARNING 0x1b +#define HEALTH_FAULT_INPUT_TOO_LOW_ERROR 0x1c +#define HEALTH_FAULT_INPUT_TOO_HIGH_WARNING 0x1d +#define HEALTH_FAULT_INPUT_TOO_HIGH_ERROR 0x1e +#define HEALTH_FAULT_INPUT_NO_CHANGE_HIGH_WARNING 0x1f +#define HEALTH_FAULT_INPUT_NO_CHANGE_HIGH_ERROR 0x20 +#define HEALTH_FAULT_ACTUATOR_BLOCKED_WARNING 0x21 +#define HEALTH_FAULT_ACTUATOR_BLOCKED_ERROR 0x22 +#define HEALTH_FAULT_HOUSING_OPENED_WARNING 0x23 +#define HEALTH_FAULT_HOUSING_OPENED_ERROR 0x24 +#define HEALTH_FAULT_TAMPER_WARNING 0x25 +#define HEALTH_FAULT_TAMPER_ERROR 0x26 +#define HEALTH_FAULT_DEVICE_MOVED_WARNING 0x27 +#define HEALTH_FAULT_DEVICE_MOVED_ERROR 0x28 +#define HEALTH_FAULT_DEVICE_DROPPED_WARNING 0x29 +#define HEALTH_FAULT_DEVICE_DROPPED_ERROR 0x2a +#define HEALTH_FAULT_OVERFLOW_WARNING 0x2b +#define HEALTH_FAULT_OVERFLOW_ERROR 0x2c +#define HEALTH_FAULT_EMPTY_WARNING 0x2d +#define HEALTH_FAULT_EMPTY_ERROR 0x2e +#define HEALTH_FAULT_INTERNAL_BUS_WARNING 0x2f +#define HEALTH_FAULT_INTERNAL_BUS_ERROR 0x30 +#define HEALTH_FAULT_MECHANISM_JAMMED_WARNING 0x31 +#define HEALTH_FAULT_MECHAISM_JAMMED_ERROR 0x32 +#define HEALTH_FAULT_VENDOR_START 0x80 + +#define IS_FAST_PERIOD_DIVISOR_VALID(divisor) ((divisor) <= 15) + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_CURT_STAT)]; + uint8_t test_id; + uint16_t company_id; + uint8_t fault_array[1]; //!< variable length +} _PACKED4_ health_curt_stat_t, *health_curt_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_FAULT_GET)]; + uint16_t company_id; +} _PACKED4_ health_fault_get_t, *health_fault_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_FAULT_CLEAR_UNACK)]; + uint16_t company_id; +} _PACKED4_ health_fault_clear_unack_t, *health_fault_clear_unack_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_FAULT_CLEAR)]; + uint16_t company_id; +} _PACKED4_ health_fault_clear_t, *health_fault_clear_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_FAULT_TEST)]; + uint8_t test_id; + uint16_t company_id; +} _PACKED4_ health_fault_test_t, *health_fault_test_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_FAULT_TEST_UNACK)]; + uint8_t test_id; + uint16_t company_id; +} _PACKED4_ health_fault_test_unack_t, *health_fault_test_unack_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_FAULT_STAT)]; + uint8_t test_id; + uint16_t company_id; + uint8_t fault_array[1]; //!< variable length +} _PACKED4_ health_fault_stat_t, *health_fault_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_PERIOD_GET)]; +} _PACKED4_ health_period_get_t, *health_period_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_PERIOD_SET_UNACK)]; + uint8_t fast_period_divisor; +} _PACKED4_ health_period_set_unack_t, *health_period_set_unack_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_PERIOD_SET)]; + uint8_t fast_period_divisor; +} _PACKED4_ health_period_set_t, *health_period_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_PERIOD_STAT)]; + uint8_t fast_period_divisor; +} _PACKED4_ health_period_stat_t, *health_period_stat_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_ATTN_GET)]; +} _PACKED4_ health_attn_get_t, *health_attn_get_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_ATTN_SET)]; + uint8_t attn; //!< attention +} _PACKED4_ health_attn_set_t, *health_attn_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_ATTN_SET_UNACK)]; + uint8_t attn; //!< attention +} _PACKED4_ health_attn_set_unack_t, *health_attn_set_unack_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_HEALTH_ATTN_STAT)]; + uint8_t attn; //!< attention +} _PACKED4_ health_attn_stat_t, *health_attn_stat_p; +/** @} */ + +/** + * @defgroup HEALTH_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +typedef void (*health_server_test_cb_t)(const mesh_model_info_p pmodel_info, uint16_t company_id, + uint8_t test_id); +typedef struct +{ + uint8_t test_id; + health_server_test_cb_t test_cb; +} health_server_test_t; +/** @} */ + +/** + * @defgroup HEALTH_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define HEALTH_CLIENT_STATUS_CURRENT 0 //!< @ref health_client_status_t +#define HEALTH_CLIENT_STATUS_REGISTERED 1 //!< @ref health_client_status_t +#define HEALTH_CLIENT_STATUS_PERIOD 2 //!< @ref health_client_status_period_t +#define HEALTH_CLIENT_STATUS_ATTENTION 3 //!< @ref health_client_status_attention_t + +typedef struct +{ + uint16_t src; + uint8_t test_id; + uint16_t company_id; + uint8_t *fault_array; + uint8_t fault_array_len; +} health_client_status_t; + +typedef struct +{ + uint8_t fast_period_divisor; +} health_client_status_period_t; + +typedef struct +{ + uint8_t attention; +} health_client_status_attention_t; +/** @} */ + + + +/** + * @defgroup HEALTH_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register health server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to health server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool health_server_reg(uint16_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief set selftest functions + * @param[in] pmodel_info: pointer to health server model context + * @param[in] ptests: selftest functions + * @param[in] num_tests: selftest function numbers + */ +void health_server_set_tests(mesh_model_info_p pmodel_info, const health_server_test_t *ptests, + uint8_t num_tests); + +/** + * @brief set company id + * @param[in] pmodel_info: pointer to health server model context + * @param[in] company_id: new company id value + */ +void health_server_set_company_id(mesh_model_info_p pmodel_info, uint16_t company_id); + +/** + * @brief register fault to health server model + * @param[in] pmodel_info: pointer to health server model context + * @param[in] fault: fault need to register + */ +void health_server_fault_register(mesh_model_info_p pmodel_info, uint8_t fault); + +/** + * @brief clear fault in current fault array + * @param[in] pmodel_info: pointer to health server model context + * @param[in] fault: fault need to clear + */ +void health_server_fault_clear(mesh_model_info_p pmodel_info, uint8_t fault); + +/** + * @brief clear all fault in current fault array + * @param[in] pmodel_info: pointer to health server model context + */ +void health_server_fault_clear_all(mesh_model_info_p pmodel_info); + +/** + * @brief check whether specified fault is in current fault array + * @param[in] pmodel_info: pointer to health server model context + * @param[in] fault: health fault value need to set + * @retval TRUE: specified fault is in current array + * @retval FALSE: specified fault is not in current array + */ +bool health_server_fault_is_set(const mesh_model_info_p pmodel_info, uint8_t fault); + +/** + * @brief get fault count in current fault array + * @param[in] pmodel_info: pointer to health server model context + */ +uint8_t health_server_fault_count(const mesh_model_info_p pmodel_info); +/** @} */ + +/** + * @defgroup HEALTH_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register generic battery server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to generic battery server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool health_client_reg(uint16_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get fault status + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] company_id: company id + * @return send status + */ +mesh_msg_send_cause_t health_fault_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t company_id); + +/** + * @brief clear registered fault + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] company_id: company id value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t health_fault_clear(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t company_id, + bool ack); + +/** + * @brief run specified selftest + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] test_id: test id value + * @param[in] company_id: company id value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t health_fault_test(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t test_id, + uint16_t company_id, bool ack); + +/** + * @brief get fast period divisor + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t health_period_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set fast period divisor + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] fast_period_divisor: new fast period divisor + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t health_period_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint8_t fast_period_divisor, bool ack); +/** + * @brief get attention value + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t health_attn_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set attention value + * @param[in] pmodel_info: pointer to health client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] attn: new attention value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t health_attn_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t attn, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _HEALTH_H */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_client.c new file mode 100644 index 00000000..f3f31d48 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_client.c @@ -0,0 +1,210 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file health_client.c +* @brief Source file for health client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-3-10 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "mesh_api.h" +#include "health.h" + +static mesh_msg_send_cause_t health_client_send(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, + uint16_t len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t health_fault_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t company_id) +{ + health_fault_get_t msg; + msg.company_id = company_id; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_FAULT_GET); + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_fault_get_t)); +} + +mesh_msg_send_cause_t health_fault_clear(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t company_id, + bool ack) +{ + health_fault_clear_t msg; + msg.company_id = company_id; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_FAULT_CLEAR); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_FAULT_CLEAR_UNACK); + } + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_fault_clear_t)); +} + +mesh_msg_send_cause_t health_fault_test(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t test_id, + uint16_t company_id, bool ack) +{ + health_fault_test_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_FAULT_TEST); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_FAULT_TEST_UNACK); + } + msg.test_id = test_id; + msg.company_id = company_id; + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_fault_test_t)); +} + +mesh_msg_send_cause_t health_period_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + health_period_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_PERIOD_GET); + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_period_get_t)); +} + +mesh_msg_send_cause_t health_period_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + uint8_t fast_period_divisor, bool ack) +{ + health_period_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_PERIOD_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_PERIOD_SET_UNACK); + } + msg.fast_period_divisor = fast_period_divisor; + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_period_set_t)); +} + +mesh_msg_send_cause_t health_attn_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + health_attn_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_ATTN_GET); + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_attn_get_t)); +} + +mesh_msg_send_cause_t health_attn_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t attn, bool ack) +{ + health_attn_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_ATTN_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_ATTN_SET_UNACK); + } + msg.attn = attn; + return health_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(health_attn_set_t)); +} + +static bool health_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_HEALTH_ATTN_STAT: + if (pmesh_msg->msg_len == sizeof(health_attn_stat_t)) + { + health_attn_stat_p pmsg = (health_attn_stat_p)pbuffer; + health_client_status_attention_t status_attn = {pmsg->attn}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, HEALTH_CLIENT_STATUS_ATTENTION, &status_attn); + } + } + break; + case MESH_MSG_HEALTH_CURT_STAT: + { + health_curt_stat_p pmsg = (health_curt_stat_p)pbuffer; + health_client_status_t status_data = {pmesh_msg->src, pmsg->company_id, pmsg->test_id, pmsg->fault_array}; + status_data.fault_array_len = pmesh_msg->msg_len - MEMBER_OFFSET(health_curt_stat_t, fault_array); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, HEALTH_CLIENT_STATUS_CURRENT, &status_data); + } + } + break; + + case MESH_MSG_HEALTH_FAULT_STAT: + { + health_fault_stat_p pmsg = (health_fault_stat_p)pbuffer; + health_client_status_t status_data = {pmesh_msg->src, pmsg->company_id, pmsg->test_id, pmsg->fault_array}; + status_data.fault_array_len = pmesh_msg->msg_len - MEMBER_OFFSET(health_fault_stat_t, fault_array); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, HEALTH_CLIENT_STATUS_REGISTERED, &status_data); + } + } + break; + case MESH_MSG_HEALTH_PERIOD_STAT: + if (pmesh_msg->msg_len == sizeof(health_period_stat_t)) + { + health_period_stat_p pmsg = (health_period_stat_p)pbuffer; + health_client_status_period_t status_period = {pmsg->fast_period_divisor}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, HEALTH_CLIENT_STATUS_PERIOD, &status_period); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool health_client_reg(uint16_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_HEALTH_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = health_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("hralth_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_server.c new file mode 100644 index 00000000..0ac0ebfc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_server.c @@ -0,0 +1,484 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file health_server.c +* @brief Source file for health server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-5 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "mesh_api.h" +#include "health.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +#define HEALTH_FAULT_MAX_NUM 256 +#define HEALTH_FAULT_BLOCK_SIZE 32 +#define HEALTH_FAULT_BLOCK_COUNT ((HEALTH_FAULT_MAX_NUM + HEALTH_FAULT_BLOCK_SIZE - 1) / HEALTH_FAULT_BLOCK_SIZE) + +typedef struct +{ + uint16_t company_id; + uint8_t recently_test_id; + uint8_t fast_period_divisor; + const health_server_test_t *ptests; + uint8_t num_tests; + uint32_t registered_faults[HEALTH_FAULT_BLOCK_COUNT]; + uint32_t current_faults[HEALTH_FAULT_BLOCK_COUNT]; +} health_info_t, *health_info_p; + +static uint8_t health_server_fault_count_internal(const uint32_t *faults); +static void health_server_fill_fault(uint8_t *dst, const uint32_t *fault_bits) +{ + uint32_t temp_fault = 0; + uint32_t bit = 0; + uint8_t offset = 0; + for (uint8_t i = 0; i < HEALTH_FAULT_BLOCK_COUNT; ++i) + { + temp_fault = fault_bits[i]; + while (0 != temp_fault) + { + bit = (temp_fault & ~(temp_fault - 1)); + offset = 0; + while (0 != bit) + { + offset ++; + bit >>= 1; + } + *dst ++ = i * 32 + offset - 1; + temp_fault &= (temp_fault - 1); + } + } +} + +static uint8_t hamming_weight(uint32_t data) +{ + uint32_t weight = data; + weight = (weight & 0x55555555) + ((weight >> 1) & 0x55555555); + weight = (weight & 0x33333333) + ((weight >> 2) & 0x33333333); + weight = (weight & 0x0f0f0f0f) + ((weight >> 4) & 0x0f0f0f0f); + weight = (weight & 0x00ff00ff) + ((weight >> 8) & 0x00ff00ff); + weight = (weight & 0x0000ffff) + ((weight >> 16) & 0x0000ffff); + + return weight; +} + +static uint8_t health_server_fault_count_internal(const uint32_t *faults) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < HEALTH_FAULT_BLOCK_COUNT; ++i) + { + count += hamming_weight(faults[i]); + } + + return count; +} + +static mesh_msg_send_cause_t health_server_send(mesh_msg_p pmesh_msg, uint8_t *pmsg, uint16_t len, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmesh_msg->pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = len; + mesh_msg.dst = pmesh_msg->src; + mesh_msg.app_key_index = pmesh_msg->app_key_index; + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t health_curt_stat(mesh_model_info_p pmodel_info, uint8_t test_id, + uint16_t company_id, const uint32_t *fault_array, uint32_t delay_time) +{ + uint8_t fault_array_len = health_server_fault_count_internal(fault_array); + uint16_t msg_len = MEMBER_OFFSET(health_curt_stat_t, fault_array) + fault_array_len; + health_curt_stat_p phealth_curt_stat = (health_curt_stat_p) plt_malloc(msg_len, RAM_TYPE_DATA_OFF); + if (phealth_curt_stat == NULL) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(phealth_curt_stat->opcode, MESH_MSG_HEALTH_CURT_STAT); + phealth_curt_stat->test_id = test_id; + phealth_curt_stat->company_id = company_id; + health_server_fill_fault(phealth_curt_stat->fault_array, fault_array); + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)phealth_curt_stat; + mesh_msg.msg_len = msg_len; + mesh_msg.delay_time = delay_time; + mesh_msg_send_cause_t ret = access_send(&mesh_msg); + plt_free(phealth_curt_stat, RAM_TYPE_DATA_OFF); + return ret; +} + +static mesh_msg_send_cause_t health_fault_stat(mesh_msg_p pmesh_msg, uint8_t test_id, + uint16_t company_id, const uint32_t *fault_array, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret; + uint8_t fault_array_len = health_server_fault_count_internal(fault_array); + uint16_t msg_len = MEMBER_OFFSET(health_curt_stat_t, fault_array) + fault_array_len; + health_curt_stat_p pmsg = (health_curt_stat_p) plt_malloc(msg_len, RAM_TYPE_DATA_OFF); + if (pmsg == NULL) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_HEALTH_FAULT_STAT); + pmsg->test_id = test_id; + pmsg->company_id = company_id; + health_server_fill_fault(pmsg->fault_array, fault_array); + ret = health_server_send(pmesh_msg, (uint8_t *)pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +static bool is_health_server_has_fault(const mesh_model_info_p pmodel_info) +{ + health_info_p phealth_info = pmodel_info->pargs; + bool has = FALSE; + for (uint8_t i = 0; i < HEALTH_FAULT_BLOCK_COUNT; ++i) + { + if (0 != phealth_info->current_faults[i]) + { + has = TRUE; + } + } + + return has; +} + +/** + * @brief health model publish callback + * @param pmodel_info - health model + * @param retrans - retransmit times + * @retval 0: nothing to do + * @retval >0: new timer interval + * @retval <0: reserved + */ +static int32_t health_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + health_info_p phealth_info = pmodel_info->pargs; + + health_curt_stat(pmodel_info, phealth_info->recently_test_id, phealth_info->company_id, + phealth_info->current_faults, 0); + + if (is_health_server_has_fault(pmodel_info)) + { + /* need to fast timer interval */ + uint32_t divisor = (1 << phealth_info->fast_period_divisor); + return mesh_model_pub_period_get(pmodel_info->pmodel) / divisor; + } + + return 0; +} + +static mesh_msg_send_cause_t health_period_stat(mesh_msg_p pmesh_msg, uint8_t fast_period_divisor, + uint32_t delay_time) +{ + health_period_stat_t msg; + msg.fast_period_divisor = fast_period_divisor; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_PERIOD_STAT); + return health_server_send(pmesh_msg, (uint8_t *)&msg, sizeof(health_period_stat_t), delay_time); +} + +static mesh_msg_send_cause_t health_attn_stat(mesh_msg_p pmesh_msg, uint8_t attn, + uint32_t delay_time) +{ + health_attn_stat_t msg; + msg.attn = attn; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_HEALTH_ATTN_STAT); + return health_server_send(pmesh_msg, (uint8_t *)&msg, sizeof(health_attn_stat_t), delay_time); +} + +uint8_t health_server_fault_count(const mesh_model_info_p pmodel_info) +{ + health_info_p phealth_info = pmodel_info->pargs; + return health_server_fault_count_internal(phealth_info->current_faults); +} + +void health_server_set_tests(mesh_model_info_p pmodel_info, const health_server_test_t *ptests, + uint8_t num_tests) +{ + health_info_p phealth_info = pmodel_info->pargs; + phealth_info->ptests = ptests; + phealth_info->num_tests = num_tests; +} + +void health_server_set_company_id(mesh_model_info_p pmodel_info, uint16_t company_id) +{ + health_info_p phealth_info = pmodel_info->pargs; + phealth_info->company_id = company_id; +} + +void health_server_fault_register(mesh_model_info_p pmodel_info, uint8_t fault) +{ + health_info_p phealth_info = pmodel_info->pargs; + uint8_t pos = fault / HEALTH_FAULT_BLOCK_SIZE; + uint8_t bit = fault % HEALTH_FAULT_BLOCK_SIZE; + phealth_info->registered_faults[pos] |= (1 << bit); + phealth_info->current_faults[pos] |= (1 << bit); + + /* TODO: only need to fast from 0 to 1 */ + health_curt_stat(pmodel_info, phealth_info->recently_test_id, phealth_info->company_id, + phealth_info->current_faults, 0); + /* need to fast timer now */ + mesh_model_p pmodel = pmodel_info->pmodel; + if (NULL != pmodel->pub_timer) + { + uint32_t divisor = (1 << phealth_info->fast_period_divisor); + uint32_t pub_period = mesh_model_pub_period_get(pmodel); + if (pub_period > 0) + { + plt_timer_change_period(pmodel->pub_timer, pub_period / divisor, 0); + } + } +} + +void health_server_fault_clear(mesh_model_info_p pmodel_info, uint8_t fault) +{ + health_info_p phealth_info = pmodel_info->pargs; + uint8_t pos = fault / HEALTH_FAULT_BLOCK_SIZE; + uint8_t bit = fault % HEALTH_FAULT_BLOCK_SIZE; + phealth_info->current_faults[pos] &= ~bit; +} + +void health_server_fault_clear_all(mesh_model_info_p pmodel_info) +{ + health_info_p phealth_info = pmodel_info->pargs; + for (uint8_t i = 0; i < HEALTH_FAULT_BLOCK_COUNT; ++i) + { + phealth_info->current_faults[i] = 0; + } +} + +static void health_server_registered_fault_clear_all(mesh_model_info_p pmodel_info) +{ + health_info_p phealth_info = pmodel_info->pargs; + for (uint8_t i = 0; i < HEALTH_FAULT_BLOCK_COUNT; ++i) + { + phealth_info->registered_faults[i] = 0; + } +} + +bool health_server_fault_is_set(const mesh_model_info_p pmodel_info, uint8_t fault) +{ + health_info_p phealth_info = pmodel_info->pargs; + uint8_t pos = fault / HEALTH_FAULT_BLOCK_SIZE; + uint8_t bit = fault % HEALTH_FAULT_BLOCK_SIZE; + + return (0x01 == (phealth_info->current_faults[pos] & (1 << bit))); +} + + +/** + * @brief health model receive callback + * @param pmesh_msg - received mesh message + */ +static bool health_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_HEALTH_ATTN_GET: + if (pmesh_msg->msg_len == sizeof(health_attn_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_attn_stat(pmesh_msg, attn_timer_get(pmesh_msg->pmodel_info->element_index), delay_rsp_time); + } + break; + case MESH_MSG_HEALTH_ATTN_SET: + case MESH_MSG_HEALTH_ATTN_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(health_attn_set_t)) + { + health_attn_set_p pmsg = (health_attn_set_p)pbuffer; + attn_timer_start(pmesh_msg->pmodel_info->element_index, pmsg->attn); + if (pmesh_msg->access_opcode == MESH_MSG_HEALTH_ATTN_SET) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_attn_stat(pmesh_msg, attn_timer_get(pmesh_msg->pmodel_info->element_index), delay_rsp_time); + } + } + break; + case MESH_MSG_HEALTH_PERIOD_GET: + if (pmesh_msg->msg_len == sizeof(health_period_get_t)) + { + health_info_p phealth_info = pmesh_msg->pmodel_info->pargs; + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_period_stat(pmesh_msg, phealth_info->fast_period_divisor, delay_rsp_time); + } + break; + case MESH_MSG_HEALTH_PERIOD_SET: + case MESH_MSG_HEALTH_PERIOD_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(health_period_set_t)) + { + health_period_set_p pmsg = (health_period_set_p)pbuffer; + health_info_p phealth_info = pmesh_msg->pmodel_info->pargs; + if (IS_FAST_PERIOD_DIVISOR_VALID(pmsg->fast_period_divisor)) + { + phealth_info->fast_period_divisor = (pmsg->fast_period_divisor & 0x0f); + if (MESH_MSG_HEALTH_PERIOD_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_period_stat(pmesh_msg, phealth_info->fast_period_divisor, delay_rsp_time); + } + } + } + break; + case MESH_MSG_HEALTH_FAULT_GET: + if (pmesh_msg->msg_len == sizeof(health_fault_get_t)) + { + health_fault_get_p pmsg = (health_fault_get_p)pbuffer; + health_info_p phealth_info = pmesh_msg->pmodel_info->pargs; + if (pmsg->company_id == phealth_info->company_id) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_fault_stat(pmesh_msg, phealth_info->recently_test_id, phealth_info->company_id, + phealth_info->registered_faults, delay_rsp_time); + } + } + break; + case MESH_MSG_HEALTH_FAULT_CLEAR: + case MESH_MSG_HEALTH_FAULT_CLEAR_UNACK: + if (pmesh_msg->msg_len == sizeof(health_fault_clear_t)) + { + health_fault_clear_p pmsg = (health_fault_clear_p)pbuffer; + health_info_p phealth_info = pmesh_msg->pmodel_info->pargs; + if (pmsg->company_id == phealth_info->company_id) + { + health_server_registered_fault_clear_all(pmesh_msg->pmodel_info); + if (MESH_MSG_HEALTH_FAULT_CLEAR == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_fault_stat(pmesh_msg, phealth_info->recently_test_id, phealth_info->company_id, + phealth_info->registered_faults, delay_rsp_time); + } + } + } + break; + case MESH_MSG_HEALTH_FAULT_TEST: + case MESH_MSG_HEALTH_FAULT_TEST_UNACK: + if (pmesh_msg->msg_len == sizeof(health_fault_test_t)) + { + health_fault_test_p pmsg = (health_fault_test_p)pbuffer; + health_info_p phealth_info = pmesh_msg->pmodel_info->pargs; + if (pmsg->company_id == phealth_info->company_id) + { + uint8_t i = 0; + for (; i < phealth_info->num_tests; ++i) + { + if (phealth_info->ptests[i].test_id == pmsg->test_id) + { + phealth_info->recently_test_id = pmsg->test_id; + if (NULL != phealth_info->ptests[i].test_cb) + { + phealth_info->ptests[i].test_cb(pmesh_msg->pmodel_info, phealth_info->company_id, pmsg->test_id); + } + break; + } + } + if (i < phealth_info->num_tests) + { + if (MESH_MSG_HEALTH_FAULT_TEST == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + health_fault_stat(pmesh_msg, phealth_info->recently_test_id, phealth_info->company_id, + phealth_info->registered_faults, delay_rsp_time); + } + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void health_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == health_server_receive) + { + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool health_server_reg(uint16_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_HEALTH_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(health_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("health_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(health_info_t)); + + pmodel_info->model_receive = health_server_receive; + +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = health_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = health_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl.h new file mode 100644 index 00000000..51c8ba4a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl.h @@ -0,0 +1,523 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_ctl.h +* @brief Head file for light ctl models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-27 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _LIGHT_CTL_H +#define _LIGHT_CTL_H + +#include "mesh_api.h" +#include "generic_transition_time.h" +#include "generic_types.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_CTL + * @{ + */ + +/** + * @defgroup LIGHT_CTL_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_LIGHT_CTL_GET 0x825D +#define MESH_MSG_LIGHT_CTL_SET 0x825E +#define MESH_MSG_LIGHT_CTL_SET_UNACK 0x825F +#define MESH_MSG_LIGHT_CTL_STAT 0x8260 +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_GET 0x8261 +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_GET 0x8262 +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_STAT 0x8263 +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_SET 0x8264 +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_SET_UNACK 0x8265 +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_STAT 0x8266 +#define MESH_MSG_LIGHT_CTL_DEFAULT_GET 0x8267 +#define MESH_MSG_LIGHT_CTL_DEFAULT_STAT 0x8268 +#define MESH_MSG_LIGHT_CTL_DEFAULT_SET 0x8269 +#define MESH_MSG_LIGHT_CTL_DEFAULT_SET_UNACK 0x826A +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET 0x826B +#define MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK 0x826C +/** @} */ + +/** + * @defgroup LIGHT_CTL_MODEL_DI Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_LIGHT_CTL_SERVER 0x1303FFFF +#define MESH_MODEL_LIGHT_CTL_SETUP_SERVER 0x1304FFFF +#define MESH_MODEL_LIGHT_CTL_CLIENT 0x1305FFFF +#define MESH_MODEL_LIGHT_CTL_TEMPERATURE_SERVER 0x1306FFFF +/** @} */ + +/** + * @defgroup LIGHT_CTL_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define LIGHT_CTL_TEMPERATURE_LOWER_LIMIT 0x0320 +#define LIGHT_CTL_TEMPERATURE_UPPER_LIMIT 0x4E20 +#define LIGHT_CTL_TEMPERATURE_DELTA (0x4E20 - 0x0320) +#define LIGHT_CTL_TEMPERATURE_UNKNOWN 0xFFFF +#define IS_LIGHT_CTL_TEMPERATURE_VALID(VAL) \ + (((VAL) >= LIGHT_CTL_TEMPERATURE_LOWER_LIMIT) && ((VAL) <= LIGHT_CTL_TEMPERATURE_UPPER_LIMIT)) +#define IS_LIGHT_CTL_TEMPERATURE_RANGE_VALID(VAL) \ + (IS_LIGHT_CTL_TEMPERATURE_VALID(VAL) || ((VAL) == LIGHT_CTL_TEMPERATURE_UNKNOWN)) + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_GET)]; +} _PACKED4_ light_ctl_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_SET)]; + uint16_t lightness; + uint16_t temperature; //!< The color temperature of white light in Kelvin + int16_t delta_uv; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_ctl_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_STAT)]; + uint16_t present_lightness; + uint16_t present_temperature; + uint16_t target_lightness; //!< optional + /* If the Target CTL Lightness field is present, the Target CTL Temperature and the Remaining Time field shall also be present; + otherwise these fields shall not be present. */ + uint16_t target_temperature; + generic_transition_time_t remaining_time; +} _PACKED4_ light_ctl_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_TEMPERATURE_GET)]; +} _PACKED4_ light_ctl_temperature_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_TEMPERATURE_SET)]; + uint16_t temperature; //!< The color temperature of white light in Kelvin + int16_t delta_uv; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_ctl_temperature_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_TEMPERATURE_STAT)]; + uint16_t present_temperature; + uint16_t present_delta_uv; + uint16_t target_temperature; //!< optional + /* If the Target CTL Lightness field is present, the Target CTL Temperature and the Remaining Time field shall also be present; + otherwise these fields shall not be present. */ + uint16_t target_delta_uv; + generic_transition_time_t remaining_time; +} _PACKED4_ light_ctl_temperature_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_GET)]; +} _PACKED4_ light_ctl_temperature_range_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET)]; + uint16_t range_min; + uint16_t range_max; +} _PACKED4_ light_ctl_temperature_range_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_STAT)]; + generic_stat_t stat; + uint16_t range_min; + uint16_t range_max; +} _PACKED4_ light_ctl_temperature_range_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_DEFAULT_GET)]; +} _PACKED4_ light_ctl_default_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_DEFAULT_SET)]; + uint16_t lightness; + uint16_t temperature; //!< The color temperature of white light in Kelvin + int16_t delta_uv; +} _PACKED4_ light_ctl_default_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CTL_DEFAULT_STAT)]; + uint16_t lightness; + uint16_t temperature; //!< The color temperature of white light in Kelvin + int16_t delta_uv; +} _PACKED4_ light_ctl_default_stat_t; +/** @} */ + +/** + * @defgroup LIGHT_CTL_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_LIGHT_CTL 0 +#define GENERIC_TRANSITION_TYPE_LIGHT_CTL_TEMPERATURE 1 +#define DELAY_EXECUTION_TYPE_CTL 0 +#define DELAY_EXECUTION_TYPE_CTL_TEMPERATURE 1 +/** @} */ + +/** + * @defgroup LIGHT_CTL_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_CTL_SERVER_GET 0 //!< @ref light_ctl_server_get_t +#define LIGHT_CTL_SERVER_GET_DEFAULT 1 //!< @ref light_ctl_server_get_default_t +#define LIGHT_CTL_SERVER_GET_TEMPERATURE 2 //!< @ref light_ctl_server_get_temperature_t +#define LIGHT_CTL_SERVER_GET_TEMPERATURE_RANGE 3 //!< @ref light_ctl_server_get_temperature_range_t +#define LIGHT_CTL_SERVER_GET_DEFAULT_TRANSITION_TIME 4 //!< @ref light_ctl_server_get_default_transition_time_t +#define LIGHT_CTL_SERVER_SET 5 //!< @ref light_ctl_server_set_t +#define LIGHT_CTL_SERVER_SET_TEMPERATURE 6 //!< @ref light_ctl_server_set_temperature_t +#define LIGHT_CTL_SERVER_SET_DEFAULT 7 //!< @ref light_ctl_server_set_default_t +#define LIGHT_CTL_SERVER_SET_TEMPERATURE_RANGE 8 //!< @ref light_ctl_server_set_temperature_range_t + +typedef struct +{ + uint16_t lightness; + uint16_t temperature; +} light_ctl_server_get_t; + +typedef struct +{ + uint16_t temperature; + int16_t delta_uv; +} light_ctl_server_get_temperature_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} light_ctl_server_get_default_transition_time_t; + +typedef struct +{ + uint16_t lightness; + uint16_t temperature; + int16_t delta_uv; +} light_ctl_server_get_default_t; + +typedef struct +{ + uint16_t range_min; + uint16_t range_max; +} light_ctl_server_get_temperature_range_t; + +typedef struct +{ + uint16_t lightness; + uint16_t temperature; + int16_t delta_uv; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_ctl_server_set_t; + +typedef struct +{ + uint16_t temperature; + int16_t delta_uv; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_ctl_server_set_temperature_t; + +typedef struct +{ + uint16_t lightness; + uint16_t temperature; + int16_t delta_uv; +} light_ctl_server_set_default_t; + +typedef struct +{ + uint16_t range_min; + uint16_t range_max; +} light_ctl_server_set_temperature_range_t; + +/** @} */ + +/** + * @defgroup LIGHT_CTL_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_CTL_CLIENT_STATUS 0 //!< @ref light_ctl_client_status_t +#define LIGHT_CTL_CLIENT_STATUS_TEMPERATURE 1 //!< @ref light_ctl_client_status_temperature_t +#define LIGHT_CTL_CLIENT_STATUS_TEMPERATURE_RANGE 2 //!< @ref light_ctl_client_status_temperature_range_t +#define LIGHT_CTL_CLIENT_STATUS_DEFAULT 3 //!< @ref light_ctl_client_status_default_t + +typedef struct +{ + uint16_t src; + uint16_t present_lightness; + uint16_t present_temperature; + bool optional; + uint16_t target_lightness; + uint16_t target_temperature; + generic_transition_time_t remaining_time; +} light_ctl_client_status_t; + +typedef struct +{ + uint16_t src; + uint16_t present_temperature; + uint16_t present_delta_uv; + bool optional; + uint16_t target_temperature; + uint16_t target_delta_uv; + generic_transition_time_t remaining_time; +} light_ctl_client_status_temperature_t; + +typedef struct +{ + uint16_t src; + generic_stat_t status; + uint16_t range_min; + uint16_t range_max; +} light_ctl_client_status_temperature_range_t; + +typedef struct +{ + uint16_t src; + uint16_t lightness; + uint16_t temperature; + int16_t delta_uv; +} light_ctl_client_status_default_t; +/** @} */ + + +/** + * @defgroup LIGHT_CTL_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register light ctl server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light ctl server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_ctl_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light ctl setup server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light ctl server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_ctl_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light ctl temperature server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light ctl temperature server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_ctl_temperature_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish light ctl status + * @param[in] pmodel_info: pointer to light ctl server model context + * @param[in] lightness: lightness need to publish + * @param[in] temperature: temperature need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_ctl_publish(const mesh_model_info_p pmodel_info, uint16_t lightness, + uint16_t temperature); + +/** + * @brief publish light temperature status + * @param[in] pmodel_info: pointer to light ctl temperature server model context + * @param[in] temperature: temperature need to publish + * @param[in] delta_uv: delta_uv need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_ctl_temperature_publish(const mesh_model_info_p pmodel_info, + uint16_t temperature, int16_t delta_uv); + +/** + * @brief convert light ctl temperature to generic level + * @param[in] temperature: light ctl temperature + * @return generic level value + */ +int16_t light_ctl_temperature_to_generic_level(uint16_t temperature); + +/** + * @brief convert generic level to light ctl temperature + * @param[in] level: generic level value + * @return light ctl temperature value + */ +uint16_t generic_level_to_light_ctl_temperature(int16_t level); + +/** + * @brief convert light ctl delta uv to represented delta uv + * @param[in] delta_uv: light ctl delta uv + * @return light represented delta uv + */ +float light_ctl_delta_uv_to_represented_delta_uv(int16_t delta_uv); + +/** + * @brief convert light represented delta uv to light ctl delta uv + * @param[in] delta_uv: light represented delta uv + * @return light ctl delta uv + */ +int16_t light_represented_delta_uv_to_ctl_delta_uv(float delta_uv); + +/** @} */ + +/** + * @defgroup LIGHT_CTL_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register light ctl client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light ctl client model context + * @retval true: register success + * @retval false: register failed + */ +bool light_ctl_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get light ctl + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_ctl_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); +/** + * @brief set light ctl + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired lightness + * @param[in] temperature: desired temperature + * @param[in] delta_uv: desired delta_uv + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_ctl_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t temperature, int16_t delta_uv, uint8_t tid, + bool optional, generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light ctl temperature + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_ctl_temperature_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light ctl temperature + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] temperature: desired temperature + * @param[in] delta_uv: desired delta_uv + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_ctl_temperature_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t temperature, int16_t delta_uv, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light ctl temperature range + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_ctl_temperature_range_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light ctl temperature range + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] range_min: desired light lightness minimum value + * @param[in] range_max: desired light lightness maximum value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_ctl_temperature_range_set(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t range_min, uint16_t range_max, bool ack); + +/** + * @brief get default light ctl + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_ctl_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set default light ctl + * @param[in] pmodel_info: pointer to light ctl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired default lightness value + * @param[in] temperature : desired default temperature value + * @param[in] delta_uv: desired default delta_uv value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_ctl_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t temperature, int16_t delta_uv, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_CTL_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_client.c new file mode 100644 index 00000000..5bf9c45b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_client.c @@ -0,0 +1,268 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_ctl_client.c +* @brief Source file for light ctl client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_ctl.h" + +static mesh_msg_send_cause_t light_ctl_client_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_ctl_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_ctl_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_GET); + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_ctl_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t temperature, int16_t delta_uv, uint8_t tid, + bool optional, generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_ctl_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_ctl_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_ctl_set_t, trans_time); + } + msg.lightness = lightness; + msg.temperature = temperature; + msg.delta_uv = delta_uv; + msg.tid = tid; + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_ctl_temperature_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_ctl_temperature_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_GET); + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_ctl_temperature_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t temperature, int16_t delta_uv, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_ctl_temperature_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_ctl_temperature_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_ctl_temperature_set_t, trans_time); + } + msg.temperature = temperature; + msg.delta_uv = delta_uv; + msg.tid = tid; + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_ctl_temperature_range_get(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index) +{ + light_ctl_temperature_range_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_GET); + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_ctl_temperature_range_set(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t range_min, uint16_t range_max, bool ack) +{ + light_ctl_temperature_range_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK); + } + + msg.range_min = range_min; + msg.range_max = range_max; + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_ctl_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_ctl_default_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_DEFAULT_GET); + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_ctl_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t temperature, int16_t delta_uv, bool ack) +{ + light_ctl_default_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_DEFAULT_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_DEFAULT_SET_UNACK); + } + msg.lightness = lightness; + msg.temperature = temperature; + msg.delta_uv = delta_uv; + return light_ctl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool light_ctl_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CTL_STAT: + { + light_ctl_stat_t *pmsg = (light_ctl_stat_t *)pbuffer; + light_ctl_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_lightness = pmsg->present_lightness; + status_data.present_temperature = pmsg->present_temperature; + if (pmesh_msg->msg_len == sizeof(light_ctl_stat_t)) + { + status_data.optional = TRUE; + status_data.target_lightness = pmsg->target_lightness; + status_data.target_temperature = pmsg->target_temperature; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_CTL_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_CTL_TEMPERATURE_STAT: + { + light_ctl_temperature_stat_t *pmsg = (light_ctl_temperature_stat_t *)pbuffer; + light_ctl_client_status_temperature_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_temperature = pmsg->present_temperature; + status_data.present_delta_uv = pmsg->present_delta_uv; + if (pmesh_msg->msg_len == sizeof(light_ctl_stat_t)) + { + status_data.optional = TRUE; + status_data.target_temperature = pmsg->target_temperature; + status_data.target_delta_uv = pmsg->target_delta_uv; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_CTL_CLIENT_STATUS_TEMPERATURE, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_STAT: + if (pmesh_msg->msg_len == sizeof(light_ctl_temperature_range_stat_t)) + { + light_ctl_temperature_range_stat_t *pmsg = (light_ctl_temperature_range_stat_t *)pbuffer; + light_ctl_client_status_temperature_range_t range_data = {pmesh_msg->src, pmsg->stat, pmsg->range_min, pmsg->range_max}; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + LIGHT_CTL_CLIENT_STATUS_TEMPERATURE_RANGE, + &range_data); + } + } + break; + case MESH_MSG_LIGHT_CTL_DEFAULT_STAT: + if (pmesh_msg->msg_len == sizeof(light_ctl_default_stat_t)) + { + light_ctl_default_stat_t *pmsg = (light_ctl_default_stat_t *)pbuffer; + light_ctl_client_status_default_t default_data = {pmesh_msg->src, pmsg->lightness, pmsg->temperature, pmsg->delta_uv}; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_CTL_CLIENT_STATUS_DEFAULT, + &default_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool light_ctl_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_CTL_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = light_ctl_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_ctl_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_server.c new file mode 100644 index 00000000..06c93307 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_server.c @@ -0,0 +1,614 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_ctl_server.c +* @brief Source file for generic on off server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "light_ctl.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +typedef struct +{ + uint8_t tid; + uint16_t target_lightness; + uint16_t target_temperature; + uint16_t target_delta_uv; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_ctl_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_ctl_process_result_t; + + +int16_t light_ctl_temperature_to_generic_level(uint16_t temperature) +{ + return (temperature - LIGHT_CTL_TEMPERATURE_LOWER_LIMIT) * 65535.0 / LIGHT_CTL_TEMPERATURE_DELTA - + 32768; +} + +uint16_t generic_level_to_light_ctl_temperature(int16_t level) +{ + return LIGHT_CTL_TEMPERATURE_LOWER_LIMIT + (level + 32768) / 65535.0 * LIGHT_CTL_TEMPERATURE_DELTA; +} + +float light_ctl_delta_uv_to_represented_delta_uv(int16_t delta_uv) +{ + return delta_uv / 32768.0; +} + +int16_t light_represented_delta_uv_to_ctl_delta_uv(float delta_uv) +{ + return delta_uv * 32768; +} + +static mesh_msg_send_cause_t light_ctl_server_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t light_ctl_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_lightness, uint16_t present_temperature, bool optional, + uint16_t target_lightness, uint16_t target_temperature, generic_transition_time_t remaining_time, + uint32_t delay_time) +{ + light_ctl_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_STAT); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(light_ctl_stat_t); + msg.target_lightness = target_lightness; + msg.target_temperature = target_temperature; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(light_ctl_stat_t, target_lightness); + } + msg.present_lightness = present_lightness; + msg.present_temperature = present_temperature; + return light_ctl_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, delay_time); +} + +mesh_msg_send_cause_t light_ctl_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness, + uint16_t temperature, uint32_t delay_time) +{ + /* avoid gcc compile warning */ + (void)delay_time; + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = light_ctl_stat(pmodel_info, 0, 0, lightness, temperature, FALSE, 0, 0, trans_time, 0); + } + + return ret; +} + +mesh_msg_send_cause_t light_ctl_publish(const mesh_model_info_p pmodel_info, uint16_t lightness, + uint16_t temperature) +{ + return light_ctl_delay_publish(pmodel_info, lightness, temperature, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_ctl_state_change_publish(const mesh_model_info_p pmodel_info, uint16_t lightness, + uint16_t temperature, light_ctl_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_ctl_publish(pmodel_info, lightness, temperature); + } +} +#endif + +/* this message is also used by light ctl temperature model */ +mesh_msg_send_cause_t light_ctl_temperature_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_temperature, uint16_t present_delta_uv, bool optional, + uint16_t target_temperature, uint16_t target_delta_uv, generic_transition_time_t remaining_time, + uint32_t delay_time) +{ + light_ctl_temperature_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_STAT); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(light_ctl_temperature_stat_t); + msg.target_temperature = target_temperature; + msg.target_delta_uv = target_delta_uv; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(light_ctl_temperature_stat_t, target_temperature); + } + msg.present_temperature = present_temperature; + msg.present_delta_uv = present_delta_uv; + return light_ctl_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, delay_time); +} + +mesh_msg_send_cause_t light_ctl_temperature_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t range_min, uint16_t range_max, + uint32_t delay_time) +{ + light_ctl_temperature_range_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_STAT); + msg.stat = stat; + msg.range_min = range_min; + msg.range_max = range_max; + return light_ctl_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t light_ctl_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t temperature, int16_t delta_uv, + uint32_t delay_time) +{ + light_ctl_default_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CTL_DEFAULT_STAT); + msg.lightness = lightness; + msg.temperature = temperature; + msg.delta_uv = delta_uv; + return light_ctl_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +static light_ctl_server_get_t get_present_ctl(const mesh_model_info_p pmodel_info) +{ + light_ctl_server_get_t get_data = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET, &get_data); + } + + return get_data; +} + +static int32_t light_ctl_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = MODEL_SUCCESS; + light_ctl_server_set_t trans_set_data; + light_ctl_info_t *pctl_info = pmodel_info->pargs; + if (NULL == pctl_info) + { + return 0; + } + trans_set_data.lightness = pctl_info->target_lightness; + trans_set_data.temperature = pctl_info->target_temperature; + trans_set_data.delta_uv = pctl_info->target_delta_uv; + trans_set_data.total_time = total_time; + trans_set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_SET, &trans_set_data); + } + + if (0 == remaining_time.num_steps) + { + light_ctl_server_get_t get_data = {0, 0}; + get_data = get_present_ctl(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + light_ctl_delay_publish(pmodel_info, get_data.lightness, get_data.temperature, + pctl_info->delay_pub_time); +#else + light_ctl_publish(pmodel_info, get_data.lightness, get_data.temperature); +#endif + } + + return ret; +} + +static light_ctl_server_get_t light_ctl_process(const mesh_model_info_p pmodel_info, + uint16_t target_lightness, + uint16_t target_temperature, int16_t target_delta_uv, + generic_transition_time_t trans_time, + light_ctl_process_result_t *presult) +{ + light_ctl_server_get_t ctl_before_set = {0, 0}; + light_ctl_server_get_t ctl_after_set = {0, 0}; + + /* get ctl before set */ + ctl_before_set = get_present_ctl(pmodel_info); + ctl_after_set = ctl_before_set; + + int32_t ret = MODEL_SUCCESS; + light_ctl_server_set_t trans_set_data; + trans_set_data.lightness = target_lightness; + trans_set_data.temperature = target_temperature; + trans_set_data.delta_uv = target_delta_uv; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_SET, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_CTL, trans_time, + light_ctl_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_SET, &trans_set_data); + } + } +#endif + } + else + { + /* get ctl after set */ + ctl_after_set = get_present_ctl(pmodel_info); + } + + + if ((ctl_after_set.lightness != ctl_before_set.lightness) || + (ctl_after_set.temperature != ctl_before_set.temperature)) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return ctl_after_set; +} + +static int32_t light_ctl_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_CTL: + { + light_ctl_info_t *pctl_info = pmodel_info->pargs; + if (NULL == pctl_info) + { + return 0; + } + pctl_info->delay_time = 0; + light_ctl_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + light_ctl_server_get_t present_ctl = light_ctl_process(pmodel_info, pctl_info->target_lightness, + pctl_info->target_temperature, pctl_info->target_delta_uv, + pctl_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_ctl_delay_publish(pmodel_info, present_ctl.lightness, present_ctl.temperature, + pctl_info->delay_pub_time); + } + } +#else + light_ctl_state_change_publish(pmodel_info, present_ctl.lightness, present_ctl.temperature, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_ctl_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CTL_GET: + if (pmesh_msg->msg_len == sizeof(light_ctl_get_t)) + { + light_ctl_info_t *pctl_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (pctl_info->delay_time > 0) + { + remaining_time = pctl_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_CTL); + } + + light_ctl_server_get_t get_data = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_ctl_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_data.lightness, get_data.temperature, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + pctl_info->target_lightness, pctl_info->target_temperature, remaining_time, + delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_CTL_SET: + case MESH_MSG_LIGHT_CTL_SET_UNACK: + { + light_ctl_set_t *pmsg = (light_ctl_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_ctl_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET_DEFAULT_TRANSITION_TIME, &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_ctl_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps) && + IS_LIGHT_CTL_TEMPERATURE_VALID(pmsg->temperature)) + { + light_ctl_server_get_temperature_range_t range = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET_TEMPERATURE_RANGE, &range); + } + + light_ctl_info_t *pctl_info = pmodel_info->pargs; + if ((0 != range.range_min) && (0 != range.range_max)) + { + pctl_info->target_temperature = CLAMP(pmsg->temperature, range.range_min, range.range_max); + } + else + { + pctl_info->target_temperature = pmsg->temperature; + } + pctl_info->target_lightness = pmsg->lightness; + pctl_info->target_delta_uv = pmsg->delta_uv; + pctl_info->tid = pmsg->tid; + pctl_info->trans_time = trans_time; + pctl_info->delay_time = delay_time; + + light_ctl_server_get_t present_ctl; + light_ctl_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_ctl = get_present_ctl(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_CTL, delay_time, + light_ctl_delay_execution); + } + else + { + present_ctl = light_ctl_process(pmodel_info, pctl_info->target_lightness, + pctl_info->target_temperature, pctl_info->target_delta_uv, + trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_CTL_SET) + { + light_ctl_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_ctl.lightness, present_ctl.temperature, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + pctl_info->target_lightness, pctl_info->target_temperature, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_CTL_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_ctl_delay_publish(pmodel_info, present_ctl.lightness, present_ctl.temperature, + delay_pub_time); + } + } + else + { + pctl_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, FALSE, + ack); + } +#else + light_ctl_state_change_publish(pmodel_info, present_ctl.lightness, present_ctl.temperature, result); +#endif + } + } + break; + case MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_GET: + if (pmesh_msg->msg_len == sizeof(light_ctl_temperature_range_get_t)) + { + light_ctl_server_get_temperature_range_t get_range = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, + LIGHT_CTL_SERVER_GET_TEMPERATURE_RANGE, &get_range); + } + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_ctl_temperature_range_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + GENERIC_STAT_SUCCESS, get_range.range_min, + get_range.range_max, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_CTL_DEFAULT_GET: + if (pmesh_msg->msg_len == sizeof(light_ctl_default_get_t)) + { + light_ctl_server_get_default_t get_default = {0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET_DEFAULT, + &get_default); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_ctl_default_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_default.lightness, get_default.temperature, + get_default.delta_uv, delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_ctl_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + light_ctl_server_get_t get_data = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET, &get_data); + } + generic_transition_time_t trans_time = {0, 0}; + light_ctl_stat(pmodel_info, 0, 0, get_data.lightness, get_data.temperature, FALSE, 0, 0, + trans_time, 0); + + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_ctl_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_ctl_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_CTL); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_CTL); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_ctl_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_CTL_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_ctl_info_t *pctl_info = plt_malloc(sizeof(light_ctl_info_t), + RAM_TYPE_DATA_ON); + if (NULL == pctl_info) + { + printe("light_ctl_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pctl_info, 0, sizeof(light_ctl_info_t)); + pmodel_info->pargs = pctl_info; + + pmodel_info->model_receive = light_ctl_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_ctl_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_ctl_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_ctl_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_setup_server.c new file mode 100644 index 00000000..042ba328 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_setup_server.c @@ -0,0 +1,167 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_ctl_setup_server.c +* @brief Source file for light ctl setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_ctl.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t light_ctl_temperature_range_stat(mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t range_min, uint16_t range_max, + uint32_t delay_time); +extern mesh_msg_send_cause_t light_ctl_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t temperature, int16_t delta_uv, + uint32_t delay_time); + +#if 0 +typedef struct +{ + uint8_t tid; + uint16_t target_lightness; + uint16_t target_temperature; + uint16_t target_delta_uv; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_ctl_info_t; +#endif + +static bool light_ctl_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET: + case MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_ctl_temperature_range_set_t)) + { + light_ctl_temperature_range_set_t *pmsg = (light_ctl_temperature_range_set_t *)pbuffer; + if ((pmsg->range_min < pmsg->range_max) && + IS_LIGHT_CTL_TEMPERATURE_RANGE_VALID(pmsg->range_min) && + IS_LIGHT_CTL_TEMPERATURE_RANGE_VALID(pmsg->range_max)) + { + light_ctl_server_set_temperature_range_t set_range; + set_range.range_min = pmsg->range_min; + set_range.range_max = pmsg->range_max; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + LIGHT_CTL_SERVER_SET_TEMPERATURE_RANGE, &set_range); + } + + if (MESH_MSG_LIGHT_CTL_TEMPERATURE_RANGE_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_ctl_temperature_range_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + GENERIC_STAT_SUCCESS, set_range.range_min, + set_range.range_max, delay_rsp_time); + } + } + } + break; + case MESH_MSG_LIGHT_CTL_DEFAULT_SET: + case MESH_MSG_LIGHT_CTL_DEFAULT_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_ctl_default_set_t)) + { + light_ctl_default_set_t *pmsg = (light_ctl_default_set_t *)pbuffer; + if (IS_LIGHT_CTL_TEMPERATURE_VALID(pmsg->temperature)) + { + light_ctl_server_set_default_t set_default; + set_default.lightness = pmsg->lightness; + set_default.temperature = pmsg->temperature; + set_default.delta_uv = pmsg->delta_uv; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_CTL_SERVER_SET_DEFAULT, + &set_default); + } + if (MESH_MSG_LIGHT_CTL_DEFAULT_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_ctl_default_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + set_default.lightness, set_default.temperature, + set_default.delta_uv, delay_rsp_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_ctl_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_ctl_setup_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_ctl_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_CTL_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + light_ctl_info_t *pctl_info = plt_malloc(sizeof(light_ctl_info_t), + RAM_TYPE_DATA_ON); + if (NULL == pctl_info) + { + printe("light_ctl_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pctl_info, 0, sizeof(light_ctl_info_t)); +#endif + pmodel_info->model_receive = light_ctl_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_ctl_setup_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_ctl_setup_server_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_temperature_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_temperature_server.c new file mode 100644 index 00000000..31464433 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_temperature_server.c @@ -0,0 +1,450 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file generic_on_off_server.c +* @brief Source file for generic on off server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "light_ctl.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t light_ctl_temperature_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_temperature, uint16_t present_delta_uv, bool optional, + uint16_t target_temperature, uint16_t target_delta_uv, generic_transition_time_t remaining_time, + uint32_t delay_time); + +typedef struct +{ + uint8_t tid; + uint16_t target_temperature; + uint16_t target_delta_uv; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_ctl_temperature_info_t, *light_ctl_temperature_info_p; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_ctl_temperature_process_result_t; + + +static light_ctl_server_get_temperature_t get_present_temperature(const mesh_model_info_p + pmodel_info) +{ + light_ctl_server_get_temperature_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET_TEMPERATURE, &get_data); + } + + return get_data; +} + +mesh_msg_send_cause_t light_ctl_temperature_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t temperature, int16_t delta_uv, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = light_ctl_temperature_stat(pmodel_info, 0, 0, temperature, delta_uv, FALSE, 0, 0, + trans_time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_ctl_temperature_publish(const mesh_model_info_p pmodel_info, + uint16_t temperature, int16_t delta_uv) +{ + return light_ctl_temperature_delay_publish(pmodel_info, temperature, delta_uv, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_ctl_temperature_state_change_publish(const mesh_model_info_p pmodel_info, + uint16_t temperature, int16_t delta_uv, + light_ctl_temperature_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_ctl_temperature_publish(pmodel_info, temperature, delta_uv); + } +} +#endif + +static int32_t light_ctl_temperature_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = 0; + light_ctl_server_set_temperature_t trans_set_data; + light_ctl_temperature_info_p ptemp_info = pmodel_info->pargs; + trans_set_data.temperature = ptemp_info->target_temperature; + trans_set_data.delta_uv = ptemp_info->target_delta_uv; + trans_set_data.total_time = total_time; + trans_set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_SET_TEMPERATURE, + &trans_set_data); + } + + if (0 == remaining_time.num_steps) + { + light_ctl_server_get_temperature_t get_data = {0, 0}; + get_data = get_present_temperature(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + light_ctl_temperature_delay_publish(pmodel_info, get_data.temperature, get_data.delta_uv, + ptemp_info->delay_pub_time); +#else + light_ctl_temperature_publish(pmodel_info, get_data.temperature, get_data.delta_uv); +#endif + } + + return ret; +} + +static light_ctl_server_get_temperature_t light_ctl_temperature_process( + const mesh_model_info_p pmodel_info, + uint16_t target_temperature, int16_t target_delta_uv, + generic_transition_time_t trans_time, + light_ctl_temperature_process_result_t *presult) +{ + light_ctl_server_get_temperature_t temperature_before_set = {0, 0}; + light_ctl_server_get_temperature_t temperature_after_set = {0, 0}; + + /* get temperature before set */ + temperature_before_set = get_present_temperature(pmodel_info); + temperature_after_set = temperature_before_set; + + int32_t ret = MODEL_SUCCESS; + light_ctl_server_set_temperature_t trans_set_data; + trans_set_data.temperature = target_temperature; + trans_set_data.delta_uv = target_delta_uv; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_SET_TEMPERATURE, + &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_CTL_TEMPERATURE, + trans_time, + light_ctl_temperature_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_SET_TEMPERATURE, &trans_set_data); + } + } +#endif + } + else + { + /* get temperature set */ + temperature_after_set = get_present_temperature(pmodel_info); + } + + if ((temperature_after_set.temperature != temperature_before_set.temperature) || + (temperature_after_set.delta_uv != temperature_before_set.delta_uv)) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return temperature_after_set; +} + +static int32_t light_ctl_temperature_delay_execution(mesh_model_info_t *pmodel_info, + uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_CTL_TEMPERATURE: + { + light_ctl_temperature_info_p ptemp_info = pmodel_info->pargs; + ptemp_info->delay_time = 0; + light_ctl_temperature_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + light_ctl_server_get_temperature_t present_temperature = light_ctl_temperature_process(pmodel_info, + ptemp_info->target_temperature, + ptemp_info->target_delta_uv, ptemp_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_ctl_temperature_delay_publish(pmodel_info, present_temperature.temperature, + present_temperature.delta_uv, ptemp_info->delay_pub_time); + } + } +#else + light_ctl_temperature_state_change_publish(pmodel_info, present_temperature.temperature, + present_temperature.delta_uv, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_ctl_temperature_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CTL_TEMPERATURE_GET: + if (pmesh_msg->msg_len == sizeof(light_ctl_temperature_get_t)) + { + light_ctl_temperature_info_p ptemp_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (ptemp_info->delay_time > 0) + { + remaining_time = ptemp_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_CTL_TEMPERATURE); + } + + light_ctl_server_get_temperature_t get_data = get_present_temperature(pmodel_info); + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_ctl_temperature_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_data.temperature, get_data.delta_uv, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + ptemp_info->target_temperature, ptemp_info->target_delta_uv, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_CTL_TEMPERATURE_SET: + case MESH_MSG_LIGHT_CTL_TEMPERATURE_SET_UNACK: + { + light_ctl_temperature_set_t *pmsg = (light_ctl_temperature_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_ctl_temperature_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET_DEFAULT_TRANSITION_TIME, &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_ctl_temperature_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps) && + IS_LIGHT_CTL_TEMPERATURE_VALID(pmsg->temperature)) + { + light_ctl_temperature_info_t *ptemp_info = pmodel_info->pargs; + light_ctl_server_get_temperature_range_t range = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_CTL_SERVER_GET_TEMPERATURE_RANGE, &range); + } + + if ((0 != range.range_min) && (0 != range.range_max)) + { + ptemp_info->target_temperature = CLAMP(pmsg->temperature, range.range_min, range.range_max); + } + else + { + ptemp_info->target_temperature = pmsg->temperature; + } + ptemp_info->target_delta_uv = pmsg->delta_uv; + ptemp_info->tid = pmsg->tid; + ptemp_info->trans_time = trans_time; + ptemp_info->delay_time = delay_time; + + light_ctl_server_get_temperature_t present_temperature; + light_ctl_temperature_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_temperature = get_present_temperature(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_CTL_TEMPERATURE, delay_time, + light_ctl_temperature_delay_execution); + } + else + { + present_temperature = light_ctl_temperature_process(pmodel_info, ptemp_info->target_temperature, + ptemp_info->target_delta_uv, trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_CTL_TEMPERATURE_SET) + { + light_ctl_temperature_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_temperature.temperature, present_temperature.delta_uv, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + ptemp_info->target_temperature, ptemp_info->target_delta_uv, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_CTL_TEMPERATURE_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_ctl_temperature_delay_publish(pmodel_info, present_temperature.temperature, + present_temperature.delta_uv, delay_pub_time); + } + } + else + { + ptemp_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + light_ctl_temperature_state_change_publish(pmodel_info, present_temperature.temperature, + present_temperature.delta_uv, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_ctl_temperature_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + light_ctl_server_get_temperature_t get_data = get_present_temperature(pmodel_info);; + generic_transition_time_t trans_time = {0, 0}; + light_ctl_temperature_stat(pmodel_info, 0, 0, get_data.temperature, get_data.delta_uv, FALSE, 0, 0, + trans_time, 0); + + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_ctl_temperature_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_ctl_temperature_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_CTL_TEMPERATURE); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_CTL_TEMPERATURE); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_ctl_temperature_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_CTL_TEMPERATURE_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_ctl_temperature_info_p ptemp_info = plt_malloc(sizeof(light_ctl_temperature_info_t), + RAM_TYPE_DATA_ON); + if (NULL == ptemp_info) + { + printe("light_ctl_temperature_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(ptemp_info, 0, sizeof(light_ctl_temperature_info_t)); + pmodel_info->pargs = ptemp_info; + + pmodel_info->model_receive = light_ctl_temperature_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_ctl_temperature_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_ctl_temperature_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_ctl_temperature_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl.h new file mode 100644 index 00000000..74f493f3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl.h @@ -0,0 +1,644 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_hsl.h +* @brief Head file for light hsl models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-27 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _LIGHT_HSL_H +#define _LIGHT_HSL_H + +#include "mesh_api.h" +#include "generic_transition_time.h" +#include "generic_types.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_HSL + * @{ + */ + +/** + * @defgroup LIGHT_HSL_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_LIGHT_HSL_GET 0x826D +#define MESH_MSG_LIGHT_HSL_HUE_GET 0x826E +#define MESH_MSG_LIGHT_HSL_HUE_SET 0x826F +#define MESH_MSG_LIGHT_HSL_HUE_SET_UNACK 0x8270 +#define MESH_MSG_LIGHT_HSL_HUE_STAT 0x8271 +#define MESH_MSG_LIGHT_HSL_SATURATION_GET 0x8272 +#define MESH_MSG_LIGHT_HSL_SATURATION_SET 0x8273 +#define MESH_MSG_LIGHT_HSL_SATURATION_SET_UNACK 0x8274 +#define MESH_MSG_LIGHT_HSL_SATURATION_STAT 0x8275 +#define MESH_MSG_LIGHT_HSL_SET 0x8276 +#define MESH_MSG_LIGHT_HSL_SET_UNACK 0x8277 +#define MESH_MSG_LIGHT_HSL_STAT 0x8278 +#define MESH_MSG_LIGHT_HSL_TARGET_GET 0x8279 +#define MESH_MSG_LIGHT_HSL_TARGET_STAT 0x827A +#define MESH_MSG_LIGHT_HSL_DEFAULT_GET 0x827B +#define MESH_MSG_LIGHT_HSL_DEFAULT_STAT 0x827C +#define MESH_MSG_LIGHT_HSL_RANGE_GET 0x827D +#define MESH_MSG_LIGHT_HSL_RANGE_STAT 0x827E +#define MESH_MSG_LIGHT_HSL_DEFAULT_SET 0x827F +#define MESH_MSG_LIGHT_HSL_DEFAULT_SET_UNACK 0x8280 +#define MESH_MSG_LIGHT_HSL_RANGE_SET 0x8281 +#define MESH_MSG_LIGHT_HSL_RANGE_SET_UNACK 0x8282 +/** @} */ + +/** + * @defgroup LIGHT_HSL_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_LIGHT_HSL_SERVER 0x1307FFFF +#define MESH_MODEL_LIGHT_HSL_SETUP_SERVER 0x1308FFFF +#define MESH_MODEL_LIGHT_HSL_CLIENT 0x1309FFFF +#define MESH_MODEL_LIGHT_HSL_HUE_SERVER 0x130AFFFF +#define MESH_MODEL_LIGHT_HSL_SATURATION_SERVER 0x130BFFFF +/** @} */ + +/** + * @defgroup LIGHT_HSL_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define LIGHT_HSL_TEMPERATURE_LOWER_LIMIT 0x0320 +#define LIGHT_HSL_TEMPERATURE_UPPER_LIMIT 0x4E20 + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_GET)]; +} _PACKED4_ light_hsl_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_SET)]; + uint16_t lightness; + uint16_t hue; + uint16_t saturation; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_hsl_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_STAT)]; + uint16_t lightness; //!< actual + uint16_t hue; + uint16_t saturation; + generic_transition_time_t remaining_time; //!< optional +} _PACKED4_ light_hsl_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_TARGET_GET)]; +} _PACKED4_ light_hsl_target_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_TARGET_STAT)]; + uint16_t lightness; + uint16_t hue; + uint16_t saturation; + generic_transition_time_t remaining_time; //!< optional +} _PACKED4_ light_hsl_target_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_HUE_GET)]; +} _PACKED4_ light_hsl_hue_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_HUE_SET)]; + uint16_t hue; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_hsl_hue_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_HUE_STAT)]; + uint16_t present_hue; + uint16_t target_hue; //!< optional + /* If the target_hue field is present, the remaining_time field shall also be present; + otherwise these fields shall not be present. */ + generic_transition_time_t remaining_time; +} _PACKED4_ light_hsl_hue_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_SATURATION_GET)]; +} _PACKED4_ light_hsl_saturation_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_SATURATION_SET)]; + uint16_t saturation; + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_hsl_saturation_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_SATURATION_STAT)]; + uint16_t present_saturation; + uint16_t target_saturation; //!< optional + /* If the target_saturation field is present, the remaining_time field shall also be present; + otherwise these fields shall not be present. */ + generic_transition_time_t remaining_time; +} _PACKED4_ light_hsl_saturation_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_DEFAULT_GET)]; +} _PACKED4_ light_hsl_default_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_DEFAULT_SET)]; + uint16_t lightness; + uint16_t hue; + uint16_t saturation; +} _PACKED4_ light_hsl_default_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_DEFAULT_STAT)]; + uint16_t lightness; + uint16_t hue; + uint16_t saturation; +} _PACKED4_ light_hsl_default_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_RANGE_GET)]; +} _PACKED4_ light_hsl_range_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_RANGE_SET)]; + uint16_t hue_range_min; + uint16_t hue_range_max; + uint16_t saturation_range_min; + uint16_t saturation_range_max; +} _PACKED4_ light_hsl_range_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_HSL_RANGE_STAT)]; + generic_stat_t stat; + uint16_t hue_range_min; + uint16_t hue_range_max; + uint16_t saturation_range_min; + uint16_t saturation_range_max; +} _PACKED4_ light_hsl_range_stat_t; +/** @} */ + +/** + * @defgroup LIGHT_HSL_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_LIGHT_HSL 0 +#define GENERIC_TRANSITION_TYPE_LIGHT_HSL_HUE 1 +#define GENERIC_TRANSITION_TYPE_LIGHT_HSL_SATURATION 2 +#define DELAY_EXECUTION_TYPE_LIGHT_HSL 0 +#define DELAY_EXECUTION_TYPE_LIGHT_HSL_HUE 1 +#define DELAY_EXECUTION_TYPE_LIGHT_HSL_SATURATION 2 +/** @} */ + +/** + * @defgroup LIGHT_HSL_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_HSL_SERVER_GET 0 //!< @ref light_hsl_server_get_t +#define LIGHT_HSL_SERVER_GET_HUE 1 //!< @ref light_hsl_server_get_hue_t +#define LIGHT_HSL_SERVER_GET_SATURATION 2 //!< @ref light_hsl_server_get_saturation_t +#define LIGHT_HSL_SERVER_GET_DEFAULT 3 //!< @ref light_hsl_server_get_default_t +#define LIGHT_HSL_SERVER_GET_RANGE 4 //!< @ref light_hsl_server_get_range_t +#define LIGHT_HSL_SERVER_GET_DEFAULT_TRANSITION_TIME 5 //!< @ref light_hsl_server_get_default_transition_time_t +#define LIGHT_HSL_SERVER_SET 6 //!< @ref light_hsl_server_set_t +#define LIGHT_HSL_SERVER_SET_HUE 8 //!< @ref light_hsl_server_set_hue_t +#define LIGHT_HSL_SERVER_SET_SATURATION 9 //!< @ref light_hsl_server_set_saturation_t +#define LIGHT_HSL_SERVER_SET_DEFAULT 10 //!< @ref light_hsl_server_set_default_t +#define LIGHT_HSL_SERVER_SET_RANGE 11 //!< @ref light_hsl_server_set_range_t + +typedef struct +{ + uint16_t lightness; + uint16_t hue; + uint16_t saturation; +} light_hsl_server_get_t; + +typedef struct +{ + uint16_t hue; +} light_hsl_server_get_hue_t; + +typedef struct +{ + uint16_t saturation; +} light_hsl_server_get_saturation_t; + +typedef struct +{ + uint16_t lightness; + uint16_t hue; + uint16_t saturation; +} light_hsl_server_get_default_t; + +typedef struct +{ + uint16_t hue_range_min; + uint16_t hue_range_max; + uint16_t saturation_range_min; + uint16_t saturation_range_max; +} light_hsl_server_get_range_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} light_hsl_server_get_default_transition_time_t; + +typedef struct +{ + uint16_t lightness; + uint16_t hue; + uint16_t saturation; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_hsl_server_set_t; + +typedef struct +{ + uint16_t hue; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_hsl_server_set_hue_t; + +typedef struct +{ + uint16_t saturation; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_hsl_server_set_saturation_t; + +typedef struct +{ + uint16_t lightness; + uint16_t hue; + uint16_t saturation; +} light_hsl_server_set_default_t; + +typedef struct +{ + uint16_t hue_range_min; + uint16_t hue_range_max; + uint16_t saturation_range_min; + uint16_t saturation_range_max; +} light_hsl_server_set_range_t; + +/** @} */ + +/** + * @defgroup LIGHT_HSL_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_HSL_CLIENT_STATUS 0 //!< @ref light_hsl_client_status_t +#define LIGHT_HSL_CLIENT_STATUS_TARGET 1 //!< @ref light_hsl_client_status_t +#define LIGHT_HSL_CLIENT_STATUS_HUE 2 //!< @ref light_hsl_client_status_hue_t +#define LIGHT_HSL_CLIENT_STATUS_SATURATION 3 //!< @ref light_hsl_client_status_saturation_t +#define LIGHT_HSL_CLIENT_STATUS_DEFAULT 4 //!< @ref light_hsl_client_status_default_t +#define LIGHT_HSL_CLIENT_STATUS_RANGE 5 //!< @ref light_hsl_client_status_range_t + +typedef struct +{ + uint16_t src; + uint16_t lightness; + uint16_t hue; + uint16_t saturation; + bool optional; + generic_transition_time_t remaining_time; +} light_hsl_client_status_t; + +typedef struct +{ + uint16_t src; + uint16_t present_hue; + bool optional; + uint16_t target_hue; + generic_transition_time_t remaining_time; +} light_hsl_client_status_hue_t; + +typedef struct +{ + uint16_t src; + uint16_t present_saturation; + bool optional; + uint16_t target_saturation; + generic_transition_time_t remaining_time; +} light_hsl_client_status_saturation_t; + +typedef struct +{ + uint16_t src; + uint16_t lightness; + uint16_t hue; + uint16_t saturation; +} light_hsl_client_status_default_t; + +typedef struct +{ + uint16_t src; + generic_stat_t status; + uint16_t hue_range_min; + uint16_t hue_range_max; + uint16_t saturation_range_min; + uint16_t saturation_range_max; +} light_hsl_client_status_range_t; +/** @} */ + +/** + * @defgroup LIGHT_HSL_SERVER_API Server API + * @brief Functions declaration + * @{ + */ +/** + * @brief register light hsl server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light hsl server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_hsl_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light hsl setup server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light hsl setup server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_hsl_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light hsl hue server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light hsl hue server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_hsl_hue_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light hsl saturation server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light hsl saturation server model context + * @retval true: register success + * @retval false: register failed + */ +bool light_hsl_saturation_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish light hsl status + * @param[in] pmodel_info: pointer to light hsl server model context + * @param[in] lightness: light lightness need to publish + * @param[in] hue: light hue need to publish + * @param[in] saturation: light saturation need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_hsl_publish(const mesh_model_info_p pmodel_info, uint16_t lightness, + uint16_t hue, uint16_t saturation); + +/** + * @brief publish light hsl hue status + * @param[in] pmodel_info: pointer to light hsl hue server model context + * @param[in] hue: light hue need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_hsl_hue_publish(const mesh_model_info_p pmodel_info, uint16_t hue); + +/** + * @brief publish light hsl saturation status + * @param[in] pmodel_info: pointer to light hsl saturation server model context + * @param[in] saturation: light saturation need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_hsl_saturation_publish(const mesh_model_info_p pmodel_info, + uint16_t saturation); + +/** + * @brief convert light hue value to generic level value + * @param[in] hue: light hue value + * @return generic level value + */ +int16_t light_hue_to_generic_level(uint16_t hue); + +/** + * @brief convert generic level value to light hue value + * @param[in] level: generic level value + * @return light hue value + */ +uint16_t generic_level_to_light_hue(int16_t level); + +/** + * @brief convert light saturation value to generic level value + * @param[in] saturation: light saturation value + * @return generic level value + */ +int16_t light_saturation_to_generic_level(uint16_t saturation); + +/** + * @brief convert generic level value to light saturation value + * @param[in] level: generic level value + * @return light saturation value + */ +uint16_t generic_level_to_light_saturation(int16_t level); + +/** @} */ + +/** + * @defgroup LIGHT_HSL_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register light hsl client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light hsl client model context + * @retval true: register success + * @retval false: register failed + */ +bool light_hsl_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get light hsl value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_hsl_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light hsl value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired lightness + * @param[in] hue: desired hue + * @param[in] saturation: desired saturation + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_hsl_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, uint8_t tid, + bool optional, generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light hsl target value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_hsl_target_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get light hsl hue value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_hsl_hue_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light hsl hue value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] hue: desired hue + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_hsl_hue_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t hue, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light hsl saturation value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_hsl_saturation_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light hsl saturation value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] saturation: desired saturation + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_hsl_saturation_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t saturation, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light hsl default value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_hsl_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set default light hsl value + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired default lightness value + * @param[in] hue: desired default hue value + * @param[in] saturation: desired default saturation value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_hsl_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, bool ack); + +/** + * @brief get light hsl range + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_hsl_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light hsl range + * @param[in] pmodel_info: pointer to light hsl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] hue_range_min: desired light hue minimum value + * @param[in] hue_range_max: desired light hue maximum value + * @param[in] saturation_range_min: desired light saturation minimum value + * @param[in] saturation_range_max: desired light saturation maximum value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_hsl_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t hue_range_min, uint16_t hue_range_max, + uint16_t saturation_range_min, uint16_t saturation_range_max, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_HSL_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_client.c new file mode 100644 index 00000000..833093e8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_client.c @@ -0,0 +1,354 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_hsl_client.c +* @brief Source file for light hsl client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_hsl.h" + +static mesh_msg_send_cause_t light_hsl_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_hsl_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_hsl_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_GET); + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, uint8_t tid, + bool optional, generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_hsl_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_hsl_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_hsl_set_t, trans_time); + } + msg.lightness = lightness; + msg.hue = hue; + msg.saturation = saturation; + msg.tid = tid; + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_hsl_target_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_hsl_target_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_TARGET_GET); + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_hue_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_hsl_hue_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_HUE_GET); + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_hue_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t hue, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_hsl_hue_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_HUE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_HUE_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_hsl_hue_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_hsl_hue_set_t, trans_time); + } + msg.hue = hue; + msg.tid = tid; + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_hsl_saturation_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_hsl_saturation_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_SATURATION_GET); + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_saturation_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t saturation, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_hsl_saturation_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_SATURATION_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_SATURATION_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_hsl_saturation_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_hsl_saturation_set_t, trans_time); + } + msg.saturation = saturation; + msg.tid = tid; + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_hsl_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_hsl_default_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_DEFAULT_GET); + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, bool ack) +{ + light_hsl_default_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_DEFAULT_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_DEFAULT_SET_UNACK); + } + msg.lightness = lightness; + msg.hue = hue; + msg.saturation = saturation; + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_hsl_range_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_RANGE_GET); + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_hsl_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t hue_range_min, uint16_t hue_range_max, + uint16_t saturation_range_min, uint16_t saturation_range_max, bool ack) +{ + light_hsl_range_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_RANGE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_RANGE_SET_UNACK); + } + msg.hue_range_min = hue_range_min; + msg.hue_range_max = hue_range_max; + msg.saturation_range_min = saturation_range_min; + msg.saturation_range_max = saturation_range_max; + return light_hsl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool light_hsl_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_HSL_STAT: + { + light_hsl_stat_t *pmsg = (light_hsl_stat_t *)pbuffer; + light_hsl_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.lightness = pmsg->lightness; + status_data.hue = pmsg->hue; + status_data.saturation = pmsg->saturation; + if (pmesh_msg->msg_len == sizeof(light_hsl_stat_t)) + { + status_data.optional = TRUE; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_HSL_TARGET_STAT: + { + light_hsl_target_stat_t *pmsg = (light_hsl_target_stat_t *)pbuffer; + light_hsl_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.lightness = pmsg->lightness; + status_data.hue = pmsg->hue; + status_data.saturation = pmsg->saturation; + if (pmesh_msg->msg_len == sizeof(light_hsl_target_stat_t)) + { + status_data.optional = TRUE; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_CLIENT_STATUS_TARGET, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_HSL_HUE_STAT: + { + light_hsl_hue_stat_t *pmsg = (light_hsl_hue_stat_t *)pbuffer; + light_hsl_client_status_hue_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_hue = pmsg->present_hue; + if (pmesh_msg->msg_len == sizeof(light_hsl_hue_stat_t)) + { + status_data.optional = TRUE; + status_data.target_hue = pmsg->target_hue; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_CLIENT_STATUS_HUE, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_HSL_SATURATION_STAT: + { + light_hsl_saturation_stat_t *pmsg = (light_hsl_saturation_stat_t *)pbuffer; + light_hsl_client_status_saturation_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_saturation = pmsg->present_saturation; + if (pmesh_msg->msg_len == sizeof(light_hsl_saturation_stat_t)) + { + status_data.optional = TRUE; + status_data.target_saturation = pmsg->target_saturation; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_CLIENT_STATUS_SATURATION, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_HSL_DEFAULT_STAT: + if (pmesh_msg->msg_len == sizeof(light_hsl_default_stat_t)) + { + light_hsl_default_stat_t *pmsg = (light_hsl_default_stat_t *)pbuffer; + light_hsl_client_status_default_t default_data = {pmesh_msg->src, pmsg->lightness, pmsg->hue, pmsg->saturation}; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_CLIENT_STATUS_DEFAULT, + &default_data); + } + } + break; + case MESH_MSG_LIGHT_HSL_RANGE_STAT: + if (pmesh_msg->msg_len == sizeof(light_hsl_range_stat_t)) + { + light_hsl_range_stat_t *pmsg = (light_hsl_range_stat_t *)pbuffer; + light_hsl_client_status_range_t range_data = {pmesh_msg->src, pmsg->stat, pmsg->hue_range_min, pmsg->hue_range_max, pmsg->saturation_range_min, pmsg->saturation_range_max}; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + LIGHT_HSL_CLIENT_STATUS_RANGE, + &range_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool light_hsl_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_HSL_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = light_hsl_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_hsl_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_hue_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_hue_server.c new file mode 100644 index 00000000..1dda944f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_hue_server.c @@ -0,0 +1,478 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_hsl_hue_server.c +* @brief Source file for light hsl hue server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_hsl.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +extern mesh_msg_send_cause_t light_hsl_hue_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_hue, bool optional, uint16_t target_hue, + generic_transition_time_t remaining_time, uint32_t delay_time); + + +typedef struct +{ + uint8_t tid; + uint16_t target_hue; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_hsl_hue_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_hsl_hue_process_result_t; + + +int16_t light_hue_to_generic_level(uint16_t hue) +{ + return hue - 32768; +} + +uint16_t generic_level_to_light_hue(int16_t level) +{ + return level + 32768; +} + +static mesh_msg_send_cause_t light_hsl_hue_server_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_hsl_hue_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_hue, bool optional, uint16_t target_hue, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + light_hsl_hue_stat_t msg; + uint32_t len; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_HUE_STAT); + msg.present_hue = present_hue; + if (optional) + { + len = sizeof(light_hsl_hue_stat_t); + msg.target_hue = target_hue; + msg.remaining_time = remaining_time; + } + else + { + len = MEMBER_OFFSET(light_hsl_hue_stat_t, target_hue); + } + return light_hsl_hue_server_send(pmodel_info, dst, (uint8_t *)&msg, len, app_key_index, delay_time); +} + +mesh_msg_send_cause_t light_hsl_hue_delay_publish(const mesh_model_info_p pmodel_info, uint16_t hue, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = light_hsl_hue_stat(pmodel_info, 0, 0, hue, FALSE, 0, trans_time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_hsl_hue_publish(const mesh_model_info_p pmodel_info, uint16_t hue) +{ + return light_hsl_hue_delay_publish(pmodel_info, hue, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_hsl_hue_state_change_publish(const mesh_model_info_p pmodel_info, uint16_t hue, + light_hsl_hue_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_hsl_hue_publish(pmodel_info, hue); + } +} +#endif + +static uint16_t get_present_hue(const mesh_model_info_p pmodel_info) +{ + light_hsl_server_get_hue_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_HUE, &get_data); + } + + return get_data.hue; +} + +static int32_t light_hsl_hue_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = MODEL_SUCCESS; + light_hsl_server_set_hue_t trans_set_data; + light_hsl_hue_info_t *phue_info = pmodel_info->pargs; + if (NULL == phue_info) + { + return 0; + } + trans_set_data.hue = phue_info->target_hue; + trans_set_data.total_time = total_time; + trans_set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET_HUE, &trans_set_data); + } + + if (0 == remaining_time.num_steps) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + light_hsl_hue_delay_publish(pmodel_info, get_present_hue(pmodel_info), phue_info->delay_pub_time); +#else + light_hsl_hue_publish(pmodel_info, get_present_hue(pmodel_info)); +#endif + } + + return ret; +} + +static uint16_t light_hsl_hue_process(const mesh_model_info_p pmodel_info, + uint16_t target_hue, + generic_transition_time_t trans_time, + light_hsl_hue_process_result_t *presult) +{ + uint16_t hue_before_set = {0}; + uint16_t hue_after_set = {0}; + + /* get hue before set */ + hue_before_set = get_present_hue(pmodel_info); + hue_after_set = hue_before_set; + + int32_t ret = MODEL_SUCCESS; + light_hsl_server_set_hue_t trans_set_data; + trans_set_data.hue = target_hue; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET_HUE, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL_HUE, trans_time, + light_hsl_hue_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET_HUE, &trans_set_data); + } + } +#endif + } + else + { + /* get hue after set */ + hue_after_set = get_present_hue(pmodel_info); + } + + if (hue_after_set != hue_before_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return hue_after_set; +} + +static int32_t light_hsl_hue_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LIGHT_HSL_HUE: + { + light_hsl_hue_info_t *phue_info = pmodel_info->pargs; + if (NULL == phue_info) + { + return 0; + } + phue_info->delay_time = 0; + light_hsl_hue_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + uint16_t present_hue = light_hsl_hue_process(pmodel_info, phue_info->target_hue, + phue_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_hsl_hue_delay_publish(pmodel_info, present_hue, phue_info->delay_pub_time); + } + } +#else + light_hsl_hue_state_change_publish(pmodel_info, present_hue, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_hsl_hue_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_HSL_HUE_GET: + if (pmesh_msg->msg_len == sizeof(light_hsl_hue_get_t)) + { + light_hsl_hue_info_t *phue_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (phue_info->delay_time > 0) + { + remaining_time = phue_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_HSL_HUE); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_hue_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_hue(pmodel_info), + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + phue_info->target_hue, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_HSL_HUE_SET: + case MESH_MSG_LIGHT_HSL_HUE_SET_UNACK: + { + light_hsl_hue_set_t *pmsg = (light_hsl_hue_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_hsl_hue_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_DEFAULT_TRANSITION_TIME, &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_hsl_hue_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_hsl_server_get_range_t range = {0, 0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_RANGE, &range); + } + + light_hsl_hue_info_t *phue_info = pmodel_info->pargs; + if ((0 != range.hue_range_min) && (0 != range.hue_range_max)) + { + phue_info->target_hue = CLAMP(pmsg->hue, range.hue_range_min, range.hue_range_max); + } + else + { + phue_info->target_hue = pmsg->hue; + } + phue_info->tid = pmsg->tid; + phue_info->trans_time = trans_time; + phue_info->delay_time = delay_time; + + uint16_t present_hue; + light_hsl_hue_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_hue = get_present_hue(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_HSL_HUE, delay_time, + light_hsl_hue_delay_execution); + } + else + { + present_hue = light_hsl_hue_process(pmodel_info, phue_info->target_hue, trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_HSL_HUE_SET) + { + light_hsl_hue_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_hue, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + phue_info->target_hue, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_HSL_HUE_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_hsl_hue_delay_publish(pmodel_info, present_hue, delay_pub_time); + } + } + else + { + phue_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, FALSE, + ack); + } +#else + light_hsl_hue_state_change_publish(pmodel_info, present_hue, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_hue_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + generic_transition_time_t trans_time = {0, 0}; + light_hsl_hue_stat(pmodel_info, 0, 0, get_present_hue(pmodel_info), FALSE, 0, trans_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_hsl_hue_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_hsl_hue_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_HSL_HUE); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL_HUE); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_hsl_hue_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_HSL_HUE_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_hsl_hue_info_t *phue_info = plt_malloc(sizeof(light_hsl_hue_info_t), + RAM_TYPE_DATA_ON); + if (NULL == phue_info) + { + printe("light_hsl_hue_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(phue_info, 0, sizeof(light_hsl_hue_info_t)); + pmodel_info->pargs = phue_info; + + pmodel_info->model_receive = light_hsl_hue_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_hsl_hue_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_hsl_hue_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_hue_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_saturation_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_saturation_server.c new file mode 100644 index 00000000..3e7280c6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_saturation_server.c @@ -0,0 +1,490 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_hsl_saturation_server.c +* @brief Source file for light hsl saturation server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "light_hsl.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t light_hsl_saturation_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_saturation, bool optional, uint16_t target_saturation, + generic_transition_time_t remaining_time, uint32_t delay_time); + +typedef struct +{ + uint8_t tid; + uint16_t target_saturation; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_hsl_saturation_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_hsl_saturation_process_result_t; + + +int16_t light_saturation_to_generic_level(uint16_t saturation) +{ + return saturation - 32768; +} + +uint16_t generic_level_to_light_saturation(int16_t level) +{ + return level + 32768; +} + +static mesh_msg_send_cause_t light_hsl_saturation_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_hsl_saturation_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_saturation, bool optional, uint16_t target_saturation, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + light_hsl_saturation_stat_t msg; + uint32_t len; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_SATURATION_STAT); + msg.present_saturation = present_saturation; + if (optional) + { + len = sizeof(light_hsl_saturation_stat_t); + msg.target_saturation = target_saturation; + msg.remaining_time = remaining_time; + } + else + { + len = MEMBER_OFFSET(light_hsl_saturation_stat_t, target_saturation); + } + return light_hsl_saturation_server_send(pmodel_info, dst, (uint8_t *)&msg, len, app_key_index, + delay_time); +} + +mesh_msg_send_cause_t light_hsl_saturation_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t saturation, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = light_hsl_saturation_stat(pmodel_info, 0, 0, saturation, FALSE, 0, trans_time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_hsl_saturation_publish(const mesh_model_info_p pmodel_info, + uint16_t saturation) +{ + return light_hsl_saturation_delay_publish(pmodel_info, saturation, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_hsl_saturation_state_change_publish(const mesh_model_info_p pmodel_info, + uint16_t saturation, light_hsl_saturation_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_hsl_saturation_publish(pmodel_info, saturation); + } +} +#endif + +static uint16_t get_present_saturation(const mesh_model_info_p pmodel_info) +{ + light_hsl_server_get_saturation_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_SATURATION, &get_data); + } + + return get_data.saturation; +} + +static int32_t light_hsl_saturation_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = 0; + light_hsl_server_set_saturation_t trans_set_data; + light_hsl_saturation_info_t *psaturation_info = pmodel_info->pargs; + if (NULL == psaturation_info) + { + return 0; + } + trans_set_data.saturation = psaturation_info->target_saturation; + trans_set_data.total_time = total_time; + trans_set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET_SATURATION, + &trans_set_data); + } + + if (0 == remaining_time.num_steps) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + light_hsl_saturation_delay_publish(pmodel_info, get_present_saturation(pmodel_info), + psaturation_info->delay_pub_time); +#else + light_hsl_saturation_publish(pmodel_info, get_present_saturation(pmodel_info)); +#endif + } + + return ret; +} + +static uint16_t light_hsl_saturation_process(const mesh_model_info_p pmodel_info, + uint16_t target_saturation, + generic_transition_time_t trans_time, + light_hsl_saturation_process_result_t *presult) +{ + uint16_t saturation_before_set = 0; + uint16_t saturation_after_set = 0; + + /* get saturation before set */ + saturation_before_set = get_present_saturation(pmodel_info); + saturation_after_set = saturation_before_set; + + int32_t ret = MODEL_SUCCESS; + light_hsl_server_set_saturation_t trans_set_data; + trans_set_data.saturation = target_saturation; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET_SATURATION, + &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { +#if MODEL_ENABLE_PUBLISH_ALL_TIME + if (NULL != presult) + { + presult->use_transition = TRUE; + } +#endif + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL_SATURATION, + trans_time, + light_hsl_saturation_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET_SATURATION, &trans_set_data); + } + } +#endif + } + else + { + /* get saturation after set */ + saturation_after_set = get_present_saturation(pmodel_info); + } + + if (saturation_after_set != saturation_before_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return saturation_after_set; +} + +static int32_t light_hsl_saturation_delay_execution(mesh_model_info_t *pmodel_info, + uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LIGHT_HSL_SATURATION: + { + light_hsl_saturation_info_t *psaturation_info = pmodel_info->pargs; + if (NULL == psaturation_info) + { + return 0; + } + psaturation_info->delay_time = 0; + light_hsl_saturation_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + uint16_t present_saturation = light_hsl_saturation_process(pmodel_info, + psaturation_info->target_saturation, + psaturation_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_hsl_saturation_delay_publish(pmodel_info, present_saturation, + psaturation_info->delay_pub_time); + } + } +#else + light_hsl_saturation_state_change_publish(pmodel_info, present_saturation, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_hsl_saturation_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_HSL_SATURATION_GET: + if (pmesh_msg->msg_len == sizeof(light_hsl_saturation_get_t)) + { + light_hsl_saturation_info_t *psaturation_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (psaturation_info->delay_time > 0) + { + remaining_time = psaturation_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_HSL_SATURATION); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_saturation_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_saturation(pmodel_info), + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + psaturation_info->target_saturation, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_HSL_SATURATION_SET: + case MESH_MSG_LIGHT_HSL_SATURATION_SET_UNACK: + { + light_hsl_saturation_set_t *pmsg = (light_hsl_saturation_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_hsl_saturation_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_DEFAULT_TRANSITION_TIME, &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_hsl_saturation_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_hsl_server_get_range_t range = {0, 0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_RANGE, &range); + } + + light_hsl_saturation_info_t *psaturation_info = pmodel_info->pargs; + if ((0 != range.saturation_range_min) && (0 != range.saturation_range_max)) + { + psaturation_info->target_saturation = CLAMP(pmsg->saturation, range.saturation_range_min, + range.saturation_range_max); + } + else + { + psaturation_info->target_saturation = pmsg->saturation; + } + psaturation_info->tid = pmsg->tid; + psaturation_info->trans_time = trans_time; + psaturation_info->delay_time = delay_time; + + uint16_t present_saturation; + light_hsl_saturation_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_saturation = get_present_saturation(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_HSL_SATURATION, delay_time, + light_hsl_saturation_delay_execution); + } + else + { + present_saturation = light_hsl_saturation_process(pmodel_info, + psaturation_info->target_saturation, trans_time, + &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_HSL_SATURATION_SET) + { + light_hsl_saturation_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_saturation, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + psaturation_info->target_saturation, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_HSL_SATURATION_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_hsl_saturation_delay_publish(pmodel_info, present_saturation, delay_pub_time); + } + } + else + { + psaturation_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + light_hsl_saturation_state_change_publish(pmodel_info, present_saturation, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_saturation_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + generic_transition_time_t trans_time = {0, 0}; + light_hsl_saturation_stat(pmodel_info, 0, 0, get_present_saturation(pmodel_info), FALSE, 0, + trans_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_hsl_saturation_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_hsl_saturation_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_HSL_SATURATION); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL_SATURATION); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_hsl_saturation_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_HSL_SATURATION_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_hsl_saturation_info_t *psaturation_info = plt_malloc(sizeof(light_hsl_saturation_info_t), + RAM_TYPE_DATA_ON); + if (NULL == psaturation_info) + { + printe("light_hsl_saturation_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(psaturation_info, 0, sizeof(light_hsl_saturation_info_t)); + pmodel_info->pargs = psaturation_info; + + pmodel_info->model_receive = light_hsl_saturation_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_hsl_saturation_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_hsl_saturation_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_saturation_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_server.c new file mode 100644 index 00000000..1279d7ed --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_server.c @@ -0,0 +1,619 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_hsl_server.c +* @brief Source file for light hsl server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "light_hsl.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +typedef struct +{ + uint8_t tid; + uint16_t target_lightness; + uint16_t target_hue; + uint16_t target_saturation; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_hsl_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_hsl_process_result_t; + + +static mesh_msg_send_cause_t light_hsl_server_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t light_hsl_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, bool optional, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + light_hsl_stat_t msg; + uint32_t len; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_STAT); + msg.lightness = lightness; + msg.hue = hue; + msg.saturation = saturation; + if (optional) + { + len = sizeof(light_hsl_stat_t); + msg.remaining_time = remaining_time; + } + else + { + len = MEMBER_OFFSET(light_hsl_stat_t, remaining_time); + } + return light_hsl_server_send(pmodel_info, dst, (uint8_t *)&msg, len, app_key_index, delay_time); +} + +mesh_msg_send_cause_t light_hsl_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness, + uint16_t hue, uint16_t saturation, uint32_t delay_time) +{ + /* avoid gcc compile warning */ + (void)delay_time; + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = light_hsl_stat(pmodel_info, 0, 0, lightness, hue, saturation, FALSE, trans_time, 0); + } + + return ret; +} + +mesh_msg_send_cause_t light_hsl_publish(const mesh_model_info_p pmodel_info, uint16_t lightness, + uint16_t hue, uint16_t saturation) +{ + return light_hsl_delay_publish(pmodel_info, lightness, hue, saturation, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_hsl_state_change_publish(const mesh_model_info_p pmodel_info, uint16_t lightness, + uint16_t hue, uint16_t saturation, light_hsl_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_hsl_publish(pmodel_info, lightness, hue, saturation); + } +} +#endif + +static mesh_msg_send_cause_t light_hsl_target_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, bool optional, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + light_hsl_target_stat_t msg; + uint32_t len; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_TARGET_STAT); + msg.lightness = lightness; + msg.hue = hue; + msg.saturation = saturation; + if (optional) + { + len = sizeof(light_hsl_target_stat_t); + msg.remaining_time = remaining_time; + } + else + { + len = MEMBER_OFFSET(light_hsl_target_stat_t, remaining_time); + } + return light_hsl_server_send(pmodel_info, dst, (uint8_t *)&msg, len, app_key_index, delay_time); +} + +mesh_msg_send_cause_t light_hsl_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, + uint32_t delay_time) +{ + light_hsl_default_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_DEFAULT_STAT); + msg.lightness = lightness; + msg.hue = hue; + msg.saturation = saturation; + return light_hsl_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t light_hsl_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t hue_range_min, uint16_t hue_range_max, + uint16_t saturation_range_min, uint16_t saturation_range_max, uint32_t delay_time) +{ + /* avoid gcc compile warning */ + (void)stat; + light_hsl_range_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_HSL_RANGE_STAT); + msg.hue_range_min = hue_range_min; + msg.hue_range_max = hue_range_max; + msg.saturation_range_min = saturation_range_min; + msg.saturation_range_max = saturation_range_max; + return light_hsl_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +static light_hsl_server_get_t get_present_hsl(const mesh_model_info_p pmodel_info) +{ + light_hsl_server_get_t get_data = {0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET, &get_data); + } + + return get_data; +} + +static int32_t light_hsl_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = 0; + light_hsl_server_set_t trans_set_data; + light_hsl_info_t *phsl_info = pmodel_info->pargs; + if (NULL == phsl_info) + { + return 0; + } + trans_set_data.lightness = phsl_info->target_lightness; + trans_set_data.hue = phsl_info->target_hue; + trans_set_data.saturation = phsl_info->target_saturation; + trans_set_data.total_time = total_time; + trans_set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET, &trans_set_data); + } + + if (0 == remaining_time.num_steps) + { + light_hsl_server_get_t get_data = {0, 0, 0}; + get_data = get_present_hsl(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + light_hsl_delay_publish(pmodel_info, get_data.lightness, get_data.hue, get_data.saturation, + phsl_info->delay_pub_time); +#else + light_hsl_publish(pmodel_info, get_data.lightness, get_data.hue, get_data.saturation); +#endif + } + + return ret; +} + +static light_hsl_server_get_t light_hsl_process(const mesh_model_info_p pmodel_info, + uint16_t target_lightness, uint16_t target_hue, + uint16_t target_saturation, + generic_transition_time_t trans_time, + light_hsl_process_result_t *presult) +{ + light_hsl_server_get_t hsl_before_set = {0}; + light_hsl_server_get_t hsl_after_set = {0}; + + /* get hsl before set */ + hsl_before_set = get_present_hsl(pmodel_info); + hsl_after_set = hsl_before_set; + + int32_t ret = MODEL_SUCCESS; + light_hsl_server_set_t trans_set_data; + trans_set_data.lightness = target_lightness; + trans_set_data.hue = target_hue; + trans_set_data.saturation = target_saturation; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL, trans_time, + light_hsl_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_SET, &trans_set_data); + } + } +#endif + } + else + { + /* get hsl after set */ + hsl_after_set = get_present_hsl(pmodel_info); + } + + if ((hsl_after_set.lightness != hsl_before_set.lightness) || + (hsl_after_set.hue != hsl_before_set.hue) || + (hsl_after_set.saturation != hsl_before_set.saturation)) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return hsl_after_set; +} + +static int32_t light_hsl_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LIGHT_HSL: + { + light_hsl_info_t *phsl_info = pmodel_info->pargs; + if (NULL == phsl_info) + { + return 0; + } + phsl_info->delay_time = 0; + light_hsl_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + light_hsl_server_get_t present_hsl = light_hsl_process(pmodel_info, phsl_info->target_lightness, + phsl_info->target_hue, + phsl_info->target_saturation, phsl_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_hsl_delay_publish(pmodel_info, present_hsl.lightness, present_hsl.hue, present_hsl.saturation, + phsl_info->delay_pub_time); + } + } +#else + light_hsl_state_change_publish(pmodel_info, present_hsl.lightness, present_hsl.hue, + present_hsl.saturation, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_hsl_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_HSL_GET: + if (pmesh_msg->msg_len == sizeof(light_hsl_get_t)) + { + light_hsl_info_t *phsl_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (phsl_info->delay_time > 0) + { + remaining_time = phsl_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_HSL); + } + + light_hsl_server_get_t get_data = get_present_hsl(pmodel_info); + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_data.lightness, get_data.hue, + get_data.saturation, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_HSL_SET: + case MESH_MSG_LIGHT_HSL_SET_UNACK: + { + light_hsl_set_t *pmsg = (light_hsl_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_hsl_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_DEFAULT_TRANSITION_TIME, &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_hsl_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_hsl_server_get_range_t range = {0, 0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_RANGE, &range); + } + + light_hsl_info_t *phsl_info = pmodel_info->pargs; + phsl_info->target_lightness = pmsg->lightness; + if ((0 != range.hue_range_min) && (0 != range.hue_range_max)) + { + phsl_info->target_hue = CLAMP(pmsg->hue, range.hue_range_min, range.hue_range_max); + } + else + { + phsl_info->target_hue = pmsg->hue; + } + + if ((0 != range.saturation_range_min) && (0 != range.saturation_range_max)) + { + phsl_info->target_saturation = CLAMP(pmsg->saturation, range.saturation_range_min, + range.saturation_range_max); + } + else + { + phsl_info->target_saturation = pmsg->saturation; + } + phsl_info->tid = pmsg->tid; + phsl_info->trans_time = trans_time; + phsl_info->delay_time = delay_time; + + light_hsl_server_get_t present_hsl; + light_hsl_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_hsl = get_present_hsl(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_HSL, delay_time, + light_hsl_delay_execution); + } + else + { + present_hsl = light_hsl_process(pmodel_info, phsl_info->target_lightness, + phsl_info->target_hue, + phsl_info->target_saturation, trans_time, + &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_HSL_SET) + { + light_hsl_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_hsl.lightness, present_hsl.hue, + present_hsl.saturation, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_HSL_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_hsl_delay_publish(pmodel_info, present_hsl.lightness, present_hsl.hue, present_hsl.saturation, + delay_pub_time); + } + } + else + { + phsl_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, FALSE, + ack); + } +#else + light_hsl_state_change_publish(pmodel_info, present_hsl.lightness, present_hsl.hue, + present_hsl.saturation, result); +#endif + } + } + break; + case MESH_MSG_LIGHT_HSL_TARGET_GET: + if (pmesh_msg->msg_len == sizeof(light_hsl_target_get_t)) + { + light_hsl_info_t *phsl_info = pmesh_msg->pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (phsl_info->delay_time > 0) + { + remaining_time = phsl_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_target_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + phsl_info->target_lightness, phsl_info->target_hue, + phsl_info->target_saturation, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_HSL_DEFAULT_GET: + if (pmesh_msg->msg_len == sizeof(light_hsl_default_get_t)) + { + light_hsl_server_get_default_t get_default = {0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_DEFAULT, + &get_default); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_default_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_default.lightness, get_default.hue, get_default.saturation, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_HSL_RANGE_GET: + if (pmesh_msg->msg_len == sizeof(light_hsl_range_get_t)) + { + light_hsl_server_get_range_t get_range = {0, 0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_HSL_SERVER_GET_RANGE, + &get_range); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_range_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + GENERIC_STAT_SUCCESS, + get_range.hue_range_min, get_range.hue_range_max, + get_range.saturation_range_min, get_range.saturation_range_max, + delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_hsl_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + light_hsl_server_get_t get_data = get_present_hsl(pmodel_info); + generic_transition_time_t trans_time = {0, 0}; + light_hsl_stat(pmodel_info, 0, 0, get_data.lightness, get_data.hue, get_data.saturation, FALSE, + trans_time, 0); + + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_hsl_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_hsl_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_HSL); + /* stop transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_HSL); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_hsl_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_HSL_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_hsl_info_t *phsl_info = plt_malloc(sizeof(light_hsl_info_t), + RAM_TYPE_DATA_ON); + if (NULL == phsl_info) + { + printe("light_hsl_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(phsl_info, 0, sizeof(light_hsl_info_t)); + pmodel_info->pargs = phsl_info; + + pmodel_info->model_receive = light_hsl_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_hsl_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_hsl_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_hsl_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_setup_server.c new file mode 100644 index 00000000..473efe82 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_setup_server.c @@ -0,0 +1,159 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_hsl_setup_server.c +* @brief Source file for light hsl setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-1 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_hsl.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t light_hsl_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint16_t hue, uint16_t saturation, + uint32_t delay_time); +extern mesh_msg_send_cause_t light_hsl_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t hue_range_min, uint16_t hue_range_max, + uint16_t saturation_range_min, uint16_t saturation_range_max, uint32_t delay_time); + +#if 0 +typedef struct +{ + uint8_t tid; + uint16_t target_lightness; + uint16_t target_hue; + uint16_t target_saturation; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_hsl_info_t; +#endif + +static bool light_hsl_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_HSL_DEFAULT_SET: + case MESH_MSG_LIGHT_HSL_DEFAULT_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_hsl_default_set_t)) + { + light_hsl_default_set_t *pmsg = (light_hsl_default_set_t *)pbuffer; + light_hsl_server_set_default_t set_default = {pmsg->lightness, pmsg->hue, pmsg->saturation}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_SERVER_SET_DEFAULT, + &set_default); + } + if (MESH_MSG_LIGHT_HSL_DEFAULT_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_default_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->lightness, + pmsg->hue, pmsg->saturation, delay_rsp_time); + } + } + break; + case MESH_MSG_LIGHT_HSL_RANGE_SET: + case MESH_MSG_LIGHT_HSL_RANGE_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_hsl_range_set_t)) + { + light_hsl_range_set_t *pmsg = (light_hsl_range_set_t *)pbuffer; + if ((pmsg->hue_range_min <= pmsg->hue_range_max) && + (pmsg->saturation_range_min <= pmsg->saturation_range_max)) + { + light_hsl_server_set_range_t set_range = {pmsg->hue_range_min, pmsg->hue_range_max, + pmsg->saturation_range_min, + pmsg->saturation_range_max + }; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_HSL_SERVER_SET_RANGE, + &set_range); + } + if (MESH_MSG_LIGHT_HSL_RANGE_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_hsl_range_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + GENERIC_STAT_SUCCESS, + pmsg->hue_range_min, pmsg->hue_range_max, + pmsg->saturation_range_min, pmsg->saturation_range_max, delay_rsp_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_hsl_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_hsl_setup_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_hsl_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_HSL_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + light_hsl_info_t *phsl_info = plt_malloc(sizeof(light_hsl_info_t), + RAM_TYPE_DATA_ON); + if (NULL == phsl_info) + { + printe("light_hsl_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(phsl_info, 0, sizeof(light_hsl_info_t)); +#endif + pmodel_info->model_receive = light_hsl_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_hsl_setup_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_hsl_setup_server_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc.h new file mode 100644 index 00000000..abb4dfca --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc.h @@ -0,0 +1,459 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lc.h +* @brief Head file for light lc models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-17 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _LIGHT_LC_H_ +#define _LIGHT_LC_H_ + +#include "mesh_api.h" +#include "generic_on_off.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_LC + * @{ + */ + +/** + * @defgroup LIGHT_LC_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_LIGHT_LC_MODE_GET 0x8291 +#define MESH_MSG_LIGHT_LC_MODE_SET 0x8292 +#define MESH_MSG_LIGHT_LC_MODE_SET_UNACK 0x8293 +#define MESH_MSG_LIGHT_LC_MODE_STATUS 0x8294 +#define MESH_MSG_LIGHT_LC_OM_GET 0x8295 +#define MESH_MSG_LIGHT_LC_OM_SET 0x8296 +#define MESH_MSG_LIGHT_LC_OM_SET_UNACK 0x8297 +#define MESH_MSG_LIGHT_LC_OM_STATUS 0x8298 +#define MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_GET 0x8299 +#define MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET 0x829A +#define MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET_UNACK 0x829B +#define MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_STATUS 0x829C +#define MESH_MSG_LIGHT_LC_PROPERTY_GET 0x829D +#define MESH_MSG_LIGHT_LC_PROPERTY_SET 0x62 +#define MESH_MSG_LIGHT_LC_PROPERTY_SET_UNACK 0x63 +#define MESH_MSG_LIGHT_LC_PROPERTY_STATUS 0x64 +/** @} */ + +/** + * @defgroup LIGHT_LC_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_LIGHT_LC_SERVER 0x130FFFFF +#define MESH_MODEL_LIGHT_LC_SETUP_SERVER 0x1310FFFF +#define MESH_MODEL_LIGHT_LC_CLIENT 0x1311FFFF +/** @} */ + +/** + * @defgroup LIGHT_LC_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint32_t time_fade; + uint32_t time_fade_on; + uint32_t time_fade_standby_auto; + uint32_t time_fade_standby_manual; + uint32_t time_occupancy_delay; + uint32_t time_prolong; + uint32_t time_run_on; +} light_lc_time_t; + +#define LIGHT_LC_MODE_TURNED_OFF 0 +#define LIGHT_LC_MODE_TURNED_ON 1 +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_MODE_GET)]; +} _PACKED4_ light_lc_mode_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_MODE_SET)]; + uint8_t mode; +} _PACKED4_ light_lc_mode_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_MODE_STATUS)]; + uint8_t mode; +} _PACKED4_ light_lc_mode_status_t; + +#define LIGHT_LC_OM_OCCUPANCY_NOT_FROM_STANDBY 0 +#define LIGHT_LC_OM_OCCUPANCY_FROM_STANDBY 1 +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_OM_GET)]; +} _PACKED4_ light_lc_om_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_MODE_SET)]; + uint8_t mode; +} _PACKED4_ light_lc_om_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_MODE_STATUS)]; + uint8_t mode; +} _PACKED4_ light_lc_om_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_GET)]; +} _PACKED4_ light_lc_light_on_off_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET)]; + generic_on_off_t light_on_off; + uint8_t tid; + generic_transition_time_t trans_time; + uint8_t delay; +} _PACKED4_ light_lc_light_on_off_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_STATUS)]; + generic_on_off_t present_light_on_off; + generic_on_off_t target_light_on_off; + generic_transition_time_t trans_time; +} _PACKED4_ light_lc_light_on_off_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_PROPERTY_GET)]; + uint16_t property_id; +} _PACKED4_ light_lc_property_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_PROPERTY_SET)]; + uint16_t property_id; + uint8_t property_value[0]; +} _PACKED4_ light_lc_property_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LC_PROPERTY_STATUS)]; + uint16_t property_id; + uint8_t property_value[0]; +} _PACKED4_ light_lc_property_status_t; +/** @} */ + +/** + * @defgroup LIGHT_LC_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_LIGHT_LC 0 +#define DELAY_EXECUTION_TYPE_LIGHT_LC 0 +/** @} */ + + +/** + * @defgroup LIGHT_LC_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_LC_SERVER_GET_MODE 0 //!< @ref light_lc_server_get_mode_t +#define LIGHT_LC_SERVER_GET_OM 1 //!< @ref light_lc_server_get_om_t +#define LIGHT_LC_SERVER_GET_LIGHT_ON_OFF 2 //!< @ref light_lc_server_get_light_on_off_t +#define LIGHT_LC_SERVER_GET_PROPERTY 3 //!< @ref light_lc_server_get_property_t +#define LIGHT_LC_SERVER_GET_DEFAULT_TRANSITION_TIME 4 //!< @ref light_lc_server_get_default_transition_time_t +#define LIGHT_LC_SERVER_GET_SM_TRANSITION_TIME 5 //!< @ref light_lc_server_get_sm_transition_time_t +#define LIGHT_LC_SERVER_SET_MODE 6 //!< @ref light_lc_server_set_mode_t +#define LIGHT_LC_SERVER_SET_OM 7 //!< @ref light_lc_server_set_om_t +#define LIGHT_LC_SERVER_SET_LIGHT_ON_OFF 8 //!< @ref light_lc_server_set_light_on_off_t +#define LIGHT_LC_SERVER_SET_PROPERTY 9 //!< @ref light_lc_server_set_property_t + + +typedef struct +{ + uint8_t mode; +} light_lc_server_get_mode_t; + +typedef struct +{ + uint8_t mode; +} light_lc_server_get_om_t; + +typedef struct +{ + generic_on_off_t on_off; +} light_lc_server_get_light_on_off_t; + +typedef struct +{ + uint16_t property_id; + uint32_t property_value; + uint8_t value_len; +} light_lc_server_get_property_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} light_lc_server_get_default_transition_time_t; + +typedef struct +{ + generic_on_off_t light_on_off; + generic_transition_time_t sm_trans_time; +} light_lc_server_get_sm_transition_time_t; + +typedef struct +{ + uint8_t mode; +} light_lc_server_set_mode_t; + +typedef struct +{ + uint8_t mode; +} light_lc_server_set_om_t; + +typedef struct +{ + generic_on_off_t light_on_off; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_lc_server_set_light_on_off_t; + +typedef struct +{ + uint16_t property_id; + uint32_t property_value; +} light_lc_server_set_property_t; +/** @} */ + +/** + * @defgroup LIGHT_LC_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_LC_CLIENT_MODE_STATUS 0 //!< @ref light_lc_client_model_status_t +#define LIGHT_LC_CLIENT_OM_STATUS 1 //!< @ref light_lc_client_om_status_t +#define LIGHT_LC_CLIENT_LIGHT_ON_OFF_STATUS 2 //!< @ref light_lc_client_light_on_off_status_t +#define LIGHT_LC_CLIENT_PROPERTY_STATUS 3 //!< @ref light_lc_client_property_status_t + +typedef struct +{ + uint16_t src; + uint8_t mode; +} light_lc_client_mode_status_t; + +typedef struct +{ + uint16_t src; + uint8_t mode; +} light_lc_client_om_status_t; + +typedef struct +{ + uint16_t src; + generic_on_off_t present_on_off; + bool optional; + generic_on_off_t target_on_off; + generic_transition_time_t remaining_time; +} light_lc_client_light_on_off_status_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint32_t property_value; +} light_lc_client_property_status_t; +/** @} */ + + +/** + * @defgroup LIGHT_LC_SERVER_API Server API + * @brief Functions declaration + * @{ + */ +/** + * @brief register light lc server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light lc server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_lc_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light lc setup server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light lc setup server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_lc_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish light lc mode + * @param[in] pmodel_info: pointer to light lc server model context + * @param[in] mode: light lc modeo need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_lc_mode_publish(const mesh_model_info_p pmodel_info, + uint8_t mode); +/** + * @brief publish light lc om + * @param[in] pmodel_info: pointer to light lc server model context + * @param[in] om: light lc om need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_lc_om_publish(const mesh_model_info_p pmodel_info, + uint8_t om); + +/** + * @brief publish light lc light on/off + * @param[in] pmodel_info: pointer to light lc server model context + * @param[in] on_off: light on/off status need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_lc_light_on_off_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off); + +/** + * @brief publish light lc property + * @param[in] pmodel_info: pointer to light lc setup server model context + * @param[in] property_id: property id need to publish + * @param[in] pproperty_value: property value need to publish + * @param[in] len: property value length + * @return publish status + */ +mesh_msg_send_cause_t light_lc_property_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, const uint8_t *pproperty_value, + uint16_t len); +/** @} */ + +/** + * @defgroup LIGHT_LC_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ +/** + * @brief register light lc client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light lc client model context + * @retval true: register success + * @retval false: register failed + */ +bool light_lc_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get light lc mode value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lc_mode_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light lc mode value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] mode: lc mode value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lc_mode_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t mode, bool ack); + +/** + * @brief get light lc om value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lc_om_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light lc om value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] mode: lc om value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lc_om_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t mode, bool ack); + +/** + * @brief get light lc light on off value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lc_light_on_off_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light lc light on off value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] light_on_off: desired light on off value + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lc_light_on_off_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t light_on_off, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light lc property value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @return send status + */ +mesh_msg_send_cause_t light_lc_property_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief set light lc property value + * @param[in] pmodel_info: pointer to light lc client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: property id + * @param[in] pvalue: property value + * @param[in] value_len: property value length + * @param[in] property_id: property id + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lc_property_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, + uint8_t *pvalue, uint16_t value_len, bool ack); +/** @} */ +/** @} */ + +END_DECLS + + +#endif /* _LIGHT_LC_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_client.c new file mode 100644 index 00000000..e0c39730 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_client.c @@ -0,0 +1,260 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lc_setup_server.c +* @brief Source file for light lc setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-18 +* @version v1.0 +* ************************************************************************************* +*/ +#include "light_lc.h" + + +static mesh_msg_send_cause_t light_lc_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_lc_mode_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lc_mode_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_MODE_GET); + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lc_mode_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t mode, bool ack) +{ + light_lc_mode_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_MODE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_MODE_SET_UNACK); + } + msg.mode = mode; + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lc_om_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lc_om_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_OM_GET); + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lc_om_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t mode, bool ack) +{ + light_lc_om_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_OM_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_OM_SET_UNACK); + } + msg.mode = mode; + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lc_light_on_off_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lc_light_on_off_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_GET); + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lc_light_on_off_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t light_on_off, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_lc_light_on_off_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_lc_light_on_off_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_lc_light_on_off_set_t, trans_time); + } + msg.light_on_off = light_on_off; + msg.tid = tid; + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_lc_property_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + light_lc_property_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_PROPERTY_GET); + msg.property_id = property_id; + return light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lc_property_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, + uint8_t *pvalue, uint16_t value_len, bool ack) +{ + uint16_t msg_len = sizeof(light_lc_property_set_t) + value_len; + light_lc_property_set_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + if (ack) + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_LIGHT_LC_PROPERTY_SET); + } + else + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_LIGHT_LC_PROPERTY_SET_UNACK); + } + pmsg->property_id = property_id; + memcpy(pmsg->property_value, pvalue, value_len); + mesh_msg_send_cause_t ret = light_lc_client_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, + msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +static bool light_lc_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_LC_MODE_STATUS: + if (pmesh_msg->msg_len == sizeof(light_lc_mode_status_t)) + { + light_lc_mode_status_t *pmsg = (light_lc_mode_status_t *)pbuffer; + light_lc_client_mode_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.mode = pmsg->mode; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LC_CLIENT_MODE_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_LC_OM_STATUS: + if (pmesh_msg->msg_len == sizeof(light_lc_om_status_t)) + { + light_lc_om_status_t *pmsg = (light_lc_om_status_t *)pbuffer; + light_lc_client_om_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.mode = pmsg->mode; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LC_CLIENT_OM_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_STATUS: + { + light_lc_light_on_off_status_t *pmsg = (light_lc_light_on_off_status_t *)pbuffer; + light_lc_client_light_on_off_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.present_on_off = pmsg->present_light_on_off; + status_data.optional = FALSE; + if (pmesh_msg->msg_len == sizeof(light_lc_light_on_off_status_t)) + { + status_data.optional = TRUE; + status_data.target_on_off = pmsg->target_light_on_off; + status_data.remaining_time = pmsg->trans_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LC_CLIENT_LIGHT_ON_OFF_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_LC_PROPERTY_STATUS: + { + light_lc_property_status_t *pmsg = (light_lc_property_status_t *)pbuffer; + uint8_t value_len = pmesh_msg->msg_len - sizeof(light_lc_property_status_t); + light_lc_client_property_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.property_id = pmsg->property_id; + status_data.property_value = 0; + for (uint8_t i = value_len; i > 0; --i) + { + status_data.property_value <<= 8; + status_data.property_value |= pmsg->property_value[i - 1]; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LC_CLIENT_PROPERTY_STATUS, + &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool light_lc_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_LC_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = light_lc_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_lc_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_fsm.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_fsm.c new file mode 100644 index 00000000..2f07978c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_fsm.c @@ -0,0 +1,445 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lc_fsm.c +* @brief Source file for light lc state machine. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-04-22 +* @version v1.0 +* ************************************************************************************* +*/ +#include "light_lc_fsm.h" +#include "mesh_api.h" +#include "model_fsm.h" + +#define LIGHT_LC_DEFAULT_TIME 4000 /* ms */ +#define LIGHT_LC_MIN_TIME 10 /* ms */ + +typedef struct +{ + uint32_t time_fade_on; + uint32_t time_run_on; + uint32_t time_fade; + uint32_t time_prolong; + uint32_t time_fade_standby_auto; + uint32_t time_fade_standby_manual; + uint32_t time_occupancy_delay; + uint32_t time_trans; +} light_lc_time_t; + +typedef struct +{ + model_fsm_t *pfsm; + bool mode_on; + bool om_on; + bool light_on; + plt_timer_t lc_timer; + light_lc_action_cb_t lc_action; + light_lc_time_t lc_time; +} light_lc_fsm_ctx_t; + +static light_lc_fsm_ctx_t lc_fsm_ctx; + +static bool light_lc_mode_on_action(uint32_t state) +{ + plt_timer_stop(lc_fsm_ctx.lc_timer, 0); + switch (state) + { + case LIGHT_LC_STATE_OFF: + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_STANDBY, 0); + } + break; + default: + break; + } + return TRUE; +} + +static bool light_lc_mode_off_action(uint32_t state) +{ + plt_timer_stop(lc_fsm_ctx.lc_timer, 0); + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_OFF, 0); + } + return TRUE; +} + +static bool light_lc_light_on_action(uint32_t state) +{ + switch (state) + { + case LIGHT_LC_STATE_STANDBY: + case LIGHT_LC_STATE_FADE: + case LIGHT_LC_STATE_PROLONG: + case LIGHT_LC_STATE_FADE_STANDBY_AUTO: + case LIGHT_LC_STATE_FADE_STANDBY_MANUAL: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_trans ? lc_fsm_ctx.lc_time.time_trans : LIGHT_LC_MIN_TIME, 0); + break; + case LIGHT_LC_STATE_RUN: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_run_on ? lc_fsm_ctx.lc_time.time_run_on : LIGHT_LC_MIN_TIME, 0); + break; + default: + break; + } + return TRUE; +} + +static bool light_lc_light_off_action(uint32_t state) +{ + switch (state) + { + case LIGHT_LC_STATE_STANDBY: + break; + case LIGHT_LC_STATE_FADE_ON: + case LIGHT_LC_STATE_RUN: + case LIGHT_LC_STATE_FADE: + case LIGHT_LC_STATE_PROLONG: + case LIGHT_LC_STATE_FADE_STANDBY_AUTO: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_trans ? lc_fsm_ctx.lc_time.time_trans : LIGHT_LC_MIN_TIME, 0); + break; + default: + break; + } + return TRUE; +} + +static bool light_lc_occupancy_on_action(uint32_t state) +{ + switch (state) + { + case LIGHT_LC_STATE_STANDBY: + if (lc_fsm_ctx.om_on) + { + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_FADE_ON, lc_fsm_ctx.lc_time.time_fade_on); + } + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_fade_on ? lc_fsm_ctx.lc_time.time_fade_on : LIGHT_LC_MIN_TIME, 0); + } + break; + case LIGHT_LC_STATE_RUN: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_run_on ? lc_fsm_ctx.lc_time.time_run_on : LIGHT_LC_MIN_TIME, 0); + break; + case LIGHT_LC_STATE_FADE: + case LIGHT_LC_STATE_PROLONG: + case LIGHT_LC_STATE_FADE_STANDBY_AUTO: + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_FADE_ON, lc_fsm_ctx.lc_time.time_fade_on); + } + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_fade_on ? lc_fsm_ctx.lc_time.time_fade_on : LIGHT_LC_MIN_TIME, 0); + break; + default: + break; + } + return TRUE; +} + +static bool light_lc_timer_off_action(uint32_t state) +{ + switch (state) + { + case LIGHT_LC_STATE_FADE_ON: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_run_on ? lc_fsm_ctx.lc_time.time_run_on : LIGHT_LC_MIN_TIME, 0); + break; + case LIGHT_LC_STATE_RUN: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_fade ? lc_fsm_ctx.lc_time.time_fade : LIGHT_LC_MIN_TIME, 0); + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_FADE, lc_fsm_ctx.lc_time.time_fade); + } + break; + case LIGHT_LC_STATE_FADE: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_prolong ? lc_fsm_ctx.lc_time.time_prolong : LIGHT_LC_MIN_TIME, 0); + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_PROLONG, lc_fsm_ctx.lc_time.time_prolong); + } + break; + case LIGHT_LC_STATE_PROLONG: + plt_timer_change_period(lc_fsm_ctx.lc_timer, + lc_fsm_ctx.lc_time.time_fade_standby_auto ? lc_fsm_ctx.lc_time.time_fade_standby_auto : + LIGHT_LC_MIN_TIME, 0); + if (lc_fsm_ctx.lc_action) + { + lc_fsm_ctx.lc_action(LIGHT_LC_ACTION_STANDBY, lc_fsm_ctx.lc_time.time_fade_standby_auto); + } + break; + case LIGHT_LC_STATE_FADE_STANDBY_AUTO: + case LIGHT_LC_STATE_FADE_STANDBY_MANUAL: + plt_timer_stop(lc_fsm_ctx.lc_timer, 0); + break; + default: + break; + } + return TRUE; +} + +static void light_lc_mode_off_enter(void) +{ + printi("lc enter mode off state"); +} + +static void light_lc_mode_off_exit(void) +{ + printi("lc exit mode off state"); +} + +static void light_lc_standby_enter(void) +{ + printi("lc enter standby state"); +} + +static void light_lc_standby_exit(void) +{ + printi("lc exit standby state"); +} + +static void light_lc_fade_on_enter(void) +{ + printi("lc enter fade on state"); +} + +static void light_lc_fade_on_exit(void) +{ + printi("lc exit fade on state"); +} + +static void light_lc_run_enter(void) +{ + printi("lc enter run state"); +} + +static void light_lc_run_exit(void) +{ + printi("sm: exit run state"); +} + +static void light_lc_fade_enter(void) +{ + printi("lc enter fade state"); +} + +static void light_lc_fade_exit(void) +{ + printi("lc exit fade state"); +} + +static void light_lc_prolong_enter(void) +{ + printi("lc enter prolong state"); +} + +static void light_lc_prolong_exit(void) +{ + printi("lc exit prolong state"); +} + +static void light_lc_fade_standby_auto_enter(void) +{ + printi("lc enter fade standby auto state"); +} + +static void light_lc_fade_standby_auto_exit(void) +{ + printi("lc exit fade standby auto state"); +} + +static void light_lc_fade_standby_manual_enter(void) +{ + printi("lc enter fade standby manual state"); +} + +static void light_lc_fade_standby_manual_exit(void) +{ + printi("lc exit fade standby manual state"); +} + +const model_fsm_event_group_t light_lc_off_events[] = +{ + {LIGHT_LC_EVENT_MODE_ON, light_lc_mode_on_action, LIGHT_LC_STATE_STANDBY} +}; + +const model_fsm_event_group_t light_lc_standby_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_ON, light_lc_light_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_OCCUPANCY_ON, light_lc_occupancy_on_action, LIGHT_LC_STATE_FADE_ON}, +}; + +const model_fsm_event_group_t light_lc_fade_on_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_OFF, light_lc_light_off_action, LIGHT_LC_STATE_FADE_STANDBY_MANUAL}, + {LIGHT_LC_EVENT_TIMER_OFF, light_lc_timer_off_action, LIGHT_LC_STATE_RUN}, +}; + +const model_fsm_event_group_t light_lc_run_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_OFF, light_lc_light_off_action, LIGHT_LC_STATE_FADE_STANDBY_MANUAL}, + {LIGHT_LC_EVENT_OCCUPANCY_ON, light_lc_occupancy_on_action, LIGHT_LC_STATE_RUN}, + {LIGHT_LC_EVENT_LIGHT_ON, light_lc_light_on_action, LIGHT_LC_STATE_RUN}, + {LIGHT_LC_EVENT_TIMER_OFF, light_lc_timer_off_action, LIGHT_LC_STATE_FADE}, +}; + +const model_fsm_event_group_t light_lc_fade_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_OFF, light_lc_light_off_action, LIGHT_LC_STATE_FADE_STANDBY_MANUAL}, + {LIGHT_LC_EVENT_OCCUPANCY_ON, light_lc_occupancy_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_LIGHT_ON, light_lc_light_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_TIMER_OFF, light_lc_timer_off_action, LIGHT_LC_STATE_PROLONG}, +}; + +const model_fsm_event_group_t light_lc_prolong_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_OFF, light_lc_light_off_action, LIGHT_LC_STATE_FADE_STANDBY_MANUAL}, + {LIGHT_LC_EVENT_OCCUPANCY_ON, light_lc_occupancy_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_LIGHT_ON, light_lc_light_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_TIMER_OFF, light_lc_timer_off_action, LIGHT_LC_STATE_FADE_STANDBY_AUTO}, +}; + +const model_fsm_event_group_t light_lc_fade_standby_auto_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_OFF, light_lc_light_off_action, LIGHT_LC_STATE_FADE_STANDBY_MANUAL}, + {LIGHT_LC_EVENT_OCCUPANCY_ON, light_lc_occupancy_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_LIGHT_ON, light_lc_light_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_TIMER_OFF, light_lc_timer_off_action, LIGHT_LC_STATE_STANDBY}, +}; + +const model_fsm_event_group_t light_lc_fade_standby_manual_events[] = +{ + {LIGHT_LC_EVENT_MODE_OFF, light_lc_mode_off_action, LIGHT_LC_STATE_OFF}, + {LIGHT_LC_EVENT_LIGHT_ON, light_lc_light_on_action, LIGHT_LC_STATE_FADE_ON}, + {LIGHT_LC_EVENT_TIMER_OFF, light_lc_timer_off_action, LIGHT_LC_STATE_STANDBY}, +}; + +const model_fsm_table_t lc_fsm_table[] = +{ + {LIGHT_LC_STATE_OFF, light_lc_mode_off_enter, light_lc_off_events, ARRAY_LEN(light_lc_off_events), light_lc_mode_off_exit}, + {LIGHT_LC_STATE_STANDBY, light_lc_standby_enter, light_lc_standby_events, ARRAY_LEN(light_lc_standby_events), light_lc_standby_exit}, + {LIGHT_LC_STATE_FADE_ON, light_lc_fade_on_enter, light_lc_fade_on_events, ARRAY_LEN(light_lc_fade_on_events), light_lc_fade_on_exit}, + {LIGHT_LC_STATE_RUN, light_lc_run_enter, light_lc_run_events, ARRAY_LEN(light_lc_run_events), light_lc_run_exit}, + {LIGHT_LC_STATE_FADE, light_lc_fade_enter, light_lc_fade_events, ARRAY_LEN(light_lc_fade_events), light_lc_fade_exit}, + {LIGHT_LC_STATE_PROLONG, light_lc_prolong_enter, light_lc_prolong_events, ARRAY_LEN(light_lc_prolong_events), light_lc_prolong_exit}, + {LIGHT_LC_STATE_FADE_STANDBY_AUTO, light_lc_fade_standby_auto_enter, light_lc_fade_standby_auto_events, ARRAY_LEN(light_lc_fade_standby_auto_events), light_lc_fade_standby_auto_exit}, + {LIGHT_LC_STATE_FADE_STANDBY_MANUAL, light_lc_fade_standby_manual_enter, light_lc_fade_standby_manual_events, ARRAY_LEN(light_lc_fade_standby_manual_events), light_lc_fade_standby_manual_exit}, +}; + +void light_lc_fsm_init(light_lc_state_t init_state, light_lc_action_cb_t action_cb, + light_lc_timeout_cb_t timeout_cb) +{ + lc_fsm_ctx.lc_timer = plt_timer_create("lc_tmr", 1000, false, 0, timeout_cb); + lc_fsm_ctx.lc_action = action_cb; + lc_fsm_ctx.lc_time.time_fade_on = LIGHT_LC_DEFAULT_TIME; + lc_fsm_ctx.lc_time.time_run_on = LIGHT_LC_DEFAULT_TIME; + lc_fsm_ctx.lc_time.time_fade = LIGHT_LC_DEFAULT_TIME; + lc_fsm_ctx.lc_time.time_prolong = LIGHT_LC_DEFAULT_TIME; + lc_fsm_ctx.lc_time.time_fade_standby_auto = LIGHT_LC_DEFAULT_TIME; + lc_fsm_ctx.lc_time.time_fade_standby_manual = LIGHT_LC_DEFAULT_TIME; + lc_fsm_ctx.lc_time.time_occupancy_delay = LIGHT_LC_DEFAULT_TIME; + + lc_fsm_ctx.pfsm = model_fsm_reg(lc_fsm_table, sizeof(lc_fsm_table) / sizeof(model_fsm_table_t), + init_state); + + model_fsm_run(lc_fsm_ctx.pfsm); +} + +void light_lc_fsm_om_set(uint8_t om) +{ + lc_fsm_ctx.om_on = om; +} + +void light_lc_time_set(light_lc_time_type_t type, uint32_t value) +{ + switch (type) + { + case LIGHT_LC_TIME_TYPE_FADE_ON: + lc_fsm_ctx.lc_time.time_fade_on = value; + break; + case LIGHT_LC_TIME_TYPE_RUN_ON: + lc_fsm_ctx.lc_time.time_run_on = value; + break; + case LIGHT_LC_TIME_TYPE_FADE: + lc_fsm_ctx.lc_time.time_fade = value; + break; + case LIGHT_LC_TIME_TYPE_PROLONG: + lc_fsm_ctx.lc_time.time_prolong = value; + break; + case LIGHT_LC_TIME_TYPE_FADE_STANDBY_AUTO: + lc_fsm_ctx.lc_time.time_fade_standby_auto = value; + break; + case LIGHT_LC_TIME_TYPE_FADE_STANDBY_MANUAL: + lc_fsm_ctx.lc_time.time_fade_standby_manual = value; + break; + case LIGHT_LC_TIME_TYPE_OCCUPANCY_DELAY: + lc_fsm_ctx.lc_time.time_occupancy_delay = value; + break; + case LIGHT_LC_TIME_TYPE_TRANS: + lc_fsm_ctx.lc_time.time_trans = value; + break; + default: + break; + } +} + +uint32_t light_lc_time_get(light_lc_time_type_t type) +{ + uint32_t value = 0; + switch (type) + { + case LIGHT_LC_TIME_TYPE_FADE_ON: + value = lc_fsm_ctx.lc_time.time_fade_on; + break; + case LIGHT_LC_TIME_TYPE_RUN_ON: + value = lc_fsm_ctx.lc_time.time_run_on; + break; + case LIGHT_LC_TIME_TYPE_FADE: + value = lc_fsm_ctx.lc_time.time_fade; + break; + case LIGHT_LC_TIME_TYPE_PROLONG: + value = lc_fsm_ctx.lc_time.time_prolong; + break; + case LIGHT_LC_TIME_TYPE_FADE_STANDBY_AUTO: + value = lc_fsm_ctx.lc_time.time_fade_standby_auto; + break; + case LIGHT_LC_TIME_TYPE_FADE_STANDBY_MANUAL: + value = lc_fsm_ctx.lc_time.time_fade_standby_manual; + break; + case LIGHT_LC_TIME_TYPE_OCCUPANCY_DELAY: + value = lc_fsm_ctx.lc_time.time_occupancy_delay; + break; + default: + break; + } + + return value; +} + +void light_lc_fsm_handle_timeout(void *ptimer) +{ + light_lc_fsm_handle_event(LIGHT_LC_EVENT_TIMER_OFF); +} + +void light_lc_fsm_handle_event(light_lc_event_t event) +{ + model_fsm_handle_event(lc_fsm_ctx.pfsm, event); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_fsm.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_fsm.h new file mode 100644 index 00000000..3f3c64a8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_fsm.h @@ -0,0 +1,138 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lc_fsm.h +* @brief Head file for light lc state machine. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-04-22 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _LIGHT_LC_FSM_H_ +#define _LIGHT_LC_FSM_H_ + +#include "platform_types.h" + +BEGIN_DECLS + + +/** + * @addtogroup LIGHT_LC_FSM + * @{ + */ + +/** + * @defgroup LIGHT_LC_FSM_MESSAGE LC FSM Msg + * @brief Light lc fsm message + * @{ + */ +typedef enum +{ + LIGHT_LC_EVENT_MODE_ON, + LIGHT_LC_EVENT_MODE_OFF, + LIGHT_LC_EVENT_OCCUPANCY_ON, + LIGHT_LC_EVENT_LIGHT_ON, + LIGHT_LC_EVENT_LIGHT_OFF, + LIGHT_LC_EVENT_TIMER_OFF, +} light_lc_event_t; + +typedef enum +{ + LIGHT_LC_ACTION_OFF, + LIGHT_LC_ACTION_FADE_ON, + LIGHT_LC_ACTION_FADE, + LIGHT_LC_ACTION_PROLONG, + LIGHT_LC_ACTION_STANDBY, +} light_lc_action_t; + +typedef enum +{ + LIGHT_LC_TIME_TYPE_FADE_ON, + LIGHT_LC_TIME_TYPE_RUN_ON, + LIGHT_LC_TIME_TYPE_FADE, + LIGHT_LC_TIME_TYPE_PROLONG, + LIGHT_LC_TIME_TYPE_FADE_STANDBY_AUTO, + LIGHT_LC_TIME_TYPE_FADE_STANDBY_MANUAL, + LIGHT_LC_TIME_TYPE_OCCUPANCY_DELAY, + LIGHT_LC_TIME_TYPE_TRANS, +} light_lc_time_type_t; + +typedef enum +{ + LIGHT_LC_STATE_OFF, + LIGHT_LC_STATE_STANDBY, + LIGHT_LC_STATE_FADE_ON, + LIGHT_LC_STATE_RUN, + LIGHT_LC_STATE_FADE, + LIGHT_LC_STATE_PROLONG, + LIGHT_LC_STATE_FADE_STANDBY_AUTO, + LIGHT_LC_STATE_FADE_STANDBY_MANUAL, +} light_lc_state_t; +/** @} */ + +/** + * @defgroup LIGHT_LC_FSM_API LC FSM API + * @brief Light lc fsm api + * @{ + */ +/** + * @brief light lc action callback function + * @param[in] action: action type + * @param[in] trans_time: action transition time + */ +typedef void (*light_lc_action_cb_t)(light_lc_action_t action, uint32_t trans_time); + +/** + * @brief light lc timeout callback function + * @param[in] pargs: timer handler + */ +typedef void (*light_lc_timeout_cb_t)(void *pargs); + +/** + * @brief initialize light lc fsm + * @param[in] init_state: fsm initialize state + * @param[in] action_cb: light lc action callback + * @param[in] timneout_cb: light lc timeout callback + */ +void light_lc_fsm_init(light_lc_state_t init_state, light_lc_action_cb_t action_cb, + light_lc_timeout_cb_t timeout_cb); + +/** + * @brief set light lc fsm occupancy mode + * @param[in] om: occupancy mode + */ +void light_lc_fsm_om_set(uint8_t om); + +/** + * @brief set light lc time + * @param[in] type: light lc time type + * @param[in] value: light lc time value + */ +void light_lc_time_set(light_lc_time_type_t type, uint32_t value); + +/** + * @brief get light lc time + * @param[in] type: light lc type + * @return light lc time + */ +uint32_t light_lc_time_get(light_lc_time_type_t type); + +/** + * @brief handle lc fsm event + * @param[in] event: lc fsm event + */ +void light_lc_fsm_handle_event(light_lc_event_t event); + +/** + * @brief handle lc fsm timeout event + * @param[in] ptimer: timer handle + */ +void light_lc_fsm_handle_timeout(void *ptimer); + +/** @} */ +/** @} */ +END_DECLS + +#endif /* LIGHT_LC_FSM_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_server.c new file mode 100644 index 00000000..2b0bd404 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_server.c @@ -0,0 +1,720 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lc_server.c +* @brief Source file for light lc server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-17 +* @version v1.0 +* ************************************************************************************* +*/ +#include "light_lc.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif +#include "model_property.h" + +typedef struct +{ + generic_on_off_t target_light_on_off; + uint8_t tid; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_lc_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_lc_process_result_t; + +static mesh_msg_send_cause_t light_lc_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t light_lc_mode_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t mode, uint32_t delay_time) +{ + light_lc_mode_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_MODE_STATUS); + msg.mode = mode; + return light_lc_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(light_lc_mode_status_t), + app_key_index, + delay_time); +} + +static mesh_msg_send_cause_t light_lc_om_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t mode, uint32_t delay_time) +{ + light_lc_om_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_OM_STATUS); + msg.mode = mode; + return light_lc_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +static mesh_msg_send_cause_t light_lc_light_on_off_status(mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, generic_on_off_t present, bool optional, + generic_on_off_t target, generic_transition_time_t trans_time, + uint32_t delay_time) +{ + light_lc_light_on_off_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_STATUS); + uint16_t msg_len = 0; + if (optional) + { + msg.present_light_on_off = present; + msg.target_light_on_off = target; + msg.trans_time = trans_time; + msg_len = sizeof(msg); + } + else + { + msg.present_light_on_off = present; + msg_len = MEMBER_OFFSET(light_lc_light_on_off_status_t, target_light_on_off); + } + return light_lc_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, + delay_time); +} + +static uint8_t get_present_lc_mode(const mesh_model_info_p pmodel_info) +{ + light_lc_server_get_mode_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_MODE, &get_data); + } + + return get_data.mode; +} + +static uint8_t get_present_lc_om(const mesh_model_info_p pmodel_info) +{ + light_lc_server_get_om_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_OM, &get_data); + } + + return get_data.mode; +} + +static generic_on_off_t get_present_light_on_off(const mesh_model_info_p pmodel_info) +{ + light_lc_server_get_light_on_off_t get_data = {GENERIC_OFF}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_LIGHT_ON_OFF, &get_data); + } + + return get_data.on_off; +} + +static mesh_msg_send_cause_t light_lc_mode_delay_publish(const mesh_model_info_p pmodel_info, + uint8_t mode, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = light_lc_mode_status(pmodel_info, 0, 0, mode, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_lc_mode_publish(const mesh_model_info_p pmodel_info, + uint8_t mode) +{ + return light_lc_mode_delay_publish(pmodel_info, mode, 0); +} + +static mesh_msg_send_cause_t light_lc_om_delay_publish(const mesh_model_info_p pmodel_info, + uint8_t om, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = light_lc_om_status(pmodel_info, 0, 0, om, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_lc_om_publish(const mesh_model_info_p pmodel_info, + uint8_t om) +{ + return light_lc_om_delay_publish(pmodel_info, om, 0); +} + +static mesh_msg_send_cause_t light_lc_light_on_off_delay_publish(const mesh_model_info_p + pmodel_info, + generic_on_off_t on_off, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = light_lc_light_on_off_status(pmodel_info, 0, 0, on_off, FALSE, on_off, trans_time, + delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_lc_light_on_off_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off) +{ + return light_lc_light_on_off_delay_publish(pmodel_info, on_off, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_lc_mode_state_change_publish(const mesh_model_info_p pmodel_info, + uint8_t mode, light_lc_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_lc_mode_publish(pmodel_info, mode); + } +} +#endif + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_lc_om_state_change_publish(const mesh_model_info_p pmodel_info, + uint8_t mode, light_lc_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_lc_om_publish(pmodel_info, mode); + } +} +#endif + + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_lc_light_on_off_state_change_publish(const mesh_model_info_p pmodel_info, + generic_on_off_t on_off, light_lc_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_lc_light_on_off_publish(pmodel_info, on_off); + } +} +#endif + +static int32_t light_lc_light_on_off_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + int32_t ret = MODEL_SUCCESS; + light_lc_server_set_light_on_off_t set_data; + light_lc_info_t *plc_info = pmodel_info->pargs; + if (NULL == plc_info) + { + return 0; + } + set_data.light_on_off = plc_info->target_light_on_off; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_SET_LIGHT_ON_OFF, &set_data); + } + + if (0 == remaining_time.num_steps) + { + generic_on_off_t present_on_off = get_present_light_on_off(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + light_lc_light_on_off_delay_publish(pmodel_info, present_on_off, plc_info->delay_pub_time); +#else + light_lc_light_on_off_publish(pmodel_info, present_on_off); +#endif + } + + return ret; +} + +static generic_on_off_t light_lc_light_on_off_process(const mesh_model_info_p pmodel_info, + generic_on_off_t target_on_off, + generic_transition_time_t trans_time, + light_lc_process_result_t *presult) +{ + generic_on_off_t on_off_before_set; + generic_on_off_t on_off_after_set; + + /* get generic on/off before set */ + on_off_before_set = get_present_light_on_off(pmodel_info); + on_off_after_set = on_off_before_set; + + int32_t ret = MODEL_SUCCESS; + light_lc_server_set_light_on_off_t trans_set_data; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + trans_set_data.light_on_off = target_on_off; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_SET_LIGHT_ON_OFF, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_LC, trans_time, + light_lc_light_on_off_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_SET_LIGHT_ON_OFF, &trans_set_data); + } + } +#endif + } + else + { + /* get on/off after set */ + on_off_after_set = get_present_light_on_off(pmodel_info); + } + + if (on_off_before_set != on_off_after_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return on_off_after_set; +} + +static int32_t light_lc_light_on_off_delay_execution(mesh_model_info_t *pmodel_info, + uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LIGHT_LC: + { + light_lc_info_t *plc_info = pmodel_info->pargs; + if (NULL == plc_info) + { + return 0; + } + plc_info->delay_time = 0; + light_lc_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + generic_on_off_t present_on_off = light_lc_light_on_off_process(pmodel_info, + plc_info->target_light_on_off, + plc_info->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_lc_light_on_off_delay_publish(pmodel_info, present_on_off, plc_info->delay_pub_time); + } + } +#else + light_lc_light_on_off_state_change_publish(pmodel_info, present_on_off, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_lc_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_LC_MODE_GET: + if (pmesh_msg->msg_len == sizeof(light_lc_mode_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lc_mode_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_lc_mode(pmodel_info), delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_LC_MODE_SET: + case MESH_MSG_LIGHT_LC_MODE_SET_UNACK: + { + light_lc_mode_set_t *pmsg = (light_lc_mode_set_t *)pbuffer; + uint8_t mode_before_set = get_present_lc_mode(pmodel_info); + if (NULL != pmodel_info->model_data_cb) + { + light_lc_server_set_mode_t set_data = {pmsg->mode}; + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_SET_MODE, &set_data); + } + + uint8_t mode_after_set = get_present_lc_mode(pmodel_info); + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_MODE_SET) + { + light_lc_mode_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + mode_after_set, delay_rsp_time); + } + + light_lc_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + (void)result; + + if (mode_before_set != mode_after_set) + { + result.state_changed = TRUE; + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_MODE_SET_UNACK) ? FALSE : TRUE; + generic_transition_time_t trans_time = {0, 0}; +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, + ack); + light_lc_mode_delay_publish(pmodel_info, mode_after_set, delay_pub_time); + } +#else + light_lc_mode_state_change_publish(pmodel_info, mode_after_set, result); +#endif + + if (0 == pmsg->mode) + { + /* stop transition */ + generic_transition_timer_stop(pmesh_msg->pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_LC); + } + } + break; + case MESH_MSG_LIGHT_LC_OM_GET: + if (pmesh_msg->msg_len == sizeof(light_lc_om_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lc_om_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_lc_om(pmodel_info), delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_LC_OM_SET: + case MESH_MSG_LIGHT_LC_OM_SET_UNACK: + { + light_lc_om_set_t *pmsg = (light_lc_om_set_t *)pbuffer; + uint8_t mode_before_set = get_present_lc_om(pmodel_info); + if (NULL != pmodel_info->model_data_cb) + { + light_lc_server_set_om_t set_data = {pmsg->mode}; + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_SET_OM, &set_data); + } + uint8_t mode_after_set = get_present_lc_om(pmodel_info); + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_OM_SET) + { + light_lc_om_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_lc_om(pmodel_info), delay_rsp_time); + } + + light_lc_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + (void)result; + + if (mode_before_set != mode_after_set) + { + result.state_changed = TRUE; + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_OM_SET_UNACK) ? FALSE : TRUE; + generic_transition_time_t trans_time = {0, 0}; +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, + ack); + light_lc_om_delay_publish(pmodel_info, mode_after_set, delay_pub_time); + } +#else + light_lc_om_state_change_publish(pmodel_info, mode_after_set, result); +#endif + } + break; + case MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_GET: + if (pmesh_msg->msg_len == sizeof(light_lc_light_on_off_get_t)) + { + /* get present on/off status */ + generic_on_off_t present_on_off = get_present_light_on_off(pmodel_info); + /* get target on/off status*/ + light_lc_info_t *plc_info = pmodel_info->pargs; + /* get remaining time */ + generic_transition_time_t remaining_time; + if (plc_info->delay_time > 0) + { + remaining_time = plc_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_LC); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lc_light_on_off_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_on_off, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + plc_info->target_light_on_off, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET: + case MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET_UNACK: + { + light_lc_light_on_off_set_t *pmsg = (light_lc_light_on_off_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + bool trans_exist = FALSE; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_lc_light_on_off_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_lc_light_on_off_set_t)) + { + trans_exist = TRUE; + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_ON_OFF_VALID(pmsg->light_on_off) && + IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_lc_info_t *plc_info = pmodel_info->pargs; + plc_info->tid = pmsg->tid; + plc_info->target_light_on_off = pmsg->light_on_off; + if (!trans_exist && GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) + { + /* calculate transition time */ + light_lc_server_get_sm_transition_time_t get_data; + get_data.light_on_off = pmsg->light_on_off; + get_data.sm_trans_time.num_steps = GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE; + get_data.sm_trans_time.step_resolution = 0; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_SM_TRANSITION_TIME, &get_data); + } + trans_time = get_data.sm_trans_time; + } + plc_info->trans_time = trans_time; + plc_info->delay_time = delay_time; + + generic_on_off_t present_on_off; + light_lc_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (delay_time > 0) + { + result.use_transition = TRUE; + present_on_off = get_present_light_on_off(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_LC, delay_time, + light_lc_light_on_off_delay_execution); + } + else + { + present_on_off = light_lc_light_on_off_process(pmodel_info, plc_info->target_light_on_off, + trans_time, + &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET) + { + light_lc_light_on_off_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_on_off, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + plc_info->target_light_on_off, trans_time, delay_rsp_time); + } + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_LIGHT_ON_OFF_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_lc_light_on_off_delay_publish(pmodel_info, present_on_off, delay_pub_time); + } + } + else + { + plc_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + light_lc_light_on_off_state_change_publish(pmodel_info, present_on_off, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_lc_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + generic_transition_time_t remaining_time; + light_lc_light_on_off_status(pmodel_info, 0, 0, get_present_light_on_off(pmodel_info), FALSE, + GENERIC_OFF, + remaining_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_lc_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_lc_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_LC); + /* stop step transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_LC); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_lc_server_reg(uint8_t element_index, mesh_model_info_t *pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_LC_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_lc_info_t *plc_info = plt_malloc(sizeof(light_lc_info_t), RAM_TYPE_DATA_ON); + if (NULL == plc_info) + { + printe("light_lc_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(plc_info, 0, sizeof(light_lc_info_t)); + pmodel_info->pargs = plc_info; + + pmodel_info->model_receive = light_lc_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_lc_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_lc_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_lc_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_setup_server.c new file mode 100644 index 00000000..2d39b483 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_setup_server.c @@ -0,0 +1,226 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lc_setup_server.c +* @brief Source file for light lc setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-18 +* @version v1.0 +* ************************************************************************************* +*/ +#include "light_lc.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif +#include "model_property.h" + +#define IS_LC_TIME_PROPERTY(value) ((value) >= 0x36) && ((value) <= 0x3c)) + +static mesh_msg_send_cause_t light_lc_setup_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t light_lc_property_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, const uint8_t *pproperty_value, uint16_t len, + uint32_t delay_time) +{ + uint16_t msg_len = sizeof(light_lc_property_status_t) + len; + light_lc_property_status_t *pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_LIGHT_LC_PROPERTY_STATUS); + pmsg->property_id = property_id; + memcpy(pmsg->property_value, pproperty_value, len); + + mesh_msg_send_cause_t ret = light_lc_setup_server_send(pmodel_info, dst, (uint8_t *)pmsg, msg_len, + app_key_index, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +static mesh_msg_send_cause_t light_lc_property_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, const uint8_t *pproperty_value, + uint16_t len, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = light_lc_property_status(pmodel_info, 0, 0, property_id, pproperty_value, len, + delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_lc_property_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, const uint8_t *pproperty_value, + uint16_t len) +{ + return light_lc_property_delay_publish(pmodel_info, property_id, pproperty_value, len, 0); +} + +bool light_lc_property_value_check(uint16_t property_id, const uint8_t *value, uint16_t value_len) +{ + if (MODEL_PROPERTY_INVALID == property_id) + { + return FALSE; + } + + uint16_t wanted_len = 0; + if ((property_id >= 0x2E) && (property_id <= 0x30)) + { + wanted_len = 2; + } + else if ((property_id >= 0x36) && (property_id <= 0x3c)) + { + wanted_len = 3; + } + if (value_len != wanted_len) + { + return FALSE; + } + + return TRUE; +} + +static bool light_lc_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_LC_PROPERTY_GET: + if (pmesh_msg->msg_len == sizeof(light_lc_property_get_t)) + { + light_lc_property_get_t *pmsg = (light_lc_property_get_t *)pbuffer; + if (MODEL_PROPERTY_INVALID != pmsg->property_id) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lc_server_get_property_t get_data = {pmsg->property_id, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_PROPERTY, &get_data); + } + light_lc_property_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_data.property_id, (uint8_t *)&get_data.property_value, get_data.value_len, + delay_rsp_time); + } + } + break; + case MESH_MSG_LIGHT_LC_PROPERTY_SET: + case MESH_MSG_LIGHT_LC_PROPERTY_SET_UNACK: + { + light_lc_property_set_t *pmsg = (light_lc_property_set_t *)pbuffer; + uint16_t value_len = pmesh_msg->msg_len - MEMBER_OFFSET(light_lc_property_set_t, property_value); + + if (light_lc_property_value_check(pmsg->property_id, pmsg->property_value, value_len)) + { + bool property_changed = FALSE; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + light_lc_server_get_property_t property_before_set = {pmsg->property_id, 0, 0}; + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_PROPERTY, &property_before_set); + + light_lc_server_set_property_t set_data; + set_data.property_id = pmsg->property_id; + set_data.property_value = 0; + for (uint8_t i = value_len; i > 0; --i) + { + set_data.property_value <<= 8; + set_data.property_value |= pmsg->property_value[i - 1]; + } + + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LC_SERVER_SET_PROPERTY, + &set_data); + + light_lc_server_get_property_t property_after_set = {pmsg->property_id, 0, 0}; + pmodel_info->model_data_cb(pmodel_info, LIGHT_LC_SERVER_GET_PROPERTY, &property_after_set); + + /* compare property before and after set */ + if (property_before_set.property_value != property_after_set.property_value) + { + property_changed = TRUE; + } + } + (void)property_changed; + + uint32_t delay_rsp_time = 0; + if (MESH_MSG_LIGHT_LC_PROPERTY_SET == pmesh_msg->access_opcode) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lc_property_status(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, pmsg->property_value, value_len, delay_rsp_time); + } + +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LC_PROPERTY_SET) ? FALSE : TRUE; +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (property_changed) +#endif + { + generic_transition_time_t trans_time = {0, 0}; + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, + ack); + light_lc_property_delay_publish(pmesh_msg->pmodel_info, pmsg->property_id, pmsg->property_value, + value_len, delay_pub_time); + } +#else + light_lc_property_publish(pmesh_msg->pmodel_info, pmsg->property_id, pmsg->property_value, + value_len); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool light_lc_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_LC_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = light_lc_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_xyl_setup_server_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness.h new file mode 100644 index 00000000..451618db --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness.h @@ -0,0 +1,504 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lightness.h +* @brief Head file for light lightness models. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-27 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _LIGHT_LIGHTNESS_H +#define _LIGHT_LIGHTNESS_H + +#include "mesh_api.h" +#include "generic_types.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_LIGHTNESS + * @{ + */ + +/** + * @defgroup LIGHT_LIGHTNESS_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_LIGHT_LIGHTNESS_GET 0x824B +#define MESH_MSG_LIGHT_LIGHTNESS_SET 0x824C +#define MESH_MSG_LIGHT_LIGHTNESS_SET_UNACK 0x824D +#define MESH_MSG_LIGHT_LIGHTNESS_STAT 0x824E +#define MESH_MSG_LIGHT_LIGHTNESS_LINEAR_GET 0x824F +#define MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET 0x8250 +#define MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET_UNACK 0x8251 +#define MESH_MSG_LIGHT_LIGHTNESS_LINEAR_STAT 0x8252 +#define MESH_MSG_LIGHT_LIGHTNESS_LAST_GET 0x8253 +#define MESH_MSG_LIGHT_LIGHTNESS_LAST_STAT 0x8254 +#define MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_GET 0x8255 +#define MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_STAT 0x8256 +#define MESH_MSG_LIGHT_LIGHTNESS_RANGE_GET 0x8257 +#define MESH_MSG_LIGHT_LIGHTNESS_RANGE_STAT 0x8258 +#define MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET 0x8259 +#define MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK 0x825A +#define MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET 0x825B +#define MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET_UNACK 0x825C +/** @} */ + +/** + * @defgroup LIGHT_LIGHTNESS_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_LIGHT_LIGHTNESS_SERVER 0x1300FFFF +#define MESH_MODEL_LIGHT_LIGHTNESS_SETUP_SERVER 0x1301FFFF +#define MESH_MODEL_LIGHT_LIGHTNESS_CLIENT 0x1302FFFF +/** @} */ + +/** + * @defgroup LIGHT_LIGHTNESS_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_GET)]; +} _PACKED4_ light_lightness_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_SET)]; + uint16_t lightness; //!< The target value of the Light Lightness Actual state. + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_lightness_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_STAT)]; + uint16_t present_lightness; + uint16_t target_lightness; //!< optional + /* If the Target Lightness field is present, the Remaining Time field shall also be present; + otherwise these fields shall not be present. */ + generic_transition_time_t remaining_time; +} _PACKED4_ light_lightness_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_LINEAR_GET)]; +} _PACKED4_ light_lightness_linear_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET)]; + uint16_t lightness; //!< The target value of the Light Lightness Linear state. + uint8_t tid; + generic_transition_time_t trans_time; //!< optional + /* If the Transition Time field is present, the Delay field shall also be present; + otherwise these fields shall not be present. */ + uint8_t delay; //!< Message execution delay in 5 millisecond steps +} _PACKED4_ light_lightness_linear_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_LINEAR_STAT)]; + uint16_t present_lightness; + uint16_t target_lightness; //!< optional + /* If the Target Lightness field is present, the Remaining Time field shall also be present; + otherwise these fields shall not be present. */ + generic_transition_time_t remaining_time; +} _PACKED4_ light_lightness_linear_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_LAST_GET)]; +} _PACKED4_ light_lightness_last_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_LAST_STAT)]; + uint16_t lightness; //!< The target value of the Light Lightness Actual state. +} _PACKED4_ light_lightness_last_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_GET)]; +} _PACKED4_ light_lightness_default_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET)]; + uint16_t lightness; //!< The target value of the Light Lightness Actual state. +} _PACKED4_ light_lightness_default_set_t, *light_lightness_default_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_STAT)]; + uint16_t lightness; //!< The target value of the Light Lightness Actual state. +} _PACKED4_ light_lightness_default_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_RANGE_GET)]; +} _PACKED4_ light_lightness_range_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET)]; + uint16_t range_min; + uint16_t range_max; +} _PACKED4_ light_lightness_range_set_t, *light_lightness_range_set_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_LIGHTNESS_RANGE_STAT)]; + generic_stat_t stat; + uint16_t range_min; + uint16_t range_max; +} _PACKED4_ light_lightness_range_stat_t; +/** @} */ + +/** + * @defgroup LIGHT_LIGHTNESS_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS 0 +#define GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS_LINEAR 1 +#define DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS 0 +#define DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS_LINEAR 1 +/** @} */ + + +/** + * @defgroup LIGHT_LIGHTNESS_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_LIGHTNESS_SERVER_GET 0 //!< @ref light_lightness_server_get_t +#define LIGHT_LIGHTNESS_SERVER_GET_LINEAR 1 //!< @ref light_lightness_server_get_t +#define LIGHT_LIGHTNESS_SERVER_GET_DEFAULT 2 //!< @ref light_lightness_server_get_t +#define LIGHT_LIGHTNESS_SERVER_GET_LAST 3 //!< @ref light_lightness_server_get_t +#define LIGHT_LIGHTNESS_SERVER_GET_RANGE 4 //!< @ref light_lightness_server_get_range_t +#define LIGHT_LIGHTNESS_SERVER_GET_DEFAULT_TRANSITION_TIME 5 //!< @ref light_lightness_server_get_default_transition_time_t +#define LIGHT_LIGHTNESS_SERVER_SET 6 //!< @ref light_lightness_server_set_t +#define LIGHT_LIGHTNESS_SERVER_SET_LINEAR 7 //!< @ref light_lightness_server_set_t +#define LIGHT_LIGHTNESS_SERVER_SET_LAST 8 //!< @ref light_lightness_server_set_t +#define LIGHT_LIGHTNESS_SERVER_SET_DEFAULT 9 //!< @ref light_lightness_server_set_t +#define LIGHT_LIGHTNESS_SERVER_SET_RANGE 10 //!< @ref light_lightness_server_set_range_t + +typedef struct +{ + uint16_t lightness; +} light_lightness_server_get_t; + +typedef struct +{ + uint16_t range_min; + uint16_t range_max; +} light_lightness_server_get_range_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} light_lightness_server_get_default_transition_time_t; + +typedef struct +{ + uint16_t lightness; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_lightness_server_set_t; + +typedef struct +{ + uint16_t lightness; +} light_lightness_server_set_last_t; + +typedef struct +{ + uint16_t lightness; +} light_lightness_server_set_default_t; + +typedef struct +{ + uint16_t range_min; + uint16_t range_max; +} light_lightness_server_set_range_t; + +/** @} */ + +/** + * @defgroup LIGHT_LIGHTNESS_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_LIGHTNESS_CLIENT_STATUS 0 //!< @ref light_lightness_client_status_t +#define LIGHT_LIGHTNESS_CLIENT_STATUS_LINEAR 1 //!< @ref light_lightness_client_status_t +#define LIGHT_LIGHTNESS_CLIENT_STATUS_LAST 2 //!< @ref light_lightness_client_status_last_t +#define LIGHT_LIGHTNESS_CLIENT_STATUS_DEFAULT 3 //!< @ref light_lightness_client_status_default_t +#define LIGHT_LIGHTNESS_CLIENT_STATUS_RANGE 4 //!< @ref light_lightness_client_status_range_t + +typedef struct +{ + uint16_t src; + uint16_t present_lightness; + bool optional; + uint16_t target_lightness; + generic_transition_time_t remaining_time; +} light_lightness_client_status_t; + +typedef struct +{ + uint16_t src; + uint16_t lightness; +} light_lightness_client_status_last_t; + +typedef struct +{ + uint16_t src; + uint16_t lightness; +} light_lightness_client_status_default_t; + +typedef struct +{ + uint16_t src; + generic_stat_t status; + uint16_t range_min; + uint16_t range_max; +} light_lightness_client_status_range_t; +/** @} */ + + +/** + * @defgroup LIGHT_LIGHTNESS_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register light lightness server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light lightness server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_lightness_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light lightness setup server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light lightness setup server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_lightness_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief enable or disable lightness period publish + * @param[in] lightness: lightness publish enable status + * @param[in] lightness_linear: lightness linear publish enable status + * @note default is lightness enable, lightness linear enabled + */ +void light_lightness_period_pub_enable(bool lightness, bool lightness_linear); + +/** + * @brief publish light lightness + * @param[in] pmodel_info: pointer to light lightness server model context + * @param[in] lightness: lightness need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_lightness_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness); + +/** + * @brief publish light lightness linear + * @param[in] pmodel_info: pointer to light lightness server model context + * @param[in] lightness: linear lightness need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_lightness_linear_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness); + +/** + * @brief convert lightness linear to lightness actual + * @param[in] lightness_linear: lightness linear + * @return lightness value + */ +uint16_t light_lightness_linear_to_actual(uint16_t lightness_linear); + +/** + * @brief convert lightness actual to lightness linear + * @param[in] lightness_actual: actual lightness + * @return lightness linear value + */ +uint16_t light_lightness_actual_to_linear(uint16_t lightness_actual); + +/** + * @brief convert light lightness value to generic level value + * @param[in] lightness: light lightness value + * @return generic level value + */ +int16_t light_lightness_to_generic_level(uint16_t lightness); + +/** + * @brief convert generic level value to light lightness value + * @param[in] level: generic level value + * @return light lightness value + */ +uint16_t generic_level_to_light_lightness(int16_t level); + +/** + * @brief convert light lightness linear value to generic level value + * @param[in] lightness: light lightness linear value + * @return generic level value + */ +int16_t light_lightness_linear_to_generic_level(uint16_t lightness); + +/** + * @brief convert generic level value to light lightness linear value + * @param[in] level: generic level value + * @return light lightness lienar value + */ +uint16_t generic_level_to_light_lightness_linear(int16_t level); + +/** @} */ + +/** + * @defgroup LIGHT_LIGHTNESS_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register light lightness client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light lightness client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_lightness_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get light lightness + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lightness_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light lightness + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired lightness + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lightness_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light lightness linear + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lightness_linear_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light lightness linear + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired lightness linear + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lightness_linear_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get last light lightness + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lightness_last_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get default light lightness + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lightness_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set default light lightness + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] lightness: desired default light lightness value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lightness_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, bool ack); + +/** + * @brief get light lightness range + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_lightness_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light lightness range + * @param[in] pmodel_info: pointer to light lightness client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] range_min: desired light lightness minimum value + * @param[in] range_max: desired light lightness maximum value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_lightness_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t range_min, uint16_t range_max, bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_LIGHTNESS_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_client.c new file mode 100644 index 00000000..f076e7bf --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_client.c @@ -0,0 +1,274 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lightness_client.c +* @brief Source file for light lightness client model. +* @details Data types and external functions declaration. +* @author bill +* @date 2017-12-22 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_lightness.h" + +static mesh_msg_send_cause_t light_lightness_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_lightness_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lightness_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_GET); + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lightness_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_lightness_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_lightness_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_lightness_set_t, trans_time); + } + msg.lightness = lightness; + msg.tid = tid; + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_lightness_linear_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lightness_linear_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_LINEAR_GET); + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lightness_linear_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_lightness_linear_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_lightness_linear_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_lightness_linear_set_t, trans_time); + } + msg.lightness = lightness; + msg.tid = tid; + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_lightness_last_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lightness_last_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_LAST_GET); + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lightness_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lightness_default_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_GET); + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lightness_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, bool ack) +{ + light_lightness_default_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK); + } + msg.lightness = lightness; + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lightness_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_lightness_range_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_RANGE_GET); + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_lightness_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t range_min, uint16_t range_max, bool ack) +{ + light_lightness_range_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET_UNACK); + } + msg.range_min = range_min; + msg.range_max = range_max; + return light_lightness_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool light_lightness_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_LIGHTNESS_STAT: + { + light_lightness_stat_t *pmsg = (light_lightness_stat_t *)pbuffer; + light_lightness_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_lightness = pmsg->present_lightness; + if (pmesh_msg->msg_len == sizeof(light_lightness_stat_t)) + { + status_data.optional = TRUE; + status_data.target_lightness = pmsg->target_lightness; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_LINEAR_STAT: + { + light_lightness_linear_stat_t *pmsg = (light_lightness_linear_stat_t *)pbuffer; + light_lightness_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.present_lightness = pmsg->present_lightness; + if (pmesh_msg->msg_len == sizeof(light_lightness_linear_stat_t)) + { + status_data.optional = TRUE; + status_data.target_lightness = pmsg->target_lightness; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_CLIENT_STATUS_LINEAR, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_LAST_STAT: + if (pmesh_msg->msg_len == sizeof(light_lightness_last_stat_t)) + { + light_lightness_last_stat_t *pmsg = (light_lightness_last_stat_t *)pbuffer; + light_lightness_client_status_last_t status_last = {pmesh_msg->src, pmsg->lightness}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_CLIENT_STATUS_LAST, + &status_last); + } + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_STAT: + if (pmesh_msg->msg_len == sizeof(light_lightness_default_stat_t)) + { + light_lightness_default_stat_t *pmsg = (light_lightness_default_stat_t *)pbuffer; + light_lightness_client_status_default_t status_default = {pmesh_msg->src, pmsg->lightness}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_CLIENT_STATUS_DEFAULT, + &status_default); + } + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_RANGE_STAT: + if (pmesh_msg->msg_len == sizeof(light_lightness_range_stat_t)) + { + light_lightness_range_stat_t *pmsg = (light_lightness_range_stat_t *)pbuffer; + light_lightness_client_status_range_t status_range = {pmesh_msg->src, pmsg->stat, pmsg->range_min, pmsg->range_max}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_CLIENT_STATUS_RANGE, + &status_range); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool light_lightness_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_LIGHTNESS_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = light_lightness_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_lightness_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_server.c new file mode 100644 index 00000000..828060cb --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_server.c @@ -0,0 +1,816 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lightness_server.c +* @brief Source file for light lightness server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-30 +* @version v1.0 +* ************************************************************************************* +*/ + +#include +#include "light_lightness.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +typedef struct +{ + uint8_t tid; + uint16_t target_lightness; + uint16_t target_lightness_linear; + generic_transition_time_t trans_time; + uint32_t delay_time; + generic_transition_time_t trans_time_linear; + uint32_t delay_time_linear; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; + uint32_t delay_pub_time_linear; +#endif +} light_lightness_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_lightness_process_result_t; + +static bool lightness_period_pub_enabled = TRUE; +static bool lightness_linear_period_pub_enabled = TRUE; + + +uint16_t light_lightness_linear_to_actual(uint16_t lightness_linear) +{ + return (uint16_t)(65535 * sqrt(lightness_linear / 65535.0)); +} + +uint16_t light_lightness_actual_to_linear(uint16_t lightness_actual) +{ + return (uint16_t)(lightness_actual / 65535.0 * lightness_actual); +} + +int16_t light_lightness_to_generic_level(uint16_t lightness) +{ + return lightness - 32768; +} + +uint16_t generic_level_to_light_lightness(int16_t level) +{ + return level + 32768; +} + +int16_t light_lightness_linear_to_generic_level(uint16_t lightness) +{ + return light_lightness_to_generic_level(light_lightness_linear_to_actual(lightness)); +} + +uint16_t generic_level_to_light_lightness_linear(int16_t level) +{ + return light_lightness_actual_to_linear(generic_level_to_light_lightness(level)); +} + +static mesh_msg_send_cause_t light_lightness_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t light_lightness_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t present_lightness, bool optional, uint16_t target_lightness, + generic_transition_time_t remaining_time, bool linear, uint32_t delay_time) +{ + light_lightness_stat_t msg; + if (linear) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_LINEAR_STAT); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_STAT); + } + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(light_lightness_stat_t); + msg.target_lightness = target_lightness; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(light_lightness_stat_t, target_lightness); + } + msg.present_lightness = present_lightness; + return light_lightness_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, + delay_time); +} + +static mesh_msg_send_cause_t light_lightness_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness, bool linear, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t remaining_time = {0, 0}; + ret = light_lightness_stat(pmodel_info, 0, 0, lightness, FALSE, lightness, remaining_time, linear, + delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_lightness_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness) +{ + return light_lightness_delay_publish(pmodel_info, lightness, FALSE, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_lightness_state_change_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness, bool linear, light_lightness_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_lightness_delay_publish(pmodel_info, lightness, linear, 0); + } +} +#endif + +mesh_msg_send_cause_t light_lightness_linear_publish(const mesh_model_info_p pmodel_info, + uint16_t lightness) +{ + return light_lightness_delay_publish(pmodel_info, lightness, TRUE, 0); +} + +static mesh_msg_send_cause_t light_lightness_last_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint32_t delay_time) +{ + light_lightness_last_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_LAST_STAT); + msg.lightness = lightness; + return light_lightness_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t light_lightness_default_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint32_t delay_time) +{ + light_lightness_default_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_STAT); + msg.lightness = lightness; + return light_lightness_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t light_lightness_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t range_min, uint16_t range_max, + uint32_t delay_time) +{ + light_lightness_range_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_LIGHTNESS_RANGE_STAT); + msg.stat = stat; + msg.range_min = range_min; + msg.range_max = range_max; + return light_lightness_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +static uint16_t get_present_lightness(const mesh_model_info_p pmodel_info, bool linear) +{ + light_lightness_server_get_t get_data = {0}; + uint32_t get_code = LIGHT_LIGHTNESS_SERVER_GET; + if (linear) + { + get_code = LIGHT_LIGHTNESS_SERVER_GET_LINEAR; + } + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, get_code, &get_data); + } + + return get_data.lightness; +} + +static int32_t light_lightness_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + int32_t ret = MODEL_SUCCESS; + light_lightness_server_set_t set_data; + light_lightness_info_t *plightness_info = pmodel_info->pargs; + if (NULL == plightness_info) + { + return 0; + } + + if (type == GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS) + { + set_data.lightness = plightness_info->target_lightness; + } + else + { + set_data.lightness = plightness_info->target_lightness_linear; + } + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + if (type == GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_SET, &set_data); + } + else + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_SET_LINEAR, &set_data); + } + } + + if (0 == remaining_time.num_steps) + { + bool linear; + uint32_t delay_rsp_time = 0; + if (GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS == type) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = plightness_info->delay_pub_time; +#endif + linear = FALSE; + } + else + { +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = plightness_info->delay_pub_time_linear; +#endif + linear = TRUE; + } + + uint16_t present_lightness = get_present_lightness(pmodel_info, linear); +#if MODEL_ENABLE_DELAY_MSG_RSP + light_lightness_delay_publish(pmodel_info, present_lightness, linear, delay_rsp_time); +#else + light_lightness_delay_publish(pmodel_info, present_lightness, linear, delay_rsp_time); +#endif + } + + return ret; +} + +static uint16_t light_lightness_process(const mesh_model_info_p pmodel_info, + uint16_t target_lightness, bool linear, + generic_transition_time_t trans_time, + light_lightness_process_result_t *presult) +{ + uint16_t lightness_before_set = 0; + uint16_t lightness_after_set = 0; + uint32_t trans_set_code = LIGHT_LIGHTNESS_SERVER_SET; + uint32_t trans_timer_code = GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS; + + if (linear) + { + trans_set_code = LIGHT_LIGHTNESS_SERVER_SET_LINEAR; + trans_timer_code = GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS_LINEAR; + } + + /* get lightness before set */ + lightness_before_set = get_present_lightness(pmodel_info, linear); + lightness_after_set = lightness_before_set; + + int32_t ret = MODEL_SUCCESS; + light_lightness_server_set_t trans_set_data; + trans_set_data.lightness = target_lightness; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, trans_set_code, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, trans_timer_code, trans_time, + light_lightness_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, trans_set_code, &trans_set_data); + } + } +#endif + } + else + { + /* get lightness after set */ + lightness_after_set = get_present_lightness(pmodel_info, linear); + } + + if (lightness_before_set != lightness_after_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + if (0 != target_lightness) + { + if (NULL != pmodel_info->model_data_cb) + { + if (linear) + { + target_lightness = light_lightness_linear_to_actual(target_lightness); + } + light_lightness_server_set_last_t set_last = {target_lightness}; + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_SET_LAST, &set_last); + } + } + + return lightness_after_set; +} + +static int32_t light_lightness_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS: + case DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS_LINEAR: + { + light_lightness_info_t *plightness_info = pmodel_info->pargs; + if (NULL == plightness_info) + { + return 0; + } + + light_lightness_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + bool linear; + generic_transition_time_t trans_time; + uint16_t target_lightness; + if (DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS == delay_type) + { + plightness_info->delay_time = 0; + linear = FALSE; + target_lightness = plightness_info->target_lightness; + trans_time = plightness_info->trans_time; + } + else + { + plightness_info->delay_time_linear = 0; + linear = TRUE; + target_lightness = plightness_info->target_lightness_linear; + trans_time = plightness_info->trans_time_linear; + } + + uint16_t present_lightness = light_lightness_process(pmodel_info, target_lightness, linear, + trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_rsp_time; + if (DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS == delay_type) + { + delay_rsp_time = plightness_info->delay_pub_time; + } + else + { + delay_rsp_time = plightness_info->delay_pub_time_linear; + } + light_lightness_delay_publish(pmodel_info, present_lightness, linear, delay_rsp_time); + } + } +#else + light_lightness_state_change_publish(pmodel_info, present_lightness, linear, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_lightness_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_LIGHTNESS_GET: + if (pmesh_msg->msg_len == sizeof(light_lightness_get_t)) + { + light_lightness_info_t *plightness_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (plightness_info->delay_time > 0) + { + remaining_time = plightness_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_lightness(pmodel_info, FALSE), + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + plightness_info->target_lightness, remaining_time, FALSE, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_SET: + case MESH_MSG_LIGHT_LIGHTNESS_SET_UNACK: + { + light_lightness_set_t *pmsg = (light_lightness_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_lightness_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_lightness_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_lightness_info_t *plightness_info = pmodel_info->pargs; + light_lightness_server_get_range_t range = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_GET_RANGE, &range); + } + if ((0 != range.range_min) && (0 != range.range_max)) + { + /* need to clamp lightness */ + plightness_info->target_lightness = CLAMP(pmsg->lightness, range.range_min, range.range_max); + } + else + { + plightness_info->target_lightness = pmsg->lightness; + } + plightness_info->tid = pmsg->tid; + plightness_info->trans_time = trans_time; + plightness_info->delay_time = delay_time; + + uint16_t present_lightness; + light_lightness_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_lightness = get_present_lightness(pmodel_info, FALSE); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS, delay_time, + light_lightness_delay_execution); + } + else + { + present_lightness = light_lightness_process(pmodel_info, plightness_info->target_lightness, + FALSE, trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LIGHTNESS_SET) + { + light_lightness_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_lightness, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + plightness_info->target_lightness, trans_time, FALSE, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LIGHTNESS_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_lightness_delay_publish(pmodel_info, present_lightness, FALSE, delay_pub_time); + } + } + else + { + plightness_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + light_lightness_state_change_publish(pmodel_info, present_lightness, FALSE, result); +#endif + } + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_LINEAR_GET: + if (pmesh_msg->msg_len == sizeof(light_lightness_linear_get_t)) + { + light_lightness_info_t *plightness_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (plightness_info->delay_time_linear) + { + remaining_time = plightness_info->trans_time_linear; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, + GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS_LINEAR); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_lightness(pmodel_info, TRUE), + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + plightness_info->target_lightness_linear, remaining_time, TRUE, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET: + case MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET_UNACK: + { + light_lightness_linear_set_t *pmsg = (light_lightness_linear_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_lightness_linear_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_lightness_linear_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_lightness_info_t *plightness_info = pmodel_info->pargs; + plightness_info->target_lightness_linear = pmsg->lightness; + plightness_info->tid = pmsg->tid; + plightness_info->trans_time_linear = trans_time; + plightness_info->delay_time_linear = delay_time; + + uint16_t present_linear; + light_lightness_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_linear = get_present_lightness(pmodel_info, TRUE); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS_LINEAR, delay_time, + light_lightness_delay_execution); + } + else + { + present_linear = light_lightness_process(pmodel_info, + plightness_info->target_lightness_linear, + TRUE, trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET) + { + light_lightness_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_linear, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + plightness_info->target_lightness_linear, trans_time, TRUE, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_LIGHTNESS_LINEAR_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_lightness_delay_publish(pmodel_info, present_linear, TRUE, delay_pub_time); + } + } + else + { + plightness_info->delay_pub_time_linear = delay_msg_get_trans_delay(delay_time, trans_time, + delay_rsp_time, FALSE, ack); + } +#else + light_lightness_state_change_publish(pmodel_info, present_linear, TRUE, result); +#endif + } + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_LAST_GET: + if (pmesh_msg->msg_len == sizeof(light_lightness_last_get_t)) + { + light_lightness_server_get_t last_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_GET_LAST, + &last_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_last_stat(pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, last_data.lightness, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_GET: + if (pmesh_msg->msg_len == sizeof(light_lightness_default_get_t)) + { + light_lightness_server_get_t default_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_GET_DEFAULT, + &default_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_default_stat(pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, default_data.lightness, delay_rsp_time); + + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_RANGE_GET: + if (pmesh_msg->msg_len == sizeof(light_lightness_range_get_t)) + { + light_lightness_server_get_range_t range_data = {0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_LIGHTNESS_SERVER_GET_RANGE, + &range_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_range_stat(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + GENERIC_STAT_SUCCESS, range_data.range_min, range_data.range_max, + delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_lightness_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + generic_transition_time_t remaining_time = {0, 0}; + if (lightness_period_pub_enabled) + { + light_lightness_stat(pmodel_info, 0, 0, get_present_lightness(pmodel_info, FALSE), FALSE, 0, + remaining_time, FALSE, 0); + } + + if (lightness_linear_period_pub_enabled) + { + light_lightness_stat(pmodel_info, 0, 0, get_present_lightness(pmodel_info, TRUE), FALSE, 0, + remaining_time, TRUE, 0); + } + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_lightness_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_lightness_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS); + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_LIGHTNESS_LINEAR); + /* stop step transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS); + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_LIGHTNESS_LINEAR); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +void light_lightness_period_pub_enable(bool lightness, bool lightness_linear) +{ + lightness_period_pub_enabled = lightness; + lightness_linear_period_pub_enabled = lightness_linear; +} + +bool light_lightness_server_reg(uint8_t element_index, mesh_model_info_t *pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_LIGHTNESS_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_lightness_info_t *plightness_info = plt_malloc(sizeof(light_lightness_info_t), + RAM_TYPE_DATA_ON); + if (NULL == plightness_info) + { + printe("light_lightness_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(plightness_info, 0, sizeof(light_lightness_info_t)); + pmodel_info->pargs = plightness_info; + + pmodel_info->model_receive = light_lightness_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_lightness_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_lightness_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_lightness_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_setup_server.c new file mode 100644 index 00000000..def3e2c3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_setup_server.c @@ -0,0 +1,160 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_lightness_setup_server.c +* @brief Source file for light lightness setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-7-30 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_lightness.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +extern mesh_msg_send_cause_t light_lightness_default_stat(mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t lightness, uint32_t delay_time); +extern mesh_msg_send_cause_t light_lightness_range_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t stat, uint16_t range_min, uint16_t range_max, + uint32_t delay_time); + +#if 0 +typedef struct +{ + uint8_t tid; + uint16_t target_lightness; + uint16_t target_lightness_linear; + generic_transition_time_t trans_time; + uint32_t delay_time; + generic_transition_time_t trans_time_linear; + uint32_t delay_time_linear; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; + uint32_t delay_pub_time_linear; +#endif +} light_lightness_info_t; +#endif + +static bool light_lightness_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET: + case MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_lightness_default_set_t)) + { + light_lightness_default_set_p pmsg = (light_lightness_default_set_p)pbuffer; + light_lightness_server_set_default_t set_default = {pmsg->lightness}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_SERVER_SET_DEFAULT, + &set_default); + } + + if (MESH_MSG_LIGHT_LIGHTNESS_DEFAULT_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_default_stat(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->lightness, delay_rsp_time); + } + + } + break; + case MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET: + case MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_lightness_range_set_t)) + { + light_lightness_range_set_p pmsg = (light_lightness_range_set_p)pbuffer; + if ((pmsg->range_min < pmsg->range_max) && + (0 != pmsg->range_min) && + (0 != pmsg->range_max)) + { + light_lightness_server_set_range_t set_range = {pmsg->range_min, pmsg->range_max}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_LIGHTNESS_SERVER_SET_RANGE, + &set_range); + } + + if (MESH_MSG_LIGHT_LIGHTNESS_RANGE_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_lightness_range_stat(pmesh_msg->pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, GENERIC_STAT_SUCCESS, + pmsg->range_min, pmsg->range_max, delay_rsp_time); + } + } + + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_lightness_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_lightness_setup_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_lightness_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_LIGHTNESS_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + pmodel_info->pargs = plt_malloc(sizeof(light_lightness_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("light_lightness_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(light_lightness_info_t)); +#endif + pmodel_info->model_receive = light_lightness_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_lightness_setup_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_lightness_setup_server_deinit; +#endif + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl.h new file mode 100644 index 00000000..afd30659 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl.h @@ -0,0 +1,419 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_xyl.h +* @brief Head file for light xyl models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-09 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _LIGHT_XYL_H +#define _LIGHT_XYL_H + +#include "mesh_api.h" +#include "generic_types.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_XYL + * @{ + */ + +/** + * @defgroup LIGHT_XYL_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_LIGHT_XYL_GET 0x8283 +#define MESH_MSG_LIGHT_XYL_SET 0x8284 +#define MESH_MSG_LIGHT_XYL_SET_UNACK 0x8285 +#define MESH_MSG_LIGHT_XYL_STATUS 0x8286 +#define MESH_MSG_LIGHT_XYL_TARGET_GET 0x8287 +#define MESH_MSG_LIGHT_XYL_TARGET_STATUS 0x8288 +#define MESH_MSG_LIGHT_XYL_DEFAULT_GET 0x8289 +#define MESH_MSG_LIGHT_XYL_DEFAULT_STATUS 0x828A +#define MESH_MSG_LIGHT_XYL_RANGE_GET 0x828B +#define MESH_MSG_LIGHT_XYL_RANGE_STATUS 0x828C +#define MESH_MSG_LIGHT_XYL_DEFAULT_SET 0x828D +#define MESH_MSG_LIGHT_XYL_DEFAULT_SET_UNACK 0x828E +#define MESH_MSG_LIGHT_XYL_RANGE_SET 0x828F +#define MESH_MSG_LIGHT_XYL_RANGE_SET_UNACK 0x8290 +/** @} */ + +/** + * @defgroup LIGHT_XYL_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_LIGHT_XYL_SERVER 0x130CFFFF +#define MESH_MODEL_LIGHT_XYL_SETUP_SERVER 0x130DFFFF +#define MESH_MODEL_LIGHT_XYL_CLIENT 0x130EFFFF +/** @} */ + +/** + * @defgroup LIGHT_XYL_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint16_t xyl_lightness; + uint16_t xyl_x; + uint16_t xyl_y; +} _PACKED4_ light_xyl_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_GET)]; +} _PACKED4_ light_xyl_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_SET)]; + light_xyl_t xyl; + uint8_t tid; + generic_transition_time_t trans_time; + uint8_t delay; +} _PACKED4_ light_xyl_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_STATUS)]; + light_xyl_t xyl; + generic_transition_time_t remaining_time; +} _PACKED4_ light_xyl_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_TARGET_GET)]; +} _PACKED4_ light_xyl_target_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_TARGET_STATUS)]; + light_xyl_t xyl; + generic_transition_time_t remaining_time; +} _PACKED4_ light_xyl_target_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_DEFAULT_GET)]; +} _PACKED4_ light_xyl_default_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_DEFAULT_SET)]; + light_xyl_t xyl; +} _PACKED4_ light_xyl_default_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_DEFAULT_STATUS)]; + light_xyl_t xyl; +} _PACKED4_ light_xyl_default_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_RANGE_GET)]; +} _PACKED4_ light_xyl_range_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_RANGE_SET)]; + uint16_t xyl_x_range_min; + uint16_t xyl_x_range_max; + uint16_t xyl_y_range_min; + uint16_t xyl_y_range_max; +} _PACKED4_ light_xyl_range_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_XYL_RANGE_SET)]; + uint8_t status_code; + uint16_t xyl_x_range_min; + uint16_t xyl_x_range_max; + uint16_t xyl_y_range_min; + uint16_t xyl_y_range_max; +} _PACKED4_ light_xyl_range_status_t; +/** @} */ + +/** + * @defgroup LIGHT_XYL_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_LIGHT_XYL 0 +#define DELAY_EXECUTION_TYPE_LIGHT_XYL 0 +/** @} */ + + +/** + * @defgroup LIGHT_XYL_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_XYL_SERVER_GET 0 //!< @ref light_xyl_server_get_t +#define LIGHT_XYL_SERVER_GET_RANGE 1 //!< @ref light_xyl_server_get_range_t +#define LIGHT_XYL_SERVER_GET_DEFAULT 2 //!< @ref light_xyl_server_get_default_t +#define LIGHT_XYL_SERVER_GET_DEFAULT_TRANSITION_TIME 3 //!< @ref light_xyl_server_get_default_transition_time_t +#define LIGHT_XYL_SERVER_SET 4 //!< @ref light_xyl_server_set_t +#define LIGHT_XYL_SERVER_SET_DEFAULT 5 //!< @ref light_xyl_server_set_default_t +#define LIGHT_XYL_SERVER_SET_RANGE 6 //!< @ref light_xyl_server_set_range_t + +typedef light_xyl_t light_xyl_server_get_t; + +typedef struct +{ + uint16_t xyl_x_range_min; + uint16_t xyl_x_range_max; + uint16_t xyl_y_range_min; + uint16_t xyl_y_range_max; +} light_xyl_server_get_range_t; + +typedef light_xyl_t light_xyl_server_get_default_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} light_xyl_server_get_default_transition_time_t; + +typedef struct +{ + light_xyl_t xyl; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} light_xyl_server_set_t; + +typedef light_xyl_t light_xyl_server_set_default_t; + +typedef struct +{ + uint16_t xyl_x_range_min; + uint16_t xyl_x_range_max; + uint16_t xyl_y_range_min; + uint16_t xyl_y_range_max; +} light_xyl_server_set_range_t; +/** @} */ + +/** + * @defgroup LIGHT_XYL_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define LIGHT_XYL_CLIENT_STATUS 0 //!< @ref light_xyl_client_status_t +#define LIGHT_XYL_CLIENT_STATUS_TARGET 1 //!< @ref light_xyl_client_status_t +#define LIGHT_XYL_CLIENT_STATUS_DEFAULT 2 //!< @ref light_xyl_client_status_default_t +#define LIGHT_XYL_CLIENT_STATUS_RANGE 3 //!< @ref light_xyl_client_status_range_t + +typedef struct +{ + uint16_t src; + light_xyl_t xyl; + bool optional; + generic_transition_time_t remaining_time; +} light_xyl_client_status_t; + +typedef struct +{ + uint16_t src; + light_xyl_t xyl; +} light_xyl_client_status_default_t; + +typedef struct +{ + uint16_t src; + generic_stat_t status; + uint16_t xyl_x_range_min; + uint16_t xyl_x_range_max; + uint16_t xyl_y_range_min; + uint16_t xyl_y_range_max; +} light_xyl_client_status_range_t; +/** @} */ + + +/** + * @defgroup LIGHT_XYL_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register light xyl server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light xyl server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_xyl_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register light xyl setup server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light xyl setup server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool light_xyl_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish light xyl + * @param[in] pmodel_info: pointer to light xyl server model context + * @param[in] xyl: xyl need to publish + * @return publish status + */ +mesh_msg_send_cause_t light_xyl_publish(const mesh_model_info_p pmodel_info, light_xyl_t xyl); + +/** + * @brief convert light xyl x to cie1931 x + * @param[in] xyl_x: light xyl_x + * @return cie1931 x value + */ +double light_xyl_x_to_cie1931_x(uint16_t xyl_x); + +/** + * @brief convert cie1931 x to light xyl x + * @param[in] cie1931_x: cie1931 x value + * @return light xyl x value + */ +uint16_t light_cie1931_x_to_xyl_x(double cie1931_x); + +/** + * @brief convert light xyl y to cie1931 y + * @param[in] xyl_y: light xyl_y + * @return cie1931 y value + */ +double light_xyl_y_to_cie1931_y(uint16_t xyl_y); + +/** + * @brief convert cie1931 y to light xyl y + * @param[in] cie1931_y: cie1931 y value + * @return light xyl y value + */ +uint16_t light_cie1931_y_to_xyl_y(double cie1931_y); + +/** + * @brief convert light intensity to xyl lightness + * @param[in] intensity: light intensity + * @return xyl lightness value + */ +uint16_t light_intensity_to_xyl_lightness(uint16_t intensity); + +/** + * @brief convert xyl lightness to light intensity + * @param[in] lightness: xyl lightness + * @return light internsity value + */ +uint16_t light_xyl_lightness_to_internsity(uint16_t lightness); +/** @} */ + +/** + * @defgroup LIGHT_LIGHTNESS_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ +/** + * @brief register light xyl client model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to light xyl client model context + * @retval true: register success + * @retval false: register failed + */ +bool light_xyl_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get light xyl value + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_xyl_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light xyl value + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] xyl: desired xyl + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_xyl_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, uint8_t tid, + bool optional, generic_transition_time_t trans_time, uint8_t delay, bool ack); + +/** + * @brief get light xyl target value + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_xyl_target_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get light xyl default value + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_xyl_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set default light xyl value + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] xyl: desired default xyl value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_xyl_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, bool ack); + +/** + * @brief get light xyl range + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t light_xyl_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set light xyl range + * @param[in] pmodel_info: pointer to light xyl client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] xyl_x_range_min: desired light xyl_x minimum value + * @param[in] xyl_x_range_max: desired light xyl_x maximum value + * @param[in] xyl_y_range_min: desired light xyl_y minimum value + * @param[in] xyl_y_range_max: desired light xyl_y maximum value + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t light_xyl_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t xyl_x_range_min, uint16_t xyl_x_range_max, + uint16_t xyl_y_range_min, uint16_t xyl_y_range_max, bool ack); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_XYL_H */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_client.c new file mode 100644 index 00000000..544e6dcd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_client.c @@ -0,0 +1,228 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_xyl_client.c +* @brief Source file for light xyl client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-11 +* @version v1.0 +* ************************************************************************************* +*/ +#include "light_xyl.h" + +static mesh_msg_send_cause_t light_xyl_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_xyl_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_xyl_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_GET); + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_xyl_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, uint8_t tid, + bool optional, generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + light_xyl_set_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_SET_UNACK); + } + + if (optional) + { + len = sizeof(light_xyl_set_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(light_xyl_set_t, trans_time); + } + msg.xyl = xyl; + msg.tid = tid; + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); +} + +mesh_msg_send_cause_t light_xyl_target_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_xyl_target_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_TARGET_GET); + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_xyl_default_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_xyl_default_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_DEFAULT_GET); + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_xyl_default_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, bool ack) +{ + light_xyl_default_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_DEFAULT_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_DEFAULT_SET_UNACK); + } + msg.xyl = xyl; + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_xyl_range_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_xyl_range_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_RANGE_GET); + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t light_xyl_range_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t xyl_x_range_min, uint16_t xyl_x_range_max, + uint16_t xyl_y_range_min, uint16_t xyl_y_range_max, bool ack) +{ + light_xyl_range_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_RANGE_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_RANGE_SET_UNACK); + } + msg.xyl_x_range_min = xyl_x_range_min; + msg.xyl_x_range_max = xyl_x_range_max; + msg.xyl_y_range_min = xyl_y_range_min; + msg.xyl_y_range_max = xyl_y_range_max; + return light_xyl_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool light_xyl_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_XYL_STATUS: + { + light_xyl_status_t *pmsg = (light_xyl_status_t *)pbuffer; + light_xyl_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.xyl = pmsg->xyl; + if (pmesh_msg->msg_len == sizeof(light_xyl_status_t)) + { + status_data.optional = TRUE; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_XYL_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_XYL_TARGET_STATUS: + { + light_xyl_target_status_t *pmsg = (light_xyl_target_status_t *)pbuffer; + light_xyl_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.xyl = pmsg->xyl; + if (pmesh_msg->msg_len == sizeof(light_xyl_target_status_t)) + { + status_data.optional = TRUE; + status_data.remaining_time = pmsg->remaining_time; + } + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_XYL_CLIENT_STATUS_TARGET, + &status_data); + } + } + break; + case MESH_MSG_LIGHT_XYL_DEFAULT_STATUS: + if (pmesh_msg->msg_len == sizeof(light_xyl_default_status_t)) + { + light_xyl_default_status_t *pmsg = (light_xyl_default_status_t *)pbuffer; + light_xyl_client_status_default_t default_data; + default_data.src = pmesh_msg->src; + default_data.xyl = pmsg->xyl; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_XYL_CLIENT_STATUS_DEFAULT, + &default_data); + } + } + break; + case MESH_MSG_LIGHT_XYL_RANGE_STATUS: + if (pmesh_msg->msg_len == sizeof(light_xyl_range_status_t)) + { + light_xyl_range_status_t *pmsg = (light_xyl_range_status_t *)pbuffer; + light_xyl_client_status_range_t range_data = {pmesh_msg->src, pmsg->status_code, pmsg->xyl_x_range_min, pmsg->xyl_x_range_max, pmsg->xyl_y_range_min, pmsg->xyl_y_range_max}; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, + LIGHT_XYL_CLIENT_STATUS_RANGE, + &range_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool light_xyl_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_XYL_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = light_xyl_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_xyl_client_reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_server.c new file mode 100644 index 00000000..5e5bfc62 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_server.c @@ -0,0 +1,626 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_xyl_server.c +* @brief Source file for light xyl server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-09 +* @version v1.0 +* ************************************************************************************* +*/ + +#include +#include "light_xyl.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +typedef struct +{ + uint8_t tid; + light_xyl_t target_xyl; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_xyl_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} light_xyl_process_result_t; + +double light_xyl_x_to_cie1931_x(uint16_t xyl_x) +{ + return xyl_x / 65535.0; +} + +uint16_t light_cie1931_x_to_xyl_x(double cie1931_x) +{ + return cie1931_x * 65535; +} + +double light_xyl_y_to_cie1931_y(uint16_t xyl_y) +{ + return xyl_y / 65535.0; +} + +uint16_t light_cie1931_y_to_xyl_y(double cie1931_y) +{ + return cie1931_y * 65535; +} + +uint16_t light_intensity_to_xyl_lightness(uint16_t intensity) +{ + return (uint16_t)(65535 * sqrt(intensity / 65535.0)); +} + +uint16_t light_xyl_lightness_to_internsity(uint16_t lightness) +{ + return (uint16_t)(lightness / 65535.0 * lightness); +} + +static mesh_msg_send_cause_t light_xyl_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t light_xyl_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, + bool optional, generic_transition_time_t remaining_time, + uint32_t delay_time) +{ + light_xyl_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_STATUS); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(light_xyl_status_t); + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(light_xyl_status_t, remaining_time); + } + msg.xyl = xyl; + return light_xyl_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, + delay_time); +} + +static mesh_msg_send_cause_t light_xyl_target_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, + bool optional, generic_transition_time_t remaining_time, + uint32_t delay_time) +{ + light_xyl_target_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_TARGET_STATUS); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(light_xyl_target_status_t); + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(light_xyl_target_status_t, remaining_time); + } + msg.xyl = xyl; + return light_xyl_server_send(pmodel_info, dst, (uint8_t *)&msg, msg_len, app_key_index, + delay_time); +} + +static mesh_msg_send_cause_t light_xyl_delay_publish(const mesh_model_info_p pmodel_info, + light_xyl_t xyl, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t remaining_time = {0, 0}; + ret = light_xyl_status(pmodel_info, 0, 0, xyl, FALSE, remaining_time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t light_xyl_publish(const mesh_model_info_p pmodel_info, light_xyl_t xyl) +{ + return light_xyl_delay_publish(pmodel_info, xyl, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void light_xyl_state_change_publish(const mesh_model_info_p pmodel_info, light_xyl_t xyl, + light_xyl_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + light_xyl_delay_publish(pmodel_info, xyl, 0); + } +} +#endif + +mesh_msg_send_cause_t light_xyl_default_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, uint32_t delay_time) +{ + light_xyl_default_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_DEFAULT_STATUS); + msg.xyl = xyl; + return light_xyl_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t light_xyl_range_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t status, uint16_t xyl_x_range_min, uint16_t xyl_x_range_max, + uint16_t xyl_y_range_min, uint16_t xyl_y_range_max, uint32_t delay_time) +{ + light_xyl_range_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_XYL_RANGE_STATUS); + msg.status_code = status; + msg.xyl_x_range_min = xyl_x_range_min; + msg.xyl_x_range_max = xyl_x_range_max; + msg.xyl_y_range_min = xyl_y_range_min; + msg.xyl_y_range_max = xyl_y_range_max; + return light_xyl_server_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index, + delay_time); +} + +static light_xyl_t get_present_xyl(const mesh_model_info_p pmodel_info) +{ + light_xyl_server_get_t get_data = {0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_GET, &get_data); + } + + return get_data; +} + +static int32_t light_xyl_trans_step_change(const mesh_model_info_p pmodel_info, + uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = MODEL_SUCCESS; + light_xyl_server_set_t set_data; + light_xyl_info_t *pxyl_info = pmodel_info->pargs; + if (NULL == pxyl_info) + { + return 0; + } + + set_data.xyl = pxyl_info->target_xyl; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_SET, &set_data); + } + + if (0 == remaining_time.num_steps) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = pxyl_info->delay_pub_time; +#endif + light_xyl_t present_xyl = get_present_xyl(pmodel_info); + light_xyl_delay_publish(pmodel_info, present_xyl, delay_rsp_time); + } + + return ret; +} + +static light_xyl_t light_xyl_process(const mesh_model_info_p pmodel_info, + light_xyl_t target_xyl, + generic_transition_time_t trans_time, + light_xyl_process_result_t *presult) +{ + light_xyl_t xyl_before_set = {0, 0, 0}; + light_xyl_t xyl_after_set = {0, 0, 0}; + + /* get xyl before set */ + xyl_before_set = get_present_xyl(pmodel_info); + xyl_after_set = xyl_before_set; + + int32_t ret = MODEL_SUCCESS; + light_xyl_server_set_t trans_set_data; + trans_set_data.xyl = target_xyl; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_SET, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { + if (NULL != presult) + { + presult->use_transition = TRUE; + } + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_XYL, trans_time, + light_xyl_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_XYL, &trans_set_data); + } + } +#endif + } + else + { + /* get xyl after set */ + xyl_after_set = get_present_xyl(pmodel_info); + } + + if ((xyl_before_set.xyl_lightness != xyl_after_set.xyl_lightness) && + (xyl_before_set.xyl_x != xyl_after_set.xyl_x) && + (xyl_before_set.xyl_y != xyl_after_set.xyl_y)) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return xyl_after_set; +} + +static int32_t light_xyl_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_LIGHT_XYL: + { + light_xyl_info_t *pxyl_info = pmodel_info->pargs; + if (NULL == pxyl_info) + { + return 0; + } + + light_xyl_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + generic_transition_time_t trans_time; + light_xyl_t target_xyl; + pxyl_info->delay_time = 0; + target_xyl = pxyl_info->target_xyl; + trans_time = pxyl_info->trans_time; + + light_xyl_t present_xyl = light_xyl_process(pmodel_info, target_xyl, trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_rsp_time = pxyl_info->delay_pub_time; + light_xyl_delay_publish(pmodel_info, present_xyl, delay_rsp_time); + } + } +#else + light_xyl_state_change_publish(pmodel_info, present_xyl, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool light_xyl_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_XYL_GET: + if (pmesh_msg->msg_len == sizeof(light_xyl_get_t)) + { + light_xyl_info_t *pxyl_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (pxyl_info->delay_time > 0) + { + remaining_time = pxyl_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_XYL); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_xyl_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_present_xyl(pmodel_info), + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_XYL_SET: + case MESH_MSG_LIGHT_XYL_SET_UNACK: + { + light_xyl_set_t *pmsg = (light_xyl_set_t *)pbuffer; + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(light_xyl_set_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else if (pmesh_msg->msg_len == sizeof(light_xyl_set_t)) + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + light_xyl_info_t *pxyl_info = pmodel_info->pargs; + light_xyl_server_get_range_t range = {0, 0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_GET_RANGE, &range); + } + + pxyl_info->target_xyl.xyl_lightness = pmsg->xyl.xyl_lightness; + if ((0 != range.xyl_x_range_min) && (0 != range.xyl_x_range_max)) + { + /* need to clamp xyl_x */ + pxyl_info->target_xyl.xyl_x = CLAMP(pmsg->xyl.xyl_x, range.xyl_x_range_min, range.xyl_x_range_max); + } + else + { + pxyl_info->target_xyl.xyl_x = pmsg->xyl.xyl_x; + } + if ((0 != range.xyl_y_range_min) && (0 != range.xyl_y_range_max)) + { + /* need to clamp xyl_y */ + pxyl_info->target_xyl.xyl_y = CLAMP(pmsg->xyl.xyl_y, range.xyl_y_range_min, range.xyl_y_range_max); + } + else + { + pxyl_info->target_xyl.xyl_y = pmsg->xyl.xyl_y; + } + pxyl_info->tid = pmsg->tid; + pxyl_info->trans_time = trans_time; + pxyl_info->delay_time = delay_time; + + light_xyl_t present_xyl; + light_xyl_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + if (delay_time > 0) + { + result.use_transition = TRUE; + present_xyl = get_present_xyl(pmodel_info); + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_XYL, delay_time, + light_xyl_delay_execution); + } + else + { + present_xyl = light_xyl_process(pmodel_info, pxyl_info->target_xyl, + trans_time, &result); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (pmesh_msg->access_opcode == MESH_MSG_LIGHT_XYL_SET) + { + light_xyl_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + present_xyl, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_LIGHT_XYL_SET_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + light_xyl_delay_publish(pmodel_info, present_xyl, delay_pub_time); + } + } + else + { + pxyl_info->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, + FALSE, ack); + } +#else + light_xyl_state_change_publish(pmodel_info, present_xyl, result); +#endif + } + } + break; + case MESH_MSG_LIGHT_XYL_TARGET_GET: + if (pmesh_msg->msg_len == sizeof(light_xyl_target_get_t)) + { + light_xyl_info_t *pxyl_info = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (pxyl_info->delay_time > 0) + { + remaining_time = pxyl_info->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_XYL); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_xyl_target_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pxyl_info->target_xyl, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_LIGHT_XYL_DEFAULT_GET: + if (pmesh_msg->msg_len == sizeof(light_xyl_default_get_t)) + { + light_xyl_server_get_default_t default_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_GET_DEFAULT, + &default_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_xyl_default_status(pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, default_data, delay_rsp_time); + + } + break; + case MESH_MSG_LIGHT_XYL_RANGE_GET: + if (pmesh_msg->msg_len == sizeof(light_xyl_range_get_t)) + { + light_xyl_server_get_range_t range_data = {0, 0, 0, 0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, LIGHT_XYL_SERVER_GET_RANGE, + &range_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_xyl_range_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + GENERIC_STAT_SUCCESS, range_data.xyl_x_range_min, range_data.xyl_x_range_max, + range_data.xyl_y_range_min, range_data.xyl_y_range_max, + delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t light_xyl_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + generic_transition_time_t remaining_time = {0, 0}; + light_xyl_status(pmodel_info, 0, 0, get_present_xyl(pmodel_info), FALSE, + remaining_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_xyl_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_xyl_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_LIGHT_XYL); + /* stop step transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_LIGHT_XYL); + + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_xyl_server_reg(uint8_t element_index, mesh_model_info_t *pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_XYL_SERVER; + if (NULL == pmodel_info->model_receive) + { + light_xyl_info_t *pxyl_info = plt_malloc(sizeof(light_xyl_info_t), RAM_TYPE_DATA_ON); + if (NULL == pxyl_info) + { + printe("light_xyl_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pxyl_info, 0, sizeof(light_xyl_info_t)); + pmodel_info->pargs = pxyl_info; + + pmodel_info->model_receive = light_xyl_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_xyl_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_xyl_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = light_xyl_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_setup_server.c new file mode 100644 index 00000000..db434f9a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_setup_server.c @@ -0,0 +1,152 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_xyl_setup_server.c +* @brief Source file for light xyl setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2019-07-09 +* @version v1.0 +* ************************************************************************************* +*/ +#include "light_xyl.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#if 0 +typedef struct +{ + uint8_t tid; + light_xyl_t target_xyl; + generic_transition_time_t trans_time; + uint32_t delay_time; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} light_xyl_info_t; +#endif + +extern mesh_msg_send_cause_t light_xyl_default_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, light_xyl_t xyl, uint32_t delay_time); +extern mesh_msg_send_cause_t light_xyl_range_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, generic_stat_t status, uint16_t xyl_x_range_min, uint16_t xyl_x_range_max, + uint16_t xyl_y_range_min, uint16_t xyl_y_range_max, uint32_t delay_time); + +static bool light_xyl_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_XYL_DEFAULT_SET: + case MESH_MSG_LIGHT_XYL_DEFAULT_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_xyl_default_set_t)) + { + light_xyl_default_set_t *pmsg = (light_xyl_default_set_t *)pbuffer; + light_xyl_server_set_default_t set_default = pmsg->xyl; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_XYL_SERVER_SET_DEFAULT, + &set_default); + } + + if (MESH_MSG_LIGHT_XYL_DEFAULT_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_xyl_default_status(pmesh_msg->pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->xyl, delay_rsp_time); + } + } + break; + case MESH_MSG_LIGHT_XYL_RANGE_SET: + case MESH_MSG_LIGHT_XYL_RANGE_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_xyl_range_set_t)) + { + light_xyl_range_set_t *pmsg = (light_xyl_range_set_t *)pbuffer; + if ((pmsg->xyl_x_range_min < pmsg->xyl_x_range_max) && + (pmsg->xyl_y_range_min < pmsg->xyl_y_range_max)) + { + light_xyl_server_set_range_t set_range = {pmsg->xyl_x_range_min, pmsg->xyl_x_range_max, pmsg->xyl_y_range_min, pmsg->xyl_y_range_max}; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, LIGHT_XYL_SERVER_SET_RANGE, + &set_range); + } + + if (MESH_MSG_LIGHT_XYL_RANGE_SET == pmesh_msg->access_opcode) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + light_xyl_range_status(pmesh_msg->pmodel_info, pmesh_msg->src, + pmesh_msg->app_key_index, GENERIC_STAT_SUCCESS, + pmsg->xyl_x_range_min, pmsg->xyl_x_range_max, + pmsg->xyl_y_range_min, pmsg->xyl_y_range_max, delay_rsp_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void light_xyl_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == light_xyl_setup_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool light_xyl_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_LIGHT_XYL_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + light_xyl_info_t *pxyl_info = plt_malloc(sizeof(light_xyl_info_t), RAM_TYPE_DATA_ON); + if (NULL == pxyl_info) + { + printe("light_xyl_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pxyl_info, 0, sizeof(light_xyl_info_t)); +#endif + pmodel_info->model_receive = light_xyl_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("light_xyl_setup_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = light_xyl_setup_server_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_fsm.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_fsm.c new file mode 100644 index 00000000..73b20c69 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_fsm.c @@ -0,0 +1,176 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file model_fsm.c +* @brief Source file for model state machine +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-4-20 +* @version v1.0 +* ************************************************************************************* +*/ +#include "model_fsm.h" +#include "mesh_api.h" + +typedef enum +{ + MODEL_FSM_STATE_IDLE, + MODEL_FSM_STATE_RUNNING, + MODEL_FSM_STATE_PAUSE, +} model_fsm_state_t; + +struct _model_fsm_t +{ + model_fsm_state_t fsm_state; + const model_fsm_table_t *ptable; + uint32_t table_len; + uint32_t init_state; + uint32_t cur_state; +}; + + +model_fsm_t *model_fsm_reg(const model_fsm_table_t *ptable, uint32_t table_len, uint32_t init_state) +{ + model_fsm_t *pfsm = plt_malloc(sizeof(struct _model_fsm_t), RAM_TYPE_DATA_ON); + if (NULL == pfsm) + { + printe("model_fsm_reg: register fsm failed, out of memory"); + return NULL; + } + pfsm->fsm_state = MODEL_FSM_STATE_IDLE; + pfsm->ptable = ptable; + pfsm->table_len = table_len; + pfsm->cur_state = init_state; + pfsm->init_state = init_state; + + return pfsm; +} + +void model_fsm_unreg(model_fsm_t *pfsm) +{ + plt_free(pfsm, RAM_TYPE_DATA_ON); +} + +void model_fsm_run(model_fsm_t *pfsm) +{ + if (MODEL_FSM_STATE_RUNNING == pfsm->fsm_state) + { + printi("model_fsm_run: state machine is already running"); + return ; + } + + printi("model_fsm_run: fsm state %d->%d", pfsm->fsm_state, MODEL_FSM_STATE_RUNNING); + uint32_t prev_state = pfsm->fsm_state; + pfsm->fsm_state = MODEL_FSM_STATE_RUNNING; + if (MODEL_FSM_STATE_IDLE == prev_state) + { + /* execute state enter */ + for (uint32_t i = 0; i < pfsm->table_len; ++i) + { + if (pfsm->cur_state == pfsm->ptable[i].state) + { + if (NULL != pfsm->ptable[i].state_enter) + { + pfsm->ptable[i].state_enter(); + } + } + } + } +} + +void model_fsm_pause(model_fsm_t *pfsm) +{ + if (MODEL_FSM_STATE_RUNNING == pfsm->fsm_state) + { + printi("model_fsm_pause: fsm state %d->%d", pfsm->fsm_state, MODEL_FSM_STATE_PAUSE); + pfsm->fsm_state = MODEL_FSM_STATE_PAUSE; + } +} + +void model_fsm_stop(model_fsm_t *pfsm) +{ + if (MODEL_FSM_STATE_IDLE == pfsm->fsm_state) + { + printi("model_fsm_stop: state machine is not running"); + return ; + } + + printi("model_fsm_pause: fsm stop, state %d->%d", pfsm->cur_state, pfsm->init_state); + pfsm->fsm_state = MODEL_FSM_STATE_IDLE; + uint32_t prev_state = pfsm->cur_state; + pfsm->cur_state = pfsm->init_state; + /* execute state exit */ + for (uint32_t i = 0; i < pfsm->table_len; ++i) + { + if (prev_state == pfsm->ptable[i].state) + { + if (NULL != pfsm->ptable[i].state_exit) + { + pfsm->ptable[i].state_exit(); + } + } + } +} + +void model_fsm_handle_event(model_fsm_t *pfsm, uint32_t event) +{ + if (MODEL_FSM_STATE_RUNNING != pfsm->fsm_state) + { + printw("model_fsm_handle_event: state machine is not running(%d)", pfsm->fsm_state); + return ; + } + + printi("model_fsm_handle_event: state %d, event %d", pfsm->cur_state, event); + bool state_transfer = false; + for (uint32_t index_table = 0; index_table < pfsm->table_len; ++index_table) + { + if (pfsm->cur_state == pfsm->ptable[index_table].state) + { + for (uint32_t index_event = 0; index_event < pfsm->ptable[index_table].event_group_len; + ++index_event) + { + if (pfsm->ptable[index_table].pevent_group[index_event].event == event) + { + /* state and event matched, start exection action */ + if (NULL != pfsm->ptable[index_table].pevent_group[index_event].event_action) + { + state_transfer = pfsm->ptable[index_table].pevent_group[index_event].event_action( + pfsm->ptable[index_table].state); + } + + printi("model_fsm_handle_event: event match, transfer %d", state_transfer); + if (state_transfer) + { + /* exit state */ + if (NULL != pfsm->ptable[index_table].state_exit) + { + pfsm->ptable[index_table].state_exit(); + } + + pfsm->cur_state = pfsm->ptable[index_table].pevent_group[index_event].next_state; + } + goto TRANSFER; + } + } + } + } + +TRANSFER: + if (state_transfer) + { + for (uint32_t index_table = 0; index_table < pfsm->table_len; ++index_table) + { + if (pfsm->cur_state == pfsm->ptable[index_table].state) + { + /* enter state */ + if (NULL != pfsm->ptable[index_table].state_enter) + { + pfsm->ptable[index_table].state_enter(); + } + break; + } + } + } +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_fsm.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_fsm.h new file mode 100644 index 00000000..c94a2a00 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_fsm.h @@ -0,0 +1,101 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file model_fsm.h +* @brief Head file for model finite state machine +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-4-20 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _MODEL_FSM_H_ +#define _MODEL_FSM_H_ + +#include "platform_types.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_LC_FSM + * @{ + */ + +/** + * @defgroup MODEL_FSM_TYPE Model FSM Types + * @brief Model fsl types + * @{ + */ +typedef struct +{ + uint32_t event; + bool (*event_action)(uint32_t state); + uint32_t next_state; +} model_fsm_event_group_t; + +typedef struct +{ + uint32_t state; + void (*state_enter)(void); + const model_fsm_event_group_t *pevent_group; + uint32_t event_group_len; + void (*state_exit)(void); +} model_fsm_table_t; + +typedef struct _model_fsm_t model_fsm_t; +/** @} */ + +/** + * @defgroup MODEL_FSL_API Model FSM API + * @brief Model fsm api + * @{ + */ + +/** + * @brief register model fsm + * @param[in] ptabel: fsm table + * @param[in] table_len: tabel length + * @param[in] init_state: fsm initialize state + * @return model fsm handle + */ +model_fsm_t *model_fsm_reg(const model_fsm_table_t *ptable, uint32_t table_len, + uint32_t init_state); + +/** + * @brief unregister model fsm + * @param[in] pfsm: model fsm handle + */ +void model_fsm_unreg(model_fsm_t *pfsm); + +/** + * @brief run model fsm + * @param[in] pfsm: model fsm handle + */ +void model_fsm_run(model_fsm_t *pfsm); + +/** + * @brief pause model fsm + * @param[pfsm] pfsm: model fsm handle + */ +void model_fsm_pause(model_fsm_t *pfsm); + +/** + * @brief stop model fsm + * @param[in] pfsm: model fsm handle + */ +void model_fsm_stop(model_fsm_t *pfsm); + +/** + * @brief model fsm handle event + * @param[in] pfsm: model fsm handle + * @param[in] event: model event + */ +void model_fsm_handle_event(model_fsm_t *pfsm, uint32_t event); +/** @} */ + +/** @} */ +END_DECLS + + +#endif /* _MODEL_SM_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_property.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_property.h new file mode 100644 index 00000000..f1b473d3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/model_property.h @@ -0,0 +1,56 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file model_property.h +* @brief Head file for model property. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-9-3 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _MODEL_PROPERTY_H_ +#define _MODEL_PROPERTY_H_ +/** + * @addtogroup MODEL_PROPERTY + * @{ + */ + +/** + * @defgroup MODEL_PROPERYTY_MACROS Model Property Macros + * @brief + * @{ + */ +#define MODEL_PROPERTY_INVALID 0x00 + +#define MODEL_PROPERTY_LIGHT_CONTORL_AMBIENT_LUXLEVEL_ON 0x002B +#define MODEL_PROPERTY_LIGHT_CONTORL_AMBIENT_LUXLEVEL_PROLONG 0x002C +#define MODEL_PROPERTY_LIGHT_CONTORL_AMBIENT_LUXLEVEL_STANDBY 0x002D +#define MODEL_PROPERTY_LIGHT_CONTORL_LIGHTNESS_ON 0x002E +#define MODEL_PROPERTY_LIGHT_CONTORL_LIGHTNESS_PROLONG 0x002F +#define MODEL_PROPERTY_LIGHT_CONTORL_LIGHTNESS_STANDBY 0x0030 +#define MODEL_PROPERTY_LIGHT_CONTORL_REGULATOR_ACCURACY 0x0031 +#define MODEL_PROPERTY_LIGHT_CONTORL_REGULATOR_KID 0x0032 +#define MODEL_PROPERTY_LIGHT_CONTORL_REGULATOR_KIU 0x0033 +#define MODEL_PROPERTY_LIGHT_CONTORL_REGULATOR_KPD 0x0034 +#define MODEL_PROPERTY_LIGHT_CONTORL_REGULATOR_KPU 0x0035 +#define MODEL_PROPERTY_LIGHT_CONTORL_TIME_FADE 0x0036 +#define MODEL_PROPERTY_LIGHT_CONTROL_TIME_FADE_ON 0x0037 +#define MODEL_PROPERTY_LIGHT_CONTORL_TIME_FADE_STANDBY_AUDIO 0x0038 +#define MODEL_PROPERTY_LIGHT_CONTORL_TIME_FADE_STANDBY_MANUAL 0x0039 +#define MODEL_PROPERTY_LIGHT_CONTROL_TIME_OCCUPANCY_DELAY 0x003A +#define MODEL_PROPERTY_LIGHT_CONTORL_TIME_PROLONG 0x003B +#define MODEL_PROPERTY_LIGHT_CONTROL_TIME_RUN_ON 0x003C +#define MODEL_PROPERTY_MOTION_SENSED 0x0042 +#define MODEL_PROPERTY_PEOPLE_COUNT 0x004C +#define MODEL_PROPERTY_PRESENCE_DETECTED 0x004D +#define MODEL_PROPERTY_PRESENT_AMBIENT_LIGHT_LEVEL 0x004E +#define MODEL_PROPERTY_TIME_SINCE_MOTION_SENSED 0x0068 +/** @} */ +/** @} */ + +#endif /* _MODEL_PROPERTY_H_ */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_client.c new file mode 100644 index 00000000..d1cf92d0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_client.c @@ -0,0 +1,151 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file private_beacon_client.c +* @brief Source file for private beacon model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-08-04 +* @version v1.0 +* ************************************************************************************* +*/ +#include "mesh_config.h" + +#if MESH_PRB +#include "private_beacon_model.h" + +mesh_model_info_t private_beacon_client_model; + + +static mesh_msg_send_cause_t private_beacon_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t net_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.akf = 0; + mesh_msg.net_key_index = net_key_index; + mesh_msg.dst = dst; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t private_beacon_get(uint16_t dst, uint16_t net_key_index) +{ + private_beacon_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PRIVATE_BEACON_GET); + + return private_beacon_client_send(&private_beacon_client_model, dst, net_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t private_beacon_set(uint16_t dst, uint16_t net_key_index, + uint8_t private_beacon, bool has_random_update, uint8_t random_update_interval_steps) +{ + private_beacon_set_t msg; + uint8_t msg_len = sizeof(private_beacon_set_t) - 1; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PRIVATE_BEACON_SET); + msg.private_beacon = private_beacon; + if (has_random_update) + { + msg.random_update_interval_steps = random_update_interval_steps; + msg_len += 1; + } + + return private_beacon_client_send(&private_beacon_client_model, dst, net_key_index, (uint8_t *)&msg, + msg_len); +} + +mesh_msg_send_cause_t private_gatt_proxy_get(uint16_t dst, uint16_t net_key_index) +{ + private_gatt_proxy_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PRIVATE_GATT_PROXY_GET); + + return private_beacon_client_send(&private_beacon_client_model, dst, net_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t private_gatt_proxy_set(uint16_t dst, uint16_t net_key_index, + uint8_t private_gatt_proxy) +{ + private_gatt_proxy_set_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PRIVATE_GATT_PROXY_SET); + msg.private_gatt_proxy = private_gatt_proxy; + + return private_beacon_client_send(&private_beacon_client_model, dst, net_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t private_node_identity_get(uint16_t dst, uint16_t net_key_index, + uint16_t sub_net_key_index) +{ + private_node_identity_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PRIVATE_NODE_IDENTITY_GET); + msg.net_key_index = sub_net_key_index; + + return private_beacon_client_send(&private_beacon_client_model, dst, net_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +mesh_msg_send_cause_t private_node_identity_set(uint16_t dst, uint16_t net_key_index, + uint16_t sub_net_key_index, uint8_t private_identity) +{ + private_node_identity_set_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PRIVATE_NODE_IDENTITY_SET); + msg.net_key_index = sub_net_key_index; + msg.private_identity = private_identity; + + return private_beacon_client_send(&private_beacon_client_model, dst, net_key_index, (uint8_t *)&msg, + sizeof(msg)); +} + +static bool private_beacon_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + //mesh_model_info_t *pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_PRIVATE_BEACON_STATUS: + if (pmesh_msg->msg_len == sizeof(private_beacon_status_t)) + { + private_beacon_status_t *pmsg = (private_beacon_status_t *)pbuffer; + data_uart_debug("private_beacon_client_receive: private beacon %d, random update interval steps %d\r\n", + pmsg->private_beacon, pmsg->random_update_interval_steps); + } + break; + case MESH_MSG_PRIVATE_GATT_PROXY_STATUS: + if (pmesh_msg->msg_len == sizeof(private_gatt_proxy_status_t)) + { + private_gatt_proxy_status_t *pmsg = (private_gatt_proxy_status_t *)pbuffer; + data_uart_debug("private_beacon_client_receive: private gatt proxy %d\r\n", + pmsg->private_gatt_proxy); + } + break; + case MESH_MSG_PRIVATE_NODE_IDENTITY_STATUS: + if (pmesh_msg->msg_len == sizeof(private_node_identity_status_t)) + { + private_node_identity_status_t *pmsg = (private_node_identity_status_t *)pbuffer; + data_uart_debug("private_beacon_client_receive: status %d, net_key_index 0x%04x, private identity %d\r\n", + pmsg->status, pmsg->net_key_index, pmsg->private_identity); + } + break; + default: + ret = false; + break; + } + return ret; +} + +bool private_beacon_client_reg(uint8_t element_index) +{ + private_beacon_client_model.model_id = MESH_MODEL_PRIVATE_BEACON_CLIENT; + if (NULL == private_beacon_client_model.model_receive) + { + private_beacon_client_model.model_receive = private_beacon_client_receive; + } + return mesh_model_reg(element_index, &private_beacon_client_model); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_model.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_model.h new file mode 100644 index 00000000..ef472ba4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_model.h @@ -0,0 +1,215 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file private_beacon_model.h +* @brief Head file for private beacon models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-08-04 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _PRIVATE_BEACON_MODEL_H_ +#define _PRIVATE_BEACON_MODEL_H_ + + +#include "mesh_api.h" + +#if MESH_PRB + +BEGIN_DECLS + +/** + * @addtogroup PRIVATE_BEACON + * @{ + */ + +/** + * @defgroup PRIVATE_BEACON_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_PRIVATE_BEACON_GET 0xB711 +#define MESH_MSG_PRIVATE_BEACON_SET 0xB712 +#define MESH_MSG_PRIVATE_BEACON_STATUS 0xB713 +#define MESH_MSG_PRIVATE_GATT_PROXY_GET 0xB714 +#define MESH_MSG_PRIVATE_GATT_PROXY_SET 0xB715 +#define MESH_MSG_PRIVATE_GATT_PROXY_STATUS 0xB716 +#define MESH_MSG_PRIVATE_NODE_IDENTITY_GET 0xB718 +#define MESH_MSG_PRIVATE_NODE_IDENTITY_SET 0xB719 +#define MESH_MSG_PRIVATE_NODE_IDENTITY_STATUS 0xB71A +/** @} */ + +/** + * @defgroup PRIVATE_BEACON_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_PRIVATE_BEACON_SERVER 0xBF40FFFF +#define MESH_MODEL_PRIVATE_BEACON_CLIENT 0xBF41FFFF +/** @} */ + +/** + * @defgroup PRIVATE_BEACON_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_BEACON_GET)]; +} _PACKED4_ private_beacon_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_BEACON_SET)]; + uint8_t private_beacon; + uint8_t random_update_interval_steps; +} _PACKED4_ private_beacon_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_BEACON_STATUS)]; + uint8_t private_beacon; + uint8_t random_update_interval_steps; +} _PACKED4_ private_beacon_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_GATT_PROXY_GET)]; +} _PACKED4_ private_gatt_proxy_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_GATT_PROXY_SET)]; + uint8_t private_gatt_proxy; +} _PACKED4_ private_gatt_proxy_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_GATT_PROXY_STATUS)]; + uint8_t private_gatt_proxy; +} _PACKED4_ private_gatt_proxy_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_NODE_IDENTITY_GET)]; + uint16_t net_key_index; +} _PACKED4_ private_node_identity_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_NODE_IDENTITY_SET)]; + uint16_t net_key_index; + uint8_t private_identity; +} _PACKED4_ private_node_identity_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PRIVATE_NODE_IDENTITY_STATUS)]; + uint8_t status; + uint16_t net_key_index; + uint8_t private_identity; +} _PACKED4_ private_node_identity_status_t; + + + +/** @} */ + +/** + * @defgroup PRIVATE_BEACON_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register private beacon server model + * @retval true: register success + * @retval false: register failed + */ +bool private_beacon_server_reg(void); + +/** @} */ + +/** + * @defgroup PRIVATE_BEACON_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register private beacon client + * @param[in] element_index: element index that model registered to + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool private_beacon_client_reg(uint8_t element_index); + +/** + * @brief private beacon get + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @return message send status + */ +mesh_msg_send_cause_t private_beacon_get(uint16_t dst, uint16_t net_key_index); + +/** + * @brief private beacon set + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] private_beacon: private beacon value + * @param[in] has_random_update: whether has random update or not + * @param[in] random_update_interval_steps: private beacon random update interval steps + * @return message send status + */ +mesh_msg_send_cause_t private_beacon_set(uint16_t dst, uint16_t net_key_index, + uint8_t private_beacon, bool has_random_update, uint8_t random_update_interval_steps); + +/** + * @brief private gatt proxy get + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @return message send status + */ +mesh_msg_send_cause_t private_gatt_proxy_get(uint16_t dst, uint16_t net_key_index); + +/** + * @brief private gatt proxy set + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] private_gatt_proxy: private gatt proxy value + * @return message send status + */ +mesh_msg_send_cause_t private_gatt_proxy_set(uint16_t dst, uint16_t net_key_index, + uint8_t private_gatt_proxy); + +/** + * @brief private node identitu get + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] sub_net_key_index: node identity network key index + * @return message send status + */ +mesh_msg_send_cause_t private_node_identity_get(uint16_t dst, uint16_t net_key_index, + uint16_t sub_net_key_index); + +/** + * @brief private node identity set + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] sub_net_key_index: node identity network key index + * @param[in] private_identity: private node identity + * @return message send status + */ +mesh_msg_send_cause_t private_node_identity_set(uint16_t dst, uint16_t net_key_index, + uint16_t sub_net_key_index, uint8_t private_identity); + +/** @} */ +/** @} */ + +END_DECLS + +#endif + +#endif /* _PRIVATE_BEACON_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c new file mode 100644 index 00000000..f4e60fa2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c @@ -0,0 +1,288 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_model_client.c +* @brief Source file for data transmission client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-10-29 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "datatrans_model.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#include "bt_mesh_device_test.h" +#include "bt_mesh_receive_response.h" +#endif + +#if 0 +typedef struct +{ + uint8_t tid; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} datatrans_info_t; +#endif + +static mesh_msg_send_cause_t datatrans_server_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len, uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t datatrans_send_data(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t data_len, uint8_t *data, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret; + datatrans_data_t *pmsg; + uint16_t msg_len = sizeof(datatrans_data_t); + msg_len += data_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_DATATRANS_DATA); + memcpy(pmsg->data, data, data_len); + + ret = datatrans_server_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t datatrans_publish(const mesh_model_info_p pmodel_info, + uint16_t data_len, uint8_t *data) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(0); +#endif + ret = datatrans_send_data(pmodel_info, 0, 0, data_len, data, delay_rsp_time); + } + + return ret; +} + +static mesh_msg_send_cause_t datatrans_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t datatrans_write(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t data_len, uint8_t *data, + bool ack) +{ + datatrans_write_t *pmsg; + mesh_msg_send_cause_t ret; + uint16_t msg_len = sizeof(datatrans_write_t); + msg_len += data_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + if (ack) + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_DATATRANS_WRITE); + } + else + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_DATATRANS_WRITE_UNACK); + } + + memcpy(pmsg->data, data, data_len); + ret = datatrans_client_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t datatrans_read(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t read_len) +{ + datatrans_read_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_DATATRANS_READ); + msg.read_len = read_len; + return datatrans_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, + sizeof(datatrans_read_t)); +} + +static bool datatrans_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_DATATRANS_STATUS: + if (pmesh_msg->msg_len == sizeof(datatrans_status_t)) + { + datatrans_status_t *pmsg = (datatrans_status_t *)pbuffer; + + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + datatrans_client_status_t status_data; + status_data.status = pmsg->status; + status_data.written_len = pmsg->written_len; + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, DATATRANS_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_DATATRANS_DATA: + { + datatrans_data_t *pmsg = (datatrans_data_t *)pbuffer; + if (NULL != pmesh_msg->pmodel_info->model_data_cb) + { + datatrans_client_data_t read_data; + read_data.data_len = pmesh_msg->msg_len - sizeof(datatrans_data_t); + read_data.data = pmsg->data; + pmesh_msg->pmodel_info->model_data_cb(pmesh_msg->pmodel_info, DATATRANS_CLIENT_DATA, + &read_data); + } + } + break; + case MESH_MSG_DATATRANS_READ: + if (pmesh_msg->msg_len == sizeof(datatrans_read_t)) + { + datatrans_read_t *pmsg = (datatrans_read_t *)pbuffer; + datatrans_server_read_t read_data = {0, NULL}; + if (NULL != pmodel_info->model_data_cb) + { + read_data.data_len = pmsg->read_len; + pmodel_info->model_data_cb(pmodel_info, DATATRANS_SERVER_READ, &read_data); + } + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + datatrans_send_data(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + read_data.data_len, read_data.data, delay_rsp_time); + } + break; + case MESH_MSG_DATATRANS_WRITE: + case MESH_MSG_DATATRANS_WRITE_UNACK: + { + datatrans_write_t *pmsg = (datatrans_write_t *)pbuffer; + uint16_t data_len = pmesh_msg->msg_len - sizeof(datatrans_write_t); + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + datatrans_server_write_t write_data = {data_len, NULL, pmesh_msg->src, DATATRANS_SUCCESS, data_len}; +#else + datatrans_server_write_t write_data = {data_len, NULL, DATATRANS_SUCCESS, data_len}; +#endif + + if (NULL != pmodel_info->model_data_cb) + { + write_data.data = pmsg->data; + pmodel_info->model_data_cb(pmodel_info, DATATRANS_SERVER_WRITE, &write_data); + } + + if (pmesh_msg->access_opcode == MESH_MSG_DATATRANS_WRITE) + { + datatrans_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_DATATRANS_STATUS); + msg.status = write_data.status; + msg.written_len = write_data.written_len; + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + datatrans_server_send(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, (uint8_t *)&msg, + sizeof(datatrans_status_t), delay_rsp_time); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void datatrans_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == datatrans_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool datatrans_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_DATATRANS; + if (NULL == pmodel_info->model_receive) + { +#if 0 + pmodel_info->pargs = plt_malloc(sizeof(datatrans_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("datatrans_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(datatrans_info_t)); +#endif + pmodel_info->model_receive = datatrans_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("datatrans_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = datatrans_deinit; +#endif + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.h new file mode 100644 index 00000000..e35d7d75 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.h @@ -0,0 +1,209 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_model.h +* @brief Head file for data transport module +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-10-29 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _DATATRANS_MODEL_H_ +#define _DATATRANS_MODEL_H_ + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup DATA_TRANSMISSION + * @{ + */ + +/** + * @defgroup DATATRANS_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_DATATRANS_WRITE 0xC95D00 +#define MESH_MSG_DATATRANS_WRITE_UNACK 0xCA5D00 +#define MESH_MSG_DATATRANS_STATUS 0xCB5D00 +#define MESH_MSG_DATATRANS_READ 0xCC5D00 +#define MESH_MSG_DATATRANS_DATA 0xCD5D00 +/** @} */ + +/** + * @defgroup DATATRANS_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_DATATRANS 0x0004005D +/** @} */ + +/** + * @defgroup DATATRANS_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +enum +{ + DATATRANS_SUCCESS, + DATATRANS_FAIL, +} _SHORT_ENUM_; +typedef uint8_t datatrans_stat_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_DATATRANS_WRITE)]; + uint8_t data[0]; +} _PACKED4_ datatrans_write_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_DATATRANS_STATUS)]; + datatrans_stat_t status; + uint16_t written_len; +} _PACKED4_ datatrans_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_DATATRANS_READ)]; + uint16_t read_len; +} _PACKED4_ datatrans_read_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_DATATRANS_DATA)]; + uint8_t data[0]; +} _PACKED4_ datatrans_data_t; + +/** @} */ + +/** + * @defgroup DATATRANS_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define DATATRANS_SERVER_WRITE 0 //!< @ref datatrans_server_write_t +#define DATATRANS_SERVER_READ 1 //!< @ref datatrans_server_read_t + +typedef struct +{ + uint16_t data_len; + uint8_t *data; + /** + * app modify status and success written length if need to, + * the default value is DATATRANS_SUCCESS and data_len + */ +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + uint16_t src; +#endif + datatrans_stat_t status; + uint16_t written_len; +} datatrans_server_write_t;; + +typedef struct +{ + /** app read length field first, then may change length and data field */ + uint16_t data_len; + uint8_t *data; +} datatrans_server_read_t; +/** @} */ + +/** + * @defgroup DATATRANS_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define DATATRANS_CLIENT_STATUS 2 //!< @ref datatrans_client_status_t +#define DATATRANS_CLIENT_DATA 3 //!< @ref datatrans_client_data_t + +typedef struct +{ + datatrans_stat_t status; + uint16_t written_len; +} datatrans_client_status_t; + +typedef struct +{ + uint16_t data_len; + uint8_t *data; +} datatrans_client_data_t; +/** @} */ + + + +/** + * @defgroup DATATRANS_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register data transmission server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to data transimission server model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool datatrans_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish data transmission data + * @param[in] pmodel_info: pointer to data transmission server model context + * @param[in] data_len: data length to publish + * @param[in] data: data need to publish + * @return publish status + */ +mesh_msg_send_cause_t datatrans_publish(const mesh_model_info_p pmodel_info, + uint16_t data_len, uint8_t *data); +/** @} */ + +/** + * @defgroup DATATRANS_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register data transmission + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to data transimission model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool datatrans_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief data transmission write data + * @param[in] pmodel_info: pointer to data transmission client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] data_len: data length to write + * @param[in] data: data to write + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t datatrans_write(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t data_len, uint8_t *data, + bool ack); + +/** + * @brief data transmission read data + * @param[in] pmodel_info: pointer to data transmission client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] read_len: data length to read + * @return send status + */ +mesh_msg_send_cause_t datatrans_read(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t read_len); +/** @} */ +/** @} */ + +END_DECLS + +#endif /** _DATATRANS_MODEL_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model_server.c new file mode 100644 index 00000000..dc39fc30 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model_server.c @@ -0,0 +1,141 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_model_server.c +* @brief Source file for data transmission server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-10-29 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "datatrans_model.h" + + +static mesh_msg_send_cause_t datatrans_server_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t datatrans_send_data(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t data_len, uint8_t *data) +{ + mesh_msg_send_cause_t ret; + datatrans_data_t *pmsg; + uint16_t msg_len = sizeof(datatrans_data_t); + msg_len += data_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_DATATRANS_DATA); + memcpy(pmsg->data, data, data_len); + + ret = datatrans_server_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t datatrans_publish(const mesh_model_info_p pmodel_info, + uint16_t data_len, uint8_t *data) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = datatrans_send_data(pmodel_info, 0, 0, data_len, data); + } + + return ret; +} + +static bool datatrans_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_DATATRANS_READ: + if (pmesh_msg->msg_len == sizeof(datatrans_read_t)) + { + datatrans_read_t *pmsg = (datatrans_read_t *)pbuffer; + datatrans_server_read_t read_data = {0, NULL}; + if (NULL != pmodel_info->model_data_cb) + { + read_data.data_len = pmsg->read_len; + pmodel_info->model_data_cb(pmodel_info, DATATRANS_SERVER_READ, &read_data); + } + datatrans_send_data(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + read_data.data_len, read_data.data); + } + break; + case MESH_MSG_DATATRANS_WRITE: + case MESH_MSG_DATATRANS_WRITE_UNACK: + { + datatrans_write_t *pmsg = (datatrans_write_t *)pbuffer; + uint16_t data_len = pmesh_msg->msg_len - sizeof(datatrans_write_t); + datatrans_server_write_t write_data = {data_len, NULL, DATATRANS_SUCCESS, data_len}; + if (NULL != pmodel_info->model_data_cb) + { + write_data.data = pmsg->data; + pmodel_info->model_data_cb(pmodel_info, DATATRANS_SERVER_WRITE, &write_data); + } + + if (pmesh_msg->access_opcode == MESH_MSG_DATATRANS_WRITE) + { + datatrans_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_DATATRANS_STATUS); + msg.status = write_data.status; + msg.written_len = write_data.written_len; + datatrans_server_send(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, (uint8_t *)&msg, + sizeof(datatrans_status_t)); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool datatrans_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_DATATRANS_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = datatrans_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("datatrans server reg: missing model data process callback!"); + } + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb.h new file mode 100644 index 00000000..4702069c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb.h @@ -0,0 +1,98 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_cwrgb.h +* @brief Head file for light cwrgb(cold/warn/red/green/blue) module. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-1-3 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _LIGHT_CWRGB_H +#define _LIGHT_CWRGB_H + +/* Add Includes here */ +#include "platform_misc.h" +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup LIGHT_CWRGB + * @{ + */ + +/** + * @defgroup LIGHT_CWRGB_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_LIGHT_CWRGB_GET 0xC45D00 +#define MESH_MSG_LIGHT_CWRGB_SET 0xC55D00 +#define MESH_MSG_LIGHT_CWRGB_SET_UNACK 0xC65D00 +#define MESH_MSG_LIGHT_CWRGB_STAT 0xC75D00 +/** @} */ + +/** + * @defgroup LIGHT_CWRGB_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_LIGHT_CWRGB_SERVER 0x0001005D +#define MESH_MODEL_LIGHT_CWRGB_CLIENT 0x0002005D +/** @} */ + +/** + * @defgroup LIGHT_CWRGB_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CWRGB_GET)]; +} _PACKED4_ light_cwrgb_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CWRGB_SET)]; + uint8_t cwrgb[5]; //!< up to 8 bytes to fit into only one adv packet +} _PACKED4_ light_cwrgb_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_LIGHT_CWRGB_STAT)]; + uint8_t cwrgb[5]; //!< up to 8 bytes to fit into only one adv packet +} _PACKED4_ light_cwrgb_stat_t; +/** @} */ + +/** + * @defgroup LIGHT_CWRGB_SERVER_API Server API + * @brief Functions declaration + * @{ + */ +void light_cwrgb_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info, + model_receive_pf pf_model_receive); +mesh_msg_send_cause_t light_cwrgb_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t cwrgb[5]); +/** @} */ + +/** + * @defgroup LIGHT_CWRGB_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ +bool light_cwrgb_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); +mesh_msg_send_cause_t light_cwrgb_get(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); +mesh_msg_send_cause_t light_cwrgb_set(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t cwrgb[5], bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _LIGHT_CWRGB_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_client.c new file mode 100644 index 00000000..cabd83e5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_client.c @@ -0,0 +1,81 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_cwrgb_client.c +* @brief Source file for light cwrgb client module. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-1-3 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_cwrgb.h" + +static mesh_msg_send_cause_t light_cwrgb_client_send(mesh_model_info_p pmodel_info, uint16_t dst, + uint8_t *pmsg, uint16_t msg_len, uint16_t app_key_index) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t light_cwrgb_get(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + light_cwrgb_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CWRGB_GET); + return light_cwrgb_client_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index); +} + +mesh_msg_send_cause_t light_cwrgb_set(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t cwrgb[5], bool ack) +{ + light_cwrgb_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CWRGB_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CWRGB_SET_UNACK); + } + memcpy(msg.cwrgb, cwrgb, sizeof(msg.cwrgb)); + return light_cwrgb_client_send(pmodel_info, dst, (uint8_t *)&msg, sizeof(msg), app_key_index); +} + +/* Sample +bool light_cwrgb_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CWRGB_STAT: + if (pmesh_msg->msg_len == sizeof(light_cwrgb_stat_t)) + { + + } + break; + default: + ret = FALSE; + break; + } + return ret; +} +*/ + +bool light_cwrgb_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + pmodel_info->model_id = MESH_MODEL_LIGHT_CWRGB_CLIENT; + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_server.c new file mode 100644 index 00000000..bd3fe6f6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_server.c @@ -0,0 +1,69 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file light_cwrgb_server.c +* @brief Source file for light cwrgb server module. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-1-3 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include "light_cwrgb.h" + +mesh_msg_send_cause_t light_cwrgb_stat(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t cwrgb[5]) +{ + light_cwrgb_stat_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_LIGHT_CWRGB_STAT); + memcpy(msg.cwrgb, cwrgb, sizeof(msg.cwrgb)); + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = sizeof(light_cwrgb_stat_t); + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +/* Sample + bool light_cwrgb_server_receive(mesh_msg_p pmesh_msg) + { + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_LIGHT_CWRGB_GET: + if (pmesh_msg->msg_len == sizeof(light_cwrgb_get_t)) + { + + } + break; + case MESH_MSG_LIGHT_CWRGB_SET: + case MESH_MSG_LIGHT_CWRGB_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(light_cwrgb_set_t)) + { + + } + break; + default: + ret = FALSE; + break; + } + return ret; + } +*/ + +void light_cwrgb_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info, + model_receive_pf pf_model_receive) +{ + pmodel_info->model_id = MESH_MODEL_LIGHT_CWRGB_SERVER; + pmodel_info->model_receive = pf_model_receive; + mesh_model_reg(element_index, pmodel_info); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping.h new file mode 100644 index 00000000..39f2ebb7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping.h @@ -0,0 +1,104 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file ping.h +* @brief Head file for ping models. +* @details Data types and external functions declaration. +* @author bill +* @date 2016-3-24 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _PING_H +#define _PING_H + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup PING + * @{ + */ + +/** + * @defgroup PING_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_PING 0xC05D00 +#define MESH_MSG_PONG 0xC15D00 +#define MESH_MSG_BIG_PING 0xC25D00 +#define MESH_MSG_BIG_PONG 0xC35D00 +/** @} */ + +/** + * @defgroup PING_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_PING_CONTROL 0x0000005D +/** @} */ + +/** + * @defgroup PING_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PING)]; + uint8_t init_ttl; //!< Initial TTL value used when sending this message. + uint16_t pong_max_delay; //!< unit: 10ms +} _PACKED4_ ping_t, *ping_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_PONG)]; + uint8_t init_ttl; //!< Initial TTL value used when sending this message. + uint8_t hops_forward; //!< Hops in the forward direction. + uint16_t pong_delay; //!< unit: 10ms +} _PACKED4_ pong_t, *pong_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BIG_PING)]; + uint8_t init_ttl; + uint16_t pong_max_delay; //!< unit: 10ms + uint8_t padding[ACCESS_PAYLOAD_MAX_SIZE - 3 - ACCESS_OPCODE_SIZE(MESH_MSG_BIG_PING)]; +} _PACKED4_ big_ping_t, *big_ping_p; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_BIG_PONG)]; + uint8_t init_ttl; + uint8_t hops_forward; + uint16_t pong_delay; //!< unit: 10ms + uint8_t padding[ACCESS_PAYLOAD_MAX_SIZE - 4 - ACCESS_OPCODE_SIZE(MESH_MSG_BIG_PONG)]; +} _PACKED4_ big_pong_t, *big_pong_p; +/** @} */ + +/** + * @defgroup PING_SERVER_API Server API + * @brief Functions declaration + * @{ + */ +void ping_control_reg(pf_ping_cb_t pf_ping_cb, pf_pong_cb_t pf_pong_cb); +mesh_msg_send_cause_t ping(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint16_t pong_max_delay); +mesh_msg_send_cause_t pong(uint16_t dst, uint8_t ttl, uint16_t app_key_index, uint8_t hops_forward, + uint16_t pong_delay); +mesh_msg_send_cause_t big_ping(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint16_t pong_max_delay); +mesh_msg_send_cause_t big_pong(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint8_t hops_forward, uint16_t pong_delay); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PING_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c new file mode 100644 index 00000000..b57a1db5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c @@ -0,0 +1,194 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file ping_control.c +* @brief Source file for ping control model. +* @details Data types and external functions declaration. +* @author bill +* @date 2016-3-24 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "trace.h" +#include "ping.h" + +mesh_model_info_t ping_control; + +static pf_ping_cb_t pf_ping_app_ping_cb; +static pf_pong_cb_t pf_ping_control_pong_cb; + +static mesh_msg_send_cause_t ping_control_send(uint16_t dst, uint8_t ttl, uint8_t *pmsg, + uint16_t msg_len, uint16_t app_key_index) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = &ping_control; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.ttl = ttl; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t ping(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint16_t pong_max_delay) +{ + ping_t msg; + msg.init_ttl = ttl; + msg.pong_max_delay = pong_max_delay; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PING); + return ping_control_send(dst, ttl, (uint8_t *)&msg, sizeof(ping_t), app_key_index); +} + +mesh_msg_send_cause_t big_ping(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint16_t pong_max_delay) +{ + big_ping_p pmsg = (big_ping_p)plt_malloc(sizeof(big_ping_t), RAM_TYPE_DATA_OFF); + if (pmsg == NULL) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + pmsg->init_ttl = ttl; + pmsg->pong_max_delay = pong_max_delay; + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_BIG_PING); + memset(pmsg->padding, 0, sizeof(pmsg->padding)); + mesh_msg_send_cause_t ret = ping_control_send(dst, ttl, (uint8_t *)pmsg, sizeof(big_ping_t), + app_key_index); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +mesh_msg_send_cause_t pong(uint16_t dst, uint8_t ttl, uint16_t app_key_index, uint8_t hops_forward, + uint16_t pong_delay) +{ + pong_t msg; + msg.init_ttl = ttl; + msg.hops_forward = hops_forward; + msg.pong_delay = pong_delay; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_PONG); + return ping_control_send(dst, ttl, (uint8_t *)&msg, sizeof(pong_t), app_key_index); +} + +mesh_msg_send_cause_t big_pong(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint8_t hops_forward, uint16_t pong_delay) +{ + big_pong_p pmsg = (big_pong_p)plt_malloc(sizeof(big_pong_t), RAM_TYPE_DATA_OFF); + if (pmsg == NULL) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + pmsg->init_ttl = ttl; + pmsg->hops_forward = hops_forward; + pmsg->pong_delay = pong_delay; + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_BIG_PONG); + memset(pmsg->padding, 0, sizeof(pmsg->padding)); + mesh_msg_send_cause_t ret = ping_control_send(dst, ttl, (uint8_t *)pmsg, sizeof(big_pong_t), + app_key_index); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +bool ping_control_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_PING: + if (pmesh_msg->msg_len == sizeof(ping_t)) + { + ping_t *pmsg = (ping_t *)(pbuffer); + if (pmsg->init_ttl >= pmesh_msg->ttl) + { + uint8_t hops_forward = pmsg->init_ttl - pmesh_msg->ttl + 1; + printi("ping_control_receive: [0x%04x -> 0x%04x]: %d hops!", pmesh_msg->src, pmesh_msg->dst, + hops_forward); + if (pf_ping_app_ping_cb) + { + pf_ping_app_ping_cb(pmesh_msg->src, pmesh_msg->dst, hops_forward, PING_PONG_TYPE_ACCESS, + pmsg->init_ttl, pmesh_msg->app_key_index, pmsg->pong_max_delay); + } + else + { + pong(pmesh_msg->src, pmsg->init_ttl, pmesh_msg->app_key_index, hops_forward, 0); + } + } + } + break; + case MESH_MSG_BIG_PING: + if (pmesh_msg->msg_len == sizeof(big_ping_t)) + { + big_ping_p pmsg = (big_ping_t *)(pbuffer); + if (pmsg->init_ttl >= pmesh_msg->ttl) + { + uint8_t hops_forward = pmsg->init_ttl - pmesh_msg->ttl + 1; + printi("ping_control_receive: Big [0x%04x -> 0x%04x]: %d hops!", pmesh_msg->src, pmesh_msg->dst, + hops_forward); + if (pf_ping_app_ping_cb) + { + pf_ping_app_ping_cb(pmesh_msg->src, pmesh_msg->dst, hops_forward, PING_PONG_TYPE_ACCESS_BIG, + pmsg->init_ttl, pmesh_msg->app_key_index, pmsg->pong_max_delay); + } + else + { + big_pong(pmesh_msg->src, pmsg->init_ttl, pmesh_msg->app_key_index, hops_forward, 0); + } + } + } + break; + case MESH_MSG_PONG: + if (pmesh_msg->msg_len == sizeof(pong_t)) + { + pong_t *pmsg = (pong_t *)(pbuffer); + if (pmsg->init_ttl >= pmesh_msg->ttl) + { + uint8_t hops_reverse = pmsg->init_ttl - pmesh_msg->ttl + 1; + printi("ping_control_receive: [0x%04x -> 0x%04x]: %d-%d hops!", pmesh_msg->dst, + pmesh_msg->src, pmsg->hops_forward, hops_reverse); + if (pf_ping_control_pong_cb) + { + pf_ping_control_pong_cb(pmesh_msg->src, pmesh_msg->dst, pmsg->hops_forward, PING_PONG_TYPE_ACCESS, + hops_reverse, pmsg->pong_delay); + } + } + } + break; + case MESH_MSG_BIG_PONG: + if (pmesh_msg->msg_len == sizeof(big_pong_t)) + { + big_pong_p pmsg = (big_pong_t *)(pbuffer); + if (pmsg->init_ttl >= pmesh_msg->ttl) + { + uint8_t hops_reverse = pmsg->init_ttl - pmesh_msg->ttl + 1; + printi("ping_control_receive: Big [0x%04x -> 0x%04x]: %d-%d hops!", pmesh_msg->dst, + pmesh_msg->src, pmsg->hops_forward, hops_reverse); + if (pf_ping_control_pong_cb != NULL) + { + pf_ping_control_pong_cb(pmesh_msg->src, pmesh_msg->dst, pmsg->hops_forward, + PING_PONG_TYPE_ACCESS_BIG, hops_reverse, pmsg->pong_delay); + } + } + } + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +void ping_control_reg(pf_ping_cb_t pf_ping_cb, pf_pong_cb_t pf_pong_cb) +{ + ping_control.model_id = MESH_MODEL_PING_CONTROL; + ping_control.model_receive = ping_control_receive; + mesh_model_reg(0, &ping_control); + pf_ping_app_ping_cb = pf_ping_cb; + pf_ping_control_pong_cb = pf_pong_cb; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp.h new file mode 100644 index 00000000..153e4f3c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp.h @@ -0,0 +1,72 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file tp.h +* @brief Head file for tp models. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-3-7 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _TP_H +#define _TP_H + +/* Add Includes here */ +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup TP + * @{ + */ + +/** + * @defgroup TP_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_TP_MSG 0xC85D00 +/** @} */ + +/** + * @defgroup TP_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_TP_CONTROL 0x0003005D +/** @} */ + +/** + * @defgroup TP_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TP_MSG)]; + uint32_t tid; + uint8_t padding[ACCESS_PAYLOAD_MAX_SIZE - sizeof(uint32_t) - ACCESS_OPCODE_SIZE(MESH_MSG_TP_MSG)]; +} _PACKED4_ tp_msg_t; +/** @} */ + +/** + * @defgroup TP_CONTROL_API Control API + * @brief Functions declaration + * @{ + */ +void tp_control_reg(model_data_cb_pf data_cb); +mesh_msg_send_cause_t tp_msg(uint16_t dst, uint8_t ttl, uint16_t app_key_index, uint8_t *pdata, + uint16_t data_len); +mesh_msg_send_cause_t tp_start(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint32_t count); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _TP_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c new file mode 100644 index 00000000..e769019a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c @@ -0,0 +1,154 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file tp_control.c +* @brief Source file for throughput/transparent control model. +* @details Data types and external functions declaration. +* @author bill +* @date 2018-3-7 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Add Includes here */ +#include +#include "trace.h" +#include "tp.h" + +mesh_model_info_t tp_control; + +struct tp_tx_ctx_t +{ + uint32_t tid; + uint32_t count; + uint16_t dst; + uint8_t ttl; + uint16_t app_key_index; + uint32_t begin_time; + uint32_t end_time; +} tp_tx_ctx; + +static mesh_msg_send_cause_t tp_control_send(uint16_t dst, uint8_t ttl, uint8_t *pmsg, + uint16_t msg_len, uint16_t app_key_index) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = &tp_control; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.ttl = ttl; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t tp_msg(uint16_t dst, uint8_t ttl, uint16_t app_key_index, uint8_t *pdata, + uint16_t data_len) +{ + uint16_t len = MEMBER_OFFSET(tp_msg_t, padding) + data_len; + tp_msg_t *pmsg = (tp_msg_t *)plt_malloc(len, RAM_TYPE_DATA_OFF); + if (pmsg == NULL) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + pmsg->tid = tp_tx_ctx.tid; + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_TP_MSG); + if (pdata) + { + memcpy(pmsg->padding, pdata, data_len); + } + mesh_msg_send_cause_t ret = tp_control_send(dst, ttl, (uint8_t *)pmsg, len, + app_key_index); + plt_free(pmsg, RAM_TYPE_DATA_OFF); + return ret; +} + +mesh_msg_send_cause_t tp_start(uint16_t dst, uint8_t ttl, uint16_t app_key_index, + uint32_t count) +{ + if (MESH_IS_UNASSIGNED_ADDR(dst) || count == 0) + { + /* quit to send segmented message */ + tp_tx_ctx.count = tp_tx_ctx.tid; + return MESH_MSG_SEND_CAUSE_SUCCESS; + } + tp_tx_ctx.tid = 0; + tp_tx_ctx.count = count; + tp_tx_ctx.dst = dst; + tp_tx_ctx.ttl = ttl; + tp_tx_ctx.app_key_index = app_key_index; + tp_tx_ctx.begin_time = plt_time_read_ms(); + return tp_msg(tp_tx_ctx.dst, tp_tx_ctx.ttl, tp_tx_ctx.app_key_index, NULL, + sizeof(tp_msg_t) - MEMBER_OFFSET(tp_msg_t, padding)); +} + +bool tp_control_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_TP_MSG: + if (pmesh_msg->msg_len >= MEMBER_OFFSET(tp_msg_t, padding)) + { + if (tp_control.model_data_cb) + { + tp_control.model_data_cb(&tp_control, 0, pmesh_msg); + } + } + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +void tp_send_cb(mesh_model_info_p pmodel_info, mesh_msg_send_stat_t stat, uint32_t access_opcode) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + (void)access_opcode; + + if (stat == MESH_MSG_SEND_STAT_SENT || stat == MESH_MSG_SEND_STAT_ACKED || + stat == MESH_MSG_SEND_STAT_ACKED_OBO) + { + tp_tx_ctx.tid++; + } + else if (MESH_IS_GROUP_ADDR(tp_tx_ctx.dst) && stat == MESH_MSG_SEND_STAT_TIMEOUT) + { + tp_tx_ctx.tid++; + } + else + { + data_uart_debug("tp tx fail reason=%d\r\n", stat); + } + /* throughput mode */ + if (tp_tx_ctx.count) + { + if (tp_tx_ctx.tid < tp_tx_ctx.count) + { + tp_msg(tp_tx_ctx.dst, tp_tx_ctx.ttl, tp_tx_ctx.app_key_index, NULL, + sizeof(tp_msg_t) - MEMBER_OFFSET(tp_msg_t, padding)); + } + else + { + tp_tx_ctx.end_time = plt_time_read_ms(); + data_uart_debug("tp tx elapsed time=%dms tp=%dbyte/s\r\n", + tp_tx_ctx.end_time - tp_tx_ctx.begin_time, + ACCESS_PAYLOAD_MAX_SIZE * tp_tx_ctx.tid * 1000 / (tp_tx_ctx.end_time - tp_tx_ctx.begin_time)); + tp_tx_ctx.count = 0; + } + } +} + +void tp_control_reg(model_data_cb_pf data_cb) +{ + tp_control.model_id = MESH_MODEL_TP_CONTROL; + tp_control.model_receive = tp_control_receive; + tp_control.model_send_cb = tp_send_cb; + tp_control.model_data_cb = data_cb; + mesh_model_reg(0, &tp_control); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/remote_provisioning.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/remote_provisioning.h new file mode 100644 index 00000000..e4942c1e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/remote_provisioning.h @@ -0,0 +1,676 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file remote_provisioning.h +* @brief Head file for remote provisioning models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2020-11-12 +* @version v1.0 +* ************************************************************************************* +*/ + +/* Define to prevent recursive inclusion */ +#ifndef _REMOTE_PROVISIONING_H +#define _REMOTE_PROVISIONING_H + +#include "mesh_api.h" +#include "provision_client.h" + +#if MESH_RPR + +BEGIN_DECLS + +/** + * @addtogroup REMOTE_PROVISIONING + * @{ + */ + +/** + * @defgroup REMOTE_PROVISIONING_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_RMT_PROV_SCAN_CAPS_GET 0x804F +#define MESH_MSG_RMT_PROV_SCAN_CAPS_STATUS 0x8050 +#define MESH_MSG_RMT_PROV_SCAN_GET 0x8051 +#define MESH_MSG_RMT_PROV_SCAN_START 0x8052 +#define MESH_MSG_RMT_PROV_SCAN_STOP 0x8053 +#define MESH_MSG_RMT_PROV_SCAN_STATUS 0x8054 +#define MESH_MSG_RMT_PROV_SCAN_REPORT 0x8055 +#define MESH_MSG_RMT_PROV_EXTENED_SCAN_START 0x8056 +#define MESH_MSG_RMT_PROV_EXTENED_SCAN_REPORT 0x8057 +#define MESH_MSG_RMT_PROV_LINK_GET 0x8058 +#define MESH_MSG_RMT_PROV_LINK_OPEN 0x8059 +#define MESH_MSG_RMT_PROV_LINK_CLOSE 0x805A +#define MESH_MSG_RMT_PROV_LINK_STATUS 0x805B +#define MESH_MSG_RMT_PROV_LINK_REPORT 0x805C +#define MESH_MSG_RMT_PROV_PDU_SEND 0x805D +#define MESH_MSG_RMT_PROV_PDU_OUTBOUND_REPORT 0x805E +#define MESH_MSG_RMT_PROV_PDU_REPORT 0x805F +/** @} */ + +/** + * @defgroup REMOTE_PROVISIONING_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_RMT_PROV_SERVER 0x0004ffff +#define MESH_MODEL_RMT_PROV_CLIENT 0x0005ffff +/** @} */ + +/** + * @defgroup REMOTE_PROVISIONING_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ + +enum +{ + RMT_PROV_SCAN_STATE_IDLE, + RMT_PROV_SCAN_STATE_MULTIPLE_DEVICES, + RMT_PROV_SCAN_STATE_SINGLE_DEVICE, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_scan_state_t; + +enum +{ + RMT_PROV_SCAN_NOT_SUPPORT_ACTIVE_SCAN, + RMT_PROV_SCAN_SUPPORT_ACTIVE_SCAN, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_active_scan_state_t; + +enum +{ + RMT_PROV_DKRI_DEV_KEY_REFRESH, + RMT_PROV_DKRI_NODE_ADDR_REFRESH, + RMT_PROV_DKRI_NODE_COMPO_REFRESH, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_dkri_procedure_t; + +enum +{ + RMT_PROV_LINK_CLOSE_SUCCESS, + RMT_PROV_LINK_CLOSE_PROHIBITED, + RMT_PROV_LINK_CLOSE_FAIL, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_link_close_reason_t; + +enum +{ + RMT_PROV_LINK_STATE_IDLE, + RMT_PROV_LINK_STATE_LINK_OPENING, + RMT_PROV_LINK_STATE_LINK_ACTIVE, + RMT_PROV_LINK_STATE_OUTBOUND_PKT_TRANS, + RMT_PROV_LINK_STATE_LINK_CLOSING, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_link_state_t; + +enum +{ + RMT_PROV_SUCCESS, + RMT_PROV_SCANNING_CANNOT_START, + RMT_PROV_INVALID_STATE, + RMT_PROV_LIMITED_RESOURCES, + RMT_PROV_LINK_CANNOT_OPEN, + RMT_PROV_LINK_OPEN_FAILED, + RMT_PROV_LINK_CLOSED_BY_DEVICE, + RMT_PROV_LINK_CLOSED_BY_SERVER, + RMT_PROV_LINK_CLOSED_BY_CLIENT, + RMT_PROV_LINK_CLOSED_AS_CANNOT_RECEIVE_PDU, + RMT_PROV_LINK_CLOSED_AS_CANNOT_SEND_PDU, + RMT_PROV_LINK_CLOSED_AS_CANNOT_DELIVER_PDU_REPORT, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_status_t; + +enum +{ + RMT_PROV_PROCEDURE_IDLE, + RMT_PROV_PROCEDURE_PROV, + RMT_PROV_PROCEDURE_DKRI, +} _SHORT_ENUM_; +typedef uint8_t rmt_prov_procedure_t; + + +#define RMT_PROV_MAX_SCANNED_ITEMS_MIN 4 +#define RMT_PROV_MAX_SCANNED_ITEMS_MAX 255 +#define RMT_PROV_SCANNED_ITEMS_NO_LIMIT 0 + +#define RMT_PROV_EXTENED_SCAN_TIMEOUT_MIN 0x01 +#define RMT_PROV_EXTENED_SCAN_TIMEOUT_MAX 0x15 + +#define RMT_PROV_LINK_OPEN_TIMEOUT_MIN 0x01 +#define RMT_PROV_LINK_OPEN_TIMEOUT_MAX 0x3C + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_CAPS_GET)]; +} _PACKED4_ rmt_prov_scan_caps_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_CAPS_STATUS)]; + uint8_t max_scanned_items; + rmt_prov_active_scan_state_t active_scan_state; +} _PACKED4_ rmt_prov_scan_caps_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_GET)]; +} _PACKED4_ rmt_prov_scan_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_START)]; + uint8_t scanned_items_limit; + uint8_t timeout; + uint8_t uuid[16]; +} _PACKED4_ rmt_prov_scan_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_STOP)]; +} _PACKED4_ rmt_prov_scan_stop_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_STATUS)]; + rmt_prov_status_t status; + rmt_prov_scan_state_t scan_state; + uint8_t scanned_items_limit; + uint8_t timeout; +} _PACKED4_ rmt_prov_scan_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_SCAN_REPORT)]; + int8_t rssi; + uint8_t uuid[16]; + uint8_t oob[2]; + uint8_t uri_hash[4]; +} _PACKED4_ rmt_prov_scan_report_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_EXTENED_SCAN_START)]; + uint8_t ad_type_filter_count; + uint8_t data[0]; +} _PACKED4_ rmt_prov_extened_scan_start_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_EXTENED_SCAN_REPORT)]; + rmt_prov_status_t status; + uint8_t uuid[16]; + uint8_t oob_adv[0]; +} _PACKED4_ rmt_prov_extened_scan_report_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_LINK_GET)]; +} _PACKED4_ rmt_prov_link_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_LINK_OPEN)]; + uint8_t uuid[16]; + uint8_t link_open_timeout; +} _PACKED4_ rmt_prov_link_open_prov_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_LINK_OPEN)]; + rmt_prov_dkri_procedure_t dkri_procedure; +} _PACKED4_ rmt_prov_link_open_dkri_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_LINK_CLOSE)]; + rmt_prov_link_close_reason_t reason; +} _PACKED4_ rmt_prov_link_close_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_LINK_STATUS)]; + rmt_prov_status_t status; + rmt_prov_link_state_t link_state; +} _PACKED4_ rmt_prov_link_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_LINK_REPORT)]; + rmt_prov_status_t status; + rmt_prov_link_state_t link_state; + rmt_prov_link_close_reason_t reason; +} _PACKED4_ rmt_prov_link_report_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_PDU_SEND)]; + uint8_t outbound_pdu_num; + uint8_t pdu[0]; +} _PACKED4_ rmt_prov_pdu_send_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_PDU_OUTBOUND_REPORT)]; + uint8_t outbound_pdu_num; +} _PACKED4_ rmt_prov_pdu_outbound_report_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_RMT_PROV_PDU_REPORT)]; + uint8_t inbound_pdu_num; + uint8_t pdu[0]; +} _PACKED4_ rmt_prov_pdu_report_t; + +/** @} */ + +/** + * @defgroup REMOTE_PROVISION_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define RMT_PROV_SERVER_ADV_STRUCTS_GET 0 //!< @ref rmt_prov_server_adv_structs_get_t + +typedef struct +{ + uint8_t ad_type_filter_count; + uint8_t *pad_type_filter; + /* app shall fill this field */ + uint8_t adv_strcuts[31]; + uint8_t adv_structs_len; +} rmt_prov_server_adv_structs_get_t; +/** @} */ + +/** + * @defgroup REMOTE_PROVISION_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define RMT_PROV_CLIENT_SCAN_CAPS_STATUS 0 //!< @ref rmt_prov_client_scan_caps_status_t +#define RMT_PROV_CLIENT_SCAN_STATUS 1 //!< @ref rmt_prov_client_scan_status_t +#define RMT_PROV_CLIENT_SCAN_REPORT 2 //!< @ref rmt_prov_client_scan_report_t +#define RMT_PROV_CLIENT_EXTENED_SCAN_REPORT 3 //!< @ref rmt_prov_client_extened_scan_report_t +#define RMT_PROV_CLIENT_LINK_STATUS 4 //!< @ref rmt_prov_client_link_status_t +#define RMT_PROV_CLIENT_LINK_REPORT 5 //!< @ref rmt_prov_client_link_report_t + +typedef struct +{ + uint16_t src; + uint8_t max_scanned_items; + bool support_active_scan; +} rmt_prov_client_scan_caps_status_t; + +typedef struct +{ + uint16_t src; + rmt_prov_status_t status; + rmt_prov_scan_state_t scan_state; + uint8_t scanned_items_limit; + uint8_t timeout; +} rmt_prov_client_scan_status_t; + +typedef struct +{ + uint16_t src; + int8_t rssi; + uint8_t uuid[16]; + uint8_t *poob; + uint8_t *puri_hash; +} rmt_prov_client_scan_report_t; + +typedef struct +{ + uint16_t src; + uint8_t uuid[16]; + uint8_t *poob; + uint8_t *padv_structs; + uint16_t adv_structs_len; +} rmt_prov_client_extened_scan_report_t; + +typedef struct +{ + uint16_t src; + rmt_prov_status_t status; + rmt_prov_link_state_t link_state; +} rmt_prov_client_link_status_t; + +typedef struct +{ + uint16_t src; + rmt_prov_status_t status; + rmt_prov_link_state_t link_state; + rmt_prov_link_close_reason_t *preason; +} rmt_prov_client_link_report_t; +/** @} */ + +/** + * @defgroup REMOTE_PROVISION_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register remote provisioning server model + * @param[in] element_index: element index that model registered to + * @retval true: register success + * @retval false: register failed + */ +bool rmt_prov_server_reg(uint8_t element_index); + +/** + * @brief set model data callback + * @param[in] pcb: model data callback + */ +void rmt_prov_server_set_cb(model_data_cb_pf pcb); + +/** + * @brief set remote provisioning server capabilites + * @param[in] max_scanned_items: max scanned items value + * @param[in] active_scan_state: active scan state value + * @return set status + */ +bool rmt_prov_server_set_capabilites(uint8_t max_scanned_items, + rmt_prov_active_scan_state_t active_scan_state); + +/** + * @brief stop scan + */ +void rmt_prov_server_scan_stop(void); + +/** + * @brief report scan information + * @param[in] dst: scan report destination address + * @param[in] net_key_index: scan report used network key index + * @param[in] rssi: received rssi value + * @param[in] uuid: received uuid value + * @param[in] oob: received oob value + * @param[in] uri_hash: received uri hash value + * @return send status + */ +mesh_msg_send_cause_t rm_prov_scan_report(uint16_t dst, uint16_t net_key_index, int8_t rssi, + uint8_t uuid[16], uint8_t oob[2], uint8_t uri_hash[4]); + +/** + * @brief report extened scan information + * @param[in] dst: extened scan report destination address + * @param[in] net_key_index: extened scan report used network key index + * @param[in] status: rextened scan status + * @param[in] uuid: received uuid value + * @param[in] oob: received oob value + * @param[in] adv_data: scanned extened adv data + * @param[in] adv_data_len: scanned extened adv data length + * @return send status + */ +mesh_msg_send_cause_t rm_prov_extened_scan_report(uint16_t dst, uint16_t net_key_index, + rmt_prov_status_t status, uint8_t uuid[16], uint8_t oob[2], uint8_t adv_data[], + uint8_t adv_data_len); + +/** + * @brief handle uprovision device beacon + * @param[in] bt_addr: device bt address + * @param[in] bt_addr_type: device bt address type + * @param[in] rssi: rssi received + * @param[in] pudb: udb information + * @param[in] len: udb information length + */ +void rmt_prov_server_handle_udb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, + beacon_udb_t *pudb, uint8_t len); + +/** + * @brief handle provision service + * @param[in] bt_addr: device bt address + * @param[in] bt_addr_type: device bt address type + * @param[in] rssi: rssi received + * @param[in] pservice_data: provision service information + * @param[in] len: udb information length + */ +void rmt_prov_server_handle_prov(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, + mesh_service_data_t *pservice_data, uint8_t len); + +/** + * @brief handle connection state change + * @param[in] conn_id: connection id + * @param[in] conn_state: new connection state + * @param[in] disc_cause: disconnect cause + */ +void rmt_prov_server_handle_conn_state_change(uint8_t conn_id, uint8_t new_state, + uint16_t disc_cause); + + +/** + * @brief get remote provision procedure + * @return remote provision procedure + */ +rmt_prov_procedure_t rmt_prov_server_procedure_get(void); + +/** + * @brief handle provision timeout + * @param[in] ptimer: timer handle + */ +void rmt_prov_handle_timeout_dev(void *ptimer); + +/** + * @brief handle externed scan data + * @param[in] adv_report_type: adv report type + * @param[in] bt_addr: device bt address + * @param[in] bt_addr_type: device bt address type + * @param[in] rssi: rssi received + * @param[in] pbuffer: scan response data + * @param[in] len: scan response data length + */ +void rmt_prov_server_extened_scan_handle(gap_sched_adv_report_type_t adv_report_type, + uint8_t bt_addr[6], uint8_t addr_type, int8_t rssi, uint8_t *pbuffer, uint16_t buf_len); + +/** + * @brief link close + * @param[in] status: provision status + * @param[in] reason: link close reason + */ +void rmt_prov_server_link_close(rmt_prov_status_t status, uint8_t reason); + +/** + * @brief handle net key delete + * @param[in] net_key_index: net key local index + */ +void rmt_prov_server_net_key_delete(uint16_t net_key_index); + +/** + * @brief clear scanned items + */ +void rmt_prov_scanned_items_clear(void); + +/** + * @brief remote provision node reset + */ +void rmt_prov_node_reset(void); + +/** + * @brief initialize remote provision + */ +void prov_init_rmt(void); + +/** + * @brief set provision prefer bearer + * @param[in] bearer: prefer bearer + */ +void rmt_prov_set_prefer_bearer(bearer_field_t bearer); + +/** @} */ + +/** + * @defgroup REMOTE_PROVISION_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ +/** + * @brief register remote provision client + * @param[in] element_index: element index that model registered to + * @param[in] pcb: client data callback function + * @retval true: register success + * @retval false: register failed + */ +bool rmt_prov_client_reg(uint8_t element_index, model_data_cb_pf pcb); + +/** + * @brief get scan capabilites + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_scan_caps_get(uint16_t dst, uint16_t net_key_index); + +/** + * @brief get scan status + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_scan_get(uint16_t dst, uint16_t net_key_index); + +/** + * @brief start scan + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] scanned_items_limit: max scanned items + * @param[in] scan_timeout: scan timeout, unit is second + * @param[in] uuid: scan uuid + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_scan_start(uint16_t dst, uint16_t net_key_index, + uint8_t scanned_items_limit, uint8_t scan_timeout, uint8_t uuid[16]); + +/** + * @brief stop scan + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_scan_stop(uint16_t dst, uint16_t net_key_index); + +/** + * @brief start extened scan + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] ad_type_filter_cnt: ad type filter count + * @param[in] pad_type_filter: ad type filter value + * @param[in] uuid: remote device uuid + * @param[in] timeout: extened scan timeout + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_extened_scan_start(uint16_t dst, uint16_t net_key_index, + uint8_t ad_type_filter_cnt, uint8_t *pad_type_filter, uint8_t uuid[16], uint8_t timeout); + +/** + * @brief get remote link status + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_link_get(uint16_t dst, uint16_t net_key_index); + +/** + * @brief link open for provision + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] uuid: remote device uuid + * @param[in] link_open_timeout: link open timeout time + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_link_open_prov(uint16_t dst, uint16_t net_key_index, + uint8_t uuid[16], uint8_t link_open_timeout); + +/** + * @brief link open for dkri + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] dkri_procedure: dkri procedure + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_link_open_dkri(uint16_t dst, uint16_t net_key_index, + rmt_prov_dkri_procedure_t dkri_procedure); + +/** + * @brief close remote provision link + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] reason: link close reason + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_link_close(uint16_t dst, uint16_t net_key_index, + rmt_prov_link_close_reason_t reason); + +/** + * @brief send remote provision pdu + * @param[in] dst: destination address + * @param[in] net_key_index: network key index + * @param[in] outbound_pdu_num: outbound pdu number + * @param[in] pdata: outbound pdu data + * @param[in] data_len: outbound pdu data length + * @return send result + */ +mesh_msg_send_cause_t rmt_prov_client_pdu_send(uint16_t dst, uint16_t net_key_index, + uint8_t outbound_pdu_num, uint8_t *pdata, uint8_t data_len); + +/** + * @brief handle provision timeout + * @param[in] ptimer: timer handle + */ +void rmt_prov_handle_timeout_prov(void *ptimer); + +/** + * @brief close remote provision link + * @param[in] reason: link close reason + */ +void rmt_prov_link_close(rmt_prov_link_close_reason_t reason); + +/** + * @brief get remote provision client link state + * @return remote provision client link state + */ +rmt_prov_link_state_t rmt_prov_client_link_state(void); + +/** + * @brief get remote provision procedure + * @return remote provision procedure + */ +rmt_prov_procedure_t rmt_prov_client_procedure(void); + +/** + * @brief get remote provision dkri procedure + * @return remote provision dkri procedure + */ +rmt_prov_dkri_procedure_t rmt_prov_dkri_procedure(void); + +/** + * @brief refresh device key + * @param[in] attn_dur: attention duration + * @return refresh status + */ +bool rmt_prov_client_refresh_dev_key(uint8_t attn_dur); + +/** + * @brief refresh node address + * @param[in] node_addr: node address + * @param[in] attn_dur: attention duration + * @return refresh status + */ +bool rmt_prov_client_refresh_node_addr(uint16_t node_addr, uint8_t attn_dur); + +/** + * @brief refresh composition data + * @param[in] attn_dur: attention duration + * @return refresh status + */ +bool rmt_prov_client_refresh_compo_data(uint8_t attn_dur); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* MESH_RPR */ + +#endif /* _REMOTE_PROVISIONING_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene.h new file mode 100644 index 00000000..cf461b1e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene.h @@ -0,0 +1,343 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scene.h +* @brief Head file for scene models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-23 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _SCENE_H_ +#define _SCENE_H_ + + +#include "mesh_api.h" +#include "generic_transition_time.h" + +BEGIN_DECLS + +/** + * @addtogroup SCENE + * @{ + */ + +/** + * @defgroup SCENE_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_SCENE_GET 0x8241 +#define MESH_MSG_SCENE_RECALL 0x8242 +#define MESH_MSG_SCENE_RECALL_UNACK 0x8243 +#define MESH_MSG_SCENE_STATUS 0x5E +#define MESH_MSG_SCENE_REGISTER_GET 0x8244 +#define MESH_MSG_SCENE_REGISTER_STATUS 0x8245 +#define MESH_MSG_SCENE_STORE 0x8246 +#define MESH_MSG_SCENE_STORE_UNACK 0x8247 +#define MESH_MSG_SCENE_DELETE 0x829E +#define MESH_MSG_SCENE_DELETE_UNACK 0x829F +/** @} */ + +/** + * @defgroup SCENE_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_SCENE_SERVER 0x1203FFFF +#define MESH_MODEL_SCENE_SETUP_SERVER 0x1204FFFF +#define MESH_MODEL_SCENE_CLIENT 0x1205FFFF +/** @} */ + +/** + * @defgroup SCENE_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define IS_SCENE_NUMBER_VALID(number) (0x00 != number) + +enum +{ + SCENE_STATUS_SUCCESS, + SCENE_STATUS_REGISTER_FULL, + SCENE_STATUS_NOT_FOUND +} _SHORT_ENUM_; +typedef uint8_t scene_status_code_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_STORE)]; + uint16_t scene_number; +} _PACKED4_ scene_store_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_RECALL)]; + uint16_t scene_number; + uint8_t tid; + generic_transition_time_t trans_time; + uint8_t delay; +} _PACKED4_ scene_recall_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_GET)]; +} _PACKED4_ scene_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_STATUS)]; + scene_status_code_t status; + uint16_t current_scene; + uint16_t target_scene; + generic_transition_time_t remaining_time; +} _PACKED4_ scene_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_REGISTER_GET)]; +} _PACKED4_ scene_register_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_REGISTER_STATUS)]; + scene_status_code_t status; + uint16_t current_scene; + uint16_t scenes[0]; +} _PACKED4_ scene_register_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCENE_DELETE)]; + uint16_t scene_number; +} _PACKED4_ scene_delete_t; + +/** 0 means unused scene number */ +typedef struct +{ + uint16_t scene_number; + void *pmemory; +} scene_storage_memory_t; +/** @} */ + +/** + * @defgroup SCENE_TRANSITION_TYPE Transition Type + * @brief Mesh message transition and delay execution type + * @{ + */ +#define GENERIC_TRANSITION_TYPE_SCENE 0 +#define DELAY_EXECUTION_TYPE_SCENE 0 +/** @} */ + + +/** + * @defgroup SCENE_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define SCENE_SERVER_GET 0 //!< @ref scene_server_get_t +#define SCENE_SERVER_GET_REGISTER_STATUS 1 //!< @ref scene_server_get_register_status_t +#define SCENE_SERVER_GET_DEFAULT_TRANSITION_TIME 2 //!< @ref scene_server_get_default_transition_time_t +#define SCENE_SERVER_STORE 3 //!< @ref scene_server_store_t +#define SCENE_SERVER_RECALL 4 //!< @ref scene_server_recall_t +#define SCENE_SERVER_DELETE 5 //!< @ref scene_server_delete_t + +typedef struct +{ + uint16_t current_scene; +} scene_server_get_t; + +typedef struct +{ + scene_status_code_t status; +} scene_server_get_register_status_t; + +typedef struct +{ + generic_transition_time_t trans_time; +} scene_server_get_default_transition_time_t; + +typedef struct +{ + scene_status_code_t status; + uint16_t scene_number; + void *pmemory; +} scene_server_store_t; + +typedef struct +{ + uint16_t scene_number; + void *pmemory; + generic_transition_time_t total_time; + generic_transition_time_t remaining_time; +} scene_server_recall_t; + +typedef struct +{ + uint16_t scene_number; +} scene_server_delete_t; +/** @} */ + +/** + * @defgroup SCENE_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define SCENE_CLIENT_STATUS 0 //!< @ref scene_client_status_t +#define SCENE_CLIENT_REGISTER_STATUS 1 //!< @ref scene_client_register_status_t + +typedef struct +{ + uint16_t src; + scene_status_code_t status; + uint16_t current_scene; + bool optional; + uint16_t target_scene; + generic_transition_time_t remaining_time; +} scene_client_status_t; + +typedef struct +{ + uint16_t src; + scene_status_code_t status; + uint16_t current_scene; + uint16_t *scene_array; + uint8_t scene_array_len; +} scene_client_register_status_t; +/** @} */ + +/** + * @defgroup SCENE_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register scene server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to scene server model context + * @retval true: register success + * @retval false: register failed + */ +bool scene_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register scene setup server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to scene setup server model context + * @retval true: register success + * @retval false: register failed + */ +bool scene_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); +/** + * @brief publish scene information + * @param[in] pmodel_info: pointer to scene server model context + * @param[in] scene: current scene + * @return publish status + */ +mesh_msg_send_cause_t scene_publish(const mesh_model_info_p pmodel_info, + uint16_t scene); + +/** + * @brief set scene server storage memory + * @param[in] pmodel_info: pointer to scene server model context + * @param[in] scenes: scene storage memeories + * @param[in] num_scenes: number of scenes + */ +void scene_server_set_storage_memory(mesh_model_info_p pmodel_info, scene_storage_memory_t *scenes, + uint16_t num_scenes); + +/** + * @brief set scene setup server storage memory + * @param[in] pmodel_info: pointer to scene setup server model context + * @param[in] scenes: scene storage memeories + * @param[in] num_scenes: number of scenes + */ +void scene_setup_server_set_storage_memory(mesh_model_info_p pmodel_info, + scene_storage_memory_t *scenes, uint16_t num_scenes); +/** @} */ + +/** + * @defgroup SCENE_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register scene client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to scene client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool scene_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief store current state to scene + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] scene_number: desired scene number + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t scene_store(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t scene_number, bool ack); + +/** + * @brief recall specified scene + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] scene_number: desired scene number + * @param[in] tid: transition identify value + * @param[in] optional: represent whether contains transition time or not + * @param[in] trans_time: new transition time + * @param[in] delay: new delay time + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t scene_recall(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t scene_number, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack); +/** + * @brief get scene status + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t scene_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get scene register status + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t scene_register_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief delete scene + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] scene_number: scene number need to be deleted + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t scene_delete(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t scene_number, bool ack); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _SCENE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_client.c new file mode 100644 index 00000000..6bf3cf8c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_client.c @@ -0,0 +1,180 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scene_client.c +* @brief Source file for scene client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-29 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "scene.h" + +static mesh_msg_send_cause_t scene_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t scene_store(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t scene_number, bool ack) +{ + scene_store_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_STORE); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_STORE_UNACK); + } + msg.scene_number = scene_number; + + return scene_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t scene_recall(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t scene_number, uint8_t tid, bool optional, + generic_transition_time_t trans_time, uint8_t delay, bool ack) +{ + scene_recall_t msg; + uint32_t len; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_RECALL); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_RECALL_UNACK); + } + + if (optional) + { + len = sizeof(scene_recall_t); + msg.trans_time = trans_time; + msg.delay = delay; + } + else + { + len = MEMBER_OFFSET(scene_recall_t, trans_time); + } + msg.scene_number = scene_number; + msg.tid = tid; + + return scene_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, len); + +} + +mesh_msg_send_cause_t scene_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + scene_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_GET); + + return scene_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t scene_register_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + scene_register_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_REGISTER_GET); + + return scene_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t scene_delete(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t scene_number, bool ack) +{ + scene_delete_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_DELETE); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_DELETE_UNACK); + } + msg.scene_number = scene_number; + + return scene_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool scene_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SCENE_STATUS: + if (pmesh_msg->msg_len == sizeof(scene_status_t) || + pmesh_msg->msg_len == MEMBER_OFFSET(scene_status_t, target_scene)) + { + scene_status_t *pmsg = (scene_status_t *)pbuffer; + scene_client_status_t status_data; + status_data.src = pmesh_msg->src; + status_data.optional = FALSE; + status_data.status = pmsg->status; + status_data.current_scene = pmsg->current_scene; + if (pmesh_msg->msg_len == sizeof(scene_status_t)) + { + status_data.optional = TRUE; + status_data.target_scene = pmsg->target_scene; + status_data.remaining_time = pmsg->remaining_time; + } + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_SCENE_REGISTER_STATUS: + { + scene_register_status_t *pmsg = (scene_register_status_t *)pbuffer; + scene_client_register_status_t status_data = {pmesh_msg->src, (scene_status_code_t)(pmsg->status), pmsg->current_scene, pmsg->scenes}; + status_data.scene_array_len = (pmesh_msg->msg_len - MEMBER_OFFSET(scene_register_status_t, + scenes)) / sizeof(uint16_t); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_CLIENT_REGISTER_STATUS, &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool scene_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SCENE_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = scene_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("scene_client_reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_server.c new file mode 100644 index 00000000..d3a82307 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_server.c @@ -0,0 +1,573 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scene_server.c +* @brief Source file for scene server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-23 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "scene.h" +#include "generic_types.h" +#include "delay_execution.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +typedef struct +{ + scene_storage_memory_t *scenes; + uint16_t num_scenes; + scene_status_code_t status_recall; + uint16_t target_scene; + generic_transition_time_t trans_time; + uint32_t delay_time; + scene_storage_memory_t *state_memory; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} scene_info_t; + +typedef struct +{ + bool state_changed; + bool use_transition; +} scene_process_result_t; + + +void scene_server_set_storage_memory(mesh_model_info_p pmodel_info, scene_storage_memory_t *scenes, + uint16_t num_scenes) +{ + scene_info_t *pinfo = pmodel_info->pargs; + pinfo->scenes = scenes; + pinfo->num_scenes = num_scenes; +} + +static scene_storage_memory_t *scene_storage_memory_get(const mesh_model_info_p pmodel_info, + uint16_t scene_number) +{ + scene_info_t *pinfo = pmodel_info->pargs; + for (uint16_t i = 0; i < pinfo->num_scenes; ++i) + { + if (pinfo->scenes[i].scene_number == scene_number) + { + return &pinfo->scenes[i]; + } + } + + return NULL; +} + +static mesh_msg_send_cause_t scene_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, void *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t scene_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, scene_status_code_t status, uint16_t current_scene, + bool optional, uint16_t target_scene, + generic_transition_time_t remaining_time, uint32_t delay_time) +{ + scene_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCENE_STATUS); + uint16_t msg_len; + if (optional) + { + msg_len = sizeof(scene_status_t); + msg.target_scene = target_scene; + msg.remaining_time = remaining_time; + } + else + { + msg_len = MEMBER_OFFSET(scene_status_t, target_scene); + } + msg.status = status; + msg.current_scene = current_scene; + + return scene_server_send(pmodel_info, dst, &msg, msg_len, app_key_index, delay_time); +} + +mesh_msg_send_cause_t scene_register_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + scene_status_code_t status, uint16_t current_scene, + uint32_t delay_time) +{ + scene_info_t *pinfo = pmodel_info->pargs; + scene_register_status_t *pmsg = plt_malloc(sizeof(scene_register_status_t) + pinfo->num_scenes * + sizeof(uint16_t), RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SCENE_REGISTER_STATUS); + pmsg->status = status; + pmsg->current_scene = current_scene; + uint16_t valid_scene_count = 0; + for (uint16_t i = 0; i < pinfo->num_scenes; ++i) + { + if (IS_SCENE_NUMBER_VALID(pinfo->scenes[i].scene_number)) + { + pmsg->scenes[valid_scene_count] = pinfo->scenes[i].scene_number; + valid_scene_count ++; + } + } + uint16_t msg_len = sizeof(scene_register_status_t) + valid_scene_count * sizeof(uint16_t); + + mesh_msg_send_cause_t cause = scene_server_send(pmodel_info, dst, pmsg, msg_len, app_key_index, + delay_time); + plt_free(pmsg, RAM_DATA_TYPE_OFF); + return cause; +} + +mesh_msg_send_cause_t scene_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t scene, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + generic_transition_time_t trans_time = {0, 0}; + ret = scene_status(pmodel_info, 0, 0, SCENE_STATUS_SUCCESS, scene, FALSE, scene, trans_time, + delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t scene_publish(const mesh_model_info_p pmodel_info, + uint16_t scene) +{ + return scene_delay_publish(pmodel_info, scene, 0); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +static void scene_state_change_publish(const mesh_model_info_p pmodel_info, + uint16_t scene, scene_process_result_t result) +{ + if (result.use_transition) + { + return ; + } + +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + scene_publish(pmodel_info, scene); + } +} +#endif + +uint16_t get_current_scene(const mesh_model_info_p pmodel_info) +{ + scene_server_get_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_GET, &get_data); + } + + return get_data.current_scene; +} + +static int32_t scene_trans_step_change(const mesh_model_info_p pmodel_info, uint32_t type, + generic_transition_time_t total_time, + generic_transition_time_t remaining_time) +{ + /* avoid gcc compile warning */ + (void)type; + int32_t ret = MODEL_SUCCESS; + scene_info_t *pinfo = pmodel_info->pargs; + if (NULL == pinfo) + { + return 0; + } + scene_storage_memory_t *state_memory = scene_storage_memory_get(pmodel_info, pinfo->target_scene); + scene_server_recall_t set_data; + if (NULL != state_memory) + { + set_data.scene_number = pinfo->target_scene; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + set_data.pmemory = state_memory->pmemory; + } + else + { + /* scene has been deleted before transition done */ + set_data.scene_number = 0; + set_data.total_time = total_time; + set_data.remaining_time = remaining_time; + set_data.pmemory = NULL; + } + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_RECALL, &set_data); + } + + /* scene transition shall be terminated when target scene has bee deleted */ + if (NULL == state_memory) + { + ret = MODEL_STOP_TRANSITION; + } + + if (0 == remaining_time.num_steps) + { + uint16_t current_scene = get_current_scene(pmodel_info); +#if MODEL_ENABLE_DELAY_MSG_RSP + scene_delay_publish(pmodel_info, current_scene, pinfo->delay_pub_time); +#else + scene_publish(pmodel_info, current_scene); +#endif + } + + return ret; +} + +static uint16_t scene_process(const mesh_model_info_p pmodel_info, + const scene_storage_memory_t *state_memory, + uint16_t target_scene, + generic_transition_time_t trans_time, + scene_process_result_t *presult) +{ + uint16_t scene_before_set; + uint16_t scene_after_set = 0; + + /* get scene before set */ + scene_before_set = get_current_scene(pmodel_info); + scene_after_set = scene_before_set; + + int32_t ret = MODEL_SUCCESS; + scene_server_recall_t trans_set_data; + trans_set_data.total_time = trans_time; + trans_set_data.remaining_time = trans_time; + trans_set_data.scene_number = target_scene; + trans_set_data.pmemory = state_memory->pmemory; + + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_RECALL, &trans_set_data); + } + + if (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE != trans_time.num_steps) + { + if ((ret >= 0) && (MODEL_STOP_TRANSITION != ret)) + { +#if MODEL_ENABLE_PUBLISH_ALL_TIME + if (NULL != presult) + { + presult->use_transition = TRUE; + } +#endif + generic_transition_timer_start(pmodel_info, GENERIC_TRANSITION_TYPE_SCENE, trans_time, + scene_trans_step_change); + } +#if MODEL_ENABLE_USER_STOP_TRANSITION_NOTIFICATION + else if (MODEL_STOP_TRANSITION == ret) + { + if (NULL != pmodel_info->model_data_cb) + { + ret = pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_RECALL, &trans_set_data); + } + } +#endif + } + else + { + /* get scene after set */ + scene_after_set = get_current_scene(pmodel_info); + } + + if (scene_before_set != scene_after_set) + { + if (NULL != presult) + { + presult->state_changed = TRUE; + } + } + + return scene_after_set; +} + +static int32_t scene_delay_execution(mesh_model_info_t *pmodel_info, uint32_t delay_type) +{ + switch (delay_type) + { + case DELAY_EXECUTION_TYPE_SCENE: + { + scene_info_t *pinfo = pmodel_info->pargs; + if (NULL == pinfo) + { + return 0; + } + pinfo->delay_time = 0; + uint16_t present_scene = 0; + scene_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + present_scene = scene_process(pmodel_info, pinfo->state_memory, pinfo->target_scene, + pinfo->trans_time, &result); +#if MODEL_ENABLE_DELAY_MSG_RSP + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + scene_delay_publish(pmodel_info, present_scene, pinfo->delay_pub_time); + } + } +#else + scene_state_change_publish(pmodel_info, present_scene, result); +#endif + } + break; + default: + break; + } + + return 0; +} + +static bool scene_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SCENE_GET: + if (pmesh_msg->msg_len == sizeof(scene_get_t)) + { + uint16_t current_scene = 0; + scene_info_t *pinfo = pmodel_info->pargs; + generic_transition_time_t remaining_time; + if (pinfo->delay_time > 0) + { + remaining_time = pinfo->trans_time; + } + else + { + remaining_time = generic_transition_time_get(pmesh_msg->pmodel_info, + GENERIC_TRANSITION_TYPE_SCENE); + if (0 == remaining_time.num_steps) + { + current_scene = get_current_scene(pmodel_info); + } + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + scene_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->status_recall, current_scene, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == remaining_time.num_steps) ? FALSE : TRUE, + pinfo->target_scene, remaining_time, delay_rsp_time); + } + break; + case MESH_MSG_SCENE_RECALL: + case MESH_MSG_SCENE_RECALL_UNACK: + if ((pmesh_msg->msg_len == MEMBER_OFFSET(scene_recall_t, trans_time)) || + (pmesh_msg->msg_len == sizeof(scene_recall_t))) + { + scene_recall_t *pmsg = (scene_recall_t *)pbuffer; + if (IS_SCENE_NUMBER_VALID(pmsg->scene_number)) + { + generic_transition_time_t trans_time = {GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE, 0}; + uint32_t delay_time = 0; + if (pmesh_msg->msg_len == MEMBER_OFFSET(scene_recall_t, trans_time)) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_GET_DEFAULT_TRANSITION_TIME, + &trans_time); + } + } + else + { + trans_time = pmsg->trans_time; + delay_time = pmsg->delay * DELAY_EXECUTION_STEP_RESOLUTION; + } + if (IS_GENERIC_TRANSITION_STEPS_VALID(trans_time.num_steps)) + { + scene_info_t *pinfo = pmodel_info->pargs; + uint16_t current_scene = 0; + pinfo->target_scene = pmsg->scene_number; + scene_storage_memory_t *state_memory = scene_storage_memory_get(pmodel_info, pmsg->scene_number); + pinfo->trans_time = trans_time; + pinfo->delay_time = delay_time; + pinfo->state_memory = state_memory; + scene_process_result_t result = + { + .state_changed = FALSE, + .use_transition = FALSE + }; + + if (NULL != state_memory) + { + if (delay_time > 0) + { + result.use_transition = TRUE; + current_scene = 0; + delay_execution_timer_start(pmodel_info, DELAY_EXECUTION_TYPE_SCENE, delay_time, + scene_delay_execution); + } + else + { + current_scene = scene_process(pmodel_info, state_memory, pmsg->scene_number, trans_time, &result); + } + pinfo->status_recall = SCENE_STATUS_SUCCESS; + } + else + { + current_scene = get_current_scene(pmodel_info); + pinfo->status_recall = SCENE_STATUS_NOT_FOUND; + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (MESH_MSG_SCENE_RECALL == pmesh_msg->access_opcode) + { + scene_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->status_recall, current_scene, + (GENERIC_TRANSITION_NUM_STEPS_IMMEDIATE == trans_time.num_steps) ? FALSE : TRUE, + pmsg->scene_number, trans_time, delay_rsp_time); + } +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_SCENE_RECALL_UNACK) ? FALSE : TRUE; + if (!result.use_transition) + { +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + uint32_t delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, TRUE, + ack); + scene_delay_publish(pmodel_info, current_scene, delay_pub_time); + } + } + else + { + pinfo->delay_pub_time = delay_msg_get_trans_delay(delay_time, trans_time, delay_rsp_time, FALSE, + ack); + } +#else + scene_state_change_publish(pmodel_info, current_scene, result); +#endif + } + } + } + break; + case MESH_MSG_SCENE_REGISTER_GET: + if (pmesh_msg->msg_len == sizeof(scene_register_get_t)) + { + uint16_t current_scene = get_current_scene(pmodel_info); + scene_server_get_register_status_t get_data = {SCENE_STATUS_SUCCESS}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_GET_REGISTER_STATUS, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + scene_register_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_data.status, current_scene, delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t scene_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + generic_transition_time_t trans_time = {0, 0}; + scene_status(pmodel_info, 0, 0, SCENE_STATUS_SUCCESS, get_current_scene(pmodel_info), FALSE, 0, + trans_time, 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void scene_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == scene_server_receive) + { + /* stop delay execution */ + delay_execution_timer_stop(pmodel_info, DELAY_EXECUTION_TYPE_SCENE); + /* stop step transition */ + generic_transition_timer_stop(pmodel_info, GENERIC_TRANSITION_TYPE_SCENE); + + /* now we can remove */ + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + pmodel_info->model_receive = NULL; + } +} +#endif + +bool scene_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SCENE_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(scene_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("scene_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(scene_info_t)); + + pmodel_info->model_receive = scene_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("scene_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = scene_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = scene_server_publish; + } + + generic_transition_time_init(); + delay_execution_init(); + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_setup_server.c new file mode 100644 index 00000000..56481bbe --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_setup_server.c @@ -0,0 +1,226 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scene_setup_server.c +* @brief Source file for scene setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-23 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "scene.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + + +typedef struct +{ + scene_storage_memory_t *scenes; + uint16_t num_scenes; + scene_status_code_t status_register; +} scene_setup_info_t; + + +extern uint16_t get_current_scene(const mesh_model_info_p pmodel_info); +extern mesh_msg_send_cause_t scene_register_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + scene_status_code_t status, uint16_t current_scene, + uint32_t delay_time); + + + +void scene_setup_server_set_storage_memory(mesh_model_info_p pmodel_info, + scene_storage_memory_t *scenes, uint16_t num_scenes) +{ + scene_setup_info_t *info = pmodel_info->pargs; + info->scenes = scenes; + info->num_scenes = num_scenes; +} + +static bool scene_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SCENE_STORE: + case MESH_MSG_SCENE_STORE_UNACK: + if (pmesh_msg->msg_len == sizeof(scene_store_t)) + { + scene_store_t *pmsg = (scene_store_t *)pbuffer; + if (IS_SCENE_NUMBER_VALID(pmsg->scene_number)) + { + scene_setup_info_t *pinfo = pmodel_info->pargs; + uint16_t index = 0; + uint16_t empty_index = pinfo->num_scenes; + /* find store place */ + for (index = 0; index < pinfo->num_scenes; ++index) + { + if (0 == pinfo->scenes[index].scene_number) + { + /* store to last empty location, just for easy process */ + empty_index = index; + } + + if (pmsg->scene_number == pinfo->scenes[index].scene_number) + { + break; + } + } + + scene_server_store_t store_data = {SCENE_STATUS_SUCCESS, pmsg->scene_number}; + pinfo->status_register = SCENE_STATUS_SUCCESS; + store_data.status = SCENE_STATUS_SUCCESS; + if (index < pinfo->num_scenes) + { + /* update exists */ + store_data.pmemory = pinfo->scenes[index].pmemory; + } + else if (empty_index < pinfo->num_scenes) + { + /* store new */ + store_data.scene_number = pmsg->scene_number; + pinfo->scenes[empty_index].scene_number = pmsg->scene_number; + store_data.pmemory = pinfo->scenes[empty_index].pmemory; + } + else + { + /* no place for store */ + pinfo->status_register = SCENE_STATUS_REGISTER_FULL; + store_data.status = SCENE_STATUS_REGISTER_FULL; + store_data.scene_number = 0; + store_data.pmemory = NULL; + } + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_STORE, &store_data); + } + + if (MESH_MSG_SCENE_STORE == pmesh_msg->access_opcode) + { + uint16_t current_scene = get_current_scene(pmodel_info); + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + scene_register_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->status_register, current_scene, delay_rsp_time); + } + } + } + break; + case MESH_MSG_SCENE_DELETE: + case MESH_MSG_SCENE_DELETE_UNACK: + if (pmesh_msg->msg_len == sizeof(scene_delete_t)) + { + scene_delete_t *pmsg = (scene_delete_t *)pbuffer; + if (IS_SCENE_NUMBER_VALID(pmsg->scene_number)) + { + /* find store index */ + scene_setup_info_t *pinfo = pmodel_info->pargs; + uint16_t index = 0; + for (index = 0; index < pinfo->num_scenes; ++index) + { + if (pmsg->scene_number == pinfo->scenes[index].scene_number) + { + break; + } + } + + pinfo->status_register = SCENE_STATUS_SUCCESS; + if (index < pinfo->num_scenes) + { + /* delete exists */ + pinfo->scenes[index].scene_number = 0; + } + else + { + /* no scene found */ + pinfo->status_register = SCENE_STATUS_NOT_FOUND; + } + + if (SCENE_STATUS_SUCCESS == pinfo->status_register) + { + scene_server_delete_t delete_data = {pmsg->scene_number}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCENE_SERVER_DELETE, &delete_data); + } + } + + if (MESH_MSG_SCENE_DELETE == pmesh_msg->access_opcode) + { + uint16_t current_scene = get_current_scene(pmodel_info); + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + scene_register_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pinfo->status_register, current_scene, delay_rsp_time); + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void scene_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == scene_setup_server_receive) + { + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool scene_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SCENE_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(scene_setup_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("scene_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(scene_setup_info_t)); + + pmodel_info->model_receive = scene_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("scene_server_reg: missing model data process callback!"); + } + +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = scene_setup_server_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler.h new file mode 100644 index 00000000..af329246 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler.h @@ -0,0 +1,295 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scheduler.h +* @brief Head file for scheduler models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-9-14 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _SCHEDULER_H_ +#define _SCHEDULER_H_ + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup SCHEDULER + * @{ + */ + +/** + * @defgroup SCHEDULER_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_SCHEDULER_ACTION_GET 0x8248 +#define MESH_MSG_SCHEDULER_ACTION_STATUS 0x5F +#define MESH_MSG_SCHEDULER_GET 0x8249 +#define MESH_MSG_SCHEDULER_STATUS 0x824A +#define MESH_MSG_SCHEDULER_ACTION_SET 0x60 +#define MESH_MSG_SCHEDULER_ACTION_SET_UNACK 0x61 +/** @} */ + +/** + * @defgroup SCHEDULER_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_SCHEDULER_SERVER 0x1206FFFF +#define MESH_MODEL_SCHEDULER_SETUP_SERVER 0x1207FFFF +#define MESH_MODEL_SCHEDULER_CLIENT 0x1208FFFF +/** @} */ + +/** @defgroup SCHEDULER_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ + +#define IS_SCHEDULER_INDEX_VALID(index) ((index <= 15)) + +/* scheduler year */ +#define SCHEDULER_EVERY_YEAR 0x64 +#define IS_SCHEDULER_YEAR_VALIE(year) ((year) <= 0x64) + +/* scheduler month */ +#define SCHEDULER_IN_JANUARY (1 << 0) +#define SCHEDULER_IN_FEBRUARY (1 << 1) +#define SCHEDULER_IN_MARCH (1 << 2) +#define SCHEDULER_IN_APRIL (1 << 3) +#define SCHEDULER_IN_MAY (1 << 4) +#define SCHEDULER_IN_JUNE (1 << 5) +#define SCHEDULER_IN_JULY (1 << 6) +#define SCHEDULER_IN_AUGUST (1 << 7) +#define SCHEDULER_IN_SETEMBER (1 << 8) +#define SCHEDULER_IN_OCTOBER (1 << 9) +#define SCHEDULER_IN_NOVEMBER (1 << 10) +#define SCHEDULER_IN_DECEMBER (1 << 11) +#define SCHEDULER_EVERY_MONTH 0x0FFF + +/* scheduler day */ +#define SCHEDULER_EVERY_DAY 0x00 + +/* scheduler hour */ +#define SCHEDULER_EVERY_HOUR 0x18 +#define SCHEDULER_RANDOM_HOUR 0x19 +#define IS_SCHEDULER_HOUR_VALID(hour) ((hour) <= 0x19) + +/* scheduler minute */ +#define SCHEDULER_EVERY_MINUTE 0x3C +#define SCHEDULER_EVERY_15_MINUTE 0x3D +#define SCHEDULER_EVERY_20_MINUTE 0x3E +#define SCHEDULER_RADOM_MINUTE 0x3F + +/* scheduler second */ +#define SCHEDULER_EVERY_SECOND 0x3C +#define SCHEDULER_EVERY_15_SECOND 0x3D +#define SCHEDULER_EVERY_20_SECOND 0x3E +#define SCHEDULER_RANDOM_SECOND 0x3F + +/* scheduler day of week */ +#define SCHEDULER_ON_MONDAYS (1 << 0) +#define SCHEDULER_ON_TUESDAYS (1 << 1) +#define SCHEDULER_ON_WEDNESDAYS (1 << 2) +#define SCHEDULER_ON_THURSDAYS (1 << 3) +#define SCHEDULER_ON_FRIDAYS (1 << 4) +#define SCHEDULER_ON_SATURDAYS (1 << 5) +#define SCHEDULER_ON_SUNDAYS (1 << 6) + +/* scheduler action */ +#define SCHEDULER_TURN_OFF 0x00 +#define SCHEDULER_TURN_ON 0x01 +#define SCHEDULER_SCENE_RECALL 0x02 +#define SCHEDULER_NO_ACTION 0x0F + +/* scheduler scene */ +#define SCHEDULER_NO_SCENE 0x00 + +typedef struct +{ + uint64_t index: 4; + uint64_t year: 7; + uint64_t month: 12; + uint64_t day: 5; + uint64_t hour: 5; + uint64_t minute: 6; + uint64_t second: 6; + uint64_t day_of_week: 7; + uint64_t action: 4; + uint64_t num_steps: 6; + uint64_t step_resolution: 2; + uint16_t scene_number; +} _PACKED4_ scheduler_register_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCHEDULER_GET)]; +} _PACKED4_ scheduler_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCHEDULER_STATUS)]; + uint16_t schedulers; +} _PACKED4_ scheduler_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCHEDULER_ACTION_GET)]; + uint8_t index; +} _PACKED4_ scheduler_action_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCHEDULER_ACTION_SET)]; + scheduler_register_t scheduler; +} _PACKED4_ scheduler_action_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SCHEDULER_ACTION_STATUS)]; + scheduler_register_t scheduler; +} _PACKED4_ scheduler_action_status_t; + +/** @} */ + + +/** + * @defgroup SCHEDULER_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define SCHEDULER_SERVER_GET 0 //!< @ref scheduler_server_get_t +#define SCHEDULER_SERVER_GET_ACTION 1 //!< @ref scheduler_server_get_action_t +#define SCHEDULER_SERVER_SET_ACTION 2 //!< @ref scheduler_server_set_action_t + +typedef struct +{ + uint16_t schedulers; +} scheduler_server_get_t; + +typedef struct +{ + uint8_t index; + scheduler_register_t scheduler; +} scheduler_server_get_action_t; + +typedef scheduler_register_t scheduler_server_set_action_t; + +/** @} */ + +/** + * @defgroup SCHEDULER_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define SCHEDULER_CLIENT_STATUS 0 //!< @ref scheduler_client_status_t +#define SCHEDULER_CLIENT_STATUS_ACTION 1 //!< @ref scheduler_client_status_action_t + +typedef struct +{ + uint16_t src; + uint16_t schedulers; +} scheduler_client_status_t; + +typedef struct +{ + uint16_t src; + scheduler_register_t scheduler; +} scheduler_client_status_action_t; + +/** @} */ + +/** + * @defgroup SCHEDULER_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register scheduler server model + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to scheduler server model context + * @retval true: register success + * @retval false: register failed + */ +bool scheduler_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register scheduler setup server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to scheduler setup server model context + * @retval true: register success + * @retval false: register failed + */ +bool scheduler_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish scene information + * @param[in] pmodel_info: pointer to scheduler server model context + * @param[in] scheduler: current scheduler + * @return publish status + */ +mesh_msg_send_cause_t scheduler_publish(const mesh_model_info_p pmodel_info, + scheduler_register_t scheduler); + +/** @} */ + +/** + * @defgroup SCHEDULER_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register scheduler client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to scheduler client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool scheduler_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get scheduler status + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t scheduler_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get scheduler action + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] index: action index + * @return send status + */ +mesh_msg_send_cause_t scheduler_action_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t index); + +/** + * @brief set scheduler action + * @param[in] pmodel_info: pointer to scene client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] scheduler: scheduler need to be setted + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t scheduler_action_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, scheduler_register_t scheduler, + bool ack); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _SCHEDULER_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_client.c new file mode 100644 index 00000000..39164a3e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_client.c @@ -0,0 +1,121 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scheduler_client.c +* @brief Source file for scheduler client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-9-17 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "scheduler.h" + +static mesh_msg_send_cause_t scheduler_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, uint8_t *pmsg, + uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t scheduler_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + scheduler_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCHEDULER_GET); + return scheduler_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t scheduler_action_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t index) +{ + scheduler_action_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCHEDULER_ACTION_GET); + msg.index = index; + return scheduler_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t scheduler_action_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, scheduler_register_t scheduler, + bool ack) +{ + scheduler_action_set_t msg; + if (ack) + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCHEDULER_ACTION_SET); + } + else + { + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCHEDULER_ACTION_SET_UNACK); + } + msg.scheduler = scheduler; + return scheduler_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool scheduler_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SCHEDULER_STATUS: + if (pmesh_msg->msg_len == sizeof(scheduler_status_t)) + { + scheduler_status_t *pmsg = (scheduler_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + scheduler_client_status_t status_data = {pmesh_msg->src, 0}; + status_data.schedulers = pmsg->schedulers; + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_SCHEDULER_ACTION_STATUS: + if (pmesh_msg->msg_len == sizeof(scheduler_action_status_t)) + { + scheduler_action_status_t *pmsg = (scheduler_action_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + scheduler_client_status_action_t status_data; + status_data.src = pmesh_msg->src; + status_data.scheduler = pmsg->scheduler; + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_CLIENT_STATUS_ACTION, &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool scheduler_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SCHEDULER_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = scheduler_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("scheduler_client_reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_server.c new file mode 100644 index 00000000..a17423a1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_server.c @@ -0,0 +1,222 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scheduler_server.c +* @brief Source file for scheduler server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-9-14 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "scheduler.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#if 0 +typedef struct +{ + uint8_t tid; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} scheduler_info_t; +#endif + +static mesh_msg_send_cause_t scheduler_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, void *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t scheduler_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t schedulers, + uint32_t delay_time) +{ + scheduler_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCHEDULER_STATUS); + msg.schedulers = schedulers; + + return scheduler_server_send(pmodel_info, dst, &msg, sizeof(msg), app_key_index, delay_time); +} + +mesh_msg_send_cause_t scheduler_action_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, scheduler_register_t scheduler, + uint32_t delay_time) +{ + scheduler_action_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SCHEDULER_ACTION_STATUS); + msg.scheduler = scheduler; + + return scheduler_server_send(pmodel_info, dst, &msg, sizeof(msg), app_key_index, delay_time); +} + +mesh_msg_send_cause_t scheduler_delay_publish(const mesh_model_info_p pmodel_info, + scheduler_register_t scheduler, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = scheduler_action_status(pmodel_info, 0, 0, scheduler, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t scheduler_publish(const mesh_model_info_p pmodel_info, + scheduler_register_t scheduler) +{ + return scheduler_delay_publish(pmodel_info, scheduler, 0); +} + +static bool scheduler_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SCHEDULER_GET: + if (pmesh_msg->msg_len == sizeof(scheduler_get_t)) + { + scheduler_server_get_t get_data = {0}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_SERVER_GET, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + scheduler_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_data.schedulers, + delay_rsp_time); + } + break; + case MESH_MSG_SCHEDULER_ACTION_GET: + if (pmesh_msg->msg_len == sizeof(scheduler_action_get_t)) + { + scheduler_action_get_t *pmsg = (scheduler_action_get_t *)pbuffer; + if (IS_SCHEDULER_INDEX_VALID(pmsg->index)) + { + scheduler_server_get_action_t get_data; + memset(&get_data, 0, sizeof(get_data)); + if (NULL != pmodel_info->model_data_cb) + { + get_data.index = pmsg->index; + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_SERVER_GET_ACTION, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + scheduler_action_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_data.scheduler, + delay_rsp_time); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t scheduler_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + scheduler_server_get_action_t get_data; + scheduler_server_get_action_t get_data_zero; + memset(&get_data_zero, 0, sizeof(scheduler_server_get_action_t)); + if (NULL != pmodel_info->model_data_cb) + { + for (uint8_t i = 0; i < 15; ++i) + { + memset(&get_data, 0, sizeof(scheduler_server_get_action_t)); + get_data.index = i; + get_data_zero.index = i; + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_SERVER_GET_ACTION, &get_data); + if (0 != memcmp(&get_data, &get_data_zero, sizeof(scheduler_server_get_action_t))) + { + scheduler_action_status(pmodel_info, 0, 0, get_data.scheduler, 0); + } + } + } + + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void scheduler_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == scheduler_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool scheduler_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SCHEDULER_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + pmodel_info->pargs = plt_malloc(sizeof(scheduler_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("scheduler_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(scheduler_info_t)); +#endif + pmodel_info->model_receive = scheduler_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("scheduler_server_reg: missing model data process callback!"); + } + +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = scheduler_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = scheduler_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_setup_server.c new file mode 100644 index 00000000..d5782abc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_setup_server.c @@ -0,0 +1,213 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file scheduler_setup_server.c +* @brief Source file for scheduler setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-9-14 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "scheduler.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#if 0 +typedef struct +{ + uint8_t tid; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} scheduler_info_t; +#endif + +extern mesh_msg_send_cause_t scheduler_action_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, scheduler_register_t scheduler, + uint32_t delay_time); +extern mesh_msg_send_cause_t scheduler_delay_publish(const mesh_model_info_p pmodel_info, + scheduler_register_t scheduler, uint32_t delay_time); + + +typedef struct +{ + bool state_changed; +} scheduler_process_result_t; + +static bool scheduler_check_parameter(const scheduler_register_t *pscheduler) +{ + if (!IS_SCHEDULER_INDEX_VALID(pscheduler->index)) + { + return FALSE; + } + + if (!IS_SCHEDULER_YEAR_VALIE(pscheduler->year)) + { + return FALSE; + } + + if (!IS_SCHEDULER_HOUR_VALID(pscheduler->hour)) + { + return FALSE; + } + + return TRUE; +} + +static bool scheduler_is_same(const scheduler_register_t *psrc, const scheduler_register_t *pdst) +{ + return ((psrc->index == pdst->index) && + (psrc->year == pdst->year) && + (psrc->month == pdst->month) && + (psrc->day == pdst->day) && + (psrc->hour == pdst->hour) && + (psrc->minute == pdst->minute) && + (psrc->second == pdst->second) && + (psrc->day_of_week == pdst->day_of_week) && + (psrc->action == pdst->action) && + (psrc->num_steps == pdst->num_steps) && + (psrc->step_resolution == pdst->step_resolution) && + (psrc->scene_number == pdst->scene_number)); +} + +#if !MODEL_ENABLE_DELAY_MSG_RSP +void scheduler_state_change_publish(const mesh_model_info_p pmodel_info, + scheduler_register_t scheduler, scheduler_process_result_t result) +{ +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + scheduler_publish(pmodel_info, scheduler); + } +} +#endif + +static bool scheduler_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SCHEDULER_ACTION_SET: + case MESH_MSG_SCHEDULER_ACTION_SET_UNACK: + if (pmesh_msg->msg_len == sizeof(scheduler_action_set_t)) + { + scheduler_action_set_t *pmsg = (scheduler_action_set_t *)pbuffer; + if (scheduler_check_parameter(&pmsg->scheduler)) + { + scheduler_server_get_action_t get_data; + memset(&get_data, 0, sizeof(scheduler_server_get_action_t)); + get_data.index = pmsg->scheduler.index; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_SERVER_GET_ACTION, &get_data); + scheduler_server_set_action_t set_data; + memset(&set_data, 0, sizeof(scheduler_server_set_action_t)); + set_data = pmsg->scheduler; + pmodel_info->model_data_cb(pmodel_info, SCHEDULER_SERVER_SET_ACTION, &set_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (MESH_MSG_SCHEDULER_ACTION_SET == pmesh_msg->access_opcode) + { + scheduler_action_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, pmsg->scheduler, + delay_rsp_time); + } + + scheduler_process_result_t result = + { + .state_changed = FALSE, + }; + if (!scheduler_is_same(&get_data.scheduler, &pmsg->scheduler)) + { + result.state_changed = TRUE; + } + +#if MODEL_ENABLE_DELAY_MSG_RSP + generic_transition_time_t trans_time = {0, 0}; + bool ack = (pmesh_msg->access_opcode == MESH_MSG_SCHEDULER_ACTION_SET_UNACK) ? FALSE : TRUE; +#if !MODEL_ENABLE_PUBLISH_ALL_TIME + if (result.state_changed) +#endif + { + (void)result.state_changed; /* fix warning */ + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, ack); + scheduler_delay_publish(pmodel_info, pmsg->scheduler, delay_pub_time); + } +#else + scheduler_state_change_publish(pmodel_info, pmsg->scheduler, result); +#endif + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void scheduler_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == scheduler_setup_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool scheduler_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SCHEDULER_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + +#if 0 + pmodel_info->pargs = plt_malloc(sizeof(scheduler_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("scheduler_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(scheduler_info_t)); +#endif + + pmodel_info->model_receive = scheduler_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("scheduler_server_reg: missing model data process callback!"); + } + +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = scheduler_setup_server_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor.h new file mode 100644 index 00000000..0c13627b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor.h @@ -0,0 +1,635 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file sensor.h +* @brief Head file for sensor models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-29 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _SENSOR_H_ +#define _SENSOR_H_ + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup SENSOR + * @{ + */ + +/** + * @defgroup SENSOR_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_SENSOR_DESCRIPTOR_GET 0x8230 +#define MESH_MSG_SENSOR_DESCRIPTOR_STATUS 0x51 +#define MESH_MSG_SENSOR_GET 0x8231 +#define MESH_MSG_SENSOR_STATUS 0x52 +#define MESH_MSG_SENSOR_COLUMN_GET 0x8232 +#define MESH_MSG_SENSOR_COLUMN_STATUS 0x53 +#define MESH_MSG_SENSOR_SERIES_GET 0x8233 +#define MESH_MSG_SENSOR_SERIES_STATUS 0x54 +#define MESH_MSG_SENSOR_CADENCE_GET 0x8234 +#define MESH_MSG_SENSOR_CADENCE_SET 0x55 +#define MESH_MSG_SENSOR_CADENCE_SET_UNACK 0x56 +#define MESH_MSG_SENSOR_CADENCE_STATUS 0x57 +#define MESH_MSG_SENSOR_SETTINGS_GET 0x8235 +#define MESH_MSG_SENSOR_SETTINGS_STATUS 0x58 +#define MESH_MSG_SENSOR_SETTING_GET 0x8236 +#define MESH_MSG_SENSOR_SETTING_SET 0x59 +#define MESH_MSG_SENSOR_SETTING_SET_UNACK 0x5A +#define MESH_MSG_SENSOR_SETTING_STATUS 0x5B +/** @} */ + +/** + * @defgroup SENSOR_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_SENSOR_SERVER 0x1100FFFF +#define MESH_MODEL_SENSOR_SETUP_SERVER 0x1101FFFF +#define MESH_MODEL_SENSOR_CLIENT 0x1102FFFF +/** @} */ + +/** + * @defgroup SENSOR_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define SENSOR_PROPERTY_ID_INVALID 0 +#define SENSOR_SETTING_PROPERTY_ID_INVALID 0 +#define SENSOR_MEASUREMENT_PERIOD_NOT_APPLICABLE 0 +#define IS_SENSOR_PROPERTY_ID_VALID(id) ((id) != SENSOR_PROPERTY_ID_INVALID) +#define IS_SENSOR_SETTING_PROPERTY_ID_VALID(id) ((id) != SENSOR_SETTING_PROPERTY_ID_INVALID) +#define IS_FAST_CADENCE_DIVISIOR_VALID(divisor) ((divisor) <= 15) +#define IS_STATUS_MIN_INTERVAL_VALID(interval) ((interval) <= 26) + +typedef enum +{ + SENSOR_SAMPLING_UNSPECIFIED, + SENSOR_SAMPLING_INSTANTANEOUS, + SENSOR_SAMPLING_ARITHMETIC_MEAN, + SENSOR_SAMPLING_RMS, + SENSOR_SAMPLING_MAXIMUM, + SENSOR_SAMPLING_MINIMUM, + SENSOR_SAMPLING_ACCUMULATED, + SENSOR_SAMPLING_COUNT, +} sensor_sampling_function_t; + +enum +{ + SENSOR_SETTING_ACCESS_READ_ONLY = 0x01, + SENSOR_SETTING_ACCESS_READ_WRITE = 0x03, +} _SHORT_ENUM_; +typedef uint8_t sensor_setting_access_t; + +typedef enum +{ + /** + * trigger value format is the same as characterstic that + * sensor property id state reference + */ + SENSOR_TRIGGER_TYPE_CHARACTERISTIC, + + /** + * trigger value is unitless, the format type is uint16_t, + * and the value is represented as percentage change with + * a resilution of 0.01 percent + */ + SENSOR_TRIGGER_TYPE_UNITLESS, +} sensor_trigger_type_t; + +typedef struct +{ + uint16_t property_id; + uint32_t positive_tolerance: 12; + uint32_t negative_tolerance: 12; + uint32_t sampling_function: 8; /**< @ref sensor_sampling_function_t */ + uint8_t measurement_period; + uint8_t update_interval; +} _PACKED4_ sensor_descriptor_t; + +typedef struct +{ + uint16_t setting_property_id; + sensor_setting_access_t setting_access; + uint8_t setting_raw_len; + void *setting_raw; +} _PACKED4_ sensor_setting_t; + +typedef struct +{ + uint8_t raw_value_len; + uint8_t fast_cadence_period_divisor: 7; + uint8_t status_trigger_type: 1; /**< @ref sensor_trigger_type_t */ + void *status_trigger_delta_down; + void *status_trigger_delta_up; + uint8_t status_min_interval; + void *fast_cadence_low; + void *fast_cadence_high; +} _PACKED4_ sensor_cadence_t; + +typedef struct +{ + sensor_descriptor_t descriptor; + uint8_t sensor_raw_data_len; + uint16_t num_settings; + sensor_setting_t *settings; + sensor_cadence_t *cadence; + int32_t pub_count; +} sensor_db_t; + +typedef struct +{ + uint16_t property_id; + uint8_t raw_data_len; + void *raw_data; +} sensor_data_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_DESCRIPTOR_GET)]; + uint16_t property_id; +} _PACKED4_ sensor_descriptor_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_DESCRIPTOR_STATUS)]; + uint8_t descriptors[0]; +} _PACKED4_ sensor_descriptor_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_GET)]; + uint16_t property_id; +} _PACKED4_ sensor_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_STATUS)]; + uint8_t sensor_data[0]; +} _PACKED4_ sensor_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_COLUMN_GET)]; + uint16_t property_id; + uint8_t raw_value_x[0]; +} _PACKED4_ sensor_column_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_COLUMN_STATUS)]; + uint16_t property_id; + uint8_t column_raw_value[0]; +} _PACKED4_ sensor_column_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SERIES_GET)]; + uint16_t property_id; + uint8_t raw_value_x[0]; +} _PACKED4_ sensor_series_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SERIES_STATUS)]; + uint16_t property_id; + uint8_t series_raw_value[0]; +} _PACKED4_ sensor_series_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_CADENCE_GET)]; + uint16_t property_id; +} _PACKED4_ sensor_cadence_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_CADENCE_SET)]; + uint16_t property_id; + uint8_t fast_cadence_period_divisor: 7; + uint8_t status_trigger_type: 1; /**< @ref sensor_trigger_type_t */ + uint8_t cadence[0]; +} _PACKED4_ sensor_cadence_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_CADENCE_STATUS)]; + uint16_t property_id; + uint8_t cadence[0]; +} _PACKED4_ sensor_cadence_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SETTINGS_GET)]; + uint16_t property_id; +} _PACKED4_ sensor_settings_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SETTINGS_STATUS)]; + uint16_t property_id; + uint16_t setting_ids[0]; +} _PACKED4_ sensor_settings_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SETTING_GET)]; + uint16_t property_id; + uint16_t setting_property_id; +} _PACKED4_ sensor_setting_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SETTING_SET)]; + uint16_t property_id; + uint16_t setting_property_id; + uint8_t setting[0]; +} _PACKED4_ sensor_setting_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_SENSOR_SETTING_STATUS)]; + uint16_t property_id; + uint16_t setting_property_id; + uint8_t setting[0]; +} _PACKED4_ sensor_setting_status_t; + +/** @} */ + +/** + * @defgroup SENSOR_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define SENSOR_SERVER_GET 0 //!< @ref sensor_server_get_t +#define SENSOR_SERVER_GET_COLUMN 1 //!< @ref sensor_server_get_column_t +#define SENSOR_SERVER_GET_SERIES 2 //!< @ref sensor_server_get_series_t +#define SENSOR_SERVER_SET_CADENCE 3 //!< @ref sensor_server_set_cadence_t +#define SENSOR_SERVER_SET_SETTING 4 //!< @ref sensor_server_set_setting_t +#define SENSOR_SERVER_COMPARE_CADENCE 5 //!< @ref sensor_server_compare_cadence_t + +typedef struct +{ + uint16_t property_id; + /* app need to modify pointer blew, default is NULL */ + void *raw_data; +} sensor_server_get_t; + +typedef struct +{ + uint16_t property_id; + uint8_t raw_value_x_len; + const void *raw_value_x; + /* app need to modify pointer blew, default is NULL */ + uint16_t column_len; + /* contains raw value x, column width and raw value y */ + void *column; +} sensor_server_get_column_t; + +typedef struct +{ + uint16_t property_id; + uint8_t raw_value_x_len; + const void *raw_value_x1; + const void *raw_value_x2; + /* app need to modify pointer blew, default is NULL */ + uint16_t series_len; + /* contains n raw value x, column width and raw value y */ + void *series; +} sensor_server_get_series_t; + +typedef struct +{ + uint16_t property_id; + /* + * just notify new cadence value in database, + * do not need to modify it, just use it if needed + */ + sensor_cadence_t *cadence; +} sensor_server_set_cadence_t; + +typedef struct +{ + uint16_t property_id; + /* + * just notify new setting value in database, + * do not need to modify it, just use it if needed + */ + sensor_setting_t *setting; +} sensor_server_set_setting_t; + +typedef struct +{ + uint16_t property_id; + bool need_fast_divisor; +} sensor_server_compare_cadence_t; +/** @} */ + +/** + * @defgroup SENSOR_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define SENSOR_CLIENT_STATUS_DESCRIPTOR 0 //!< @ref sensor_client_status_descriptor_t +#define SENSOR_CLIENT_STATUS_CADENCE 1 //!< @ref sensor_client_status_cadence_t +#define SENSOR_CLIENT_STATUS_SETTINGS 2 //!< @ref sensor_client_status_settings_t +#define SENSOR_CLIENT_STATUS_SETTING 3 //!< @ref sensor_client_status_settings_t +#define SENSOR_CLIENT_STATUS 4 //!< @ref sensor_client_status_t +#define SENSOR_CLIENT_STATUS_COLUMN 5 //!< @ref sensor_client_status_column_t +#define SENSOR_CLIENT_STATUS_SERIES 6 //!< @ref sensor_client_status_series_t + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint16_t num_descriptors; + sensor_descriptor_t *descriptors; +} sensor_client_status_descriptor_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + sensor_cadence_t *cadence; +} sensor_client_status_cadence_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint16_t num_ids; + uint16_t *setting_ids; +} sensor_client_status_settings_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint16_t setting_property_id; + sensor_setting_t *setting; +} sensor_client_status_setting_t; + +typedef struct +{ + uint16_t src; + uint16_t marshalled_sensor_data_len; + void *marshalled_sensor_data; +} sensor_client_status_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint16_t column_raw_value_len; + void *column_raw_value; +} sensor_client_status_column_t; + +typedef struct +{ + uint16_t src; + uint16_t property_id; + uint16_t series_raw_value_len; + void *series_raw_value; +} sensor_client_status_series_t; +/** @} */ + +/** + * @defgroup SENSOR_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register sensor server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to sensor server model context + * @retval true: register success + * @retval false: register failed + */ +bool sensor_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register sensor setup server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to sensor setup server model context + * @retval true: register success + * @retval false: register failed + */ +bool sensor_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief set user defined sensor database + * @param[in] pmodel_info: pointer to sensor server model context + * @param[in] sensors: user defined sensor database + * @param[in] num_sensors: sensor numbers + */ +void sensor_server_set_db(mesh_model_info_p pmodel_info, sensor_db_t *sensors, + uint16_t num_sensors); + +/** + * @brief set user defined sensor database + * @param[in] pmodel_info: pointer to sensor setup server model context + * @param[in] sensors: user defined sensor database + * @param[in] num_sensors: sensor numbers + */ +void sensor_setup_server_set_db(mesh_model_info_p pmodel_info, sensor_db_t *sensors, + uint16_t num_sensors); + +/** + * @brief publish sensor information + * @param[in] pmodel_info: pointer to sensor server model context + * @param[in] sensor_data: sensor data need to publish + * @param[in] num_sensor_data: sensor data count + * @return publish status + */ +mesh_msg_send_cause_t sensor_publish(const mesh_model_info_p pmodel_info, + const sensor_data_t *sensor_data, + uint16_t num_sensor_data); + +/** + * @brief publish sensor cadence information + * @param[in] pmodel_info: pointer to sensor setup server model context + * @param[in] property_id: sensor property id + * @param[in] cadence: sensor cadence need to publish + * @return publish status + */ +mesh_msg_send_cause_t sensor_cadence_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, + const sensor_cadence_t *cadence); + +/** + * @brief publish sensor setting information + * @param[in] pmodel_info: pointer to sensor setup server model context + * @param[in] property_id: sensor property id + * @param[in] setting: sensor setting need to publish + * @return publish status + */ +mesh_msg_send_cause_t sensor_setting_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, + const sensor_setting_t *setting); + +/** + * @brief convert sensor tolerance value to percentage + * @param[in] tolerance: sensor tolerance digital value + * @return sensor tolerance percentage value + */ +uint8_t sensor_tolerance_to_percentage(uint16_t tolerance); + +/** + * @brief convert measurement period to seconds + * @param[in] period: measurement period + * @return measurement period in seconds + */ +double sensor_measurement_period_to_seconds(uint8_t period); + +/** + * @brief convert update interval to seconds + * @param[in] period: sensor update interval + * @return sensor update interval in seconds + */ +double sensor_update_interval_to_seconds(uint8_t period); +/** @} */ + +/** + * @defgroup SENSOR_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register sensor client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to sensor client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool sensor_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get sensor descriptor + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @return send status + */ +mesh_msg_send_cause_t sensor_descriptor_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief get sensor cadence + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @return send status + */ +mesh_msg_send_cause_t sensor_cadence_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief get sensor cadence + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @param[in] cadence: sensor cadence data + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t sensor_cadence_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, const sensor_cadence_t *cadence, bool ack); + +/** + * @brief get sensor settings + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @return send status + */ +mesh_msg_send_cause_t sensor_settings_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief get sensor settings + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @param[in] setting_property_id: sensor setting property id + * @return send status + */ +mesh_msg_send_cause_t sensor_setting_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint16_t setting_property_id); + +/** + * @brief set sensor settings + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @param[in] setting_property_id: sensor setting property id + * @param[in] setting_raw_len: setting raw data length + * @param[in] setting_raw: sensor setting raw data + * @param[in] ack: acknowledge flag + * @return send status + */ +mesh_msg_send_cause_t sensor_setting_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint16_t setting_property_id, + uint8_t setting_raw_len, const void *setting_raw, bool ack); + +/** + * @brief get sensor data + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @return send status + */ +mesh_msg_send_cause_t sensor_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id); + +/** + * @brief get sensor column data + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @param[in] raw_value_x_len: column raw value x length + * @param[in] raw_value_x: column raw value x + * @return send status + */ +mesh_msg_send_cause_t sensor_column_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t raw_value_x_len, const void *raw_value_x); + +/** + * @brief get sensor series data + * @param[in] pmodel_info: pointer to sensor client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] property_id: sensor property id + * @param[in] raw_value_x_len: column raw value x length + * @param[in] raw_value_x1: column raw value x1 + * @param[in] raw_value_x2: column raw value x2 + * @return send status + */ +mesh_msg_send_cause_t sensor_series_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t raw_value_x_len, const void *raw_value_x1, + const void *raw_value_x2); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _SENSOR_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_client.c new file mode 100644 index 00000000..d83bfb97 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_client.c @@ -0,0 +1,414 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file sensor_client.c +* @brief Source file for sensor client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-9-12 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "sensor.h" + +#define PROPERTY_ID_LEN 2 +#define SETTING_PROPERTY_ID_LEN 2 +#define TRIGGER_DELTA_UNITLESS_LEN 2 + +static mesh_msg_send_cause_t sensor_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, uint8_t *pmsg, uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t sensor_descriptor_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + sensor_descriptor_get_t msg; + uint16_t msg_len = sizeof(msg); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_DESCRIPTOR_GET); + if (0 == property_id) + { + msg_len -= PROPERTY_ID_LEN; + } + msg.property_id = property_id; + + return sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, msg_len); +} + +mesh_msg_send_cause_t sensor_cadence_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + sensor_cadence_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_CADENCE_GET); + msg.property_id = property_id; + + return sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t sensor_cadence_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, const sensor_cadence_t *cadence, bool ack) +{ + mesh_msg_send_cause_t ret; + sensor_cadence_set_t *pmsg = NULL; + uint8_t trigger_len = 0; + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == cadence->status_trigger_type) + { + trigger_len = cadence->raw_value_len; + } + else + { + trigger_len = TRIGGER_DELTA_UNITLESS_LEN; + } + uint16_t msg_len = sizeof(sensor_cadence_set_t) + sizeof(uint8_t) + trigger_len * 2 + + cadence->raw_value_len * 2; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + if (ack) + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_CADENCE_SET); + } + else + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_CADENCE_SET_UNACK); + } + pmsg->property_id = property_id; + pmsg->fast_cadence_period_divisor = cadence->fast_cadence_period_divisor; + pmsg->status_trigger_type = cadence->status_trigger_type; + uint8_t *pdata = pmsg->cadence; + + for (uint8_t i = 0; i < trigger_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->status_trigger_delta_down)[i]; + } + + for (uint8_t i = 0; i < trigger_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->status_trigger_delta_up)[i]; + } + + *pdata ++ = cadence->status_min_interval; + + for (uint8_t i = 0; i < cadence->raw_value_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->fast_cadence_low)[i]; + } + + for (uint8_t i = 0; i < cadence->raw_value_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->fast_cadence_high)[i]; + } + + + ret = sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + return ret; +} + +mesh_msg_send_cause_t sensor_settings_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + sensor_settings_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_SETTINGS_GET); + msg.property_id = property_id; + + return sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t sensor_setting_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint16_t setting_property_id) +{ + sensor_setting_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_SETTING_GET); + msg.property_id = property_id; + msg.setting_property_id = setting_property_id; + + return sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t sensor_setting_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint16_t setting_property_id, + uint8_t setting_raw_len, const void *setting_raw, bool ack) +{ + mesh_msg_send_cause_t ret; + sensor_setting_set_t *pmsg = NULL; + uint16_t msg_len = sizeof(sensor_setting_set_t) + setting_raw_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + uint8_t *pdata = pmsg->setting; + if (ack) + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_SETTING_SET); + } + else + { + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_SETTING_SET_UNACK); + } + pmsg->property_id = property_id; + pmsg->setting_property_id = setting_property_id; + + for (uint8_t i = 0; i < setting_raw_len; ++i) + { + *pdata ++ = ((const uint8_t *)setting_raw)[i]; + } + + ret = sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + return ret; +} + +mesh_msg_send_cause_t sensor_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id) +{ + sensor_get_t msg; + uint16_t msg_len = sizeof(msg); + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_GET); + if (0 == property_id) + { + msg_len -= PROPERTY_ID_LEN; + } + msg.property_id = property_id; + + return sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, msg_len); +} + +mesh_msg_send_cause_t sensor_column_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t raw_value_x_len, const void *raw_value_x) +{ + mesh_msg_send_cause_t ret; + sensor_column_get_t *pmsg = NULL; + uint16_t msg_len = sizeof(sensor_column_get_t) + raw_value_x_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_COLUMN_GET); + pmsg->property_id = property_id; + + uint8_t *pdata = pmsg->raw_value_x; + for (uint8_t i = 0; i < raw_value_x_len; ++i) + { + *pdata ++ = ((const uint8_t *)raw_value_x)[i]; + } + + ret = sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + return ret; +} + +mesh_msg_send_cause_t sensor_series_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, uint8_t raw_value_x_len, const void *raw_value_x1, + const void *raw_value_x2) +{ + mesh_msg_send_cause_t ret; + sensor_series_get_t *pmsg = NULL; + uint16_t msg_len = sizeof(sensor_series_get_t) + raw_value_x_len * 2; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_SERIES_GET); + pmsg->property_id = property_id; + + uint8_t *pdata = pmsg->raw_value_x; + for (uint8_t i = 0; i < raw_value_x_len; ++i) + { + *pdata ++ = ((const uint8_t *)raw_value_x1)[i]; + } + + for (uint8_t i = 0; i < raw_value_x_len; ++i) + { + *pdata ++ = ((const uint8_t *)raw_value_x2)[i]; + } + + ret = sensor_client_send(pmodel_info, dst, app_key_index, (uint8_t *)pmsg, msg_len); + plt_free(pmsg, RAM_TYPE_DATA_ON); + return ret; +} + +static bool sensor_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SENSOR_DESCRIPTOR_STATUS: + { + sensor_descriptor_status_t *pmsg = (sensor_descriptor_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_descriptor_t status_data = {pmesh_msg->src, 0, 0, NULL}; + uint16_t descriptor_len = pmesh_msg->msg_len - sizeof(sensor_descriptor_status_t); + if (PROPERTY_ID_LEN == descriptor_len) + { + status_data.property_id = *((uint16_t *)pmsg->descriptors); + } + else + { + status_data.num_descriptors = descriptor_len / sizeof(sensor_descriptor_t); + status_data.descriptors = (sensor_descriptor_t *)pmsg->descriptors; + } + + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS_DESCRIPTOR, &status_data); + } + } + break; + case MESH_MSG_SENSOR_CADENCE_STATUS: + { + sensor_cadence_status_t *pmsg = (sensor_cadence_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_cadence_t status_data = {pmesh_msg->src, 0, NULL}; + status_data.property_id = pmsg->property_id; + uint8_t *pdata = pmsg->cadence; + sensor_cadence_t cadence; + status_data.cadence = &cadence; + cadence.fast_cadence_period_divisor = (*pdata & 0x7f); + cadence.status_trigger_type = (*pdata >> 7); + uint8_t trigger_len = 0; + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == cadence.status_trigger_type) + { + trigger_len = (pmesh_msg->msg_len - sizeof(sensor_cadence_status_t) - sizeof(uint8_t) * 2) / 4; + cadence.raw_value_len = trigger_len; + } + else + { + trigger_len = TRIGGER_DELTA_UNITLESS_LEN; + cadence.raw_value_len = (pmesh_msg->msg_len - sizeof(sensor_cadence_status_t) - sizeof( + uint8_t) * 2 - trigger_len * 2) / 2; + } + + cadence.status_trigger_delta_down = pmsg->cadence + sizeof(uint8_t); + cadence.status_trigger_delta_up = (uint8_t *)cadence.status_trigger_delta_down + trigger_len; + cadence.status_min_interval = *((uint8_t *)cadence.status_trigger_delta_up + trigger_len); + cadence.fast_cadence_low = (uint8_t *)cadence.status_trigger_delta_up + trigger_len + sizeof( + uint8_t); + cadence.fast_cadence_high = (uint8_t *)cadence.fast_cadence_low + cadence.raw_value_len; + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS_CADENCE, &status_data); + } + } + break; + case MESH_MSG_SENSOR_SETTINGS_STATUS: + { + sensor_settings_status_t *pmsg = (sensor_settings_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_settings_t status_data = {pmesh_msg->src, 0, 0, NULL}; + status_data.property_id = pmsg->property_id; + uint16_t ids_len = pmesh_msg->msg_len - sizeof(sensor_settings_status_t); + status_data.num_ids = ids_len / SETTING_PROPERTY_ID_LEN; + status_data.setting_ids = pmsg->setting_ids; + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS_SETTINGS, &status_data); + } + } + break; + case MESH_MSG_SENSOR_SETTING_STATUS: + { + sensor_setting_status_t *pmsg = (sensor_setting_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_setting_t status_data = {pmesh_msg->src, 0, 0, NULL}; + uint8_t data_len = pmesh_msg->msg_len - sizeof(sensor_setting_status_t); + status_data.property_id = pmsg->property_id; + status_data.setting_property_id = pmsg->setting_property_id; + sensor_setting_t setting; + if (data_len > 0) + { + status_data.setting = &setting; + setting.setting_property_id = pmsg->setting_property_id; + setting.setting_raw_len = data_len - 1; + uint8_t *pdata = pmsg->setting; + setting.setting_access = (sensor_setting_access_t)(*pdata); + pdata ++; + setting.setting_raw = pdata; + } + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS_SETTING, &status_data); + } + } + break; + case MESH_MSG_SENSOR_STATUS: + { + sensor_status_t *pmsg = (sensor_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_t status_data = {pmesh_msg->src, 0, NULL}; + status_data.marshalled_sensor_data_len = pmesh_msg->msg_len - sizeof(sensor_status_t); + status_data.marshalled_sensor_data = pmsg->sensor_data; + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS, &status_data); + } + } + break; + case MESH_MSG_SENSOR_COLUMN_STATUS: + { + sensor_column_status_t *pmsg = (sensor_column_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_column_t status_data = {pmesh_msg->src, 0, 0, NULL}; + status_data.property_id = pmsg->property_id; + status_data.column_raw_value_len = pmesh_msg->msg_len - sizeof(sensor_column_status_t); + status_data.column_raw_value = pmsg->column_raw_value; + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS_COLUMN, &status_data); + } + } + break; + case MESH_MSG_SENSOR_SERIES_STATUS: + { + sensor_series_status_t *pmsg = (sensor_series_status_t *)pbuffer; + if (NULL != pmodel_info->model_data_cb) + { + sensor_client_status_series_t status_data = {pmesh_msg->src, 0, 0, NULL}; + status_data.property_id = pmsg->property_id; + status_data.series_raw_value_len = pmesh_msg->msg_len - sizeof(sensor_series_status_t); + status_data.series_raw_value = pmsg->series_raw_value; + pmodel_info->model_data_cb(pmodel_info, SENSOR_CLIENT_STATUS_SERIES, &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool sensor_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SENSOR_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = sensor_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("sensor_client_reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_server.c new file mode 100644 index 00000000..834c3621 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_server.c @@ -0,0 +1,726 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file sensor_server.c +* @brief Source file for sensor server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-29 +* @version v1.0 +* ************************************************************************************* +*/ + +#include +#include "sensor.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#define SENSOR_FAST_PERIOD_ENABLE 1 + +#define SENSOR_TIME_PERIOD 100 +#define PROPERTY_ID_LEN 2 + +typedef struct +{ + sensor_db_t *sensors; + uint16_t num_sensors; +} sensor_info_t; + +typedef struct +{ + uint16_t format: 1; + uint16_t length: 4; + uint16_t property_id: 11; +} _PACKED4_ sensor_formata_t; + +typedef struct +{ + uint8_t format: 1; + uint8_t length: 7; + uint16_t property_id; +} _PACKED4_ sensor_formatb_t; + +uint8_t sensor_tolerance_to_percentage(uint16_t tolerance) +{ + return tolerance / 4095.0 * 100; +} + +double sensor_measurement_period_to_seconds(uint8_t period) +{ + return pow(1.1, period - 64); +} + +double sensor_update_interval_to_seconds(uint8_t interval) +{ + return pow(1.1, interval - 64); +} + +void sensor_server_set_db(mesh_model_info_p pmodel_info, sensor_db_t *sensors, uint16_t num_sensors) +{ + sensor_info_t *pinfo = pmodel_info->pargs; + pinfo->sensors = sensors; + pinfo->num_sensors = num_sensors; +} + +static mesh_msg_send_cause_t sensor_server_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, void *pmsg, uint16_t msg_len, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t sensor_status_internal(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, uint32_t delay_time) +{ + sensor_status_t *pmsg; + mesh_msg_send_cause_t ret; + uint16_t msg_len = sizeof(sensor_status_t); + sensor_info_t *pinfo = pmodel_info->pargs; + sensor_server_get_t get_data = {0, NULL}; + if (0 == property_id) + { + /* get all sensor data */ + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if ((pinfo->sensors[i].sensor_raw_data_len <= 16) && + (pinfo->sensors[i].descriptor.property_id < 2048)) + { + msg_len += 2; + } + else + { + msg_len += 3; + } + msg_len += pinfo->sensors[i].sensor_raw_data_len; + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_STATUS); + uint8_t *pdata = pmsg->sensor_data; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if ((pinfo->sensors[i].sensor_raw_data_len <= 16) && + (pinfo->sensors[i].descriptor.property_id < 2048)) + { + sensor_formata_t *pformat = (sensor_formata_t *)pdata; + pformat->format = 0; + pformat->length = pinfo->sensors[i].sensor_raw_data_len - 1; + pformat->property_id = pinfo->sensors[i].descriptor.property_id; + pdata += sizeof(sensor_formata_t); + } + else + { + sensor_formatb_t *pformat = (sensor_formatb_t *)pdata; + pformat->format = 1; + pformat->length = pinfo->sensors[i].sensor_raw_data_len - 1; + pformat->property_id = pinfo->sensors[i].descriptor.property_id; + pdata += sizeof(sensor_formatb_t); + } + + get_data.property_id = pinfo->sensors[i].descriptor.property_id; + get_data.raw_data = NULL; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_GET, &get_data); + } + + if (NULL != get_data.raw_data) + { + for (uint16_t j = 0; j < pinfo->sensors[i].sensor_raw_data_len; ++j) + { + *pdata ++ = ((uint8_t *)(get_data.raw_data))[j]; + } + } + } + } + else + { + /* get specified sensor data */ + sensor_db_t *psensor = NULL; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if (pinfo->sensors[i].descriptor.property_id == property_id) + { + psensor = &pinfo->sensors[i]; + } + } + + if (NULL == psensor) + { + if (property_id < 2048) + { + msg_len += 2; + } + else + { + msg_len += 3; + } + } + else + { + if ((psensor->sensor_raw_data_len <= 16) && + (psensor->descriptor.property_id < 2048)) + { + msg_len += 2; + } + else + { + msg_len += 3; + } + msg_len += psensor->sensor_raw_data_len; + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_STATUS); + uint8_t *pdata = pmsg->sensor_data; + if (NULL == psensor) + { + if (property_id < 2048) + { + sensor_formata_t *pformat = (sensor_formata_t *)pdata; + pformat->format = 0; + pformat->length = 0x0f; + pformat->property_id = property_id; + pdata += sizeof(sensor_formata_t); + } + else + { + sensor_formatb_t *pformat = (sensor_formatb_t *)pdata; + pformat->format = 1; + pformat->length = 0x7f; + pformat->property_id = property_id; + pdata += sizeof(sensor_formatb_t); + } + } + else + { + if ((psensor->sensor_raw_data_len <= 16) && + (psensor->descriptor.property_id < 2048)) + { + sensor_formata_t *pformat = (sensor_formata_t *)pdata; + pformat->format = 0; + pformat->length = psensor->sensor_raw_data_len - 1; + pformat->property_id = psensor->descriptor.property_id; + pdata += sizeof(sensor_formata_t); + } + else + { + sensor_formatb_t *pformat = (sensor_formatb_t *)pdata; + pformat->format = 1; + pformat->length = psensor->sensor_raw_data_len - 1; + pformat->property_id = psensor->descriptor.property_id; + pdata += sizeof(sensor_formatb_t); + } + + get_data.property_id = psensor->descriptor.property_id; + get_data.raw_data = NULL; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_GET, &get_data); + } + + if (NULL != get_data.raw_data) + { + for (uint16_t i = 0; i < psensor->sensor_raw_data_len; ++i) + { + *pdata ++ = ((uint8_t *)get_data.raw_data)[i]; + } + } + } + } + ret = sensor_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +static mesh_msg_send_cause_t sensor_status(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, + const sensor_data_t *sensor_data, uint16_t num_sensor_data, + uint32_t delay_time) +{ + sensor_status_t *pmsg; + uint16_t msg_len = sizeof(sensor_status_t);; + for (uint16_t i = 0; i < num_sensor_data; ++i) + { + if ((sensor_data[i].raw_data_len <= 16) && + (sensor_data[i].property_id < 2048)) + { + msg_len += 2; + } + else + { + msg_len += 3; + } + msg_len += sensor_data[i].raw_data_len; + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_STATUS); + uint8_t *pdata = pmsg->sensor_data; + for (uint16_t i = 0; i < num_sensor_data; ++i) + { + if ((sensor_data[i].raw_data_len <= 16) && + (sensor_data[i].property_id < 2048)) + { + sensor_formata_t *pformat = (sensor_formata_t *)pdata; + pformat->format = 0; + pformat->length = sensor_data[i].raw_data_len - 1; + pformat->property_id = sensor_data[i].property_id; + pdata += sizeof(sensor_formata_t); + } + else + { + sensor_formatb_t *pformat = (sensor_formatb_t *)pdata; + pformat->format = 0; + pformat->length = sensor_data[i].raw_data_len - 1; + pformat->property_id = sensor_data[i].property_id; + pdata += sizeof(sensor_formatb_t); + } + + for (uint16_t j = 0; j < sensor_data[i].raw_data_len; ++j) + { + *pdata ++ = ((uint8_t *)sensor_data[i].raw_data)[j]; + } + } + + mesh_msg_send_cause_t ret = sensor_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, + delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +mesh_msg_send_cause_t sensor_delay_publish(const mesh_model_info_p pmodel_info, + const sensor_data_t *sensor_data, + uint16_t num_sensor_data, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = sensor_status(pmodel_info, 0, 0, sensor_data, num_sensor_data, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t sensor_publish(const mesh_model_info_p pmodel_info, + const sensor_data_t *sensor_data, + uint16_t num_sensor_data) +{ + return sensor_delay_publish(pmodel_info, sensor_data, num_sensor_data, 0); +} + +static int32_t sensor_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + sensor_info_t *pinfo = pmodel_info->pargs; + sensor_db_t *psensor = NULL; + sensor_server_get_t get_data = {0, NULL}; + sensor_data_t sensor_data = {0, 0, NULL}; + +#if SENSOR_FAST_PERIOD_ENABLE + uint32_t status_min_interval = 0; + uint32_t pub_period = 0; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + psensor = &pinfo->sensors[i]; + if (psensor->pub_count <= 0) + { + status_min_interval = 0; + /* get data */ + get_data.property_id = psensor->descriptor.property_id; + get_data.raw_data = NULL; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_GET, &get_data); + } + sensor_data.property_id = psensor->descriptor.property_id; + sensor_data.raw_data_len = psensor->sensor_raw_data_len; + sensor_data.raw_data = get_data.raw_data; + /* publish */ + sensor_status(pmodel_info, 0, 0, &sensor_data, 1, 0); + /* compare data */ + sensor_server_compare_cadence_t get_data = {psensor->descriptor.property_id, FALSE}; + if (NULL != psensor->cadence) + { + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_COMPARE_CADENCE, &get_data); + } + status_min_interval = (1 << psensor->cadence->status_min_interval); + } + + pub_period = mesh_model_pub_period_get(pmodel_info->pmodel); + if (pub_period < status_min_interval) + { + pub_period = status_min_interval; + } + if (get_data.need_fast_divisor) + { + uint32_t divisor = (1 << psensor->cadence->fast_cadence_period_divisor); + if (pub_period / divisor < status_min_interval) + { + psensor->pub_count = status_min_interval / SENSOR_TIME_PERIOD; + } + else + { + psensor->pub_count = pub_period / divisor / SENSOR_TIME_PERIOD; + } + } + else + { + psensor->pub_count = pub_period / SENSOR_TIME_PERIOD; + } + } + else + { + psensor->pub_count --; + } + } + + return SENSOR_TIME_PERIOD; +#else + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + psensor = &pinfo->sensors[i]; + /* get data */ + get_data.property_id = psensor->descriptor.property_id; + get_data.raw_data = NULL; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_GET, &get_data); + } + sensor_data.property_id = psensor->descriptor.property_id; + sensor_data.raw_data_len = psensor->sensor_raw_data_len; + sensor_data.raw_data = get_data.raw_data; + /* publish */ + sensor_status(pmodel_info, 0, 0, &sensor_data, 1, 0); + } + return 0; +#endif +} + +static mesh_msg_send_cause_t sensor_descriptor_status(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, uint32_t delay_time) +{ + sensor_descriptor_status_t *pmsg; + sensor_info_t *pinfo = pmodel_info->pargs; + mesh_msg_send_cause_t ret; + uint16_t msg_len; + if (0 == property_id) + { + /* get all descriptors */ + msg_len = sizeof(sensor_descriptor_status_t) + sizeof(sensor_descriptor_t) * pinfo->num_sensors; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_DESCRIPTOR_STATUS); + sensor_descriptor_t *pdescriptor = (sensor_descriptor_t *)pmsg->descriptors; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + *pdescriptor ++ = pinfo->sensors[i].descriptor; + } + } + else + { + /* get specified descriptor */ + sensor_descriptor_t *pdescriptor = NULL; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if (pinfo->sensors[i].descriptor.property_id == property_id) + { + pdescriptor = &(pinfo->sensors[i].descriptor); + break; + } + } + + if (NULL == pdescriptor) + { + msg_len = sizeof(sensor_descriptor_status_t) + PROPERTY_ID_LEN; + } + else + { + msg_len = sizeof(sensor_descriptor_status_t) + sizeof(sensor_descriptor_t); + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_DESCRIPTOR_STATUS); + if (NULL == pdescriptor) + { + pmsg->descriptors[0] = (uint8_t)(property_id); + pmsg->descriptors[1] = (uint8_t)(property_id >> 8); + } + else + { + *((sensor_descriptor_t *)(pmsg->descriptors)) = *pdescriptor; + } + } + + ret = sensor_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +static mesh_msg_send_cause_t sensor_column_status(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, + uint8_t raw_value_x_len, const void *raw_value_x, + uint16_t column_len, const void *column, uint32_t delay_time) +{ + sensor_column_status_t *pmsg; + mesh_msg_send_cause_t ret; + uint16_t msg_len; + if ((0 == column_len) || (NULL == column)) + { + msg_len = sizeof(sensor_column_status_t) + raw_value_x_len; + } + else + { + msg_len = sizeof(sensor_column_status_t) + column_len; + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_COLUMN_STATUS); + pmsg->property_id = property_id; + uint8_t *pdata = pmsg->column_raw_value; + if ((column_len > 0) && (NULL != column)) + { + memcpy(pdata, column, column_len); + } + else + { + memcpy(pdata, raw_value_x, raw_value_x_len); + } + + ret = sensor_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + +static mesh_msg_send_cause_t sensor_series_status(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint16_t property_id, + uint8_t series_len, void *series, uint32_t delay_time) +{ + sensor_series_status_t *pmsg; + mesh_msg_send_cause_t ret; + uint16_t msg_len = sizeof(sensor_column_status_t) + series_len; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_SERIES_STATUS); + pmsg->property_id = property_id; + uint8_t *pdata = pmsg->series_raw_value; + memcpy(pdata, series, series_len); + + ret = sensor_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + + return ret; +} + + +static bool sensor_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SENSOR_DESCRIPTOR_GET: + if (pmesh_msg->msg_len == sizeof(sensor_descriptor_get_t)) + { + /* get specified descriptor */ + sensor_descriptor_get_t *pmsg = (sensor_descriptor_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_descriptor_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, pmsg->property_id, + delay_rsp_time); + } + } + else if (pmesh_msg->msg_len == MEMBER_OFFSET(sensor_descriptor_get_t, property_id)) + { + /* get all descriptors */ + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_descriptor_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, 0, delay_rsp_time); + } + break; + case MESH_MSG_SENSOR_GET: + if (pmesh_msg->msg_len == sizeof(sensor_get_t)) + { + /* get specified sensor data */ + sensor_get_t *pmsg = (sensor_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_status_internal(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, pmsg->property_id, + delay_rsp_time); + } + } + else if (pmesh_msg->msg_len == MEMBER_OFFSET(sensor_get_t, property_id)) + { + /* get all sensor data */ + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_status_internal(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, 0, delay_rsp_time); + } + break; + case MESH_MSG_SENSOR_COLUMN_GET: + { + sensor_column_get_t *pmsg = (sensor_column_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + sensor_server_get_column_t get_data; + memset(&get_data, 0, sizeof(sensor_server_get_column_t)); + get_data.property_id = pmsg->property_id; + get_data.raw_value_x_len = pmesh_msg->msg_len - sizeof(sensor_column_get_t); + get_data.raw_value_x = pmsg->raw_value_x; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_GET_COLUMN, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_column_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, get_data.raw_value_x_len, get_data.raw_value_x, + get_data.column_len, get_data.column, delay_rsp_time); + } + } + break; + case MESH_MSG_SENSOR_SERIES_GET: + { + sensor_series_get_t *pmsg = (sensor_series_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + sensor_server_get_series_t get_data; + memset(&get_data, 0, sizeof(sensor_server_get_series_t)); + get_data.property_id = pmsg->property_id; + if (pmesh_msg->msg_len > sizeof(sensor_series_get_t)) + { + get_data.raw_value_x_len = (pmesh_msg->msg_len - sizeof(sensor_series_get_t)) / 2; + get_data.raw_value_x1 = pmsg->raw_value_x; + get_data.raw_value_x2 = pmsg->raw_value_x + get_data.raw_value_x_len; + } + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_GET_SERIES, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_series_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, pmsg->property_id, + get_data.series_len, get_data.series, delay_rsp_time); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void sensor_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == sensor_server_receive) + { + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } + pmodel_info->model_receive = NULL; + } +} +#endif + +bool sensor_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SENSOR_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(sensor_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("sensor_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(sensor_info_t)); + + pmodel_info->model_receive = sensor_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("sensor_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = sensor_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = sensor_server_publish; + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_setup_server.c new file mode 100644 index 00000000..d863d804 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_setup_server.c @@ -0,0 +1,610 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file sensor_setup_server.c +* @brief Source file for sensor setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-22 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "sensor.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#define SETTING_PROPERTY_ID_LEN 2 +#define TRIGGER_DELTA_UNITLESS_LEN 2 + +typedef struct +{ + sensor_db_t *sensors; + uint16_t num_sensors; +} sensor_setup_info_t; + +void sensor_setup_server_set_db(mesh_model_info_p pmodel_info, sensor_db_t *sensors, + uint16_t num_sensors) +{ + sensor_setup_info_t *pinfo = pmodel_info->pargs; + pinfo->sensors = sensors; + pinfo->num_sensors = num_sensors; +} + +static sensor_setting_t *sensor_get_setting(const mesh_model_info_p pmodel_info, + uint16_t property_id, uint16_t setting_property_id) +{ + sensor_setup_info_t *pinfo = pmodel_info->pargs; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if (pinfo->sensors[i].descriptor.property_id == property_id) + { + for (uint16_t j = 0; j < pinfo->sensors[i].num_settings; ++j) + { + if (pinfo->sensors[i].settings[j].setting_property_id == setting_property_id) + { + return &pinfo->sensors[i].settings[j]; + } + } + break; + } + } + + return NULL; +} + +static sensor_cadence_t *sensor_get_cadence(const mesh_model_info_p pmodel_info, + uint16_t property_id) +{ + sensor_setup_info_t *pinfo = pmodel_info->pargs; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if (pinfo->sensors[i].descriptor.property_id == property_id) + { + return pinfo->sensors[i].cadence; + } + } + + return NULL; +} + +static mesh_msg_send_cause_t sensor_setup_server_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, void *pmsg, uint16_t msg_len, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +static mesh_msg_send_cause_t sensor_cadence_status(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, const sensor_cadence_t *cadence, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret; + if (NULL == cadence) + { + sensor_cadence_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_CADENCE_STATUS); + msg.property_id = property_id; + ret = sensor_setup_server_send(pmodel_info, dst, app_key_index, &msg, + sizeof(sensor_cadence_status_t), delay_time); + } + else + { + sensor_cadence_status_t *pmsg; + uint16_t msg_len = 0; + uint8_t trigger_len; + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == cadence->status_trigger_type) + { + msg_len = sizeof(sensor_cadence_status_t) + sizeof(sensor_cadence_t) - sizeof( + uint8_t *) * 4 - sizeof(uint8_t) + cadence->raw_value_len * 4; + trigger_len = cadence->raw_value_len; + } + else + { + msg_len = sizeof(sensor_cadence_status_t) + sizeof(sensor_cadence_t) - sizeof( + uint8_t *) * 4 - sizeof(uint8_t) + TRIGGER_DELTA_UNITLESS_LEN * 2 + cadence->raw_value_len * 2; + trigger_len = TRIGGER_DELTA_UNITLESS_LEN; + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_CADENCE_STATUS); + pmsg->property_id = property_id; + uint8_t *pdata = pmsg->cadence; + *pdata = cadence->fast_cadence_period_divisor; + *pdata |= (cadence->status_trigger_type << 7); + pdata ++; + for (uint8_t i = 0; i < trigger_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->status_trigger_delta_down)[i]; + } + + for (uint8_t i = 0; i < trigger_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->status_trigger_delta_up)[i]; + } + + *pdata ++ = cadence->status_min_interval; + + for (uint8_t i = 0; i < cadence->raw_value_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->fast_cadence_low)[i]; + } + + for (uint8_t i = 0; i < cadence->raw_value_len; ++i) + { + *pdata ++ = ((uint8_t *)cadence->fast_cadence_high)[i]; + } + ret = sensor_setup_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + } + + return ret; +} + +mesh_msg_send_cause_t sensor_cadence_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, + const sensor_cadence_t *cadence, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = sensor_cadence_status(pmodel_info, 0, 0, property_id, cadence, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t sensor_cadence_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, + const sensor_cadence_t *cadence) +{ + return sensor_cadence_delay_publish(pmodel_info, property_id, cadence, 0); +} + +static mesh_msg_send_cause_t sensor_settings_status(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, const sensor_setting_t *settings, uint16_t num_settings, + uint32_t delay_time) +{ + mesh_msg_send_cause_t ret; + if ((NULL == settings) || (0 == num_settings)) + { + sensor_settings_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_SETTINGS_STATUS); + msg.property_id = property_id; + ret = sensor_setup_server_send(pmodel_info, dst, app_key_index, &msg, + sizeof(sensor_settings_status_t), delay_time); + } + else + { + sensor_settings_status_t *pmsg; + uint16_t msg_len = sizeof(sensor_settings_status_t) + num_settings * SETTING_PROPERTY_ID_LEN; + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_SETTINGS_STATUS); + pmsg->property_id = property_id; + uint16_t *pid = pmsg->setting_ids; + for (uint16_t i = 0; i < num_settings; ++i) + { + *pid ++ = settings[i].setting_property_id; + } + ret = sensor_setup_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + } + + return ret; +} + +static mesh_msg_send_cause_t sensor_setting_status(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, + uint16_t property_id, uint16_t setting_property_id, + bool set_read_only, const sensor_setting_t *setting, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret; + if (NULL == setting) + { + sensor_setting_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_SENSOR_SETTING_STATUS); + msg.property_id = property_id; + msg.setting_property_id = setting_property_id; + ret = sensor_setup_server_send(pmodel_info, dst, app_key_index, &msg, + sizeof(sensor_setting_status_t), delay_time); + } + else + { + sensor_setting_status_t *pmsg; + uint16_t msg_len = 0; + if (!set_read_only) + { + msg_len = sizeof(sensor_setting_status_t) + 1 + setting->setting_raw_len; + } + else + { + msg_len = sizeof(sensor_setting_status_t) + 1; + } + pmsg = plt_malloc(msg_len, RAM_TYPE_DATA_ON); + if (NULL == pmsg) + { + return MESH_MSG_SEND_CAUSE_NO_MEMORY; + } + + ACCESS_OPCODE_BYTE(pmsg->opcode, MESH_MSG_SENSOR_SETTING_STATUS); + pmsg->property_id = property_id; + pmsg->setting_property_id = setting_property_id; + uint8_t *pdata = pmsg->setting; + *pdata ++ = setting->setting_access; + if (!set_read_only) + { + for (uint16_t i = 0; i < setting->setting_raw_len; ++i) + { + *pdata ++ = ((uint8_t *)setting->setting_raw)[i]; + } + } + ret = sensor_setup_server_send(pmodel_info, dst, app_key_index, pmsg, msg_len, delay_time); + plt_free(pmsg, RAM_TYPE_DATA_ON); + } + + return ret; + +} + +mesh_msg_send_cause_t sensor_setting_delay_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, + const sensor_setting_t *setting, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = sensor_setting_status(pmodel_info, 0, 0, property_id, setting->setting_property_id, FALSE, + setting, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t sensor_setting_publish(const mesh_model_info_p pmodel_info, + uint16_t property_id, + const sensor_setting_t *setting) +{ + return sensor_setting_delay_publish(pmodel_info, property_id, setting, 0); +} + +static bool sensor_check_msg(const mesh_model_info_p pmodel_info, const sensor_cadence_set_t *pmsg) +{ + if (!IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + return FALSE; + } + + if (!IS_FAST_CADENCE_DIVISIOR_VALID(pmsg->fast_cadence_period_divisor)) + { + return FALSE; + } + + sensor_cadence_t *cadence = sensor_get_cadence(pmodel_info, pmsg->property_id); + if (NULL == cadence) + { + return TRUE; + } + + const uint8_t *pdata = pmsg->cadence; + uint8_t trigger_len; + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == pmsg->status_trigger_type) + { + trigger_len = cadence->raw_value_len; + } + else + { + trigger_len = TRIGGER_DELTA_UNITLESS_LEN; + } + pdata += (trigger_len * 2); + + if (!IS_STATUS_MIN_INTERVAL_VALID(*pdata)) + { + return FALSE; + } + + return TRUE; +} + +static bool sensor_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_SENSOR_CADENCE_GET: + if (pmesh_msg->msg_len == sizeof(sensor_cadence_get_t)) + { + sensor_cadence_get_t *pmsg = (sensor_cadence_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + sensor_cadence_t *cadence = sensor_get_cadence(pmodel_info, pmsg->property_id); + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_cadence_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, cadence, delay_rsp_time); + } + } + break; + case MESH_MSG_SENSOR_CADENCE_SET: + case MESH_MSG_SENSOR_CADENCE_SET_UNACK: + { + sensor_cadence_set_t *pmsg = (sensor_cadence_set_t *)pbuffer; + if (sensor_check_msg(pmodel_info, pmsg)) + { + sensor_cadence_t *cadence = sensor_get_cadence(pmodel_info, pmsg->property_id); + if (NULL != cadence) + { + uint8_t *pdata = pmsg->cadence; + uint8_t trigger_len; + cadence->fast_cadence_period_divisor = pmsg->fast_cadence_period_divisor; + cadence->status_trigger_type = pmsg->status_trigger_type; + + if (SENSOR_TRIGGER_TYPE_CHARACTERISTIC == pmsg->status_trigger_type) + { + trigger_len = cadence->raw_value_len; + } + else + { + trigger_len = TRIGGER_DELTA_UNITLESS_LEN; + } + + for (uint8_t i = 0; i < trigger_len; ++i) + { + ((uint8_t *)cadence->status_trigger_delta_down)[i] = *pdata ++; + } + + for (uint8_t i = 0; i < trigger_len; ++i) + { + ((uint8_t *)cadence->status_trigger_delta_up)[i] = *pdata ++; + } + + cadence->status_min_interval = *pdata ++; + + for (uint8_t i = 0; i < cadence->raw_value_len; ++i) + { + ((uint8_t *)cadence->fast_cadence_low)[i] = *pdata ++; + } + + for (uint8_t i = 0; i < cadence->raw_value_len; ++i) + { + ((uint8_t *)cadence->fast_cadence_high)[i] = *pdata ++; + } + if (NULL != pmodel_info->model_data_cb) + { + sensor_server_set_cadence_t set_data = {pmsg->property_id, cadence}; + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_SET_CADENCE, &set_data); + } + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (MESH_MSG_SENSOR_CADENCE_SET == pmesh_msg->access_opcode) + { + sensor_cadence_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, cadence, delay_rsp_time); + } + + if (NULL != cadence) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_SENSOR_CADENCE_SET_UNACK) ? FALSE : TRUE; + generic_transition_time_t trans_time = {0, 0}; + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, ack); + sensor_cadence_delay_publish(pmodel_info, pmsg->property_id, cadence, delay_pub_time); +#else + /* TODO: check if cadence is the same */ + sensor_cadence_publish(pmodel_info, pmsg->property_id, cadence); +#endif + } + } + } + break; + case MESH_MSG_SENSOR_SETTINGS_GET: + if (pmesh_msg->msg_len == sizeof(sensor_settings_get_t)) + { + sensor_settings_get_t *pmsg = (sensor_settings_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + sensor_setup_info_t *pinfo = pmodel_info->pargs; + sensor_setting_t *psettings = NULL; + uint16_t num_settings = 0; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + if (pinfo->sensors[i].descriptor.property_id == pmsg->property_id) + { + psettings = pinfo->sensors[i].settings; + num_settings = pinfo->sensors[i].num_settings; + break; + } + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_settings_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, psettings, num_settings, delay_rsp_time); + } + } + break; + case MESH_MSG_SENSOR_SETTING_GET: + if (pmesh_msg->msg_len == sizeof(sensor_setting_get_t)) + { + sensor_setting_get_t *pmsg = (sensor_setting_get_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id)) + { + sensor_setting_get_t *pmsg = (sensor_setting_get_t *)pbuffer; + sensor_setting_t *setting = sensor_get_setting(pmodel_info, pmsg->property_id, + pmsg->setting_property_id); + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + sensor_setting_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, pmsg->setting_property_id, FALSE, setting, delay_rsp_time); + } + } + break; + case MESH_MSG_SENSOR_SETTING_SET: + case MESH_MSG_SENSOR_SETTING_SET_UNACK: + { + sensor_setting_set_t *pmsg = (sensor_setting_set_t *)pbuffer; + if (IS_SENSOR_PROPERTY_ID_VALID(pmsg->property_id) && + IS_SENSOR_SETTING_PROPERTY_ID_VALID(pmsg->setting_property_id)) + { + sensor_setting_t *setting = sensor_get_setting(pmodel_info, pmsg->property_id, + pmsg->setting_property_id); + bool set_read_only = FALSE; + if (NULL != setting) + { + if (SENSOR_SETTING_ACCESS_READ_WRITE == setting->setting_access) + { + uint16_t data_len = pmesh_msg->msg_len - sizeof(sensor_setting_set_t); + for (uint16_t i = 0; i < data_len; ++i) + { + setting->setting_raw_len = data_len; + ((uint8_t *)setting->setting_raw)[i] = pmsg->setting[i]; + } + if (NULL != pmodel_info->model_data_cb) + { + sensor_server_set_setting_t set_data = {pmsg->property_id, setting}; + pmodel_info->model_data_cb(pmodel_info, SENSOR_SERVER_SET_SETTING, &set_data); + } + } + else + { + set_read_only = TRUE; + } + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + if (MESH_MSG_SENSOR_SETTING_SET == pmesh_msg->access_opcode) + { + sensor_setting_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + pmsg->property_id, pmsg->setting_property_id, set_read_only, + setting, delay_rsp_time); + } + + if (NULL != setting) + { +#if MODEL_ENABLE_DELAY_MSG_RSP + bool ack = (pmesh_msg->access_opcode == MESH_MSG_SENSOR_SETTING_SET_UNACK) ? FALSE : TRUE; + generic_transition_time_t trans_time = {0, 0}; + uint32_t delay_pub_time = delay_msg_get_trans_delay(0, trans_time, delay_rsp_time, TRUE, ack); + sensor_setting_delay_publish(pmodel_info, pmsg->property_id, setting, delay_pub_time); +#else + /* TODO: check if setting is the same */ + sensor_setting_publish(pmodel_info, pmsg->property_id, setting); +#endif + } + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t sensor_setup_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + sensor_setup_info_t *pinfo = pmodel_info->pargs; + uint16_t property_id = 0; + for (uint16_t i = 0; i < pinfo->num_sensors; ++i) + { + property_id = pinfo->sensors[i].descriptor.property_id; + /* publish cadence */ + sensor_cadence_status(pmodel_info, 0, 0, property_id, pinfo->sensors[i].cadence, 0); + /* publish setting */ + for (uint16_t j = 0; j < pinfo->sensors[i].num_settings; ++j) + { + sensor_setting_status(pmodel_info, 0, 0, property_id, + pinfo->sensors[i].settings[i].setting_property_id, FALSE, + &(pinfo->sensors[i].settings[i]), 0); + } + } + + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void sensor_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == sensor_setup_server_receive) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + pmodel_info->model_receive = NULL; + } +} +#endif + +bool sensor_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_SENSOR_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->pargs = plt_malloc(sizeof(sensor_setup_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("sensor_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(sensor_setup_info_t)); + + pmodel_info->model_receive = sensor_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("sensor_setup_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = sensor_setup_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = sensor_setup_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_client.c new file mode 100644 index 00000000..1b7163e4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_client.c @@ -0,0 +1,208 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file time_client.c +* @brief Source file for time client model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-23 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "time_model.h" + +static mesh_msg_send_cause_t time_client_send(const mesh_model_info_p pmodel_info, + uint16_t dst, uint16_t app_key_index, uint8_t *pmsg, + uint16_t msg_len) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t time_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + time_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_GET); + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t time_get_zone(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + time_zone_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_ZONE_GET); + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t time_get_tai_utc_delta(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index) +{ + tai_utc_delta_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TAI_UTC_DELTA_GET); + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); + +} + +mesh_msg_send_cause_t time_get_role(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index) +{ + time_role_get_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_ROLE_GET); + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t time_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, tai_time_t time) +{ + time_set_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_SET); + /* to avoid gcc compile warning */ + uint8_t *temp = msg.tai_seconds; + *((tai_time_t *)temp) = time; + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t time_set_zone(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t time_zone_offset_new, + uint8_t tai_of_zone_change[5]) +{ + time_zone_set_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_ZONE_SET); + msg.time_zone_offset_new = time_zone_offset_new; + memcpy(msg.tai_of_zone_change, tai_of_zone_change, 5); + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t time_set_tai_utc_delta(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t tai_utc_delta_new, + uint8_t tai_of_delta_change[5]) +{ + tai_utc_delta_set_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TAI_UTC_DELTA_SET); + msg.tai_utc_delta_new = tai_utc_delta_new; + msg.padding = 0; + memcpy(msg.tai_of_delta_change, tai_of_delta_change, 5); + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +mesh_msg_send_cause_t time_set_role(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, time_role_t role) +{ + time_role_set_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_ROLE_SET); + msg.role = role; + return time_client_send(pmodel_info, dst, app_key_index, (uint8_t *)&msg, sizeof(msg)); +} + +static bool time_client_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_TIME_STATUS: + if (pmesh_msg->msg_len == sizeof(time_status_t) || + pmesh_msg->msg_len == MEMBER_OFFSET(time_status_t, subsecond)) + { + time_status_t *pmsg = (time_status_t *)pbuffer; + time_client_status_t status_data; + memset(&status_data, 0, sizeof(time_client_status_t)); + if (pmesh_msg->msg_len == sizeof(time_status_t)) + { + /* to avoid gcc compile warning */ + uint8_t *temp = pmsg->tai_seconds; + status_data.src = pmesh_msg->src; + status_data.tai_time = *((tai_time_t *)(temp)); + } + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_CLIENT_STATUS, + &status_data); + } + } + break; + case MESH_MSG_TIME_ROLE_STATUS: + if (pmesh_msg->msg_len == sizeof(time_role_status_t)) + { + time_role_status_t *pmsg = (time_role_status_t *)pbuffer; + time_client_status_role_t status_data; + status_data.role = (time_role_t)(pmsg->role); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_CLIENT_STATUS_ROLE, + &status_data); + } + } + break; + case MESH_MSG_TIME_ZONE_STATUS: + if (pmesh_msg->msg_len == sizeof(time_zone_status_t)) + { + time_zone_status_t *pmsg = (time_zone_status_t *)pbuffer; + time_client_status_zone_t status_data; + status_data.src = pmesh_msg->src; + status_data.time_zone_offset_current = pmsg->time_zone_offset_current; + status_data.time_zone_offset_new = pmsg->time_zone_offset_new; + memcpy(status_data.tai_of_zone_change, pmsg->tai_of_zone_change, 5); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_CLIENT_STATUS_ZONE, + &status_data); + } + } + break; + case MESH_MSG_TAI_UTC_DELTA_STATUS: + if (pmesh_msg->msg_len == sizeof(tai_utc_delta_status_t)) + { + tai_utc_delta_status_t *pmsg = (tai_utc_delta_status_t *)pbuffer; + time_client_status_tai_utc_delta_t status_data; + status_data.src = pmesh_msg->src; + status_data.tai_utc_delta_current = pmsg->tai_utc_delta_current; + status_data.padding1 = 0; + status_data.tai_utc_delta_new = pmsg->tai_utc_delta_new; + status_data.padding2 = 0; + memcpy(status_data.tai_of_delta_change, pmsg->tai_of_delta_change, 5); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_CLIENT_STATUS_TAI_UTC_DELTA, + &status_data); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +bool time_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_TIME_CLIENT; + if (NULL == pmodel_info->model_receive) + { + pmodel_info->model_receive = time_client_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("time_client_reg: missing data process callback!"); + } + } + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_model.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_model.h new file mode 100644 index 00000000..770b4bad --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_model.h @@ -0,0 +1,453 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file time_model.h +* @brief Head file for time models. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-22 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _TIME_MODEL_H_ +#define _TIME_MODEL_H_ + +#include "mesh_api.h" + +BEGIN_DECLS + +/** + * @addtogroup TIME + * @{ + */ + +/** + * @defgroup TIME_ACCESS_OPCODE Access Opcode + * @brief Mesh message access opcode + * @{ + */ +#define MESH_MSG_TIME_GET 0x8237 +#define MESH_MSG_TIME_SET 0x5C +#define MESH_MSG_TIME_STATUS 0x5D +#define MESH_MSG_TIME_ROLE_GET 0x8238 +#define MESH_MSG_TIME_ROLE_SET 0x8239 +#define MESH_MSG_TIME_ROLE_STATUS 0x823A +#define MESH_MSG_TIME_ZONE_GET 0x823B +#define MESH_MSG_TIME_ZONE_SET 0x823C +#define MESH_MSG_TIME_ZONE_STATUS 0x823D +#define MESH_MSG_TAI_UTC_DELTA_GET 0x823E +#define MESH_MSG_TAI_UTC_DELTA_SET 0x823F +#define MESH_MSG_TAI_UTC_DELTA_STATUS 0x8240 +/** @} */ + +/** + * @defgroup TIME_MODEL_ID Model ID + * @brief Mesh model id + * @{ + */ +#define MESH_MODEL_TIME_SERVER 0x1200FFFF +#define MESH_MODEL_TIME_SETUP_SERVER 0x1201FFFF +#define MESH_MODEL_TIME_CLIENT 0x1202FFFF +/** @} */ + +/** + * @defgroup TIME_MESH_MSG Mesh Msg + * @brief Mesh message types used by models + * @{ + */ +#define MAX_UNCERTAINTY 255 + +typedef struct +{ + uint8_t tai_seconds[5]; /* little endian */ + uint8_t subsecond; + uint8_t uncertainty; + uint16_t time_authority: 1; + uint16_t tai_utc_delta: 15; + uint8_t time_zone_offset; +} _PACKED4_ tai_time_t; + +typedef struct +{ + uint8_t time_zone_offset_current; + uint8_t time_zone_offset_new; + uint8_t tai_of_zone_change[5]; /* little endian */ +} _PACKED4_ time_zone_t; + +typedef struct +{ + uint16_t tai_utc_delta_current: 15; + uint16_t padding1: 1; /* always 0*/ + uint16_t tai_utc_delta_new: 15; + uint16_t padding2: 1; /* always 0*/ + uint8_t tai_of_delta_change[5]; /* little endian */ +} _PACKED4_ tai_utc_delta_t; + +enum +{ + TIME_ROLE_NONE, + TIME_ROLE_AUTHORITY, + TIME_ROLE_RELAY, + TIME_ROLE_CLIENT +} _SHORT_ENUM_; +typedef uint8_t time_role_t; + +#define IS_TIME_ROLE_VALID(role) (role <= TIME_ROLE_CLIENT) + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_GET)]; +} _PACKED4_ time_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_SET)]; + uint8_t tai_seconds[5]; /* little endian */ + uint8_t subsecond; + uint8_t uncertainty; + uint16_t time_authority: 1; + uint16_t tai_utc_delta: 15; + uint8_t time_zone_offset; +} _PACKED4_ time_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_STATUS)]; + uint8_t tai_seconds[5]; /* little endian */ + uint8_t subsecond; + uint8_t uncertainty; + uint16_t time_authority: 1; + uint16_t tai_utc_delta: 15; + uint8_t time_zone_offset; +} _PACKED4_ time_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_ZONE_GET)]; +} _PACKED4_ time_zone_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_ZONE_SET)]; + uint8_t time_zone_offset_new; + uint8_t tai_of_zone_change[5]; /* little endian */ +} _PACKED4_ time_zone_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_ZONE_STATUS)]; + uint8_t time_zone_offset_current; + uint8_t time_zone_offset_new; + uint8_t tai_of_zone_change[5]; /* little endian */ +} _PACKED4_ time_zone_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TAI_UTC_DELTA_GET)]; +} _PACKED4_ tai_utc_delta_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TAI_UTC_DELTA_SET)]; + uint16_t tai_utc_delta_new: 15; + uint16_t padding: 1; /* always 0*/ + uint8_t tai_of_delta_change[5]; /* little endian */ +} _PACKED4_ tai_utc_delta_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TAI_UTC_DELTA_SET)]; + uint16_t tai_utc_delta_current: 15; + uint16_t padding1: 1; /* always 0*/ + uint16_t tai_utc_delta_new: 15; + uint16_t padding2: 1; /* always 0*/ + uint8_t tai_of_delta_change[5]; /* little endian */ +} _PACKED4_ tai_utc_delta_status_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_ROLE_GET)]; +} _PACKED4_ time_role_get_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_ROLE_SET)]; + time_role_t role; +} _PACKED4_ time_role_set_t; + +typedef struct +{ + uint8_t opcode[ACCESS_OPCODE_SIZE(MESH_MSG_TIME_ROLE_STATUS)]; + time_role_t role; +} _PACKED4_ time_role_status_t; +/** @} */ + +/** + * @defgroup TIME_SERVER_DATA Server Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define TIME_SERVER_GET 0 //!< @ref time_server_get_t +#define TIME_SERVER_GET_ROLE 1 //!< @ref time_server_get_role_t +#define TIME_SERVER_GET_ZONE 2 //!< @ref time_server_get_zone_t +#define TIME_SERVER_GET_TAI_UTC_DELTA 3 //!< @ref time_server_get_tai_utc_delta_t +#define TIME_SERVER_SET 4 //!< @ref time_server_set_t +#define TIME_SERVER_SET_ROLE 5 //!< @ref time_server_set_role_t +#define TIME_SERVER_STATUS_SET 6 //!< @ref time_server_status_set_t +#define TIME_SERVER_SET_ZONE 7 //!< @ref time_server_set_zone_t +#define TIME_SERVER_SET_TAI_UTC_DELTA 8 //!< @ref time_server_set_tai_utc_delta_t + +typedef tai_time_t time_server_get_t; +typedef time_zone_t time_server_get_zone_t; +typedef tai_utc_delta_t time_server_get_tai_utc_delta_t; +typedef tai_time_t time_server_set_t; + +typedef struct +{ + time_role_t role; +} time_server_get_role_t; + +typedef struct +{ + uint8_t tai_seconds[5]; /* little endian */ + uint8_t subsecond; + uint8_t uncertainty; + uint16_t tai_utc_delta; + uint8_t time_zone_offset; +} _PACKED4_ time_server_status_set_t; + +typedef struct +{ + time_role_t role; +} time_server_set_role_t; + +typedef struct +{ + uint8_t time_zone_offset_new; + uint8_t tai_of_zone_change[5]; /* little endian */ +} time_server_set_zone_t; + +typedef struct +{ + uint16_t tai_utc_delta_new: 15; + uint16_t padding: 1; /* always 0*/ + uint8_t tai_of_delta_change[5]; /* little endian */ +} time_server_set_tai_utc_delta_t; +/** @} */ + +/** + * @defgroup TIEM_CLIENT_DATA Client Data + * @brief Data types and structure used by data process callback + * @{ + */ +#define TIME_CLIENT_STATUS 0 //!< @ref time_client_status_t +#define TIME_CLIENT_STATUS_ZONE 1 //!< @ref time_client_status_zone_t +#define TIME_CLIENT_STATUS_TAI_UTC_DELTA 2 //!< @ref time_client_status_tai_utc_delta_t +#define TIME_CLIENT_STATUS_ROLE 3 //!< @ref time_client_status_role_t + +typedef struct +{ + uint16_t src; + tai_time_t tai_time; +} time_client_status_t; + +typedef struct +{ + uint16_t src; + uint8_t time_zone_offset_current; + uint8_t time_zone_offset_new; + uint8_t tai_of_zone_change[5]; +} time_client_status_zone_t; + +typedef struct +{ + uint16_t src; + uint16_t tai_utc_delta_current: 15; + uint16_t padding1: 1; /* always 0*/ + uint16_t tai_utc_delta_new: 15; + uint16_t padding2: 1; /* always 0*/ + uint8_t tai_of_delta_change[5]; /* little endian */ +} time_client_status_tai_utc_delta_t; + +typedef struct +{ + time_role_t role; +} time_client_status_role_t; +/** @} */ + +/** + * @defgroup TIME_SERVER_API Server API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register time server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to time server model context + * @retval true: register success + * @retval false: register failed + */ +bool time_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief register time setup server + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to time setup server model context + * @retval true: register success + * @retval false: register failed + */ +bool time_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief publish time information + * @param[in] pmodel_info: pointer to time server model context + * @param[in] time: time information need to publish + * @return publish status + */ +mesh_msg_send_cause_t time_publish(const mesh_model_info_p pmodel_info, + tai_time_t time); + +/** + * @brief increate time uncertainty + * @param[in] uncertainty: current time uncertainty + * @param[in] delta: increase delta + */ +void increase_uncertainty(uint8_t *uncertainty, uint8_t delta); + +/** + * @brief convert tai utc delta unsigned value to signed value + * @param[in] delta: unsigned delta value + * @return singed delta value + * @note tai utc delta valid range is -255 through +32512 + * (i.e., 0x00FF represents a value of 0 and 0x7FFF + * represents a value of 32512). + */ +int16_t tai_utc_delta_convert(uint16_t delta); + +/** + * @brief convert time zone offset unsigned value to signed value + * @param[in] time_zone_offset: unsigned time zone offset value + * @return singed time zone offset value + * @note time zone offset is a uint8 value representing the + * valid range of -64 through +191 + * (i.e., 0x40 represents a value of 0 and 0xFF + * represents a value of 191). + * time zone offset is 15-minute increments + */ +int16_t time_zone_offset_convert(uint8_t time_zone_offset); + +/** @} */ + +/** + * @defgroup TIME_CLIENT_API Client API + * @brief Functions declaration + * @{ + */ + +/** + * @brief register time client + * @param[in] element_index: element index that model registered to + * @param[in] pmodel_info: pointer to time client model context + * @retval TRUE: register success + * @retval FALSE: register failed + */ +bool time_client_reg(uint8_t element_index, mesh_model_info_p pmodel_info); + +/** + * @brief get time information + * @param[in] pmodel_info: pointer to time client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t time_get(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get time zone + * @param[in] pmodel_info: pointer to time client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t time_get_zone(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get time tai utc delta + * @param[in] pmodel_info: pointer to time client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t time_get_tai_utc_delta(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index); + +/** + * @brief get time role + * @param[in] pmodel_info: pointer to time client model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @return send status + */ +mesh_msg_send_cause_t time_get_role(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index); + +/** + * @brief set time information + * @param[in] pmodel_info: pointer to time information model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] time: time information + * @return send status + */ +mesh_msg_send_cause_t time_set(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, tai_time_t time); + +/** + * @brief set time zone + * @param[in] pmodel_info: pointer to time information model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] time_zone_offset_new: new time zone offset value + * @param[in] tai_of_zone_change: tai zone change value + * @return send status + */ +mesh_msg_send_cause_t time_set_zone(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, uint8_t time_zone_offset_new, + uint8_t tai_of_zone_change[5]); + +/** + * @brief set time information + * @param[in] pmodel_info: pointer to time information model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] tai_utc_delta_new: new tai utc delta value + * @param[in] tai_of_delta_change: tai delta change value + * @return send status + */ +mesh_msg_send_cause_t time_set_tai_utc_delta(const mesh_model_info_p pmodel_info, + uint16_t dst, + uint16_t app_key_index, uint16_t tai_utc_delta_new, + uint8_t tai_of_delta_change[5]); +/** + * @brief set time information + * @param[in] pmodel_info: pointer to time information model context + * @param[in] dst: remote address + * @param[in] app_key_index: mesh message used app key index + * @param[in] role: time role + * @return send status + */ +mesh_msg_send_cause_t time_set_role(const mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, time_role_t role); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _TIME_MODEL_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_server.c new file mode 100644 index 00000000..5c27cda1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_server.c @@ -0,0 +1,319 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file time_server.c +* @brief Source file for time server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-22 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "time_model.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#if 0 +typedef struct +{ + uint8_t tid; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} time_info_t; +#endif + +int16_t tai_utc_delta_convert(uint16_t delta) +{ + return delta - 0xff; +} + +int16_t time_zone_offset_convert(uint8_t time_zone_offset) +{ + return (int16_t)time_zone_offset - 0x40; +} + +void increase_uncertainty(uint8_t *uncertainty, uint8_t delta) +{ + if ((MAX_UNCERTAINTY - *uncertainty) > delta) + { + *uncertainty += delta; + } + else + { + *uncertainty = MAX_UNCERTAINTY; + } +} + +static mesh_msg_send_cause_t time_server_send(mesh_model_info_p pmodel_info, + uint16_t dst, void *pmsg, uint16_t msg_len, uint16_t app_key_index, + uint32_t delay_time) +{ + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = pmsg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t time_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, tai_time_t time, uint32_t delay_time) +{ + time_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_STATUS); + + uint8_t zero_tai_seconds[5] = {0, 0, 0, 0, 0}; + /* avoid gcc compile warning */ + uint8_t *temp = msg.tai_seconds; + *((tai_time_t *)(temp)) = time; + uint16_t msg_len = sizeof(time_status_t); + if (0 == memcmp(time.tai_seconds, zero_tai_seconds, 5)) + { + msg_len = MEMBER_OFFSET(time_status_t, subsecond); + } + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = msg_len; + if (0 != dst) + { + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + } + else + { + /* spec need time publish ttl to be 0 */ + mesh_msg.ttl = 0; + } + mesh_msg.delay_time = delay_time; + return access_send(&mesh_msg); +} + +mesh_msg_send_cause_t time_zone_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, time_zone_t time_zone, uint32_t delay_time) +{ + time_zone_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_ZONE_STATUS); + /* avoid gcc compile warning */ + uint8_t *temp = (uint8_t *)&(msg.time_zone_offset_current); + *((time_zone_t *)temp) = time_zone; + + return time_server_send(pmodel_info, dst, &msg, sizeof(time_zone_status_t), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t tai_utc_delta_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, tai_utc_delta_t time_tai_utc_delta, uint32_t delay_time) +{ + tai_utc_delta_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TAI_UTC_DELTA_STATUS); + + msg.tai_utc_delta_current = time_tai_utc_delta.tai_utc_delta_current; + msg.padding1 = 0; + msg.tai_utc_delta_new = time_tai_utc_delta.tai_utc_delta_new; + msg.padding2 = 0; + memcpy(msg.tai_of_delta_change, time_tai_utc_delta.tai_of_delta_change, 5); + + return time_server_send(pmodel_info, dst, &msg, sizeof(tai_utc_delta_status_t), app_key_index, + delay_time); +} + +mesh_msg_send_cause_t time_delay_publish(const mesh_model_info_p pmodel_info, + tai_time_t time, uint32_t delay_time) +{ + mesh_msg_send_cause_t ret = MESH_MSG_SEND_CAUSE_INVALID_DST; + if (mesh_model_pub_check(pmodel_info)) + { + ret = time_status(pmodel_info, 0, 0, time, delay_time); + } + + return ret; +} + +mesh_msg_send_cause_t time_publish(const mesh_model_info_p pmodel_info, + tai_time_t time) +{ + return time_delay_publish(pmodel_info, time, 0); +} + +static tai_time_t get_present_time(const mesh_model_info_p pmodel_info) +{ + time_server_get_t get_data; + memset(&get_data, 0, sizeof(time_server_get_t)); + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET, &get_data); + } + + return get_data; +} + +static bool time_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_TIME_GET: + if (pmesh_msg->msg_len == sizeof(time_get_t)) + { + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + time_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_present_time(pmodel_info), + delay_rsp_time); + } + break; + case MESH_MSG_TIME_STATUS: + if (pmesh_msg->msg_len == sizeof(time_status_t)) + { + time_status_t *pmsg = (time_status_t *)pbuffer; + time_server_get_role_t get_role = {TIME_ROLE_NONE}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET_ROLE, &get_role); + } + + time_server_status_set_t status_set; + memcpy(status_set.tai_seconds, pmsg->tai_seconds, 5); + status_set.subsecond = pmsg->subsecond; + status_set.uncertainty = pmsg->uncertainty; + status_set.tai_utc_delta = pmsg->tai_utc_delta; + status_set.time_zone_offset = pmsg->time_zone_offset; + if ((TIME_ROLE_RELAY == get_role.role) || + (TIME_ROLE_CLIENT == get_role.role)) + { + /* update time */ + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_STATUS_SET, &status_set); + } + } + + if (TIME_ROLE_RELAY == get_role.role) + { + /* avoid gcc compile warning */ + uint8_t *temp = pmsg->tai_seconds; + /* publish time */ + time_publish(pmodel_info, *((tai_time_t *)(temp))); + } + } + break; + case MESH_MSG_TIME_ZONE_GET: + if (pmesh_msg->msg_len == sizeof(time_zone_get_t)) + { + time_server_get_zone_t get_zone; + memset(&get_zone, 0, sizeof(time_server_get_zone_t)); + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET_ZONE, &get_zone); + } + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + time_zone_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_zone, delay_rsp_time); + } + break; + case MESH_MSG_TAI_UTC_DELTA_GET: + if (pmesh_msg->msg_len == sizeof(tai_utc_delta_get_t)) + { + time_server_get_tai_utc_delta_t get_data; + memset(&get_data, 0, sizeof(time_server_get_tai_utc_delta_t)); + + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET_TAI_UTC_DELTA, &get_data); + } + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + tai_utc_delta_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_data, + delay_rsp_time); + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +static int32_t time_server_publish(mesh_model_info_p pmodel_info, bool retrans) +{ + /* avoid gcc compile warning */ + (void)retrans; + time_status(pmodel_info, 0, 0, get_present_time(pmodel_info), 0); + return 0; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void time_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == time_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool time_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_TIME_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + pmodel_info->pargs = plt_malloc(sizeof(time_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("time_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(time_info_t)); +#endif + pmodel_info->model_receive = time_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("time_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = time_server_deinit; +#endif + } + + if (NULL == pmodel_info->model_pub_cb) + { + pmodel_info->model_pub_cb = time_server_publish; + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_setup_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_setup_server.c new file mode 100644 index 00000000..f41579f2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_setup_server.c @@ -0,0 +1,228 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file time_setup_server.c +* @brief Source file for time setup server model. +* @details Data types and external functions declaration. +* @author hector_huang +* @date 2018-8-22 +* @version v1.0 +* ************************************************************************************* +*/ + +#include "time_model.h" +#if MODEL_ENABLE_DELAY_MSG_RSP +#include "delay_msg_rsp.h" +#endif + +#if 0 +typedef struct +{ + uint8_t tid; +#if MODEL_ENABLE_DELAY_MSG_RSP + uint32_t delay_pub_time; +#endif +} time_info_t; +#endif + +extern mesh_msg_send_cause_t time_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, tai_time_t time_info, uint32_t delay_time); +extern mesh_msg_send_cause_t time_zone_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, time_zone_t time_zone, uint32_t delay_time); +extern mesh_msg_send_cause_t tai_utc_delta_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, tai_utc_delta_t tai_utc_delta, uint32_t delay_time); + + +mesh_msg_send_cause_t time_role_status(mesh_model_info_p pmodel_info, uint16_t dst, + uint16_t app_key_index, time_role_t role, uint32_t delay_time) +{ + time_role_status_t msg; + ACCESS_OPCODE_BYTE(msg.opcode, MESH_MSG_TIME_ROLE_STATUS); + + uint16_t msg_len = sizeof(time_role_status_t); + msg.role = role; + + mesh_msg_t mesh_msg; + mesh_msg.pmodel_info = pmodel_info; + access_cfg(&mesh_msg); + mesh_msg.pbuffer = (uint8_t *)&msg; + mesh_msg.msg_len = msg_len; + mesh_msg.dst = dst; + mesh_msg.app_key_index = app_key_index; + mesh_msg.delay_time = delay_time; + + return access_send(&mesh_msg); +} + +static bool time_setup_server_receive(mesh_msg_p pmesh_msg) +{ + bool ret = TRUE; + uint8_t *pbuffer = pmesh_msg->pbuffer + pmesh_msg->msg_offset; + mesh_model_info_p pmodel_info = pmesh_msg->pmodel_info; + + switch (pmesh_msg->access_opcode) + { + case MESH_MSG_TIME_SET: + if (pmesh_msg->msg_len == sizeof(time_set_t)) + { + time_set_t *pmsg = (time_set_t *)pbuffer; + + time_server_set_t set_data; + /* avoid gcc compile warning */ + uint8_t *temp = pmsg->tai_seconds; + set_data = *((tai_time_t *)(temp)); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_SET, &set_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + time_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, set_data, delay_rsp_time); + } + break; + case MESH_MSG_TIME_ZONE_SET: + if (pmesh_msg->msg_len == sizeof(time_zone_set_t)) + { + time_zone_set_t *pmsg = (time_zone_set_t *)pbuffer; + + time_server_set_zone_t set_data; + set_data.time_zone_offset_new = pmsg->time_zone_offset_new; + memcpy(set_data.tai_of_zone_change, pmsg->tai_of_zone_change, 5); + time_server_get_zone_t get_zone; + memset(&get_zone, 0, sizeof(time_server_get_zone_t)); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_SET_ZONE, &set_data); + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET_ZONE, &get_zone); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + time_zone_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_zone, delay_rsp_time); + } + break; + case MESH_MSG_TAI_UTC_DELTA_SET: + if (pmesh_msg->msg_len == sizeof(tai_utc_delta_set_t)) + { + tai_utc_delta_set_t *pmsg = (tai_utc_delta_set_t *)pbuffer; + + time_server_set_tai_utc_delta_t set_data; + set_data.tai_utc_delta_new = pmsg->tai_utc_delta_new; + memcpy(set_data.tai_of_delta_change, pmsg->tai_of_delta_change, 5); + time_server_get_tai_utc_delta_t get_data; + memset(&get_data, 0, sizeof(time_server_get_tai_utc_delta_t)); + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_SET_TAI_UTC_DELTA, &set_data); + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET_TAI_UTC_DELTA, &get_data); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + tai_utc_delta_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, get_data, + delay_rsp_time); + } + break; + case MESH_MSG_TIME_ROLE_GET: + if (pmesh_msg->msg_len == sizeof(time_role_get_t)) + { + time_server_get_role_t get_role = {TIME_ROLE_NONE}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_GET_ROLE, &get_role); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + time_role_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + get_role.role, delay_rsp_time); + } + break; + case MESH_MSG_TIME_ROLE_SET: + if (pmesh_msg->msg_len == sizeof(time_role_set_t)) + { + time_role_set_t *pmsg = (time_role_set_t *)pbuffer; + if (IS_TIME_ROLE_VALID(pmsg->role)) + { + time_server_set_role_t set_role = {pmsg->role}; + if (NULL != pmodel_info->model_data_cb) + { + pmodel_info->model_data_cb(pmodel_info, TIME_SERVER_SET_ROLE, &set_role); + } + + uint32_t delay_rsp_time = 0; +#if MODEL_ENABLE_DELAY_MSG_RSP + delay_rsp_time = delay_msg_get_rsp_delay(pmesh_msg->dst); +#endif + time_role_status(pmodel_info, pmesh_msg->src, pmesh_msg->app_key_index, + set_role.role, delay_rsp_time); + } + } + break; + default: + ret = FALSE; + break; + } + return ret; +} + +#if MESH_MODEL_ENABLE_DEINIT +static void time_setup_server_deinit(mesh_model_info_t *pmodel_info) +{ + if (pmodel_info->model_receive == time_setup_server_receive) + { +#if 0 + /* now we can remove */ + if (NULL != pmodel_info->pargs) + { + plt_free(pmodel_info->pargs, RAM_TYPE_DATA_ON); + pmodel_info->pargs = NULL; + } +#endif + pmodel_info->model_receive = NULL; + } +} +#endif + +bool time_setup_server_reg(uint8_t element_index, mesh_model_info_p pmodel_info) +{ + if (NULL == pmodel_info) + { + return FALSE; + } + + pmodel_info->model_id = MESH_MODEL_TIME_SETUP_SERVER; + if (NULL == pmodel_info->model_receive) + { +#if 0 + pmodel_info->pargs = plt_malloc(sizeof(time_info_t), RAM_TYPE_DATA_ON); + if (NULL == pmodel_info->pargs) + { + printe("time_setup_server_reg: fail to allocate memory for the new model extension data!"); + return FALSE; + } + memset(pmodel_info->pargs, 0, sizeof(time_info_t)); +#endif + pmodel_info->model_receive = time_setup_server_receive; + if (NULL == pmodel_info->model_data_cb) + { + printw("time_setup_server_reg: missing model data process callback!"); + } +#if MESH_MODEL_ENABLE_DEINIT + pmodel_info->model_deinit = time_setup_server_deinit; +#endif + } + + return mesh_model_reg(element_index, pmodel_info); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_diagnose.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_diagnose.h new file mode 100644 index 00000000..feb0c7a8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_diagnose.h @@ -0,0 +1,164 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_diagnose.h + * @brief Head file for platform diagnose related. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-9-28 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PLATFORM_DIAGNOSE_H +#define _PLATFORM_DIAGNOSE_H + +/* Add Includes here */ +#include "platform_macros.h" +#include "trace.h" + +BEGIN_DECLS + +/** @addtogroup Platform_Diagnose + * @{ + */ + +/** @defgroup Platform_Diagnose_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/** @brief Mesh Modules */ +typedef enum +{ + MM_COMMON, + MM_GAP_SCHED, + MM_PB_ADV, + MM_PB_GATT, + MM_SERVICE, + MM_PROV, + MM_PROXY, + MM_BEACON, + MM_BEARER, //!< 8 + MM_NETWORK, + MM_TRANSPORT, + MM_FRND, + MM_HB, + MM_TRANS_PING, + MM_ACCESS, + MM_RPL, + MM_SECURITY, //!< 16 + MM_FLASH, + MM_MODEL, + MM_APP, + MM_NUM = 32 +} mesh_module_t; + +/** @{ */ +#define MESH_LOG_LEVEL_COUNT 4 //!< 0 LEVEL_ERROR (Highest) | 1 LEVEL_WARN | 2 LEVEL_INFO | 3 LEVEL_TRACE (Lowest) +#define MESH_LOG_LEVEL TRACE_LEVEL_TRACE //!< log of lower level won't be outputed +#define MESH_LOG_LEVEL_SIZE ((MM_NUM + 31)/32) //!< sizeof(uint32_t) +/** @} */ + +/** @brief log level control */ +extern uint32_t mesh_log_switch[MESH_LOG_LEVEL_COUNT][MESH_LOG_LEVEL_SIZE]; + +///@cond +#define ARG_T(t) t +#define ARG_N(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,N,...) N +#define ARG_N_HELPER(...) ARG_T(ARG_N(__VA_ARGS__)) +#define COUNT_ARG1(...) ARG_N_HELPER(__VA_ARGS__,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) +#define COUNT_ARG(...) ((COUNT_ARG1(1, ##__VA_ARGS__) - 1)%21) + +#ifndef MM_ID +#define MM_ID MM_COMMON +#endif +#define LOG_PRINT1(module, level, fmt, ...) do\ + {\ + if(level <= MESH_LOG_LEVEL && module < MM_NUM && mesh_log_switch[level][module/32] & (1 << (module % 32)))\ + DBG_BUFFER(TYPE_BTLIB, SUBTYPE_FORMAT, TRACE_MODULE_APP, LEVEL_ERROR, "!**"#module" "fmt, COUNT_ARG(__VA_ARGS__), ##__VA_ARGS__);\ + } while(0) +#define LOG_PRINT(module, level, fmt, ...) LOG_PRINT1(module, level, fmt, ##__VA_ARGS__) +#define LOG_DUMP1(module, level, pdata, len) do\ + {\ + if(level <= MESH_LOG_LEVEL && mesh_log_switch[level][module/32] & (1 << (module % 32)))\ + DBG_BUFFER(TYPE_BTLIB, SUBTYPE_FORMAT, TRACE_MODULE_APP, LEVEL_ERROR, "!**"#module" %b", 1, TRACE_BINARY(len, pdata));\ + } while(0) +#define LOG_DUMP(module, level, pdata, len) LOG_DUMP1(module, level, pdata, len) +///@endcond + +/** @} */ + +/** @defgroup Platform_Diagnose_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** @defgroup Diagnose_API Diagnose API + * @brief C-type printf log api + * + * format print, each has four trace types. + * -# ERROR : Fatal, Procedure Cannot Advance + * -# WARN : Abnormal Condition Occurred, But Procedure Can Advance + * -# INFO : Important Notification + * -# TRACE : Verbose Debug, Security Info + * @{ + */ +#define printe(fmt, ...) LOG_PRINT(MM_ID, TRACE_LEVEL_ERROR, fmt, ##__VA_ARGS__) +#define printw(fmt, ...) LOG_PRINT(MM_ID, TRACE_LEVEL_WARN, fmt, ##__VA_ARGS__) +#define printi(fmt, ...) LOG_PRINT(MM_ID, TRACE_LEVEL_INFO, fmt, ##__VA_ARGS__) +#define printt(fmt, ...) LOG_PRINT(MM_ID, TRACE_LEVEL_TRACE, fmt, ##__VA_ARGS__) +/** @} */ + +/** @defgroup Dump_API Dump API + * @brief raw data dump api + * + * raw data dump, each has four trace types. + * -# ERROR : Fatal, Procedure Cannot Advance + * -# WARN : Abnormal Condition Occurred, But Procedure Can Advance + * -# INFO : Important Notification + * -# TRACE : Verbose Debug, Security Info + * @{ + */ +#define dprinte(pdata, len) LOG_DUMP(MM_ID, TRACE_LEVEL_ERROR, pdata, len) +#define dprintw(pdata, len) LOG_DUMP(MM_ID, TRACE_LEVEL_WARN, pdata, len) +#define dprinti(pdata, len) LOG_DUMP(MM_ID, TRACE_LEVEL_INFO, pdata, len) +#define dprintt(pdata, len) LOG_DUMP(MM_ID, TRACE_LEVEL_TRACE, pdata, len) +/** @} */ + +/** @brief assert */ +#define diag_assert(expr) //PLATFORM_ASSERT(expr) + +/** + * @brief Set mesh modules debug diagnose level + * + * Each modules has four levels of logs with different importance which can be set independantly. + * There maybe too many logs of the stack to analyze the application behavior. + * So it's recommended to close the log of LEVEL_TRACE which is the least important. + * @param[in] level: log level @ref MESH_LOG_LEVEL_COUNT + * @param[in] module_bitmap: bitmap of mesh modules, 0 means disable the log of the corresponding module + * @return operation result + * @retval true: operation success + * @retval false: operation failure + * + * Example usage + * \code{.c} + void mesh_stack_init(void) + { + ... + uint32_t log_value[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(LEVEL_TRACE, log_value); + ... + } + * \endcode + */ +bool diag_level_set(uint8_t level, uint32_t *module_bitmap); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_DIAGNOSE_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_list.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_list.h new file mode 100644 index 00000000..0a9d2e6a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_list.h @@ -0,0 +1,90 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_list.h + * @brief Head file for list structure related. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-9-28 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PLATFORM_LIST_ +#define _PLATFORM_LIST_ + +#include "platform_types.h" + +BEGIN_DECLS + +/** @addtogroup Platform_List + * @{ + */ + +/** @defgroup Platform_List_Exported_Types Exported Types + * @{ + */ + +/** @brief general element type of link list */ +typedef struct _plt_list_e_t +{ + struct _plt_list_e_t *pnext; + uint8_t data[4]; +} plt_list_e_t; + +/** @brief general list type of link list */ +typedef struct +{ + plt_list_e_t *pfirst; + plt_list_e_t *plast; + uint32_t count; +} plt_list_t; + +/** @} */ + +/** @defgroup Platform_List_Exported_Functions Exported Functions + * @brief + * @{ + */ + +/** + * @brief push in the element to the end of the list + * @param[in] plist: the list pointer + * @param[in] plist_e: the element pointer + * @return none + */ +void plt_list_push(plt_list_t *plist, void *plist_e); + +/** + * @brief pop out the first element of the list + * @param[in] plist: the list pointer + * @return the list element + */ +void *plt_list_pop(plt_list_t *plist); + +/** + * @brief insert the element to any position of the list + * @param[in] plist: the list pointer + * @param[in] plist_e: the ahead element pointer + * @param[in] plist_e_new: the new element pointer + * @return none + */ +void plt_list_insert(plt_list_t *plist, void *plist_e, void *plist_e_new); + +/** + * @brief delete the element at any position of the list + * @param[in] plist: the list pointer + * @param[in] plist_e_previous: the ahead element pointer + * @param[in] plist_e: the deleted element pointer + * @return none + */ +void plt_list_delete(plt_list_t *plist, void *plist_e_previous, void *plist_e); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_LIST_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_macros.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_macros.h new file mode 100644 index 00000000..0f85ea3c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_macros.h @@ -0,0 +1,167 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_macros.h + * @brief Head file for platform macros. + * @details Compile, mathematic etc related + * @author bill + * @date 2017-3-3 + * @version v1.0 + * ************************************************************************************* + */ + +#ifndef _PLATFORM_MACROS_H_ +#define _PLATFORM_MACROS_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** @addtogroup Platform_Macros + * @{ + */ + +/** @defgroup Platform_Macros_Exported_Macros Exported Macros + * @{ + */ +#undef _PACKED4_ +#undef _SHORT_ENUM_ +#define _PACKED4_ __attribute__ ((packed)) +#define _SHORT_ENUM_ __attribute__ ((packed)) +/* avoid gcc compile warning */ +#ifndef __INLINE +#if defined ( __CC_ARM ) +#define __INLINE __inline +#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) +#define __INLINE __inline +#elif defined ( __GNUC__ ) +#define __INLINE __inline +#elif defined( __ICCARM__ ) +#define __INLINE inline +#endif +#endif + +#undef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +#undef ABS +#define ABS(a) ((a < 0) ? -(a) : (a)) + +#undef CLAMP +#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x))) + +#define MEMBER_OFFSET(struct_type, member) ((uint32_t)&((struct_type *)0)->member) + +#define CONTAINER_OF(member_ptr, struct_type, member) \ + (struct_type *)((char *)member_ptr - MEMBER_OFFSET(struct_type, member)) + +/* avoid gcc compile warning */ +#ifndef BIT0 +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#endif +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#ifndef BIT +#define BIT(_n) (uint32_t)(1U << (_n)) +#endif + +#define BYTE0(data) ((uint8_t)data) +#define BYTE1(data) ((uint8_t)(data >> 8)) +#define BYTE2(data) ((uint8_t)(data >> 16)) +#define BYTE3(data) ((uint8_t)(data >> 24)) +#define BYTE(data, n) ((uint8_t)(data >> 8*n)) +#define BYTES2(data) BYTE0(data), BYTE1(data) +#define BYTES4(data) BYTE0(data), BYTE1(data), BYTE2(data), BYTE3(data) + +/* Get local WORD from external 2 BYTE, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_EXTRN2WORD(p) ((*((p)+1)) & 0xff) + ((*(p)) << 8) + +/* Get local DWORD from external 4 BYTE, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_EXTRN2DWORD(p) ((unsigned long)(*((p)+3)) & 0xff) + ((unsigned long)(*((p)+2)) << 8) \ + + ((unsigned long)(*((p)+1)) << 16) + ((unsigned long)(*((p)+0)) << 24) + +/* PUT external 2 CHARS from local SHORT, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_WORD2EXTRN(p,w) \ + {*((p)+1) = (unsigned char)((w) & 0xff); \ + *(p) = /*lint -e(572,778)*/ (unsigned char)(((w)>>8) & 0xff);} + +/* PUT external 4 BYTE from local DWORD, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_DWORD2EXTRN(p,w) \ + {*((p)+3) = (unsigned char)((w) & 0xff); \ + *((p)+2) = /*lint -e(572,778)*/ (unsigned char)(((w)>>8) & 0xff); \ + *((p)+1) = /*lint -e(572,778)*/ (unsigned char)(((w)>>16) & 0xff); \ + *((p)+0) = /*lint -e(572,778)*/ (unsigned char)(((w)>>24) & 0xff);} + +/* Get local WORD from external 2 BYTE, Little-Endian format */ +#define LE_EXTRN2WORD(p) (((*(p)) & 0xff) + ((*((p)+1)) << 8)) + +/* Get local DWORD from external 4 BYTE, Little-Endian format */ +#define LE_EXTRN2DWORD(p) (((unsigned long)(*((p)+0)) & 0xff) + ((unsigned long)(*((p)+1)) << 8) \ + + ((unsigned long)(*((p)+2)) << 16) + ((unsigned long)(*((p)+3)) << 24)) + +/* PUT external 2 BYTE from local WORD, Little-Endian Format */ +#define LE_WORD2EXTRN(p,w) \ + {*((unsigned char*)p) = (unsigned char)((unsigned short)(w) & 0xff); \ + *(((unsigned char*)p)+1) = /*lint -e(572,778)*/ (unsigned char)(((unsigned short)(w)>>8) & 0xff);} + +/* PUT external 4 BYTE from local DWORD, Little endian Format */ +#define LE_DWORD2EXTRN(p,w) \ + {*((unsigned char*)p) = (unsigned char)((unsigned long)(w) & 0xff); \ + *(((unsigned char*)p)+1) = (unsigned char)(((unsigned long)(w)>>8) & 0xff); \ + *(((unsigned char*)p)+2) = (unsigned char)(((unsigned long)(w)>>16) & 0xff); \ + *(((unsigned char*)p)+3) = (unsigned char)(((unsigned long)(w)>>24) & 0xff);} + +#ifdef __cplusplus +#define BEGIN_DECLS extern "C" { +#define END_DECLS } +#else +#define BEGIN_DECLS +#define END_DECLS +#endif + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) +#endif + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _PLATFORM_MACROS_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_misc.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_misc.h new file mode 100644 index 00000000..f0408db9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_misc.h @@ -0,0 +1,152 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_misc.h + * @brief Head file for platform miscellaneous. + * @details Data types and external functions declaration. + * @author bill + * @date 2017-3-3 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PLATFORM_MISC_H +#define _PLATFORM_MISC_H + +/* Add Includes here */ +#include +#include "platform_types.h" +//#include "rtl876x_wdg.h" + +BEGIN_DECLS + +/** @addtogroup Platform_Misc + * @{ + */ + +/** @defgroup Platform_Misc_Exported_Functions Platform Misc Exported Functions + * @brief + * @{ + */ + +/** + * @brief Swap the endianess of the data + * @param[in] pdata: data pointer + * @param[out] pdata: data pointer + * @param[in] len: data length + * @return none + */ +void plt_swap1(uint8_t *pdata, uint16_t len); + +/** + * @brief Swap the endianess from the src addr to the dst addr who + * have different address range + * @param[out] dst: destination data pointer + * @param[in] src: source data pointer + * @param[in] len: data length + * @return none + */ +void plt_swap2(uint8_t *dst, uint8_t *src, uint16_t len); + +/** + * @brief Swap the endianess from the src addr to the dst addr who + * have any address range + * @param[out] dst: destination data pointer + * @param[in] src: source data pointer + * @param[in] len: data length + * @return none + */ +void plt_swap(uint8_t *dst, uint8_t *src, uint16_t len); + +/** @brief calculate the bytes needed by the bit pool */ +#define plt_bit_pool_size(bit_num) (((bit_num) + 7) / 8) + +/** + * @brief get the bit field value from the bit pool + * @param[in] pool: pool addr + * @param[in] bit: bit num + * @return bit field value + */ +bool plt_bit_pool_get(uint8_t *pool, uint32_t bit); + +/** + * @brief set the bit field of the bit pool + * @param[in] pool: pool addr + * @param[in] bit: bit num + * @param[in] value: bit value + * @return none + */ +void plt_bit_pool_set(uint8_t *pool, uint32_t bit, bool value); + +/** + * @brief count the bit 1 of the bit pool + * @param[in] pool: pool addr + * @param[in] pool_len: pool length + * @return bit 1 number + */ +uint32_t plt_bit_pool_count(uint8_t *pool, uint32_t pool_len); + +/** + * @brief set the seed + * @param[in] seed + * @return none + */ +void plt_srand(uint32_t seed); + +/** + * @brief generate the random number + * @param[out] prand: the addr to output + * @param[in] len: the length of the rand + * @return none + */ +void plt_rand(uint8_t *prand, uint16_t len); + +/** + * @brief logarithm + * @param[in] value: exp value + * @return log value + */ +uint8_t plt_log2(uint32_t value); + +/** + * @brief exponent + * @param[in] log: log value + * @return exp value + */ +uint32_t plt_exp2(uint8_t log); + +/** + * @brief trasnform the hex string to a binary array (big endian) + * + * The binary array will be filled with 0 if the string length is not enough. + * @param[out] pbin: binary output + * @param[in] phex: hex ascii input + * @param[in] pbin_len: binary output max lenght + * @return actual binary output length + * + * Example usage + * \code{.c} + void test(void) + { + ... + uint8_t *string = "01020304"; + uint8_t uuid[16]; + plt_hex_to_bin(uuid, string, sizeof(uuid)); + // result: uuid[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04} + ... + } + * \endcode + */ +uint16_t plt_hex_to_bin(uint8_t *pbin, uint8_t *phex, uint16_t pbin_len); + +/** @brief reset */ +#define plt_reset(reason) //WDG_SystemReset(RESET_ALL, UPPER_CMD_RESET) + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_MISC_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_os.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_os.h new file mode 100644 index 00000000..af5a3724 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_os.h @@ -0,0 +1,127 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_os.h + * @brief Head file for platform os related. + * @details OS related + * @author bill + * @date 2017-9-30 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PLATFORM_OS_H +#define _PLATFORM_OS_H + +/* Add Includes here */ +#include "platform_macros.h" +#include "os_timer.h" +#include "os_msg.h" +#include "os_sync.h" +#include "os_mem.h" +#include "os_sched.h" +#include "os_task.h" + +BEGIN_DECLS + +/** @addtogroup Platform_OS + * @{ + */ + +/** @defgroup Critical_Section Critical Section + * @{ + */ +#define plt_critical_enter() os_lock() +#define plt_critical_exit(flags) os_unlock(flags) +/** @} */ + +/** @defgroup os task + * @{ + */ +void *plt_task_handle_get(void); +/** @} */ + +/** @defgroup Mutex Mutex + * @{ + */ +typedef void *plt_mutex_t; +plt_mutex_t plt_mutex_create(void); +#define plt_mutex_delete(mutex) os_mutex_delete(mutex) +#define plt_mutex_take(mutex, wait_ms) os_mutex_take(mutex, wait_ms) +#define plt_mutex_give(mutex) os_mutex_give(mutex) +/** @} */ + +/** @defgroup Dynamic_Memory Dynamic Memory + * @brief heap memory management + * @{ + */ +#define RAM_TYPE_DATA_OFF RAM_TYPE_DATA_ON +#define plt_malloc(size, ram_type) os_mem_alloc(ram_type, size) +#define plt_zalloc(size, ram_type) os_mem_zalloc(ram_type, size) +#define plt_free(p, ram_type) os_mem_free(p) +/** @} */ + +/** @defgroup Sync_Queue Sync Queue + * @brief sync os queue, the task maybe blocked when invoked + * @{ + */ +typedef void *plt_os_queue_handle_t; +plt_os_queue_handle_t plt_os_queue_create(uint32_t item_num, uint32_t item_size); +#define plt_os_queue_delete(queue_handle) os_msg_queue_delete(queue_handle) +#define plt_os_queue_send(queue_handle, pmsg, wait_ms) os_msg_send(queue_handle, pmsg, wait_ms) +#define plt_os_queue_receive(queue_handle, pmsg, wait_ms) os_msg_recv(queue_handle, pmsg, wait_ms) +/** @} */ + +/** @defgroup SW Timer + * @{ + */ +typedef void *plt_timer_t; +plt_timer_t plt_timer_create(const char *name, uint32_t period_ms, bool reload, uint32_t timer_id, + void (*pf_cb)(void *)); +#define plt_timer_delete(timer, wait_ms) os_timer_delete(&timer) +#define plt_timer_start(timer, wait_ms) os_timer_start(&timer) +#define plt_timer_stop(timer, wait_ms) os_timer_stop(&timer) +#define plt_timer_reset(timer, wait_ms) os_timer_start(&timer) +#define plt_timer_change_period(timer, period_ms, wait_ms) os_timer_restart(&timer, period_ms) +bool plt_timer_is_active(plt_timer_t timer); +uint32_t plt_timer_get_id(plt_timer_t timer); +/** @} */ + +/** @defgroup Time + * @{ + */ +/** cpu occupied delay */ +void plt_delay_us(uint32_t t); + +/** precision: 10ms, cpu unoccupied delay since task is switched out */ +#define plt_delay_ms(t) os_delay(t) + +/** @brief system time value increase progressively */ +#define VENDOR_BASE_ADDRESS 0x40058000 +#define VENDOR_READ(Vendor_offset) ((uint32_t)*((volatile uint32_t*)(VENDOR_BASE_ADDRESS+(Vendor_offset)))) +#define PLT_TIME_READ_US_MAX_VALUE (0x3FFFFFF/40) +/* precision: 1us, range: 0 ~ 1.677 second */ +#define plt_time_read_us() 0//((VENDOR_READ(0x17C) & 0x3FFFFFF)/40) + +/* precision: 10ms, range: 0 ~ 49 day*/ +#define plt_time_read_ms() os_sys_time_get() + +/** + * @brief diff the time with high precision as much as possible + * + * The precision is 1us in the range of 0 ~ 1.6 second, otherwise 10ms with the range of 0 ~ 24 day. + * @param[in] begin_ms: the ms-level begin time + * @param[in] begin_us: the us-level begin time + * @param[in] end_ms: the ms-level end time + * @param[in] end_us: the us-level end time + * @return time elapsed (bit31 indicates the unit of return value: 1 - us, 0 - ms.) + */ +uint32_t plt_time_diff(uint32_t begin_ms, uint32_t begin_us, uint32_t end_ms, uint32_t end_us); +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_OS_H */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_types.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_types.h new file mode 100644 index 00000000..74f2a80d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform/platform_types.h @@ -0,0 +1,55 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file platform_types.h + * @brief Head file for platform types. + * @details Basic types related. + * @author bill + * @date 2017-3-3 + * @version v1.0 + * ************************************************************************************* + */ + +#ifndef _PLATFORM_TYPES_H_ +#define _PLATFORM_TYPES_H_ + +#include +#include +#include +#include "platform_macros.h" + +BEGIN_DECLS + +/** @addtogroup Platform_Types + * @{ + */ + +/** @defgroup Platform_Types_Exported_Macros Exported Macros + * @brief + * @{ + */ + +/* boolean definition */ +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL (0L) +#else +#define NULL ((void *)0) +#endif +#endif + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PLATFORM_TYPES_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.c new file mode 100644 index 00000000..78d05f24 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.c @@ -0,0 +1,523 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_client.c +* @brief Source file for data transmission client. +* @details +* @author hector_huang +* @date 2018-10-31 +* @version v1.0 +* ************************************************************************************* +*/ +#include "mesh_api.h" +#include "datatrans_service.h" +#include "datatrans_client.h" + +/** used for CCCD handle discovering in discovery procedure */ +typedef enum +{ + DATATRANS_CCCD_DISC_START, + DATATRANS_CCCD_DISC_DATA_OUT, + DATATRANS_CCCD_DISC_END +} datatrans_cccd_disc_state_t; + +T_CLIENT_ID datatrans_client_id = CLIENT_PROFILE_GENERAL_ID; +/**< callback used to send data to app from datatrans client layer. */ +static P_FUN_GENERAL_APP_CB datatrans_client_app_cb = NULL; +/**< discovery state indicate which cccd is in discovery. */ +static datatrans_cccd_disc_state_t datatrans_cccd_disc_state = DATATRANS_CCCD_DISC_START; +/**< data transmission service discovered handles */ +static uint16_t datatrans_hdl_cache[HDL_DATATRANS_CACHE_LEN]; +/**< datatrans discovery end handle control. */ +static datatrans_handle_type_t datatrans_end_handle_idx = HDL_DATATRANS_CACHE_LEN; + +bool datatrans_client_handle_set(datatrans_handle_type_t type, uint16_t value) +{ + if (type < HDL_DATATRANS_CACHE_LEN) + { + datatrans_hdl_cache[type] = value; + return TRUE; + } + return FALSE; +} + +uint16_t datatrans_client_handle_get(datatrans_handle_type_t type) +{ + return datatrans_hdl_cache[type]; +} + +bool datatrans_client_start_discovery(uint8_t conn_id) +{ + printi("datatrans_client_start_discovery"); + memset(datatrans_hdl_cache, 0, sizeof(datatrans_hdl_cache)); + return (GAP_CAUSE_SUCCESS == client_by_uuid128_srv_discovery(conn_id, datatrans_client_id, + (uint8_t *)GATT_UUID_DATATRANS_SERVICE)); +} + +/** + * @brief start the discovery of data transmission characteristics. + * @retval TRUE: send request to upper stack success. + * @retval FALSE: send request to upper stack failed. + */ +static bool datatrans_client_start_char_discovery(uint8_t conn_id) +{ + printi("datatrans_client_start_char_discovery"); + return (GAP_CAUSE_SUCCESS == client_all_char_discovery(conn_id, datatrans_client_id, + datatrans_hdl_cache[HDL_DATATRANS_SRV_START], datatrans_hdl_cache[HDL_DATATRANS_SRV_END])); +} + +/** + * @brief used internal, start the discovery of data transmission characteristics descriptor. + * @retval TRUE: request to upper stack success. + * @retval FALSE: request to upper stack failed. + */ +static bool datatrans_client_start_char_descriptor_discovery(uint16_t start_handle, + uint16_t end_handle) +{ + uint8_t conn_id = 0; + printi("datatrans_client_start_char_descriptor_discovery"); + return (client_all_char_descriptor_discovery(conn_id, datatrans_client_id, start_handle, + end_handle) == GAP_CAUSE_SUCCESS); +} + +/** + * @brief used internal, switch to the next cccd handle to be discovered. + * @param cccd_state: CCCD discovery state. + */ +static void datatrans_client_switch_next_descriptor(datatrans_cccd_disc_state_t *cccd_state) +{ + datatrans_cccd_disc_state_t new_state; + switch (*cccd_state) + { + case DATATRANS_CCCD_DISC_START: + if (datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT]) + { + new_state = DATATRANS_CCCD_DISC_DATA_OUT; + } + else + { + new_state = DATATRANS_CCCD_DISC_END; + } + break; + case DATATRANS_CCCD_DISC_DATA_OUT: + new_state = DATATRANS_CCCD_DISC_END; + break; + default: + new_state = DATATRANS_CCCD_DISC_END; + break; + } + + *cccd_state = new_state; +} + +/** + * @brief called by profile client layer, when discover state of discovery procedure changed. + * @param conn_id[in]: connection link id + * @param disc_state: current service discovery state. + */ +static void datatrans_disc_state_cb(uint8_t conn_id, T_DISCOVERY_STATE disc_state) +{ + bool cb_flag = FALSE; + bool descriptor_disc_flag = FALSE; + uint16_t start_handle; + uint16_t end_handle; + datatrans_client_cb_data_t cb_data; + cb_data.cb_type = DATATRANS_CLIENT_CB_TYPE_DISC_STATE; + printi("datatrans_discover_state_cb: disc_state = %d", disc_state); + switch (disc_state) + { + case DISC_STATE_SRV_DONE: + if ((0 != datatrans_hdl_cache[HDL_DATATRANS_SRV_START]) || + (0 != datatrans_hdl_cache[HDL_DATATRANS_SRV_END])) + { + /** indicate that service handle found. start discover characteristic. */ + if (datatrans_client_start_char_discovery(0) == FALSE) + { + cb_data.cb_content.disc_state = DATATRANS_DISC_FAIL; + cb_flag = TRUE; + } + } + else + { + /** no datatrans service handle found. discover procedure complete. */ + cb_data.cb_content.disc_state = DATATRANS_DISC_NOT_FOUND; + cb_flag = TRUE; + } + break; + case DISC_STATE_CHAR_DONE: + if (datatrans_end_handle_idx < HDL_DATATRANS_CACHE_LEN) + { + /** we should store the last char end handle if needed. */ + datatrans_hdl_cache[datatrans_end_handle_idx] = datatrans_hdl_cache[HDL_DATATRANS_SRV_END]; + datatrans_end_handle_idx = HDL_DATATRANS_CACHE_LEN; + } + /** find the first descriptor to be discovered. */ + datatrans_cccd_disc_state = DATATRANS_CCCD_DISC_START; + datatrans_client_switch_next_descriptor(&datatrans_cccd_disc_state); + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + /** find the next descriptor to be discovered. */ + datatrans_client_switch_next_descriptor(&datatrans_cccd_disc_state); + break; + case DISC_STATE_FAILED: + cb_data.cb_content.disc_state = DATATRANS_DISC_FAIL; + cb_flag = TRUE; + break; + default: + printw("datatrans_client_disc_state_cb: invalid discovery state!"); + break; + } + + /** switch different char descriptor discovery, if has multi char descriptors. */ + switch (datatrans_cccd_disc_state) + { + case DATATRANS_CCCD_DISC_DATA_OUT: + /** need to discover datatrans notify characteristic descriptor. */ + start_handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT] + 1; + end_handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_END]; + descriptor_disc_flag = TRUE; + break; + case DATATRANS_CCCD_DISC_END: + cb_data.cb_content.disc_state = DATATRANS_DISC_DONE; + cb_flag = TRUE; + break; + default: + /** no need to send char descriptor discovery. */ + break; + } + if (descriptor_disc_flag) + { + if (datatrans_client_start_char_descriptor_discovery(start_handle, end_handle) == FALSE) + { + cb_data.cb_content.disc_state = DATATRANS_DISC_FAIL; + cb_flag = TRUE; + } + } + + /** send discover state to application if needed. */ + if (cb_flag && datatrans_client_app_cb) + { + datatrans_client_app_cb(datatrans_client_id, conn_id, &cb_data); + } +} + +/** + * @brief called by profile client layer, when discover result fetched. + * @param conn_id[in]: connection link id + * @param result_type: indicate which type of value discovered in service discovery procedure. + * @param result_data: value discovered. + */ +static void datatrans_disc_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + /* avoid gcc compile warning */ + (void)conn_id; + + printi("datatrans_discover_result_cb: result_type = %d", result_type); + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + datatrans_client_handle_set(HDL_DATATRANS_SRV_START, result_data.p_srv_disc_data->att_handle); + datatrans_client_handle_set(HDL_DATATRANS_SRV_END, result_data.p_srv_disc_data->end_group_handle); + break; + case DISC_RESULT_CHAR_UUID16: + /** when use client api all characteristic discovery */ + if (datatrans_end_handle_idx < HDL_DATATRANS_CACHE_LEN) + { + datatrans_hdl_cache[datatrans_end_handle_idx] = result_data.p_char_uuid16_disc_data->decl_handle - + 1; + datatrans_end_handle_idx = HDL_DATATRANS_CACHE_LEN; + } + /** we should inform intrested handles to upper application */ + switch (result_data.p_char_uuid16_disc_data->uuid16) + { + case DATATRANS_DATA_IN_UUID: + datatrans_client_handle_set(HDL_DATATRANS_DATA_IN, + result_data.p_char_uuid16_disc_data->value_handle); + break; + case DATATRANS_DATA_OUT_UUID: + datatrans_client_handle_set(HDL_DATATRANS_DATA_OUT, + result_data.p_char_uuid16_disc_data->value_handle); + datatrans_end_handle_idx = HDL_DATATRANS_DATA_OUT_END; + break; + default: + /** have no interest on this handle */ + break; + } + break; + case DISC_RESULT_CHAR_DESC_UUID16: + if (GATT_UUID_CHAR_CLIENT_CONFIG == result_data.p_char_desc_uuid16_disc_data->uuid16) + { + /** when use client api_all characteristic descriptor discovery */ + uint16_t temp_handle = result_data.p_char_desc_uuid16_disc_data->handle; + if ((temp_handle > datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT]) && + (temp_handle <= datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_END])) + { + datatrans_client_handle_set(HDL_DATATRANS_DATA_OUT_CCCD, temp_handle); + } + else + { + /** have no interest in this handle */ + } + } + break; + default: + printe("datatrans_discover_result_cb: invalid discovery result type!"); + break; + } +} + +/** + * @brief called by profile client layer, when read request responsed. + * @param conn_id[in]: connection handle id + * @param cause[in]: read result cause + * @param handle[in]: handle of the value in read response. + * @param value_size[in]: size of the value in read response. + * @param pvalue[in]: pointer to the value in read response. + */ +static void datatrans_read_result_cb(uint8_t conn_id, uint16_t cause, uint16_t handle, + uint16_t value_size, uint8_t *p_value) +{ + datatrans_client_cb_data_t cb_data; + cb_data.cb_type = DATATRANS_CLIENT_CB_TYPE_READ_RESULT; + cb_data.cb_content.read_result.cause = cause; + printi("datatrans_client_read_result_cb: cause = %d, handle = 0x%x, size = %d", cause, handle, + value_size); + /* if read req success, branch to fetch value and send to application. */ + if (handle == datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_CCCD]) + { + cb_data.cb_content.read_result.type = DATATRANS_READ_DATA_OUT_CCCD; + if ((cause == GAP_SUCCESS) && (value_size == sizeof(uint16_t))) + { + uint16_t cccd_value = LE_EXTRN2WORD(p_value); + cb_data.cb_content.read_result.data.datatrans_data_out_cccd = cccd_value & + GATT_CLIENT_CHAR_CONFIG_NOTIFY; + } + /** inform application the read result. */ + if (datatrans_client_app_cb) + { + datatrans_client_app_cb(datatrans_client_id, conn_id, &cb_data); + } + } + else if (handle == datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT]) + { + cb_data.cb_content.read_result.type = DATATRANS_READ_DATA_OUT; + if (cause == GAP_SUCCESS) + { + if (value_size > DATATRANS_CLIENT_MAX_DATA_OUT_LEN) + { + value_size = DATATRANS_CLIENT_MAX_DATA_OUT_LEN; + printw("datatrans_read_result_cb: data too long, truncated!"); + } + cb_data.cb_content.read_result.data.value.len = value_size; + memcpy(cb_data.cb_content.read_result.data.value.datatrans_data_out, p_value, value_size); + } + /** inform application the read result. */ + if (datatrans_client_app_cb) + { + datatrans_client_app_cb(datatrans_client_id, conn_id, &cb_data); + } + } +} + +/** + * @brief called by profile client layer, when write request complete. + * @param conn_id[in]: connection link id + * @param type[in]: write type + * @param handle[in]: attribute handle to write + * @param cause[in]: write result cause + * @param credits[in]: write result credits + */ +static void datatrans_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, uint16_t handle, + uint16_t cause, uint8_t credits) +{ + /* avoid gcc compile warning */ + (void)type; + (void)credits; + + /** if write req success, branch to fetch value and send to application */ + if (handle == datatrans_hdl_cache[HDL_DATATRANS_DATA_IN]) + { + datatrans_client_cb_data_t cb_data; + cb_data.cb_type = DATATRANS_CLIENT_CB_TYPE_WRITE_RESULT; + cb_data.cb_content.write_result.cause = cause; + cb_data.cb_content.write_result.type = DATATRANS_WRITE_DATA_IN; + + /** inform application the write result */ + if (datatrans_client_app_cb) + { + datatrans_client_app_cb(datatrans_client_id, conn_id, &cb_data); + } + } +} + +/** + * @brief called by profile client layer, when notification or indication arrived. + * @param conn_id[in]: connection link id + * @param notify[in]: TRUE: notify FALSE: indication + * @param handle[in]: handle of the value in received data. + * @param len[in]: size of the value in received data. + * @param pvalue[in]: pointer to the value in received data. + * @retval APP_RESULT_SUCESS: procedure OK. + * other value: procedure exception. + */ +static T_APP_RESULT datatrans_notify_indicate_result_cb(uint8_t conn_id, bool notify, + uint16_t handle, + uint16_t value_size, uint8_t *p_value) +{ + T_APP_RESULT app_result = APP_RESULT_REJECT; + + if (notify && (handle == datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT])) + { + datatrans_client_cb_data_t cb_data; + cb_data.cb_type = DATATRANS_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + cb_data.cb_content.notify_indicate_data.type = DATATRANS_DATA_OUT_NOTIFY; + if (value_size > DATATRANS_CLIENT_MAX_DATA_OUT_LEN) + { + value_size = DATATRANS_CLIENT_MAX_DATA_OUT_LEN; + printw("datatrans_notify_indicate_result_cb: data too long, truncated!"); + } + cb_data.cb_content.notify_indicate_data.value.len = value_size; + memcpy(cb_data.cb_content.notify_indicate_data.value.datatrans_data_out, p_value, value_size); + /** inform application notify/indication data */ + if (datatrans_client_app_cb) + { + datatrans_client_app_cb(datatrans_client_id, conn_id, &cb_data); + } + + app_result = APP_RESULT_SUCCESS; + } + return app_result; +} + +/** + * @brief called by profile client layer, when link disconnected. + * @param conn_id[in]: connection link id + */ +static void datatrans_disconnect_cb(uint8_t conn_id) +{ + /* avoid gcc compile warning */ + (void)conn_id; + + /* seset some params, when disconnection occurs. */ + datatrans_end_handle_idx = HDL_DATATRANS_CACHE_LEN; + datatrans_cccd_disc_state = DATATRANS_CCCD_DISC_START; +} + +const T_FUN_CLIENT_CBS datatrans_client_cbs = +{ + datatrans_disc_state_cb, //!< Discovery State callback function pointer + datatrans_disc_result_cb, //!< Discovery result callback function pointer + datatrans_read_result_cb, //!< Read response callback function pointer + datatrans_write_result_cb, //!< Write result callback function pointer + datatrans_notify_indicate_result_cb, //!< Notify Indicate callback function pointer + datatrans_disconnect_cb //!< Link disconnection callback function pointer +}; + +bool datatrans_client_read_by_handle(uint8_t conn_id, datatrans_read_type_t type) +{ + uint16_t handle = 0; + switch (type) + { + case DATATRANS_READ_DATA_OUT_CCCD: + handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_CCCD]; + break; + case DATATRANS_READ_DATA_OUT: + handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT]; + break; + default: + break; + } + + if (handle) + { + if (GAP_CAUSE_SUCCESS == client_attr_read(conn_id, datatrans_client_id, handle)) + { + return TRUE; + } + } + printe("datatrans_client_read_by_handle: request fail! please check!"); + return FALSE; +} + +bool datatrans_client_read_by_uuid(uint8_t conn_id, datatrans_read_type_t type) +{ + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + switch (type) + { + case DATATRANS_READ_DATA_OUT_CCCD: + start_handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT] + 1; + end_handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case DATATRANS_READ_DATA_OUT: + start_handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT]; + end_handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_END] - 1; + uuid16 = DATATRANS_DATA_OUT_UUID; + break; + default: + break; + } + + if (start_handle && + (GAP_CAUSE_SUCCESS == client_attr_read_using_uuid(conn_id, datatrans_client_id, start_handle, + end_handle, uuid16, NULL))) + { + return TRUE; + } + printe("datatrans_client_read_by_uuid: request fail! please check!"); + return FALSE; +} + +bool datatrans_client_data_out_cccd_set(uint8_t conn_id, bool command) +{ + uint16_t handle; + handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_OUT_CCCD]; + if (handle) + { + uint16_t cccd_value = command ? 1 : 0; + uint16_t length = sizeof(uint16_t); + uint8_t *pdata = (uint8_t *)&cccd_value; + if (GAP_CAUSE_SUCCESS == client_attr_write(conn_id, datatrans_client_id, GATT_WRITE_TYPE_REQ, + handle, length, + pdata)) + { + return TRUE; + } + } + + printe("datatrans_client_data_out_cccd_set: request fail! please check!"); + return FALSE; +} + +bool datatrans_client_data_in_write(uint8_t conn_id, uint8_t *pdata, uint16_t length) +{ + uint16_t handle; + handle = datatrans_hdl_cache[HDL_DATATRANS_DATA_IN]; + if (handle && + (GAP_CAUSE_SUCCESS == client_attr_write(conn_id, datatrans_client_id, GATT_WRITE_TYPE_CMD, handle, + length, pdata))) + { + return TRUE; + } + printe("datatrans_client_data_in_write: request fail! please check!"); + return FALSE; +} + +T_CLIENT_ID datatrans_client_add(P_FUN_GENERAL_APP_CB app_cb) +{ + T_CLIENT_ID client_id; + if (FALSE == client_register_spec_client_cb(&client_id, &datatrans_client_cbs)) + { + client_id = CLIENT_PROFILE_GENERAL_ID; + printe("datatrans_client_add: fail!"); + return client_id; + } + datatrans_client_id = client_id; + /* register callback for profile to inform application that some events happened. */ + datatrans_client_app_cb = app_cb; + return datatrans_client_id; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.h new file mode 100644 index 00000000..e48ed23f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.h @@ -0,0 +1,215 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_client.h +* @brief Head file for data transmission client +* @details +* @author hector_huang +* @date 2018-10-31 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _DATATRANS_CLIENT_H_ +#define _DATATRANS_CLIENT_H_ + +#include "platform_types.h" +#include "profile_client.h" + +BEGIN_DECLS + +/** @addtogroup Data_Trans_Client + * @{ + */ + +/** + * @defgroup Data_Trans_Client_Exported_Macros Exported Macros + * @{ + */ +#define DATATRANS_CLIENT_MAX_DATA_OUT_LEN 32 +/** @} */ + +/** + * @defgroup Data_Trans_Client_Exported_types Exported Types + * @{ + */ +/** datatrans client ID. */ +extern T_CLIENT_ID datatrans_client_id; + +typedef enum +{ + HDL_DATATRANS_SRV_START, + HDL_DATATRANS_SRV_END, + HDL_DATATRANS_DATA_IN, + HDL_DATATRANS_DATA_OUT, + HDL_DATATRANS_DATA_OUT_END, + HDL_DATATRANS_DATA_OUT_CCCD, + HDL_DATATRANS_CACHE_LEN +} datatrans_handle_type_t; + +typedef enum +{ + DATATRANS_DISC_DONE, + DATATRANS_DISC_FAIL, + DATATRANS_DISC_NOT_FOUND +} datatrans_disc_state_t; + +typedef struct +{ + datatrans_handle_type_t handle_type; + uint16_t handle_value; +} datatrans_disc_hdl_info_t; + +typedef enum +{ + DATATRANS_READ_DATA_OUT_CCCD, + DATATRANS_READ_DATA_OUT +} datatrans_read_type_t; + +typedef struct +{ + uint16_t len; + uint8_t datatrans_data_out[DATATRANS_CLIENT_MAX_DATA_OUT_LEN]; +} _PACKED4_ datatrans_data_out_value_t; + +typedef union +{ + bool datatrans_data_out_cccd; + datatrans_data_out_value_t value; +} datatrans_read_data_t; + +typedef struct +{ + datatrans_read_type_t type; + datatrans_read_data_t data; + uint16_t cause; +} datatrans_read_result_t; + +typedef enum +{ + DATATRANS_WRITE_DATA_IN +} datatrans_write_type_t; + +typedef struct +{ + datatrans_write_type_t type; + uint16_t cause; +} datatrans_write_result_t; + +typedef enum +{ + DATATRANS_DATA_OUT_NOTIFY +} datatrans_notify_indicate_type_t; + +typedef struct +{ + datatrans_notify_indicate_type_t type; + datatrans_data_out_value_t value; +} datatrans_notify_indicate_data_t; + +typedef enum +{ + DATATRANS_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + DATATRANS_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + DATATRANS_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + DATATRANS_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + DATATRANS_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} datatrans_client_cb_type_t; + +typedef union +{ + datatrans_disc_state_t disc_state; + datatrans_disc_hdl_info_t disc_hdl_info; + datatrans_read_result_t read_result; + datatrans_write_result_t write_result; + datatrans_notify_indicate_data_t notify_indicate_data; +} datatrans_client_cb_content_t; + +typedef struct +{ + datatrans_client_cb_type_t cb_type; + datatrans_client_cb_content_t cb_content; +} datatrans_client_cb_data_t; +/** @} */ + +/** + * @defgroup Data_Trans_Client_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief add data transmission client to gatt stack + * @param[in] app_cb: application callback function + * @return service id + */ +T_CLIENT_ID datatrans_client_add(P_FUN_GENERAL_APP_CB app_cb); + +/** + * @brief start discovery data transmission service + * @param[in] conn_id: connection link id + * @retval TRUE: start discovery success + * @retval FALSE: start discovery fail + */ +bool datatrans_client_start_discovery(uint8_t conn_id); + +/** + * @brief read data from server by using handles. + * @param[in] conn_id: connection link id + * @param[in] type: one of characteristic that has the readable property. + * @retval TRUE: send request to upper stack success. + * @retval FALSE: send request to upper stack failed. + */ +bool datatrans_client_read_by_handle(uint8_t conn_id, datatrans_read_type_t type); + +/** + * @brief read data from server by using uuids. + * @param[in] conn_id: connection link id + * @param[in] type: one of characteristic that has the readable property. + * @retval TRUE: send request to upper stack success. + * FALSE: send request to upper stack failed. + */ +bool datatrans_client_read_by_uuid(uint8_t conn_id, datatrans_read_type_t type); + +/** + * @brief enable or disable the notification of peer server's notify characteristic. + * @param[in] conn_id: connection link id + * @param[in] command: 0-disable the notification, 1-enable the notification. + * @retval TRUE: send request to upper stack success. + * @retval FALSE: send request to upper stack failed. + */ +bool datatrans_client_data_out_cccd_set(uint8_t conn_id, bool command); + +/** + * @brief send write request to peer server's control point characteristic. + * @param[in] conn_id: connection link id + * @param[in] pdata: data to write + * @param[in] length: data length + * @retval TRUE: send request to upper stack success. + * @retval FALSE: send request to upper stack failed. + */ +bool datatrans_client_data_in_write(uint8_t conn_id, uint8_t *pdata, uint16_t length); + +/** + * @brief used by application, to set the handles in datatrans handle cache. + * @param[in] type: handle types of this specific profile. + * @param[in] value: handle value to set. + * @retval TRUE: success. + * @retval FALSE: failed. + */ +bool datatrans_client_handle_set(datatrans_handle_type_t type, uint16_t value); + +/** + * @brief used by application, to get the handles in datatrans handle cache. + * @param[in] type: handle types of this specific profile. + * @retval handle value. + */ +uint16_t datatrans_client_handle_get(datatrans_handle_type_t type); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /** _DATATRANS_CLIENT_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.c new file mode 100644 index 00000000..68c3b1c5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.c @@ -0,0 +1,270 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_server.c +* @brief Source file for data transmission server +* @details +* @author hector_huang +* @date 2018-10-31 +* @version v1.0 +* ************************************************************************************* +*/ +#define MM_ID MM_SERVICE + +#include "platform_misc.h" +#include "platform_diagnose.h" +#include "gap.h" +#include "profile_server.h" +#include "datatrans_service.h" +#include "datatrans_server.h" + +/** application callback function */ +static P_FUN_SERVER_GENERAL_CB datatrans_cb = NULL; + +/** @brief Index of each characteristic in service database. */ +#define DATATRANS_DATA_IN_INDEX 0x02 +#define DATATRANS_DATA_OUT_INDEX 0x04 +#define DATATRANS_DATA_OUT_CCCD_INDEX (DATATRANS_DATA_OUT_INDEX + 1) + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +uint8_t datatrans_server_id = SERVICE_PROFILE_GENERAL_ID; +//static uint8_t datatrans_data_out_cccd = GATT_CLIENT_CHAR_CONFIG_DEFAULT; + + +/** @brief profile/service definition. */ +const T_ATTRIB_APPL datatrans_server_table[] = +{ + /* <>, Data transmission service */ + { + (ATTRIB_FLAG_VOID | ATTRIB_FLAG_LE), /* wFlags */ + { /* bTypeValue */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + }, + UUID_128BIT_SIZE, /* bValueLen */ + (void *)GATT_UUID_DATATRANS_SERVICE, /* pValueContext */ + GATT_PERM_READ /* wPermissions */ + }, + + /* <>, Data transmission in */ + { + ATTRIB_FLAG_VALUE_INCL, /* wFlags */ + { /* bTypeValue */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_WRITE_NO_RSP /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* wPermissions */ + }, + /* Data transmission data value */ + { + ATTRIB_FLAG_VALUE_APPL, /* wFlags */ + { /* bTypeValue */ + LO_WORD(DATATRANS_DATA_IN_UUID), + HI_WORD(DATATRANS_DATA_IN_UUID) + }, + 0, /* bValueLen, 0 : variable length */ + NULL, + GATT_PERM_WRITE /* wPermissions */ + }, + + /* <>, Data transmission out */ + { + ATTRIB_FLAG_VALUE_INCL, /* wFlags */ + { /* bTypeValue */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_NOTIFY | GATT_CHAR_PROP_READ /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* wPermissions */ + }, + /* Data transmission data value */ + { + ATTRIB_FLAG_VALUE_APPL, /* wFlags */ + { /* bTypeValue */ + LO_WORD(DATATRANS_DATA_OUT_UUID), + HI_WORD(DATATRANS_DATA_OUT_UUID) + }, + 0, /* bValueLen, 0 : variable length */ + NULL, + GATT_PERM_READ /* wPermissions */ + }, + + /* Client characteristic configuration */ + { + (ATTRIB_FLAG_VALUE_INCL | /* wFlags */ + ATTRIB_FLAG_CCCD_APPL), + { /* bTypeValue */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* wPermissions */ + } +}; + +/** + * @brief data transmission server read data callback function + * @param conn_id[in]: connection link id + * @param service_id[in]: service id to be read + * @param attrib_index[in]: attribute index in service + * @param offset[in]: value read offset from pp_value + * @param p_length[out]: output value length + * @param pp_value[out]: output value pointer + * @return status + */ +static T_APP_RESULT datatrans_server_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + /* avoid gcc compile warning */ + (void)conn_id; + (void)offset; + T_APP_RESULT ret = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + case DATATRANS_DATA_OUT_INDEX: + if (NULL != datatrans_cb) + { + /** get data from specified app */ + datatrans_server_data_t cb_data; + cb_data.type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + datatrans_cb(service_id, &cb_data); + *p_length = cb_data.len; + *pp_value = cb_data.data; + } + break; + default: + printe("datatrans_server_read_cb: attribute not fount, index %d", attrib_index); + ret = APP_RESULT_ATTR_NOT_FOUND; + break; + } + + return ret; +} + +/** + * @brief data transmission server write data callback function + * @param conn_id[in]: connection link id + * @param service_id[in]: serivce id to be write to + * @param attrib_index[in]: attribute index in service + * @param wtire_type[in]: wtite type + * @param len[in]: data length + * @param pvalue[in]: data value + * @param ppost_proc[in]: write done callback + * @return status + */ +static T_APP_RESULT datatrans_server_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, + T_WRITE_TYPE write_type, uint16_t len, uint8_t *pvalue, P_FUN_WRITE_IND_POST_PROC *ppost_proc) +{ + /* avoid gcc compile warning */ + (void)conn_id; + (void)write_type; + (void)ppost_proc; + T_APP_RESULT ret = APP_RESULT_SUCCESS; + switch (attrib_index) + { + case DATATRANS_DATA_IN_INDEX: + if (NULL != datatrans_cb) + { + /** write data to specified app */ + datatrans_server_data_t cb_data; + cb_data.type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + cb_data.len = len; + cb_data.data = pvalue; + + datatrans_cb(service_id, &cb_data); + } + break; + default: + printe("datatrans_server_write_cb: attribute not fount, index %d", attrib_index); + ret = APP_RESULT_ATTR_NOT_FOUND; + break; + } + return ret; +} + +bool datatrans_server_notify(uint8_t conn_id, uint8_t *pvalue, uint16_t len) +{ + return server_send_data(conn_id, datatrans_server_id, DATATRANS_DATA_OUT_INDEX, pvalue, len, + GATT_PDU_TYPE_NOTIFICATION); +} + +/** + * @brief update cccd bits from stack. + * @param conn_id[in]: connection link id + * @param server_id[in]: service id + * @param attrib_index[in]: attribute index of characteristic data + * @param cccd_bits[in]: cccd bits from stack. + */ +static void datatrans_server_cccd_update_cb(uint8_t conn_id, T_SERVER_ID server_id, + uint16_t attrib_index, + uint16_t cccd_bits) +{ + /* avoid gcc compile warning */ + (void)conn_id; + (void)server_id; + printi("datatrans_server_cccd_update_cb: index = %d, cccd_bits = 0x%x", attrib_index, cccd_bits); + switch (attrib_index) + { + case DATATRANS_DATA_OUT_CCCD_INDEX: + { + if (cccd_bits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + /** enable notification */ + //datatrans_data_out_cccd = GATT_CLIENT_CHAR_CONFIG_NOTIFY; + } + else + { + /** disable Notification */ + //datatrans_data_out_cccd = GATT_CLIENT_CHAR_CONFIG_DEFAULT; + } + } + break; + default: + break; + } +} + +/** + * @brief service callbacks. + */ +const T_FUN_GATT_SERVICE_CBS datatrans_server_cbs = +{ + .read_attr_cb = datatrans_server_read_cb, /** read callback function pointer */ + .write_attr_cb = datatrans_server_write_cb, /** write callback function pointer */ + .cccd_update_cb = datatrans_server_cccd_update_cb /** cccd update callback function pointer */ +}; + +uint8_t datatrans_server_add(void *pcb) +{ + uint8_t server_id; + if (FALSE == server_add_service(&server_id, (uint8_t *)datatrans_server_table, + sizeof(datatrans_server_table), + datatrans_server_cbs)) + { + printe("datatrans_server_add: add service id(%d) failed!", datatrans_server_id); + server_id = SERVICE_PROFILE_GENERAL_ID; + return server_id; + } + + datatrans_server_id = server_id; + datatrans_cb = (P_FUN_SERVER_GENERAL_CB)pcb; + return datatrans_server_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.h new file mode 100644 index 00000000..89b78eca --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.h @@ -0,0 +1,69 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_server.h +* @brief Head file for data transmission server +* @details +* @author hector_huang +* @date 2018-10-31 +* @version v1.0 +* ************************************************************************************* +*/ +#ifndef _DATATRANS_SERVER_H_ +#define _DATATRANS_SERVER_H_ + +#include "platform_types.h" +#include "datatrans_service.h" + +BEGIN_DECLS + +/** @addtogroup Data_Trans_Server + * @{ + */ + +/** + * @defgroup Data_Trans_Server_Exported_Types Exported Types + * @{ + */ + +/** data transmission service id */ +extern uint8_t datatrans_server_id; + +/** callback data structure */ +typedef struct +{ + T_SERVICE_CALLBACK_TYPE type; + uint16_t len; + uint8_t *data; +} datatrans_server_data_t; +/** @} */ + +/** + * @defgroup Data_Trans_Server_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief add data transmission server service to gatt database + * @param[in] pcb: application callback function + * @return service id + */ +uint8_t datatrans_server_add(void *pcb); + +/** + * @brief notify data change to remote device + * @param[in] conn_id: connection link id + * @param[in] pvalue: value to notify + * @param[in] len: value length + * @return status + */ +bool datatrans_server_notify(uint8_t conn_id, uint8_t *pvalue, uint16_t len); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /** DATATRANS_SERVER_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c new file mode 100644 index 00000000..a92771ff --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c @@ -0,0 +1,17 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_service.c +* @brief Source file for data transmission service +* @details +* @author hector_huang +* @date 2018-11-05 +* @version v1.0 +* ************************************************************************************* +*/ +#include "datatrans_service.h" + +/** 128bit UUID of data transmission service */ +const uint8_t GATT_UUID_DATATRANS_SERVICE[16] = { 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xE0, 0x00, 0x00}; + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.h new file mode 100644 index 00000000..7d6af119 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.h @@ -0,0 +1,49 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** +* @file datatrans_service.h +* @brief Head file for data transmission service +* @details +* @author hector_huang +* @date 2018-11-05 +* @version v1.0 +* ************************************************************************************* +*/ + +#ifndef _DATATRANS_SERVICE_H_ +#define _DATATRANS_SERVICE_H_ + +#include "platform_types.h" + +BEGIN_DECLS + +/** + * @addtogroup Data_Trans + * @{ + */ + +/** + * @defgroup Data_Trans_Exported_Macros Exported Macros + * @{ + */ +/** characteristic uuid */ +#define DATATRANS_DATA_IN_UUID 0xFFE1 +#define DATATRANS_DATA_OUT_UUID 0xFFE2 +/** @} */ + +/** + * @defgroup Data_Trans_Exported_Types Exported Types + * @{ + */ + +/** 128bit UUID of data transmission service */ +extern const uint8_t GATT_UUID_DATATRANS_SERVICE[16]; + +/** @} */ +/** @} */ + +END_DECLS + +#endif /** _DATATRANS_SERVICE_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/provision_client.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/provision_client.h new file mode 100644 index 00000000..fbcbf7f2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/provision_client.h @@ -0,0 +1,219 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provision_client.h + * @brief Head file for using provision service Client. + * @details Data structs and external functions declaration. + * @author bill + * @date 2015-11-09 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROV_CLIENT_H_ +#define _PROV_CLIENT_H_ + +/* Add Includes here */ +#include "mesh_config.h" +#include "profile_client.h" +#include "provision_service.h" + +BEGIN_DECLS + +/** @addtogroup Prov_Client + * @{ + */ + +/** @defgroup Prov_Client_Exported_Types Exported Types + * @brief types that other.c files may use all defined here + * @{ + */ + +/** @brief Handle cache for intrested UUIDs */ +typedef enum +{ + HDL_PROV_SRV_START, // start handle of simple ble service + HDL_PROV_SRV_END, // end handle of simple ble service + HDL_PROV_DATA_IN, + HDL_PROV_DATA_OUT, + HDL_PROV_DATA_OUT_END, + HDL_PROV_DATA_OUT_CCCD, + HDL_PROV_CACHE_LEN +} prov_handle_type_t; + +/** @brief used to inform app the discovery procedure is done or pending */ +typedef enum +{ + PROV_DISC_DONE, + PROV_DISC_FAIL, + PROV_DISC_NOT_FOUND +} prov_disc_state_t; + +/** @brief handle information found in discovery procedure */ +typedef struct +{ + prov_handle_type_t handle_type; + uint16_t handle_value; +} prov_disc_hdl_info_t; + +/** @brief read request type, used by app to send read request */ +typedef enum +{ + PROV_READ_DATA_OUT_CCCD +} prov_read_type_t; + +/** @brief read content, used to inform app read response data content */ +typedef union +{ + bool prov_data_out_cccd; +} prov_read_data_t; + +/** @brief read data, used to inform app read response data */ +typedef struct +{ + prov_read_type_t type; + prov_read_data_t data; + uint16_t cause; +} prov_read_result_t; + +/** @brief write request result */ +typedef enum +{ + PROV_WRITE_DATA_IN +} prov_write_type_t; + +/** @brief write request result */ +typedef struct +{ + prov_write_type_t type; + uint16_t cause; +} prov_write_result_t; + +/** @brief notif/ind receive type */ +typedef enum +{ + PROV_DATA_OUT_NOTIFY +} prov_notify_indicate_type_t; + +/** @brief notif/ind receive content */ +typedef union +{ + uint8_t prov_data_out[65]; +} _PACKED4_ prov_notify_indicate_value_t; + +/** @brief The notif/ind data received by client */ +typedef struct +{ + prov_notify_indicate_type_t type; + prov_notify_indicate_value_t value; +} prov_notify_indicate_data_t; + +/** @brief Event type to inform app */ +typedef enum +{ + PROV_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + PROV_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + PROV_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + PROV_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + PROV_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} prov_client_cb_type_t; + +/** @brief Callback content sent to application */ +typedef union +{ + prov_disc_state_t disc_state; + prov_disc_hdl_info_t disc_hdl_info; + prov_read_result_t read_result; + prov_write_result_t write_result; + prov_notify_indicate_data_t notify_indicate_data; +} prov_client_cb_content_t; + +/** @brief data sent to application from client, include type and content */ +typedef struct +{ + prov_client_cb_type_t cb_type; + prov_client_cb_content_t cb_content; +} prov_client_cb_data_t; + +extern uint8_t prov_client_conn_id; +extern T_CLIENT_ID prov_client_id; +/** @} */ + +/** @defgroup Prov_Client_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief register the client + * @param[in] app_cb: the callback function + * @return client id + */ +T_CLIENT_ID prov_client_add(P_FUN_GENERAL_APP_CB app_cb); + +/** + * @brief set the handle of the client + * @param[in] conn_id: the connection id + * @param[in] type: the handle type + * @param[in] value: the handle value + * @return the operatino result + */ +bool prov_client_handle_set(uint8_t conn_id, prov_handle_type_t type, uint16_t value); + +/** + * @brief get the handle of the client + * @param[in] conn_id: the connection id + * @param[in] type: the handle type + * @return the handle value + */ +uint16_t prov_client_handle_get(uint8_t conn_id, prov_handle_type_t type); + +/** + * @brief start the service discovery + * + * contains the service/characteristic/cccd declaration + * @param[in] conn_id: the connection id + * @return the operatino result + */ +bool prov_client_start_discovery(uint8_t conn_id); + +/** + * @brief read the server by handle + * @param[in] conn_id: the connection id + * @param[in] type: the read type + * @return the operatino result + */ +bool prov_client_read_by_handle(uint8_t conn_id, prov_read_type_t type); + +/** + * @brief read the server by uuid + * @param[in] conn_id: the connection id + * @param[in] type: the handle type + * @return the operatino result + */ +bool prov_client_read_by_uuid(uint8_t conn_id, prov_read_type_t type); + +/** + * @brief write the cccd of the characteristic + * @param[in] conn_id: the connection id + * @param[in] command: the cccd value + * @return the operatino result + */ +bool prov_client_data_out_cccd_set(uint8_t conn_id, bool command); + +/** + * @brief write the characteristic + * @param[in] conn_id: the connection id + * @param[in] pdata: the data pointer + * @param[in] length: the data length + * @return the operatino result + */ +bool prov_client_data_in_write(uint8_t conn_id, uint8_t *pdata, uint16_t length); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROV_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/provision_service.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/provision_service.h new file mode 100644 index 00000000..0d1d8787 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/provision_service.h @@ -0,0 +1,67 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provision_service.h + * @brief Head file for smart mesh provision service. + * @details + * @author bill + * @date 2015-11-09 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROVISION_SERVICE_H_ +#define _PROVISION_SERVICE_H_ + +/* Add Includes here */ +#include "provision_generic.h" +#include "proxy_protocol.h" + +BEGIN_DECLS + +/** @addtogroup Provision_Service + * @{ + */ + +/** @defgroup Provision_Service_Exported_Constants Exported Constants + * @{ + */ +#define MESH_PB_GATT_PKT_OFFSET (3) //!< opcode + handle +#define MESH_PB_GATT_PKT_HEADER_SIZE (1) //!< control(2 bits) + info(6 bits) +#define MESH_PB_GATT_START_HEADER_SIZE (3) //!< length(2) + fcs(1) + +///@cond +/** @brief Index of each characteristic in service database. */ +#define MESH_PROV_SERVICE_UUID 0x1827 +#define MESH_PROV_DATA_IN_UUID 0x2ADB +#define MESH_PROV_DATA_OUT_UUID 0x2ADC +///@endcond + +/** @} */ + +/** @defgroup Provision_Service_Exported_Types Exported Types + * @brief + * @{ + */ +extern uint8_t prov_proxy_ctx_id; +extern prov_bearer_cb_pf pf_pb_gatt_cb; +/** @} */ + +/** @defgroup Provision_Service_Exported_Functions Exported Functions + * @brief + * @{ + */ +///@cond +bool prov_service_send(uint8_t *pvalue, uint16_t len); +bool prov_service_receive(uint8_t ctx_id, proxy_pdu_type_t type, uint8_t *pvalue, uint16_t len); +void prov_service_handle_tx_done(void); +void prov_service_handle_disc(gap_sched_link_t link); +///@endcond +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROVISION_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/proxy_client.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/proxy_client.h new file mode 100644 index 00000000..45a14a46 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/proxy_client.h @@ -0,0 +1,219 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file proxy_client.h + * @brief Head file for using proxy service client. + * @details Data structs and external functions declaration. + * @author bill + * @date 2016-4-1 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROXY_CLIENT_H_ +#define _PROXY_CLIENT_H_ + +/* Add Includes here */ +#include "mesh_config.h" +#include "profile_client.h" +#include "proxy_service.h" + +BEGIN_DECLS + +/** @addtogroup Proxy_Client + * @{ + */ + +/** @defgroup Proxy_Client_Exported_Types Exported Types + * @{ + */ + +/** @brief Handle cache for intrested UUIDs */ +typedef enum +{ + HDL_PROXY_SRV_START, + HDL_PROXY_SRV_END, + HDL_PROXY_DATA_IN, + HDL_PROXY_DATA_OUT, + HDL_PROXY_DATA_OUT_END, + HDL_PROXY_DATA_OUT_CCCD, + HDL_PROXY_CACHE_LEN +} proxy_handle_type_t; + +/** @brief used to inform app the discovery procedure is done or pending */ +typedef enum +{ + PROXY_DISC_DONE, + PROXY_DISC_FAIL, + PROXY_DISC_NOT_FOUND +} proxy_disc_state_t; + +/** @brief handle information found in discovery procedure */ +typedef struct +{ + proxy_handle_type_t handle_type; + uint16_t handle_value; +} proxy_disc_hdl_info_t; + +/** @brief read request type, used by app to send read request */ +typedef enum +{ + PROXY_READ_DATA_OUT_CCCD +} proxy_read_type_t; + +/** @brief read content, used to inform app read response data content */ +typedef union +{ + bool proxy_data_out_cccd; +} proxy_read_data_t; + +/** @brief read data, used to inform app read response data */ +typedef struct +{ + proxy_read_type_t type; + proxy_read_data_t data; + uint16_t cause; +} proxy_read_result_t; + +/** @brief write request result + */ +typedef enum +{ + PROXY_WRITE_DATA_IN +} proxy_write_type_t; + +/** @brief write request result */ +typedef struct +{ + proxy_write_type_t type; + uint16_t cause; +} proxy_write_result_t; + +/** @brief notif/ind receive type */ +typedef enum +{ + PROXY_DATA_OUT_NOTIFY +} proxy_notify_indicate_type_t; + +/** @brief notif/ind receive content */ +typedef union +{ + uint8_t proxy_data_out[31]; +} proxy_notify_indicate_value_t; + +/** @brief The notif/ind data received by client */ +typedef struct +{ + proxy_notify_indicate_type_t type; + proxy_notify_indicate_value_t value; +} proxy_notify_indicate_data_t; + +/** @brief Event type to inform app */ +typedef enum +{ + PROXY_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + PROXY_CLIENT_CB_TYPE_DISC_HDL, //!< Discovered handle information. + PROXY_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + PROXY_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + PROXY_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + PROXY_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} proxy_client_cb_type_t; + +/** @brief Callback content sent to application */ +typedef union +{ + proxy_disc_state_t disc_state; + proxy_disc_hdl_info_t disc_hdl_info; + proxy_read_result_t read_result; + proxy_write_result_t write_result; + proxy_notify_indicate_data_t notify_indicate_data; +} proxy_client_cb_content_t; + +/** @brief Callback data sent to application from client */ +typedef struct +{ + proxy_client_cb_type_t cb_type; + proxy_client_cb_content_t cb_content; +} proxy_client_cb_data_t; + +extern T_CLIENT_ID proxy_client_id; +/** @} */ + +/** @defgroup Proxy_Client_Exported_Functions Exported Functions + * @{ + */ + +/** + * @brief register the client + * @param[in] app_cb: the callback function + * @return client id + */ +T_CLIENT_ID proxy_client_add(P_FUN_GENERAL_APP_CB appCB); + +/** + * @brief set the handle of the client + * @param[in] conn_id: the connection id + * @param[in] type: the handle type + * @param[in] value: the handle value + * @return the operatino result + */ +bool proxy_client_handle_set(uint8_t conn_id, proxy_handle_type_t type, uint16_t value); + +/** + * @brief get the handle of the client + * @param[in] conn_id: the connection id + * @param[in] type: the handle type + * @return the handle value + */ +uint16_t proxy_client_handle_get(uint8_t conn_id, proxy_handle_type_t handle_type); + +/** + * @brief start the service discovery + * + * contains the service/characteristic/cccd declaration + * @param[in] conn_id: the connection id + * @return the operatino result + */ +bool proxy_client_start_discovery(uint8_t conn_id); + +/** + * @brief read the server by handle + * @param[in] conn_id: the connection id + * @param[in] type: the read type + * @return the operatino result + */ +bool proxy_client_read_by_handle(uint8_t conn_id, proxy_read_type_t readCharType); + +/** + * @brief read the server by uuid + * @param[in] conn_id: the connection id + * @param[in] type: the handle type + * @return the operatino result + */ +bool proxy_client_read_by_uuid(uint8_t conn_id, proxy_read_type_t readCharType); + +/** + * @brief write the cccd of the characteristic + * @param[in] conn_id: the connection id + * @param[in] command: the cccd value + * @return the operatino result + */ +bool proxy_client_data_out_cccd_set(uint8_t conn_id, bool command); + +/** + * @brief write the characteristic + * @param[in] conn_id: the connection id + * @param[in] pdata: the data pointer + * @param[in] length: the data length + * @return the operatino result + */ +bool proxy_client_data_in_write(uint8_t conn_id, uint8_t *pdata, uint16_t length); + +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROXY_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/proxy_service.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/proxy_service.h new file mode 100644 index 00000000..eb40d710 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/proxy_service.h @@ -0,0 +1,65 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file proxy_service.h + * @brief Head file for smart mesh proxy service. + * @details + * @author bill + * @date 2015-11-09 + * @version v1.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PROXY_SERVICE_H_ +#define _PROXY_SERVICE_H_ + +/* Add Includes here */ +#include "platform_types.h" +#include "proxy_protocol.h" + +BEGIN_DECLS + +/** @addtogroup Proxy_Service + * @{ + */ + +/** @defgroup Proxy_Service_Exported_Constants Exported Constants + * @{ + */ + +#define PROXY_PKT_OFFSET 3 //!< opcode + handle +#define PROXY_PKT_HEADER_SIZE 1 //!< @ref proxy_pkt_header_t + +///@cond +/** @brief Index of each characteristic in service database. */ +#define MESH_PROXY_SERVICE_UUID 0x1828 +#define MESH_PROXY_DATA_IN_UUID 0x2ADD +#define MESH_PROXY_DATA_OUT_UUID 0x2ADE +///@endcond + +/** @} */ + +/** @defgroup Proxy_Service_Exported_Types Exported Types + * @brief + * @{ + */ +/** @} */ + +/** @defgroup Proxy_Service_Exported_Functions Exported Functions + * @brief + * @{ + */ +///@cond +bool proxy_service_send(uint8_t ctx_id, proxy_pdu_type_t type, uint16_t dst, uint8_t *pvalue, + uint16_t len); +bool proxy_service_receive(uint8_t ctx_id, proxy_pdu_type_t type, uint8_t *pvalue, uint16_t len); +void proxy_service_handle_disc(gap_sched_link_t link); +///@endcond +/** @} */ +/** @} */ + +END_DECLS + +#endif /* _PROXY_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/utility/.gitignore b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/utility/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/utility/aes.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/utility/aes.h new file mode 100644 index 00000000..4b9334e0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/utility/aes.h @@ -0,0 +1,46 @@ +#ifndef _AES_H_ +#define _AES_H_ + +/* aes 128 implementation*/ +#include + +/** + * @addtogroup AES + * @{ + */ + +/** + * @defgroup Aes_Exported_Macros AES Exported Macros + * @brief + * @{ + */ +// #define the macros below to 1/0 to enable/disable the mode of operation. +// +// CBC enables AES128 encryption in CBC-mode of operation and handles 0-padding. +// ECB enables the basic ECB 16-byte block algorithm. Both can be enabled simultaneously. +// The #ifndef-guard allows it to be configured before #include'ing or at compile time. +#define CBC 0 +#define ECB 1 +/** @} */ + +/** + * @defgroup Aes_Exported_Functions AES Exported Functions + * @brief + * @{ + */ +#if ECB +void AES128_ECB_encrypt(const uint8_t input[16], const uint8_t key[16], uint8_t *output); +void AES128_ECB_decrypt(uint8_t *input, const uint8_t *key, uint8_t *output); +#endif + +#if CBC +void AES128_CBC_encrypt_buffer(uint8_t *output, uint8_t *input, uint32_t length, const uint8_t *key, + const uint8_t *iv); +void AES128_CBC_decrypt_buffer(uint8_t *output, uint8_t *input, uint32_t length, const uint8_t *key, + const uint8_t *iv); +#endif +/** @} */ +/** @} */ + +#endif //_AES_H_ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_flags.h new file mode 100644 index 00000000..21078712 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_flags.h @@ -0,0 +1,41 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_PROVISIONER_APP_FLAGS_H_ +#define _BT_MESH_PROVISIONER_APP_FLAGS_H_ + +#include + +/** + * @addtogroup MESH_APP_CONFIG + * @{ + */ + +/** + * @defgroup Mesh_App_Config Mesh App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/ +#define F_BT_AIRPLANE_MODE_SUPPORT 0 + +/** @} */ +/** @} */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_main.c new file mode 100644 index 00000000..fa46527d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_main.c @@ -0,0 +1,448 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "provisioner_app.h" +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "health.h" +#include "ping.h" +#include "ping_app.h" +#include "tp.h" +#include "generic_client_app.h" +#include "light_client_app.h" +#include "provision_client.h" +#include "proxy_client.h" +#include "datatrans_app.h" +#include "bt_mesh_provisioner_app_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#include "wifi_constants.h" +#if defined(MESH_RPR) && MESH_RPR +#include "rmt_prov_client_app.h" +#endif +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_distributor_app.h" +#endif +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO +#include "bt_mesh_app_list_intf.h" +#endif + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_provisioner_api.h" +#endif + +#define COMPANY_ID 0x005D +#define PRODUCT_ID 0x0000 +#define VERSION_ID 0x0000 + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; + +void bt_mesh_example_device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + /* avoid gcc compile warning */ + (void)bt_addr; + (void)bt_addr_type; + (void)rssi; + uint8_t NULL_UUID[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + if (pinfo->type == DEVICE_INFO_UDB) { + if (rtw_memcmp(pinfo->pbeacon_udb->dev_uuid, NULL_UUID, 16) == 0) + add_unproed_dev(pinfo->pbeacon_udb->dev_uuid); + } +} + +void generic_on_off_client_subscribe(void) +{ + uint16_t sub_addr = 0xFEFF; + mesh_model_p pmodel = model_goo_client.pmodel; + + if (pmodel == NULL || MESH_NOT_SUBSCRIBE_ADDR(sub_addr)) { + return; + } else { + mesh_model_sub(pmodel, sub_addr); + } +} +#endif + +/****************************************************************** + * @fn Initial gap parameters + * @brief Initialize peripheral and gap bond manager related parameters + * + * @return void + */ +void bt_mesh_provisioner_stack_init(void) +{ + /** set ble stack log level, disable nonsignificant log */ + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + // log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_ERROR, 0); + // log_module_trace_set(TRACE_MODULE_SNOOP, TRACE_LEVEL_ERROR, 0); + + /** set mesh stack log level, default all on, disable the log of level LEVEL_TRACE */ + uint32_t module_bitmap[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(TRACE_LEVEL_TRACE, module_bitmap); + + /** mesh stack needs rand seed */ + plt_srand(platform_random(0xffffffff)); + + /** set device name and appearance */ + char *dev_name = "Mesh Provisioner"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + gap_sched_params_set(GAP_SCHED_PARAMS_DEVICE_NAME, dev_name, GAP_DEVICE_NAME_LEN); + gap_sched_params_set(GAP_SCHED_PARAMS_APPEARANCE, &appearance, sizeof(appearance)); + + /** configure provisioning parameters */ + prov_params_set(PROV_PARAMS_CALLBACK_FUN, (void *)prov_cb, sizeof(prov_cb_pf)); + + /** config node parameters */ + mesh_node_features_t features = + { + .role = MESH_ROLE_PROVISIONER, + .relay = 1, + .proxy = 1, + .fn = 1, + .lpn = 2, + .prov = 1, + .udb = 0, + .snb = 1, + .bg_scan = 1, + .flash = 1, + .flash_rpl = 1 + }; + + mesh_node_cfg_t node_cfg = + { + .dev_key_num = 20, + .net_key_num = 10, + .app_key_num = 3, + .vir_addr_num = 3, + .rpl_num = 20, + .sub_addr_num = 5, + .proxy_num = 1 + }; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + features.relay = 0; + features.flash_rpl = 0; + node_cfg.dev_key_num = 50; + node_cfg.rpl_num = 50; + node_cfg.sub_addr_num = 0; +#endif + + node_cfg.proxy_interval = 5; + mesh_node_cfg(features, &node_cfg); + mesh_node.net_trans_count = 6; + mesh_node.relay_retrans_count = 2; + mesh_node.trans_retrans_count = 4; + mesh_node.ttl = 5; + + /** create elements and register models */ + mesh_element_create(GATT_NS_DESC_UNKNOWN); + mesh_element_create(GATT_NS_DESC_UNKNOWN); + cfg_client_reg(); + generic_client_models_init(); +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + init_bt_mesh_priv(); +#else + tp_control_reg(tp_reveive); + ping_control_reg(ping_app_ping_cb, pong_receive); + trans_ping_pong_init(ping_app_ping_cb, pong_receive); + light_client_models_init(); + datatrans_model_init(); +#endif +#if defined(MESH_DFU) && MESH_DFU + dfu_dist_models_init(); +#endif +#if defined(MESH_RPR) && MESH_RPR + rmt_prov_client_init(); +#endif + compo_data_page0_header_t compo_data_page0_header = {COMPANY_ID, PRODUCT_ID, VERSION_ID}; + compo_data_page0_gen(&compo_data_page0_header); + + /** init mesh stack */ + mesh_init(); + + /** register udb/provision adv/proxy adv callback */ +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + device_info_cb_reg(bt_mesh_example_device_info_cb); + hb_init(hb_cb); + generic_on_off_client_subscribe(); +#else + device_info_cb_reg(device_info_cb); + hb_init(hb_cb); +#endif +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_mesh_provisioner_app_le_gap_init(void) +{ + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + uint16_t scan_window = 0x100; /* 160ms */ + uint16_t scan_interval = 0x120; /* 180ms */ + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_mesh_provisioner_app_gap_callback); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + + vendor_cmd_init(bt_mesh_provisioner_app_vendor_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_mesh_provisioner_app_le_profile_init(void) +{ + server_init(MESH_GATT_SERVER_COUNT); + /* Add Server Module */ + + /* Register Server Callback */ + server_register_app_cb(bt_mesh_provisioner_app_profile_callback); + + client_init(MESH_GATT_CLIENT_COUNT); + /* Add Client Module */ + prov_client_add(bt_mesh_provisioner_app_client_callback); + proxy_client_add(bt_mesh_provisioner_app_client_callback); + + /* Register Client Callback--App_ClientCallback to handle events from Profile Client layer. */ + client_register_general_client_cb(bt_mesh_provisioner_app_client_callback); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void bt_mesh_provisioner_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_mesh_provisioner_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void bt_mesh_provisioner_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void bt_mesh_provisioner_task_init(void) +{ + bt_mesh_provisioner_app_task_init(); +} + +void bt_mesh_provisioner_task_deinit(void) +{ + bt_mesh_provisioner_app_task_deinit(); +} + +void bt_mesh_provisioner_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_mesh_provisioner_app_main(void) +{ + bt_trace_init(); + bt_mesh_provisioner_stack_config_init(); + bte_init(); + bt_mesh_provisioner_board_init(); + bt_mesh_provisioner_driver_init(); + le_gap_init(APP_MAX_LINKS); + bt_mesh_provisioner_app_le_gap_init(); + bt_mesh_provisioner_app_le_profile_init(); + bt_mesh_provisioner_stack_init(); + bt_mesh_provisioner_pwr_mgr_init(); + bt_mesh_provisioner_task_init(); + + return 0; +} + +typedef unsigned long rtw_interface_t; +extern int wifi_is_up(rtw_interface_t interface); +extern void bt_coex_init(void); + +int bt_mesh_provisioner_app_init(void) +{ + int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + bt_stack_already_on = 1; + printf("[BT Mesh Provisioner]BT Stack already on\n\r"); + return 0; + } + else + bt_mesh_provisioner_app_main(); + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + if (bt_stack_already_on) { + uint8_t bt_addr[6]; + uint8_t net_key[16] = MESH_NET_KEY; + uint8_t net_key1[16] = MESH_NET_KEY1; + uint8_t app_key[16] = MESH_APP_KEY; + uint8_t app_key1[16] = MESH_APP_KEY1; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /** configure provisioner */ + mesh_node.node_state = PROV_NODE; + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + memcpy(&net_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&net_key1[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key1[10], bt_addr, sizeof(bt_addr)); + uint16_t net_key_index = net_key_add(0, net_key); + app_key_add(net_key_index, 0, app_key); + uint8_t net_key_index1 = net_key_add(1, net_key1); + app_key_add(net_key_index1, 1, app_key1); + mesh_model_bind_all_key(); + } + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_provisioner_api_init()) { + printf("[BT Mesh Provisioner] bt_mesh_provisioner_api_init fail ! \n\r"); + return 1; + } +#endif + + return 0; + +} + +extern void mesh_deinit(void); +extern bool mesh_initial_state; +extern bool bt_trace_uninit(void); + +void bt_mesh_provisioner_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + bt_mesh_provisioner_api_deinit(); +#endif + bt_mesh_provisioner_task_deinit(); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Provisioner] BT Stack is not running\n\r"); + mesh_initial_state = FALSE; + return; + } +#if F_BT_DEINIT + else { + bte_deinit(); + printf("[BT Mesh Provisioner] BT Stack deinitalized\n\r"); + } +#endif + mesh_deinit(); + bt_trace_uninit(); + + mesh_initial_state = FALSE; +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.c new file mode 100644 index 00000000..e1a9f617 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.c @@ -0,0 +1,236 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif + +#include "mesh_api.h" +#include "provisioner_app.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "provisioner_cmd.h" +#include "platform_opts.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif + +/*============================================================================* + * Macros + *============================================================================*/ +#define EVENT_MESH 0x80 +#define APP_TASK_PRIORITY 4 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x40 //!< IO message queue size +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#else +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#endif + +#if defined(CONFIG_PLATFORM_8721D) +#define UART_TX _PA_18 +#define UART_RX _PA_19 +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +#define UART_TX PA_14 +#define UART_RX PA_13 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_mesh_provisioner_app_task_handle; //!< APP Task handle +void *bt_mesh_provisioner_evt_queue_handle; //!< Event queue handle +void *bt_mesh_provisioner_io_queue_handle; //!< IO queue handle +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +void *bt_mesh_provisioner_user_cmd_io_queue_handle; //!< user cmd queue handle +#endif + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_mesh_provisioner_app_main_task(void *p_param); + +void app_send_uart_msg(uint8_t data) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = IO_MSG_TYPE_UART; + msg.subtype = data; + if (os_msg_send(bt_mesh_provisioner_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_evt_queue_handle, &event, 0) == false) + { + } +} + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern CMD_MOD_INFO_S btMeshCmdPriv; +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg) +{ + uint8_t event = EVENT_USER_API_REQ; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)p_io_msg->u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + //trace commands transmitted to mesh stack + btMeshCmdPriv.cmdTransmittedNum ++; + if (os_msg_send(bt_mesh_provisioner_user_cmd_io_queue_handle, p_io_msg, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_provisioner_user_cmd_io_queue_handle fail!\r\n"); + return 1; + } + else if (os_msg_send(bt_mesh_provisioner_evt_queue_handle, &event, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_provisioner_evt_queue_handle fail!\r\n"); + return 1; + } + + return 0; +} +#endif + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_provisioner_app_task_init() +{ + os_task_create(&bt_mesh_provisioner_app_task_handle, "bt_mesh_provisioner_app", bt_mesh_provisioner_app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_mesh_provisioner_app_main_task(void *p_param) +{ + /* avoid gcc compile warning */ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_mesh_provisioner_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_mesh_provisioner_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + os_msg_queue_create(&bt_mesh_provisioner_user_cmd_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); +#endif + gap_start_bt_stack(bt_mesh_provisioner_evt_queue_handle, bt_mesh_provisioner_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + mesh_start(EVENT_MESH, EVENT_IO_TO_APP, bt_mesh_provisioner_evt_queue_handle, bt_mesh_provisioner_io_queue_handle); + + mesh_data_uart_init(UART_TX, UART_RX, app_send_uart_msg); + mesh_user_cmd_init("MeshProvisioner"); + + while (true) + { + if (os_msg_recv(bt_mesh_provisioner_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_provisioner_app_handle_io_msg(io_msg); + } + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + else if (event == EVENT_USER_API_REQ) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_user_cmd_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_io_msg_handler(io_msg); + } + } +#endif +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + else if (event == EVENT_USER_HTTP_SERVER) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_demo_io_msg_handler(io_msg); + } + } +#endif + else if (event == EVENT_MESH) + { + mesh_inner_msg_handle(event); + } + else + { + gap_handle_msg(event); + } + + } + } +} + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_provisioner_app_task_deinit(void) +{ + if (bt_mesh_provisioner_app_task_handle) { + os_task_delete(bt_mesh_provisioner_app_task_handle); + } + if (bt_mesh_provisioner_io_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_io_queue_handle); + } + if (bt_mesh_provisioner_evt_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_evt_queue_handle); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_provisioner_user_cmd_io_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_user_cmd_io_queue_handle); + } + bt_mesh_provisioner_user_cmd_io_queue_handle = NULL; +#endif + bt_mesh_provisioner_io_queue_handle = NULL; + bt_mesh_provisioner_evt_queue_handle = NULL; + bt_mesh_provisioner_app_task_handle = NULL; + mesh_user_cmd_deinit("MeshProvisioner"); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.h new file mode 100644 index 00000000..a2c12d55 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.h @@ -0,0 +1,25 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_PROVISIONER_APP_TASK_H_ +#define _BT_MESH_PROVISIONER_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_provisioner_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_provisioner_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.c new file mode 100644 index 00000000..a2f25e90 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.c @@ -0,0 +1,1200 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.c +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +#include "provisioner_app.h" +#include "trace_app.h" +#include "gap_wrapper.h" +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_cmd.h" +#include "ping_app.h" +#include "provisioner_cmd.h" +#include "provision_provisioner.h" +#include "provision_client.h" +#include "proxy_client.h" +#include "bt_flags.h" +#include "bt_mesh_provisioner_app_flags.h" +#include "platform_opts.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_distributor_app.h" +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#include "bt_mesh_provisioner_api.h" +#endif + +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO +#include "bt_mesh_app_lib_intf.h" +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; +#endif + +bool prov_manual; +uint32_t prov_start_time; +prov_auth_value_type_t prov_auth_value_type; + +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; + +T_GAP_DEV_STATE bt_mesh_provisioner_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_APP_LINK app_link_table[APP_MAX_LINKS]; + +void bt_mesh_provisioner_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +#if defined(MESH_DFU) && MESH_DFU +extern void dfu_dist_handle_timeout(void); +#endif +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_provisioner_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + bt_mesh_provisioner_app_handle_gap_msg(&io_msg); + break; + case IO_MSG_TYPE_UART: + { + /* We handle user command informations from Data UART in this branch. */ + uint8_t data = io_msg.subtype; + mesh_user_cmd_collect(&data, sizeof(data), provisioner_cmd_table); + } + break; + case PING_TIMEOUT_MSG: + ping_handle_timeout(); + break; + case PING_APP_TIMEOUT_MSG: + ping_app_handle_timeout(); + break; +#if defined(MESH_DFU) && MESH_DFU + case DFU_DIST_APP_TIMEOUT_MSG: + dfu_dist_handle_timeout(); + break; +#endif + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_mesh_provisioner_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_mesh_provisioner_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_mesh_provisioner_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + uint8_t net_key[16] = MESH_NET_KEY; + uint8_t net_key1[16] = MESH_NET_KEY1; + uint8_t app_key[16] = MESH_APP_KEY; + uint8_t app_key1[16] = MESH_APP_KEY1; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /** configure provisioner */ + mesh_node.node_state = PROV_NODE; + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + memcpy(&net_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&net_key1[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key1[10], bt_addr, sizeof(bt_addr)); + uint16_t net_key_index = net_key_add(0, net_key); + app_key_add(net_key_index, 0, app_key); + uint8_t net_key_index1 = net_key_add(1, net_key1); + app_key_add(net_key_index1, 1, app_key1); + mesh_model_bind_all_key(); + } + } + if (bt_mesh_provisioner_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + //data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + //data_uart_print("GAP scan start\r\n"); + } + } + + bt_mesh_provisioner_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_mesh_provisioner_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("bt_mesh_provisioner_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, app_link_table[conn_id].conn_state, new_state, disc_cause); + + app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_mesh_provisioner_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + data_uart_debug("Disconnect conn_id %d\r\n", conn_id); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } + } else { + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_disconnect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_disconnect)); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } + } else { + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + break; + } +#endif + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, app_link_table[conn_id].bd_addr, + &app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(app_link_table[conn_id].bd_addr), app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_debug("Connected success conn_id %d\r\n", conn_id); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + } +#endif +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, 251, 2120); +#endif + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_mesh_provisioner_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_mesh_provisioner_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_mesh_provisioner_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_debug("Pair success\r\n"); + APP_PRINT_INFO0("bt_mesh_provisioner_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_debug("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_mesh_provisioner_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_mesh_provisioner_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_mesh_provisioner_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_mesh_provisioner_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_mesh_provisioner_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_mesh_provisioner_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_mesh_provisioner_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_mesh_provisioner_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + } + break; + + default: + break; + } +} + +bool mesh_initial_state = FALSE; + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * sub_type of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_mesh_provisioner_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_mesh_provisioner_app_handle_gap_msg: sub_type %d", p_gap_msg->subtype); + mesh_inner_msg_t mesh_inner_msg; + mesh_inner_msg.type = MESH_BT_STATUS_UPDATE; + mesh_inner_msg.sub_type = p_gap_msg->subtype; + mesh_inner_msg.parm = p_gap_msg->u.param; + gap_sched_handle_bt_status_msg(&mesh_inner_msg); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + //static bool start = FALSE; + if (!mesh_initial_state) + { + mesh_initial_state = TRUE; + /** set device uuid according to bt address */ + uint8_t bt_addr[6]; + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + memcpy(dev_uuid, bt_addr, sizeof(bt_addr)); + device_uuid_set(dev_uuid); + /** configure provisioner */ + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + } + bt_mesh_provisioner_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_mesh_provisioner_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_mesh_provisioner_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_mesh_provisioner_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_mesh_provisioner_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_debug("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_app_handle_gap_msg: unknown sub_type %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + gap_sched_handle_adv_report(p_data->p_le_scan_info); + break; + +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + gap_sched_adv_params_set_done(); + break; + /* + case GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: cause 0x%x", + p_data->le_cause.cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + break; + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; + + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; + */ +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_provisioner_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + else if (client_id == prov_client_id) + { + prov_client_cb_data_t *pcb_data = (prov_client_cb_data_t *)p_data; + switch (pcb_data->cb_type) + { + case PROV_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case PROV_DISC_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + data_uart_debug("Prov service discovery end!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + case PROV_DISC_FAIL: + /* Discovery Request failed. */ + data_uart_debug("Prov service discovery fail!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + case PROV_DISC_NOT_FOUND: + /* Discovery Request failed. */ + data_uart_debug("Prov service not found!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + default: + break; + } + break; + case PROV_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case PROV_READ_DATA_OUT_CCCD: + if (pcb_data->cb_content.read_result.cause == 0) + { + data_uart_debug("Prov data out cccd = %d.\r\n", + pcb_data->cb_content.read_result.data.prov_data_out_cccd); + } + break; + default: + break; + } + break; + case PROV_CLIENT_CB_TYPE_WRITE_RESULT: + break; + default: + break; + } + } + else if (client_id == proxy_client_id) + { + proxy_client_cb_data_t *pcb_data = (proxy_client_cb_data_t *)p_data; + switch (pcb_data->cb_type) + { + case PROXY_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case PROXY_DISC_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + data_uart_debug("Proxy service discovery end!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_proxy_discover), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_proxy_discover)); + } +#endif + break; + case PROXY_DISC_FAIL: + /* Discovery Request failed. */ + data_uart_debug("Proxy service discovery fail!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_proxy_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_proxy_discover)); + } +#endif + break; + case PROXY_DISC_NOT_FOUND: + /* Discovery Request failed. */ + data_uart_debug("Proxy service not found!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_proxy_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_proxy_discover)); + } +#endif + break; + default: + break; + } + break; + case PROXY_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case PROXY_READ_DATA_OUT_CCCD: + if (pcb_data->cb_content.read_result.cause == 0) + { + data_uart_debug("Proxy data out cccd = %d.\r\n", + pcb_data->cb_content.read_result.data.proxy_data_out_cccd); + } + break; + default: + break; + } + break; + case PROXY_CLIENT_CB_TYPE_WRITE_RESULT: + break; + default: + break; + } + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_provisioner_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + return app_result; +} + +/****************************************************************** + * @fn device_info_cb + * @brief device_info_cb callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return void + */ +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + if (!dev_info_show_flag) + { + return; + } + data_uart_debug("bt addr=0x%02x%02x%02x%02x%02x%02x type=%d rssi=%d ", bt_addr[5], bt_addr[4], + bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0], bt_addr_type, rssi); + switch (pinfo->type) + { + case DEVICE_INFO_UDB: + data_uart_debug("udb="); + data_uart_dump(pinfo->pbeacon_udb->dev_uuid, 16); + break; + case DEVICE_INFO_PROV_ADV: + data_uart_debug("prov="); + data_uart_dump(pinfo->pservice_data->provision.dev_uuid, 16); + break; + case DEVICE_INFO_PROXY_ADV: + data_uart_debug("proxy="); + data_uart_dump((uint8_t *)&pinfo->pservice_data->proxy, pinfo->len); + break; + default: + break; + } +} + +/****************************************************************** + * @fn prov_cb + * @brief Provisioning callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return the operation result + */ +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data) +{ + APP_PRINT_INFO1("prov_cb: type = %d", cb_type); + + switch (cb_type) + { + case PROV_CB_TYPE_PB_ADV_LINK_STATE: + switch (cb_data.pb_generic_cb_type) + { + case PB_GENERIC_CB_LINK_OPENED: + data_uart_debug("PB-ADV Link Opened!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_flag = 1; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_pb_adv_con), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_pb_adv_con)); + } +#endif + break; + case PB_GENERIC_CB_LINK_OPEN_FAILED: + data_uart_debug("PB-ADV Link Open Failed!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_flag = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_pb_adv_con), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_pb_adv_con)); + } +#endif + break; + case PB_GENERIC_CB_LINK_CLOSED: + data_uart_debug("PB-ADV Link Closed!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); + break; + default: + break; + } + break; + case PROV_CB_TYPE_PATH_CHOOSE: + { + if (prov_manual) + { + /* use cmd "authpath" to select oob/no oob public key and no oob/static oob/input oob/output oob auth data according to the device capabilities */ + prov_capabilities_p pprov_capabilities = cb_data.pprov_capabilities; + data_uart_debug("prov capabilities: en-%d al-%d pk-%d so-%d os-%d oa-%d is-%d ia-%d\r\n", + pprov_capabilities->element_num, pprov_capabilities->algorithm, + pprov_capabilities->public_key, pprov_capabilities->static_oob, + pprov_capabilities->output_oob_size, pprov_capabilities->output_oob_action, + pprov_capabilities->input_oob_size, pprov_capabilities->input_oob_action); + } + else + { + /* select no oob public key and no oob auth data as default provision method */ + prov_start_t prov_start; + memset(&prov_start, 0, sizeof(prov_start_t)); + prov_path_choose(&prov_start); + } + } + break; + case PROV_CB_TYPE_PUBLIC_KEY: + { + APP_PRINT_INFO0("prov_cb: get the public key from the device"); + uint8_t public_key[64] = {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79}; + prov_device_public_key_set(public_key); + } + break; + case PROV_CB_TYPE_AUTH_DATA: + { + prov_start_p pprov_start = cb_data.pprov_start; + prov_auth_value_type = prov_auth_value_type_get(pprov_start); + /* use cmd to set auth data */ + data_uart_debug("auth method=%d[nsoi] action=%d size=%d type=%d[nbNa]\r\n>", + pprov_start->auth_method, + pprov_start->auth_action, pprov_start->auth_size, prov_auth_value_type); + //uint8_t auth_data[16] = {1}; + switch (pprov_start->auth_method) + { + case PROV_AUTH_METHOD_STATIC_OOB: + //prov_auth_value_set(auth_data, sizeof(auth_data)); + APP_PRINT_INFO0("prov_cb: Please share the oob data with the device"); + break; + case PROV_AUTH_METHOD_OUTPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.output_oob_size); + APP_PRINT_INFO2("prov_cb: Please input the oob data provided by the device, output size = %d, action = %d", + pprov_start->auth_size.output_oob_size, pprov_start->auth_action.output_oob_action); + break; + case PROV_AUTH_METHOD_INPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.input_oob_size); + APP_PRINT_INFO2("prov_cb: Please output the oob data to the device, input size = %d, action = %d", + pprov_start->auth_size.input_oob_size, pprov_start->auth_action.input_oob_action); + break; + default: + break; + } + } + break; + case PROV_CB_TYPE_CONF_CHECK: + { + /* check confirmation value when using OOB */ + uint8_t rand[16] = {0}; + uint8_t confirmation[16] = {0}; + prov_check_conf_t prov_check_conf = cb_data.prov_check_conf; + + memcpy((void *)rand, (void *)prov_check_conf.rand, sizeof(rand)); + memcpy((void *)confirmation, (void *)prov_check_conf.conf, sizeof(confirmation)); + printf("confimation %02x %02x %02x %02x %02x %02x \r\n", confirmation[0], confirmation[1], confirmation[2], confirmation[3], confirmation[4], confirmation[5]); + printf("rand %02x %02x %02x %02x %02x %02x \r\n", rand[0], rand[1], rand[2], rand[3], rand[4], rand[5]); + + /* if confirmation from device is correct invoke prov_send_prov_data() */ + /* if confirmation from device is wrong invoke prov_reject() */ + // if (success) { + // prov_send_prov_data(); + // } else { + // prov_reject(); + // } + } + break; + case PROV_CB_TYPE_COMPLETE: + { + prov_data_p pprov_data = cb_data.pprov_data; + data_uart_debug("Has provisioned device with addr 0x%04x in %dms!\r\n", pprov_data->unicast_address, + plt_time_read_ms() - prov_start_time); + /* the spec requires to disconnect, but you can remove it as you like! :) */ + prov_disconnect(PB_ADV_LINK_CLOSE_SUCCESS); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_mesh_addr = pprov_data->unicast_address; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + printf("\r\n %s() pprov_data->unicast_address = %x",__func__,pprov_data->unicast_address); + if (bt_mesh_indication(GEN_MESH_CODE(_prov), BT_MESH_USER_CMD_SUCCESS, (void *)&pprov_data->unicast_address) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov)); + } +#endif + } + break; + case PROV_CB_TYPE_FAIL: + data_uart_debug("provision fail, type=%d!\r\n", cb_data.prov_fail.fail_type); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_mesh_addr = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov)); + } +#endif + + break; + case PROV_CB_TYPE_PROV: + /* stack ready */ + data_uart_debug("ms addr: 0x%04x\r\n>", mesh_node.unicast_addr); + break; + default: + break; + } + return true; +} + +/****************************************************************** + * @fn fn_cb + * @brief fn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + + char *string[] = {"establishing with lpn 0x%04x\r\n", "no poll from 0x%04x\r\n", "established with lpn 0x%04x\r\n", "lpn 0x%04x lost\r\n"}; + data_uart_debug(string[type], lpn_addr); + if (type == FN_CB_TYPE_ESTABLISH_SUCCESS || type == FN_CB_TYPE_FRND_LOST) + { + user_cmd_time(NULL); + } +} + +/****************************************************************** + * @fn hb_cb + * @brief heartbeat callbacks are handled in this function. + * + * @param type + * @param pdata + * @return void + */ +void hb_cb(hb_data_type_t type, void *pargs) +{ + switch (type) + { + case HB_DATA_PUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat publish timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat publish timer stop\r\n"); + } + } + break; + case HB_DATA_SUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat subscription timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat subscription timer stop\r\n"); + } + } + break; + case HB_DATA_PUB_COUNT_UPDATE: + { + hb_data_pub_count_update_t *pdata = pargs; + data_uart_debug("heartbeat publish count update: %d\r\n", pdata->count); + } + break; + case HB_DATA_SUB_PERIOD_UPDATE: + { + hb_data_sub_period_update_t *pdata = pargs; + data_uart_debug("heartbeat subscription period update: %d\r\n", pdata->period); + } + break; + case HB_DATA_SUB_RECEIVE: + { + hb_data_sub_receive_t *pdata = pargs; + data_uart_debug("receive heartbeat: src = %d, init_ttl = %d, features = %d-%d-%d-%d, ttl = %d\r\n", + pdata->src, pdata->init_ttl, pdata->features.relay, pdata->features.proxy, + pdata->features.frnd, pdata->features.lpn, pdata->ttl); + } + break; + default: + break; + } +} + +void bt_mesh_provisioner_app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("bt_mesh_provisioner_app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_INFO1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.h new file mode 100644 index 00000000..40b38d88 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.h @@ -0,0 +1,74 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.h +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _MESH_APPLICATION__ +#define _MESH_APPLICATION__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mesh_api.h" +#include +#include +#include "app_msg.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_provisioner_api.h" +#endif + +extern bool dev_info_show_flag; +extern bool prov_manual; +extern uint32_t prov_start_time; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_provisioner_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +T_APP_RESULT bt_mesh_provisioner_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo); +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +void hb_cb(hb_data_type_t type, void *pargs); +void bt_mesh_provisioner_app_vendor_callback(uint8_t cb_type, void *p_cb_data); +#ifdef __cplusplus +} +#endif + +#endif /* _MESH_APPLICATION__S */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.c new file mode 100644 index 00000000..24f3916e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.c @@ -0,0 +1,811 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provisioner_cmd.c + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ + +#include +#include "provisioner_app.h" +#include "trace.h" +#include "gap_wrapper.h" +#include "provisioner_cmd.h" +#include "provision_client.h" +#include "provision_provisioner.h" +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "test_cmd.h" +#include "client_cmd.h" +#include "generic_client_app.h" +#include "datatrans_model.h" +#include "datatrans_app.h" +#include "remote_provisioning.h" + + +static user_cmd_parse_result_t user_cmd_prov_discover(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Prov Start Discover\r\n"); + prov_client_conn_id = pparse_value->dw_parameter[0]; + prov_client_start_discovery(prov_client_conn_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_read_char(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char to be read. */ + prov_read_type_t read_char_type = (prov_read_type_t)pparse_value->dw_parameter[0]; + /* Read by handle or UUID, 1--by UUID, 0--by handle. */ + uint8_t read_pattern = (uint8_t)pparse_value->dw_parameter[1]; + data_uart_debug("Pro Read Char\r\n"); + if (read_pattern) + { + prov_client_read_by_uuid(prov_client_conn_id, read_char_type); + } + else + { + prov_client_read_by_handle(prov_client_conn_id, read_char_type); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_cccd_operate(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char CCCD command. */ + uint8_t cmd_type = (uint8_t)pparse_value->dw_parameter[0]; + /* Enable or disable, 1--enable, 0--disable. */ + bool cmd_data = (bool)pparse_value->dw_parameter[1]; + data_uart_debug("Prov Cccd Operate\r\n"); + switch (cmd_type) + { + case 0:/* V3 Notify char notif enable/disable. */ + { + prov_client_data_out_cccd_set(prov_client_conn_id, cmd_data); + proxy_ctx_set_link(prov_proxy_ctx_id, prov_client_conn_id); + } + break; + default: + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_list(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Prov Server Handle List:\r\nidx\thandle\r\n"); + for (prov_handle_type_t hdl_idx = HDL_PROV_SRV_START; hdl_idx < HDL_PROV_CACHE_LEN; hdl_idx++) + { + data_uart_debug("%d\t0x%x\r\n", hdl_idx, prov_client_handle_get(prov_client_conn_id, hdl_idx)); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_pb_adv_con(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + + send_coex_mailbox_to_wifi_from_BtAPP(1); + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[0], sizeof(dev_uuid)); + if (!pb_adv_link_open(0, dev_uuid)) + { + data_uart_debug("PB_ADV: Link Busy!\r\n"); + + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_pb_adv_disc(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + if (pb_adv_link_close(0, PB_ADV_LINK_CLOSE_SUCCESS)) + { + data_uart_debug("PB_ADV: Link Closed!\r\n"); + } + else + { + data_uart_debug("PB_ADV: Link Closed Already!\r\n"); + } + return USER_CMD_RESULT_OK; +} + +#if defined(MESH_RPR) && MESH_RPR +static user_cmd_parse_result_t user_cmd_rmt_prov_client_scan_start(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t scanned_items_limit = pparse_value->dw_parameter[2]; + uint8_t scan_timeout = pparse_value->dw_parameter[3]; + uint8_t ret = 0; + + if (pparse_value->para_count == 5) { + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[4], sizeof(dev_uuid)); + ret = rmt_prov_client_scan_start(dst, net_key_index, scanned_items_limit, scan_timeout, dev_uuid); + } else if (pparse_value->para_count == 4) { + ret = rmt_prov_client_scan_start(dst, net_key_index, scanned_items_limit, scan_timeout, NULL); + } else { + data_uart_debug("invalid param\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + if (ret == MESH_MSG_SEND_CAUSE_SUCCESS) { + return USER_CMD_RESULT_OK; + } else { + data_uart_debug("fail\r\n"); + return USER_CMD_RESULT_ERROR; + } +} + +static user_cmd_parse_result_t user_cmd_rmt_prov_client_link_open_prov(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t link_open_timeout = pparse_value->dw_parameter[3]; + + if (pparse_value->para_count == 4) { + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[2], sizeof(dev_uuid)); + } else { + data_uart_debug("invalid uuid\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return rmt_prov_client_link_open_prov(dst, net_key_index, dev_uuid, link_open_timeout) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_rmt_prov_client_close(user_cmd_parse_value_t *pparse_value) +{ + rmt_prov_link_close_reason_t reason; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + + if (pparse_value->para_count == 3) { + reason = (rmt_prov_link_close_reason_t)pparse_value->dw_parameter[2]; + } else { + data_uart_debug("invalid reason\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + + return rmt_prov_client_link_close(dst, net_key_index, reason) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} +#endif + +static user_cmd_parse_result_t user_cmd_prov(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("provision...\r\n"); + uint32_t attn_dur = pparse_value->dw_parameter[0]; + prov_manual = pparse_value->dw_parameter[1]; + prov_start_time = plt_time_read_ms(); + return prov_invite(attn_dur) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_prov_stop(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + return prov_reject() ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_prov_auth_path(user_cmd_parse_value_t *pparse_value) +{ + prov_start_algorithm_t algo = (prov_start_algorithm_t)pparse_value->dw_parameter[0]; + prov_start_public_key_t public_key = (prov_start_public_key_t)pparse_value->dw_parameter[1]; + prov_auth_method_t auth_method = (prov_auth_method_t)pparse_value->dw_parameter[2]; + uint8_t oob_action = pparse_value->dw_parameter[3]; + uint8_t oob_size = pparse_value->dw_parameter[4]; + + prov_start_t prov_start; + prov_start.algorithm = algo; + prov_start.public_key = public_key; + prov_start.auth_method = auth_method; + prov_start.auth_action.oob_action = oob_action; + prov_start.auth_size.oob_size = oob_size; + return prov_path_choose(&prov_start) == true ? USER_CMD_RESULT_OK : USER_CMD_RESULT_WRONG_PARAMETER; +} + +static user_cmd_parse_result_t user_cmd_unprov(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Unprovision...\r\n"); +#if MESH_UNPROVISIONING_SUPPORT + prov_unprovisioning(); +#endif + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_cfg_client_key_set(user_cmd_parse_value_t + *pparse_value) +{ + uint8_t key_index = pparse_value->dw_parameter[0]; + bool use_app_key = pparse_value->dw_parameter[1] ? TRUE : FALSE; + mesh_node.features.cfg_model_use_app_key = use_app_key; + return cfg_client_key_set(key_index) ? USER_CMD_RESULT_OK : + USER_CMD_RESULT_VALUE_OUT_OF_RANGE; +} + +static user_cmd_parse_result_t user_cmd_compo_data_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t page = pparse_value->dw_parameter[1]; + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + data_uart_debug("CDP0 len=%d, data=", mesh_node.compo_data_size[0]); + data_uart_dump(mesh_node.compo_data[0], mesh_node.compo_data_size[0]); + } + else + { + cfg_compo_data_get(dst, page); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_node_reset(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + bool clear = pparse_value->dw_parameter[1]; + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + mesh_node_reset(); + } + else + { + cfg_node_reset(dst); + if (clear) + { + int dev_key_index = dev_key_find(dst); + if (dev_key_index >= 0) + { + dev_key_delete(dev_key_index); + mesh_flash_store(MESH_FLASH_PARAMS_DEV_KEY, &dev_key_index); + } + } + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_net_key_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + cfg_net_key_add(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_new_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_net_key_update(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t net_key[MESH_COMMON_KEY_SIZE]; + plt_hex_to_bin(net_key, (uint8_t *)pparse_value->pparameter[2], MESH_COMMON_KEY_SIZE); + return net_key_update(net_key_index, mesh_node.net_key_list[net_key_index].net_key_index_g, + net_key) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; + } + else + { + cfg_net_key_update(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_new_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key); + return USER_CMD_RESULT_OK; + } +} + +static user_cmd_parse_result_t user_cmd_app_key_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + data_uart_debug("\r\n %s() dst = %x",__func__,dst); + cfg_app_key_add(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.app_key_list[app_key_index].app_key_index_g, + mesh_node.app_key_list[app_key_index].papp_key[key_state_to_new_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_app_key_update(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t app_key[MESH_COMMON_KEY_SIZE]; + plt_hex_to_bin(app_key, (uint8_t *)pparse_value->pparameter[3], MESH_COMMON_KEY_SIZE); + return app_key_update(app_key_index, net_key_index, + mesh_node.app_key_list[app_key_index].app_key_index_g, + app_key) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; + } + else + { + cfg_app_key_update(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.app_key_list[app_key_index].app_key_index_g, + mesh_node.app_key_list[app_key_index].papp_key[key_state_to_new_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key); + return USER_CMD_RESULT_OK; + } +} + +static user_cmd_parse_result_t user_cmd_model_app_bind(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t app_key_index = pparse_value->dw_parameter[3]; + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + cfg_model_app_bind(dst, dst + element_index, mesh_node.app_key_list[app_key_index].app_key_index_g, + model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_pub_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 11) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + pub_key_info_t pub_key_info = {pparse_value->dw_parameter[4], pparse_value->dw_parameter[5], 0}; + pub_period_t pub_period = {pparse_value->dw_parameter[7] & 0x3f, pparse_value->dw_parameter[7] >> 6}; + pub_retrans_info_t pub_retrans_info = {pparse_value->dw_parameter[8], pparse_value->dw_parameter[9]}; + uint8_t addr[16]; + if (0 == pparse_value->dw_parameter[2]) + { + uint16_t element_addr = (uint16_t)(pparse_value->dw_parameter[3]); + LE_WORD2EXTRN(addr, element_addr); + } + else + { + plt_hex_to_bin(addr, (uint8_t *)pparse_value->pparameter[3], 16); + } + cfg_model_pub_set(dst, pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + addr, pub_key_info, pparse_value->dw_parameter[6], pub_period, + pub_retrans_info, pparse_value->dw_parameter[10]); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t group_addr = pparse_value->dw_parameter[3]; + if (MESH_NOT_GROUP_ADDR(group_addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + cfg_model_sub_add(dst, dst + element_index, false, (uint8_t *)&group_addr, model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_get(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + cfg_model_sub_get(dst, dst + element_index, model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_delete(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t group_addr = pparse_value->dw_parameter[3]; + if (pparse_value->para_count == 4) + { + if (MESH_NOT_GROUP_ADDR(group_addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + cfg_model_sub_delete(dst, dst + element_index, false, (uint8_t *)&group_addr, model_id); + } + else if (pparse_value->para_count == 3) + { + cfg_model_sub_delete_all(dst, dst + element_index, model_id); + } + else + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_key_refresh_phase_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + cfg_key_refresh_phase_get(dst, net_key_index_to_global(net_key_index)); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_key_refresh_phase_set(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t phase = pparse_value->dw_parameter[2]; + cfg_key_refresh_phase_set(dst, net_key_index_to_global(net_key_index), phase); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_write(user_cmd_parse_value_t *pparse_value) +{ + uint8_t para_count = pparse_value->para_count; + uint8_t data[18]; + + for (uint8_t i = 0; i < para_count - 3; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + datatrans_write(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[para_count - 2], para_count - 3, data, + pparse_value->dw_parameter[para_count - 1]); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_read(user_cmd_parse_value_t *pparse_value) +{ + datatrans_read(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const user_cmd_table_entry_t provisioner_cmd_table[] = +{ + // mesh common cmd + MESH_COMMON_CMD, + CLIENT_CMD, + TEST_CMD, + // provisioner cmd + // pb-adv + { + "pbadvcon", + "pbadvcon [dev uuid]\n\r", + "create a pb-adv link with the device uuid\n\r", + user_cmd_pb_adv_con + }, + { + "pbadvdisc", + "pbadvdisc\n\r", + "disconnect the pb-adv link\n\r", + user_cmd_pb_adv_disc + }, + // pb-gatt + { + "provdis", + "provdis [conn id]\n\r", + "Start discovery provisioning service\n\r", + user_cmd_prov_discover + }, + { + "provread", + "provread [char] [pattern: handle/UUID16]\n\r", + "Read all related chars by user input\n\r", + user_cmd_prov_read_char + }, + { + "provcmd", + "provcmd [char CCCD] [command: enable/disable]\n\r", + "Provisioning notify/ind switch command\n\r", + user_cmd_prov_cccd_operate + }, + { + "provls", + "provls\n\r", + "Provision server handle list\n\r", + user_cmd_prov_list + }, + // provisioner + { + "prov", + "prov [attn_dur] [manual]\n\r", + "provision a new mesh device\n\r", + user_cmd_prov + }, + { + "provs", + "provs\n\r", + "provision stop\n\r", + user_cmd_prov_stop + }, + { + "pap", + "pap [algorithm] [pubkey] [method: nsoi] [action] [size]\n\r", + "provision authentication path\n\r", + user_cmd_prov_auth_path + }, + { + "unprov", + "unprov\n\r", + "unprovision the mesh device\n\r", + user_cmd_unprov + }, + // cfg client key set + { + "ccks", + "ccks [key_index] [use_app_key]\n\r", + "cfg client key set\n\r", + user_cmd_cfg_client_key_set + }, + // cfg client or local setting + { + "cdg", + "cdg [dst]\n\r", + "compo data get\n\r", + user_cmd_compo_data_get + }, + { + "nr", + "nr [dst] [clear]\n\r", + "node reset\n\r", + user_cmd_node_reset + }, + { + "nka", + "nka [dst] [net_key_index]\n\r", + "net key add\n\r", + user_cmd_net_key_add + }, + { + "nku", + "nku [dst] [net_key_index] [net key]\n\r", + "net key update\n\r", + user_cmd_net_key_update + }, + { + "aka", + "aka [dst] [net_key_index] [app_key_index]\n\r", + "app key add\n\r", + user_cmd_app_key_add + }, + { + "aku", + "aku [dst] [net_key_index] [app_key_index] [app key]\n\r", + "app key update\n\r", + user_cmd_app_key_update + }, + { + "mab", + "mab [dst] [element index] [model_id] [app_key_index]\n\r", + "model app bind\n\r", + user_cmd_model_app_bind + }, + { + "msa", + "msa [dst] [element index] [model_id] [group addr]\n\r", + "model subsribe add\n\r", + user_cmd_model_sub_add + }, + { + "msd", + "msd [dst] [element index] [model_id] \n\r", + "model subsribe delete\n\r", + user_cmd_model_sub_delete + }, + { + "krpg", + "krpg [dst] [net key index]\n\r", + "key refresh phase get\n\r", + user_cmd_key_refresh_phase_get + }, + { + "krps", + "krps [dst] [net key index] [phase]\n\r", + "key refresh phase set\n\r", + user_cmd_key_refresh_phase_set + }, + { + "dtw", + "dtw [dst] [data...] [app_key_index] [ack] \n\r", + "data transmission write data\n\r", + user_cmd_datatrans_write + }, + { + "dtr", + "dtr [dst] [len] [app_key_index]\n\r", + "data transmission read data\n\r", + user_cmd_datatrans_read + }, +#if defined(MESH_RPR) && MESH_RPR + { + "rmtscan", + "rmtscan [dst] [net key index] [scanned items limit] [scan timeout] [dev uuid]\n\r", + "romte provision scan start\n\r", + user_cmd_rmt_prov_client_scan_start + }, + { + "rmtcon", + "rmtcon [dst] [net key index] [dev uuid] [link open timeout]\n\r", + "romte link open for provision\n\r", + user_cmd_rmt_prov_client_link_open_prov + }, + { + "rmtdisc", + "rmtdisc [dst] [net_key_index] [reason]\n\r", + "romte link close for provision\n\r", + user_cmd_rmt_prov_client_close + }, +#endif + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +const struct bt_mesh_api_hdl provisionercmds[] = +{ + GEN_MESH_HANDLER(_pb_adv_con) + GEN_MESH_HANDLER(_prov) + GEN_MESH_HANDLER(_prov_stop) + GEN_MESH_HANDLER(_app_key_add) + GEN_MESH_HANDLER(_model_app_bind) + GEN_MESH_HANDLER(_model_pub_set) + GEN_MESH_HANDLER(_generic_on_off_set) + GEN_MESH_HANDLER(_generic_on_off_get) + GEN_MESH_HANDLER(_node_reset) + GEN_MESH_HANDLER(_model_sub_delete) + GEN_MESH_HANDLER(_model_sub_add) + GEN_MESH_HANDLER(_model_sub_get) + GEN_MESH_HANDLER(_prov_discover) + GEN_MESH_HANDLER(_prov_cccd_operate) + GEN_MESH_HANDLER(_proxy_discover) + GEN_MESH_HANDLER(_proxy_cccd_operate) + GEN_MESH_HANDLER(_datatrans_write) + GEN_MESH_HANDLER(_datatrans_read) + GEN_MESH_HANDLER(_connect) + GEN_MESH_HANDLER(_disconnect) + GEN_MESH_HANDLER(_list) + GEN_MESH_HANDLER(_dev_info_show) + GEN_MESH_HANDLER(_fn_init) + GEN_MESH_HANDLER(_fn_deinit) + GEN_MESH_HANDLER(_light_lightness_get) + GEN_MESH_HANDLER(_light_lightness_set) + GEN_MESH_HANDLER(_light_lightness_linear_get) + GEN_MESH_HANDLER(_light_lightness_linear_set) + GEN_MESH_HANDLER(_light_lightness_last_get) + GEN_MESH_HANDLER(_light_lightness_default_get) + GEN_MESH_HANDLER(_light_lightness_default_set) + GEN_MESH_HANDLER(_light_lightness_range_get) + GEN_MESH_HANDLER(_light_lightness_range_set) + GEN_MESH_HANDLER(_light_ctl_get) + GEN_MESH_HANDLER(_light_ctl_set) + GEN_MESH_HANDLER(_light_ctl_temperature_get) + GEN_MESH_HANDLER(_light_ctl_temperature_set) + GEN_MESH_HANDLER(_light_ctl_temperature_range_get) + GEN_MESH_HANDLER(_light_ctl_temperature_range_set) + GEN_MESH_HANDLER(_light_ctl_default_get) + GEN_MESH_HANDLER(_light_ctl_default_set) + GEN_MESH_HANDLER(_light_hsl_get) + GEN_MESH_HANDLER(_light_hsl_set) + GEN_MESH_HANDLER(_light_hsl_target_get) + GEN_MESH_HANDLER(_light_hsl_hue_get) + GEN_MESH_HANDLER(_light_hsl_hue_set) + GEN_MESH_HANDLER(_light_hsl_saturation_get) + GEN_MESH_HANDLER(_light_hsl_saturation_set) + GEN_MESH_HANDLER(_light_hsl_default_get) + GEN_MESH_HANDLER(_light_hsl_default_set) + GEN_MESH_HANDLER(_light_hsl_range_get) + GEN_MESH_HANDLER(_light_hsl_range_set) + GEN_MESH_HANDLER(_light_xyl_get) + GEN_MESH_HANDLER(_light_xyl_set) + GEN_MESH_HANDLER(_light_xyl_target_get) + GEN_MESH_HANDLER(_light_xyl_default_get) + GEN_MESH_HANDLER(_light_xyl_default_set) + GEN_MESH_HANDLER(_light_xyl_range_get) + GEN_MESH_HANDLER(_light_xyl_range_set) + GEN_MESH_HANDLER(_time_set) + GEN_MESH_HANDLER(_time_get) + GEN_MESH_HANDLER(_time_zone_set) + GEN_MESH_HANDLER(_time_zone_get) + GEN_MESH_HANDLER(_time_tai_utc_delta_set) + GEN_MESH_HANDLER(_time_tai_utc_delta_get) + GEN_MESH_HANDLER(_time_role_set) + GEN_MESH_HANDLER(_time_role_get) + GEN_MESH_HANDLER(_scene_store) + GEN_MESH_HANDLER(_scene_recall) + GEN_MESH_HANDLER(_scene_get) + GEN_MESH_HANDLER(_scene_register_get) + GEN_MESH_HANDLER(_scene_delete) + GEN_MESH_HANDLER(_scheduler_get) + GEN_MESH_HANDLER(_scheduler_action_get) + GEN_MESH_HANDLER(_scheduler_action_set) +#if defined(MESH_RPR) && MESH_RPR + GEN_MESH_HANDLER(_rmt_prov_client_scan_start) + GEN_MESH_HANDLER(_rmt_prov_client_link_open_prov) + GEN_MESH_HANDLER(_rmt_prov_client_close) +#endif +#if defined(MESH_DFU) && MESH_DFU + GEN_MESH_HANDLER(_fw_update_info_get) + GEN_MESH_HANDLER(_fw_update_start) + GEN_MESH_HANDLER(_fw_update_cancel) +#endif +}; +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.h new file mode 100644 index 00000000..f08c0dbd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.h @@ -0,0 +1,36 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _PRO_CMD_H_ +#define _PRO_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_config.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_cmd_types.h" +#endif + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +extern const user_cmd_table_entry_t provisioner_cmd_table[]; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern const struct bt_mesh_api_hdl provisionercmds[]; +#endif +void light_cwrgb_process(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.c new file mode 100644 index 00000000..4b9220e8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.c @@ -0,0 +1,73 @@ +#include "platform_opts.h" +#include +#include +#include +#include "platform_os.h" +#include "os_task.h" +#if defined(CONFIG_PLATFORM_8721D) +#include +#endif +#include "bt_config_wifi.h" + +#include + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + +//media +extern void amebacam_broadcast_demo_thread(void); +//httpd +extern void httpd_demo_init_thread(void); +#if defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE +extern int bt_mesh_device_app_main(void); +#elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE +extern int bt_mesh_device_multiple_profile_app_main(void); +#endif +extern void bt_coex_init(void); +extern uint8_t bt_mesh_device_api_init(void); + +void bt_mesh_example_init_thread(void *param) +{ + /* avoid gcc compile warning */ + (void)param; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } +#if defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE + /*Init BT mesh device*/ + bt_mesh_device_app_main(); +#elif defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE + bt_mesh_device_multiple_profile_app_main(); +#endif + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + } while (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + if (bt_mesh_device_api_init()) { + printf("[BT Mesh Device] bt_mesh_device_api_init fail ! \n\r"); + } + + vTaskDelete(NULL); +} + +void example_bt_mesh(void) +{ + //init bt config/bt mesh + void *task = NULL; + + if (os_task_create(&task, ((const char*)"bt_mesh_example_demo_init_thread"), bt_mesh_example_init_thread, + NULL, 2048, 5) != true) { + printf("\n\r%s xTaskCreate(bt_mesh_example_demo_init_thread) failed", __FUNCTION__); + } +} + +#endif /* CONFIG_EXAMPLE_BT_MESH_DEMO */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.h new file mode 100644 index 00000000..e77501b0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.h @@ -0,0 +1,7 @@ +#ifndef _EXAMPLE_BT_MESH_H_ +#define _EXAMPLE_BT_MESH_H_ + +void example_bt_mesh(void); + +#endif /* _EXAMPLE_BT_MESH_DEMO_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_adapter_service.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_adapter_service.c new file mode 100644 index 00000000..7f8dc8b5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_adapter_service.c @@ -0,0 +1,347 @@ +/** +********************************************************************************************************* +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file simple_ble_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date +* @version +********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +#include +#include +#include "bt_mesh_device_matter_adapter_service.h" +#include +#include +#include "platform_stdlib.h" + +#define BT_MATTER_ADAPTER_SERVICE_CHAR_RX_INDEX 0x02 +#define BT_MATTER_ADAPTER_SERVICE_CHAR_TX_INDEX 0x04 +#define BT_MATTER_ADAPTER_SERVICE_CHAR_NOTIFY_CCCD_INDEX (BT_MATTER_ADAPTER_SERVICE_CHAR_TX_INDEX + 1) +#define BT_MATTER_ADAPTER_SERVICE_C3_INDEX 0x07 + +#define UUID_RX 0x11, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 +#define UUID_TX 0x12, 0x9D, 0x9F, 0x42, 0x9C, 0x4F, 0x9F, 0x95, 0x59, 0x45, 0x3D, 0x26, 0xF5, 0x2E, 0xEE, 0x18 +#define UUID_C3 0x04, 0x8F, 0x21, 0x83, 0x8A, 0x74, 0x7D, 0xB8, 0xF2, 0x45, 0x72, 0x87, 0x38, 0x02, 0x63, 0x64 + +T_SERVER_ID bt_matter_adapter_service_id; +/**< Value of bt config characteristic. */ +static uint8_t bt_matter_adapter_char_read_value[BT_MATTER_ADAPTER_READ_V1_MAX_LEN]; +static uint16_t bt_matter_adapter_char_read_len = 1; + +/**< Function pointer used to send event to application from ble config wifi profile. Initiated in bt_matter_adapter_service_add_service. */ +static P_FUN_SERVER_GENERAL_CB pfn_bt_matter_adapter_service_cb = NULL; + +/**< @brief profile/service definition. */ +/**should changed according BT team **/ +T_ATTRIB_APPL bt_matter_adapter_service_tbl[] = +{ +/* <>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(0xFFF6), /* service UUID */ + HI_WORD(0xFFF6) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + +/* <> Data RX */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL | ATTRIB_FLAG_UUID_128BIT, /* flags */ + { /* type_value */ + UUID_RX + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + +/* <> Data TX */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ | GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL | ATTRIB_FLAG_UUID_128BIT, /* flags */ + { /* type_value */ + UUID_TX + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ //GATT_PERM_NONE // permissions + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + +/* <> C3 Data TX */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL | ATTRIB_FLAG_UUID_128BIT, /* flags */ + { /* type_value */ + UUID_C3 + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ //GATT_PERM_NONE // permissions + }, +}; + + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool bt_matter_adapter_service_set_parameter(T_BTMATTER_PARAM_TYPE param_type, uint16_t len, void *p_value) +{ + bool ret = true; + + switch (param_type) { + case BTMATTER_SERVICE_PARAM_V1_READ_CHAR_VAL: + if (len <= BT_MATTER_ADAPTER_READ_V1_MAX_LEN) { + memcpy(bt_matter_adapter_char_read_value, p_value, len); + bt_matter_adapter_char_read_len = len; + } else { + ret = false; + } + break; + + default: + ret = false; + break; + } + + if (!ret) { + APP_PRINT_ERROR0("bt_matter_adapter_service_set_parameter failed"); + } + + return ret; +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param attrib_index Attribute index of getting characteristic data. + * @param offset Used for Blob Read. + * @param p_length length of getting characteristic data. + * @param pp_value data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT bt_matter_adapter_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + case BT_MATTER_ADAPTER_SERVICE_C3_INDEX: + { + T_MATTER_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = BTCONFIG_READ_V1; + callback_data.msg_data.read_offset = offset; + callback_data.conn_id = conn_id; + if (pfn_bt_matter_adapter_service_cb) + { + pfn_bt_matter_adapter_service_cb(service_id, (void *)&callback_data); + } + *pp_value = callback_data.msg_data.write.p_value; + *p_length = callback_data.msg_data.write.len; + } + break; + default: + printf("bt_matter_adapter_service_attr_read_cb, Attr not found, index %d", attrib_index); + cause = APP_RESULT_ATTR_NOT_FOUND; + break; + } + + return (cause); +} + +/** + * @brief write characteristic data from service. + * + * @param conn_id + * @param service_id ServiceID to be written. + * @param attrib_index Attribute index of characteristic. + * @param length length of value to be written. + * @param p_value value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT bt_matter_adapter_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + //printf("[BT_MATTER_ADAPTER] Write %d\n\r", length); + T_MATTER_CALLBACK_DATA callback_data; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("bt_matter_adapter_service_attr_write_cb write_type = 0x%x", write_type); + *p_write_ind_post_proc = NULL; + + if (BT_MATTER_ADAPTER_SERVICE_CHAR_RX_INDEX == attrib_index) { + /* Make sure written value size is valid. */ + if (p_value == NULL) { + cause = APP_RESULT_INVALID_VALUE_SIZE; + } else { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = BTCONFIG_WRITE_V1; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + //handle_bt_matter_adapter_app_data(p_value, length); + if (pfn_bt_matter_adapter_service_cb) { + pfn_bt_matter_adapter_service_cb(service_id, (void *)&callback_data); + } + } + } else { + APP_PRINT_ERROR2("bt_matter_adapter_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, length); + cause = APP_RESULT_ATTR_NOT_FOUND; + } + + return cause; +} + +/** + * @brief update CCCD bits from stack. + * + * @param conn_id connection id. + * @param service_id Service ID. + * @param index Attribute index of characteristic data. + * @param cccbits CCCD bits from stack. + * @return None +*/ +void bt_matter_adapter_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index, + uint16_t cccbits) +{ + T_MATTER_CALLBACK_DATA callback_data; + bool is_handled = false; + callback_data.conn_id = conn_id; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + //printf("simp_ble_service_cccd_update_cb: index = %d, cccbits 0x%x\r\n", index, cccbits); + switch (index) + { + case BT_MATTER_ADAPTER_SERVICE_CHAR_NOTIFY_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_data.notification_indification_index = MATTER_NOTIFY_INDICATE_V3_ENABLE; + } + else + { + // Disable Notification + callback_data.msg_data.notification_indification_index = MATTER_NOTIFY_INDICATE_V3_DISABLE; + } + is_handled = true; + } + break; + default: + break; + } + /* Notify Application. */ + if (pfn_bt_matter_adapter_service_cb && (is_handled == true)) + { + pfn_bt_matter_adapter_service_cb(service_id, (void *)&callback_data); + } +} + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS bt_matter_adapter_service_cbs = +{ + bt_matter_adapter_service_attr_read_cb, // Read callback function pointer + bt_matter_adapter_service_attr_write_cb, // Write callback function pointer + bt_matter_adapter_service_cccd_update_cb // CCCD update callback function pointer +}; + +/** + * @brief Add simple BLE service to the BLE stack database. + * + * @param[in] p_func Callback when service attribute was read, write or cccd update. + * @return Service id generated by the BLE stack: @ref T_SERVER_ID. + * @retval 0xFF Operation failure. + * @retval others Service id assigned by stack. + * + */ +T_SERVER_ID bt_matter_adapter_service_add_service(void *p_func) +{ + //dump_bytes(bt_matter_adapter_service_tbl, sizeof(bt_matter_adapter_service_tbl)); + if (false == server_add_service(&bt_matter_adapter_service_id, + (uint8_t *)bt_matter_adapter_service_tbl, + sizeof(bt_matter_adapter_service_tbl), + bt_matter_adapter_service_cbs)) + { + // DBG_8195A("bt_matter_adapter_service_add_service: fail\n\r"); + APP_PRINT_ERROR0("bt_matter_adapter_service_add_service: fail"); + bt_matter_adapter_service_id = 0xff; + return bt_matter_adapter_service_id; + } + + pfn_bt_matter_adapter_service_cb = (P_FUN_SERVER_GENERAL_CB)p_func; + return bt_matter_adapter_service_id; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_adapter_service.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_adapter_service.h new file mode 100644 index 00000000..3333df55 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_adapter_service.h @@ -0,0 +1,177 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_matter_adapter_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _BT_MESH_DEVICE_MATTER_ADAPTER_SERVICE_H_ +#define _BT_MESH_DEVICE_MATTER_ADAPTER_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include + + +/** @defgroup SIMP_Service Simple Ble Service + * @brief Simple BLE service + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Macros SIMP Service Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +typedef enum +{ + BTMATTER_SERVICE_PARAM_V1_READ_CHAR_VAL = 0x01, +} T_BTMATTER_PARAM_TYPE; + +/** @} */ + + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ +#define MATTER_NOTIFY_INDICATE_V3_ENABLE 1 +#define MATTER_NOTIFY_INDICATE_V3_DISABLE 2 +//#define SIMP_NOTIFY_INDICATE_V4_ENABLE 3 +//#define SIMP_NOTIFY_INDICATE_V4_DISABLE 4 + +/** @defgroup SIMP_Service_Read_Info SIMP Service Read Info + * @brief Parameter for reading characteristic value. + * @{ + */ +#define BTCONFIG_READ_V1 1 +/** @} */ + +/** @defgroup SIMP_Service_Write_Info SIMP Service Write Info + * @brief Parameter for writing characteristic value. + * @{ + */ +#define BTCONFIG_WRITE_V1 1 +/** @} */ + +#define BT_MATTER_ADAPTER_READ_V1_MAX_LEN 300 + +/** @} End of SIMP_Service_Upstream_Message */ + +/** @} End of SIMP_Service_Exported_Macros */ +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +typedef struct +{ + uint8_t opcode; //!< ref: @ref SIMP_Service_Write_Info + T_WRITE_TYPE write_type; + uint16_t len; + uint8_t *p_value; +} T_MATTER_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + T_MATTER_WRITE_MSG write; + uint16_t read_offset; +} T_MATTER_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct +{ + uint8_t conn_id; + T_SERVICE_CALLBACK_TYPE msg_type; + T_MATTER_UPSTREAM_MSG_DATA msg_data; +} T_MATTER_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +/* + +*/ +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief + * @{ + */ + +/** + * @brief Add simple BLE service to the BLE stack database. + * + * @param[in] p_func Callback when service attribute was read, write or cccd update. + * @return Service id generated by the BLE stack: @ref T_SERVER_ID. + * @retval 0xFF Operation failure. + * @retval others Service id assigned by stack. + * + */ +T_SERVER_ID bt_matter_adapter_service_add_service(void *p_func); + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool bt_matter_adapter_service_set_parameter(T_BTMATTER_PARAM_TYPE param_type, uint16_t len, void *p_value); + +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +//extern T_SERVER_ID bt_matter_adapter_service_id; + +#ifdef __cplusplus +} +#endif + +#endif /* _BT_MATTER_ADAPTER_WIFI_SERVICE_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app.c new file mode 100644 index 00000000..afd0862c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app.c @@ -0,0 +1,2043 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.c +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace_app.h" +#include "gap_wrapper.h" +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "device_cmd.h" +#include "mesh_cmd.h" +#include "ping_app.h" +#include "datatrans_server.h" +#include "bt_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#include "bt_mesh_device_matter_app.h" +#include "bt_mesh_device_matter_app_task.h" +#include +#include "bt_mesh_device_matter_app_main.h" +#include +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#include "bt_mesh_device_api.h" +#endif +#include "platform_stdlib.h" +#include +#include +#include "gatt_builtin_services.h" +#include "ble_central_at_cmd.h" +#include "ble_peripheral_at_cmd.h" +#include +#include +#include + +/*********************************************************************************************************/ +int bt_mesh_device_matter_scan_state = 0; +int bt_mesh_device_matter_peripheral_app_max_links = 0; +int bt_mesh_device_matter_central_app_max_links = 0; + +T_GAP_DEV_STATE bt_mesh_device_matter_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_APP_LINK bt_mesh_device_matter_app_link_table[BT_MESH_DEVICE_MATTER_APP_MAX_LINKS]; + +T_CLIENT_ID bt_mesh_device_matter_gcs_client_id; /**< General Common Services client client id*/ +T_SERVER_ID bt_mesh_device_matter_adapter_srv_id; /**< Matter service id */ + +prov_auth_value_type_t prov_auth_value_type; +static uint8_t datatrans_sample_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; +uint8_t lpn_disable_scan_flag = 0; +uint8_t mesh_device_conn_state = 0; +bool mesh_initial_state = FALSE; + +uint8_t bt_mesh_device_matter_config_adv_flag = 0; + +chip_blemgr_callback chip_blemgr_callback_func = NULL; +void *chip_blemgr_callback_data = NULL; + +extern uint8_t bt_mesh_device_matter_adv_data[31]; +extern uint8_t bt_mesh_device_matter_le_adv_start_enable; +extern void bt_mesh_device_matter_le_adv_start(void); +extern void bt_mesh_device_matter_le_adv_stop(void); + +/*************************************************************************************************************************/ +void chip_blemgr_set_callback_func(chip_blemgr_callback p, void *data) +{ + chip_blemgr_callback_func = p; + chip_blemgr_callback_data = data; +} + +int bt_mesh_device_matter_app_handle_upstream_msg(uint16_t subtype, void *pdata) +{ + int ret = 0; + + BT_MATTER_SERVER_SEND_DATA *param = (BT_MATTER_SERVER_SEND_DATA *)pdata; + if(param) + { + server_send_data(param->conn_id, param->service_id, param->attrib_index, param->p_data, param->data_len, param->type); + os_mem_free(param->p_data); + os_mem_free(param); + } + + return ret; +} + +void bt_mesh_device_matter_handle_callback_msg(T_IO_MSG callback_msg)//receive +{ + uint16_t msg_type = callback_msg.type; + + switch (msg_type) + { + case BT_MATTER_SEND_CB_MSG_DISCONNECTED: + case BT_MATTER_SEND_CB_MSG_CONNECTED: + { + if (chip_blemgr_callback_func) { + chip_blemgr_callback_func(chip_blemgr_callback_data, callback_msg.u.buf, 0, CB_GAP_MSG_CONN_EVENT); + } + os_mem_free(callback_msg.u.buf); + callback_msg.u.buf = NULL; + } + break; + case BT_MATTER_SEND_CB_MSG_ALL_GAP_MSG: + break; + case BT_MATTER_SEND_CB_MSG_SEND_DATA_COMPLETE: + { + uint8_t service_id = callback_msg.subtype; + if (chip_blemgr_callback_func) { + chip_blemgr_callback_func(chip_blemgr_callback_data, callback_msg.u.buf, service_id, CB_PROFILE_CALLBACK); + } + os_mem_free(callback_msg.u.buf); + callback_msg.u.buf = NULL; + } + break; + case BT_MATTER_SEND_CB_MSG_IND_NTF_DISABLE: + case BT_MATTER_SEND_CB_MSG_IND_NTF_ENABLE: + case BT_MATTER_SEND_CB_MSG_READ_WRITE_CHAR: + { + uint8_t service_id = callback_msg.subtype; + if (chip_blemgr_callback_func) { + chip_blemgr_callback_func(chip_blemgr_callback_data, callback_msg.u.buf, service_id, CB_PROFILE_CALLBACK); + } + T_MATTER_CALLBACK_DATA *pp_param = (T_MATTER_CALLBACK_DATA *)callback_msg.u.buf; + if (pp_param->msg_data.write.len !=0) + { + os_mem_free(pp_param->msg_data.write.p_value); + pp_param->msg_data.write.p_value = NULL; + } + os_mem_free(callback_msg.u.buf); + callback_msg.u.buf = NULL; + } + break; + default: + break; + } +} + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_device_matter_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_mesh_device_matter_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + { + /* We handle user command informations from Data UART in this branch. */ + uint8_t data = io_msg.subtype; + mesh_user_cmd_collect(&data, sizeof(data), device_cmd_table); + } + break; + case PING_TIMEOUT_MSG: + { + ping_handle_timeout(); + } + break; + case PING_APP_TIMEOUT_MSG: + { + ping_app_handle_timeout(); + } + break; + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; + if (ble_central_app_handle_at_cmd(subtype, arg) != 1) { + ble_peripheral_app_handle_at_cmd(subtype, arg); + } + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 2) { + gap_sched_scan(false); + } else if (io_msg.subtype == 3) { + gap_sched_scan(true); + } + else if (io_msg.subtype == 4) { + bt_mesh_device_matter_app_handle_upstream_msg(io_msg.subtype, io_msg.u.buf); + } + } + break; + case IO_MSG_TYPE_ADV: + { + if (bt_mesh_device_matter_le_adv_start_enable) { + uint8_t *padv_data = gap_sched_task_get(); + + if (NULL == padv_data) + { + printf("[BT Mesh Device] bt_mesh_device_matter_adv_timer_handler allocate padv_data fail ! \n\r"); + break; + } + + gap_sched_task_p ptask = CONTAINER_OF(padv_data, gap_sched_task_t, adv_data); + + memcpy(padv_data, (uint8_t *)bt_mesh_device_matter_adv_data, sizeof(bt_mesh_device_matter_adv_data)); + + ptask->adv_len += 23; + ptask->adv_type = GAP_SCHED_ADV_TYPE_IND; + + gap_sched_try(ptask); + } + } + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_mesh_device_matter_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_mesh_device_matter_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_mesh_device_matter_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + //bt_mesh_device_matter_le_adv_start(); + } + } + + if (bt_mesh_device_matter_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("\n\rGAP adv stoped: because connection created\n\r"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + printf("\n\rGAP adv stopped\n\r"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("\n\rGAP adv start\n\r"); + } + } + + if (bt_mesh_device_matter_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + //data_uart_debug("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + //data_uart_debug("GAP scan start\r\n"); + } + } + + bt_mesh_device_matter_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_mesh_device_matter_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + T_GAP_CONN_INFO conn_info; + if (conn_id >= BT_MESH_DEVICE_MATTER_APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("bt_mesh_device_matter_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, bt_mesh_device_matter_app_link_table[conn_id].conn_state, new_state, disc_cause); + + bt_mesh_device_matter_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_mesh_device_matter_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + data_uart_debug("Disconnect conn_id %d, cause 0x%x\r\n", conn_id, disc_cause); + mesh_device_conn_state = 0; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + goto next; + } + } else { + goto next; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_disconnect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_disconnect)); + goto next; + } + } else { + goto next; + } +#endif + +next: + if (bt_mesh_device_matter_config_adv_flag){ + if (bt_mesh_device_matter_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + /*stack ready*/ + bt_mesh_device_matter_le_adv_start(); + } + } + + if (bt_mesh_device_matter_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + bt_mesh_device_matter_central_app_max_links --; + } else if (bt_mesh_device_matter_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + bt_mesh_device_matter_peripheral_app_max_links --; + } + + memset(&bt_mesh_device_matter_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + + //send data to matter + BT_MATTER_CONN_EVENT *disconnected = os_mem_alloc(0, sizeof(BT_MATTER_CONN_EVENT)); + if(disconnected) + { + disconnected->conn_id = conn_id; + disconnected->new_state = new_state; + disconnected->disc_cause = disc_cause; + if(bt_mesh_device_matter_adapter_send_callback_msg(BT_MATTER_SEND_CB_MSG_DISCONNECTED, NULL, disconnected)==false) + { + os_mem_free(disconnected); + } + } + else + printf("Malloc failed\r\n"); + + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, bt_mesh_device_matter_app_link_table[conn_id].bd_addr, + &bt_mesh_device_matter_app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(bt_mesh_device_matter_app_link_table[conn_id].bd_addr), bt_mesh_device_matter_app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_debug("Connected success conn_id %d\r\n", conn_id); + mesh_device_conn_state = 1; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + } +#endif + + //get device role + if (le_get_conn_info(conn_id, &conn_info)){ + bt_mesh_device_matter_app_link_table[conn_id].role = conn_info.role; + if (bt_mesh_device_matter_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + bt_mesh_device_matter_central_app_max_links ++; + } else if (bt_mesh_device_matter_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE){ + bt_mesh_device_matter_peripheral_app_max_links ++; + } + } + + ////print bt address type + uint8_t local_bd_type; + //uint8_t features[8]; + uint8_t remote_bd_type; + le_get_conn_param(GAP_PARAM_CONN_LOCAL_BD_TYPE, &local_bd_type, conn_id); + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR_TYPE, &remote_bd_type, conn_id); + APP_PRINT_INFO3("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); + data_uart_debug("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); + + //send data to matter + BT_MATTER_CONN_EVENT *connected = os_mem_alloc(0, sizeof(BT_MATTER_CONN_EVENT)); + if(connected) + { + connected->conn_id = conn_id; + connected->new_state = new_state; + connected->disc_cause = disc_cause; + if(bt_mesh_device_matter_adapter_send_callback_msg(BT_MATTER_SEND_CB_MSG_CONNECTED, NULL, connected)==false) + { + os_mem_free(connected); + } + } + else + printf("Malloc failed\r\n"); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, 251, 2120); +#endif + if (bt_mesh_device_matter_config_adv_flag) { + if (bt_mesh_device_matter_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + bt_mesh_device_matter_le_adv_stop(); + } + } + + } + break; + + default: + break; + + } + +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_mesh_device_matter_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_mesh_device_matter_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_mesh_device_matter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_debug("Pair success\r\n"); + APP_PRINT_INFO0("bt_mesh_device_matter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_debug("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_mesh_device_matter_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_mesh_device_matter_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_mesh_device_matter_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_mesh_device_matter_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_mesh_device_matter_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_mesh_device_matter_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_debug("\n\rbt_mesh_device_matter_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x \r\n", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_mesh_device_matter_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + data_uart_debug("\n\rbt_mesh_device_matter_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x\r\n", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_mesh_device_matter_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + data_uart_debug("\n\rbt_mesh_device_matter_app_handle_conn_param_update_evt update pending: conn_id %d\r\n", conn_id); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * sub_type of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_mesh_device_matter_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_mesh_device_matter_app_handle_gap_msg: sub_type %d", p_gap_msg->subtype); + mesh_inner_msg_t mesh_inner_msg; + mesh_inner_msg.type = MESH_BT_STATUS_UPDATE; + mesh_inner_msg.sub_type = p_gap_msg->subtype; + mesh_inner_msg.parm = p_gap_msg->u.param; + gap_sched_handle_bt_status_msg(&mesh_inner_msg); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + if (!mesh_initial_state) + { + mesh_initial_state = TRUE; + /** set device uuid according to bt address */ + uint8_t bt_addr[6]; + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + memcpy(dev_uuid, bt_addr, sizeof(bt_addr)); + device_uuid_set(dev_uuid); + } + bt_mesh_device_matter_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_mesh_device_matter_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_mesh_device_matter_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_mesh_device_matter_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_mesh_device_matter_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", conn_id, display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", conn_id, display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_debug("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_device_app_handle_gap_msg: unknown sub_type %d", p_gap_msg->subtype); + break; + } +} + +/** @defgroup CENTRAL_CLIENT_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void bt_mesh_device_matter_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("bt_mesh_device_matter_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_scatternet_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); + //BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} + +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void bt_mesh_device_matter_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + data_uart_debug("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + data_uart_debug("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + data_uart_debug("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + data_uart_debug("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + data_uart_debug("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + data_uart_debug("Invalid disc type: conn_id %d, discov_type %d\n\r", + conn_id, discov_result.discov_type); + break; + } +} + +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_device_matter_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_mesh_device_matter_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_mesh_device_matter_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_debug("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\n\r", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_debug("READ VALUE: "); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_debug("\n\r"); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_debug("WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("INDICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("INDICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("NOTIFICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + + return result; +} + + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + char adv_type[20]; + char remote_addr_type[10]; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + + if (bt_mesh_device_matter_scan_state) { + /* If you want to parse the scan info, please reference function ble_central_app_parse_scan_info. */ + sprintf(adv_type,"%s",(p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_UNDIRECTED)? "CON_UNDIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_DIRECTED)? "CON_DIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCANNABLE)? "SCANABLE_UNDIRCT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_NON_CONNECTABLE)? "NON_CONNECTABLE": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCAN_RSP)? "SCAN_RSP":"unknown"); + sprintf(remote_addr_type,"%s",(p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_PUBLIC)? "public": + (p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_RANDOM)? "random":"unknown"); + + BLE_PRINT("ADVType\t\t\t| AddrType\t|%s\t\t\t|rssi\n\r","BT_Addr"); + BLE_PRINT("%s\t\t%s\t"BD_ADDR_FMT"\t%d\n\r",adv_type,remote_addr_type,BD_ADDR_ARG(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->rssi); + + bt_mesh_device_matter_app_parse_scan_info(p_data->p_le_scan_info); + } + gap_sched_handle_adv_report(p_data->p_le_scan_info); + break; + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + gap_sched_adv_params_set_done(); + break; + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + data_uart_print("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d\r\n", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_device_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + + return result; +} + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_device_matter_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_device_matter_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + data_uart_debug("\n\rPROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE success\r\n"); + + //send msg to matter + if (p_param->event_data.send_data_result.service_id == bt_mesh_device_matter_adapter_srv_id) + { + T_SERVER_APP_CB_DATA *send_data_complete = os_mem_alloc(0, sizeof(T_SERVER_APP_CB_DATA)); + if(send_data_complete) + { + memcpy(send_data_complete, p_param, sizeof(T_SERVER_APP_CB_DATA)); + if(bt_mesh_device_matter_adapter_send_callback_msg(BT_MATTER_SEND_CB_MSG_SEND_DATA_COMPLETE, service_id, send_data_complete)==false) + { + os_mem_free(send_data_complete); + } + } + else + printf("Malloc failed\r\n"); + } + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE failed\r\n"); + } + break; + + default: + break; + } + } + else if (service_id == datatrans_server_id) + { + datatrans_server_data_t *pdata = p_data; + switch (pdata->type) + { + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + pdata->len = sizeof(datatrans_sample_data); + pdata->data = datatrans_sample_data; + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + if (pdata->len > sizeof(datatrans_sample_data)) + { + pdata->len = sizeof(datatrans_sample_data); + } + memcpy(datatrans_sample_data, pdata->data, pdata->len); + break; + default: + break; + } + } + else if (service_id = bt_mesh_device_matter_adapter_srv_id) + { + T_MATTER_CALLBACK_DATA *p_simp_cb_data = (T_MATTER_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case MATTER_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("MATTER_NOTIFY_INDICATE_V3_ENABLE"); + printf("\n\rMATTER_NOTIFY_INDICATE_V3_ENABLE\r\n"); + //send msg to matter + T_MATTER_CALLBACK_DATA *indication_notification_enable = os_mem_alloc(0, sizeof(T_MATTER_CALLBACK_DATA)); + + if(indication_notification_enable) + { + memcpy(indication_notification_enable, p_simp_cb_data, sizeof(T_MATTER_CALLBACK_DATA)); + if (indication_notification_enable->msg_data.write.len !=0) + { + indication_notification_enable->msg_data.write.p_value = os_mem_alloc(0, indication_notification_enable->msg_data.write.len); + memcpy(indication_notification_enable->msg_data.write.p_value, p_simp_cb_data->msg_data.write.p_value, p_simp_cb_data->msg_data.write.len); + } + if(bt_mesh_device_matter_adapter_send_callback_msg(BT_MATTER_SEND_CB_MSG_IND_NTF_ENABLE, service_id, indication_notification_enable)==false) + { + if (indication_notification_enable->msg_data.write.len !=0) + { + os_mem_free(indication_notification_enable->msg_data.write.p_value); + indication_notification_enable->msg_data.write.p_value = NULL; + } + os_mem_free(indication_notification_enable); + indication_notification_enable = NULL; + } + } + else + printf("Malloc failed\r\n"); + } + break; + + case MATTER_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("MATTER_NOTIFY_INDICATE_V3_DISABLE"); + printf("\n\rMATTER_NOTIFY_INDICATE_V3_DISABLE\r\n"); + + //send msg to matter + T_MATTER_CALLBACK_DATA *indication_notification_disable = os_mem_alloc(0, sizeof(T_MATTER_CALLBACK_DATA)); + if(indication_notification_disable) + { + memcpy(indication_notification_disable, p_simp_cb_data, sizeof(T_MATTER_CALLBACK_DATA)); + if (indication_notification_disable->msg_data.write.len !=0) + { + indication_notification_disable->msg_data.write.p_value = os_mem_alloc(0, indication_notification_disable->msg_data.write.len); + memcpy(indication_notification_disable->msg_data.write.p_value, p_simp_cb_data->msg_data.write.p_value, p_simp_cb_data->msg_data.write.len); + } + + if(bt_mesh_device_matter_adapter_send_callback_msg(BT_MATTER_SEND_CB_MSG_IND_NTF_DISABLE, service_id, indication_notification_disable)==false) + { + if (indication_notification_disable->msg_data.write.len !=0) + { + os_mem_free(indication_notification_disable->msg_data.write.p_value); + indication_notification_disable->msg_data.write.p_value = NULL; + } + os_mem_free(indication_notification_disable); + indication_notification_disable = NULL; + } + } + else + printf("Malloc failed\r\n"); + } + break; + + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + //send msg to matter + T_MATTER_CALLBACK_DATA *read_write_char_val = os_mem_alloc(0, sizeof(T_MATTER_CALLBACK_DATA)); + if(read_write_char_val) + { + memcpy(read_write_char_val, p_simp_cb_data, sizeof(T_MATTER_CALLBACK_DATA)); + + //Make sure not malloc size of 0 + if (read_write_char_val->msg_data.write.len !=0) + { + read_write_char_val->msg_data.write.p_value = os_mem_alloc(0, read_write_char_val->msg_data.write.len); + memcpy(read_write_char_val->msg_data.write.p_value, p_simp_cb_data->msg_data.write.p_value, p_simp_cb_data->msg_data.write.len); + } + if(bt_mesh_device_matter_adapter_send_callback_msg(BT_MATTER_SEND_CB_MSG_READ_WRITE_CHAR, service_id, read_write_char_val)==false) + { + if (read_write_char_val->msg_data.write.len !=0) + { + os_mem_free(read_write_char_val->msg_data.write.p_value); + read_write_char_val->msg_data.write.p_value = NULL; + } + os_mem_free(read_write_char_val); + read_write_char_val = NULL; + } + } + else + printf("Malloc failed\r\n"); + } + break; + + default: + break; + } + } + + return app_result; +} + +/****************************************************************** + * @fn device_info_cb + * @brief device_info_cb callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return void + */ +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + if (!dev_info_show_flag) + { + return; + } + data_uart_debug("bt addr=0x%02x%02x%02x%02x%02x%02x type=%d rssi=%d ", bt_addr[5], bt_addr[4], + bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0], bt_addr_type, rssi); + switch (pinfo->type) + { + case DEVICE_INFO_UDB: + data_uart_debug("udb="); + data_uart_dump(pinfo->pbeacon_udb->dev_uuid, 16); + break; + case DEVICE_INFO_PROV_ADV: + data_uart_debug("prov="); + data_uart_dump(pinfo->pservice_data->provision.dev_uuid, 16); + break; + case DEVICE_INFO_PROXY_ADV: + data_uart_debug("proxy="); + data_uart_dump((uint8_t *)&pinfo->pservice_data->proxy, pinfo->len); + break; + default: + break; + } +} + +/****************************************************************** + * @fn prov_cb + * @brief Provisioning callbacks are handled in this function. + * + * @param cb_data - @ref TProvisioningCbData + * @return the operation result + */ +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data) +{ + APP_PRINT_INFO1("prov_cb: type = %d", cb_type); + + switch (cb_type) + { + case PROV_CB_TYPE_PB_ADV_LINK_STATE: + switch (cb_data.pb_generic_cb_type) + { + case PB_GENERIC_CB_LINK_OPENED: + data_uart_debug("PB-ADV Link Opened!\r\n>"); + break; + case PB_GENERIC_CB_LINK_OPEN_FAILED: + data_uart_debug("PB-ADV Link Open Failed!\r\n>"); + break; + case PB_GENERIC_CB_LINK_CLOSED: + data_uart_debug("PB-ADV Link Closed!\r\n>"); + break; + default: + break; + } + break; + case PROV_CB_TYPE_UNPROV: + data_uart_debug("unprov device!\r\n>"); + break; + case PROV_CB_TYPE_START: + data_uart_debug("being prov-ed!\r\n"); + break; + case PROV_CB_TYPE_PUBLIC_KEY: + { + uint8_t public_key[64] = {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79}; + uint8_t private_key[32] = {0x52, 0x9a, 0xa0, 0x67, 0x0d, 0x72, 0xcd, 0x64, 0x97, 0x50, 0x2e, 0xd4, 0x73, 0x50, 0x2b, 0x03, 0x7e, 0x88, 0x03, 0xb5, 0xc6, 0x08, 0x29, 0xa5, 0xa3, 0xca, 0xa2, 0x19, 0x50, 0x55, 0x30, 0xba}; + prov_params_set(PROV_PARAMS_PUBLIC_KEY, public_key, sizeof(public_key)); + prov_params_set(PROV_PARAMS_PRIVATE_KEY, private_key, sizeof(private_key)); + APP_PRINT_INFO0("prov_cb: Please show the public key to the provisioner"); + } + break; + case PROV_CB_TYPE_AUTH_DATA: + { + prov_start_p pprov_start = cb_data.pprov_start; + prov_auth_value_type = prov_auth_value_type_get(pprov_start); + /* use cmd to set auth data */ + data_uart_debug("auth method=%d[nsoi] action=%d size=%d type=%d[nbNa]\r\n>", + pprov_start->auth_method, + pprov_start->auth_action, pprov_start->auth_size, prov_auth_value_type); + //uint8_t auth_data[16] = {1}; + switch (pprov_start->auth_method) + { + case PROV_AUTH_METHOD_STATIC_OOB: + //prov_auth_value_set(auth_data, sizeof(auth_data)); + APP_PRINT_INFO0("prov_cb: Please exchange the oob data with the provisioner"); + break; + case PROV_AUTH_METHOD_OUTPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.output_oob_size); + APP_PRINT_INFO2("prov_cb: Please output the oob data to the provisioner, output size = %d, action = %d", + pprov_start->auth_size.output_oob_size, pprov_start->auth_action.output_oob_action); + break; + case PROV_AUTH_METHOD_INPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.input_oob_size); + APP_PRINT_INFO2("prov_cb: Please input the oob data provided by the provisioner, input size = %d, action = %d", + pprov_start->auth_size.input_oob_size, pprov_start->auth_action.input_oob_action); + break; + default: + break; + } + } + break; + case PROV_CB_TYPE_COMPLETE: + { + mesh_node.iv_timer_count = MESH_IV_INDEX_48W; + prov_data_p pprov_data = cb_data.pprov_data; + data_uart_debug("been prov-ed with addr 0x%04x!\r\n", pprov_data->unicast_address); + } + break; + case PROV_CB_TYPE_FAIL: + data_uart_debug("provision fail, type=%d!\r\n", cb_data.prov_fail.fail_type); + break; + case PROV_CB_TYPE_PROV: + /* stack ready */ + data_uart_debug("ms addr: 0x%04x\r\n>", mesh_node.unicast_addr); + break; + default: + break; + } + return true; +} + +/****************************************************************** + * @fn fn_cb + * @brief fn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"establishing with lpn 0x%04x\r\n", "no poll from 0x%04x\r\n", "established with lpn 0x%04x\r\n", "lpn 0x%04x lost\r\n"}; + data_uart_debug(string[type], lpn_addr); + if (type == FN_CB_TYPE_ESTABLISH_SUCCESS || type == FN_CB_TYPE_FRND_LOST) + { + user_cmd_time(NULL); + } +} + +/****************************************************************** + * @fn lpn_cb + * @brief lpn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"established with fn 0x%04x\r\n", "no frnd offer\r\n", "no frnd update\r\n", "fn 0x%04x lost\r\n"}; + data_uart_debug(string[type], fn_addr); + if (type == LPN_CB_TYPE_ESTABLISH_SUCCESS || type == LPN_CB_TYPE_FRIENDSHIP_LOST) + { + user_cmd_time(NULL); + } + + if (type == LPN_CB_TYPE_ESTABLISH_SUCCESS) + { + gap_sched_scan(false); + lpn_disable_scan_flag = 1; + mesh_service_adv_stop(); + } + else if (type == LPN_CB_TYPE_FRIENDSHIP_LOST) + { + if (lpn_disable_scan_flag){ + gap_sched_scan(true); + lpn_disable_scan_flag = 0; + } + mesh_service_adv_start(); + } +} + +/****************************************************************** + * @fn hb_cb + * @brief heartbeat callbacks are handled in this function. + * + * @param type + * @param pdata + * @return void + */ +void hb_cb(hb_data_type_t type, void *pargs) +{ + switch (type) + { + case HB_DATA_PUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat publish timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat publish timer stop\r\n"); + } + } + break; + case HB_DATA_SUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat subscription timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat subscription timer stop\r\n"); + } + } + break; + case HB_DATA_PUB_COUNT_UPDATE: + { + hb_data_pub_count_update_t *pdata = pargs; + data_uart_debug("heartbeat publish count update: %d\r\n", pdata->count); + } + break; + case HB_DATA_SUB_PERIOD_UPDATE: + { + hb_data_sub_period_update_t *pdata = pargs; + data_uart_debug("heartbeat subscription period update: %d\r\n", pdata->period); + } + break; + case HB_DATA_SUB_RECEIVE: + { + hb_data_sub_receive_t *pdata = pargs; + data_uart_debug("receive heartbeat: src = %d, init_ttl = %d, features = %d-%d-%d-%d, ttl = %d\r\n", + pdata->src, pdata->init_ttl, pdata->features.relay, pdata->features.proxy, + pdata->features.frnd, pdata->features.lpn, pdata->ttl); + } + break; + default: + break; + } +} + +void bt_mesh_device_matter_app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("bt_mesh_device_matter_app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_ERROR1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} + +#if F_BT_GAPS_CHAR_WRITEABLE +/** @defgroup SCATTERNET_GAPS_WRITE GAP Service Callback Handler + * @brief Use @ref F_BT_GAPS_CHAR_WRITEABLE to open + * @{ + */ +/** + * @brief All the BT GAP service callback events are handled in this function + * @param[in] service_id Profile service ID + * @param[in] p_para Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_gap_service_callback(T_SERVER_ID service_id, void *p_para) +{ + (void) service_id; + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; + APP_PRINT_INFO2("bt_mesh_device_matter_gap_service_callback: conn_id = %d msg_type = %d\n", p_gap_data->conn_id, + p_gap_data->msg_type); + APP_PRINT_INFO2("bt_mesh_device_matter_gap_service_callback: len = 0x%x,opcode = %d\n", p_gap_data->msg_data.len, + p_gap_data->msg_data.opcode); + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) + { + switch (p_gap_data->msg_data.opcode) + { + case GAPS_WRITE_DEVICE_NAME: + { + T_LOCAL_NAME device_name; + memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); + device_name.local_name[p_gap_data->msg_data.len] = 0; + //data_uart_debug("GAPS_WRITE_DEVICE_NAME:device_name = %s \n\r",device_name.local_name); + flash_save_local_name(&device_name); + } + break; + + case GAPS_WRITE_APPEARANCE: + { + uint16_t appearance_val; + T_LOCAL_APPEARANCE appearance; + + LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); + appearance.local_appearance = appearance_val; + //data_uart_debug("GAPS_WRITE_APPEARANCE:appearance = %s \n\r",appearance.local_appearance); + flash_save_local_appearance(&appearance); + } + break; + default: + APP_PRINT_ERROR1("bt_mesh_device_matter_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + //data_uart_debug("bt_mesh_device_matter_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + break; + } + } + return result; +} +/** @} */ +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app.h new file mode 100644 index 00000000..d037aa07 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app.h @@ -0,0 +1,147 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.h +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _BT_MESH_DEVICE_MATTER_APP_H__ +#define _BT_MESH_DEVICE_MATTER_APP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "app_msg.h" +#include "mesh_api.h" +#include "bt_mesh_device_matter_app_flags.h" + +/*============================================================================* + * Variables + *============================================================================*/ +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] + +extern T_CLIENT_ID bt_mesh_device_matter_gcs_client_id; /**< General Common Services client client id*/ +extern T_SERVER_ID bt_mesh_device_matter_adapter_srv_id; /**< Matter service id */ + +extern int bt_mesh_device_matter_peripheral_app_max_links; +extern int bt_mesh_device_matter_central_app_max_links; + +extern bool mesh_initial_state; +extern T_GAP_DEV_STATE bt_mesh_device_matter_gap_dev_state; +extern uint8_t bt_mesh_device_matter_config_adv_flag; + +typedef struct +{ + uint8_t conn_id; + uint8_t new_state; + uint16_t disc_cause; +} BT_MATTER_CONN_EVENT; + +typedef enum +{ + BT_MATTER_MSG_START_ADV = 12, + BT_MATTER_MSG_STOP_ADV, + BT_MATTER_MSG_SEND_DATA, +} BT_MATTER_SERVER_MSG_TYPE; + +typedef enum +{ + BT_MATTER_SEND_CB_MSG_DISCONNECTED = 1, + BT_MATTER_SEND_CB_MSG_CONNECTED, + BT_MATTER_SEND_CB_MSG_ALL_GAP_MSG, + BT_MATTER_SEND_CB_MSG_SEND_DATA_COMPLETE, + BT_MATTER_SEND_CB_MSG_IND_NTF_ENABLE, + BT_MATTER_SEND_CB_MSG_IND_NTF_DISABLE, + BT_MATTER_SEND_CB_MSG_READ_WRITE_CHAR, +} BT_MATTER_SEND_MSG_TYPE; + +typedef enum +{ + CB_PROFILE_CALLBACK = 0x01, /**< bt_matter_adapter_app_profile_callback */ + CB_GAP_CALLBACK = 0x02, /**< bt_matter_adapter_app_gap_callback */ + CB_GAP_MSG_CONN_EVENT = 0x3, /**< bt_matter_adapter_app_handle_gap_msg */ +} T_CHIP_BLEMGR_CALLBACK_TYPE; +/*============================================================================* + * Functions + *============================================================================*/ +typedef int (*chip_blemgr_callback)(void *param, void *cb_data, int type, T_CHIP_BLEMGR_CALLBACK_TYPE callback_type); +void chip_blemgr_set_callback_func(chip_blemgr_callback p, void *data); + +void bt_mesh_device_matter_handle_callback_msg(T_IO_MSG callback_msg); + +void bt_mesh_device_matter_app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_device_matter_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_device_matter_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_matter_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +#if F_BT_GAPS_CHAR_WRITEABLE +T_APP_RESULT bt_mesh_device_matter_gap_service_callback(T_SERVER_ID service_id, void *p_para); +#endif + +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo); +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +void hb_cb(hb_data_type_t type, void *pargs); +void bt_mesh_device_matter_app_vendor_callback(uint8_t cb_type, void *p_cb_data); +#ifdef __cplusplus +} +#endif + +#endif /* _MESH_APPLICATION__S */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_flags.h new file mode 100644 index 00000000..6860eaa1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_flags.h @@ -0,0 +1,51 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_DEVICE_MATTER_APP_FLAGS_H_ +#define _BT_MESH_DEVICE_MATTER_APP_FLAGS_H_ + +#include "platform_opts_bt.h" + +#include + +/** + * @addtogroup MESH_APP_CONFIG + * @{ + */ + +/** + * @defgroup Mesh_App_Config Mesh App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ +#if defined(CONFIG_PLATFORM_8721D) +#define BT_MESH_DEVICE_MATTER_APP_MAX_LINKS 4 +#define BT_MESH_DEVICE_MATTER_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BT_MESH_DEVICE_MATTER_CENTRAL_APP_MAX_LINKS 3 //for max master link num +#elif defined(CONFIG_PLATFORM_8710C) +#define BT_MESH_DEVICE_MATTER_APP_MAX_LINKS 2 +#define BT_MESH_DEVICE_MATTER_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BT_MESH_DEVICE_MATTER_CENTRAL_APP_MAX_LINKS 1 //for max master link num +#endif + +/** @brief Config the discovery table number of gcs_client */ +#define BT_MESH_DEVICE_MATTER_SCATTERNET_APP_MAX_DISCOV_TABLE_NUM 40 + +/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/ +#define F_BT_AIRPLANE_MODE_SUPPORT 0 + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_main.c new file mode 100644 index 00000000..2f74ef90 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_main.c @@ -0,0 +1,764 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "health.h" +#include "generic_on_off.h" +#include "light_server_app.h" +#include "time_server_app.h" +#include "scheduler_server_app.h" +#include "scene_server_app.h" +#include "ping.h" +#include "ping_app.h" +#include "tp.h" +#include "datatrans_server.h" +#include "health.h" +#include "datatrans_app.h" +#include +#include "bt_mesh_device_matter_app_flags.h" +#include "bt_mesh_device_matter_app.h" +#include "bt_mesh_device_matter_adapter_service.h" +#include "bt_mesh_device_matter_app_main.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#include "osdep_service.h" +#include "wifi_constants.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_device_api.h" +#endif +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK +#include "device_idle_check.h" +#endif +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_updater_app.h" +#endif +#include +#include +#include "trace_uart.h" +#include +#include +#include "rtk_coex.h" +#include +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 400 + +/** @brief Default scan interval (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_INTERVAL 0x520 +/** @brief Default scan window (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_WINDOW 0x520 + +#define COMPANY_ID 0x005D +#define PRODUCT_ID 0x0000 +#define VERSION_ID 0x0000 + +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +uint8_t bt_mesh_device_matter_adv_data[31] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0C, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'M', 'E', 'S', 'H', '_', 'M', 'A', 'T', 'T', 'E', 'R', +}; +int array_count_of_adv_data = sizeof(bt_mesh_device_matter_adv_data) / sizeof(bt_mesh_device_matter_adv_data[0]); + +plt_timer_t bt_mesh_device_matter_adv_timer = NULL; +uint8_t bt_mesh_device_matter_le_adv_start_enable = 0; +uint16_t bt_mesh_device_matter_adv_interval = 352; + +mesh_model_info_t health_server_model; +mesh_model_info_t generic_on_off_server_model; + +generic_on_off_t current_on_off = GENERIC_OFF; + +/*============================================================================* + * Functions + *============================================================================*/ +#if defined(MESH_DFU) && MESH_DFU + extern void blob_transfer_server_caps_set(blob_server_capabilites_t *pcaps); +#endif + +void bt_mesh_device_matter_adv_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + uint16_t adv_interval = bt_mesh_device_matter_adv_interval * 625 / 1000; + + io_msg.type = IO_MSG_TYPE_ADV; + if (os_msg_send(bt_mesh_device_matter_io_queue_handle, &io_msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_matter_evt_queue_handle, &event, 0) == false) + { + } + if (bt_mesh_device_matter_le_adv_start_enable) { + plt_timer_change_period(bt_mesh_device_matter_adv_timer, adv_interval, 0xFFFFFFFF); + } +} + +void bt_mesh_device_matter_le_adv_start(void) +{ + uint16_t adv_interval = bt_mesh_device_matter_adv_interval * 625 / 1000; + + bt_mesh_device_matter_le_adv_start_enable = 1; + plt_timer_change_period(bt_mesh_device_matter_adv_timer, adv_interval, 0xFFFFFFFF); +} + +void bt_mesh_device_matter_le_adv_stop(void) +{ + bt_mesh_device_matter_le_adv_start_enable = 0; +} + +static int32_t generic_on_off_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case GENERIC_ON_OFF_SERVER_GET: + { + generic_on_off_server_get_t *pdata = pargs; + pdata->on_off = current_on_off; + } + break; + case GENERIC_ON_OFF_SERVER_GET_DEFAULT_TRANSITION_TIME: + break; + case GENERIC_ON_OFF_SERVER_SET: + { + generic_on_off_server_set_t *pdata = pargs; + if (pdata->total_time.num_steps == pdata->remaining_time.num_steps) + { + if (pdata->on_off != current_on_off) + { + current_on_off = pdata->on_off; + if (current_on_off == GENERIC_OFF) + { + printf("Provisioner turn light OFF!\r\n"); + } + else if (current_on_off == GENERIC_ON) + { + printf("Provisioner turn light ON!\r\n"); + } + } + } + } + break; + default: + break; + } + + return 0; +} + +void generic_on_off_server_model_init(void) +{ + generic_on_off_server_model.model_data_cb = generic_on_off_server_data; + generic_on_off_server_reg(0, &generic_on_off_server_model); +} + +/****************************************************************** + * @fn Initial gap parameters + * @brief Initialize peripheral and gap bond manager related parameters + * + * @return void + */ +void bt_mesh_device_matter_stack_init(void) +{ + /** set mesh stack log level, default all on, disable the log of level LEVEL_TRACE */ + uint32_t module_bitmap[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(TRACE_LEVEL_TRACE, module_bitmap); + + /** mesh stack needs rand seed */ + plt_srand(platform_random(0xffffffff)); + + /** configure provisioning parameters */ + prov_capabilities_t prov_capabilities = + { + .algorithm = PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE, + .public_key = 0, + .static_oob = 0, + .output_oob_size = 0, + .output_oob_action = 0, + .input_oob_size = 0, + .input_oob_action = 0 + }; + prov_params_set(PROV_PARAMS_CAPABILITIES, &prov_capabilities, sizeof(prov_capabilities_t)); + prov_params_set(PROV_PARAMS_CALLBACK_FUN, (void *)prov_cb, sizeof(prov_cb_pf)); + + /** config node parameters */ + mesh_node_features_t features = + { + .role = MESH_ROLE_DEVICE, + .relay = 1, + .proxy = 1, + .fn = 1, + .lpn = 1, + .prov = 1, + .udb = 1, + .snb = 1, + .bg_scan = 1, + .flash = 1, + .flash_rpl = 1 + }; + + mesh_node_cfg_t node_cfg = + { + .dev_key_num = 2, + .net_key_num = 10, + .app_key_num = 3, + .vir_addr_num = 3, + .rpl_num = 20, + .sub_addr_num = 5, + .proxy_num = 1, + .prov_interval = 2, + .udb_interval = 2, + .proxy_interval = 5 + }; + + mesh_node_cfg(features, &node_cfg); + proxy_server_support_prov_on_proxy(true); + mesh_node.net_trans_count = 6; + mesh_node.relay_retrans_count = 2; + mesh_node.trans_retrans_count = 4; + mesh_node.ttl = 5; +#if MESH_LPN + mesh_node.frnd_poll_retry_times = 32; +#endif + + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /** create elements and register models */ + mesh_element_create(GATT_NS_DESC_UNKNOWN); + +#if !defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) || (!CONFIG_BT_MESH_DEVICE_RTK_DEMO) + health_server_reg(0, &health_server_model); + health_server_set_company_id(&health_server_model, COMPANY_ID); + ping_control_reg(ping_app_ping_cb, pong_receive); + trans_ping_pong_init(ping_app_ping_cb, pong_receive); + tp_control_reg(tp_reveive); + datatrans_model_init(); + light_server_models_init(); + time_server_models_init(); + scene_server_model_init(); + scheduler_server_model_init(); +#endif + + generic_on_off_server_model_init(); + +#if defined(MESH_DFU) && MESH_DFU + dfu_updater_models_init(); + blob_server_capabilites_t caps = { + 6, //BLOB_TRANSFER_CPAS_MIN_BLOCK_SIZE_LOG + 12, //BLOB_TRANSFER_CPAS_MAX_BLOCK_SIZE_LOG + 20, //BLOB_TRANSFER_CPAS_MAX_TOTAL_CHUNKS + 256, //BLOB_TRANSFER_CPAS_MAX_CHUNK_SIZE + 1000000, //!< supported max size + 350, //BLOB_TRANSFER_CPAS_SERVER_MTU_SIZE + 1, //BLOB_TRANSFER_CPAS_MODE_PULL_SUPPORT + 1, //BLOB_TRANSFER_CPAS_MODE_PUSH_SUPPORT + 0 //RFU + }; + blob_transfer_server_caps_set(&caps); +#endif + + bt_mesh_device_matter_adv_timer = plt_timer_create("bt_mesh_device_matter_adv_timer", 0xFFFFFFFF, FALSE, NULL, bt_mesh_device_matter_adv_timer_handler); + if (!bt_mesh_device_matter_adv_timer) { + printf("[BT Mesh Device Matter] Create adv timer failed\n\r"); + } + + compo_data_page0_header_t compo_data_page0_header = {COMPANY_ID, PRODUCT_ID, VERSION_ID}; + compo_data_page0_gen(&compo_data_page0_header); + + /** init mesh stack */ + mesh_init(); + + /** register proxy adv callback */ + device_info_cb_reg(device_info_cb); + hb_init(hb_cb); +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_mesh_device_matter_app_le_gap_init(void) +{ + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + uint16_t scan_window = 0x100; /* 160ms */ + uint16_t scan_interval = 0x120; /* 180ms */ + + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "MESH_MATTER"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* Scan parameters */ + //uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + //uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + //uint16_t scan_window = DEFAULT_SCAN_WINDOW; + //uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + //uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, array_count_of_adv_data, (void *)bt_mesh_device_matter_adv_data); + // le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + +#if 0 + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_USE_STATIC_RANDOM_ADDR + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (ble_scatternet_app_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + ble_scatternet_app_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer +#if 0 + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#endif +#endif +#if F_BT_GAPS_CHAR_WRITEABLE + uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; + uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; + T_LOCAL_APPEARANCE appearance_local; + T_LOCAL_NAME local_device_name; + if (flash_load_local_appearance(&appearance_local) == 0) + { + gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance); + } + + if (flash_load_local_name(&local_device_name) == 0) + { + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name); + } + gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop); + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop); + gatt_register_callback((void*)bt_mesh_device_matter_gap_service_callback); +#endif + } + + vendor_cmd_init(bt_mesh_device_matter_app_vendor_callback); + /* register gap message callback */ + le_register_app_cb(bt_mesh_device_matter_app_gap_callback); + +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_mesh_device_matter_app_le_profile_init(void) +{ + server_init(MESH_GATT_SERVER_COUNT + 1); + bt_mesh_device_matter_adapter_srv_id = bt_matter_adapter_service_add_service((void *)bt_mesh_device_matter_app_profile_callback); + + /* Register Server Callback */ + server_register_app_cb(bt_mesh_device_matter_app_profile_callback); + + client_init(MESH_GATT_CLIENT_COUNT + 1); + /* Add Client Module */ + bt_mesh_device_matter_gcs_client_id = gcs_add_client(bt_mesh_device_matter_gcs_client_callback, BT_MESH_DEVICE_MATTER_APP_MAX_LINKS, + BT_MESH_DEVICE_MATTER_SCATTERNET_APP_MAX_DISCOV_TABLE_NUM); + + /* Register Client Callback--App_ClientCallback to handle events from Profile Client layer. */ + client_register_general_client_cb(bt_mesh_device_matter_app_client_callback); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void bt_mesh_device_matter_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_mesh_device_matter_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void bt_mesh_device_matter_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void bt_mesh_device_matter_task_init(void) +{ + bt_mesh_device_matter_app_task_init(); +} + +void bt_mesh_device_matter_task_deinit(void) +{ + bt_mesh_device_matter_app_task_deinit(); +} + +void bt_mesh_device_matter_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_MESH_DEVICE_MATTER_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_MESH_DEVICE_MATTER_APP_MAX_LINKS); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_mesh_device_matter_app_main(void) +{ + bt_trace_init(); + bt_mesh_device_matter_stack_config_init(); + bte_init(); + bt_mesh_device_matter_board_init(); + bt_mesh_device_matter_driver_init(); + le_gap_init(BT_MESH_DEVICE_MATTER_APP_MAX_LINKS); + bt_mesh_device_matter_app_le_gap_init(); + bt_mesh_device_matter_app_le_profile_init(); + bt_mesh_device_matter_stack_init(); + bt_mesh_device_matter_pwr_mgr_init(); + bt_mesh_device_matter_task_init(); + + return 0; +} + +int bt_mesh_device_matter_app_init(void) +{ + //int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT Mesh Device Matter]BT Stack already on\n\r"); + return 0; + } + else + bt_mesh_device_matter_app_main(); + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_device_api_init()) { + printf("[BT Mesh Device Matter] bt_mesh_device_api_init fail ! \n\r"); + return 1; + } +#endif + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK + bt_mesh_idle_check_init(); +#endif + + return 0; +} + +extern void mesh_deinit(void); +extern bool bt_trace_uninit(void); +extern void gcs_delete_client(void); +void bt_mesh_device_matter_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + if (plt_timer_is_active(bt_mesh_device_matter_adv_timer)) { + plt_timer_stop(bt_mesh_device_matter_adv_timer, 0xFFFFFFFF); + } + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + bt_mesh_device_api_deinit(); +#endif + bt_mesh_device_matter_task_deinit(); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Device Matter] BT Stack is not running\n\r"); + mesh_initial_state = FALSE; + bt_mesh_device_matter_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; + return; + } +#if F_BT_DEINIT + else { + gcs_delete_client(); + bte_deinit(); + printf("[BT Mesh Device Matter] BT Stack deinitalized\n\r"); + } +#endif + mesh_deinit(); + bt_trace_uninit(); + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK + bt_mesh_idle_check_deinit(); +#endif + + plt_timer_delete(bt_mesh_device_matter_adv_timer, 0xFFFFFFFF); + bt_mesh_device_matter_adv_timer = NULL; + + mesh_initial_state = FALSE; + bt_mesh_device_matter_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; +} + + +uint16_t ble_att_mtu_z2(uint16_t conn_id) +{ + int ret; + uint16_t mtu_size; + + ret = le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, &mtu_size, conn_id); + if (ret == 0) + { + printf("printing MTU size\r\n"); + return mtu_size; + } + else + return 0; +} + +bool ble_matter_netmgr_server_send_data(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint8_t *p_data, uint16_t data_len, T_GATT_PDU_TYPE type) +{ + BT_MATTER_SERVER_SEND_DATA *param = os_mem_alloc(0, sizeof(BT_MATTER_SERVER_SEND_DATA)); + if(param) + { + param->conn_id = conn_id; + param->service_id = service_id; + param->attrib_index = attrib_index; + param->data_len = data_len; + param->type = type; + if (param->data_len != 0) + { + param->p_data = os_mem_alloc(0, param->data_len); + memcpy(param->p_data, p_data, param->data_len); + } + if(bt_mesh_device_matter_adapter_send_msg(4, param) == false) + { + printf("os_mem_free\r\n"); + os_mem_free(param); + os_mem_free(param->p_data); + return false; + } + } + else + printf("Malloc failed\r\n"); + + return true; +} + +bool ble_matter_netmgr_adv_param_handler(uint16_t adv_int_min, uint16_t adv_int_max, + void *advData, uint8_t advData_len) +{ + int ret = 0; + bt_mesh_device_matter_config_adv_flag = 1; //matter moudle enable config adv + bt_mesh_device_matter_adv_interval = adv_int_min; + memcpy(bt_mesh_device_matter_adv_data, advData, advData_len); + + return ret; +} + +bool ble_matter_netmgr_adv_start_handler(void) +{ + bt_mesh_device_matter_le_adv_start(); + return 0; +} + +bool ble_matter_netmgr_adv_stop_handler(void) +{ + bt_mesh_device_matter_config_adv_flag = 0; //matter moudle disable config adv + bt_mesh_device_matter_le_adv_stop(); + return 0; +} + +bool ble_matter_netmgr_adapter_init_handler(void) +{ + return bt_mesh_device_matter_app_init(); +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_main.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_main.h new file mode 100644 index 00000000..d0906604 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_main.h @@ -0,0 +1,61 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file bt_matter_adapter_peripheral_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_DEVICE_MATTER_APP_MAIN_H__ +#define _BT_MESH_DEVICE_MATTER_APP_MAIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +typedef struct +{ + uint8_t conn_id; + uint8_t service_id; + uint16_t attrib_index; + uint8_t *p_data; + uint16_t data_len; + uint8_t type; +} BT_MATTER_SERVER_SEND_DATA; + +/*============================================================================* + * Functions + *============================================================================*/ +uint16_t ble_att_mtu_z2(uint16_t conn_id); + +bool ble_matter_netmgr_server_send_data(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint8_t *p_data, uint16_t data_len, T_GATT_PDU_TYPE type); + +bool ble_matter_netmgr_adv_param_handler(uint16_t adv_int_min, uint16_t adv_int_max, void *advData, uint8_t advData_len); + +bool ble_matter_netmgr_adv_start_handler(void); + +bool ble_matter_netmgr_adv_stop_handler(void); + +bool ble_matter_netmgr_adapter_init_handler(void); + + +#ifdef __cplusplus +}; +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_task.c new file mode 100644 index 00000000..5127c58c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_task.c @@ -0,0 +1,326 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +#include +#include +#include +#include +#include +#include +#include +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "device_cmd.h" +#include "platform_opts.h" +#include "ble_scatternet_user_cmd.h" +#include "bt_mesh_device_matter_app.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +/*============================================================================* + * Macros + *============================================================================*/ +#define EVENT_MESH 0x80 +#define APP_TASK_PRIORITY 4 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#else +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#endif + +//ble matter +#define BT_MATTER_APP_CALLBACK_TASK_PRIORITY APP_TASK_PRIORITY +#define BT_MATTER_APP_CALLBACK_TASK_STACK_SIZE 1024*4 +#define BT_MATTER_MAX_NUMBER_OF_CALLBACK_MESSAGE 0x20 + +#if defined(CONFIG_PLATFORM_8721D) +#define UART_TX _PA_18 +#define UART_RX _PA_19 +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +#define UART_TX PA_14 +#define UART_RX PA_13 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_mesh_device_matter_app_task_handle; //!< APP Task handle +void *bt_mesh_device_matter_evt_queue_handle; //!< Event queue handle +void *bt_mesh_device_matter_io_queue_handle; //!< IO queue handle +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +void *bt_mesh_device_matter_user_cmd_io_queue_handle; //!< user cmd queue handle +#endif + +void *bt_mesh_device_matter_callback_task_handle = NULL; /* Callback Task handle */ +void *bt_mesh_device_matter_callback_queue_handle = NULL; /* Callback Queue handle */ + +/*============================================================================* + * Functions + *============================================================================*/ +/*note: [input]subtype: set as BT_MATTER_SERVER_MSG_TYPE*/ +bool bt_mesh_device_matter_adapter_send_msg(uint16_t sub_type, void *arg) +{ + uint8_t event = EVENT_IO_TO_APP; + + T_IO_MSG io_msg; + + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + io_msg.u.buf = arg; + + if (bt_mesh_device_matter_evt_queue_handle != NULL && bt_mesh_device_matter_io_queue_handle != NULL) { + if (os_msg_send(bt_mesh_device_matter_io_queue_handle, &io_msg, 0) == false) { + printf("bt matter adapter send msg fail: subtype 0x%x", io_msg.subtype); + } else if (os_msg_send(bt_mesh_device_matter_evt_queue_handle, &event, 0) == false) { + printf("bt matter adapter event fail: subtype 0x%x", io_msg.subtype); + } + } + return true; +} + +bool bt_mesh_device_matter_adapter_send_callback_msg(uint16_t msg_type, uint8_t cb_type, void *arg) +{ + T_IO_MSG callback_msg; + callback_msg.type = msg_type; + + if( (msg_type==BT_MATTER_SEND_CB_MSG_SEND_DATA_COMPLETE) || (msg_type==BT_MATTER_SEND_CB_MSG_IND_NTF_ENABLE) ||\ + (msg_type==BT_MATTER_SEND_CB_MSG_IND_NTF_DISABLE) || (msg_type==BT_MATTER_SEND_CB_MSG_READ_WRITE_CHAR) ) + { + callback_msg.subtype = cb_type; + } + + callback_msg.u.buf = arg; + if (bt_mesh_device_matter_callback_queue_handle != NULL) { + if (os_msg_send(bt_mesh_device_matter_callback_queue_handle, &callback_msg, 0) == false) { + printf("bt matter send msg fail: subtype 0x%x", callback_msg.type); + return false; + } + + return true; + } + + return false; +} + +void bt_mesh_device_matter_adapter_callback_main_task(void *p_param) +{ + (void)p_param; + T_IO_MSG callback_msg; + + os_msg_queue_create(&bt_mesh_device_matter_callback_queue_handle, BT_MATTER_MAX_NUMBER_OF_CALLBACK_MESSAGE, sizeof(T_IO_MSG)); + + while (true) + { + if (os_msg_recv(bt_mesh_device_matter_callback_queue_handle, &callback_msg, 0xFFFFFFFF) == true) + { + bt_mesh_device_matter_handle_callback_msg(callback_msg); + } + } +} + +/*************************************************************************************************************/ +void app_send_uart_msg(uint8_t data) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = IO_MSG_TYPE_UART; + msg.subtype = data; + if (os_msg_send(bt_mesh_device_matter_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_matter_evt_queue_handle, &event, 0) == false) + { + } +} + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern CMD_MOD_INFO_S btMeshCmdPriv; +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg) +{ + uint8_t event = EVENT_USER_API_REQ; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)p_io_msg->u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + //trace commands transmitted to mesh stack + btMeshCmdPriv.cmdTransmittedNum ++; + if (os_msg_send(bt_mesh_device_matter_user_cmd_io_queue_handle, p_io_msg, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_device_matter_user_cmd_io_queue_handle fail!\r\n"); + return 1; + } + else if (os_msg_send(bt_mesh_device_matter_evt_queue_handle, &event, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_device_matter_evt_queue_handle fail!\r\n"); + return 1; + } + + return 0; +} +#endif + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_mesh_device_matter_app_main_task(void *p_param) +{ + /* avoid gcc compile warning */ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_mesh_device_matter_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_mesh_device_matter_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + os_msg_queue_create(&bt_mesh_device_matter_user_cmd_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); +#endif + gap_start_bt_stack(bt_mesh_device_matter_evt_queue_handle, bt_mesh_device_matter_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + mesh_start(EVENT_MESH, EVENT_IO_TO_APP, bt_mesh_device_matter_evt_queue_handle, bt_mesh_device_matter_io_queue_handle); + + mesh_data_uart_init(UART_TX, UART_RX, app_send_uart_msg); + mesh_user_cmd_init("MeshDevice"); + + while (true) + { + if (os_msg_recv(bt_mesh_device_matter_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_matter_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_device_matter_app_handle_io_msg(io_msg); + } + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + else if (event == EVENT_USER_API_REQ) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_matter_user_cmd_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_io_msg_handler(io_msg); + } + } +#endif +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + else if (event == EVENT_USER_HTTP_SERVER) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_matter_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_demo_io_msg_handler(io_msg); + } + } +#endif + else if (event == EVENT_MESH) + { + mesh_inner_msg_handle(event); + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_device_matter_app_task_init() +{ + /*app main task*/ + os_task_create(&bt_mesh_device_matter_app_task_handle, "bt_mesh_device_matter_app_task", bt_mesh_device_matter_app_main_task, + 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); + + /*ble matter task*/ + if (bt_mesh_device_matter_callback_task_handle == NULL) { + os_task_create(&bt_mesh_device_matter_callback_task_handle, "bt_mesh_device_matter_adapter_callback", bt_mesh_device_matter_adapter_callback_main_task, + 0, BT_MATTER_APP_CALLBACK_TASK_STACK_SIZE, BT_MATTER_APP_CALLBACK_TASK_PRIORITY); + } + +} + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_device_matter_app_task_deinit(void) +{ + if (bt_mesh_device_matter_app_task_handle) { + os_task_delete(bt_mesh_device_matter_app_task_handle); + } + if (bt_mesh_device_matter_io_queue_handle) { + os_msg_queue_delete(bt_mesh_device_matter_io_queue_handle); + } + if (bt_mesh_device_matter_evt_queue_handle) { + os_msg_queue_delete(bt_mesh_device_matter_evt_queue_handle); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_device_matter_user_cmd_io_queue_handle) { + os_msg_queue_delete(bt_mesh_device_matter_user_cmd_io_queue_handle); + } + bt_mesh_device_matter_user_cmd_io_queue_handle = NULL; +#endif + bt_mesh_device_matter_io_queue_handle = NULL; + bt_mesh_device_matter_evt_queue_handle = NULL; + bt_mesh_device_matter_app_task_handle = NULL; + + bt_mesh_device_matter_peripheral_app_max_links = 0; + bt_mesh_device_matter_central_app_max_links = 0; + + //bt matter + if (bt_mesh_device_matter_callback_task_handle) { + os_task_delete(bt_mesh_device_matter_callback_task_handle); + } + if (bt_mesh_device_matter_callback_queue_handle) { + os_msg_queue_delete(bt_mesh_device_matter_callback_queue_handle); + } + bt_mesh_device_matter_callback_task_handle = NULL; + bt_mesh_device_matter_callback_queue_handle = NULL; + bt_mesh_device_matter_config_adv_flag = 0; //matter moudle disable config adv + + mesh_user_cmd_deinit("MeshDevice"); +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_task.h new file mode 100644 index 00000000..fd747ea7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_app_task.h @@ -0,0 +1,41 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_DEVICE_MATTER_APP_TASK_H_ +#define _BT_MESH_DEVICE_MATTER_APP_TASK_H_ + +#include "mesh_config.h" +#include "app_msg.h" + +extern void *bt_mesh_device_matter_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_device_matter_io_queue_handle; //!< IO queue handle + +bool bt_mesh_device_matter_adapter_send_msg(uint16_t sub_type, void *arg); + +bool bt_mesh_device_matter_adapter_send_callback_msg(uint16_t msg_type, uint8_t cb_type, void *arg); + +void app_send_uart_msg(uint8_t data); + +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg); + + + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_device_matter_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_device_matter_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_cmd.c new file mode 100644 index 00000000..cf926300 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_cmd.c @@ -0,0 +1,349 @@ +/** +************************************************************************************************************ +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +************************************************************************************************************ +* @file device_cmd.c +* @brief User defined Mesh test commands. +* @details User command interfaces. +* @author +* @date 2015-03-19 +* @version v0.1 +************************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER +#include +#include "trace.h" +#include "gap_wrapper.h" +#include "mesh_cmd.h" +#include "test_cmd.h" +#include "mesh_api.h" +#include "device_cmd.h" +#include "device_app.h" +#include "datatrans_model.h" +#include "datatrans_app.h" +#include "generic_on_off.h" +#include "datatrans_server.h" + +extern mesh_model_info_t health_server_model; +extern mesh_model_info_t generic_on_off_server_model; +extern uint8_t lpn_disable_scan_flag; + +static user_cmd_parse_result_t user_cmd_node_reset(user_cmd_parse_value_t *pparse_value) +{ + switch (pparse_value->dw_parameter[0]) + { + case 0: + mesh_node_reset(); + break; + case 1: + mesh_node_clean(); + break; + case 2: + mesh_node_restore(); + break; + default: + break; + } + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_prov_capa_set(user_cmd_parse_value_t *pparse_value) +{ + prov_capabilities_t prov_capabilities; + prov_capabilities.algorithm = PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE; + prov_capabilities.public_key = pparse_value->dw_parameter[0] ? PROV_CAP_PUBLIC_KEY_OOB : 0; + prov_capabilities.static_oob = pparse_value->dw_parameter[1] ? PROV_CAP_STATIC_OOB : 0; + prov_capabilities.output_oob_size = pparse_value->dw_parameter[2]; + prov_capabilities.output_oob_action = pparse_value->dw_parameter[3]; + prov_capabilities.input_oob_size = pparse_value->dw_parameter[4]; + prov_capabilities.input_oob_action = pparse_value->dw_parameter[5]; + if (prov_capabilities.output_oob_size > OUTPUT_OOB_SIZE_MAX || + prov_capabilities.input_oob_size > INPUT_OOB_SIZE_MAX) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + else + { + prov_params_set(PROV_PARAMS_CAPABILITIES, &prov_capabilities, sizeof(prov_capabilities_t)); + return USER_CMD_RESULT_OK; + } +} + +#if MESH_LPN +static user_cmd_parse_result_t user_cmd_lpn_init(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_num = pparse_value->dw_parameter[0]; + return lpn_init(fn_num, lpn_cb) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_lpn_deinit(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + lpn_deinit(); + if (lpn_disable_scan_flag){ + gap_sched_scan(true); + lpn_disable_scan_flag = 0; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_lpn_req(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + lpn_req_params_t req_params = {50, 100, {1, 0, 0, 0}}; + + if(le_get_active_link_num() != 0) + { + data_uart_debug("Have BLE active link, cannot establish friendship\n\r"); + return (USER_CMD_RESULT_ERROR); + } + + if (pparse_value->dw_parameter[2]) + { + req_params.poll_interval = pparse_value->dw_parameter[2]; + } + if (pparse_value->dw_parameter[3]) + { + req_params.poll_timeout = pparse_value->dw_parameter[3]; + } + if (pparse_value->dw_parameter[4] >= 0xa && pparse_value->dw_parameter[4] <= 0xff) + { + mesh_node.frnd_rx_delay = pparse_value->dw_parameter[4]; + } + if (pparse_value->para_count >= 6 && pparse_value->dw_parameter[5] <= 0xff) + { + mesh_node.frnd_rx_widen = pparse_value->dw_parameter[5]; + } + return lpn_req(fn_index, net_key_index, + &req_params) == LPN_REQ_REASON_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_lpn_sub(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + uint16_t addr = pparse_value->dw_parameter[1]; + bool add_rm = pparse_value->dw_parameter[2]; + frnd_sub_list_add_rm(fn_index, &addr, 1, add_rm); + return (USER_CMD_RESULT_OK); +} + +static user_cmd_parse_result_t user_cmd_lpn_clear(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + lpn_clear(fn_index); + return (USER_CMD_RESULT_OK); +} +#endif + +#if MESH_RMT_PRO_CLIENT +static user_cmd_parse_result_t user_cmd_rmt_pro_scan(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t mode = 0; + if (pparse_value->para_count > 1) + { + mode = pparse_value->dw_parameter[1]; + } + switch (mode) + { + case 0: + RmtProClient_ScanStart(dst); + break; + case 1: + { + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + RmtProClient_ScanStartWithFilter(dst, dev_uuid); + } + break; + case 2: + RmtProClient_ScanUnproDeviceNum(dst, 3); + break; + default: + break; + } + + return (USER_CMD_RESULT_OK); +} +#endif + +static user_cmd_parse_result_t user_cmd_data_transmission_notify(user_cmd_parse_value_t + *pparse_value) +{ + uint8_t conn_id = pparse_value->dw_parameter[0]; + uint8_t data_len = pparse_value->para_count - 1; + uint8_t data[20]; + if (data_len > 20) + { + data_len = 20; + } + + for (uint8_t i = 0; i < data_len; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + + datatrans_server_notify(conn_id, data, data_len); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_generic_on_off_publish(user_cmd_parse_value_t *pparse_value) +{ + generic_on_off_t on_off = (generic_on_off_t)pparse_value->dw_parameter[0]; + mesh_model_p pmodel = generic_on_off_server_model.pmodel; + + pmodel->pub_params.pub_addr = 0xFEFF; + pmodel->pub_params.pub_ttl = 0x3F; + generic_on_off_publish(&generic_on_off_server_model, on_off); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_write(user_cmd_parse_value_t *pparse_value) +{ + uint8_t para_count = pparse_value->para_count; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + uint8_t data[75]; +#else + uint8_t data[18]; +#endif + + for (uint8_t i = 0; i < para_count - 3; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + datatrans_write(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[para_count - 2], para_count - 3, data, + pparse_value->dw_parameter[para_count - 1]); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_read(user_cmd_parse_value_t *pparse_value) +{ + datatrans_read(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const user_cmd_table_entry_t device_cmd_table[] = +{ + // mesh common cmd + MESH_COMMON_CMD, + TEST_CMD, + // device cmd + { + "nr", + "nr [mode]\n\r", + "node reset\n\r", + user_cmd_node_reset + }, + // prov + { + "pcs", + "pcs [public key oob] [static oob] [output size] [output action] [input size] [input action]\n\r", + "provision capability set\n\r", + user_cmd_prov_capa_set + }, +#if MESH_LPN + { + "lpninit", + "lpninit [fn_num]\n\r", + "low power node init\n\r", + user_cmd_lpn_init + }, + { + "lpndeinit", + "lpndeinit\n\r", + "low power node deinit\n\r", + user_cmd_lpn_deinit + }, + { + "lpnreq", + "lpnreq [fn_index] [net_key_index] [poll int(100ms)] [poll to(100ms)] [rx delay(ms)] [rx widen(ms)]\n\r", + "LPN request to estabish a friendship\n\r", + user_cmd_lpn_req + }, + { + "lpnsub", + "lpnsub [fn_index] [addr] [add/rm]\n\r", + "LPN subsript list add or rm\n\r", + user_cmd_lpn_sub + }, + { + "lpnclear", + "lpnclear [fn_index]\n\r", + "LPN clear\n\r", + user_cmd_lpn_clear + }, +#endif +#if MESH_RMT_PRO_CLIENT + { + "rmtproscan", + "rmtproscan [dst addr]\n\r", + "command remote server to scan\n\r", + user_cmd_rmt_pro_scan + }, +#endif + { + "dtn", + "dtn [conn_id] [value...]\n\r", + "data transmission notify\n\r", + user_cmd_data_transmission_notify + }, + { + "dtw", + "dtw [dst] [data...] [app_key_index] [ack] \n\r", + "data transmission write data\n\r", + user_cmd_datatrans_write + }, + { + "dtr", + "dtr [dst] [len] [app_key_index]\n\r", + "data transmission read data\n\r", + user_cmd_datatrans_read + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +const struct bt_mesh_api_hdl devicecmds[] = +{ + GEN_MESH_HANDLER(_node_reset) + GEN_MESH_HANDLER(_prov_capa_set) +#if MESH_LPN + GEN_MESH_HANDLER(_lpn_init) + GEN_MESH_HANDLER(_lpn_deinit) + GEN_MESH_HANDLER(_lpn_req) + GEN_MESH_HANDLER(_lpn_sub) + GEN_MESH_HANDLER(_lpn_clear) +#endif +#if MESH_FN + GEN_MESH_HANDLER(_fn_init) + GEN_MESH_HANDLER(_fn_deinit) +#endif + GEN_MESH_HANDLER(_data_transmission_notify) + GEN_MESH_HANDLER(_generic_on_off_publish) + GEN_MESH_HANDLER(_datatrans_write) + GEN_MESH_HANDLER(_datatrans_read) + GEN_MESH_HANDLER(_connect) + GEN_MESH_HANDLER(_disconnect) + GEN_MESH_HANDLER(_list) + GEN_MESH_HANDLER(_dev_info_show) +}; +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_cmd.h new file mode 100644 index 00000000..e4b41917 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_device_matter/bt_mesh_device_matter_cmd.h @@ -0,0 +1,36 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_DEVICE_MATTER_CMD_H_ +#define _BT_MESH_DEVICE_MATTER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_config.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_cmd_types.h" +#endif + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +extern const user_cmd_table_entry_t device_cmd_table[]; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern const struct bt_mesh_api_hdl devicecmds[]; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app.c new file mode 100644 index 00000000..085bab6b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app.c @@ -0,0 +1,2438 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.c +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +#include "trace_app.h" +#include "gap_wrapper.h" +#include "bt_flags.h" +#include "platform_opts.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_cmd.h" +#include "ping_app.h" +#include "provisioner_cmd.h" +#include "provision_provisioner.h" +#include "provision_client.h" +#include "proxy_client.h" +#include "platform_stdlib.h" +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_distributor_app.h" +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#include "bt_mesh_provisioner_api.h" +#endif +#include +#include "ble_central_at_cmd.h" +#include "ble_peripheral_at_cmd.h" +#include "gatt_builtin_services.h" +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "insert_write.h" +#endif +#include "bt_mesh_provisioner_ota_client_app.h" +#include "bt_mesh_provisioner_ota_client_link_mgr.h" +#include +#include "rtk_coex.h" + + +int bt_mesh_provisioner_ota_client_scan_state = 0; +int bt_mesh_provisioner_ota_client_peripheral_app_max_links = 0; +int bt_mesh_provisioner_ota_client_central_app_max_links = 0; + +T_GAP_DEV_STATE bt_mesh_provisioner_ota_client_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +T_APP_LINK bt_mesh_provisioner_ota_client_app_link_table[BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS]; + +T_CLIENT_ID bt_mesh_provisioner_ota_gcs_client_id; /**< General Common Services client client id*/ +T_CLIENT_ID bt_mesh_provisioner_ota_gaps_client_id; /**< Gaps Service client client id*/ +T_CLIENT_ID bt_mesh_provisioner_ota_bas_client_id; /**< Battery Service client client id*/ +T_CLIENT_ID bt_mesh_provisioner_ota_dfu_client_id; /**< DFU Service client client id*/ +T_CLIENT_ID bt_mesh_provisioner_ota_client_id; /**< OTA Service client client id*/ + +T_SERVER_ID bt_mesh_provisioner_ota_simp_srv_id; /**< Simple ble service id*/ + +uint8_t g_ota_mac_addr[6]; +uint32_t g_patch_version = 0; +uint32_t g_patch_ext_version = 0; +uint32_t g_app_version = 0; +T_OTA_DEVICE_INFO g_ota_device_info; + +bool prov_manual; +uint32_t prov_start_time; +prov_auth_value_type_t prov_auth_value_type; +bool mesh_initial_state = FALSE; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x14, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'P', 'R', 'O', 'V', '_', 'S', 'C', 'A', 'T', 'T', 'E', 'R', 'N', 'E', 'T', '_', 'O', 'T', 'A', +}; +int array_count_of_adv_data = sizeof(adv_data) / sizeof(adv_data[0]); + +extern uint8_t bt_mesh_provisioner_ota_client_le_adv_start_enable; +extern void bt_mesh_provisioner_ota_client_le_adv_start(void); +extern void bt_mesh_provisioner_ota_client_le_adv_stop(void); +extern int bt_mesh_provisioner_ota_client_start_ota(uint16_t subtype, void *arg); +#if defined(MESH_DFU) && MESH_DFU +extern void dfu_dist_handle_timeout(void); +#endif + + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_mesh_provisioner_ota_client_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + { + /* We handle user command informations from Data UART in this branch. */ + uint8_t data = io_msg.subtype; + mesh_user_cmd_collect(&data, sizeof(data), provisioner_cmd_table); + } + break; + case PING_TIMEOUT_MSG: + { + ping_handle_timeout(); + } + break; + case PING_APP_TIMEOUT_MSG: + { + ping_app_handle_timeout(); + } + break; + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; + + if (ble_central_app_handle_at_cmd(subtype, arg) != 1) { + ble_peripheral_app_handle_at_cmd(subtype, arg); + } + if (subtype == BT_ATCMD_OTA_START) { + bt_mesh_provisioner_ota_client_start_ota(BT_ATCMD_OTA_START, arg); + } + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 2) { + gap_sched_scan(false); + } else if (io_msg.subtype == 3) { + gap_sched_scan(true); + } +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + else if (io_msg.subtype == 4) {//user send write request during ota process + T_OTA_WRITE_MSG *ota_write_msg = (T_OTA_WRITE_MSG *)io_msg.u.buf; + uint8_t conn_id = ota_write_msg->conn_id; + uint16_t handle = ota_write_msg->handle; + user_write_request_example(conn_id, handle, bt_mesh_provisioner_ota_gcs_client_id); + } +#endif + } + break; + case IO_MSG_TYPE_ADV: + { + if (bt_mesh_provisioner_ota_client_le_adv_start_enable) { + uint8_t *padv_data = gap_sched_task_get(); + + if (NULL == padv_data) + { + printf("[BT Mesh Provisioner OTA Client] bt_mesh_provisioner_ota_client_adv_timer_handler allocate padv_data fail ! \n\r"); + break; + } + + gap_sched_task_p ptask = CONTAINER_OF(padv_data, gap_sched_task_t, adv_data); + + memcpy(padv_data, (uint8_t *)adv_data, sizeof(adv_data)); + + ptask->adv_len += array_count_of_adv_data; + ptask->adv_type = GAP_SCHED_ADV_TYPE_IND; + + gap_sched_try(ptask); + } + } + break; +#if defined(MESH_DFU) && MESH_DFU + case DFU_DIST_APP_TIMEOUT_MSG: + dfu_dist_handle_timeout(); + break; +#endif + default: + break; + } +} + + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_mesh_provisioner_ota_client_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_mesh_provisioner_ota_client_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + uint8_t net_key[16] = MESH_NET_KEY; + uint8_t net_key1[16] = MESH_NET_KEY1; + uint8_t app_key[16] = MESH_APP_KEY; + uint8_t app_key1[16] = MESH_APP_KEY1; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /** configure provisioner */ + mesh_node.node_state = PROV_NODE; + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + memcpy(&net_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&net_key1[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key1[10], bt_addr, sizeof(bt_addr)); + uint16_t net_key_index = net_key_add(0, net_key); + app_key_add(net_key_index, 0, app_key); + uint8_t net_key_index1 = net_key_add(1, net_key1); + app_key_add(net_key_index1, 1, app_key1); + mesh_model_bind_all_key(); + + /*stack ready*/ + bt_mesh_provisioner_ota_client_le_adv_start(); + } + } + + if (bt_mesh_provisioner_ota_client_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("\n\rGAP adv stoped: because connection created\n\r"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + printf("\n\rGAP adv stopped\n\r"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("\n\rGAP adv start\n\r"); + } + } + + if (bt_mesh_provisioner_ota_client_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + //data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + //data_uart_print("GAP scan start\r\n"); + } + } + + bt_mesh_provisioner_ota_client_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + T_GAP_CONN_INFO conn_info; + + if (conn_id >= BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("bt_mesh_provisioner_ota_client_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, bt_mesh_provisioner_ota_client_app_link_table[conn_id].conn_state, new_state, disc_cause); + + bt_mesh_provisioner_ota_client_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_mesh_provisioner_ota_client_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + + data_uart_debug("Disconnect conn_id %d\r\n", conn_id); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + goto next; + } + } else { + goto next; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_disconnect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_disconnect)); + goto next; + } + } else { + goto next; + } +#endif +next: + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + /*stack ready*/ + bt_mesh_provisioner_ota_client_le_adv_start(); + } + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + /* Clear all key information */ + //le_bond_clear_all_keys(); +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + /* if disconnected during ota process, then need queue out and free memory */ + disconnect_and_queue_out(conn_id); +#endif + dfu_client_disconnect_cb(conn_id); + } + + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + bt_mesh_provisioner_ota_client_central_app_max_links --; + } else if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + bt_mesh_provisioner_ota_client_peripheral_app_max_links --; + } + + memset(&bt_mesh_provisioner_ota_client_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_addr, + &bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_addr), bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_debug("Connected success conn_id %d\r\n", conn_id); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + } +#endif + + //get device role + if (le_get_conn_info(conn_id, &conn_info)){ + bt_mesh_provisioner_ota_client_app_link_table[conn_id].role = conn_info.role; + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) + bt_mesh_provisioner_ota_client_central_app_max_links ++; + else if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) + bt_mesh_provisioner_ota_client_peripheral_app_max_links ++; + } + + ////print bt address type + uint8_t local_bd_type; + //uint8_t features[8]; + uint8_t remote_bd_type; + le_get_conn_param(GAP_PARAM_CONN_LOCAL_BD_TYPE, &local_bd_type, conn_id); + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR_TYPE, &remote_bd_type, conn_id); + APP_PRINT_INFO3("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); + data_uart_debug("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, 251, 2120); +#endif + + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + bt_mesh_provisioner_ota_client_le_adv_stop(); + } +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + /* after connected, init flag and queue*/ + connect_and_init(conn_id); + } +#endif + } + break; + + default: + break; + + } + +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_debug("Pair success\r\n"); + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_debug("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +#if (RCU_SILENT_OTA == 1) + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + le_bond_pair(conn_id); + } +#endif +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_debug("\n\rbt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x \r\n", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + data_uart_debug("\n\rbt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x\r\n", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + data_uart_debug("\n\rbt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt update pending: conn_id %d\r\n", conn_id); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * sub_type of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_mesh_provisioner_ota_client_app_handle_gap_msg: sub_type %d", p_gap_msg->subtype); + mesh_inner_msg_t mesh_inner_msg; + mesh_inner_msg.type = MESH_BT_STATUS_UPDATE; + mesh_inner_msg.sub_type = p_gap_msg->subtype; + mesh_inner_msg.parm = p_gap_msg->u.param; + gap_sched_handle_bt_status_msg(&mesh_inner_msg); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + //static bool start = FALSE; + if (!mesh_initial_state) + { + mesh_initial_state = TRUE; + /** set device uuid according to bt address */ + uint8_t bt_addr[6]; + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + memcpy(dev_uuid, bt_addr, sizeof(bt_addr)); + device_uuid_set(dev_uuid); + /** configure provisioner */ + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + } + bt_mesh_provisioner_ota_client_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_mesh_provisioner_ota_client_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_mesh_provisioner_ota_client_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_mesh_provisioner_ota_client_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_mesh_provisioner_ota_client_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", + conn_id, display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", + conn_id, display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_debug("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_app_handle_gap_msg: unknown sub_type %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void bt_mesh_provisioner_ota_client_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("bt_mesh_provisioner_ota_client_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("bt_mesh_provisioner_ota_client_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); + //BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + char adv_type[20]; + char remote_addr_type[10]; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + + if (bt_mesh_provisioner_ota_client_scan_state) { + /* If you want to parse the scan info, please reference function ble_central_app_parse_scan_info. */ + sprintf(adv_type,"%s",(p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_UNDIRECTED)? "CON_UNDIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_DIRECTED)? "CON_DIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCANNABLE)? "SCANABLE_UNDIRCT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_NON_CONNECTABLE)? "NON_CONNECTABLE": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCAN_RSP)? "SCAN_RSP":"unknown"); + sprintf(remote_addr_type,"%s",(p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_PUBLIC)? "public": + (p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_RANDOM)? "random":"unknown"); + + BLE_PRINT("ADVType\t\t\t| AddrType\t|%s\t\t\t|rssi\n\r","BT_Addr"); + BLE_PRINT("%s\t\t%s\t"BD_ADDR_FMT"\t%d\n\r",adv_type,remote_addr_type,BD_ADDR_ARG(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->rssi); + + bt_mesh_provisioner_ota_client_app_parse_scan_info(p_data->p_le_scan_info); + } + gap_sched_handle_adv_report(p_data->p_le_scan_info); + break; + +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif + + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + gap_sched_adv_params_set_done(); + break; + /* + case GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: cause 0x%x", + p_data->le_cause.cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + break; + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; + + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; + */ +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + data_uart_print("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d\r\n", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +/** @defgroup CENTRAL_SRV_DIS GATT Services discovery and storage + * @brief GATT Services discovery and storage + * @{ + */ +/** + * @brief Discovery GATT services + * @param conn_id connection ID. + * @param start first call. true - first call this function after conncection, false - not first + * @retval None + */ +void bt_mesh_provisioner_ota_client_app_discov_services(uint8_t conn_id, bool start) +{ +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + request_in_process_flag[conn_id] = 1; //protect discovery service process +#endif + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].conn_state != GAP_CONN_STATE_CONNECTED) + { + //DBG_DIRECT("ota_central_client_app_discov_services conn_id %d not connected ", conn_id); + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_discov_services: conn_id %d not connected ", conn_id); + printf("bt_mesh_provisioner_ota_client_app_discov_services: conn_id %d not connected \n\r", conn_id); +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + request_in_process_flag[conn_id] = 0; +#endif + return; + } + if (start) + { +#if F_BT_GATT_SRV_HANDLE_STORAGE + bool is_disc = true; + T_APP_SRVS_HDL_TABLE app_srvs_table; + if (bt_mesh_provisioner_ota_client_app_load_srvs_hdl_table(&app_srvs_table) == 0) + { + if ((app_srvs_table.srv_found_flags != 0) && + (app_srvs_table.bd_type == bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_type) && + (memcmp(app_srvs_table.bd_addr, bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_addr, GAP_BD_ADDR_LEN) == 0)) + { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_discov_services: load from flash, srv_found_flags 0x%x", + app_srvs_table.srv_found_flags); + bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags = app_srvs_table.srv_found_flags; + if (app_srvs_table.srv_found_flags & APP_DISCOV_OTA_FLAG) + { + ota_client_set_hdl_cache(conn_id, app_srvs_table.ota_hdl_cache, sizeof(uint16_t) * HDL_OTA_CACHE_LEN); + } + if (app_srvs_table.srv_found_flags & APP_DISCOV_DFU_FLAG) + { + dfu_client_set_hdl_cache(conn_id, app_srvs_table.dfu_hdl_cache, sizeof(uint16_t) * HDL_DFU_CACHE_LEN); + } + if (app_srvs_table.srv_found_flags & APP_DISCOV_BAS_FLAG) + { + bas_set_hdl_cache(conn_id, app_srvs_table.bas_hdl_cache, sizeof(uint16_t) * HDL_BAS_CACHE_LEN); + } + is_disc = false; + } + } + else + { + APP_PRINT_ERROR0("bt_mesh_provisioner_ota_client_app_load_srvs_hdl_table: failed"); + } + + if (is_disc) + { + if (gaps_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_discov_services: discover gaps failed conn_id %d", conn_id); + } + } +#else + if (gaps_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_discov_services: discover gaps failed conn_id %d", conn_id); + printf("bt_mesh_provisioner_ota_client_app_discov_services: discover gaps failed conn_id %d\n\r", conn_id); + } +#endif + return; + } + + if ((bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags & APP_DISCOV_BAS_FLAG) == 0) + { + if (bas_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_discov_services: discover bas failed conn_id %d", conn_id); + printf("bt_mesh_provisioner_ota_client_app_discov_services: discover bas failed conn_id %d\n\r", conn_id); + } + } + else if ((bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags & APP_DISCOV_OTA_FLAG) == 0) + { + if (ota_client_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_discov_services: discover ota failed conn_id %d", conn_id); + printf("bt_mesh_provisioner_ota_client_app_discov_services: discover ota failed conn_id %d\n\r", conn_id); + } + } + else if ((bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags & APP_DISCOV_DFU_FLAG) == 0) + { + if (dfu_client_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_discov_services: discover dfu failed conn_id %d", conn_id); + printf("bt_mesh_provisioner_ota_client_app_discov_services: discover dfu failed conn_id %d\n\r", conn_id); + } + } + else + { + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_app_discov_services: discover complete, conn_id %d, srv_found_flags 0x%x", + conn_id, bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags); + printf("bt_mesh_provisioner_ota_client_app_discov_services: discover complete, conn_id %d, srv_found_flags 0x%x\n\r", + conn_id, bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags); +#if F_BT_GATT_SRV_HANDLE_STORAGE + if (bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags != 0) + { + T_APP_SRVS_HDL_TABLE app_srvs_table; + memset(&app_srvs_table, 0, sizeof(T_APP_SRVS_HDL_TABLE)); + app_srvs_table.bd_type = bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_type; + app_srvs_table.srv_found_flags = bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags; + memcpy(app_srvs_table.bd_addr, bt_mesh_provisioner_ota_client_app_link_table[conn_id].bd_addr, GAP_BD_ADDR_LEN); + ota_client_get_hdl_cache(conn_id, app_srvs_table.ota_hdl_cache, + sizeof(uint16_t) * HDL_OTA_CACHE_LEN); + dfu_client_get_hdl_cache(conn_id, app_srvs_table.dfu_hdl_cache, + sizeof(uint16_t) * HDL_DFU_CACHE_LEN); + bas_get_hdl_cache(conn_id, app_srvs_table.bas_hdl_cache, sizeof(uint16_t) * HDL_BAS_CACHE_LEN); + if (bt_mesh_provisioner_ota_client_app_save_srvs_hdl_table(&app_srvs_table) != 0) + { + APP_PRINT_ERROR0("bt_mesh_provisioner_ota_client_app_save_srvs_hdl_table: failed"); + } + } +#endif + } + + return; +} + +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void bt_mesh_provisioner_ota_client_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + data_uart_debug("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + data_uart_debug("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + data_uart_debug("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + data_uart_debug("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + data_uart_debug("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + data_uart_debug("Invalid disc type: conn_id %d, discov_type %d\n\r", + conn_id, discov_result.discov_type); + break; + } +} + +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_mesh_provisioner_ota_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_mesh_provisioner_ota_client_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_debug("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\n\r", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_debug("READ VALUE: "); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_debug("\n\r"); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_debug("WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if (p_gcs_cb_data->cb_content.write_result.type == GATT_WRITE_TYPE_REQ) + { + request_in_process_flag[conn_id] = 0; + if_queue_out_and_send(conn_id); + } +#endif + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("INDICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("INDICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("NOTIFICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + + } + break; + default: + break; + } + } + + return result; +} + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + else if (client_id == prov_client_id) + { + prov_client_cb_data_t *pcb_data = (prov_client_cb_data_t *)p_data; + switch (pcb_data->cb_type) + { + case PROV_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case PROV_DISC_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + data_uart_debug("Prov service discovery end!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + case PROV_DISC_FAIL: + /* Discovery Request failed. */ + data_uart_debug("Prov service discovery fail!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + case PROV_DISC_NOT_FOUND: + /* Discovery Request failed. */ + data_uart_debug("Prov service not found!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + default: + break; + } + break; + case PROV_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case PROV_READ_DATA_OUT_CCCD: + if (pcb_data->cb_content.read_result.cause == 0) + { + data_uart_debug("Prov data out cccd = %d.\r\n", + pcb_data->cb_content.read_result.data.prov_data_out_cccd); + } + break; + default: + break; + } + break; + case PROV_CLIENT_CB_TYPE_WRITE_RESULT: + break; + default: + break; + } + } + else if (client_id == proxy_client_id) + { + proxy_client_cb_data_t *pcb_data = (proxy_client_cb_data_t *)p_data; + switch (pcb_data->cb_type) + { + case PROXY_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case PROXY_DISC_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + data_uart_debug("Proxy service discovery end!\r\n"); + break; + case PROXY_DISC_FAIL: + /* Discovery Request failed. */ + data_uart_debug("Proxy service discovery fail!\r\n"); + break; + case PROXY_DISC_NOT_FOUND: + /* Discovery Request failed. */ + data_uart_debug("Proxy service not found!\r\n"); + break; + default: + break; + } + break; + case PROXY_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case PROXY_READ_DATA_OUT_CCCD: + if (pcb_data->cb_content.read_result.cause == 0) + { + data_uart_debug("Proxy data out cccd = %d.\r\n", + pcb_data->cb_content.read_result.data.proxy_data_out_cccd); + } + break; + default: + break; + } + break; + case PROXY_CLIENT_CB_TYPE_WRITE_RESULT: + break; + default: + break; + } + } + else if (client_id == bt_mesh_provisioner_ota_gaps_client_id) + { + T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data; + switch (p_gaps_cb_data->cb_type) { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_gaps_cb_data->cb_content.disc_state) { + case DISC_GAPS_DONE: + bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_GAPS_FLAG; + bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags |= APP_DISCOV_GAPS_FLAG; + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, false); + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: discover gaps procedure done."); + break; + case DISC_GAPS_FAILED: + bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_GAPS_FLAG; + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, false); + /* Discovery Request failed. */ + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: discover gaps request failed."); + break; + default: + break; + } + break; + + default: + break; + } + } + else if (client_id == bt_mesh_provisioner_ota_bas_client_id) + { + T_BAS_CLIENT_CB_DATA *p_bas_cb_data = (T_BAS_CLIENT_CB_DATA *)p_data; + switch (p_bas_cb_data->cb_type) { + case BAS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_bas_cb_data->cb_content.disc_state) { + case DISC_BAS_DONE: + /* Discovery BAS procedure successfully done. */ + bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_BAS_FLAG; + bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags |= APP_DISCOV_BAS_FLAG; + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: discover bas procedure done"); + break; + case DISC_BAS_FAILED: + /* Discovery Request failed. */ + bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_BAS_FLAG; + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: discover bas procedure failed"); + break; + default: + break; + } + break; + + default: + break; + } + } + else if (client_id == bt_mesh_provisioner_ota_client_id) + { + T_OTA_CLIENT_CB_DATA *p_ota_client_cb_data = (T_OTA_CLIENT_CB_DATA *)p_data; + uint16_t read_value_size = p_ota_client_cb_data->cb_content.read_result.data.value_size; + uint8_t *p_read_value = p_ota_client_cb_data->cb_content.read_result.data.p_value; + switch (p_ota_client_cb_data->cb_type) { + case OTA_CLIENT_CB_TYPE_DISC_STATE: + switch (p_ota_client_cb_data->cb_content.disc_state) { + case DISC_OTA_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_OTA_FLAG; + bt_mesh_provisioner_ota_client_app_link_table[conn_id].srv_found_flags |= APP_DISCOV_OTA_FLAG; + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: discover ota procedure done."); + + //start read ota target device info + ota_client_read_by_handle(conn_id, OTA_READ_DEVICE_MAC); + //app_discov_services(conn_id, false); //start find dfu service + + break; + case DISC_OTA_FAILED: + /* Discovery Request failed. */ + bt_mesh_provisioner_ota_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_OTA_FLAG; + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: discover ota request failed."); + break; + default: + break; + } + break; + case OTA_CLIENT_CB_TYPE_READ_RESULT: + switch (p_ota_client_cb_data->cb_content.read_result.type) { + case OTA_READ_DEVICE_MAC: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) { + if (read_value_size == sizeof(g_ota_mac_addr)) { + memcpy(g_ota_mac_addr, p_read_value, read_value_size); + LE_ARRAY_TO_UINT32(g_patch_version, p_read_value); + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA Target MAC ADDR=%s", TRACE_BDADDR(g_ota_mac_addr)); + ota_client_read_by_handle(conn_id, OTA_READ_DEVICE_INFO); + } else { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA_READ_DEVICE_MAC invalid read value size=%d", + read_value_size); + } + } else { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_READ_DEVICE_MAC failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + } + break; + case OTA_READ_PATCH_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) { + if (read_value_size == sizeof(g_patch_version)) { + LE_ARRAY_TO_UINT32(g_patch_version, p_read_value); + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA Target patch version=0x%x", g_patch_version); + } else { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA_READ_PATCH_VER invalid read value size=%d", + read_value_size); + } + } else { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_READ_PATCH_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_APP_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) { + if (read_value_size == sizeof(g_app_version)) { + LE_ARRAY_TO_UINT32(g_app_version, p_read_value); + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA Target app version=0x%x", g_app_version); + } else { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA_READ_APP_VER invalid read value size=%d", + read_value_size); + } + } else { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_READ_APP_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_PATCH_EXT_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) { + if (read_value_size == sizeof(g_patch_ext_version)) { + LE_ARRAY_TO_UINT32(g_patch_ext_version, p_read_value); + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA Target patch ext version=0x%x", g_patch_ext_version); + } else { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA_READ_PATCH_EXT_VER invalid read value size=%d", + read_value_size); + } + } else { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_READ_PATCH_EXT_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_DEVICE_INFO: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) { + if (read_value_size == sizeof(g_ota_device_info)) { + memcpy((uint8_t *)&g_ota_device_info, p_read_value, read_value_size); + APP_PRINT_INFO4("bt_mesh_provisioner_ota_client_app_client_callback: aesflg=%d, aesmode=%d,buffercheck=%d, maxbuffersize=%d", + g_ota_device_info.mode.aesflg, g_ota_device_info.mode.aesmode, + g_ota_device_info.mode.buffercheck, g_ota_device_info.maxbuffersize); + g_dfu_ctx.mode.value = g_ota_device_info.mode.value; + g_dfu_ctx.maxbuffersize = g_ota_device_info.maxbuffersize; + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, false); //start find dfu service + } else { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: OTA_READ_DEVICE_INFO invalid read value size=%d", + read_value_size); + } + } else { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_READ_DEVICE_INFO failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_IMG_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) { + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: g_app_version 0x%x", g_app_version); + } else { + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_READ_IMG_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + + default: + break; + } + break; + case OTA_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_ota_client_cb_data->cb_content.write_result.type) { + case OTA_WRITE_CMD: + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_WRITE_CMD write result 0x%x", + p_ota_client_cb_data->cb_content.write_result.cause); + + break; + case OTA_WRITE_TEST_MODE: + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_WRITE_TEST_MODE write result 0x%x", + p_ota_client_cb_data->cb_content.write_result.cause); + break; + case OTA_WRITE_IMG_COUNTER: + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_client_callback: Type OTA_WRITE_IMG_COUNTER write result 0x%x", + p_ota_client_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + case OTA_CLIENT_CB_TYPE_INVALID: + APP_PRINT_ERROR0("BT_OTA_CENTRAL_CLIENT_CB_TYPE_INVALID!"); + } + } + else if (client_id == bt_mesh_provisioner_ota_dfu_client_id) + { + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback: dfu_client."); + T_DFU_CB_MSG *pmsg = (T_DFU_CB_MSG *)p_data; + switch (pmsg->type) { + case DFU_CB_START: + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback--dfu_client_start."); + //dfu_client_start(); //just notify app do something + break; + case DFU_CB_FAIL: + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback--dfu_client_fail."); + //dfu_client_fail(); + break; + case DFU_CB_END: + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_client_callback--dfu_client_end."); + //dfu_client_end(); + break; + default: + break; + } + } + + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + data_uart_debug("\n\rPROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE success\r\n"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE failed\r\n"); + } + break; + + default: + break; + } + } + else if (service_id == bt_mesh_provisioner_ota_simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V3_ENABLE\r\n"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V3_DISABLE\r\n"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V4_ENABLE\r\n"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V4_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + data_uart_debug("SIMP_READ_V1: value 0x%02x 0x%02x\r\n", value[0], value[1]); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_debug("SIMP_WRITE_V2: write type %d, len %d\r\n", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_debug("SIMP_WRITE_V2: value "); + for(int i = 0; i < p_simp_cb_data->msg_data.write.len; i ++){ + data_uart_debug("0x%02x ", *(p_simp_cb_data->msg_data.write.p_value + i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + + return app_result; +} + +/****************************************************************** + * @fn device_info_cb + * @brief device_info_cb callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return void + */ +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + if (!dev_info_show_flag) + { + return; + } + data_uart_debug("bt addr=0x%02x%02x%02x%02x%02x%02x type=%d rssi=%d ", bt_addr[5], bt_addr[4], + bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0], bt_addr_type, rssi); + switch (pinfo->type) + { + case DEVICE_INFO_UDB: + data_uart_debug("udb="); + data_uart_dump(pinfo->pbeacon_udb->dev_uuid, 16); + break; + case DEVICE_INFO_PROV_ADV: + data_uart_debug("prov="); + data_uart_dump(pinfo->pservice_data->provision.dev_uuid, 16); + break; + case DEVICE_INFO_PROXY_ADV: + data_uart_debug("proxy="); + data_uart_dump((uint8_t *)&pinfo->pservice_data->proxy, pinfo->len); + break; + default: + break; + } +} + +/****************************************************************** + * @fn prov_cb + * @brief Provisioning callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return the operation result + */ +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data) +{ + APP_PRINT_INFO1("prov_cb: type = %d", cb_type); + + switch (cb_type) + { + case PROV_CB_TYPE_PB_ADV_LINK_STATE: + switch (cb_data.pb_generic_cb_type) + { + case PB_GENERIC_CB_LINK_OPENED: + data_uart_debug("PB-ADV Link Opened!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_pb_adv_con), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_pb_adv_con)); + } +#endif + break; + case PB_GENERIC_CB_LINK_OPEN_FAILED: + data_uart_debug("PB-ADV Link Open Failed!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_pb_adv_con), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_pb_adv_con)); + } +#endif + break; + case PB_GENERIC_CB_LINK_CLOSED: + data_uart_debug("PB-ADV Link Closed!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); + break; + default: + break; + } + break; + case PROV_CB_TYPE_PATH_CHOOSE: + { + if (prov_manual) + { + /* use cmd "authpath" to select oob/no oob public key and no oob/static oob/input oob/output oob auth data according to the device capabilities */ + prov_capabilities_p pprov_capabilities = cb_data.pprov_capabilities; + data_uart_debug("prov capabilities: en-%d al-%d pk-%d so-%d os-%d oa-%d is-%d ia-%d\r\n", + pprov_capabilities->element_num, pprov_capabilities->algorithm, + pprov_capabilities->public_key, pprov_capabilities->static_oob, + pprov_capabilities->output_oob_size, pprov_capabilities->output_oob_action, + pprov_capabilities->input_oob_size, pprov_capabilities->input_oob_action); + } + else + { + /* select no oob public key and no oob auth data as default provision method */ + prov_start_t prov_start; + memset(&prov_start, 0, sizeof(prov_start_t)); + prov_path_choose(&prov_start); + } + } + break; + case PROV_CB_TYPE_PUBLIC_KEY: + { + APP_PRINT_INFO0("prov_cb: get the public key from the device"); + uint8_t public_key[64] = {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79}; + prov_device_public_key_set(public_key); + } + break; + case PROV_CB_TYPE_AUTH_DATA: + { + prov_start_p pprov_start = cb_data.pprov_start; + prov_auth_value_type = prov_auth_value_type_get(pprov_start); + /* use cmd to set auth data */ + data_uart_debug("auth method=%d[nsoi] action=%d size=%d type=%d[nbNa]\r\n>", + pprov_start->auth_method, + pprov_start->auth_action, pprov_start->auth_size, prov_auth_value_type); + //uint8_t auth_data[16] = {1}; + switch (pprov_start->auth_method) + { + case PROV_AUTH_METHOD_STATIC_OOB: + //prov_auth_value_set(auth_data, sizeof(auth_data)); + APP_PRINT_INFO0("prov_cb: Please share the oob data with the device"); + break; + case PROV_AUTH_METHOD_OUTPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.output_oob_size); + APP_PRINT_INFO2("prov_cb: Please input the oob data provided by the device, output size = %d, action = %d", + pprov_start->auth_size.output_oob_size, pprov_start->auth_action.output_oob_action); + break; + case PROV_AUTH_METHOD_INPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.input_oob_size); + APP_PRINT_INFO2("prov_cb: Please output the oob data to the device, input size = %d, action = %d", + pprov_start->auth_size.input_oob_size, pprov_start->auth_action.input_oob_action); + break; + default: + break; + } + } + break; + case PROV_CB_TYPE_COMPLETE: + { + prov_data_p pprov_data = cb_data.pprov_data; + data_uart_debug("Has provisioned device with addr 0x%04x in %dms!\r\n", pprov_data->unicast_address, + plt_time_read_ms() - prov_start_time); + + /* the spec requires to disconnect, but you can remove it as you like! :) */ + prov_disconnect(PB_ADV_LINK_CLOSE_SUCCESS); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + printf("\r\n %s() pprov_data->unicast_address = %x\r\n",__func__,pprov_data->unicast_address); + if (bt_mesh_indication(GEN_MESH_CODE(_prov), BT_MESH_USER_CMD_SUCCESS, (void *)&pprov_data->unicast_address) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov)); + } +#endif + } + break; + case PROV_CB_TYPE_FAIL: + data_uart_debug("provision fail, type=%d!\r\n", cb_data.prov_fail.fail_type); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov)); + } +#endif + + break; + case PROV_CB_TYPE_PROV: + /* stack ready */ + data_uart_debug("ms addr: 0x%04x\r\n>", mesh_node.unicast_addr); + break; + default: + break; + } + return true; +} + +/****************************************************************** + * @fn fn_cb + * @brief fn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"establishing with lpn 0x%04x\r\n", "no poll from 0x%04x\r\n", "established with lpn 0x%04x\r\n", "lpn 0x%04x lost\r\n"}; + data_uart_debug(string[type], lpn_addr); + if (type == FN_CB_TYPE_ESTABLISH_SUCCESS || type == FN_CB_TYPE_FRND_LOST) + { + user_cmd_time(NULL); + } +} + +/****************************************************************** + * @fn hb_cb + * @brief heartbeat callbacks are handled in this function. + * + * @param type + * @param pdata + * @return void + */ +void hb_cb(hb_data_type_t type, void *pargs) +{ + switch (type) + { + case HB_DATA_PUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat publish timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat publish timer stop\r\n"); + } + } + break; + case HB_DATA_SUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat subscription timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat subscription timer stop\r\n"); + } + } + break; + case HB_DATA_PUB_COUNT_UPDATE: + { + hb_data_pub_count_update_t *pdata = pargs; + data_uart_debug("heartbeat publish count update: %d\r\n", pdata->count); + } + break; + case HB_DATA_SUB_PERIOD_UPDATE: + { + hb_data_sub_period_update_t *pdata = pargs; + data_uart_debug("heartbeat subscription period update: %d\r\n", pdata->period); + } + break; + case HB_DATA_SUB_RECEIVE: + { + hb_data_sub_receive_t *pdata = pargs; + data_uart_debug("receive heartbeat: src = %d, init_ttl = %d, features = %d-%d-%d-%d, ttl = %d\r\n", + pdata->src, pdata->init_ttl, pdata->features.relay, pdata->features.proxy, + pdata->features.frnd, pdata->features.lpn, pdata->ttl); + } + break; + default: + break; + } +} + +void bt_mesh_provisioner_ota_client_app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_INFO1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} + +#if F_BT_GAPS_CHAR_WRITEABLE +/** @defgroup SCATTERNET_GAPS_WRITE GAP Service Callback Handler + * @brief Use @ref F_BT_GAPS_CHAR_WRITEABLE to open + * @{ + */ +/** + * @brief All the BT GAP service callback events are handled in this function + * @param[in] service_id Profile service ID + * @param[in] p_para Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_gap_service_callback(T_SERVER_ID service_id, void *p_para) +{ + (void) service_id; + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_gap_service_callback: conn_id = %d msg_type = %d\n", p_gap_data->conn_id, + p_gap_data->msg_type); + APP_PRINT_INFO2("bt_mesh_provisioner_ota_client_gap_service_callback: len = 0x%x,opcode = %d\n", p_gap_data->msg_data.len, + p_gap_data->msg_data.opcode); + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) + { + switch (p_gap_data->msg_data.opcode) + { + case GAPS_WRITE_DEVICE_NAME: + { + T_LOCAL_NAME device_name; + memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); + device_name.local_name[p_gap_data->msg_data.len] = 0; + //data_uart_print("GAPS_WRITE_DEVICE_NAME:device_name = %s \n\r",device_name.local_name); + flash_save_local_name(&device_name); + } + break; + + case GAPS_WRITE_APPEARANCE: + { + uint16_t appearance_val; + T_LOCAL_APPEARANCE appearance; + + LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); + appearance.local_appearance = appearance_val; + //data_uart_print("GAPS_WRITE_APPEARANCE:appearance = %s \n\r",appearance.local_appearance); + flash_save_local_appearance(&appearance); + } + break; + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_ota_client_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + //data_uart_print("bt_mesh_provisioner_ota_client_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + break; + } + } + return result; +} +/** @} */ +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app.h new file mode 100644 index 00000000..3ba65d2e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app.h @@ -0,0 +1,114 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.h +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _BT_MESH_PROVISIONER_OTA_CLIENT_APP__ +#define _BT_MESH_PROVISIONER_OTA_CLIENT_APP__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mesh_api.h" +#include +#include +#include "app_msg.h" +#include "bt_mesh_provisioner_ota_client_app_flags.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_provisioner_api.h" +#endif + +/*============================================================================* + * Variables + *============================================================================*/ + +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] + +extern T_CLIENT_ID bt_mesh_provisioner_ota_gcs_client_id; /**< General Common Services client client id*/ +extern T_CLIENT_ID bt_mesh_provisioner_ota_gaps_client_id; /**< Gaps Service client client id*/ +extern T_CLIENT_ID bt_mesh_provisioner_ota_bas_client_id; /**< Battery Service client client id*/ +extern T_CLIENT_ID bt_mesh_provisioner_ota_dfu_client_id; /**< DFU Service client client id*/ +extern T_CLIENT_ID bt_mesh_provisioner_ota_client_id; /**< OTA Service client client id*/ + +extern T_SERVER_ID bt_mesh_provisioner_ota_simp_srv_id; /**< Simple ble service id*/ + +extern bool mesh_initial_state; +extern T_GAP_DEV_STATE bt_mesh_provisioner_ota_client_gap_dev_state; + +extern const uint8_t adv_data[]; +extern int array_count_of_adv_data; + +extern bool dev_info_show_flag; +extern bool prov_manual; +extern uint32_t prov_start_time; + +extern int bt_mesh_provisioner_ota_client_central_app_max_links; +extern int bt_mesh_provisioner_ota_client_peripheral_app_max_links; +/*============================================================================* + * Functions + *============================================================================*/ +void bt_mesh_provisioner_ota_client_app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_provisioner_ota_client_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +T_APP_RESULT bt_mesh_provisioner_ota_client_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_ota_client_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#if F_BT_GAPS_CHAR_WRITEABLE +extern T_APP_RESULT bt_mesh_provisioner_ota_client_gap_service_callback(T_SERVER_ID service_id, void *p_para); +#endif + +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo); +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +void hb_cb(hb_data_type_t type, void *pargs); +void bt_mesh_provisioner_ota_client_app_vendor_callback(uint8_t cb_type, void *p_cb_data); + +#ifdef __cplusplus +} +#endif + +#endif /* _MESH_APPLICATION__S */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_flags.h new file mode 100644 index 00000000..77c9aa9c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_flags.h @@ -0,0 +1,54 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_PROVISIONER_OTA_CLIENT_APP_FLAGS_H_ +#define _BT_MESH_PROVISIONER_OTA_CLIENT_APP_FLAGS_H_ + +#include "platform_opts_bt.h" + +#include + +/** + * @addtogroup MESH_APP_CONFIG + * @{ + */ + +/** + * @defgroup Mesh_App_Config Mesh App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ +#if defined(CONFIG_PLATFORM_8721D) +#define BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS 4 +#define BT_MESH_PROVISIONER_OTA_CLIENT_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BT_MESH_PROVISIONER_OTA_CLIENT_CENTRAL_APP_MAX_LINKS 3 //for max master link num +#elif defined(CONFIG_PLATFORM_8710C) +#define BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS 2 +#define BT_MESH_PROVISIONER_OTA_CLIENT_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BT_MESH_PROVISIONER_OTA_CLIENT_CENTRAL_APP_MAX_LINKS 1 //for max master link num +#endif +/** @brief Config the discovery table number of gcs_client */ +#define BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_DISCOV_TABLE_NUM 40 + +/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/ +#define F_BT_AIRPLANE_MODE_SUPPORT 0 + +/** @brief Config GATT services storage: 0-Not save, 1-Save to flash + * If configure to 1, the GATT services discovery results will save to the flash. */ +#define F_BT_GATT_SRV_HANDLE_STORAGE 0 + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_main.c new file mode 100644 index 00000000..0d1c1a13 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_main.c @@ -0,0 +1,597 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "health.h" +#include "ping.h" +#include "ping_app.h" +#include "tp.h" +#include "generic_client_app.h" +#include "light_client_app.h" +#include "provision_client.h" +#include "proxy_client.h" +#include "datatrans_app.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#include "wifi_constants.h" +#include +#include "bt_mesh_provisioner_ota_client_app.h" +#include "bt_mesh_provisioner_ota_client_app_flags.h" +#if defined(MESH_RPR) && MESH_RPR +#include "rmt_prov_client_app.h" +#endif +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_distributor_app.h" +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_provisioner_api.h" +#endif +#include +#include "trace_uart.h" +#include +#include +#include +#include "rtk_coex.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +#define COMPANY_ID 0x005D +#define PRODUCT_ID 0x0000 +#define VERSION_ID 0x0000 + +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 400 + +/** @brief Default scan interval (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_INTERVAL 0x520 +/** @brief Default scan window (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_WINDOW 0x520 + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; +plt_timer_t bt_mesh_provisioner_ota_client_adv_timer = NULL; +uint8_t bt_mesh_provisioner_ota_client_le_adv_start_enable = 0; +uint16_t bt_mesh_provisioner_ota_client_adv_interval = 352; + +extern void rtw_set_timer(_timer *ptimer,u32 delay_time); +extern void rtw_init_timer(_timer *ptimer, void *adapter, TIMER_FUN pfunc,void* cntx, const char *name); + +void bt_mesh_provisioner_ota_client_adv_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + uint16_t adv_interval = bt_mesh_provisioner_ota_client_adv_interval * 625 / 1000; + + io_msg.type = IO_MSG_TYPE_ADV; + + if (os_msg_send(bt_mesh_provisioner_ota_client_io_queue_handle, &io_msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) + { + } + if (bt_mesh_provisioner_ota_client_le_adv_start_enable) { + plt_timer_change_period(bt_mesh_provisioner_ota_client_adv_timer, adv_interval, 0xFFFFFFFF); + } +} + +void bt_mesh_provisioner_ota_client_le_adv_start(void) +{ + uint16_t adv_interval = bt_mesh_provisioner_ota_client_adv_interval * 625 / 1000; + + bt_mesh_provisioner_ota_client_le_adv_start_enable = 1; + plt_timer_change_period(bt_mesh_provisioner_ota_client_adv_timer, adv_interval, 0xFFFFFFFF); +} + +void bt_mesh_provisioner_ota_client_le_adv_stop(void) +{ + bt_mesh_provisioner_ota_client_le_adv_start_enable = 0; +} + +/****************************************************************** + * @fn Initial gap parameters + * @brief Initialize peripheral and gap bond manager related parameters + * + * @return void + */ +void bt_mesh_provisioner_ota_client_stack_init(void) +{ + /** set ble stack log level, disable nonsignificant log */ + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + // log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_ERROR, 0); + // log_module_trace_set(TRACE_MODULE_SNOOP, TRACE_LEVEL_ERROR, 0); + + /** set mesh stack log level, default all on, disable the log of level LEVEL_TRACE */ + uint32_t module_bitmap[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(TRACE_LEVEL_TRACE, module_bitmap); + + /** mesh stack needs rand seed */ + plt_srand(platform_random(0xffffffff)); + + /** configure provisioning parameters */ + prov_params_set(PROV_PARAMS_CALLBACK_FUN, (void *)prov_cb, sizeof(prov_cb_pf)); + + /** config node parameters */ + mesh_node_features_t features = + { + .role = MESH_ROLE_PROVISIONER, + .relay = 1, + .proxy = 1, + .fn = 1, + .lpn = 2, + .prov = 1, + .udb = 0, + .snb = 1, + .bg_scan = 1, + .flash = 1, + .flash_rpl = 1 + }; + + mesh_node_cfg_t node_cfg = + { + .dev_key_num = 20, + .net_key_num = 10, + .app_key_num = 3, + .vir_addr_num = 3, + .rpl_num = 20, + .sub_addr_num = 5, + .proxy_num = 1 + }; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + features.relay = 0; + features.flash_rpl = 0; + node_cfg.dev_key_num = 50; + node_cfg.rpl_num = 50; + node_cfg.sub_addr_num = 0; +#endif + + node_cfg.proxy_interval = 5; + mesh_node_cfg(features, &node_cfg); + mesh_node.net_trans_count = 6; + mesh_node.relay_retrans_count = 2; + mesh_node.trans_retrans_count = 4; + mesh_node.ttl = 5; + + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /*Increase the number of ADV caches reserved for the network layer*/ + uint8_t task_num = 25; + gap_sched_params_set(GAP_SCHED_PARAMS_TASK_NUM, &task_num, sizeof(task_num)); + + /** create elements and register models */ + mesh_element_create(GATT_NS_DESC_UNKNOWN); + mesh_element_create(GATT_NS_DESC_UNKNOWN); + cfg_client_reg(); + generic_client_models_init(); + + tp_control_reg(tp_reveive); + ping_control_reg(ping_app_ping_cb, pong_receive); + trans_ping_pong_init(ping_app_ping_cb, pong_receive); + light_client_models_init(); + datatrans_model_init(); + +#if defined(MESH_DFU) && MESH_DFU + dfu_dist_models_init(); +#endif +#if defined(MESH_RPR) && MESH_RPR + rmt_prov_client_init(); +#endif + + bt_mesh_provisioner_ota_client_adv_timer = plt_timer_create("bt_mesh_provisioner_ota_client_adv_timer", 0xFFFFFFFF, FALSE, NULL, bt_mesh_provisioner_ota_client_adv_timer_handler); + if (!bt_mesh_provisioner_ota_client_adv_timer) { + printf("[BT Mesh Provisioner OTA Client] Create adv timer failed\n\r"); + } + + compo_data_page0_header_t compo_data_page0_header = {COMPANY_ID, PRODUCT_ID, VERSION_ID}; + compo_data_page0_gen(&compo_data_page0_header); + + /** init mesh stack */ + mesh_init(); + + /** register udb/provision adv/proxy adv callback */ + device_info_cb_reg(device_info_cb); + hb_init(hb_cb); + +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_mesh_provisioner_ota_client_app_le_gap_init(void) +{ + uint16_t scan_window = 0x100; /* 160ms */ + uint16_t scan_interval = 0x120; /* 180ms */ + + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "PROV_SCATTERNET_OTA"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* Scan parameters */ + //uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + //uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + //uint16_t scan_window = DEFAULT_SCAN_WINDOW; + //uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + //uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, array_count_of_adv_data, (void *)adv_data); + // le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + +#if 0 + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_USE_STATIC_RANDOM_ADDR + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (ble_scatternet_app_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + ble_scatternet_app_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer +#if 0 + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#endif +#endif +#if F_BT_GAPS_CHAR_WRITEABLE + uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; + uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; + T_LOCAL_APPEARANCE appearance_local; + T_LOCAL_NAME local_device_name; + if (flash_load_local_appearance(&appearance_local) == 0) + { + gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance); + } + + if (flash_load_local_name(&local_device_name) == 0) + { + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name); + } + gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop); + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop); + gatt_register_callback((void*)bt_mesh_provisioner_ota_client_gap_service_callback); +#endif + } + + vendor_cmd_init(bt_mesh_provisioner_ota_client_app_vendor_callback); + /* register gap message callback */ + le_register_app_cb(bt_mesh_provisioner_ota_client_app_gap_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_mesh_provisioner_ota_client_app_le_profile_init(void) +{ + server_init(MESH_GATT_SERVER_COUNT + 2); + /* Add Server Module */ + bt_mesh_provisioner_ota_simp_srv_id = simp_ble_service_add_service((void *)bt_mesh_provisioner_ota_client_app_profile_callback); + /* Register Server Callback */ + server_register_app_cb(bt_mesh_provisioner_ota_client_app_profile_callback); + + client_init(MESH_GATT_CLIENT_COUNT + 5); + /* Add Client Module */ + prov_client_add(bt_mesh_provisioner_ota_client_app_client_callback); + proxy_client_add(bt_mesh_provisioner_ota_client_app_client_callback); + bt_mesh_provisioner_ota_gcs_client_id = gcs_add_client(bt_mesh_provisioner_ota_client_gcs_client_callback, BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS, + BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_DISCOV_TABLE_NUM); + bt_mesh_provisioner_ota_gaps_client_id = gaps_add_client(bt_mesh_provisioner_ota_client_app_client_callback, BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); + bt_mesh_provisioner_ota_bas_client_id = bas_add_client(bt_mesh_provisioner_ota_client_app_client_callback, BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); + bt_mesh_provisioner_ota_client_id = ota_add_client(bt_mesh_provisioner_ota_client_app_client_callback, BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); + bt_mesh_provisioner_ota_dfu_client_id = dfu_add_client(bt_mesh_provisioner_ota_client_app_client_callback, BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); + /* Register Client Callback--App_ClientCallback to handle events from Profile Client layer. */ + client_register_general_client_cb(bt_mesh_provisioner_ota_client_app_client_callback); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void bt_mesh_provisioner_ota_client_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_mesh_provisioner_ota_client_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void bt_mesh_provisioner_ota_client_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void bt_mesh_provisioner_ota_client_task_init(void) +{ + bt_mesh_provisioner_ota_client_app_task_init(); +} + +void bt_mesh_provisioner_ota_client_task_deinit(void) +{ + bt_mesh_provisioner_ota_client_app_task_deinit(); +} + +void bt_mesh_provisioner_ota_client_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_mesh_provisioner_ota_client_app_main(void) +{ + bt_trace_init(); + bt_mesh_provisioner_ota_client_stack_config_init(); + bte_init(); + bt_mesh_provisioner_ota_client_board_init(); + bt_mesh_provisioner_ota_client_driver_init(); + le_gap_init(BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_LINKS); + bt_mesh_provisioner_ota_client_app_le_gap_init(); + bt_mesh_provisioner_ota_client_app_le_profile_init(); + bt_mesh_provisioner_ota_client_stack_init(); + bt_mesh_provisioner_ota_client_pwr_mgr_init(); + bt_mesh_provisioner_ota_client_task_init(); + + return 0; +} + +int bt_mesh_provisioner_ota_client_app_init(void) +{ + int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + bt_stack_already_on = 1; + printf("[BT Mesh Provisioner OTA Client]BT Stack already on\n\r"); + return 0; + } + else + bt_mesh_provisioner_ota_client_app_main(); + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + if (bt_stack_already_on) { + uint8_t bt_addr[6]; + uint8_t net_key[16] = MESH_NET_KEY; + uint8_t net_key1[16] = MESH_NET_KEY1; + uint8_t app_key[16] = MESH_APP_KEY; + uint8_t app_key1[16] = MESH_APP_KEY1; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /** configure provisioner */ + mesh_node.node_state = PROV_NODE; + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + memcpy(&net_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&net_key1[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key1[10], bt_addr, sizeof(bt_addr)); + uint16_t net_key_index = net_key_add(0, net_key); + app_key_add(net_key_index, 0, app_key); + uint8_t net_key_index1 = net_key_add(1, net_key1); + app_key_add(net_key_index1, 1, app_key1); + mesh_model_bind_all_key(); + } + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_provisioner_api_init()) { + printf("[BT Mesh Provisioner] bt_mesh_provisioner_api_init fail ! \n\r"); + return 1; + } +#endif + + return 0; +} + +extern void mesh_deinit(void); +extern bool bt_trace_uninit(void); +extern void gcs_delete_client(void); +extern void gaps_delete_client(void); +extern void bas_delete_client(void); +extern void ota_delete_client(void); +extern void dfu_delete_client(void); +void bt_mesh_provisioner_ota_client_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + bt_mesh_provisioner_api_deinit(); +#endif + bt_mesh_provisioner_ota_client_task_deinit(); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Provisioner OTA Client] BT Stack is not running\n\r"); + mesh_initial_state = FALSE; + bt_mesh_provisioner_ota_client_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; + return; + } +#if F_BT_DEINIT + else { + gcs_delete_client(); + gaps_delete_client(); + bas_delete_client(); + ota_delete_client(); + dfu_delete_client(); + bte_deinit(); + printf("[BT Mesh Provisioner OTA Client] BT Stack deinitalized\n\r"); + } +#endif + mesh_deinit(); + bt_trace_uninit(); + + plt_timer_delete(bt_mesh_provisioner_ota_client_adv_timer, 0xFFFFFFFF); + bt_mesh_provisioner_ota_client_adv_timer = NULL; + + mesh_initial_state = FALSE; + bt_mesh_provisioner_ota_client_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_task.c new file mode 100644 index 00000000..84ad66fc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_task.c @@ -0,0 +1,229 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include +#include +#include +#include +#include +#include +#include +#include "platform_opts.h" +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "provisioner_cmd.h" +//#include +#include "bt_mesh_provisioner_ota_client_app.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#include "ble_scatternet_user_cmd.h" + +/*============================================================================* + * Macros + *============================================================================*/ +#define EVENT_MESH 0x80 +#define APP_TASK_PRIORITY 4 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x40 //!< IO message queue size +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#else +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#endif + +#if defined(CONFIG_PLATFORM_8721D) +#define UART_TX _PA_18 +#define UART_RX _PA_19 +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +#define UART_TX PA_14 +#define UART_RX PA_13 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_mesh_provisioner_ota_client_app_task_handle; //!< APP Task handle +void *bt_mesh_provisioner_ota_client_evt_queue_handle; //!< Event queue handle +void *bt_mesh_provisioner_ota_client_io_queue_handle; //!< IO queue handle +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +void *bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle; //!< user cmd queue handle +#endif + +/*============================================================================* + * Functions + *============================================================================*/ +void app_send_uart_msg(uint8_t data) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = IO_MSG_TYPE_UART; + msg.subtype = data; + if (os_msg_send(bt_mesh_provisioner_ota_client_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) + { + } +} + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern CMD_MOD_INFO_S btMeshCmdPriv; +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg) +{ + uint8_t event = EVENT_USER_API_REQ; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)p_io_msg->u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + //trace commands transmitted to mesh stack + btMeshCmdPriv.cmdTransmittedNum ++; + if (os_msg_send(bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle, p_io_msg, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle fail!\r\n"); + return 1; + } + else if (os_msg_send(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_provisioner_ota_client_evt_queue_handle fail!\r\n"); + return 1; + } + + return 0; +} +#endif + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_mesh_provisioner_ota_client_app_main_task(void *p_param) +{ + /* avoid gcc compile warning */ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_mesh_provisioner_ota_client_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_mesh_provisioner_ota_client_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + os_msg_queue_create(&bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); +#endif + gap_start_bt_stack(bt_mesh_provisioner_ota_client_evt_queue_handle, bt_mesh_provisioner_ota_client_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + mesh_start(EVENT_MESH, EVENT_IO_TO_APP, bt_mesh_provisioner_ota_client_evt_queue_handle, bt_mesh_provisioner_ota_client_io_queue_handle); + + mesh_data_uart_init(UART_TX, UART_RX, app_send_uart_msg); + mesh_user_cmd_init("MeshProvisioner"); + + while (true) + { + if (os_msg_recv(bt_mesh_provisioner_ota_client_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_ota_client_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_provisioner_ota_client_app_handle_io_msg(io_msg); + } + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + else if (event == EVENT_USER_API_REQ) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_io_msg_handler(io_msg); + } + } +#endif + else if (event == EVENT_MESH) + { + mesh_inner_msg_handle(event); + } + else + { + gap_handle_msg(event); + } + + } + } +} + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_provisioner_ota_client_app_task_init() +{ + os_task_create(&bt_mesh_provisioner_ota_client_app_task_handle, "bt_mesh_provisioner_ota_client_app", bt_mesh_provisioner_ota_client_app_main_task, 0, APP_TASK_STACK_SIZE, APP_TASK_PRIORITY); +} + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_provisioner_ota_client_app_task_deinit(void) +{ + if (bt_mesh_provisioner_ota_client_app_task_handle) { + os_task_delete(bt_mesh_provisioner_ota_client_app_task_handle); + } + if (bt_mesh_provisioner_ota_client_io_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_ota_client_io_queue_handle); + } + if (bt_mesh_provisioner_ota_client_evt_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_ota_client_evt_queue_handle); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle); + } + bt_mesh_provisioner_ota_client_user_cmd_io_queue_handle = NULL; +#endif + bt_mesh_provisioner_ota_client_io_queue_handle = NULL; + bt_mesh_provisioner_ota_client_evt_queue_handle = NULL; + bt_mesh_provisioner_ota_client_app_task_handle = NULL; + + bt_mesh_provisioner_ota_client_central_app_max_links = 0; + bt_mesh_provisioner_ota_client_peripheral_app_max_links = 0; + + mesh_user_cmd_deinit("MeshProvisioner"); +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_task.h new file mode 100644 index 00000000..8ee4936b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_app_task.h @@ -0,0 +1,30 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_PROVISIONER_OTA_CLIENT_APP_TASK_H_ +#define _BT_MESH_PROVISIONER_OTA_CLIENT_APP_TASK_H_ + +#include "mesh_config.h" + +extern void *bt_mesh_provisioner_ota_client_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_ota_client_io_queue_handle; //!< IO queue handle + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_provisioner_ota_client_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_provisioner_ota_client_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_cmd.c new file mode 100644 index 00000000..e5eefcd9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_cmd.c @@ -0,0 +1,811 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provisioner_cmd.c + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include +#include "trace.h" +#include "gap_wrapper.h" +#include "provisioner_cmd.h" +#include "provisioner_app.h" +#include "provision_client.h" +#include "provision_provisioner.h" +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "test_cmd.h" +#include "client_cmd.h" +#include "generic_client_app.h" +#include "datatrans_model.h" +#include "datatrans_app.h" +#include "remote_provisioning.h" + +static user_cmd_parse_result_t user_cmd_prov_discover(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Prov Start Discover\r\n"); + prov_client_conn_id = pparse_value->dw_parameter[0]; + prov_client_start_discovery(prov_client_conn_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_read_char(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char to be read. */ + prov_read_type_t read_char_type = (prov_read_type_t)pparse_value->dw_parameter[0]; + /* Read by handle or UUID, 1--by UUID, 0--by handle. */ + uint8_t read_pattern = (uint8_t)pparse_value->dw_parameter[1]; + data_uart_debug("Pro Read Char\r\n"); + if (read_pattern) + { + prov_client_read_by_uuid(prov_client_conn_id, read_char_type); + } + else + { + prov_client_read_by_handle(prov_client_conn_id, read_char_type); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_cccd_operate(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char CCCD command. */ + uint8_t cmd_type = (uint8_t)pparse_value->dw_parameter[0]; + /* Enable or disable, 1--enable, 0--disable. */ + bool cmd_data = (bool)pparse_value->dw_parameter[1]; + data_uart_debug("Prov Cccd Operate\r\n"); + switch (cmd_type) + { + case 0:/* V3 Notify char notif enable/disable. */ + { + prov_client_data_out_cccd_set(prov_client_conn_id, cmd_data); + proxy_ctx_set_link(prov_proxy_ctx_id, prov_client_conn_id); + } + break; + default: + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_list(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Prov Server Handle List:\r\nidx\thandle\r\n"); + for (prov_handle_type_t hdl_idx = HDL_PROV_SRV_START; hdl_idx < HDL_PROV_CACHE_LEN; hdl_idx++) + { + data_uart_debug("%d\t0x%x\r\n", hdl_idx, prov_client_handle_get(prov_client_conn_id, hdl_idx)); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_pb_adv_con(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + + send_coex_mailbox_to_wifi_from_BtAPP(1); + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[0], sizeof(dev_uuid)); + if (!pb_adv_link_open(0, dev_uuid)) + { + data_uart_debug("PB_ADV: Link Busy!\r\n"); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_pb_adv_disc(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + if (pb_adv_link_close(0, PB_ADV_LINK_CLOSE_SUCCESS)) + { + data_uart_debug("PB_ADV: Link Closed!\r\n"); + } + else + { + data_uart_debug("PB_ADV: Link Closed Already!\r\n"); + } + return USER_CMD_RESULT_OK; +} + +#if defined(MESH_RPR) && MESH_RPR +static user_cmd_parse_result_t user_cmd_rmt_prov_client_scan_start(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t scanned_items_limit = pparse_value->dw_parameter[2]; + uint8_t scan_timeout = pparse_value->dw_parameter[3]; + uint8_t ret = 0; + + if (pparse_value->para_count == 5) { + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[4], sizeof(dev_uuid)); + ret = rmt_prov_client_scan_start(dst, net_key_index, scanned_items_limit, scan_timeout, dev_uuid); + } else if (pparse_value->para_count == 4) { + ret = rmt_prov_client_scan_start(dst, net_key_index, scanned_items_limit, scan_timeout, NULL); + } else { + data_uart_debug("invalid param\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + if (ret == MESH_MSG_SEND_CAUSE_SUCCESS) { + return USER_CMD_RESULT_OK; + } else { + data_uart_debug("fail\r\n"); + return USER_CMD_RESULT_ERROR; + } +} + +static user_cmd_parse_result_t user_cmd_rmt_prov_client_link_open_prov(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t link_open_timeout = pparse_value->dw_parameter[3]; + + if (pparse_value->para_count == 4) { + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[2], sizeof(dev_uuid)); + } else { + data_uart_debug("invalid uuid\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return rmt_prov_client_link_open_prov(dst, net_key_index, dev_uuid, link_open_timeout) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_rmt_prov_client_close(user_cmd_parse_value_t *pparse_value) +{ + rmt_prov_link_close_reason_t reason; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + + if (pparse_value->para_count == 3) { + reason = (rmt_prov_link_close_reason_t)pparse_value->dw_parameter[2]; + } else { + data_uart_debug("invalid reason\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + + return rmt_prov_client_link_close(dst, net_key_index, reason) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} +#endif + +static user_cmd_parse_result_t user_cmd_prov(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("provision...\r\n"); + uint32_t attn_dur = pparse_value->dw_parameter[0]; + prov_manual = pparse_value->dw_parameter[1]; + prov_start_time = plt_time_read_ms(); + return prov_invite(attn_dur) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_prov_stop(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + return prov_reject() ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_prov_auth_path(user_cmd_parse_value_t *pparse_value) +{ + prov_start_algorithm_t algo = (prov_start_algorithm_t)pparse_value->dw_parameter[0]; + prov_start_public_key_t public_key = (prov_start_public_key_t)pparse_value->dw_parameter[1]; + prov_auth_method_t auth_method = (prov_auth_method_t)pparse_value->dw_parameter[2]; + uint8_t oob_action = pparse_value->dw_parameter[3]; + uint8_t oob_size = pparse_value->dw_parameter[4]; + + prov_start_t prov_start; + prov_start.algorithm = algo; + prov_start.public_key = public_key; + prov_start.auth_method = auth_method; + prov_start.auth_action.oob_action = oob_action; + prov_start.auth_size.oob_size = oob_size; + return prov_path_choose(&prov_start) == true ? USER_CMD_RESULT_OK : USER_CMD_RESULT_WRONG_PARAMETER; +} + +static user_cmd_parse_result_t user_cmd_unprov(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Unprovision...\r\n"); +#if MESH_UNPROVISIONING_SUPPORT + prov_unprovisioning(); +#endif + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_cfg_client_key_set(user_cmd_parse_value_t + *pparse_value) +{ + uint8_t key_index = pparse_value->dw_parameter[0]; + bool use_app_key = pparse_value->dw_parameter[1] ? TRUE : FALSE; + mesh_node.features.cfg_model_use_app_key = use_app_key; + return cfg_client_key_set(key_index) ? USER_CMD_RESULT_OK : + USER_CMD_RESULT_VALUE_OUT_OF_RANGE; +} + +static user_cmd_parse_result_t user_cmd_compo_data_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t page = pparse_value->dw_parameter[1]; + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + data_uart_debug("CDP0 len=%d, data=", mesh_node.compo_data_size[0]); + data_uart_dump(mesh_node.compo_data[0], mesh_node.compo_data_size[0]); + } + else + { + cfg_compo_data_get(dst, page); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_node_reset(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + bool clear = pparse_value->dw_parameter[1]; + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + mesh_node_reset(); + } + else + { + cfg_node_reset(dst); + if (clear) + { + int dev_key_index = dev_key_find(dst); + if (dev_key_index >= 0) + { + dev_key_delete(dev_key_index); + mesh_flash_store(MESH_FLASH_PARAMS_DEV_KEY, &dev_key_index); + } + } + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_net_key_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + cfg_net_key_add(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_new_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_net_key_update(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t net_key[MESH_COMMON_KEY_SIZE]; + plt_hex_to_bin(net_key, (uint8_t *)pparse_value->pparameter[2], MESH_COMMON_KEY_SIZE); + return net_key_update(net_key_index, mesh_node.net_key_list[net_key_index].net_key_index_g, + net_key) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; + } + else + { + cfg_net_key_update(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_new_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key); + return USER_CMD_RESULT_OK; + } +} + +static user_cmd_parse_result_t user_cmd_app_key_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + data_uart_debug("\r\n %s() dst = %x",__func__,dst); + cfg_app_key_add(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.app_key_list[app_key_index].app_key_index_g, + mesh_node.app_key_list[app_key_index].papp_key[key_state_to_new_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_app_key_update(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t app_key[MESH_COMMON_KEY_SIZE]; + plt_hex_to_bin(app_key, (uint8_t *)pparse_value->pparameter[3], MESH_COMMON_KEY_SIZE); + return app_key_update(app_key_index, net_key_index, + mesh_node.app_key_list[app_key_index].app_key_index_g, + app_key) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; + } + else + { + cfg_app_key_update(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.app_key_list[app_key_index].app_key_index_g, + mesh_node.app_key_list[app_key_index].papp_key[key_state_to_new_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key); + return USER_CMD_RESULT_OK; + } +} + +static user_cmd_parse_result_t user_cmd_model_app_bind(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t app_key_index = pparse_value->dw_parameter[3]; + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + cfg_model_app_bind(dst, dst + element_index, mesh_node.app_key_list[app_key_index].app_key_index_g, + model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_pub_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 11) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + pub_key_info_t pub_key_info = {pparse_value->dw_parameter[4], pparse_value->dw_parameter[5], 0}; + pub_period_t pub_period = {pparse_value->dw_parameter[7] & 0x3f, pparse_value->dw_parameter[7] >> 6}; + pub_retrans_info_t pub_retrans_info = {pparse_value->dw_parameter[8], pparse_value->dw_parameter[9]}; + uint8_t addr[16]; + if (0 == pparse_value->dw_parameter[2]) + { + uint16_t element_addr = (uint16_t)(pparse_value->dw_parameter[3]); + LE_WORD2EXTRN(addr, element_addr); + } + else + { + plt_hex_to_bin(addr, (uint8_t *)pparse_value->pparameter[3], 16); + } + cfg_model_pub_set(dst, pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + addr, pub_key_info, pparse_value->dw_parameter[6], pub_period, + pub_retrans_info, pparse_value->dw_parameter[10]); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t group_addr = pparse_value->dw_parameter[3]; + if (MESH_NOT_GROUP_ADDR(group_addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + cfg_model_sub_add(dst, dst + element_index, false, (uint8_t *)&group_addr, model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_get(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + cfg_model_sub_get(dst, dst + element_index, model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_delete(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t group_addr = pparse_value->dw_parameter[3]; + if (pparse_value->para_count == 4) + { + if (MESH_NOT_GROUP_ADDR(group_addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + cfg_model_sub_delete(dst, dst + element_index, false, (uint8_t *)&group_addr, model_id); + } + else if (pparse_value->para_count == 3) + { + cfg_model_sub_delete_all(dst, dst + element_index, model_id); + } + else + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_key_refresh_phase_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + cfg_key_refresh_phase_get(dst, net_key_index_to_global(net_key_index)); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_key_refresh_phase_set(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t phase = pparse_value->dw_parameter[2]; + cfg_key_refresh_phase_set(dst, net_key_index_to_global(net_key_index), phase); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_write(user_cmd_parse_value_t *pparse_value) +{ + uint8_t para_count = pparse_value->para_count; + uint8_t data[18]; + + for (uint8_t i = 0; i < para_count - 3; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + datatrans_write(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[para_count - 2], para_count - 3, data, + pparse_value->dw_parameter[para_count - 1]); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_read(user_cmd_parse_value_t *pparse_value) +{ + datatrans_read(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const user_cmd_table_entry_t provisioner_cmd_table[] = +{ + // mesh common cmd + MESH_COMMON_CMD, + CLIENT_CMD, + TEST_CMD, + // provisioner cmd + // pb-adv + { + "pbadvcon", + "pbadvcon [dev uuid]\n\r", + "create a pb-adv link with the device uuid\n\r", + user_cmd_pb_adv_con + }, + { + "pbadvdisc", + "pbadvdisc\n\r", + "disconnect the pb-adv link\n\r", + user_cmd_pb_adv_disc + }, + // pb-gatt + { + "provdis", + "provdis [conn id]\n\r", + "Start discovery provisioning service\n\r", + user_cmd_prov_discover + }, + { + "provread", + "provread [char] [pattern: handle/UUID16]\n\r", + "Read all related chars by user input\n\r", + user_cmd_prov_read_char + }, + { + "provcmd", + "provcmd [char CCCD] [command: enable/disable]\n\r", + "Provisioning notify/ind switch command\n\r", + user_cmd_prov_cccd_operate + }, + { + "provls", + "provls\n\r", + "Provision server handle list\n\r", + user_cmd_prov_list + }, + // provisioner + { + "prov", + "prov [attn_dur] [manual]\n\r", + "provision a new mesh device\n\r", + user_cmd_prov + }, + { + "provs", + "provs\n\r", + "provision stop\n\r", + user_cmd_prov_stop + }, + { + "pap", + "pap [algorithm] [pubkey] [method: nsoi] [action] [size]\n\r", + "provision authentication path\n\r", + user_cmd_prov_auth_path + }, + { + "unprov", + "unprov\n\r", + "unprovision the mesh device\n\r", + user_cmd_unprov + }, + // cfg client key set + { + "ccks", + "ccks [key_index] [use_app_key]\n\r", + "cfg client key set\n\r", + user_cmd_cfg_client_key_set + }, + // cfg client or local setting + { + "cdg", + "cdg [dst]\n\r", + "compo data get\n\r", + user_cmd_compo_data_get + }, + { + "nr", + "nr [dst] [clear]\n\r", + "node reset\n\r", + user_cmd_node_reset + }, + { + "nka", + "nka [dst] [net_key_index]\n\r", + "net key add\n\r", + user_cmd_net_key_add + }, + { + "nku", + "nku [dst] [net_key_index] [net key]\n\r", + "net key update\n\r", + user_cmd_net_key_update + }, + { + "aka", + "aka [dst] [net_key_index] [app_key_index]\n\r", + "app key add\n\r", + user_cmd_app_key_add + }, + { + "aku", + "aku [dst] [net_key_index] [app_key_index] [app key]\n\r", + "app key update\n\r", + user_cmd_app_key_update + }, + { + "mab", + "mab [dst] [element index] [model_id] [app_key_index]\n\r", + "model app bind\n\r", + user_cmd_model_app_bind + }, + { + "msa", + "msa [dst] [element index] [model_id] [group addr]\n\r", + "model subsribe add\n\r", + user_cmd_model_sub_add + }, + { + "msd", + "msd [dst] [element index] [model_id] \n\r", + "model subsribe delete\n\r", + user_cmd_model_sub_delete + }, + { + "krpg", + "krpg [dst] [net key index]\n\r", + "key refresh phase get\n\r", + user_cmd_key_refresh_phase_get + }, + { + "krps", + "krps [dst] [net key index] [phase]\n\r", + "key refresh phase set\n\r", + user_cmd_key_refresh_phase_set + }, + { + "dtw", + "dtw [dst] [data...] [app_key_index] [ack] \n\r", + "data transmission write data\n\r", + user_cmd_datatrans_write + }, + { + "dtr", + "dtr [dst] [len] [app_key_index]\n\r", + "data transmission read data\n\r", + user_cmd_datatrans_read + }, +#if defined(MESH_RPR) && MESH_RPR + { + "rmtscan", + "rmtscan [dst] [net key index] [scanned items limit] [scan timeout] [dev uuid]\n\r", + "romte provision scan start\n\r", + user_cmd_rmt_prov_client_scan_start + }, + { + "rmtcon", + "rmtcon [dst] [net key index] [dev uuid] [link open timeout]\n\r", + "romte link open for provision\n\r", + user_cmd_rmt_prov_client_link_open_prov + }, + { + "rmtdisc", + "rmtdisc [dst] [net_key_index] [reason]\n\r", + "romte link close for provision\n\r", + user_cmd_rmt_prov_client_close + }, +#endif + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +const struct bt_mesh_api_hdl provisionercmds[] = +{ + GEN_MESH_HANDLER(_pb_adv_con) + GEN_MESH_HANDLER(_prov) + GEN_MESH_HANDLER(_prov_stop) + GEN_MESH_HANDLER(_app_key_add) + GEN_MESH_HANDLER(_model_app_bind) + GEN_MESH_HANDLER(_model_pub_set) + GEN_MESH_HANDLER(_generic_on_off_set) + GEN_MESH_HANDLER(_generic_on_off_get) + GEN_MESH_HANDLER(_node_reset) + GEN_MESH_HANDLER(_model_sub_delete) + GEN_MESH_HANDLER(_model_sub_add) + GEN_MESH_HANDLER(_model_sub_get) + GEN_MESH_HANDLER(_prov_discover) + GEN_MESH_HANDLER(_prov_cccd_operate) + GEN_MESH_HANDLER(_proxy_discover) + GEN_MESH_HANDLER(_proxy_cccd_operate) + GEN_MESH_HANDLER(_datatrans_write) + GEN_MESH_HANDLER(_datatrans_read) + GEN_MESH_HANDLER(_connect) + GEN_MESH_HANDLER(_disconnect) + GEN_MESH_HANDLER(_list) + GEN_MESH_HANDLER(_dev_info_show) + GEN_MESH_HANDLER(_fn_init) + GEN_MESH_HANDLER(_fn_deinit) + GEN_MESH_HANDLER(_light_lightness_get) + GEN_MESH_HANDLER(_light_lightness_set) + GEN_MESH_HANDLER(_light_lightness_linear_get) + GEN_MESH_HANDLER(_light_lightness_linear_set) + GEN_MESH_HANDLER(_light_lightness_last_get) + GEN_MESH_HANDLER(_light_lightness_default_get) + GEN_MESH_HANDLER(_light_lightness_default_set) + GEN_MESH_HANDLER(_light_lightness_range_get) + GEN_MESH_HANDLER(_light_lightness_range_set) + GEN_MESH_HANDLER(_light_ctl_get) + GEN_MESH_HANDLER(_light_ctl_set) + GEN_MESH_HANDLER(_light_ctl_temperature_get) + GEN_MESH_HANDLER(_light_ctl_temperature_set) + GEN_MESH_HANDLER(_light_ctl_temperature_range_get) + GEN_MESH_HANDLER(_light_ctl_temperature_range_set) + GEN_MESH_HANDLER(_light_ctl_default_get) + GEN_MESH_HANDLER(_light_ctl_default_set) + GEN_MESH_HANDLER(_light_hsl_get) + GEN_MESH_HANDLER(_light_hsl_set) + GEN_MESH_HANDLER(_light_hsl_target_get) + GEN_MESH_HANDLER(_light_hsl_hue_get) + GEN_MESH_HANDLER(_light_hsl_hue_set) + GEN_MESH_HANDLER(_light_hsl_saturation_get) + GEN_MESH_HANDLER(_light_hsl_saturation_set) + GEN_MESH_HANDLER(_light_hsl_default_get) + GEN_MESH_HANDLER(_light_hsl_default_set) + GEN_MESH_HANDLER(_light_hsl_range_get) + GEN_MESH_HANDLER(_light_hsl_range_set) + GEN_MESH_HANDLER(_light_xyl_get) + GEN_MESH_HANDLER(_light_xyl_set) + GEN_MESH_HANDLER(_light_xyl_target_get) + GEN_MESH_HANDLER(_light_xyl_default_get) + GEN_MESH_HANDLER(_light_xyl_default_set) + GEN_MESH_HANDLER(_light_xyl_range_get) + GEN_MESH_HANDLER(_light_xyl_range_set) + GEN_MESH_HANDLER(_time_set) + GEN_MESH_HANDLER(_time_get) + GEN_MESH_HANDLER(_time_zone_set) + GEN_MESH_HANDLER(_time_zone_get) + GEN_MESH_HANDLER(_time_tai_utc_delta_set) + GEN_MESH_HANDLER(_time_tai_utc_delta_get) + GEN_MESH_HANDLER(_time_role_set) + GEN_MESH_HANDLER(_time_role_get) + GEN_MESH_HANDLER(_scene_store) + GEN_MESH_HANDLER(_scene_recall) + GEN_MESH_HANDLER(_scene_get) + GEN_MESH_HANDLER(_scene_register_get) + GEN_MESH_HANDLER(_scene_delete) + GEN_MESH_HANDLER(_scheduler_get) + GEN_MESH_HANDLER(_scheduler_action_get) + GEN_MESH_HANDLER(_scheduler_action_set) +#if defined(MESH_RPR) && MESH_RPR + GEN_MESH_HANDLER(_rmt_prov_client_scan_start) + GEN_MESH_HANDLER(_rmt_prov_client_link_open_prov) + GEN_MESH_HANDLER(_rmt_prov_client_close) +#endif +#if defined(MESH_DFU) && MESH_DFU + GEN_MESH_HANDLER(_fw_update_info_get) + GEN_MESH_HANDLER(_fw_update_start) + GEN_MESH_HANDLER(_fw_update_cancel) +#endif +}; +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_cmd.h new file mode 100644 index 00000000..57f3fb1c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_cmd.h @@ -0,0 +1,36 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_PROVISIONER_OTA_CLIENT_CMD_H_ +#define _BT_MESH_PROVISIONER_OTA_CLIENT_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_config.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_cmd_types.h" +#endif + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +extern const user_cmd_table_entry_t provisioner_cmd_table[]; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern const struct bt_mesh_api_hdl provisionercmds[]; +#endif +void light_cwrgb_process(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_handle.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_handle.c new file mode 100644 index 00000000..592fa235 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_handle.c @@ -0,0 +1,80 @@ +#include "platform_opts_bt.h" +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include +#include +#include "log_service.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "insert_write.h" +#endif + + +uint8_t* bt_mesh_provisioner_ota_client_image = NULL; +uint8_t* bt_mesh_provisioner_ota_client_key = NULL; + +extern void bt_mesh_provisioner_ota_client_app_discov_services(uint8_t conn_id, bool start); + +/** + * NOTE: OTA Image and AEK KEY + */ +bool bt_mesh_provisioner_ota_client_set_image(uint8_t* image) +{ + if (image == NULL) { + printf("bt_mesh_provisioner_ota_client_set_image: image is NULL\r\n"); + return false; + } + + bt_mesh_provisioner_ota_client_image = image; + return true; +} + +bool bt_mesh_provisioner_ota_client_set_key(uint8_t* key) +{ + if (key == NULL) { + printf("bt_mesh_provisioner_ota_client_set_key: key is NULL\r\n"); + return false; + } + + bt_mesh_provisioner_ota_client_key = key; + return true; +} + +/* start discovery services and ota process. */ +int bt_mesh_provisioner_ota_client_start_ota(uint16_t subtype, void *arg) +{ + int argc = 0; + char *argv[MAX_ARGC] = {0}; + int conn_id = 0; + + if (arg) { + argc = parse_param(arg, argv); + } + + conn_id = atoi(argv[1]); + +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(if_queue_in(1, conn_id, 0, 0, 0, NULL) == 0) +#endif + { + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, true); + } + + return 0; +} + +/* ******************* wrap the function for conmon file of ota process ***************************** */ +void bt_ota_central_client_app_discov_services(uint8_t conn_id, bool start) +{ + bt_mesh_provisioner_ota_client_app_discov_services(conn_id, start); +} + +uint8_t* bt_ota_central_client_get_image(void) +{ + return bt_mesh_provisioner_ota_client_image; +} + +uint8_t* bt_ota_central_client_get_key(void) +{ + return bt_mesh_provisioner_ota_client_key; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_link_mgr.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_link_mgr.c new file mode 100644 index 00000000..fb5239a9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_link_mgr.c @@ -0,0 +1,142 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include +#include +#include + +/*============================================================================* + * Constants + *============================================================================*/ +#if F_BT_GATT_SRV_HANDLE_STORAGE +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** @brief Define start offset of the falsh to save GATT Server information. */ +#define APP_SRVS_HDL_TABLE_FLASH_OFFSET 0 +/** @} */ /* End of group CENTRAL_SRV_DIS */ +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +T_DEV_INFO bt_mesh_provisioner_ota_client_dev_list[BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_DEVICE_INFO]; +uint8_t bt_mesh_provisioner_ota_client_dev_list_count = 0; +/** @} */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool bt_mesh_provisioner_ota_client_link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (bt_mesh_provisioner_ota_client_dev_list_count < BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < bt_mesh_provisioner_ota_client_dev_list_count; i++) + { + if (memcmp(bd_addr, bt_mesh_provisioner_ota_client_dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(bt_mesh_provisioner_ota_client_dev_list[bt_mesh_provisioner_ota_client_dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + bt_mesh_provisioner_ota_client_dev_list[bt_mesh_provisioner_ota_client_dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + bt_mesh_provisioner_ota_client_dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void bt_mesh_provisioner_ota_client_link_mgr_clear_device_list(void) +{ + bt_mesh_provisioner_ota_client_dev_list_count = 0; +} +/** @} */ + +#if F_BT_GATT_SRV_HANDLE_STORAGE +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** + * @brief Save GATT Services information into flash. + * @param[in] p_info the buffer for saving data + * @retval 0 Save success. + * @retval other Failed. + */ +uint32_t bt_mesh_provisioner_ota_client_app_save_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info) +{ + APP_PRINT_INFO0("bt_mesh_provisioner_ota_client_app_save_srvs_hdl_table"); + return ftl_save(p_info, APP_SRVS_HDL_TABLE_FLASH_OFFSET, sizeof(T_APP_SRVS_HDL_TABLE)); +} + +/** + * @brief load GATT Services information from storage + * @param[out] p_info the buffer for loading data + * @retval 0 Load success. + * @retval other Failed. + */ +uint32_t bt_mesh_provisioner_ota_client_app_load_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info) +{ + uint32_t result; + result = ftl_load(p_info, APP_SRVS_HDL_TABLE_FLASH_OFFSET, sizeof(T_APP_SRVS_HDL_TABLE)); + APP_PRINT_INFO1("bt_mesh_provisioner_ota_client_app_load_srvs_hdl_table: result %u", result); + if (result) + { + memset(p_info, 0, sizeof(T_APP_SRVS_HDL_TABLE)); + } + return result; +} +/** @} */ +#endif + +#endif + +/** @} */ + + + + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_link_mgr.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_link_mgr.h new file mode 100644 index 00000000..c0738422 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_link_mgr.h @@ -0,0 +1,91 @@ +#ifndef _BT_MESH_PROVISIONER_OTA_CLIENT_LINK_MGR_H_ +#define _BT_MESH_PROVISIONER_OTA_CLIENT_LINK_MGR_H_ + +#include +#include +#include +#include + +/*============================================================================* + * Constants + *============================================================================*/ +/** @defgroup APP_DISCOV_BITS Application discover services Bits +* @{ + */ +#define APP_DISCOV_GAPS_FLAG 0x01 +#define APP_DISCOV_BAS_FLAG 0x02 +#define APP_DISCOV_OTA_FLAG 0x04 +#define APP_DISCOV_DFU_FLAG 0x08 + +/** @brief Define device list table size. */ +#define BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_DEVICE_INFO 6 + +/** @addtogroup CENTRAL_CLIENT_GAP_MSG + * @{ + */ +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + uint8_t discovered_flags; /**< discovered flags. */ + uint8_t srv_found_flags; /**< service founded flags. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + T_GAP_ROLE role; //!< Device role +} T_APP_LINK; +/** @} */ +/* End of group CENTRAL_CLIENT_GAP_MSG */ + +#if F_BT_GATT_SRV_HANDLE_STORAGE +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** @brief App link table */ +typedef struct +{ + uint8_t srv_found_flags; + uint8_t bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint32_t reserved; + uint16_t ota_hdl_cache[HDL_OTA_CACHE_LEN]; + uint16_t dfu_hdl_cache[HDL_DFU_CACHE_LEN]; + uint16_t bas_hdl_cache[HDL_BAS_CACHE_LEN]; +} T_APP_SRVS_HDL_TABLE; +/** @} */ +#endif + +/** @addtogroup CENTRAL_CLIENT_SCAN_MGR + * @{ + */ +/** + * @brief Device list block definition. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/** @} */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO bt_mesh_provisioner_ota_client_dev_list[BT_MESH_PROVISIONER_OTA_CLIENT_APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t bt_mesh_provisioner_ota_client_dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool bt_mesh_provisioner_ota_client_link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void bt_mesh_provisioner_ota_client_link_mgr_clear_device_list(void); + +#if F_BT_GATT_SRV_HANDLE_STORAGE +uint32_t bt_mesh_provisioner_ota_client_app_save_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info); +uint32_t bt_mesh_provisioner_ota_client_app_load_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info); +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_test_image.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_test_image.c new file mode 100644 index 00000000..5d72aaf4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/bt_mesh_provisioner_ota_client_test_image.c @@ -0,0 +1,1628 @@ +/* + C-file generated by Bin2C + Compiled: Aug 9 2004 at 15:18:55 + + Copyright (C) 2004 + Segger Microcontroller Systeme GmbH + www.segger.com + + Solutions for real time microcontroller applications +*/ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#include "bt_ota_central_client.h" +unsigned char rtl8762c_aes256_key[32] = +{ + 0x1a, 0x60, 0x8e, 0x11, 0xd3, 0x4c, 0x0d, 0x96, + 0x70, 0x7e, 0x7a, 0x80, 0xdf, 0x63, 0x67, 0x1f, + 0xfb, 0x10, 0xf6, 0xd1, 0x0c, 0x1a, 0x97, 0x9a, + 0xe2, 0x29, 0x2b, 0x09, 0xc5, 0xf8, 0x46, 0x4e +}; + +unsigned char rtl8762c_image[] = +#if (RCU_SILENT_OTA == 1) //rcu silent ota test image +{ + 0x05, 0x00, 0x01, 0x01, 0x93, 0x27, 0x00, 0x00, + 0x68, 0x98, 0x00, 0x00, 0x6D, 0x67, 0xDE, 0xF1, 0x3E, 0x33, 0xE8, 0x11, 0xB1, 0x02, 0x4D, 0x2D, 0xF4, 0x0C, 0xDE, 0x01, 0x00, 0xE4, 0x80, 0x00, 0x00, 0xE4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x00, 0x08, 0x50, 0x43, 0x46, 0x1E, 0x73, 0x64, 0x6B, 0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF8, 0x85, 0xED, 0x47, 0xD3, 0x1F, 0xC7, 0x59, 0x67, 0xC2, 0xDE, 0x7D, 0x87, 0x95, 0xC5, 0x9B, 0x32, 0x02, 0x63, 0xC8, 0x0D, 0xCA, 0x77, 0x60, 0x0B, 0x6C, 0x99, 0xAF, 0x18, 0xEB, 0xD1, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD1, 0x85, 0x0E, 0x60, 0xE2, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x00, 0x47, 0x5F, 0xE5, 0x80, 0x00, 0xAF, 0xF3, 0x00, 0x80, 0x0D, 0xF6, 0xF8, 0xF5, 0x10, 0xB5, 0x7D, 0x4A, 0x7D, 0x49, 0x7E, 0x48, + 0x4B, 0xF4, 0x3F, 0xF5, 0x7D, 0x4A, 0x7E, 0x49, 0x7E, 0x48, 0x4B, 0xF4, 0x3A, 0xF5, 0x7E, 0x49, 0x7E, 0x48, 0x4B, 0xF4, 0xF7, 0xF5, 0x7E, 0x4A, 0x7E, 0x49, 0x7F, 0x48, 0x4B, 0xF4, 0x31, 0xF5, 0x7E, 0x4A, 0x7F, 0x49, 0x7F, 0x48, 0x4B, 0xF4, + 0x2C, 0xF5, 0xBD, 0xE8, 0x10, 0x40, 0x7E, 0x49, 0x7E, 0x48, 0x4B, 0xF4, 0xE7, 0xB5, 0x7F, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF0, 0xE9, 0xE0, 0x12, 0x11, 0x44, 0x80, 0x68, 0x10, 0x22, 0x0D, 0x18, 0x29, 0x46, 0x68, 0x46, 0x4B, 0xF4, 0x19, 0xF5, + 0x10, 0x22, 0x69, 0x46, 0x00, 0x20, 0xF8, 0xF7, 0xB1, 0xDF, 0x75, 0x49, 0xD1, 0xF8, 0x7C, 0x11, 0x74, 0x4E, 0x60, 0xF3, 0x1F, 0x41, 0x4F, 0xF0, 0xFF, 0x30, 0xF1, 0x60, 0xF9, 0xF7, 0x95, 0xD9, 0xF1, 0x68, 0x48, 0x43, 0xF0, 0x60, 0x0F, 0xF6, + 0x95, 0xF3, 0x00, 0x24, 0x0D, 0xF6, 0xBE, 0xF5, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0x04, 0x2C, 0xF8, 0xDB, 0x0D, 0xF6, 0xB7, 0xF5, 0xF0, 0x60, 0x7F, 0xBD, 0x70, 0xB5, 0x68, 0x4D, 0x69, 0x49, 0x69, 0x4C, 0x28, 0x68, 0x4F, 0xF0, 0x00, 0x02, + 0xB1, 0xEB, 0x00, 0x2F, 0x05, 0xD0, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x65, 0x49, 0xF9, 0xF7, 0xCA, 0x9A, 0x00, 0x21, 0x45, 0xF2, 0x06, 0x00, 0xFD, 0xF7, 0xCF, 0xDD, 0x10, 0xF0, 0xFF, 0x03, 0x03, 0xD0, 0x60, 0x49, 0x01, 0x22, 0x1C, 0x31, + 0x04, 0xE0, 0x28, 0x68, 0x5D, 0x49, 0x03, 0x0E, 0x01, 0x22, 0x50, 0x31, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xF9, 0xF7, 0xB4, 0x9A, 0x38, 0xB5, 0x72, 0xB6, 0xFF, 0xF7, 0xD6, 0xFF, 0xFF, 0xF7, 0x87, 0xFF, 0xFF, 0xF7, 0xA4, 0xFF, 0x00, 0x20, + 0xFD, 0xF5, 0x7C, 0xF1, 0x16, 0x20, 0xFA, 0xF5, 0x3E, 0xF2, 0x17, 0x20, 0xFA, 0xF5, 0x3B, 0xF2, 0x51, 0xA1, 0x1F, 0x20, 0x4B, 0xF4, 0x6A, 0xF4, 0x4F, 0xF0, 0x05, 0x55, 0x4F, 0xA1, 0x28, 0x46, 0xF9, 0xF7, 0x9F, 0xDC, 0x04, 0x46, 0x54, 0xA1, + 0x28, 0x46, 0xF9, 0xF7, 0x9A, 0xDC, 0x03, 0x46, 0x48, 0x49, 0x47, 0x48, 0x02, 0x22, 0x7C, 0x31, 0x80, 0x1E, 0x00, 0x94, 0xF9, 0xF7, 0x8B, 0xDA, 0xFA, 0xF5, 0x2C, 0xF2, 0x4E, 0x48, 0x00, 0x68, 0x00, 0x28, 0x03, 0xD0, 0x01, 0xB0, 0xBD, 0xE8, + 0x30, 0x40, 0x00, 0x47, 0x38, 0xBD, 0x10, 0xB5, 0xFE, 0xF7, 0xFE, 0xD8, 0x00, 0x28, 0x4D, 0xD1, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0xDC, 0x12, 0xC9, 0x07, 0x47, 0xD0, 0xAF, 0xF2, 0x81, 0x01, 0x44, 0x4A, 0x11, 0x60, 0x45, 0x4A, 0x44, 0x49, + 0x11, 0x60, 0x4F, 0xF4, 0x34, 0x41, 0xC0, 0xF8, 0x84, 0x13, 0x44, 0xF6, 0xF0, 0x71, 0xC0, 0xF8, 0x88, 0x13, 0x41, 0x49, 0xC0, 0xF8, 0xCC, 0x13, 0x90, 0xF8, 0x4D, 0x13, 0x41, 0xF0, 0x08, 0x01, 0x80, 0xF8, 0x4D, 0x13, 0x06, 0x21, 0x80, 0xF8, + 0x4F, 0x13, 0x90, 0xF8, 0x78, 0x23, 0x90, 0xF8, 0x9A, 0x13, 0x42, 0xF0, 0x26, 0x02, 0x80, 0xF8, 0x78, 0x23, 0x21, 0xF0, 0x21, 0x01, 0x80, 0xF8, 0x9A, 0x13, 0x90, 0xF8, 0x34, 0x13, 0x1F, 0x22, 0x21, 0xF0, 0x01, 0x01, 0x80, 0xF8, 0x34, 0x13, + 0x90, 0xF8, 0x7A, 0x13, 0x80, 0xF8, 0x79, 0x23, 0x41, 0xF0, 0xDF, 0x01, 0x80, 0xF8, 0x7A, 0x13, 0x90, 0xF8, 0xC3, 0x13, 0x21, 0xF0, 0xC0, 0x01, 0x80, 0xF8, 0xC3, 0x13, 0xF0, 0x21, 0x80, 0xF8, 0x20, 0x13, 0x3C, 0x21, 0x80, 0xF8, 0x21, 0x13, + 0xC8, 0x21, 0x80, 0xF8, 0x22, 0x13, 0xFF, 0x21, 0x80, 0xF8, 0x23, 0x13, 0x10, 0xBD, 0x00, 0x00, 0xE0, 0x69, 0x00, 0x00, 0x90, 0xE7, 0x80, 0x00, 0x00, 0x7C, 0x20, 0x00, 0xAC, 0x01, 0x00, 0x00, 0x70, 0x51, 0x81, 0x00, 0xE0, 0xE5, 0x20, 0x00, + 0xCC, 0x31, 0x00, 0x00, 0x8C, 0xE7, 0x20, 0x00, 0x4C, 0x29, 0x00, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x00, 0xC0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x7C, 0x81, 0x00, 0x4C, 0xE9, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xE9, 0x21, 0x00, + 0x00, 0x80, 0x05, 0x40, 0x8C, 0xE7, 0x20, 0x00, 0xE0, 0xE5, 0x20, 0x00, 0x00, 0x74, 0x65, 0x72, 0x02, 0x03, 0x10, 0x21, 0x00, 0x00, 0x80, 0x08, 0x43, 0x00, 0x00, 0x00, 0x54, 0x68, 0x75, 0x20, 0x4D, 0x61, 0x79, 0x20, 0x20, 0x37, 0x20, 0x31, + 0x37, 0x3A, 0x31, 0x37, 0x3A, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x32, 0x2E, 0x32, 0x2E, 0x31, 0x00, 0x94, 0xE7, 0x20, 0x00, 0x38, 0x0C, 0x20, 0x00, 0x8D, 0x88, 0x20, 0x00, 0x3C, 0x0C, 0x20, 0x00, + 0x03, 0x00, 0xAA, 0xA2, 0x00, 0x38, 0x20, 0x00, 0x01, 0xE4, 0x80, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x71, 0x83, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x19, 0x87, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x0D, 0x7C, 0x20, 0x00, 0x59, 0x7C, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0xA5, 0x7C, 0x20, 0x00, 0xE9, 0x7C, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0xA9, 0x84, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x0D, 0xCC, 0x20, 0x00, 0xED, 0x84, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x1F, 0xB5, 0x06, 0xF0, 0x09, 0xF8, 0x15, 0xF0, 0xEE, 0xFF, 0x1F, 0xBD, 0x47, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x20, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x11, 0xFE, 0x20, 0x06, 0x01, 0xD5, 0x00, 0xF0, + 0x0D, 0xFE, 0x20, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x09, 0xFE, 0x20, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0x05, 0xFE, 0x20, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x01, 0xFE, 0x20, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xFD, 0xFD, 0x20, 0x01, 0x01, 0xD5, 0x00, 0xF0, + 0xF9, 0xFD, 0x00, 0x2C, 0x03, 0xDA, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xF3, 0xBD, 0x10, 0xBD, 0x34, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x60, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0xEB, 0xFD, 0x60, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0xE7, 0xFD, 0x60, 0x05, + 0x01, 0xD5, 0x00, 0xF0, 0xE3, 0xFD, 0x60, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0xDF, 0xFD, 0x60, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0xDB, 0xFD, 0x60, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xD7, 0xFD, 0x60, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0xD3, 0xFD, 0x60, 0x00, + 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xCD, 0xBD, 0x10, 0xBD, 0x21, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xA0, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0xC5, 0xFD, 0xA0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0xC1, 0xFD, 0xA0, 0x04, 0x01, 0xD5, 0x00, 0xF0, + 0xBD, 0xFD, 0xA0, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0xB9, 0xFD, 0xA0, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xB5, 0xFD, 0xA0, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0xB1, 0xFD, 0xA0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xAB, 0xBD, 0x10, 0xBD, + 0x10, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xE0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0xA3, 0xFD, 0xE0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x9F, 0xFD, 0xE0, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0x9B, 0xFD, 0xE0, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x97, 0xFD, 0xE0, 0x02, + 0x01, 0xD5, 0x00, 0xF0, 0x93, 0xFD, 0xE0, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0x8F, 0xFD, 0xE0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x89, 0xBD, 0x10, 0xBD, 0x00, 0x10, 0x00, 0x40, 0x4F, 0xF0, 0x80, 0x42, 0xD2, 0xF8, 0x10, 0x02, + 0x40, 0xF4, 0x80, 0x30, 0xC2, 0xF8, 0x10, 0x02, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF4, 0x40, 0x40, 0xC2, 0xF8, 0x30, 0x02, 0xFE, 0x49, 0x51, 0xF8, 0x50, 0x3B, 0xFE, 0x48, 0x03, 0x60, 0x51, 0xF8, 0x48, 0x3C, 0x43, 0x60, 0x0B, 0x6E, 0x83, 0x60, + 0x51, 0xF8, 0x3C, 0x3C, 0xC3, 0x60, 0x51, 0xF8, 0x34, 0x3C, 0x03, 0x61, 0x4B, 0x6E, 0x43, 0x61, 0x51, 0xF8, 0x28, 0x3C, 0x83, 0x61, 0x51, 0xF8, 0x20, 0x3C, 0xC3, 0x61, 0x8B, 0x6E, 0x03, 0x62, 0x51, 0xF8, 0x14, 0x3C, 0x43, 0x62, 0x51, 0xF8, + 0x0C, 0x3C, 0x83, 0x62, 0xCB, 0x6E, 0xC3, 0x62, 0x0B, 0x68, 0x03, 0x63, 0x8B, 0x68, 0x43, 0x63, 0x0B, 0x6F, 0x83, 0x63, 0x4B, 0x69, 0xC3, 0x63, 0xCB, 0x69, 0x03, 0x64, 0x4B, 0x6F, 0x43, 0x64, 0x8B, 0x6A, 0x83, 0x64, 0x0B, 0x6B, 0xC3, 0x64, + 0x8B, 0x6F, 0x03, 0x65, 0xCB, 0x6B, 0x43, 0x65, 0x4B, 0x6C, 0x83, 0x65, 0xC9, 0x6F, 0xC1, 0x65, 0xD2, 0xF8, 0x5C, 0x13, 0x01, 0x66, 0xD2, 0xF8, 0x60, 0x13, 0x41, 0x66, 0xD2, 0xF8, 0x64, 0x13, 0xF8, 0x38, 0xC1, 0x60, 0xD2, 0xF8, 0x68, 0x13, + 0x01, 0x61, 0x70, 0x47, 0x4F, 0xF0, 0x80, 0x42, 0xD2, 0xF8, 0x10, 0x02, 0x40, 0xF4, 0x80, 0x30, 0xC2, 0xF8, 0x10, 0x02, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF4, 0x40, 0x40, 0xC2, 0xF8, 0x30, 0x02, 0xD4, 0x48, 0x01, 0x6E, 0xC2, 0xF8, 0x5C, 0x13, + 0x41, 0x6E, 0xC2, 0xF8, 0x60, 0x13, 0xD0, 0x49, 0x03, 0x68, 0x41, 0xF8, 0x50, 0x3B, 0x43, 0x68, 0x41, 0xF8, 0x48, 0x3C, 0x83, 0x68, 0x0B, 0x66, 0xC3, 0x68, 0x41, 0xF8, 0x3C, 0x3C, 0x03, 0x69, 0x41, 0xF8, 0x34, 0x3C, 0x43, 0x69, 0x4B, 0x66, + 0x83, 0x69, 0x41, 0xF8, 0x28, 0x3C, 0xC3, 0x69, 0x41, 0xF8, 0x20, 0x3C, 0x03, 0x6A, 0x8B, 0x66, 0x43, 0x6A, 0x41, 0xF8, 0x14, 0x3C, 0x83, 0x6A, 0x41, 0xF8, 0x0C, 0x3C, 0xC3, 0x6A, 0xCB, 0x66, 0x03, 0x6B, 0x0B, 0x60, 0x43, 0x6B, 0x8B, 0x60, + 0x83, 0x6B, 0x0B, 0x67, 0xC3, 0x6B, 0x4B, 0x61, 0x03, 0x6C, 0xCB, 0x61, 0x43, 0x6C, 0x4B, 0x67, 0x83, 0x6C, 0x8B, 0x62, 0xC3, 0x6C, 0x0B, 0x63, 0x03, 0x6D, 0x8B, 0x67, 0x43, 0x6D, 0xCB, 0x63, 0x83, 0x6D, 0x4B, 0x64, 0xC0, 0x6D, 0xC8, 0x67, + 0xB4, 0x48, 0xF8, 0x38, 0xC1, 0x68, 0xC2, 0xF8, 0x64, 0x13, 0x00, 0x69, 0xC2, 0xF8, 0x68, 0x03, 0x70, 0x47, 0x10, 0xB5, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, + 0x41, 0xF0, 0x80, 0x51, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x1C, 0x12, 0x41, 0xF0, 0x01, 0x01, 0xC0, 0xF8, 0x1C, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x40, 0x71, 0xC0, 0xF8, 0x38, 0x12, 0xA3, 0x48, 0xC1, 0x68, 0x21, 0xF0, 0x1F, 0x01, + 0xC1, 0x60, 0xA0, 0x49, 0x68, 0x31, 0xCA, 0x6A, 0x02, 0x65, 0x82, 0x68, 0x6F, 0xF3, 0x0F, 0x02, 0x82, 0x60, 0xCA, 0x68, 0x02, 0x61, 0x0A, + 0x69, 0x42, 0x61, 0x4A, 0x69, 0x82, 0x61, 0x8A, 0x69, 0xC2, 0x61, 0xCA, 0x69, 0x02, 0x62, 0x0A, + 0x6A, 0x42, 0x62, 0x4A, 0x6A, 0x82, 0x62, 0x8A, 0x6A, 0xC2, 0x62, 0x4A, 0x68, 0x82, 0x60, 0x0A, + 0x68, 0x22, 0xF0, 0x03, 0x02, 0x42, 0x60, 0x0A, + 0x6B, 0x42, 0x65, 0x4A, 0x6B, 0x82, 0x65, 0x42, 0x68, 0x42, 0xF0, 0x80, 0x62, 0x42, 0x60, 0xC2, 0x68, 0x42, 0xF4, 0xF8, 0x52, 0xC2, 0x60, 0x89, 0x68, 0xC1, 0x60, 0x4F, 0xF4, 0x88, 0x74, 0x20, 0x46, 0x36, 0xF6, 0x6C, 0xFF, 0x40, 0xF0, 0x04, + 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x36, 0xF6, 0x75, 0xBF, 0x7C, 0xB5, 0x00, 0x24, 0x4F, 0xF0, 0xE0, 0x20, 0x01, 0x21, 0xC0, 0xF8, 0x80, 0x11, 0xD0, 0xF8, 0x00, 0x21, 0x7F, 0x49, 0xE4, 0x39, 0x0A, + 0x60, 0xD0, 0xF8, 0x00, 0x22, 0x4A, 0x60, 0xD0, 0xF8, 0x00, 0x03, 0x88, 0x60, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x92, 0xF8, 0x00, 0x24, 0x41, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0x20, 0x28, 0xF6, 0xD3, 0x78, 0x48, 0x00, 0x68, 0xC1, 0xF8, 0x80, + 0x00, 0x77, 0x48, 0xC0, 0x68, 0x73, 0x4D, 0xF8, 0x3D, 0x05, 0xF1, 0x98, 0x02, 0x28, 0x60, 0x00, 0x20, 0x81, 0x00, 0x01, 0xF1, 0x80, 0x41, 0xD1, 0xF8, 0x80, 0x12, 0x42, 0xF8, 0x20, 0x10, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x04, 0xF0, 0xE5, 0xFD, 0xA8, 0x68, 0x00, 0xB1, 0x80, 0x47, 0xFF, 0xF7, 0xC1, 0xFE, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x00, + 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x18, 0x12, 0x41, 0xF4, 0x80, 0x21, 0xC0, 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x30, 0x01, 0xC0, 0xF8, 0x38, 0x12, 0x4F, 0xF0, 0x40, 0x21, 0x0B, 0x68, 0x58, 0x4A, 0x14, 0x3A, 0x13, + 0x60, 0x4B, 0x68, 0x53, 0x60, 0xCB, 0x68, 0x93, 0x60, 0x4B, 0x69, 0xD3, 0x60, 0xC9, 0x69, 0x11, 0x61, 0xD0, 0xF8, 0x18, 0x12, 0x41, 0xF4, 0x80, 0x61, 0xC0, 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x34, 0x12, 0x41, 0xF4, 0x40, 0x11, 0xC0, 0xF8, 0x34, + 0x12, 0x51, 0x49, 0x0B, 0x68, 0xB4, 0x32, 0x13, 0x60, 0x4B, 0x68, 0x53, 0x60, 0x8B, 0x69, 0x93, 0x60, 0x49, 0x6A, 0xD1, 0x60, 0xD0, 0xF8, 0x1C, 0x12, 0x41, 0xF4, 0x80, 0x71, 0xC0, 0xF8, 0x1C, 0x12, 0xD0, 0xF8, 0x30, 0x12, 0x41, 0xF0, 0x40, + 0x71, 0xC0, 0xF8, 0x30, 0x12, 0x47, 0x4A, 0x13, 0x68, 0x41, 0x49, 0x38, 0x39, 0x0B, 0x60, 0x53, 0x68, 0x4B, 0x60, 0x93, 0x68, 0x8B, 0x60, 0x13, 0x6B, 0xCB, 0x60, 0x53, 0x6B, 0x0B, 0x61, 0x93, 0x6B, 0x4B, 0x61, 0xD3, 0x6B, 0x8B, 0x61, 0x92, + 0x6C, 0xCA, 0x61, 0xD0, 0xF8, 0x44, 0x03, 0x08, 0x62, 0x00, 0xF0, 0x08, 0xF9, 0x4F, 0xF4, 0x00, 0x15, 0x95, 0xF8, 0x34, 0x03, 0xC0, 0x07, 0x0F, 0xD0, 0x00, 0x94, 0x02, 0x23, 0x01, 0x22, 0x00, 0x21, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xA7, + 0xF9, 0x00, 0x94, 0x02, 0x23, 0x01, 0x22, 0x00, 0x21, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0x9F, 0xF9, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x23, 0x00, 0xF0, 0x3F, 0x00, 0x1A, 0x46, 0x00, 0x21, 0x09, 0xF6, 0x94, 0xF9, 0x7C, + 0xBD, 0x30, 0xB5, 0x24, 0x49, 0x00, 0x20, 0x85, 0xB0, 0x60, 0x39, 0x82, 0x00, 0x02, 0xF1, 0x80, 0x42, 0x51, 0xF8, 0x20, 0x30, 0xC2, 0xF8, 0x80, 0x32, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x00, 0x24, 0x4F, 0xF4, 0x00, 0x15, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x22, 0x00, 0xF0, 0x3F, 0x00, 0x23, 0x46, 0x11, 0x46, 0x05, 0xF5, 0x66, 0x75, 0x09, 0xF6, 0x73, 0xF9, 0x15, 0xF8, 0x64, 0x0C, 0xC0, + 0x07, 0x0F, 0xD0, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0x67, 0xF9, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0x5F, 0xF9, 0x04, 0xF0, 0x3E, 0xFD, 0xFF, + 0xF7, 0x5B, 0xFE, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x00, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x18, 0x12, 0x0D, 0xE0, 0x00, 0x20, 0x00, + 0x40, 0xA4, 0xE8, 0x20, 0x00, 0x00, 0x00, 0x01, 0x40, 0x08, 0xED, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x40, 0x00, 0x30, 0x00, 0x40, 0x00, 0x10, 0x00, 0x40, 0x41, 0xF4, 0x80, 0x21, 0xC0, 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x30, + 0x01, 0xC0, 0xF8, 0x38, 0x12, 0x65, 0x49, 0x4F, 0xF0, 0x40, 0x22, 0x0B, 0x68, 0x13, 0x60, 0x4B, 0x68, 0x53, 0x60, 0x8B, 0x68, 0xD3, 0x60, 0xCB, 0x68, 0x53, 0x61, 0x09, 0x69, 0xD1, 0x61, 0xD0, 0xF8, 0x18, 0x12, 0x41, 0xF4, 0x80, 0x61, 0xC0, + 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x34, 0x12, 0x41, 0xF4, 0x40, 0x11, 0xC0, 0xF8, 0x34, 0x12, 0x59, 0x4A, 0x59, 0x49, 0xB4, 0x32, 0x10, 0x68, 0x08, 0x60, 0x50, 0x68, 0x48, 0x60, 0x00, 0x28, 0x04, 0xDA, 0x90, 0x68, 0x88, 0x61, 0xD0, 0x68, 0x48, + 0x62, 0x00, 0xE0, 0x4C, 0x61, 0x00, 0xF0, 0x33, 0xF8, 0xFF, 0xF7, 0x5D, 0xFE, 0x4F, 0x4D, 0xE4, 0x3D, 0x68, 0x68, 0x00, 0xB1, 0x80, 0x47, 0x01, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x03, 0x20, 0x03, 0x90, 0x8D, 0xF8, 0x08, 0x40, 0x02, 0xA8, 0x09, + 0xF6, 0x69, 0xF8, 0x48, 0x4C, 0xD0, 0x3C, 0x63, 0x68, 0x58, 0x08, 0x04, 0xD0, 0x01, 0x22, 0x47, 0x49, 0x47, 0x48, 0xFF, 0xF5, 0x2E, 0xFC, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x14, 0xF8, 0x20, 0x10, 0x82, 0xF8, 0x00, 0x14, 0x40, 0x1C, 0x20, + 0x28, 0xF6, 0xD3, 0x42, 0x49, 0xD4, 0xF8, 0x80, 0x00, 0x08, 0x60, 0x41, 0x49, 0x28, 0x68, 0xC8, 0x60, 0x4F, 0xF0, 0xE0, 0x21, 0x20, 0x68, 0xC1, 0xF8, 0x00, 0x01, 0x05, 0xB0, 0x30, 0xBD, 0x10, 0xB5, 0x4F, 0xF0, 0x80, 0x42, 0xD2, 0xF8, 0x1C, + 0x02, 0x40, 0xF4, 0x80, 0x70, 0xC2, 0xF8, 0x1C, 0x02, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF0, 0x40, 0x70, 0xC2, 0xF8, 0x30, 0x02, 0x2F, 0x48, 0x35, 0x49, 0x24, 0x38, 0x43, 0x68, 0x4B, 0x60, 0x84, 0x68, 0x8C, 0x60, 0x04, 0x69, 0x4C, 0x63, 0x44, + 0x69, 0x8C, 0x63, 0x84, 0x69, 0xCC, 0x63, 0xC4, 0x69, 0x8C, 0x64, 0x04, 0x68, 0x0C, 0x60, 0xDB, 0x43, 0xCB, 0x64, 0xC3, 0x68, 0x0B, 0x63, 0x00, 0x6A, 0xC2, 0xF8, 0x44, 0x03, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, + 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x51, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x1C, 0x12, 0x41, 0xF0, 0x01, 0x01, 0xC0, 0xF8, 0x1C, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x40, + 0x71, 0xC0, 0xF8, 0x38, 0x12, 0x1C, 0x48, 0x42, 0x68, 0x14, 0x49, 0x7C, 0x31, 0x0A, + 0x60, 0x82, 0x68, 0x4A, 0x60, 0xC2, 0x68, 0x8A, 0x60, 0x02, 0x69, 0xCA, 0x60, 0x42, 0x69, 0x0A, + 0x61, 0x82, 0x69, 0x4A, 0x61, 0xC2, 0x69, 0x8A, 0x61, 0x02, 0x6A, 0xCA, 0x61, 0x42, 0x6A, 0x0A, + 0x62, 0x82, 0x6A, 0x4A, 0x62, 0x82, 0x6A, 0x8A, 0x62, 0x02, 0x6D, 0xCA, 0x62, 0x42, 0x6D, 0x0A, + 0x63, 0x80, 0x6D, 0x4F, 0xF4, 0x88, 0x74, 0x48, 0x63, 0x20, 0x46, 0x36, 0xF6, 0x82, 0xFD, 0x20, 0xF0, 0x04, 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x36, 0xF6, 0x8B, 0xBD, 0x00, 0x00, 0x90, 0xE8, 0x20, 0x00, 0x00, 0x30, 0x00, 0x40, 0xE8, + 0x00, 0x80, 0x08, 0x01, 0x04, 0x10, 0x21, 0x08, 0xED, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x40, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x40, 0x26, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0x03, 0xF0, 0x7D, 0xBE, 0x70, + 0x47, 0x22, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0x03, 0xF0, 0x91, 0xBE, 0x70, 0x47, 0x1E, 0x48, 0x10, 0xB5, 0x40, 0x78, 0x38, 0xB1, 0x1D, 0x48, 0x00, 0x78, 0x20, 0xB1, 0x15, 0xF0, 0x21, 0xF9, 0x08, 0xB1, 0x01, + 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x22, 0x18, 0x49, 0x18, 0x48, 0xFF, 0xF5, 0x70, 0xFB, 0x00, 0x26, 0x4F, 0xF0, 0xE0, 0x25, 0x01, 0x24, 0xC5, 0xF8, 0x80, 0x41, 0x2B, 0x20, 0x36, 0xF6, 0x3A, 0xFD, 0x01, + 0x06, 0x17, 0xD5, 0x40, 0xF0, 0x80, 0x01, 0x2B, 0x20, 0x36, 0xF6, 0x54, 0xFD, 0x00, 0x20, 0x03, 0xF0, 0xAE, 0xFD, 0x0A, + 0x4F, 0x32, 0x21, 0x0D, 0x48, 0x7E, 0x70, 0xBC, 0x70, 0x1E, 0xF6, 0x46, 0xFC, 0x38, 0xB9, 0x08, 0x49, 0x09, 0x48, 0x00, 0x22, 0x38, 0x31, 0x80, 0x1E, 0xFF, 0xF5, 0x4E, 0xFB, 0x7C, 0x70, 0xC5, 0xF8, 0x80, 0x42, 0xBD, 0xE8, 0xF0, 0x81, 0x70, + 0xF2, 0x20, 0x00, 0xCC, 0xF2, 0x20, 0x00, 0x08, 0xF3, 0x20, 0x00, 0xF0, 0x10, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0xC8, 0xF2, 0x20, 0x00, 0x2B, 0x48, 0x10, 0xB5, 0x81, 0x7C, 0x01, 0x29, 0x0B, 0xD1, 0x40, 0x7D, 0x01, 0x28, 0x08, 0xD0, 0x02, + 0x20, 0x03, 0xF0, 0x6E, 0xF8, 0x05, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x26, 0x20, 0x04, 0xF0, 0xEE, 0xBA, 0x10, 0xBD, 0x22, 0x48, 0x10, 0xB5, 0x80, 0x7C, 0x03, 0x28, 0x09, 0xD1, 0x00, 0x22, 0x20, 0x49, 0x21, 0x48, 0xFF, 0xF5, 0x21, 0xFB, 0xBD, + 0xE8, 0x10, 0x40, 0x04, 0x20, 0x03, 0xF0, 0x7C, 0xB8, 0x10, 0xBD, 0x1A, 0x48, 0x10, 0xB5, 0x83, 0x7C, 0x04, 0x2B, 0x08, 0xD0, 0x19, 0x49, 0x19, 0x48, 0x01, 0x22, 0x30, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x40, 0x1E, 0xFF, 0xF5, 0x0D, 0xBB, 0x16, + 0x48, 0x40, 0x78, 0x01, 0x28, 0x0B, 0xD0, 0x4F, 0xF4, 0xFA, 0x62, 0x0E, 0x21, 0x0C, 0x20, 0x03, 0xF0, 0x8A, 0xF8, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x02, 0xF0, 0x4D, 0xB8, 0xBD, 0xE8, 0x10, 0x40, 0x41, 0xF2, 0x88, 0x31, 0x0D, + 0x48, 0x1E, 0xF6, 0xE6, 0xBB, 0x08, 0x48, 0x10, 0xB5, 0x80, 0x7C, 0x04, 0x28, 0x0A, + 0xD1, 0x06, 0x49, 0x00, 0x22, 0x68, 0x31, 0x06, 0x48, 0xFF, 0xF5, 0xEB, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0x20, 0x03, 0xF0, 0x46, 0xB8, 0x10, 0xBD, 0x70, 0xF2, 0x20, 0x00, 0xFC, 0x26, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x08, 0xF3, 0x20, + 0x00, 0xA8, 0xF2, 0x20, 0x00, 0x1C, 0xB5, 0x0D, 0x4C, 0x20, 0x46, 0xE1, 0x68, 0x00, 0x21, 0x14, 0xF0, 0x92, 0xFB, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x1A, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x68, 0x46, 0x03, 0xF0, 0x20, 0xF9, 0x20, 0xB9, 0x00, + 0x22, 0x05, 0x49, 0x06, 0x48, 0xFF, 0xF5, 0xC5, 0xFA, 0x01, 0x21, 0x20, 0x46, 0x14, 0xF0, 0x7F, 0xFB, 0x1C, 0xBD, 0x00, 0x00, 0x78, 0x20, 0x00, 0x40, 0x9C, 0x28, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x2D, 0xE9, 0xFF, 0x41, 0x47, 0x4E, 0x30, + 0x6A, 0x4F, 0xF0, 0x00, 0x48, 0x10, 0xF4, 0x00, 0x3F, 0x59, 0xD0, 0x45, 0x4C, 0x01, 0x25, 0x2A, 0x46, 0x65, 0x70, 0x04, 0x21, 0x30, 0x46, 0x13, 0xF0, 0x1C, 0xFE, 0x30, 0x6A, 0x41, 0x4F, 0xC0, 0xF3, 0x05, 0x12, 0xA2, 0x61, 0xCA, 0xB3, 0x04, + 0xF1, 0x1C, 0x01, 0x30, 0x46, 0x13, 0xF0, 0x19, 0xFE, 0xA5, 0x70, 0x00, 0x20, 0xE0, 0x70, 0x32, 0x21, 0x20, 0x1F, 0x1E, 0xF6, 0x86, 0xFB, 0x10, 0xB1, 0x20, 0x78, 0x18, 0xB1, 0x10, 0xE0, 0x00, 0x22, 0x37, 0x49, 0x35, 0xE0, 0x34, 0x48, 0x14, + 0x22, 0x18, 0x30, 0x21, 0x1D, 0x06, 0x46, 0x51, 0xF6, 0x5B, 0xFC, 0x00, 0x28, 0x34, 0xD0, 0x14, 0x22, 0x31, 0x46, 0x20, 0x1D, 0x51, 0xF6, 0x26, 0xFD, 0x2D, 0x48, 0xAD, 0xF8, 0x00, 0x50, 0x00, 0x1D, 0x01, 0x90, 0xAD, 0xF8, 0x02, 0x50, 0x68, + 0x46, 0x03, 0xF0, 0xCC, 0xF8, 0x00, 0x28, 0x23, 0xD1, 0x29, 0x49, 0x00, 0x22, 0x40, 0x31, 0x38, 0x46, 0xFF, 0xF5, 0x6F, 0xFA, 0x03, 0xF0, 0xB4, 0xFC, 0x23, 0x48, 0x00, 0x1F, 0x1E, 0xF6, 0x6C, 0xFB, 0x13, 0xE0, 0xFF, 0xE7, 0xE0, 0x78, 0x70, + 0xB9, 0xAD, 0xF8, 0x08, 0x50, 0x03, 0x20, 0xAD, 0xF8, 0x0A, + 0x00, 0x02, 0xA8, 0x03, 0xF0, 0xB2, 0xF8, 0x28, 0xB9, 0x1D, 0x49, 0x00, 0x22, 0x8C, 0x31, 0x38, 0x46, 0xFF, 0xF5, 0x56, 0xFA, 0x03, 0xF0, 0x9B, 0xFC, 0x40, 0x46, 0x03, 0xF0, 0xA2, 0xFC, 0xBD, 0xE8, 0xFF, 0x81, 0x01, 0xB5, 0x14, 0x48, 0x82, + 0xB0, 0x81, 0x78, 0x01, 0x29, 0x0A, + 0xD0, 0x01, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x03, 0x20, 0xAD, 0xF8, 0x02, 0x00, 0x68, 0x46, 0x03, 0xF0, 0x95, 0xF8, 0x58, 0xB1, 0x0F, 0xE0, 0x00, 0x21, 0x81, 0x70, 0x41, 0x70, 0x08, 0x46, 0x03, 0xF0, 0x89, 0xFC, 0x0A, + 0x21, 0x02, 0xA8, 0x1E, 0xF6, 0x24, 0xFB, 0x0E, 0xBD, 0x00, 0x22, 0x09, 0x49, 0x06, 0x48, 0xFF, 0xF5, 0x2E, 0xFA, 0x03, 0xF0, 0x73, 0xFC, 0x4F, 0xF0, 0x00, 0x40, 0x03, 0xF0, 0x79, 0xFC, 0x0E, 0xBD, 0x00, 0x50, 0x00, 0x40, 0xCC, 0xF2, 0x20, + 0x00, 0x00, 0x30, 0x10, 0x21, 0xDC, 0x31, 0x80, 0x08, 0xDC, 0x32, 0x80, 0x08, 0x70, 0xB5, 0x37, 0x4C, 0x01, 0x22, 0x37, 0x49, 0x37, 0x48, 0x63, 0x68, 0xFF, 0xF5, 0x15, 0xFA, 0x60, 0x68, 0x01, 0x28, 0x2B, 0xD1, 0x35, 0x4C, 0x00, 0x25, 0x20, + 0x78, 0x10, 0xB1, 0x25, 0x70, 0x43, 0xF6, 0x84, 0xFD, 0x65, 0x72, 0xA0, 0x7C, 0x40, 0xB1, 0x01, 0x28, 0x0B, 0xD0, 0x04, 0x28, 0x1D, 0xD1, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0x02, 0xF0, 0x5F, 0xBF, 0xBD, 0xE8, 0x70, 0x40, 0x03, 0x20, 0x02, + 0xF0, 0x6D, 0xBD, 0x60, 0x7D, 0x03, 0x28, 0x09, 0xD0, 0x01, 0x28, 0x02, 0xD0, 0x27, 0x48, 0x1E, 0xF6, 0xF5, 0xFA, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0x02, 0xF0, 0x29, 0xBF, 0xBD, 0xE8, 0x70, 0x40, 0x44, 0xF6, 0x20, 0x61, 0x21, 0x48, 0x1E, + 0xF6, 0xD6, 0xBA, 0x70, 0xBD, 0x7C, 0xB5, 0x1B, 0x4C, 0x1D, 0x4E, 0x1C, 0x4D, 0x61, 0x78, 0x20, 0x78, 0xCD, 0xE9, 0x00, 0x01, 0x18, 0x49, 0xB3, 0x7C, 0x03, 0x22, 0x44, 0x31, 0x28, 0x46, 0xFF, 0xF5, 0xD6, 0xF9, 0xB0, 0x7C, 0x04, 0x28, 0x11, + 0xD1, 0x21, 0x78, 0x00, 0x29, 0x0E, 0xD0, 0x60, 0x78, 0x68, 0xB1, 0x06, 0x29, 0x1A, 0xD0, 0x10, 0x49, 0x00, 0x22, 0xEC, 0x31, 0x28, 0x46, 0xFF, 0xF5, 0xC6, 0xF9, 0x20, 0x78, 0x03, 0xF0, 0x14, 0xFD, 0x00, 0x20, 0x20, 0x70, 0x7C, 0xBD, 0x06, + 0x29, 0xFA, 0xD0, 0x09, 0x49, 0x00, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFF, 0xF5, 0xB8, 0xF9, 0x20, 0x78, 0x03, 0xF0, 0x06, 0xFD, 0x20, 0x78, 0x60, 0x70, 0x00, 0x20, 0xEB, 0xE7, 0x03, 0xF0, 0x96, 0xFF, 0xEA, 0xE7, 0x00, 0x00, 0x00, 0xF3, 0x20, + 0x00, 0xE4, 0x33, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x70, 0xF2, 0x20, 0x00, 0xA0, 0xF2, 0x20, 0x00, 0x7C, 0xB5, 0x01, 0x21, 0x08, 0x46, 0x00, 0xF0, 0x63, 0xFB, 0x17, 0x4D, 0x68, 0x78, 0x01, 0x28, 0x20, 0xD1, 0x00, 0x22, 0x15, 0x49, 0x16, + 0x48, 0xFF, 0xF5, 0x95, 0xF9, 0x06, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x00, 0x26, 0xAD, 0xF8, 0x02, 0x60, 0xA8, 0x78, 0x05, 0xF2, 0xE3, 0x14, 0x90, 0xB1, 0x01, 0x94, 0x68, 0x46, 0x02, 0xF0, 0xDC, 0xFF, 0x0F, 0x48, 0x0E, 0x49, 0x01, 0x60, 0xA9, + 0x78, 0x69, 0xB1, 0xAE, 0x70, 0xED, 0x1C, 0x85, 0x60, 0x78, 0x21, 0xC1, 0x61, 0x01, 0x21, 0x08, 0x46, 0x00, 0xF0, 0xE8, 0xFA, 0x7C, 0xBD, 0x04, 0x48, 0xC0, 0x1C, 0x01, 0x90, 0xE9, 0xE7, 0x01, 0x21, 0xA9, 0x70, 0x84, 0x60, 0xF0, 0xE7, 0x00, + 0x00, 0x08, 0xF3, 0x20, 0x00, 0x88, 0x38, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x10, 0x00, 0x02, 0x40, 0x58, 0x70, 0x02, 0x40, 0x2D, 0xE9, 0xFC, 0x5F, 0x32, 0x21, 0x26, 0x48, 0x1E, 0xF6, 0x4F, 0xFA, 0xDF, 0xF8, 0x90, 0x90, 0xDF, 0xF8, 0x90, + 0xA0, 0xA9, 0xF1, 0x04, 0x09, 0x4F, 0xF0, 0x01, 0x0B, 0xD9, 0xF8, 0x00, 0x10, 0x49, 0x1C, 0x00, 0x27, 0x3C, 0x46, 0xC9, 0xF8, 0x00, 0x10, 0x1D, 0x48, 0x00, 0x26, 0x04, 0xEB, 0x44, 0x01, 0x00, 0x1D, 0x00, 0xEB, 0xC1, 0x05, 0x68, 0x69, 0x20, + 0xB3, 0x04, 0xF0, 0xA2, 0xF8, 0x0A, + 0xEB, 0xC0, 0x01, 0xD9, 0xF8, 0x00, 0x30, 0x4A, 0x78, 0x1A, 0xF8, 0x30, 0xC0, 0xB3, 0xFB, 0xF2, 0xF8, 0x02, 0xFB, 0x18, 0x33, 0x01, 0x27, 0x0B, 0xFA, 0x03, 0xF3, 0x5A, 0x46, 0x84, 0x45, 0x00, 0xD1, 0x4E, 0x68, 0x33, 0x42, 0x02, 0xD0, 0x00, + 0x92, 0x01, 0x92, 0x02, 0xE0, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0xB0, 0x00, 0x23, 0x68, 0x78, 0x01, 0x22, 0x19, 0x46, 0x08, 0xF6, 0xE4, 0xFD, 0x20, 0x46, 0x04, 0xF0, 0x45, 0xF8, 0x64, 0x1C, 0x14, 0xF0, 0xFF, 0x04, 0xCD, 0xD0, 0x00, 0x2F, 0x04, + 0xD1, 0xBD, 0xE8, 0xFC, 0x5F, 0x02, 0x48, 0x1E, 0xF6, 0x1A, 0xBA, 0xBD, 0xE8, 0xFC, 0x9F, 0x30, 0x13, 0x21, 0x00, 0xEC, 0xE1, 0x20, 0x00, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0x49, 0xEF, 0xF3, 0x05, 0x82, 0x10, 0x4B, 0x98, 0x47, 0xFE, 0xE7, 0x70, + 0x47, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x20, 0x49, 0x53, 0x52, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, + 0x72, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64, 0x21, 0x0A, + 0x00, 0x4E, 0x88, 0x20, 0x00, 0xB1, 0x79, 0x00, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x94, 0xF8, 0x9B, 0x03, 0x40, 0xF0, 0x80, 0x00, 0x84, 0xF8, 0x9B, 0x03, 0x94, 0xF8, 0xDC, 0x02, 0xC1, 0x07, 0x4F, 0xF0, 0x04, 0x50, 0x03, 0xD0, 0x6C, + 0xA1, 0xFF, 0xF5, 0x80, 0xF8, 0x06, 0xE0, 0x6D, 0xA1, 0xFF, 0xF5, 0x7C, 0xF8, 0x09, 0xF6, 0x43, 0xF8, 0x1D, 0xF6, 0x81, 0xFF, 0x94, 0xF8, 0x9A, 0x03, 0xC0, 0x07, 0x02, 0xD0, 0x00, 0x20, 0xFF, 0xF5, 0x83, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0x05, + 0xF2, 0x99, 0xB5, 0x40, 0xEA, 0x01, 0x21, 0x01, 0x20, 0xFE, 0xF5, 0xE0, 0xBC, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x00, 0x22, 0x94, 0xF8, 0x4C, 0x13, 0x60, 0xF3, 0x01, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x11, 0x46, 0x45, 0xF2, 0x02, 0x00, 0x03, + 0xF6, 0xBA, 0xFB, 0x00, 0x28, 0x05, 0xD1, 0x94, 0xF8, 0x4C, 0x13, 0x21, 0xF0, 0x03, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x10, 0xBD, 0x01, 0x46, 0x40, 0xF2, 0x5D, 0x43, 0x5F, 0x4A, 0x00, 0x20, 0x1D, 0xF6, 0x21, 0xBA, 0x5D, 0x4A, 0x41, 0x43, 0xD2, + 0x1D, 0x40, 0xF2, 0x62, 0x43, 0x00, 0x20, 0x1D, 0xF6, 0x45, 0xBA, 0x10, 0xB5, 0x0C, 0x46, 0x08, 0xB1, 0x1D, 0xF6, 0x9F, 0xFA, 0x56, 0x4A, 0x21, 0x46, 0x0E, 0x32, 0xBD, 0xE8, 0x10, 0x40, 0x40, 0xF2, 0x6C, 0x43, 0x00, 0x20, 0x1D, 0xF6, 0x0A, + 0xBA, 0x1D, 0xF6, 0x93, 0xBA, 0x51, 0x4A, 0xD1, 0x70, 0x51, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x4F, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x4D, 0x48, 0x00, 0x68, 0x70, 0x47, 0x4A, + 0x48, 0x10, 0xB5, 0x0E, 0x22, 0x4B, 0x49, 0x10, 0x30, 0x51, 0xF6, 0x8D, 0xFA, 0x46, 0x48, 0x10, 0x30, 0x10, 0xBD, 0x48, 0x48, 0x80, 0x1E, 0x00, 0x78, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, + 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x3A, 0x49, 0xBE, 0xB0, 0x40, 0x22, 0x18, 0x31, 0x2D, 0xA8, 0x51, 0xF6, 0xF9, 0xFA, 0x37, 0x49, 0xB4, 0x22, 0x58, 0x31, 0x68, 0x46, 0x51, 0xF6, 0xF3, 0xFA, 0x3C, + 0x49, 0x4F, 0xF4, 0x00, 0x10, 0x38, 0x4E, 0x39, 0x4F, 0x09, 0x68, 0x05, 0x46, 0x00, 0x24, 0xA9, 0x42, 0x01, 0xD0, 0xFC, 0xF5, 0x67, 0xF9, 0xDF, 0xF8, 0xDC, 0x80, 0x4F, 0xF0, 0x05, 0x59, 0xDF, 0xF8, 0xD8, 0xA0, 0x2F, 0xE0, 0x6C, 0xB3, 0x01, + 0x2C, 0x2B, 0xD0, 0x56, 0xF8, 0x24, 0x00, 0x40, 0x45, 0x00, 0xD0, 0x38, 0xB9, 0x40, 0x45, 0x24, 0xD1, 0x55, 0xF8, 0x24, 0x00, 0xA0, 0xF5, 0x80, 0x71, 0x55, 0x39, 0x1E, 0xD1, 0x10, 0x2C, 0x09, 0xD2, 0x2D, 0xA8, 0x50, 0xF8, 0x24, 0x10, 0x48, + 0x46, 0xFF, 0xF5, 0x29, 0xFA, 0x03, 0x46, 0x01, 0x22, 0x28, 0x49, 0x0B, 0xE0, 0x68, 0x46, 0x00, 0xEB, 0x84, 0x00, 0x50, 0xF8, 0x40, 0x1C, 0x48, 0x46, 0xFF, 0xF5, 0x1D, 0xFA, 0x23, 0x49, 0x01, 0x22, 0x03, 0x46, 0x24, 0x31, 0x50, 0x46, 0xFF, + 0xF5, 0x10, 0xF8, 0x56, 0xF8, 0x24, 0x00, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0xB4, 0xEB, 0x97, 0x0F, 0xCC, 0xD3, 0xBF, 0xF3, 0x5F, 0x8F, 0xBF, 0xF3, 0x4F, 0x8F, 0x3E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x49, 0x6E, 0x20, 0x53, 0x6F, 0x43, 0x20, + 0x4D, 0x6F, 0x64, 0x65, 0x00, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x3A, 0x20, 0x49, 0x6E, 0x20, 0x48, 0x43, 0x49, 0x20, 0x4D, 0x6F, 0x64, 0x65, 0x2C, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, + 0x41, 0x50, 0x50, 0x20, 0x54, 0x61, 0x73, 0x6B, 0x00, 0x80, 0xE2, 0x21, 0x00, 0xE0, 0xE5, 0x20, 0x00, 0x8C, 0xE7, 0x20, 0x00, 0x90, 0xE7, 0x20, 0x00, 0xF4, 0x00, 0x20, 0x00, 0xF5, 0x28, 0x20, 0x00, 0x9C, 0xE6, 0x80, 0x00, 0xF4, 0x00, 0x00, + 0x00, 0x08, 0xED, 0x00, 0xE0, 0x3D, 0x88, 0x20, 0x00, 0x01, 0x01, 0x10, 0x21, 0x9C, 0x00, 0x80, 0x08, 0x10, 0xB5, 0x00, 0x21, 0x04, 0x48, 0xFF, 0xF5, 0x10, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x02, 0x48, 0xFF, 0xF5, 0x0A, + 0xBE, 0x00, 0x00, 0x3B, 0x7F, 0x20, 0x00, 0xB7, 0x80, 0x20, 0x00, 0x00, 0x22, 0xCC, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x13, 0xF0, 0x66, 0xBB, 0xF0, 0xB5, 0xCA, 0x69, 0x02, 0x60, 0x0A, + 0x6A, 0x82, 0x60, 0xC8, 0x4A, 0x01, 0x25, 0xC2, 0xF8, 0x98, 0x53, 0xD2, 0xF8, 0xA0, 0x33, 0x0C, 0x78, 0x05, 0xFA, 0x04, 0xF3, 0xD2, 0xF8, 0x38, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x38, 0x43, 0xD2, 0xF8, 0x40, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x40, + 0x43, 0xD2, 0xF8, 0x50, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x50, 0x43, 0xD2, 0xF8, 0x48, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x48, 0x43, 0xD2, 0xF8, 0x58, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x58, 0x43, 0x0B, 0x78, 0x08, 0x33, 0x05, 0xFA, 0x03, 0xF4, 0xC2, + 0xF8, 0x10, 0x43, 0xC2, 0xF8, 0x18, 0x43, 0xC2, 0xF8, 0x28, 0x43, 0xC2, 0xF8, 0x20, 0x43, 0xC2, 0xF8, 0x30, 0x43, 0x0B, 0x69, 0xCC, 0x68, 0x05, 0xEB, 0x43, 0x03, 0x43, 0xEA, 0x04, 0x13, 0x4C, 0x7A, 0x43, 0xEA, 0xC4, 0x13, 0x0C, 0x7A, 0x43, + 0xEA, 0x44, 0x23, 0x8C, 0x69, 0x43, 0xEA, 0xC4, 0x23, 0x4C, 0x69, 0x43, 0xEA, 0x84, 0x33, 0x4C, 0x78, 0x43, 0xEA, 0x04, 0x53, 0x83, 0x61, 0x4B, 0x68, 0xC3, 0x61, 0x4B, 0x78, 0x33, 0xB1, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x10, 0xD0, 0x00, + 0x24, 0x04, 0x64, 0x05, 0xE0, 0x4F, 0xF4, 0x40, 0x63, 0x01, 0xE0, 0x4F, 0xF4, 0x00, 0x63, 0x03, 0x64, 0x9C, 0x4F, 0x91, 0xF8, 0x2E, 0x30, 0x58, 0x37, 0x9B, 0x4E, 0x01, 0x2B, 0x03, 0xD0, 0x17, 0xE0, 0x4F, 0xF4, 0x80, 0x63, 0xF3, 0xE7, 0xB8, + 0x42, 0x01, 0xD1, 0x01, 0x23, 0x00, 0xE0, 0x00, 0x23, 0xB0, 0x42, 0x01, 0xD1, 0x01, 0x24, 0x00, 0xE0, 0x00, 0x24, 0x23, 0x43, 0x08, 0xD0, 0x83, 0x69, 0x43, 0xF4, 0x00, 0x33, 0x83, 0x61, 0x0C, 0x8E, 0x4B, 0x6B, 0x43, 0xEA, 0x04, 0x53, 0x83, + 0x64, 0x91, 0xF8, 0x2D, 0x30, 0x01, 0x2B, 0x13, 0xD1, 0xB8, 0x42, 0x00, 0xD1, 0x00, 0xE0, 0x00, 0x23, 0xB0, 0x42, 0x01, 0xD1, 0x01, 0x24, 0x00, 0xE0, 0x00, 0x24, 0x23, 0x43, 0x08, 0xD0, 0x83, 0x69, 0x43, 0xF4, 0x80, 0x23, 0x83, 0x61, 0x0C, + 0x8F, 0xCB, 0x6B, 0x43, 0xEA, 0x04, 0x53, 0x03, 0x65, 0x91, 0xF8, 0x2C, 0x30, 0x01, 0x2B, 0x22, 0xD1, 0x90, 0x42, 0x00, 0xD1, 0x00, 0xE0, 0x00, 0x23, 0x7D, 0x4C, 0x58, 0x3C, 0xA0, 0x42, 0x01, 0xD1, 0x01, 0x24, 0x00, 0xE0, 0x00, 0x24, 0x23, + 0x43, 0x15, 0xD0, 0x03, 0x6C, 0x23, 0xF0, 0x40, 0x43, 0x03, 0x64, 0x83, 0x69, 0x23, 0xF0, 0xC0, 0x53, 0x83, 0x61, 0x0B, 0x6C, 0x03, 0xF0, 0x40, 0x44, 0x13, 0xF0, 0xC0, 0x53, 0x04, 0xD0, 0x8E, 0x6A, 0x06, 0x61, 0x86, 0x69, 0x1E, 0x43, 0x86, + 0x61, 0x03, 0x6C, 0x23, 0x43, 0x03, 0x64, 0x43, 0x6C, 0x6E, 0x4C, 0x23, 0x40, 0x43, 0x64, 0x91, 0xF8, 0x44, 0x30, 0x03, 0xF0, 0x10, 0x04, 0x64, 0xF3, 0x1F, 0x13, 0x44, 0x6C, 0x44, 0xEA, 0xC3, 0x13, 0x43, 0x64, 0x91, 0xF8, 0x45, 0x30, 0x03, + 0xF0, 0x0F, 0x04, 0x03, 0xF0, 0x10, 0x03, 0x44, 0xEA, 0x43, 0x03, 0x44, 0x6C, 0x44, 0xEA, 0xC3, 0x23, 0x43, 0x64, 0x91, 0xF8, 0x45, 0x30, 0x18, 0x2B, 0x06, 0xD3, 0x61, 0x4E, 0x74, 0x6A, 0x08, 0x3B, 0x05, 0xFA, 0x03, 0xF3, 0x1C, 0x43, 0x74, + 0x62, 0x43, 0x6C, 0x23, 0xF0, 0x03, 0x03, 0x43, 0x64, 0x43, 0x6C, 0x43, 0xF0, 0x02, 0x03, 0x43, 0x64, 0x08, 0x78, 0x85, 0x40, 0xD2, 0xF8, 0x38, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x38, 0x03, 0xD2, 0xF8, 0x40, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x40, + 0x03, 0xD2, 0xF8, 0x50, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x50, 0x03, 0xD2, 0xF8, 0x48, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x48, 0x03, 0xD2, 0xF8, 0x58, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x58, 0x03, 0xF0, 0xBD, 0x00, 0x21, 0x02, 0x22, 0x01, 0x70, 0x42, + 0x70, 0xC8, 0x23, 0x43, 0x60, 0x02, 0x72, 0x41, 0x72, 0xC1, 0x60, 0x01, 0x61, 0x41, 0x61, 0x81, 0x61, 0xC1, 0x61, 0x01, 0x62, 0x4F, 0xF0, 0xC0, 0x52, 0x02, 0x64, 0x41, 0x62, 0x80, 0xF8, 0x44, 0x10, 0x80, 0xF8, 0x45, 0x10, 0x80, 0xF8, 0x2C, + 0x10, 0x80, 0xF8, 0x2D, 0x10, 0x80, 0xF8, 0x2E, 0x10, 0x81, 0x62, 0x81, 0x63, 0xC1, 0x63, 0x01, 0x63, 0x41, 0x63, 0x70, 0x47, 0x10, 0xB5, 0x01, 0x24, 0x00, 0xF1, 0x08, 0x03, 0x04, 0xFA, 0x03, 0xF2, 0x34, 0x4B, 0x39, 0xB1, 0x84, 0x40, 0xD3, + 0xF8, 0xA0, 0x03, 0x14, 0x43, 0x04, 0x43, 0xC3, 0xF8, 0xA0, 0x43, 0x10, 0xBD, 0xC3, 0xF8, 0xA0, 0x23, 0x10, 0xBD, 0x30, 0xB5, 0x01, 0x23, 0x00, 0xF1, 0x08, 0x05, 0x03, 0xFA, 0x05, 0xF4, 0x2B, 0x4D, 0x2A, 0xB3, 0x83, 0x40, 0x23, 0x43, 0xC8, + 0x07, 0x04, 0xD0, 0xD5, 0xF8, 0x10, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x10, 0x03, 0x88, 0x07, 0x04, 0xD5, 0xD5, 0xF8, 0x18, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x18, 0x03, 0x48, 0x07, 0x04, 0xD5, 0xD5, 0xF8, 0x20, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x20, + 0x03, 0x08, 0x07, 0x04, 0xD5, 0xD5, 0xF8, 0x28, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x28, 0x03, 0xC8, 0x06, 0x04, 0xD5, 0xD5, 0xF8, 0x30, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x30, 0x03, 0x30, 0xBD, 0xC8, 0x07, 0x01, 0xD0, 0xC5, 0xF8, 0x10, 0x43, 0x88, + 0x07, 0x01, 0xD5, 0xC5, 0xF8, 0x18, 0x43, 0x48, 0x07, 0x01, 0xD5, 0xC5, 0xF8, 0x20, 0x43, 0x08, 0x07, 0x01, 0xD5, 0xC5, 0xF8, 0x28, 0x43, 0xC8, 0x06, 0xEC, 0xD5, 0xC5, 0xF8, 0x30, 0x43, 0x30, 0xBD, 0x01, 0x22, 0x82, 0x40, 0x0B, 0x48, 0xCB, + 0x07, 0x01, 0xD0, 0xC0, 0xF8, 0x38, 0x23, 0x8B, 0x07, 0x01, 0xD5, 0xC0, 0xF8, 0x40, 0x23, 0x4B, 0x07, 0x01, 0xD5, 0xC0, 0xF8, 0x48, 0x23, 0x0B, 0x07, 0x01, 0xD5, 0xC0, 0xF8, 0x50, 0x23, 0xC9, 0x06, 0x01, 0xD5, 0xC0, 0xF8, 0x58, 0x23, 0x70, + 0x47, 0x00, 0x00, 0x01, 0x20, 0x00, 0x70, 0x02, 0x40, 0x08, 0x71, 0x02, 0x40, 0x7F, 0x00, 0xFE, 0xFF, 0x00, 0x60, 0x00, 0x40, 0x00, 0x22, 0x4F, 0xF0, 0x04, 0x51, 0x5D, 0x48, 0x13, 0xF0, 0xC2, 0xB9, 0x03, 0x79, 0x5C, 0x49, 0x01, 0x2B, 0x02, + 0x68, 0x4B, 0x68, 0x30, 0xD0, 0x93, 0x43, 0x4B, 0x60, 0x42, 0x79, 0x01, 0x2A, 0x2A, 0xD1, 0x00, 0x22, 0x4A, 0x63, 0x82, 0x79, 0x8A, 0xB3, 0x01, 0x2A, 0x3D, 0xD0, 0x8A, 0x6E, 0x03, 0x68, 0x1A, 0x43, 0x8A, 0x66, 0xC2, 0x79, 0x52, 0xB3, 0xCB, + 0x6B, 0x02, 0x68, 0x93, 0x43, 0x13, 0x43, 0xCB, 0x63, 0x02, 0x7A, 0x7A, 0xB3, 0x8B, 0x6C, 0x02, 0x68, 0x93, 0x43, 0x13, 0x43, 0x8B, 0x64, 0x4F, 0xF0, 0x80, 0x41, 0x4F, 0xF4, 0xE0, 0x52, 0xC1, 0xF8, 0x44, 0x23, 0xD1, 0xF8, 0x44, 0x23, 0xC0, + 0x68, 0x44, 0xF6, 0x20, 0x63, 0x58, 0x43, 0xFF, 0x23, 0x03, 0xEB, 0x50, 0x30, 0xC0, 0xB2, 0x02, 0x43, 0xC1, 0xF8, 0x44, 0x23, 0x70, 0x47, 0x13, 0x43, 0x4B, 0x60, 0x42, 0x7A, 0x00, 0x2A, 0x8A, 0x68, 0x00, 0x68, 0x04, 0xD0, 0x02, 0x43, 0x8A, + 0x60, 0x70, 0x47, 0x02, 0xE0, 0x11, 0xE0, 0x82, 0x43, 0xF9, 0xE7, 0x8A, 0x6B, 0x03, 0x68, 0x9A, 0x43, 0x8A, 0x63, 0x0A, + 0x6E, 0x03, 0x68, 0x1A, 0x43, 0x0A, + 0x66, 0xC6, 0xE7, 0x0A, + 0xE0, 0x8B, 0x6B, 0x02, 0x68, 0x93, 0x43, 0x13, 0x43, 0x8B, 0x63, 0xBF, 0xE7, 0xCA, 0x6B, 0x03, 0x68, 0x9A, 0x43, 0xCA, 0x63, 0xC1, 0xE7, 0x8A, 0x6C, 0x00, 0x68, 0x82, 0x43, 0x8A, 0x64, 0xE0, 0xE7, 0x4F, 0xF0, 0xFF, 0x31, 0x01, 0x60, 0x00, + 0x21, 0x01, 0x71, 0x41, 0x71, 0x81, 0x71, 0xC1, 0x71, 0x01, 0x72, 0x41, 0x72, 0x14, 0x21, 0xC1, 0x60, 0xD3, 0xE7, 0x26, 0x4A, 0x00, 0x29, 0x11, 0x6B, 0x01, 0xD0, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x11, 0x63, 0xCA, 0xE7, 0x22, 0x49, 0xC8, + 0x64, 0xC7, 0xE7, 0x20, 0x4A, 0x00, 0x29, 0x51, 0x6B, 0x01, 0xD0, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x51, 0x63, 0xBE, 0xE7, 0x01, 0x21, 0x1E, 0x28, 0x0E, 0xD9, 0xA0, 0xF1, 0x20, 0x02, 0x03, 0x2A, 0x01, 0xD8, 0x00, 0x1F, 0x08, 0xE0, 0x24, + 0x28, 0x05, 0xD0, 0x25, 0x28, 0x03, 0xD0, 0x26, 0x28, 0x01, 0xD0, 0xFF, 0x20, 0xAD, 0xE7, 0x0B, 0x38, 0x01, 0xFA, 0x00, 0xF0, 0xA9, 0xE7, 0x1E, 0x28, 0xA7, 0xD9, 0xA0, 0xF1, 0x20, 0x01, 0x03, 0x29, 0x01, 0xD8, 0x00, 0x1F, 0x08, 0xE0, 0x24, + 0x28, 0x05, 0xD0, 0x25, 0x28, 0x03, 0xD0, 0x26, 0x28, 0x01, 0xD0, 0xFF, 0x20, 0x99, 0xE7, 0x0B, 0x38, 0xC0, 0xB2, 0x96, 0xE7, 0x4F, 0xF0, 0x80, 0x41, 0x00, 0x28, 0xD1, 0xF8, 0x44, 0x03, 0x02, 0xD0, 0x40, 0xF4, 0x80, 0x50, 0x01, 0xE0, 0x20, + 0xF4, 0x80, 0x50, 0xC1, 0xF8, 0x44, 0x03, 0x88, 0xE7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x40, 0x10, 0xB5, 0x4A, 0x88, 0x0B, 0x88, 0x42, 0xEA, 0x03, 0x12, 0x02, 0x60, 0x0A, + 0x79, 0x01, 0x2A, 0x0A, + 0xD1, 0xCA, 0x89, 0x8B, 0x89, 0x4C, 0x89, 0x42, 0xEA, 0x03, 0x12, 0x0B, 0x89, 0x5B, 0x03, 0x43, 0xEA, 0x04, 0x33, 0x1A, 0x43, 0x42, 0x60, 0x4A, 0x79, 0x01, 0x2A, 0x0A, + 0xD1, 0xCA, 0x8A, 0x8B, 0x8A, 0x4C, 0x8A, 0x42, 0xEA, 0x03, 0x12, 0x0B, 0x8A, 0x5B, 0x03, 0x43, 0xEA, 0x04, 0x33, 0x1A, 0x43, 0xC2, 0x60, 0x8A, 0x79, 0x01, 0x2A, 0x0A, + 0xD1, 0xCA, 0x8B, 0x8B, 0x8B, 0x42, 0xEA, 0x03, 0x12, 0x0B, 0x8B, 0x49, 0x8B, 0x5B, 0x03, 0x43, 0xEA, 0x01, 0x31, 0x0A, + 0x43, 0x42, 0x61, 0x10, 0xBD, 0x00, 0x22, 0x53, 0x49, 0x54, 0x48, 0x13, 0xF0, 0xD0, 0xB8, 0x27, 0x21, 0x01, 0x80, 0x00, 0x21, 0x41, 0x80, 0x01, 0x71, 0x40, 0xF2, 0x71, 0x22, 0x82, 0x81, 0x01, 0x81, 0x41, 0x81, 0xC1, 0x81, 0x41, 0x71, 0x82, + 0x82, 0x01, 0x82, 0x41, 0x82, 0xC1, 0x82, 0x81, 0x71, 0x82, 0x83, 0x01, 0x83, 0x41, 0x83, 0xC1, 0x83, 0x70, 0x47, 0x01, 0x2A, 0x4F, 0xEA, 0xC1, 0x72, 0x23, 0xD0, 0x1A, 0xB1, 0x42, 0x68, 0x22, 0xF4, 0x00, 0x42, 0x42, 0x60, 0x4A, 0x07, 0x03, + 0xD5, 0xC2, 0x68, 0x22, 0xF4, 0x00, 0x42, 0xC2, 0x60, 0xCA, 0x06, 0x03, 0xD5, 0x42, 0x69, 0x22, 0xF4, 0x00, 0x42, 0x42, 0x61, 0x8A, 0x07, 0x03, 0xD5, 0x42, 0x68, 0x22, 0xF4, 0x80, 0x42, 0x42, 0x60, 0x0A, + 0x07, 0x03, 0xD5, 0x42, 0x68, 0x22, 0xF4, 0x80, 0x42, 0x42, 0x60, 0x89, 0x06, 0x03, 0xD5, 0x41, 0x68, 0x21, 0xF4, 0x80, 0x41, 0x41, 0x60, 0x70, 0x47, 0x1A, 0xB1, 0x42, 0x68, 0x42, 0xF4, 0x00, 0x42, 0x42, 0x60, 0x4A, 0x07, 0x03, 0xD5, 0xC2, + 0x68, 0x42, 0xF4, 0x00, 0x42, 0xC2, 0x60, 0xCA, 0x06, 0x03, 0xD5, 0x42, 0x69, 0x42, 0xF4, 0x00, 0x42, 0x42, 0x61, 0x8A, 0x07, 0x03, 0xD5, 0x42, 0x68, 0x42, 0xF4, 0x80, 0x42, 0x42, 0x60, 0x0A, + 0x07, 0x03, 0xD5, 0xC2, 0x68, 0x42, 0xF4, 0x80, 0x42, 0xC2, 0x60, 0x89, 0x06, 0xDF, 0xD5, 0x41, 0x69, 0x41, 0xF4, 0x80, 0x41, 0x41, 0x61, 0x70, 0x47, 0x02, 0x46, 0x00, 0x20, 0x47, 0xF2, 0x07, 0x03, 0x19, 0x42, 0x04, 0xD0, 0x12, 0x6A, 0x0A, + 0x42, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x08, 0x29, 0x0C, 0xD0, 0x10, 0x29, 0x0C, 0xD0, 0x20, 0x29, 0x0D, 0xD0, 0x40, 0x29, 0x0D, 0xD0, 0x80, 0x29, 0x0D, 0xD0, 0xB1, 0xF5, 0x80, 0x7F, 0xF1, 0xD1, 0x91, 0x69, 0x09, 0xE0, 0x91, 0x68, 0x00, + 0xE0, 0x11, 0x69, 0x49, 0x03, 0x05, 0xE0, 0x91, 0x69, 0xFB, 0xE7, 0x91, 0x68, 0x00, 0xE0, 0x11, 0x69, 0x09, 0x03, 0x00, 0x29, 0xE1, 0xDB, 0x70, 0x47, 0x01, 0x2A, 0x05, 0xD0, 0x4F, 0xF0, 0x40, 0x22, 0xD0, 0x69, 0x88, 0x43, 0xD0, 0x61, 0x70, + 0x47, 0xC2, 0x69, 0x0A, + 0x43, 0xC2, 0x61, 0x70, 0x47, 0x49, 0x08, 0x00, 0xEB, 0x81, 0x00, 0x01, 0x2A, 0x41, 0x68, 0x03, 0xD0, 0x21, 0xF0, 0x40, 0x41, 0x41, 0x60, 0x70, 0x47, 0x41, 0xF0, 0x40, 0x41, 0xFA, 0xE7, 0x00, 0x00, 0x10, 0x00, 0x00, 0x60, 0x00, 0x00, 0x04, + 0x08, 0x70, 0xB5, 0x13, 0x46, 0x01, 0x24, 0x9A, 0x4A, 0x09, 0x28, 0x06, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x0C, 0x15, 0x21, 0x2A, 0x33, 0x3C, 0x45, 0x4C, 0x56, 0x00, 0x00, 0x24, 0x22, 0x46, 0x95, 0x49, 0x95, 0x48, 0xFE, 0xF5, 0x66, 0xFC, 0x12, + 0xE0, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x11, 0x70, 0x8F, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x0C, 0x30, 0x07, 0xE0, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x51, 0x70, 0x8B, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x20, 0x30, 0x50, 0xF6, 0x70, 0xFE, 0x20, 0x46, 0x70, 0xBD, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x91, 0x70, 0x85, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x34, 0x30, 0xF2, 0xE7, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0xD1, 0x70, 0x80, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x48, 0x30, 0xE9, 0xE7, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x11, 0x71, 0x7C, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x5C, 0x30, 0xE0, 0xE7, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x51, 0x71, 0x77, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x70, 0x30, 0xD7, 0xE7, 0x08, 0x29, 0x00, 0xD9, 0x08, 0x21, 0x0A, + 0x46, 0x19, 0x46, 0x75, 0x48, 0xD0, 0xE7, 0x1E, 0x29, 0x00, 0xD9, 0x1E, 0x21, 0x73, 0x48, 0x0A, + 0x46, 0x08, 0x38, 0x01, 0x70, 0x19, 0x46, 0x10, 0x30, 0xC6, 0xE7, 0x07, 0x29, 0x00, 0xD9, 0x07, 0x21, 0x6E, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0xC0, 0x1F, 0xBE, 0xE7, 0x2D, 0xE9, 0xFC, 0x47, 0x92, 0x46, 0xDD, 0xE9, 0x0A, + 0x45, 0x0A, + 0x46, 0x00, 0x26, 0x26, 0x80, 0x02, 0x21, 0x8D, 0xF8, 0x04, 0x10, 0x8D, 0xF8, 0x05, 0x00, 0xAA, 0xF1, 0x02, 0x00, 0x08, 0x27, 0xDF, 0xF8, 0x80, 0x81, 0x4F, 0xF0, 0x07, 0x09, 0x11, 0x28, 0x0A, + 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x1E, 0x09, 0x8C, 0x09, 0x2C, 0x09, 0x49, 0x09, 0x3B, 0x09, 0x57, 0x09, 0x13, 0x09, 0x65, 0x09, 0x72, 0x00, 0x59, 0x49, 0x53, 0x46, 0x01, 0x22, 0x1C, 0x31, 0x58, 0x48, 0xFE, 0xF5, 0xEB, 0xFB, 0x40, 0xF2, 0x0A, + 0x46, 0x6B, 0xE0, 0x8D, 0xF8, 0x06, 0x90, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x52, 0x48, 0x28, 0x60, 0x27, 0x80, 0x60, 0xE0, 0x01, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, + 0x47, 0x49, 0x48, 0x0C, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x00, 0x00, 0x0C, 0xE0, 0x03, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x42, 0x48, 0x34, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x02, 0x00, 0x20, + 0x80, 0x43, 0xE0, 0x05, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x3B, 0x48, 0x5C, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x04, 0x00, 0xEF, 0xE7, 0x04, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, + 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x34, 0x48, 0x48, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x03, 0x00, 0xE1, 0xE7, 0x06, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x2D, 0x48, 0x70, 0x30, 0x28, + 0x60, 0x98, 0xF8, 0x05, 0x00, 0xD3, 0xE7, 0x8D, 0xF8, 0x06, 0x70, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x29, 0x48, 0x08, 0x30, 0x28, 0x60, 0x10, 0x38, 0x00, 0x78, 0xC6, 0xE7, 0x09, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, + 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x22, 0x48, 0xC0, 0x1F, 0x28, 0x60, 0xA4, 0xF8, 0x00, 0x90, 0x20, 0x88, 0x00, 0x90, 0x1D, 0x49, 0x1D, 0x48, 0x53, 0x46, 0x02, 0x22, 0x44, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0x72, 0xFB, 0x30, + 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x8D, 0xF8, 0x06, 0x10, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x13, 0x48, 0x20, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x01, 0x00, 0x9F, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x13, 0x48, 0xD0, 0xE9, 0x06, + 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF5, 0x00, 0x71, 0x43, 0x69, 0x4F, 0xF4, 0x05, 0x72, 0x02, 0xA8, 0x46, 0xF6, 0x5B, 0xF9, 0x50, 0xB9, 0x09, 0x49, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x7C, 0x31, 0x07, 0x48, 0xFE, 0xF5, 0x4A, 0xFB, 0xFF, + 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x02, 0x48, 0x84, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x00, 0x00, 0x60, 0xE9, 0x20, 0x00, 0x14, 0x01, 0x80, 0x08, 0x00, 0x33, 0x10, 0x21, 0xEC, 0xE5, 0x20, 0x00, 0x2C, 0xDE, 0x20, 0x00, 0x10, 0xB5, 0x01, + 0x24, 0x01, 0x28, 0x06, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x53, 0x49, 0x54, 0x48, 0xFE, 0xF5, 0x2D, 0xFB, 0x06, 0xE0, 0x01, 0x29, 0x01, 0xD0, 0x00, 0x24, 0x02, 0xE0, 0x51, 0x49, 0x10, 0x78, 0x08, 0x70, 0x20, 0x46, 0x10, 0xBD, 0x07, 0xB5, 0x82, + 0xB0, 0x00, 0x23, 0x01, 0x22, 0xCD, 0xE9, 0x00, 0x23, 0x04, 0xAB, 0x02, 0x22, 0x46, 0xF6, 0xBC, 0xF9, 0x05, 0xB0, 0x00, 0xBD, 0x07, 0xB5, 0x48, 0x4B, 0x82, 0xB0, 0x5A, 0x78, 0x4A, 0xB1, 0x00, 0x22, 0x5A, 0x70, 0x01, 0x23, 0xCD, 0xE9, 0x00, + 0x32, 0x04, 0xAB, 0x02, 0x22, 0x46, 0xF6, 0x23, 0xF9, 0xEE, 0xE7, 0x00, 0x20, 0xEC, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0xDD, 0xE9, 0x08, 0x67, 0x00, 0x20, 0x30, 0x80, 0x88, 0x46, 0x00, 0x93, 0x39, 0x49, 0x3A, 0x48, 0x14, 0x46, 0x13, + 0x46, 0x02, 0x22, 0x1C, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0xF4, 0xFA, 0x02, 0x2C, 0x0A, + 0xD0, 0x34, 0x49, 0x23, 0x46, 0x01, 0x22, 0x4C, 0x31, 0x33, 0x48, 0xFE, 0xF5, 0xEB, 0xFA, 0x40, 0xF2, 0x0A, + 0x40, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x8D, 0xF8, 0x00, 0x50, 0x2E, 0x4D, 0x01, 0x24, 0x8D, 0xF8, 0x02, 0x40, 0x6A, 0x68, 0x69, 0x46, 0x40, 0x46, 0x90, 0x47, 0xA0, 0xF5, 0x50, 0x61, 0x01, 0x39, 0x00, 0xD1, 0x6C, + 0x70, 0x3D, 0x60, 0x34, 0x80, 0xE8, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x26, 0x8D, 0xF8, 0x05, 0x60, 0x88, 0x46, 0x8D, 0xF8, 0x04, 0x00, 0x1D, 0x46, 0x00, 0x93, 0x1F, 0x49, 0x1F, 0x48, 0x17, 0x46, 0x13, 0x46, 0x34, 0x46, 0x02, 0x22, 0x7C, + 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0xBE, 0xFA, 0x03, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x1A, 0x48, 0x42, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xE8, 0x07, 0x02, 0xD0, 0x8D, + 0xF8, 0x06, 0x60, 0xEF, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xEB, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x10, 0x48, 0xD0, 0xE9, 0x1D, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0x01, 0x46, 0x03, 0x6F, 0x70, 0x22, 0x02, 0xA8, 0x46, 0xF6, 0xA2, 0xF8, 0x50, + 0xB9, 0x07, 0x49, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x06, 0x48, 0xFE, 0xF5, 0x91, 0xFA, 0xFF, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x04, 0x48, 0x44, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0xB4, 0x01, 0x80, 0x08, 0x00, 0x33, 0x10, + 0x21, 0xE4, 0xE9, 0x20, 0x00, 0x8C, 0xE3, 0x21, 0x00, 0x2D, 0xE9, 0xFF, 0x47, 0x17, 0x46, 0xDD, 0xE9, 0x0C, 0x86, 0x89, 0x46, 0x01, 0x24, 0x13, 0x46, 0x00, 0x25, 0x22, 0x46, 0x3D, 0x49, 0x3E, 0x48, 0xFE, 0xF5, 0x73, 0xFA, 0x03, 0x20, 0x02, + 0x2F, 0x0F, 0xD0, 0x05, 0x2F, 0x1E, 0xD0, 0x00, 0x24, 0x40, 0xF2, 0x0A, + 0x45, 0x39, 0x48, 0x02, 0x68, 0x1A, 0xB1, 0x14, 0xB1, 0x69, 0x46, 0x48, 0x46, 0x90, 0x47, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xB8, 0xF1, 0x10, 0x0F, 0x09, 0xD1, 0x46, 0xB1, 0x8D, 0xF8, 0x00, 0x00, 0x01, 0x20, 0x8D, 0xF8, 0x04, + 0x00, 0x10, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x0A, + 0xE0, 0x00, 0x24, 0x4F, 0xF4, 0x90, 0x65, 0xE3, 0xE7, 0x8D, 0xF8, 0x00, 0x00, 0x02, 0x20, 0x8D, 0xF8, 0x04, 0x00, 0x8D, 0xF8, 0x08, 0x80, 0x03, 0x96, 0xDA, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x86, 0xB0, 0x88, 0x46, 0x1E, 0x46, 0x01, 0x24, 0x00, + 0x93, 0x21, 0x49, 0x17, 0x46, 0x13, 0x46, 0x25, 0x46, 0x8D, 0xF8, 0x04, 0x40, 0x02, 0x22, 0x34, 0x31, 0x1E, 0x48, 0xFE, 0xF5, 0x34, 0xFA, 0x03, 0x2F, 0x0C, 0xD0, 0x00, 0x24, 0x1C, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, + 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xF0, 0x07, 0x8D, 0xF8, 0x04, 0x50, 0x02, 0xD0, 0x8D, 0xF8, 0x08, 0x50, 0xEC, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xE8, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x11, + 0x48, 0xD0, 0xE9, 0x0B, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF1, 0x80, 0x01, 0x83, 0x6A, 0xA8, 0x22, 0x02, 0xA8, 0x46, 0xF6, 0x14, 0xF8, 0x20, 0xB1, 0x09, 0x48, 0x04, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x05, 0x49, 0x9D, 0xF8, 0x08, + 0x30, 0x01, 0x22, 0x6C, 0x31, 0x03, 0x48, 0xFE, 0xF5, 0xFE, 0xF9, 0xFF, 0x20, 0x3E, 0xBD, 0x00, 0x00, 0xB8, 0x03, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0xF8, 0xE9, 0x20, 0x00, 0x88, 0xE4, 0x21, 0x00, 0x2D, 0xE9, 0xF7, 0x4F, 0x86, 0xB0, 0x00, + 0x24, 0x03, 0x94, 0x10, 0x20, 0x8D, 0xF8, 0x0C, 0x00, 0xDF, 0xF8, 0x24, 0x94, 0x0A, + 0x20, 0x96, 0x46, 0x04, 0x94, 0x8D, 0xF8, 0x0D, 0x00, 0x4F, 0xF4, 0x00, 0x62, 0x01, 0x26, 0x07, 0x27, 0xDF, 0xF8, 0x0C, 0xB4, 0xD9, 0xF8, 0x14, 0x00, 0x25, 0x46, 0xA9, 0xF6, 0x14, 0x0A, + 0x91, 0x42, 0x20, 0xD9, 0xCD, 0xE9, 0x00, 0x20, 0x0B, 0x46, 0x4C, 0x46, 0x03, 0x22, 0xFE, 0x49, 0x58, 0x46, 0xFE, 0xF5, 0xCE, 0xF9, 0xAA, 0xF8, 0x02, 0x50, 0x02, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x9A, 0xF8, 0x01, 0x10, 0x32, 0xE0, 0xBA, 0xF8, 0x02, 0x30, 0x8B, 0x42, 0x06, 0xD0, 0xD9, 0xF8, + 0x0C, 0x20, 0x00, 0xEB, 0x03, 0x0C, 0xC8, 0x46, 0x94, 0x45, 0x75, 0xD1, 0x72, 0x46, 0xD0, 0x46, 0x19, 0x46, 0xDA, 0xF8, 0x10, 0x00, 0x3E, 0xF6, 0x2A, 0xF8, 0x28, 0xB3, 0xE6, 0x49, 0x4C, 0x46, 0x01, 0x22, 0x48, 0x31, 0x58, 0x46, 0xD9, 0xF8, + 0x14, 0x30, 0xFE, 0xF5, 0x9A, 0xF9, 0xA8, 0xF8, 0x02, 0x50, 0x05, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x98, 0xF8, 0x01, 0x10, 0x03, 0xAB, 0x04, 0x22, 0x06, 0x98, 0x46, 0xF6, 0x23, 0xF8, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0x82, 0x46, 0xB8, 0xF8, 0x02, 0x00, 0x00, 0x1B, 0x10, 0x28, 0x11, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0xCB, 0x48, 0x07, 0xF6, + 0x49, 0xFA, 0xD8, 0xF8, 0x10, 0x00, 0x20, 0x44, 0x01, 0x46, 0xFF, 0xF5, 0x3B, 0xFB, 0x10, 0x34, 0xA4, 0xB2, 0xE8, 0xE7, 0x02, 0xF0, 0xA2, 0xF8, 0xB9, 0xF8, 0x04, 0x00, 0x44, 0x46, 0xD9, 0xF8, 0x14, 0x10, 0xB8, 0xF8, 0x02, 0x20, 0xD8, 0xF8, + 0x10, 0x30, 0x02, 0xF0, 0xF6, 0xF9, 0x03, 0x00, 0x4F, 0xF4, 0x80, 0x5A, 0x19, 0xD0, 0xBC, 0x49, 0x01, 0x22, 0x7C, 0x31, 0x58, 0x46, 0xFE, 0xF5, 0x48, 0xF9, 0xC8, 0x46, 0xB9, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x61, 0x68, 0x02, 0xF0, 0x2B, 0xF9, + 0x4F, 0xF0, 0x08, 0x09, 0xD0, 0xB1, 0x65, 0x80, 0xB3, 0x49, 0x63, 0x68, 0x01, 0x22, 0x45, 0x46, 0xB4, 0x31, 0xC8, 0xF8, 0x14, 0x30, 0x2E, 0xE0, 0x58, 0xE0, 0x62, 0x88, 0xD9, 0xF8, 0x14, 0x00, 0x10, 0x44, 0xC9, 0xF8, 0x14, 0x00, 0x61, 0x68, + 0x42, 0x1A, 0x52, 0x45, 0x02, 0xD3, 0x01, 0xF5, 0x80, 0x51, 0x61, 0x60, 0x65, 0x80, 0x8D, 0xF8, 0x0E, 0x60, 0x22, 0xE0, 0xD8, 0xF8, 0x14, 0x00, 0x61, 0x68, 0x40, 0x1A, 0x50, 0x45, 0x32, 0xD9, 0xA3, 0x49, 0xA1, 0x48, 0x00, 0x22, 0xF4, 0x31, + 0x80, 0x1C, 0xFE, 0xF5, 0x16, 0xF9, 0x61, 0x68, 0xB8, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x01, 0xF5, 0x80, 0x51, 0x02, 0xF0, 0xF8, 0xF8, 0x10, 0xB3, 0x65, 0x80, 0x63, 0x68, 0x9C, 0x49, 0x45, 0x46, 0x01, 0x22, 0xC8, 0xF8, 0x14, 0x30, 0x58, 0x46, + 0xFE, 0xF5, 0x03, 0xF9, 0x8D, 0xF8, 0x0E, 0x90, 0x68, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x06, 0x98, 0x45, 0xF6, 0x90, 0xFF, 0x02, 0xF0, 0x48, 0xF8, 0x69, 0xE7, 0x65, 0x80, + 0x8B, 0x49, 0x87, 0x48, 0x63, 0x68, 0x45, 0x46, 0x01, 0x22, 0x40, 0x31, 0x80, 0x1C, 0xC8, 0xF8, 0x14, 0x30, 0xFE, 0xF5, 0xDE, 0xF8, 0x8D, 0xF8, 0x0E, 0x70, 0xD9, 0xE7, 0xCD, 0xE9, 0x00, 0x30, 0x0B, 0x46, 0x83, 0x49, 0x02, 0x92, 0x54, 0x46, + 0x04, 0x22, 0x70, 0x31, 0x58, 0x46, 0xFE, 0xF5, 0xD0, 0xF8, 0x65, 0x80, 0x06, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0xD8, 0xF8, 0x14, 0x00, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x35, 0xE7, 0x3E, 0xB5, 0x70, 0x4B, 0x04, 0x46, 0x58, 0x7E, 0x01, 0x28, 0x1D, 0xD1, + 0x00, 0x22, 0x5A, 0x76, 0x02, 0x92, 0x10, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x07, 0x20, 0x8D, 0xF8, 0x09, 0x00, 0x8D, 0xF8, 0x0A, + 0x10, 0x0B, 0x46, 0x6A, 0x49, 0x66, 0x48, 0x01, 0x22, 0xD8, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0xA0, 0xF8, 0x01, 0x21, 0x03, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x66, 0x48, 0x02, 0xAB, 0x04, 0x22, 0x41, 0x78, 0x20, 0x46, 0x45, 0xF6, 0x38, 0xFF, 0x3E, + 0xBD, 0x3E, 0xB5, 0x05, 0x46, 0x00, 0x20, 0x02, 0x90, 0x5C, 0x48, 0x80, 0x88, 0x02, 0xF0, 0xD7, 0xF9, 0x04, 0x46, 0x03, 0x46, 0x58, 0x48, 0x01, 0x22, 0x5D, 0x49, 0x80, 0x1C, 0xFE, 0xF5, 0x84, 0xF8, 0x01, 0x20, 0x14, 0xB1, 0x8D, 0xF8, 0x0A, + 0x00, 0x02, 0xE0, 0x05, 0x21, 0x8D, 0xF8, 0x0A, + 0x10, 0x10, 0x21, 0x8D, 0xF8, 0x08, 0x10, 0x03, 0x21, 0xCD, 0xE9, 0x00, 0x10, 0x53, 0x48, 0x8D, 0xF8, 0x09, 0x10, 0x02, 0xAB, 0x41, 0x78, 0x04, 0x22, 0x28, 0x46, 0x45, 0xF6, 0x10, 0xFF, 0x3E, 0xBD, 0x2D, 0xE9, 0xF7, 0x4F, 0x8C, 0xB0, 0x00, + 0x20, 0x05, 0x90, 0x06, 0x90, 0x07, 0x90, 0x92, 0xF8, 0x00, 0x80, 0x0E, 0x46, 0x00, 0x91, 0x49, 0x49, 0x43, 0x48, 0x15, 0x46, 0x57, 0x1C, 0x43, 0x46, 0x02, 0x22, 0xCD, 0xF8, 0x20, 0x80, 0x40, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0x55, 0xF8, 0xDF, + 0xF8, 0x08, 0x91, 0x01, 0x24, 0x4F, 0xF0, 0x10, 0x0A, + 0x4F, 0xF0, 0x03, 0x0B, 0xB8, 0xF1, 0x0D, 0x0F, 0x0D, 0xD2, 0x08, 0x98, 0x58, 0xB1, 0xDF, 0xF8, 0xE0, 0x80, 0x0C, 0x28, 0x6A, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x69, 0x0D, 0xDD, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0x69, 0xF8, 0xF7, 0xF6, 0x8D, 0xF8, + 0x14, 0xA0, 0x08, 0x98, 0x8D, 0xF8, 0x15, 0x00, 0xFF, 0x20, 0x96, 0xE0, 0x11, 0x2E, 0x6A, 0xD1, 0x4F, 0xF4, 0x00, 0x16, 0x96, 0xF8, 0x14, 0x03, 0x80, 0x06, 0x26, 0xD5, 0x3A, 0x46, 0x10, 0x21, 0x30, 0x48, 0xFE, 0xF5, 0x7F, 0xFA, 0x27, 0x4D, + 0x2D, 0x49, 0x03, 0x46, 0xED, 0x1C, 0x01, 0x22, 0x84, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0x20, 0xF8, 0x96, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x23, 0x48, 0x07, 0xF6, 0xF8, 0xF8, 0x39, 0x46, 0x08, 0x46, 0xFF, 0xF5, + 0xEC, 0xF9, 0x3A, 0x46, 0x10, 0x21, 0x22, 0x48, 0xFE, 0xF5, 0x64, 0xFA, 0x20, 0x49, 0x03, 0x46, 0x01, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0x07, 0xF8, 0x3B, 0x78, 0x0A, + 0x93, 0xB8, 0x78, 0xFA, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x02, 0x20, 0x86, 0xB2, 0x38, 0x79, 0x7A, 0x79, 0x0D, 0xF1, 0x08, 0x0C, 0x00, 0xEB, 0x02, 0x20, 0x80, 0xB2, 0x09, 0x90, 0xB8, 0x79, 0xFA, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x85, 0xB2, 0x38, + 0x7A, 0x7A, 0x7A, 0x00, 0xEB, 0x02, 0x20, 0xBA, 0x7A, 0xFF, 0x7A, 0x12, 0x04, 0x02, 0xEB, 0x07, 0x62, 0xCD, 0xE9, 0x00, 0x16, 0x87, 0x18, 0x09, 0x98, 0x0B, 0x49, 0x8C, 0xE8, 0xA1, 0x00, 0x04, 0x48, 0x06, 0x22, 0xD4, 0x31, 0xC0, 0x1C, 0xFD, + 0xF5, 0xDC, 0xFF, 0x0A, + 0x9B, 0x11, 0xE0, 0x4B, 0xE2, 0x00, 0x31, 0x10, 0x21, 0x54, 0xF2, 0x20, 0x00, 0xFC, 0x06, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x20, 0x08, 0x80, 0x08, 0x40, 0xEA, 0x20, 0x00, 0x30, 0x09, 0x80, 0x08, 0x00, 0x00, 0x50, 0x21, 0xEE, 0xE1, 0x88, + 0xF8, 0x00, 0x30, 0xA8, 0xF8, 0x02, 0x60, 0x09, 0x98, 0xA8, 0xF8, 0x04, 0x00, 0xA8, 0xF8, 0x06, 0x50, 0xC8, 0xF8, 0x08, 0x70, 0x07, 0xF5, 0x80, 0x67, 0xC8, 0xF8, 0x0C, 0x70, 0x05, 0x2B, 0x02, 0xD0, 0x01, 0x22, 0xFB, 0x49, 0x0C, 0xE0, 0xA0, + 0xF5, 0x1C, 0x51, 0x90, 0x39, 0x0A, + 0x29, 0x1C, 0xD3, 0xA0, 0xF5, 0x7F, 0x41, 0xFE, 0x39, 0x18, 0xD0, 0xF5, 0x49, 0x01, 0x22, 0x03, 0x46, 0x30, 0x39, 0xF4, 0x48, 0xFD, 0xF5, 0xA4, 0xFF, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, + 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x45, 0xF6, 0x37, 0xFE, 0x0F, 0xB0, 0x12, 0xE6, 0x01, 0xF0, 0xD5, 0xFE, 0xB8, 0xF8, 0x04, 0x00, 0xE9, 0x4B, 0x0C, 0x22, 0x00, 0x21, 0x02, 0xF0, 0x2D, 0xF8, 0x05, + 0x46, 0x01, 0xF0, 0xE3, 0xFE, 0xC5, 0xB1, 0x2A, 0x46, 0xE5, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFD, 0xF5, 0x28, 0xFF, 0xB8, 0xF8, 0x04, 0x00, 0x02, 0xF0, 0xAA, 0xF8, 0x3D, 0xF6, 0xD3, 0xFD, 0xDC, 0x49, 0x00, 0x22, 0x54, 0x39, 0xEA, 0x48, 0xFD, + 0xF5, 0x73, 0xFF, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x8D, 0xF8, 0x16, 0x40, 0x01, 0xE1, 0xD8, 0xF8, 0x14, 0x00, 0x0C, 0x30, 0xC8, 0xF8, 0x14, 0x00, 0xEC, 0xE7, 0x07, 0x2E, 0x04, 0xD0, 0xD2, 0x49, 0x01, 0x22, 0x33, 0x46, 0x70, + 0x31, 0x92, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xA8, 0xF8, 0x04, 0x30, 0xB8, 0x78, 0xFA, 0x78, 0x7C, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x3A, 0x79, 0x12, 0x04, 0x02, 0xEB, 0x04, 0x62, 0x80, 0x18, 0x07, 0xE0, 0x7B, + 0xE1, 0x59, 0xE1, 0x2E, 0xE1, 0xCE, 0xE0, 0x75, 0xE0, 0x53, 0xE0, 0x4A, 0xE0, 0x12, 0xE0, 0xC8, 0xF8, 0x14, 0x00, 0x01, 0xD0, 0x0C, 0x28, 0x04, 0xD1, 0x00, 0x22, 0xA9, 0xF8, 0x02, 0x20, 0xC9, 0xF8, 0x04, 0x20, 0x00, 0x90, 0xBD, 0x49, 0xBD, + 0x48, 0x02, 0x22, 0x30, 0x31, 0xC0, 0x1C, 0xFD, 0xF5, 0x33, 0xFF, 0x58, 0xE1, 0x03, 0x2E, 0x03, 0xD0, 0x33, 0x46, 0x01, 0x22, 0xC7, 0x49, 0x5F, 0xE0, 0x38, 0x78, 0x79, 0x78, 0xB6, 0x4D, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xC3, 0x49, 0xED, + 0x1C, 0x44, 0x46, 0xA8, 0xF8, 0x04, 0x30, 0x01, 0x22, 0x64, 0x39, 0x28, 0x46, 0xFD, 0xF5, 0x1C, 0xFF, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x7A, 0x03, 0xC0, 0x06, 0xE2, 0xD5, 0xE0, 0x68, 0xB0, 0xF5, 0x80, 0x1F, 0xDE, 0xD9, 0x6F, 0xF0, 0x7F, + 0x61, 0x08, 0x44, 0xC0, 0xF3, 0x07, 0x50, 0x09, 0x17, 0x01, 0xEB, 0x40, 0x11, 0x8C, 0xB2, 0xB4, 0x49, 0x83, 0x00, 0x02, 0x22, 0x40, 0x39, 0x28, 0x46, 0x00, 0x94, 0xFD, 0xF5, 0x01, 0xFF, 0x03, 0x22, 0x0F, 0x21, 0x20, 0x46, 0x07, 0xF6, 0x4E, + 0xFE, 0x21, 0xE1, 0xAD, 0x49, 0x9E, 0x48, 0x00, 0x22, 0x2C, 0x31, 0xC0, 0x1C, 0xFD, 0xF5, 0xF4, 0xFE, 0x19, 0xE1, 0xA9, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x99, 0x48, 0xFD, 0xF5, 0xED, 0xFE, 0xB8, 0xF8, 0x04, 0x00, 0xA0, 0xF5, 0x1C, 0x51, 0x90, + 0x39, 0x0A, + 0x29, 0x0A, + 0xD2, 0x02, 0xF6, 0xF5, 0xFD, 0x38, 0xB1, 0x81, 0x78, 0x09, 0x06, 0x04, 0xD4, 0x20, 0xF0, 0x7F, 0x41, 0x02, 0x20, 0x02, 0xF6, 0xBF, 0xF9, 0x4F, 0xF4, 0xFA, 0x60, 0x1C, 0xF6, 0x60, 0xFD, 0xD4, 0x21, 0x03, 0x20, 0xFE, 0xF7, 0x0F, 0xFE, 0xF8, + 0xE0, 0x03, 0x2E, 0x07, 0xD0, 0x98, 0x49, 0x01, 0x22, 0x33, 0x46, 0xE4, 0x31, 0x87, 0x48, 0xFD, 0xF5, 0xC9, 0xFE, 0xEE, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x92, 0x4F, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0x91, 0x49, 0x45, 0x46, 0xA8, 0xF8, 0x04, + 0x30, 0x01, 0x22, 0x68, 0x31, 0x38, 0x46, 0xFD, 0xF5, 0xB9, 0xFE, 0xA8, 0x88, 0x7E, 0x4E, 0xA0, 0xF5, 0x7F, 0x41, 0x10, 0x36, 0xFE, 0x39, 0x2E, 0xD0, 0x32, 0x1D, 0x31, 0x46, 0x3D, 0xF6, 0xF9, 0xFB, 0x00, 0x20, 0x68, 0x61, 0x00, 0x90, 0x85, + 0x49, 0x02, 0x22, 0x9C, 0x31, 0x38, 0x46, 0x2B, 0x69, 0xFD, 0xF5, 0xA4, 0xFE, 0x8D, 0xF8, 0x14, 0xA0, 0x06, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x28, 0x69, 0x8D, 0xF8, 0x17, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x18, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x19, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1A, 0x00, 0x68, 0x69, 0x8D, 0xF8, 0x1B, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x1C, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x1D, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1E, 0x00, 0x0B, 0x20, 0xF0, 0xE0, 0x05, 0x20, 0x02, 0xF6, 0xF1, 0xF8, 0x32, 0x46, 0x04, 0x21, 0x60, 0x30, 0x02, 0xF6, 0xC9, 0xFB, 0xCB, 0xE7, 0x07, 0x20, + 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x00, 0x09, 0x2E, 0x0D, 0xD0, 0x33, 0x46, 0x01, 0x22, 0x69, 0x49, 0x59, 0x48, 0xFD, 0xF5, 0x6D, 0xFE, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x43, 0xE0, + 0x98, 0xF8, 0x19, 0x00, 0xC2, 0x46, 0x30, 0xB1, 0x61, 0x49, 0x00, 0x22, 0xA0, 0x39, 0x50, 0x48, 0xFD, 0xF5, 0x5B, 0xFE, 0x26, 0xE0, 0x68, 0x78, 0xA9, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x87, 0xB2, 0xE8, 0x78, 0x29, 0x79, 0x00, 0xEB, 0x01, 0x20, + 0x86, 0xB2, 0x68, 0x79, 0xA9, 0x79, 0x32, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x1F, 0xFA, 0x80, 0xF8, 0xE8, 0x79, 0x29, 0x7A, 0x43, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x85, 0xB2, 0x6F, 0xF0, 0x01, 0x00, 0x00, 0xEB, 0x46, 0x01, 0x00, 0xEB, 0x47, 0x00, + 0x89, 0xB2, 0x80, 0xB2, 0x00, 0x95, 0xCD, 0xE9, 0x01, 0x01, 0x39, 0x46, 0x00, 0x20, 0x43, 0xF6, 0x4A, 0xFF, 0x18, 0xB1, 0x58, 0x46, 0x8D, 0xF8, 0x16, 0xB0, 0x9C, 0xE0, 0x8A, 0xF8, 0x19, 0x40, 0x00, 0x96, 0x47, 0x49, 0x36, 0x48, 0xCD, 0xE9, + 0x01, 0x85, 0x3B, 0x46, 0x04, 0x22, 0x5C, 0x39, 0x80, 0x1C, 0xFD, 0xF5, 0x22, 0xFE, 0x47, 0xE0, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x45, 0xF6, 0xBF, 0xFC, 0x41, 0xE0, 0x2F, 0x49, 0x40, 0xF2, 0x75, 0x20, 0x18, 0x31, 0x0C, 0x9A, 0x43, 0xF6, + 0x24, 0xFE, 0x4F, 0xF4, 0x00, 0x60, 0x00, 0x90, 0x39, 0x49, 0x29, 0x48, 0x45, 0x46, 0x98, 0xF8, 0x18, 0x30, 0x02, 0x22, 0x3C, 0x31, 0xC0, 0x1C, 0xFD, 0xF5, 0x07, 0xFE, 0x00, 0x20, 0x89, 0xF8, 0x00, 0x00, 0x8D, 0xF8, 0x14, 0xA0, 0x09, 0x22, + 0x8D, 0xF8, 0x15, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0x08, 0x22, 0x8D, 0xF8, 0x17, 0x00, 0x8D, 0xF8, 0x18, 0x20, 0x2A, 0x7E, 0x8D, 0xF8, 0x19, 0x20, 0x8D, 0xF8, 0x1A, 0x00, 0x07, 0x20, 0x5E, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x02, 0x22, 0x00, 0xEB, + 0x01, 0x20, 0x85, 0xB2, 0xB8, 0x78, 0xF9, 0x78, 0x2B, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x84, 0xB2, 0x23, 0x49, 0x13, 0x48, 0x7C, 0x31, 0xC0, 0x1C, 0x00, 0x94, 0xFD, 0xF5, 0xDE, 0xFD, 0x22, 0x46, 0x29, 0x46, 0x0C, 0x98, 0xFF, 0xF7, 0xE6, 0xFB, + 0x1E, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x40, 0xAE, 0x08, 0x99, 0x0C, 0x98, 0x90, 0x47, 0x3B, 0xE6, 0x8D, 0xF8, 0x14, 0xA0, 0x0B, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x02, 0xA9, 0x42, 0xF2, 0x90, 0x70, 0x3D, 0xF6, 0xEC, 0xFA, 0x20, 0xB1, + 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xFF, 0x20, 0x2A, 0xE0, 0x25, 0xE0, 0xD0, 0x0A, + 0x80, 0x08, 0x00, 0x31, 0x10, 0x21, 0x54, 0xF2, 0x20, 0x00, 0x44, 0x46, 0x55, 0x5F, 0x4F, 0x50, 0x43, 0x4F, 0x44, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5F, 0x44, 0x46, 0x55, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x00, 0x02, 0x33, 0x10, 0x21, 0xDC, 0x0B, 0x80, 0x08, 0x94, 0x0D, 0x80, 0x08, 0x4C, 0xEA, 0x20, 0x00, 0x9D, 0xF8, 0x08, 0x00, 0x8D, 0xF8, + 0x16, 0x40, 0x8D, 0xF8, 0x17, 0x00, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x04, 0x05, 0xAB, 0x04, 0x22, 0x6B, 0xE7, 0x03, 0x46, 0x01, 0x22, 0x88, 0x49, 0x89, 0x48, 0xBC, 0xE6, 0x2D, 0xE9, 0xFE, 0x4F, 0x88, 0x4F, 0x05, 0x46, 0xA7, 0xF6, 0x14, 0x04, + 0x88, 0x46, 0x78, 0x69, 0x61, 0x88, 0xFA, 0x68, 0x8D, 0xE8, 0x07, 0x00, 0x81, 0x49, 0x2B, 0x46, 0x04, 0x22, 0x3C, 0x31, 0x80, 0x48, 0xFD, 0xF5, 0x75, 0xFD, 0xDF, 0xF8, 0xF8, 0xA1, 0x20, 0x78, 0xAA, 0xF1, 0x03, 0x0A, + 0xC0, 0xB1, 0x60, 0x88, 0x43, 0x19, 0x4F, 0xF4, 0x00, 0x60, 0x83, 0x42, 0x08, 0xD9, 0x77, 0x49, 0x00, 0x90, 0x02, 0x22, 0xAC, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0x62, 0xFD, 0x3D, 0xF6, 0xBA, 0xFB, 0x61, 0x88, 0x20, 0x69, 0x2A, 0x46, 0x08, 0x44, + 0x41, 0x46, 0x4F, 0xF6, 0x77, 0xFF, 0x60, 0x88, 0x28, 0x44, 0x70, 0xE0, 0x60, 0x88, 0x4F, 0xF4, 0xFF, 0x66, 0x43, 0x19, 0xB3, 0x42, 0x07, 0xD9, 0x02, 0x22, 0x6D, 0x49, 0x50, 0x46, 0x00, 0x96, 0xFD, 0xF5, 0x4A, 0xFD, 0x3D, 0xF6, 0xA2, 0xFB, + 0x60, 0x88, 0x79, 0x69, 0x28, 0x44, 0xFB, 0x68, 0x08, 0x44, 0xA1, 0x46, 0x98, 0x42, 0x07, 0xD9, 0x66, 0x49, 0x01, 0x22, 0x68, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0x3A, 0xFD, 0x3D, 0xF6, 0x92, 0xFB, 0x10, 0x2D, 0x1D, 0xD3, 0x4F, 0xF4, 0x00, 0x10, + 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0xDF, 0xF8, 0x7C, 0xB1, 0x00, 0x24, 0x82, 0x46, 0x28, 0x1B, 0x10, 0x28, 0x10, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x58, 0x46, 0x06, 0xF6, 0x01, 0xFE, + 0x08, 0xEB, 0x04, 0x00, 0x01, 0x46, 0xFE, 0xF5, 0xF4, 0xFE, 0x10, 0x34, 0xA4, 0xB2, 0xEB, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xD9, 0xF8, 0x10, 0x00, 0x4C, 0x46, 0x08, 0x44, 0x2A, 0x46, 0x41, 0x46, 0x4F, 0xF6, 0x2C, 0xFF, 0x60, 0x88, 0x28, 0x44, + 0x80, 0xB2, 0x60, 0x80, 0xB0, 0x42, 0x04, 0xD0, 0x79, 0x69, 0x01, 0x44, 0xF8, 0x68, 0x81, 0x42, 0x1E, 0xD1, 0x01, 0xF0, 0x46, 0xFC, 0xB8, 0x88, 0x79, 0x69, 0x62, 0x88, 0x23, 0x69, 0x01, 0xF0, 0x9F, 0xFD, 0x05, 0x46, 0x01, 0xF0, 0x55, 0xFC, + 0x65, 0xB1, 0x2A, 0x46, 0x43, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFD, 0xF5, 0x9A, 0xFC, 0xB8, 0x88, 0x01, 0xF0, 0x1D, 0xFE, 0xBD, 0xE8, 0xFE, 0x4F, 0x3D, 0xF6, 0x44, 0xBB, 0x61, 0x88, 0x78, 0x69, 0x08, 0x44, 0x78, 0x61, 0x00, 0x20, 0x60, 0x80, + 0xBD, 0xE8, 0xFE, 0x8F, 0x10, 0xB5, 0x03, 0x46, 0xDD, 0xE9, 0x02, 0x01, 0x00, 0x24, 0x04, 0x2A, 0x0B, 0xD0, 0x02, 0x2A, 0x0F, 0xD0, 0x32, 0x49, 0x13, 0x46, 0x01, 0x22, 0xD0, 0x31, 0x40, 0x48, 0xFD, 0xF5, 0xD2, 0xFC, 0x40, 0xF2, 0x0A, + 0x40, 0x10, 0xBD, 0x0A, + 0x46, 0x01, 0x46, 0x18, 0x46, 0xFF, 0xF7, 0x5E, 0xFC, 0x01, 0xE0, 0xFF, 0xF7, 0x3F, 0xFF, 0x20, 0x46, 0x10, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x25, 0x88, 0x46, 0x1E, 0x46, 0x8D, 0xF8, 0x05, 0x50, 0x00, 0x93, 0x24, 0x49, 0x17, 0x46, 0x8D, + 0xF8, 0x04, 0x00, 0x13, 0x46, 0x2C, 0x46, 0x02, 0x22, 0xFC, 0x31, 0x30, 0x48, 0xFD, 0xF5, 0xB2, 0xFC, 0x05, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x2E, 0x48, 0x82, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, + 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xF0, 0x07, 0x8D, 0xF8, 0x05, 0x50, 0x02, 0xD0, 0x8D, 0xF8, 0x06, 0x50, 0xED, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xE9, 0xE7, 0x7C, 0xB5, 0x24, 0x49, 0x05, 0x46, 0xD1, 0xE9, 0x01, 0x02, 0xCD, 0xE9, 0x00, + 0x02, 0x20, 0x48, 0x0B, 0x68, 0xA8, 0x22, 0x20, 0x49, 0x40, 0x1C, 0x45, 0xF6, 0x93, 0xFA, 0x1C, 0x4C, 0x28, 0xB1, 0x04, 0xF1, 0x14, 0x00, 0xA5, 0x60, 0x20, 0x61, 0x60, 0x78, 0x7C, 0xBD, 0x17, 0x48, 0x63, 0x78, 0x01, 0x22, 0x1A, 0x49, 0x80, + 0x1E, 0xFD, 0xF5, 0x7C, 0xFC, 0xFF, 0x20, 0x60, 0x70, 0x7C, 0xBD, 0x4C, 0x0E, 0x80, 0x08, 0x03, 0x31, 0x10, 0x21, 0x54, 0xF2, 0x20, 0x00, 0x60, 0x0F, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x64, 0x66, 0x75, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x70, 0x61, 0x63, 0x6B, 0x65, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, + 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x02, 0x33, 0x10, 0x21, 0x40, 0xEA, 0x20, 0x00, 0xEC, 0xE6, 0x21, 0x00, 0x1C, 0xE6, 0x20, 0x00, 0x8C, 0x10, 0x80, 0x08, 0x2D, 0xE9, 0xF0, 0x41, 0x01, 0x46, 0xFE, 0x48, 0xFE, 0x4E, 0x00, 0x25, 0xFE, + 0x4C, 0x07, 0x29, 0x4D, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x26, 0x09, 0x11, 0x04, 0x4C, 0x15, 0x1F, 0x00, 0x00, 0x22, 0xFA, 0x49, 0xFD, 0xF5, 0x36, 0xFC, 0x3C, 0xE0, 0xF8, 0x49, 0x00, 0x22, 0x20, 0x31, 0xFD, 0xF5, 0x30, 0xFC, 0x25, 0x70, 0x03, + 0x20, 0x36, 0xE0, 0xF4, 0x49, 0x00, 0x22, 0x3C, 0x31, 0x0C, 0xE0, 0xF2, 0x49, 0x00, 0x22, 0x58, 0x31, 0xFD, 0xF5, 0x24, 0xFC, 0x25, 0x70, 0x06, 0x20, 0xB0, 0x74, 0xBD, 0xE8, 0xF0, 0x81, 0xED, 0x49, 0x00, 0x22, 0x78, 0x31, 0xFD, 0xF5, 0x1A, + 0xFC, 0x25, 0x70, 0xF6, 0xE7, 0xEA, 0x49, 0x00, 0x22, 0x98, 0x31, 0x07, 0x46, 0xFD, 0xF5, 0x12, 0xFC, 0x70, 0x7D, 0x01, 0x28, 0xED, 0xD1, 0xE5, 0x49, 0xB3, 0x79, 0x01, 0x22, 0xB4, 0x31, 0x38, 0x46, 0xFD, 0xF5, 0x08, 0xFC, 0xB0, 0x79, 0x03, + 0x28, 0x06, 0xD2, 0x01, 0x20, 0x00, 0xF0, 0x75, 0xFF, 0xB0, 0x79, 0x40, 0x1C, 0xB0, 0x71, 0xDC, 0xE7, 0xB5, 0x71, 0x20, 0x78, 0x00, 0x28, 0xD8, 0xD0, 0x01, 0x28, 0xDD, 0xD1, 0x25, 0x70, 0x05, 0x20, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0xF0, 0x65, + 0xBF, 0xD7, 0x49, 0xD3, 0x48, 0xB3, 0x7D, 0x01, 0x22, 0xE0, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0xEA, 0xFB, 0xCE, 0xE7, 0x10, 0xB5, 0x01, 0x46, 0xCE, 0x48, 0xCF, 0x4C, 0x08, 0x29, 0x39, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x38, 0x04, 0x09, 0x0D, 0x1A, + 0x2A, 0x32, 0x14, 0x00, 0x22, 0xCD, 0x49, 0xFD, 0xF5, 0xD9, 0xFB, 0x1B, 0xE0, 0xCB, 0x49, 0x00, 0x22, 0x38, 0x31, 0x26, 0xE0, 0xC9, 0x49, 0x00, 0x22, 0x70, 0x31, 0xFD, 0xF5, 0xCF, 0xFB, 0x3D, 0xF6, 0x09, 0xFC, 0xD2, 0x21, 0xBD, 0xE8, 0x10, + 0x40, 0x01, 0x20, 0xFE, 0xF7, 0x03, 0xBB, 0xC2, 0x49, 0x63, 0x7A, 0x01, 0x22, 0xA4, 0x31, 0xFD, 0xF5, 0xC1, 0xFB, 0x60, 0x7A, 0x03, 0x28, 0x0D, 0xD2, 0x40, 0x1C, 0x60, 0x72, 0xBD, 0xE8, 0x10, 0x40, 0x03, 0x20, 0x00, 0xF0, 0x2A, 0xBF, 0xBA, + 0x49, 0x00, 0x22, 0xF4, 0x31, 0xFD, 0xF5, 0xB2, 0xFB, 0x06, 0x20, 0xA0, 0x74, 0x10, 0xBD, 0xB7, 0x49, 0x00, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0xFD, 0xF5, 0xA9, 0xBB, 0xB4, 0x49, 0xE3, 0x7D, 0xAE, 0x48, 0x01, 0x22, 0x3C, 0x31, 0xBD, 0xE8, 0x10, + 0x40, 0x40, 0x1E, 0xFD, 0xF5, 0x9F, 0xBB, 0x10, 0xB5, 0x01, 0x78, 0x00, 0x24, 0x86, 0xB0, 0x02, 0x29, 0x68, 0xD1, 0x81, 0x78, 0x01, 0x29, 0x10, 0xD0, 0x02, 0x29, 0x16, 0xD0, 0x03, 0x29, 0x1C, 0xD0, 0x04, 0x29, 0x22, 0xD0, 0x05, 0x29, 0x29, + 0xD0, 0x06, 0x29, 0x30, 0xD0, 0x07, 0x29, 0x37, 0xD0, 0x08, 0x29, 0x3E, 0xD0, 0x09, 0x29, 0x45, 0xD0, 0x54, 0xE0, 0xA3, 0xA0, 0x07, 0xC8, 0x8D, 0xE8, 0x07, 0x00, 0x0A, + 0x21, 0x6A, 0x46, 0x00, 0x20, 0x4A, 0xE0, 0xA2, 0xA1, 0x0F, 0xC9, 0x8D, 0xE8, 0x0F, 0x00, 0x0D, 0x21, 0x6A, 0x46, 0x01, 0x20, 0x42, 0xE0, 0xA2, 0xA1, 0x0F, 0xC9, 0x8D, 0xE8, 0x0F, 0x00, 0x0F, 0x21, 0x6A, 0x46, 0x02, 0x20, 0x3A, 0xE0, 0x14, + 0x22, 0xA2, 0xA1, 0x68, 0x46, 0x4F, 0xF6, 0x0D, 0xFE, 0x11, 0x21, 0x6A, 0x46, 0x03, 0x20, 0x31, 0xE0, 0x14, 0x22, 0xA2, 0xA1, 0x68, 0x46, 0x4F, 0xF6, 0x04, 0xFE, 0x11, 0x21, 0x6A, 0x46, 0x04, 0x20, 0x28, 0xE0, 0x14, 0x22, 0xA3, 0xA1, 0x68, + 0x46, 0x4F, 0xF6, 0xFB, 0xFD, 0x11, 0x21, 0x6A, 0x46, 0x05, 0x20, 0x1F, 0xE0, 0xA4, 0xA0, 0x6A, 0x46, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x00, 0x10, 0x08, 0x21, 0x06, 0x20, 0x16, 0xE0, 0x14, 0x22, 0xA1, 0xA1, 0x68, 0x46, 0x4F, 0xF6, 0xE9, + 0xFD, 0x12, 0x21, 0x6A, 0x46, 0x07, 0x20, 0x0D, 0xE0, 0xA2, 0xA0, 0x6A, 0x46, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x00, 0x10, 0x03, 0x20, 0x8D, 0xF8, 0x05, 0x00, 0x00, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x07, 0x21, 0x08, 0x20, 0xFE, 0xF7, 0xB7, + 0xFE, 0x06, 0xB0, 0x20, 0x46, 0x10, 0xBD, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xC0, 0x81, 0x04, 0x46, 0x03, 0x78, 0x00, 0x25, 0x01, 0x22, 0x96, 0x49, 0x40, 0x46, 0xFD, 0xF5, 0x21, 0xFB, 0x20, 0x78, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x28, 0x4B, + 0xD1, 0x3A, 0xE0, 0x20, 0x79, 0x00, 0x26, 0x01, 0x27, 0x68, 0x4C, 0x07, 0x28, 0x44, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x43, 0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x00, 0x8B, 0x49, 0x00, 0x22, 0x20, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0x09, 0xFB, 0x67, + 0x70, 0x36, 0xE0, 0x87, 0x49, 0x00, 0x22, 0x54, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0x01, 0xFB, 0x66, 0x70, 0x2E, 0xE0, 0x83, 0x49, 0x00, 0x22, 0x88, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xF9, 0xFA, 0xA7, 0x70, 0x26, 0xE0, 0x7F, 0x49, 0x00, 0x22, 0xC0, + 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xF1, 0xFA, 0xA6, 0x70, 0x1E, 0xE0, 0x7B, 0x49, 0x00, 0x22, 0xF8, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xE9, 0xFA, 0x27, 0x71, 0x16, 0xE0, 0x00, 0x22, 0x78, 0x49, 0x40, 0x46, 0xFD, 0xF5, 0xE2, 0xFA, 0x26, 0x71, 0x0F, + 0xE0, 0x75, 0x49, 0x00, 0x22, 0x38, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xDA, 0xFA, 0x20, 0x79, 0x01, 0x28, 0x06, 0xD1, 0x20, 0x7A, 0x8D, 0xF8, 0x00, 0x00, 0x69, 0x46, 0x02, 0x20, 0x02, 0xF0, 0xEF, 0xF8, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x70, + 0xB5, 0x0C, 0x46, 0x05, 0x46, 0x03, 0x46, 0x01, 0x22, 0x6A, 0x49, 0x3E, 0x48, 0xFD, 0xF5, 0xC4, 0xFA, 0x04, 0xF1, 0x08, 0x01, 0x4D, 0xB1, 0x01, 0x2D, 0x0A, + 0xD0, 0x02, 0x2D, 0x0B, 0xD1, 0xA2, 0x7B, 0x00, 0x20, 0xBD, 0xE8, 0x70, 0x40, 0x42, 0xF6, 0xB2, 0xBC, 0xA2, 0x7B, 0x02, 0x20, 0xF8, 0xE7, 0xA2, 0x7B, 0x01, 0x20, 0xF5, 0xE7, 0x70, 0xBD, 0x2D, 0xE9, 0xF8, 0x4F, 0x0D, 0x46, 0x00, 0x91, 0x06, + 0x46, 0x5B, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0x33, 0x46, 0x02, 0x22, 0x48, 0x31, 0x58, 0x46, 0xFD, 0xF5, 0x9F, 0xFA, 0xAB, 0xF1, 0x01, 0x0A, + 0x2D, 0xB1, 0x01, 0x2D, 0x03, 0xD0, 0x53, 0x49, 0x00, 0x22, 0x88, 0x31, 0x3A, 0xE0, 0x27, 0x4F, 0x4F, 0xF0, 0x01, 0x09, 0x38, 0x7F, 0x01, 0x28, 0x0E, 0xD0, 0x01, 0x20, 0xB0, 0x40, 0xB9, 0x8C, 0x01, 0x2D, 0x15, 0xD0, 0x81, 0x43, 0x08, 0x04, + 0xB9, 0x84, 0x00, 0x0C, 0x97, 0xF8, 0x21, 0x00, 0x10, 0xD0, 0x01, 0x28, 0x16, 0xD0, 0x19, 0xE0, 0x46, 0x49, 0x00, 0x22, 0xBC, 0x31, 0x58, 0x46, 0xFD, 0xF5, 0x7B, 0xFA, 0x07, 0xF8, 0x1D, 0x9F, 0x7D, 0x71, 0xFE, 0x70, 0xBD, 0xE8, 0xF8, 0x8F, + 0x01, 0x43, 0xE8, 0xE7, 0x10, 0xB1, 0x4F, 0xF0, 0x00, 0x08, 0x07, 0xE0, 0x3D, 0x49, 0x00, 0x22, 0xF4, 0x31, 0x01, 0xE0, 0x3C, 0x49, 0x00, 0x22, 0x58, 0x46, 0x0C, 0xE0, 0x41, 0x46, 0x00, 0x20, 0x42, 0xF6, 0x28, 0xFD, 0x58, 0xB1, 0x64, 0x1C, + 0xE4, 0xB2, 0x03, 0x2C, 0xF6, 0xD3, 0x36, 0x49, 0x00, 0x22, 0xA0, 0x31, 0x50, 0x46, 0xBD, 0xE8, 0xF8, 0x4F, 0xFD, 0xF5, 0x56, 0xBA, 0x32, 0x49, 0xBB, 0x8C, 0x01, 0x22, 0x40, 0x31, 0x58, 0x46, 0xFD, 0xF5, 0x4F, 0xFA, 0x00, 0x20, 0x78, 0x77, + 0x87, 0xF8, 0x1C, 0x90, 0x5A, 0xE0, 0x00, 0x00, 0x02, 0x30, 0x10, 0x21, 0x70, 0xF2, 0x20, 0x00, 0x00, 0xF3, 0x20, 0x00, 0x70, 0x11, 0x80, 0x08, 0x70, 0x12, 0x80, 0x08, 0xA0, 0x13, 0x80, 0x08, 0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x6B, 0x20, + 0x42, 0x54, 0x00, 0x00, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x20, 0x4E, 0x62, 0x72, 0x20, 0x30, 0x2E, 0x39, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4B, 0x42, 0x65, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x00, 0x52, 0x54, 0x4B, 0x42, + 0x65, 0x65, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x76, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4B, 0x42, 0x65, 0x65, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x76, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4B, 0x42, + 0x65, 0x65, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x76, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x03, 0x04, 0x05, 0x52, 0x54, 0x4B, 0x42, 0x65, 0x65, 0x49, 0x45, 0x45, 0x45, 0x44, 0x61, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x74, 0x00, 0x00, 0x01, 0x5D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x15, 0x80, 0x08, 0xD4, 0x16, 0x80, 0x08, 0x58, 0x18, 0x80, 0x08, 0x8C, 0x19, 0x80, 0x08, 0x87, 0xF8, 0x21, 0x50, 0xFE, 0x77, 0x73, 0xE7, 0x10, 0xB5, 0x2E, 0x21, + 0xF7, 0x48, 0x4F, 0xF6, 0xC5, 0xFC, 0xF6, 0x4C, 0x17, 0x20, 0x20, 0x72, 0x00, 0x20, 0x60, 0x71, 0x13, 0xF0, 0x84, 0xF9, 0x60, 0x71, 0x00, 0x28, 0x06, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x22, 0xF0, 0x49, 0xF1, 0x48, 0xFD, 0xF5, 0xD5, 0xB9, + 0x10, 0xBD, 0x7C, 0xB5, 0xEE, 0x4D, 0xEC, 0x4C, 0x06, 0x46, 0x6D, 0x1C, 0x39, 0xB1, 0x01, 0x29, 0x27, 0xD0, 0x02, 0x29, 0x24, 0xD1, 0x00, 0x22, 0xEA, 0x49, 0x28, 0x46, 0x3E, 0xE0, 0x00, 0x20, 0xE5, 0x49, 0xE0, 0x71, 0x32, 0x46, 0x28, 0x31, + 0x40, 0xF2, 0x72, 0x20, 0x43, 0xF6, 0xCD, 0xF9, 0xE1, 0x49, 0x32, 0x46, 0x2A, 0x31, 0x40, 0xF2, 0x73, 0x20, 0x43, 0xF6, 0xC6, 0xF9, 0xDE, 0x49, 0x32, 0x46, 0x2C, 0x31, 0x4F, 0xF4, 0x1D, 0x70, 0x43, 0xF6, 0xBF, 0xF9, 0xA1, 0x8D, 0x60, 0x8D, + 0xCD, 0xE9, 0x00, 0x01, 0x23, 0x8D, 0x03, 0x22, 0xDB, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0xA5, 0xF9, 0x7C, 0xBD, 0xD9, 0x49, 0xD6, 0x48, 0x13, 0x46, 0x01, 0x22, 0x7C, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0x9C, 0xF9, 0xE1, 0x79, 0xD2, 0x48, 0x03, 0x29, + 0x0D, 0xD2, 0x49, 0x1C, 0xE1, 0x71, 0xD1, 0x49, 0x00, 0x22, 0x8C, 0x39, 0xFD, 0xF5, 0x91, 0xF9, 0xBD, 0xE8, 0x7C, 0x40, 0x41, 0xF2, 0x88, 0x31, 0xCE, 0x48, 0x1C, 0xF6, 0x7A, 0xBA, 0xCB, 0x49, 0x00, 0x22, 0x48, 0x39, 0x02, 0xB0, 0xBD, 0xE8, + 0x70, 0x40, 0xFD, 0xF5, 0x82, 0xB9, 0x2D, 0xE9, 0xF0, 0x41, 0xC5, 0x4E, 0x15, 0x46, 0x0C, 0x46, 0x03, 0x46, 0x76, 0x1C, 0x01, 0x22, 0xC6, 0x49, 0x30, 0x46, 0xFD, 0xF5, 0x76, 0xF9, 0x54, 0xB1, 0x01, 0x2C, 0x11, 0xD0, 0x23, 0x46, 0x30, 0x46, + 0xBD, 0xE8, 0xF0, 0x41, 0xBE, 0x49, 0x01, 0x22, 0x3C, 0x39, 0xFD, 0xF5, 0x6A, 0xB9, 0xBE, 0x49, 0x00, 0x22, 0x30, 0x31, 0x30, 0x46, 0xFD, 0xF5, 0x64, 0xF9, 0x42, 0xF2, 0x10, 0x71, 0x0E, 0xE0, 0x95, 0xB1, 0xA5, 0xF5, 0xA0, 0x60, 0xEB, 0x38, + 0x01, 0xD1, 0x41, 0xF6, 0xD3, 0xFC, 0xB4, 0x49, 0x00, 0x22, 0x68, 0x39, 0x30, 0x46, 0xFD, 0xF5, 0x54, 0xF9, 0x42, 0xF6, 0xE0, 0x61, 0xB3, 0x48, 0xBD, 0xE8, 0xF0, 0x41, 0x1C, 0xF6, 0x3D, 0xBA, 0xAF, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x30, 0x46, + 0xFD, 0xF5, 0x47, 0xF9, 0xA6, 0x4D, 0x01, 0x20, 0x00, 0x24, 0x28, 0x70, 0x04, 0x20, 0xA8, 0x74, 0x6C, 0x72, 0xAA, 0x48, 0x1C, 0xF6, 0x40, 0xFA, 0xA9, 0x49, 0xAA, 0x48, 0x1C, 0xF6, 0x29, 0xFA, 0x03, 0x22, 0x06, 0x21, 0x26, 0x20, 0x02, 0xF0, + 0xBD, 0xF8, 0x68, 0x7D, 0xA6, 0x4D, 0x41, 0xF2, 0x88, 0x37, 0x01, 0x28, 0x03, 0xD0, 0x02, 0x28, 0x01, 0xD0, 0x2C, 0x70, 0x23, 0xE0, 0x28, 0x78, 0xB0, 0xB1, 0x01, 0x28, 0x4F, 0xF0, 0x00, 0x02, 0x0A, + 0xD0, 0x9B, 0x49, 0x30, 0x46, 0x7C, 0x31, 0xFD, 0xF5, 0x1F, 0xF9, 0x4F, 0xF4, 0x96, 0x71, 0x9C, 0x48, 0x1C, 0xF6, 0x0A, + 0xFA, 0x04, 0xE0, 0x93, 0x49, 0x30, 0x46, 0xA4, 0x39, 0xFD, 0xF5, 0x14, 0xF9, 0x28, 0x78, 0x06, 0x28, 0x0A, + 0xD0, 0x4F, 0xF4, 0xFA, 0x62, 0x0E, 0x21, 0x0C, 0x20, 0x00, 0xF0, 0x92, 0xFE, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0x21, 0x08, 0x46, 0x55, 0xE6, 0x39, 0x46, 0x8A, 0x48, 0xB1, 0xE7, 0x2D, 0xE9, 0xF0, 0x43, 0x83, 0x4C, 0x81, 0x46, 0x8B, 0xB0, 0x0E, + 0x46, 0x20, 0x7D, 0xDF, 0xF8, 0x0C, 0x82, 0xCD, 0xE9, 0x00, 0x06, 0x17, 0x46, 0x08, 0xF1, 0x01, 0x08, 0x4B, 0x46, 0x03, 0x22, 0x88, 0x49, 0x40, 0x46, 0xFD, 0xF5, 0xEF, 0xF8, 0x00, 0x25, 0x16, 0xB1, 0x02, 0x2E, 0x75, 0xD1, 0x34, 0xE0, 0xA5, + 0x74, 0x80, 0x48, 0x1C, 0xF6, 0xE9, 0xF9, 0x7D, 0x48, 0x1C, 0xF6, 0xE6, 0xF9, 0x81, 0x48, 0x40, 0x78, 0x01, 0x28, 0x03, 0xD1, 0x80, 0x48, 0x05, 0x70, 0x01, 0xF0, 0xA5, 0xFE, 0xA7, 0xF5, 0x80, 0x70, 0x13, 0x38, 0x0B, 0xD0, 0xB7, 0xF5, 0x8B, + 0x7F, 0x1A, 0xD0, 0x79, 0x49, 0x3B, 0x46, 0x01, 0x22, 0x84, 0x31, 0x6D, 0x48, 0xFD, 0xF5, 0xCD, 0xF8, 0xE5, 0x75, 0x55, 0xE0, 0x74, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xC5, 0xF8, 0x20, 0x78, 0x00, 0x28, 0xF4, 0xD1, 0x60, + 0x7A, 0x03, 0x28, 0xF1, 0xD2, 0x40, 0x1C, 0x60, 0x72, 0x03, 0x20, 0x00, 0xF0, 0x2D, 0xFC, 0xEB, 0xE7, 0xE0, 0x7D, 0xFF, 0xF7, 0xCD, 0xFC, 0xE7, 0xE7, 0x03, 0x20, 0xA0, 0x74, 0x42, 0xF2, 0x10, 0x71, 0x62, 0x48, 0x1C, 0xF6, 0x9E, 0xF9, 0xE5, + 0x61, 0x25, 0x62, 0xA5, 0x84, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xF7, 0xFD, 0xFB, 0x21, 0x40, 0xF6, 0x48, 0x02, 0x48, 0x46, 0x42, 0xF6, 0x33, 0xFB, 0x4A, 0x46, 0x06, 0xA9, 0x40, 0xF2, 0x72, 0x20, 0x43, 0xF6, 0xAB, 0xF8, 0x4A, 0x46, 0x08, + 0xA9, 0x40, 0xF2, 0x73, 0x20, 0x43, 0xF6, 0xA5, 0xF8, 0x4A, 0x46, 0x09, 0xA9, 0x4F, 0xF4, 0x1D, 0x70, 0x43, 0xF6, 0x9F, 0xF8, 0x07, 0xAA, 0x04, 0xA9, 0x48, 0x46, 0x43, 0xF6, 0x52, 0xF9, 0x04, 0xA9, 0x56, 0x48, 0xFD, 0xF5, 0x43, 0xFA, 0x03, + 0x46, 0x9D, 0xF8, 0x1C, 0x00, 0xBD, 0xF8, 0x24, 0x50, 0xBD, 0xF8, 0x20, 0x20, 0xBD, 0xF8, 0x18, 0x10, 0x8D, 0xE8, 0x27, 0x00, 0x46, 0x49, 0x05, 0x22, 0x84, 0x39, 0x40, 0x46, 0xFD, 0xF5, 0x75, 0xF8, 0x26, 0x75, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, + 0x83, 0x2D, 0xE9, 0xFE, 0x4F, 0xC4, 0xB2, 0xC4, 0xF3, 0x81, 0x05, 0xA7, 0x09, 0x00, 0x95, 0xCD, 0xE9, 0x01, 0x71, 0x04, 0xF0, 0x01, 0x00, 0xDF, 0xF8, 0xE0, 0xA0, 0x36, 0x49, 0x80, 0x46, 0x03, 0x46, 0x0A, + 0xF1, 0x01, 0x0A, + 0x04, 0x22, 0x60, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0x5A, 0xF8, 0x30, 0x4E, 0x4F, 0xF0, 0x01, 0x09, 0xF0, 0x7C, 0x00, 0xF0, 0x01, 0x01, 0x40, 0x46, 0x4F, 0xF0, 0x00, 0x08, 0x81, 0x42, 0x29, 0xD0, 0xE0, 0x07, 0x27, 0xD0, 0x35, 0x49, 0x00, 0x22, + 0xA4, 0x39, 0x50, 0x46, 0xFD, 0xF5, 0x47, 0xF8, 0x0C, 0x21, 0xC8, 0x23, 0x0E, 0x22, 0x08, 0x46, 0x46, 0xF6, 0xB0, 0xFF, 0x86, 0xF8, 0x12, 0x80, 0x16, 0x20, 0x12, 0xF0, 0x18, 0xFF, 0x45, 0xF6, 0xAB, 0xFC, 0x78, 0xB1, 0x01, 0x78, 0x69, 0xB1, + 0x86, 0xF8, 0x00, 0x90, 0x82, 0x7B, 0x00, 0xF1, 0x08, 0x01, 0x01, 0x20, 0x42, 0xF6, 0x2A, 0xFA, 0x03, 0x20, 0xB0, 0x71, 0x01, 0x20, 0x00, 0xF0, 0x9D, 0xFB, 0x01, 0xE0, 0x86, 0xF8, 0x00, 0x80, 0x12, 0xF0, 0x0F, 0xFC, 0xF0, 0x7C, 0xC0, 0xF3, + 0x81, 0x00, 0xA8, 0x42, 0x4F, 0xD0, 0x14, 0xF0, 0x0C, 0x0F, 0x02, 0xD0, 0x02, 0x2D, 0x43, 0xD0, 0x49, 0xE0, 0x05, 0x21, 0x26, 0x20, 0x01, 0xF0, 0xD8, 0xFF, 0x86, 0xF8, 0x12, 0x80, 0x70, 0x7D, 0x45, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x1B, 0x48, + 0x1C, 0xF6, 0x10, 0xF9, 0xA0, 0x07, 0x4F, 0xF0, 0x00, 0x02, 0x09, 0xD4, 0x13, 0x49, 0x50, 0x46, 0x90, 0x39, 0xFD, 0xF5, 0x04, 0xF8, 0xB0, 0x7D, 0xFF, 0xF7, 0xB8, 0xFB, 0xB5, 0x75, 0x2E, 0xE0, 0x0E, 0x49, 0x50, 0x46, 0x5C, 0x39, 0xFC, 0xF5, + 0xFA, 0xFF, 0x28, 0xE0, 0x70, 0xF2, 0x20, 0x00, 0x5C, 0x1A, 0x80, 0x08, 0x01, 0x30, 0x10, 0x21, 0xA0, 0x1F, 0x80, 0x08, 0x64, 0x1E, 0x80, 0x08, 0xA8, 0xF2, 0x20, 0x00, 0x00, 0x1D, 0x80, 0x08, 0xAC, 0xF2, 0x20, 0x00, 0xE0, 0x93, 0x04, 0x00, + 0xA4, 0xF2, 0x20, 0x00, 0x00, 0xF3, 0x20, 0x00, 0xFC, 0xF2, 0x20, 0x00, 0xB8, 0x1B, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0xF4, 0xF6, 0x20, 0x00, 0x00, 0x00, 0x30, 0x21, 0xA0, 0xF2, 0x20, 0x00, 0x00, 0x22, 0xF6, 0x49, 0x50, 0x46, 0xFC, 0xF5, + 0xD2, 0xFF, 0x86, 0xF8, 0x12, 0x90, 0xF0, 0x7C, 0x83, 0x09, 0xB3, 0xEB, 0x94, 0x1F, 0x06, 0xD0, 0xF0, 0x49, 0x02, 0x22, 0x14, 0x31, 0x50, 0x46, 0x00, 0x97, 0xFC, 0xF5, 0xC4, 0xFF, 0xF4, 0x74, 0xBD, 0xE8, 0xFE, 0x8F, 0x7F, 0xB5, 0x05, 0x46, + 0x43, 0x88, 0x44, 0x68, 0x01, 0x22, 0xEA, 0x49, 0xEA, 0x48, 0xFC, 0xF5, 0xB8, 0xFF, 0x6B, 0x88, 0xE8, 0x4D, 0x00, 0x20, 0x6D, 0x1E, 0x0B, 0x2B, 0x75, 0xD2, 0xDF, 0xE8, 0x03, 0xF0, 0x8A, 0x06, 0x0C, 0x6C, 0x75, 0x14, 0x29, 0x45, 0x56, 0x33, + 0x1C, 0x00, 0x04, 0xB0, 0x20, 0x46, 0x21, 0x0C, 0xBD, 0xE8, 0x70, 0x40, 0x32, 0xE7, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x98, 0xE6, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, + 0xBD, 0xE8, 0x70, 0x40, 0x11, 0xE6, 0xE0, 0xB2, 0x01, 0x21, 0x02, 0xF0, 0x4C, 0xF9, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xD2, 0x49, 0x00, 0x22, 0x24, 0x31, 0xFC, 0xF5, 0x87, 0xBF, 0x00, 0x90, 0xE0, 0xB2, 0x69, 0x46, 0x41, 0xF6, + 0x48, 0xFC, 0xCD, 0x49, 0x01, 0x22, 0x44, 0x31, 0x00, 0x9B, 0x52, 0xE0, 0xE4, 0xB2, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, 0x41, 0xF6, 0x3D, 0xFC, 0xC7, 0x49, 0x01, 0x22, 0x74, 0x31, 0x28, 0x46, 0x00, 0x9B, 0xFC, 0xF5, 0x70, 0xFF, 0x01, 0x21, + 0x20, 0x46, 0x41, 0xF6, 0x47, 0xFC, 0x7F, 0xBD, 0xC1, 0x49, 0xE4, 0xB2, 0xC2, 0x4E, 0x23, 0x46, 0x01, 0x22, 0xA8, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x62, 0xFF, 0x04, 0xB0, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x22, 0x41, 0xF6, + 0xEC, 0xBB, 0xB9, 0x49, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0xE4, 0xB2, 0x00, 0x22, 0xD8, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x4F, 0xFF, 0x6A, 0x46, 0x10, 0x21, 0x4F, 0xF4, 0x04, 0x70, 0x41, 0xF6, 0x11, 0xFB, 0x01, 0x21, 0x20, 0x46, + 0x41, 0xF6, 0xF1, 0xFB, 0x7F, 0xBD, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x67, 0xE5, 0x14, 0xE0, 0x8D, 0xF8, 0x00, 0x00, 0xE2, 0xB2, 0x69, 0x46, 0x40, 0xF2, 0x75, 0x20, 0x42, 0xF6, 0x43, 0xFF, + 0x9D, 0xF8, 0x00, 0x30, 0x17, 0x2B, 0xE9, 0xD3, 0xA6, 0x48, 0xA3, 0x49, 0x01, 0x22, 0x03, 0x72, 0xF8, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x27, 0xFF, 0x7F, 0xBD, 0x04, 0xB0, 0x9F, 0x48, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x22, 0xA0, 0x49, 0xC0, 0x1E, + 0xFC, 0xF5, 0x1D, 0xBF, 0x13, 0xB5, 0x9B, 0x4B, 0xBD, 0xF8, 0x00, 0x00, 0x5B, 0x1E, 0x06, 0x28, 0x2D, 0xD0, 0x18, 0xDC, 0x20, 0xB3, 0x01, 0x28, 0x14, 0xD1, 0x9A, 0x49, 0x9A, 0x48, 0x1B, 0xF6, 0xFE, 0xFF, 0x9A, 0x48, 0x41, 0x68, 0x21, 0xB1, + 0x00, 0x21, 0x41, 0x60, 0x98, 0x48, 0x1C, 0xF6, 0x09, 0xF8, 0xBD, 0xF8, 0x02, 0x00, 0x03, 0x28, 0x16, 0xD0, 0x01, 0x28, 0x02, 0xD1, 0x01, 0x98, 0x01, 0xF0, 0x6A, 0xFB, 0x1C, 0xBD, 0x17, 0x28, 0x21, 0xD0, 0x1A, 0x28, 0xFA, 0xD1, 0x87, 0x49, + 0x00, 0x22, 0xF0, 0x39, 0x18, 0x46, 0xFC, 0xF5, 0xF2, 0xFE, 0x06, 0xF6, 0x6B, 0xFE, 0x1C, 0xBD, 0x68, 0x46, 0xFF, 0xF7, 0x2B, 0xFF, 0x1C, 0xBD, 0x01, 0xF0, 0x36, 0xFB, 0x1C, 0xBD, 0x00, 0x22, 0x88, 0x49, 0x18, 0x46, 0xFC, 0xF5, 0xE3, 0xFE, + 0x87, 0x49, 0x48, 0x68, 0x40, 0x1C, 0x48, 0x60, 0x07, 0x28, 0xF3, 0xD3, 0x69, 0x46, 0x03, 0x20, 0x01, 0xF0, 0xF8, 0xFC, 0x1C, 0xBD, 0x12, 0xF0, 0xB2, 0xFD, 0x1C, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x76, 0x4D, 0x00, 0x26, 0x6D, 0x1E, 0x0C, 0x46, + 0x01, 0x28, 0x29, 0xD0, 0x12, 0x28, 0x32, 0xD0, 0x14, 0x28, 0x0A, + 0xD0, 0x20, 0x28, 0x15, 0xD0, 0x03, 0x46, 0x01, 0x22, 0x79, 0x49, 0x28, 0x46, 0xFC, 0xF5, 0xC1, 0xFE, 0x30, 0x46, 0xBD, 0xE8, 0xFC, 0x81, 0x08, 0x68, 0x82, 0x88, 0x41, 0x88, 0xCD, 0xE9, 0x00, 0x12, 0x6C, 0x49, 0x03, 0x78, 0x03, 0x22, 0x30, + 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xB2, 0xFE, 0xEF, 0xE7, 0x20, 0x68, 0x68, 0x49, 0x01, 0x22, 0x03, 0x78, 0x84, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xA9, 0xFE, 0x20, 0x68, 0x41, 0x68, 0x00, 0x78, 0xFF, 0xF7, 0xD7, 0xFB, 0xE1, 0xE7, 0x08, 0x68, 0x02, + 0x22, 0x41, 0x88, 0x00, 0x91, 0x5F, 0x49, 0x03, 0x78, 0xB0, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x99, 0xFE, 0xD6, 0xE7, 0x20, 0x68, 0x62, 0x49, 0x01, 0x22, 0x03, 0x88, 0xC4, 0x39, 0x2F, 0x46, 0x28, 0x46, 0xFC, 0xF5, 0x8F, 0xFE, 0x56, 0x4D, 0x00, + 0x20, 0x28, 0x77, 0x21, 0x68, 0x09, 0x88, 0x99, 0xB1, 0xA8, 0x7F, 0x4F, 0xF0, 0x00, 0x02, 0x05, 0x28, 0x1D, 0xD2, 0x59, 0x49, 0x4E, 0x48, 0x58, 0x39, 0x80, 0x1E, 0xFC, 0xF5, 0x7E, 0xFE, 0xA8, 0x7F, 0x40, 0x1C, 0xA8, 0x77, 0x95, 0xF8, 0x21, + 0x10, 0xE8, 0x7F, 0xFF, 0xF7, 0xC6, 0xFB, 0xB3, 0xE7, 0xA8, 0x77, 0x68, 0x7F, 0x01, 0x28, 0xAF, 0xD1, 0x4F, 0x49, 0x00, 0x22, 0x94, 0x39, 0x38, 0x46, 0xFC, 0xF5, 0x6B, 0xFE, 0x95, 0xF8, 0x22, 0x10, 0x95, 0xF8, 0x20, 0x00, 0xED, 0xE7, 0x4A, + 0x49, 0x3F, 0x48, 0x2C, 0x39, 0xC0, 0x1E, 0xFC, 0xF5, 0x60, 0xFE, 0x9D, 0xE7, 0x10, 0xB5, 0x00, 0x24, 0xFF, 0x28, 0x07, 0xD0, 0x3C, 0x4A, 0x93, 0x7A, 0x83, 0x42, 0x07, 0xD1, 0x08, 0x46, 0x00, 0xF0, 0x8B, 0xF8, 0x17, 0xE0, 0x08, 0x46, 0x00, + 0xF0, 0x2E, 0xF8, 0x2A, 0xE0, 0xD3, 0x7A, 0x83, 0x42, 0x03, 0xD1, 0x08, 0x46, 0xFF, 0xF7, 0xAA, 0xFA, 0x0C, 0xE0, 0x13, 0x7B, 0x83, 0x42, 0x03, 0xD1, 0x08, 0x46, 0xFF, 0xF7, 0x15, 0xFB, 0x05, 0xE0, 0x53, 0x7B, 0x83, 0x42, 0x04, 0xD1, 0x08, + 0x46, 0x00, 0xF0, 0xA4, 0xF8, 0x04, 0x46, 0x14, 0xE0, 0x92, 0x7B, 0x82, 0x42, 0x11, 0xD1, 0x08, 0x78, 0x03, 0x28, 0x0E, 0xD1, 0x88, 0x78, 0x01, 0x28, 0x0B, 0xD1, 0x08, 0x79, 0x01, 0x28, 0x08, 0xD1, 0x23, 0x48, 0x00, 0x22, 0x2D, 0x49, 0x40, + 0x1E, 0xFC, 0xF5, 0x27, 0xFE, 0x03, 0x20, 0x00, 0xF0, 0x84, 0xFB, 0x20, 0x46, 0x10, 0xBD, 0x7F, 0xB5, 0x04, 0x46, 0x1D, 0x4E, 0x00, 0x25, 0x00, 0x78, 0x76, 0x1E, 0x10, 0xB1, 0x01, 0x28, 0x1E, 0xD1, 0x06, 0xE0, 0xA3, 0x78, 0x01, 0x22, 0x24, + 0x49, 0x30, 0x46, 0xFC, 0xF5, 0x12, 0xFE, 0x16, 0xE0, 0x20, 0x89, 0x63, 0x88, 0xE2, 0x88, 0x61, 0x79, 0x8D, 0xE8, 0x0F, 0x00, 0x1E, 0x49, 0x23, 0x79, 0x05, 0x22, 0x2C, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x04, 0xFE, 0x20, 0x89, 0x4F, 0xF0, 0x00, + 0x02, 0x40, 0xB1, 0x19, 0x49, 0x0C, 0x48, 0xC0, 0x31, 0xC0, 0x1E, 0xFC, 0xF5, 0xFA, 0xFD, 0x04, 0xB0, 0x28, 0x46, 0x70, 0xBD, 0x14, 0x49, 0x30, 0x46, 0x94, 0x31, 0xFC, 0xF5, 0xF2, 0xFD, 0x13, 0x48, 0x40, 0x78, 0x00, 0x28, 0xF3, 0xD0, 0x00, + 0x21, 0x01, 0x20, 0x01, 0xF0, 0x09, 0xFC, 0xEE, 0xE7, 0x8C, 0x1B, 0x80, 0x08, 0xC8, 0x1F, 0x80, 0x08, 0x03, 0x30, 0x10, 0x21, 0x38, 0x90, 0x0D, 0x00, 0x70, 0xF2, 0x20, 0x00, 0xF4, 0x20, 0x80, 0x08, 0xE0, 0x93, 0x04, 0x00, 0xA4, 0xF2, 0x20, + 0x00, 0x00, 0xF3, 0x20, 0x00, 0xF8, 0xF2, 0x20, 0x00, 0x7C, 0x1A, 0x80, 0x08, 0xF4, 0xF6, 0x20, 0x00, 0xA4, 0x22, 0x80, 0x08, 0x34, 0x18, 0x80, 0x08, 0x10, 0x14, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0x7C, 0xB5, 0x41, 0x78, 0x00, 0x25, 0x3F, + 0x4C, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x27, 0xD1, 0x0F, 0xE0, 0x81, 0x78, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x03, 0xD0, 0x20, 0xE0, 0x00, 0x22, 0x39, 0x49, 0x02, 0xE0, 0x38, 0x49, 0x00, 0x22, 0x38, 0x31, 0x20, 0x46, 0xFC, 0xF5, 0xB1, + 0xFD, 0x16, 0xE0, 0x36, 0x49, 0x88, 0x1C, 0x12, 0xF0, 0x29, 0xFC, 0x34, 0x4E, 0x32, 0x49, 0x18, 0x3E, 0x02, 0x22, 0x70, 0x8B, 0x00, 0x90, 0x33, 0x8B, 0x70, 0x31, 0x20, 0x46, 0xFC, 0xF5, 0xA1, 0xFD, 0xB0, 0x7E, 0x8D, 0xF8, 0x04, 0x00, 0x01, + 0x21, 0x01, 0xAA, 0x08, 0x46, 0xFE, 0xF7, 0x62, 0xFA, 0x28, 0x46, 0x7C, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x26, 0x4E, 0x04, 0x46, 0x03, 0x78, 0x00, 0x25, 0x01, 0x22, 0x27, 0x49, 0x30, 0x46, 0xFC, 0xF5, 0x8C, 0xFD, 0x20, 0x78, 0x01, 0x28, 0x02, + 0xD0, 0x03, 0x28, 0x3D, 0xD1, 0x1F, 0xE0, 0x20, 0x79, 0x01, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x13, 0xD0, 0x36, 0xE0, 0x1F, 0x49, 0x00, 0x22, 0x24, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x7A, 0xFD, 0x01, 0x21, 0x10, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x19, + 0x48, 0x1A, 0x4B, 0x18, 0x38, 0x02, 0x22, 0x41, 0x7B, 0x00, 0x20, 0x44, 0xF6, 0x11, 0xFC, 0x23, 0xE0, 0x15, 0x49, 0x00, 0x22, 0x50, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x67, 0xFD, 0x1C, 0xE0, 0x20, 0x79, 0x4F, 0xF4, 0x90, 0x67, 0x01, 0x28, 0x16, + 0xD1, 0x0F, 0x49, 0x00, 0x22, 0x80, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x5B, 0xFD, 0x10, 0x22, 0x0D, 0x48, 0xE1, 0x68, 0x4E, 0xF6, 0x74, 0xFF, 0x10, 0x21, 0x0A, + 0x48, 0xFD, 0xF5, 0xD5, 0xFF, 0x38, 0xB9, 0x07, 0x49, 0x04, 0x48, 0x00, 0x22, 0xC0, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x4A, 0xFD, 0x3D, 0x46, 0x28, 0x46, 0x86, 0xE6, 0x02, 0x30, 0x10, 0x21, 0xFC, 0x14, 0x80, 0x08, 0x88, 0xF2, 0x20, 0x00, 0x38, + 0x17, 0x80, 0x08, 0xFC, 0xE9, 0x20, 0x00, 0x00, 0xB5, 0x9D, 0xB0, 0x1C, 0x21, 0x03, 0xA8, 0x4F, 0xF6, 0x38, 0xF8, 0xF8, 0x48, 0x07, 0xC8, 0x8D, 0xE8, 0x07, 0x00, 0x4F, 0xF4, 0xC0, 0x70, 0xAD, 0xF8, 0x6C, 0x00, 0x00, 0x20, 0x07, 0x21, 0x8D, + 0xF8, 0x34, 0x10, 0x4F, 0xF4, 0xA0, 0x71, 0xAD, 0xF8, 0x44, 0x10, 0xAD, 0xF8, 0x30, 0x10, 0x01, 0x21, 0x8D, 0xF8, 0x3C, 0x00, 0x8D, 0xF8, 0x40, 0x00, 0x0A, + 0x90, 0x0B, 0x90, 0x8D, 0xF8, 0x38, 0x00, 0x03, 0x22, 0x8D, 0xF8, 0x48, 0x10, 0xAD, 0xF8, 0x4C, 0x10, 0x8D, 0xF8, 0x50, 0x20, 0x8D, 0xF8, 0x54, 0x00, 0x8D, 0xF8, 0x58, 0x00, 0x17, 0x90, 0x8D, 0xF8, 0x60, 0x00, 0xAD, 0xF8, 0x64, 0x10, 0x8D, + 0xF8, 0x68, 0x10, 0x1A, 0xAA, 0x40, 0xF2, 0x23, 0x20, 0x41, 0xF6, 0xFA, 0xFD, 0xE0, 0x48, 0x41, 0xF6, 0xF4, 0xFD, 0x6A, 0x46, 0x28, 0x21, 0x40, 0xF2, 0x22, 0x20, 0x41, 0xF6, 0xF1, 0xFD, 0x1B, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x21, 0x20, 0x41, + 0xF6, 0xEB, 0xFD, 0x0F, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, 0x09, 0xFF, 0x10, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x19, 0x70, 0x46, 0xF6, 0x03, 0xFF, 0x0A, + 0xAA, 0x06, 0x21, 0x40, 0xF2, 0x65, 0x20, 0x46, 0xF6, 0xFD, 0xFE, 0x0D, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0xF7, 0xFE, 0x0E, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0xF1, 0xFE, 0x11, 0xAA, 0x02, 0x21, 0x4F, + 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0xEB, 0xFE, 0x0C, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0xE5, 0xFE, 0xC5, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0xDF, 0xFE, 0xC2, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, + 0x20, 0x46, 0xF6, 0xD8, 0xFE, 0x12, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x02, 0x20, 0x40, 0xF6, 0x5F, 0xFF, 0x13, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x03, 0x20, 0x40, 0xF6, 0x59, 0xFF, 0x14, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x01, 0x70, 0x40, 0xF6, 0x53, + 0xFF, 0x15, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x05, 0x20, 0x40, 0xF6, 0x4D, 0xFF, 0x17, 0xAA, 0x04, 0x21, 0x40, 0xF2, 0x11, 0x20, 0x41, 0xF6, 0x69, 0xF8, 0x16, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x12, 0x20, 0x41, 0xF6, 0x63, 0xF8, 0x18, 0xAA, 0x01, + 0x21, 0x40, 0xF2, 0x13, 0x20, 0x41, 0xF6, 0x5D, 0xF8, 0x19, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0x41, 0xF6, 0x57, 0xF8, 0x1D, 0xB0, 0x00, 0xBD, 0x2D, 0xE9, 0xF1, 0x4F, 0x86, 0xB0, 0x00, 0x24, 0x45, 0xF6, 0xF8, 0xF8, 0xA3, 0x4E, 0x05, + 0x46, 0xB3, 0x7C, 0x43, 0xB1, 0x01, 0x22, 0xA2, 0x49, 0xA2, 0x48, 0xFC, 0xF5, 0x7E, 0xFC, 0x00, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x99, 0x9F, 0x48, 0x01, 0x27, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x03, 0x0A, + 0x4F, 0xF0, 0x07, 0x08, 0x4F, 0xF0, 0x20, 0x0B, 0x06, 0x29, 0x78, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x77, 0x03, 0x3A, 0xE0, 0xFE, 0x84, 0x8D, 0xF8, 0x10, 0x70, 0x8D, 0xF8, 0x04, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, + 0x63, 0x20, 0x46, 0xF6, 0x75, 0xFE, 0x05, 0xF1, 0x0E, 0x02, 0x01, 0x21, 0x4F, 0xF4, 0x19, 0x70, 0x46, 0xF6, 0x6E, 0xFE, 0x05, 0xF1, 0x08, 0x02, 0x06, 0x21, 0x40, 0xF2, 0x65, 0x20, 0x46, 0xF6, 0x67, 0xFE, 0x01, 0xAA, 0x01, 0x21, 0x40, 0xF2, + 0x67, 0x20, 0x46, 0xF6, 0x61, 0xFE, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x5B, 0xFE, 0x46, 0xF6, 0x74, 0xFF, 0x4F, 0xF0, 0x00, 0x02, 0x10, 0xB1, 0x7F, 0x49, 0x5C, 0x31, 0x5B, 0xE1, 0x7E, 0x49, 0x7E, 0x48, 0x34, 0x31, + 0x40, 0x1C, 0xFC, 0xF5, 0x34, 0xFC, 0xB7, 0x74, 0x77, 0x75, 0x0E, 0xE1, 0x8D, 0xF8, 0x10, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0xA0, 0xAD, 0xF8, 0x08, 0xB0, 0xAD, 0xF8, 0x0C, 0xB0, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, + 0x46, 0xF6, 0x3A, 0xFE, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x34, 0xFE, 0x01, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0x2E, 0xFE, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0x28, 0xFE, + 0x03, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0x22, 0xFE, 0x63, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0x1C, 0xFE, 0x60, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0x15, 0xFE, 0x46, 0xF6, + 0x2E, 0xFF, 0x4F, 0xF0, 0x00, 0x02, 0x18, 0xB1, 0x5C, 0x49, 0xB0, 0x31, 0x15, 0xE1, 0x24, 0xE1, 0x5A, 0x49, 0x5B, 0x48, 0x80, 0x31, 0x40, 0x1C, 0xFC, 0xF5, 0xED, 0xFB, 0xB7, 0x74, 0x02, 0x20, 0x70, 0x75, 0x40, 0xF6, 0xB8, 0x31, 0x57, 0xE0, + 0x54, 0x49, 0x00, 0x22, 0xDC, 0x31, 0xFC, 0xF5, 0xE2, 0xFB, 0x30, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x4E, 0x49, 0x00, 0x20, 0x8D, 0xF8, 0x10, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0xA0, 0xAD, 0xF8, 0x08, 0xB0, 0x3A, 0x31, 0x2A, 0x18, + 0x0B, 0x18, 0x12, 0x7A, 0x40, 0x1C, 0xDA, 0x74, 0x06, 0x28, 0xF8, 0xDB, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, 0xE0, 0xFD, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0xDA, 0xFD, 0x01, 0xAA, 0x01, 0x21, + 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0xD4, 0xFD, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0xCE, 0xFD, 0x03, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0xC8, 0xFD, 0x36, 0x4A, 0x19, 0x21, 0x3A, 0x32, 0x40, 0xF2, + 0x61, 0x20, 0x46, 0xF6, 0xC1, 0xFD, 0x33, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0xBA, 0xFD, 0x46, 0xF6, 0xD3, 0xFE, 0x4F, 0xF0, 0x00, 0x02, 0x08, 0xB1, 0x32, 0x49, 0xBB, 0xE0, 0x31, 0x49, 0x2E, 0x48, 0x2C, 0x39, + 0x40, 0x1C, 0xFC, 0xF5, 0x94, 0xFB, 0xB7, 0x74, 0x05, 0x20, 0x70, 0x75, 0x42, 0xF6, 0xE0, 0x61, 0x2C, 0x48, 0x1B, 0xF6, 0x7C, 0xFC, 0x68, 0xE0, 0x29, 0x49, 0x00, 0x22, 0x28, 0x31, 0xFC, 0xF5, 0x86, 0xFB, 0x30, 0x20, 0xAD, 0xF8, 0x0C, 0x00, + 0x8D, 0xF8, 0x10, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0x90, 0xAD, 0xF8, 0x08, 0xB0, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, 0x8E, 0xFD, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x88, 0xFD, + 0x01, 0xAA, 0x00, 0xE0, 0x4B, 0xE0, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0x80, 0xFD, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0x7A, 0xFD, 0x03, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0x74, 0xFD, + 0x0C, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0x6E, 0xFD, 0x09, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0x67, 0xFD, 0x46, 0xF6, 0x80, 0xFE, 0x4F, 0xF0, 0x00, 0x02, 0xA8, 0xB1, 0x08, 0x49, 0x7C, 0x31, + 0x67, 0xE0, 0x00, 0x00, 0xF8, 0xE6, 0x21, 0x00, 0xB5, 0xAC, 0x20, 0x00, 0xC8, 0xE6, 0x20, 0x00, 0x70, 0xF2, 0x20, 0x00, 0xD0, 0x22, 0x80, 0x08, 0x01, 0x30, 0x10, 0x21, 0x02, 0x33, 0x10, 0x21, 0x04, 0x24, 0x80, 0x08, 0xA0, 0xF2, 0x20, 0x00, + 0x76, 0x49, 0x77, 0x48, 0xFC, 0xF5, 0x2F, 0xFB, 0xB7, 0x74, 0x86, 0xF8, 0x15, 0xA0, 0x44, 0xF6, 0x20, 0x61, 0x74, 0x48, 0x1B, 0xF6, 0x17, 0xFC, 0x00, 0x22, 0x05, 0x21, 0x26, 0x20, 0x01, 0xF0, 0xAB, 0xFA, 0x01, 0x24, 0x59, 0xE0, 0x6D, 0x49, + 0x00, 0x22, 0x54, 0x31, 0xFC, 0xF5, 0x1B, 0xFB, 0x30, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x8D, 0xF8, 0x10, 0xA0, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0xA0, 0xAD, 0xF8, 0x08, 0xB0, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, + 0x23, 0xFD, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x1D, 0xFD, 0x01, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0x17, 0xFD, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0x11, 0xFD, 0x03, 0xAA, + 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0x0B, 0xFD, 0x59, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0x05, 0xFD, 0x56, 0x4A, 0x04, 0x21, 0x21, 0x3A, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0xFE, 0xFC, 0x46, 0xF6, 0x17, 0xFE, + 0x4F, 0xF0, 0x00, 0x02, 0x30, 0xB1, 0x4D, 0x49, 0xA4, 0x31, 0x4D, 0x48, 0x40, 0x1E, 0xFC, 0xF5, 0xDA, 0xFA, 0x12, 0xE0, 0x49, 0x49, 0x4A, 0x48, 0x78, 0x31, 0xFC, 0xF5, 0xD4, 0xFA, 0xB7, 0x74, 0x04, 0x20, 0x70, 0x75, 0x41, 0xF2, 0x88, 0x31, + 0x3E, 0xE7, 0x0B, 0x46, 0x43, 0x49, 0x44, 0x48, 0x01, 0x22, 0xCC, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0xC6, 0xFA, 0x20, 0x46, 0x46, 0xE6, 0x70, 0xB5, 0x42, 0x4D, 0x3F, 0x4E, 0x00, 0x24, 0xA8, 0x75, 0xAB, 0x7C, 0x76, 0x1E, 0x01, 0x2B, 0x06, 0xD0, + 0x01, 0x22, 0x3F, 0x49, 0x30, 0x46, 0xFC, 0xF5, 0xB6, 0xFA, 0x20, 0x46, 0x70, 0xBD, 0x46, 0xF6, 0x48, 0xFE, 0x4F, 0xF0, 0x00, 0x02, 0x28, 0xB1, 0x39, 0x49, 0x30, 0x46, 0x30, 0x39, 0xFC, 0xF5, 0xAA, 0xFA, 0xF2, 0xE7, 0x36, 0x49, 0x32, 0x48, + 0x68, 0x39, 0xFC, 0xF5, 0xA4, 0xFA, 0x02, 0x20, 0xA8, 0x74, 0x01, 0x24, 0xE9, 0xE7, 0x70, 0xB5, 0x01, 0x46, 0x30, 0x48, 0x2C, 0x4D, 0x00, 0x24, 0xC1, 0x75, 0x83, 0x7C, 0x6D, 0x1E, 0x03, 0x2B, 0x09, 0xD0, 0x04, 0x2B, 0x07, 0xD0, 0x2C, 0x49, + 0x01, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x8E, 0xFA, 0x20, 0x46, 0x70, 0xBD, 0x00, 0x20, 0x42, 0xF6, 0x6C, 0xFB, 0x4F, 0xF0, 0x00, 0x02, 0x28, 0xB1, 0x25, 0x49, 0x28, 0x46, 0x70, 0x31, 0xFC, 0xF5, 0x81, 0xFA, 0xF1, 0xE7, 0x22, 0x49, + 0x1D, 0x48, 0x2C, 0x31, 0xFC, 0xF5, 0x7B, 0xFA, 0x01, 0x24, 0xEA, 0xE7, 0x3E, 0xB5, 0x1D, 0x4C, 0x0B, 0x46, 0x00, 0x21, 0xE1, 0x71, 0x0A, + 0x21, 0xB2, 0xFB, 0xF1, 0xF2, 0x6F, 0xF0, 0x01, 0x01, 0x01, 0xEB, 0x40, 0x01, 0x89, 0xB2, 0xCD, 0xE9, 0x00, 0x21, 0x02, 0x46, 0x02, 0x91, 0x11, 0x46, 0x00, 0x20, 0x42, 0xF6, 0x7A, 0xFB, 0x00, 0x28, 0x1A, 0xD0, 0x0F, 0x48, 0xE1, 0x79, 0x40, + 0x1E, 0x03, 0x29, 0x0E, 0xD2, 0x49, 0x1C, 0xE1, 0x71, 0x0F, 0x49, 0x00, 0x22, 0xE4, 0x31, 0xFC, 0xF5, 0x56, 0xFA, 0x03, 0xB0, 0x41, 0xF2, 0x88, 0x31, 0xBD, 0xE8, 0x30, 0x40, 0x0B, 0x48, 0x1B, 0xF6, 0x3E, 0xBB, 0x03, 0xB0, 0x00, 0x22, 0xBD, + 0xE8, 0x30, 0x40, 0x09, 0x49, 0xFC, 0xF5, 0x47, 0xBA, 0x3E, 0xBD, 0x00, 0x00, 0x54, 0x24, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0xA0, 0xF2, 0x20, 0x00, 0xE5, 0xE6, 0x20, 0x00, 0x70, 0xF2, 0x20, 0x00, 0xB0, 0x25, 0x80, 0x08, 0xA8, 0xF2, 0x20, + 0x00, 0xC8, 0x26, 0x80, 0x08, 0x7C, 0xB5, 0x26, 0x48, 0x00, 0x24, 0xCD, 0xE9, 0x00, 0x40, 0x44, 0xF6, 0x20, 0x63, 0x01, 0x22, 0x23, 0xA1, 0x26, 0x48, 0x1B, 0xF6, 0xE5, 0xFA, 0x25, 0x4D, 0x20, 0xB9, 0x00, 0x22, 0x25, 0x49, 0x28, 0x46, 0xFC, + 0xF5, 0x22, 0xFA, 0x24, 0x48, 0x42, 0xF6, 0xE0, 0x63, 0xCD, 0xE9, 0x00, 0x40, 0x1E, 0x48, 0x01, 0x22, 0x21, 0xA1, 0x0C, 0x30, 0x1B, 0xF6, 0xD3, 0xFA, 0x28, 0xB9, 0x1D, 0x49, 0x00, 0x22, 0x2C, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x10, 0xFA, 0x22, + 0x48, 0x22, 0x4B, 0xCD, 0xE9, 0x00, 0x40, 0x16, 0x48, 0x01, 0x22, 0x21, 0xA1, 0x00, 0x1D, 0x1B, 0xF6, 0xC2, 0xFA, 0x28, 0xB9, 0x14, 0x49, 0x00, 0x22, 0x64, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xFF, 0xF9, 0x21, 0x48, 0x41, 0xF2, 0x88, 0x33, 0xCD, + 0xE9, 0x00, 0x40, 0x0D, 0x48, 0x01, 0x22, 0x1F, 0xA1, 0x08, 0x30, 0x1B, 0xF6, 0xB0, 0xFA, 0x28, 0xB9, 0x0B, 0x49, 0x00, 0x22, 0x98, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xED, 0xF9, 0x00, 0xF0, 0x0F, 0xFD, 0xBD, 0xE8, 0x7C, 0x40, 0x00, 0xF0, 0x01, + 0xBE, 0xE5, 0x83, 0x20, 0x00, 0x61, 0x64, 0x76, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0xA0, 0xF2, 0x20, 0x00, 0x02, 0x30, 0x10, 0x21, 0x94, 0x27, 0x80, 0x08, 0x09, 0x84, 0x20, 0x00, 0x70, 0x61, 0x69, 0x72, 0x5F, 0x66, 0x61, + 0x69, 0x6C, 0x5F, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x73, 0x84, 0x20, 0x00, 0xE0, 0x93, 0x04, 0x00, 0x6E, 0x6F, 0x5F, 0x61, 0x63, 0x74, 0x5F, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, + 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x29, 0x84, 0x20, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5F, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xB5, 0x02, 0x22, 0x8D, 0xF8, 0x04, 0x20, 0x3D, 0x22, 0x38, 0x4C, 0x00, 0x92, 0x01, 0x46, 0x35, 0x4B, 0x00, 0x22, 0xA0, 0x68, 0x1A, 0xF6, 0x61, 0xFC, 0x35, 0x4D, 0x50, 0xB1, 0x42, 0x20, 0x00, 0x90, 0x31, 0x4B, 0x00, 0x22, 0x01, + 0xA9, 0x60, 0x68, 0x1A, 0xF6, 0x57, 0xFC, 0x20, 0xB1, 0x01, 0x20, 0x7C, 0xBD, 0x00, 0x22, 0x2F, 0x49, 0x02, 0xE0, 0x2E, 0x49, 0x00, 0x22, 0x1C, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x88, 0xF9, 0x00, 0x20, 0x7C, 0xBD, 0x1F, 0xB5, 0x5B, 0x20, 0x00, + 0x90, 0x25, 0x4B, 0x26, 0x48, 0x18, 0x33, 0x08, 0x22, 0x20, 0x21, 0x08, 0x30, 0x1A, 0xF6, 0xC6, 0xFB, 0x5C, 0x20, 0x00, 0x90, 0x20, 0x4B, 0x21, 0x48, 0x18, 0x33, 0x01, 0x22, 0x40, 0x21, 0x00, 0x1D, 0x1A, 0xF6, 0xBC, 0xFB, 0x1D, 0x4C, 0x20, + 0x22, 0xD4, 0xE9, 0x01, 0x01, 0x40, 0xF6, 0x71, 0xFB, 0x00, 0xF0, 0xA6, 0xF8, 0x67, 0x25, 0x4F, 0xF0, 0xFF, 0x37, 0x6D, 0x26, 0x16, 0x4B, 0x00, 0x95, 0x18, 0x33, 0x3A, 0x46, 0x03, 0xA9, 0x60, 0x68, 0x1A, 0xF6, 0x50, 0xFC, 0x00, 0x28, 0xF5, + 0xD0, 0x9D, 0xF8, 0x0C, 0x00, 0x02, 0x28, 0x02, 0xD0, 0x40, 0xF6, 0xC8, 0xFB, 0xEE, 0xE7, 0x0E, 0x4B, 0x00, 0x96, 0x18, 0x33, 0x00, 0x22, 0x01, 0xA9, 0xA0, 0x68, 0x1A, 0xF6, 0x3F, 0xFC, 0x00, 0x28, 0xE4, 0xD0, 0xDD, 0xE9, 0x01, 0x01, 0xFF, + 0xF7, 0x29, 0xFA, 0xDF, 0xE7, 0x1C, 0xB5, 0x01, 0x21, 0xC8, 0x02, 0x00, 0x23, 0xAF, 0xF2, 0x8D, 0x02, 0xCD, 0xE9, 0x00, 0x01, 0x06, 0xA1, 0x03, 0x48, 0x1B, 0xF6, 0xF2, 0xF8, 0x1C, 0xBD, 0x00, 0x00, 0x04, 0xE7, 0x21, 0x00, 0xB0, 0xF2, 0x20, + 0x00, 0x00, 0x30, 0x10, 0x21, 0x64, 0x28, 0x80, 0x08, 0x61, 0x70, 0x70, 0x00, 0x10, 0xB5, 0x03, 0x28, 0x01, 0xD3, 0x00, 0x20, 0x10, 0xBD, 0x1A, 0x49, 0x00, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x80, 0x04, 0x08, 0x22, 0x18, 0x49, 0x20, 0x68, 0x4E, + 0xF6, 0xF1, 0xFA, 0x98, 0xB1, 0xA2, 0x69, 0x61, 0x68, 0xE0, 0x68, 0x4E, 0xF6, 0x36, 0xFB, 0xE2, 0x69, 0xA1, 0x68, 0x20, 0x69, 0x4E, 0xF6, 0x31, 0xFB, 0x21, 0x6A, 0x60, 0x69, 0x4E, 0xF6, 0xEE, 0xFB, 0x20, 0x68, 0x0E, 0x49, 0x02, 0x68, 0x0A, + 0x60, 0x40, 0x68, 0x48, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x09, 0x4D, 0x00, 0x24, 0x04, 0xEB, 0xC4, 0x00, 0x08, 0x22, 0x55, 0xF8, 0x20, 0x00, 0x06, 0x49, 0x4E, 0xF6, 0xCF, 0xFA, 0x20, 0xB1, 0x64, 0x1C, 0x03, 0x2C, 0xF3, 0xDB, 0x03, + 0x20, 0x70, 0xBD, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0x00, 0x1C, 0xE7, 0x20, 0x00, 0xBC, 0xF2, 0x20, 0x00, 0x30, 0xB5, 0x01, 0x22, 0x91, 0xB0, 0x15, 0x49, 0x10, 0x04, 0x10, 0xF0, 0x97, 0xFC, 0x68, 0x46, 0x11, 0xF0, 0x95, 0xF9, 0x00, 0x20, 0xAD, + 0xF8, 0x0A, + 0x00, 0x11, 0x48, 0x11, 0x4C, 0x01, 0x25, 0x03, 0x90, 0xAD, 0xF8, 0x08, 0x50, 0x69, 0x46, 0x20, 0x46, 0x11, 0xF0, 0xF5, 0xF8, 0x03, 0x20, 0x08, 0x21, 0x0E, 0x90, 0x8D, 0xF8, 0x34, 0x10, 0x8D, 0xF8, 0x3C, 0x50, 0x0D, 0xA8, 0x05, 0xF6, 0xFF, + 0xFC, 0xE0, 0x68, 0x01, 0x21, 0x20, 0x46, 0x11, 0xF0, 0x93, 0xF9, 0x01, 0x21, 0x20, 0x46, 0x11, 0xF0, 0x83, 0xF9, 0x11, 0xB0, 0x30, 0xBD, 0xD2, 0xE7, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0xFF, 0xB3, 0xC4, 0x04, 0x78, 0x20, 0x00, 0x40, 0x10, + 0xB5, 0xFC, 0x4C, 0x00, 0x22, 0xFA, 0x49, 0x20, 0x46, 0xFC, 0xF5, 0xB4, 0xF8, 0xFA, 0x49, 0x4F, 0xF4, 0x00, 0x00, 0x01, 0xF0, 0x4C, 0xFD, 0x00, 0x28, 0x08, 0xD0, 0xF6, 0x48, 0xF4, 0x49, 0x01, 0x22, 0x03, 0x78, 0x30, 0x31, 0x20, 0x46, 0xFC, + 0xF5, 0xA5, 0xF8, 0x01, 0x20, 0x10, 0xBD, 0xF1, 0x48, 0x00, 0x78, 0xFF, 0x28, 0x01, 0xD0, 0x12, 0xF0, 0x90, 0xB9, 0x70, 0x47, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x02, 0x20, 0x00, 0xF6, 0x7A, 0xFB, 0x04, 0x46, 0x00, 0x90, 0xE8, 0x49, 0xE8, + 0x48, 0x2B, 0x46, 0x02, 0x22, 0x70, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x8C, 0xF8, 0x20, 0x46, 0x38, 0xBD, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x04, 0x20, 0x00, 0xF6, 0x68, 0xFB, 0x04, 0x46, 0x00, 0x90, 0xDF, 0x49, 0xDF, 0x48, 0x2B, 0x46, 0x02, + 0x22, 0xAC, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x7A, 0xF8, 0x20, 0x46, 0x38, 0xBD, 0x70, 0xB5, 0x0D, 0x46, 0x00, 0x24, 0x00, 0xF6, 0x84, 0xFF, 0x20, 0xB1, 0x28, 0x44, 0xFF, 0xF7, 0xD3, 0xFF, 0x10, 0xB1, 0x02, 0xE0, 0x66, 0x24, 0x00, 0xE0, 0x6C, + 0x24, 0xD3, 0x49, 0xD3, 0x48, 0x23, 0x46, 0x01, 0x22, 0xE8, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x62, 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x2D, 0xE9, 0xFC, 0x47, 0x16, 0x46, 0x0D, 0x46, 0xDF, 0xF8, 0x34, 0x93, 0xCD, 0xE9, 0x00, 0x56, 0x04, 0x46, 0x03, + 0x46, 0xA9, 0xF1, 0x01, 0x09, 0x00, 0x27, 0x03, 0x22, 0xCA, 0x49, 0x48, 0x46, 0xFC, 0xF5, 0x4E, 0xF8, 0xA4, 0xF5, 0x7F, 0x40, 0xFE, 0x38, 0x15, 0xD0, 0x1A, 0xF6, 0x41, 0xFF, 0x80, 0x46, 0x32, 0x46, 0x29, 0x46, 0x20, 0x46, 0x3B, 0xF6, 0xF8, + 0xFE, 0x07, 0x46, 0x40, 0x46, 0x1A, 0xF6, 0x44, 0xFF, 0xC0, 0x49, 0x3B, 0x46, 0x01, 0x22, 0x70, 0x31, 0x48, 0x46, 0xFC, 0xF5, 0x37, 0xF8, 0x38, 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x00, 0x24, 0x05, 0x20, 0x00, 0xF6, 0xA1, 0xFA, 0x05, 0x44, 0x13, + 0xE0, 0x6A, 0x46, 0x04, 0x21, 0x28, 0x46, 0x00, 0xF6, 0x77, 0xFD, 0x00, 0x98, 0x40, 0x1C, 0x09, 0xD0, 0xB4, 0x49, 0xB1, 0x48, 0x23, 0x46, 0x01, 0x22, 0x44, 0x31, 0xC0, 0x1E, 0xFC, 0xF5, 0x1E, 0xF8, 0x85, 0x27, 0xDD, 0xE7, 0x64, 0x1C, 0x2D, + 0x1D, 0xB4, 0xEB, 0x96, 0x0F, 0xE8, 0xD3, 0xD7, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x0E, 0x46, 0x00, 0x24, 0xA0, 0xF5, 0x7F, 0x41, 0x91, 0x46, 0x80, 0x46, 0xFE, 0x39, 0x1B, 0xD0, 0x00, 0xF6, 0x1B, 0xFF, 0xE0, 0xB1, 0x87, 0x19, 0x38, 0x46, 0xFF, + 0xF7, 0x69, 0xFF, 0x4A, 0x46, 0x31, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xA0, 0xFF, 0x05, 0x00, 0x02, 0xD0, 0x64, 0x1C, 0x03, 0x2C, 0xF2, 0xD3, 0x9E, 0x49, 0x23, 0x46, 0x02, 0x22, 0x98, 0x31, 0x9A, 0x48, 0x00, 0x95, 0xFB, 0xF5, 0xF3, 0xFF, 0x28, + 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x20, 0x00, 0xF6, 0x5E, 0xFA, 0xE1, 0xE7, 0xB1, 0x25, 0xEE, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, 0x04, 0x46, 0x00, 0x25, 0x00, 0xF6, 0xD6, 0xFE, 0x90, 0xF0, 0x01, 0x0F, 0x42, 0xF2, 0x91, 0x77, 0x42, 0xF2, 0x92, + 0x78, 0x42, 0xF2, 0x93, 0x79, 0x42, 0xF2, 0x94, 0x7A, 0x42, 0xF2, 0x95, 0x7B, 0x0E, 0xD0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x2E, 0xD1, 0x04, 0x20, 0x00, 0xF6, 0x77, + 0xFA, 0x05, 0x46, 0x29, 0xE0, 0x02, 0x20, 0x00, 0xF6, 0x36, 0xFA, 0x06, 0x46, 0xF5, 0xF5, 0x79, 0xFB, 0xB0, 0x42, 0x03, 0xD1, 0x03, 0x20, 0x00, 0xF6, 0x2E, 0xFA, 0x06, 0x46, 0x42, 0xF2, 0x90, 0x71, 0x8C, 0x42, 0x02, 0xD1, 0x4F, 0xF4, 0x80, + 0x55, 0x16, 0xE0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x0C, 0xD1, 0x30, 0x46, 0x00, 0xF6, 0x4D, 0xFE, 0x40, 0xB1, 0x06, 0xEB, 0xC4, 0x00, 0xA0, 0xF5, 0xA0, 0x30, 0xD0, + 0xF8, 0x14, 0x55, 0x68, 0x1C, 0x00, 0xD1, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFC, 0x41, 0x0E, 0x46, 0x08, 0x9C, 0x4F, 0xF0, 0x00, 0x01, 0x1D, 0x00, 0x17, 0x46, 0x21, 0x60, 0x0F, 0xD0, 0xA0, 0xF5, 0x7F, 0x41, 0xFE, + 0x39, 0x07, 0xD0, 0xFF, 0xF7, 0xA1, 0xFF, 0xDF, 0xF8, 0x90, 0xC1, 0xAC, 0xF1, 0x03, 0x0C, 0x3E, 0xB1, 0x15, 0xE0, 0x05, 0x20, 0x00, 0xF6, 0x2F, 0xFA, 0xF5, 0xE7, 0x4F, 0xF4, 0xE3, 0x70, 0x1B, 0xE0, 0xAB, 0x68, 0x03, 0xF5, 0x80, 0x63, 0x83, + 0x42, 0x09, 0xD9, 0x5D, 0x49, 0x00, 0x90, 0x02, 0x22, 0xC4, 0x31, 0x60, 0x46, 0xFB, 0xF5, 0x72, 0xFF, 0x40, 0xF2, 0xDD, 0x10, 0x0C, 0xE0, 0xF1, 0x19, 0x81, 0x42, 0x0D, 0xD9, 0xCD, 0xE9, 0x00, 0x70, 0x33, 0x46, 0x03, 0x22, 0x56, 0x49, 0x60, + 0x46, 0xFB, 0xF5, 0x64, 0xFF, 0x4F, 0xF4, 0xF3, 0x70, 0x20, 0x60, 0x00, 0x20, 0xBD, 0xE8, 0xFC, 0x81, 0x01, 0x20, 0xFB, 0xE7, 0x2D, 0xE9, 0xFF, 0x47, 0x80, 0x46, 0x00, 0x91, 0x16, 0x46, 0x00, 0x20, 0x0D, 0x46, 0xDF, 0xF8, 0x24, 0xA1, 0xCD, + 0xE9, 0x01, 0x60, 0x4A, 0x49, 0x1C, 0x46, 0xAA, 0xF1, 0x01, 0x0A, + 0x43, 0x46, 0x03, 0x22, 0x54, 0x31, 0x50, 0x46, 0xFB, 0xF5, 0x47, 0xFF, 0xB0, 0x07, 0x02, 0xD0, 0x40, 0xF2, 0x4F, 0x20, 0x60, 0xE0, 0x3C, 0xB1, 0xA8, 0xF5, 0x7F, 0x41, 0x40, 0x46, 0xFE, 0x39, 0x05, 0xD0, 0x00, 0xF6, 0x4B, 0xFE, 0x05, 0xE0, + 0x40, 0xF2, 0x55, 0x20, 0x54, 0xE0, 0x05, 0x20, 0x00, 0xF6, 0xA4, 0xF9, 0x07, 0x00, 0x0C, 0xD0, 0x02, 0xA8, 0x00, 0x90, 0x23, 0x46, 0x32, 0x46, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x8E, 0xFF, 0xF0, 0xB3, 0xDF, 0xF8, 0xCC, 0x90, 0x1D, 0xB1, + 0x0E, 0xE0, 0x4F, 0xF4, 0x1C, 0x70, 0x3F, 0xE0, 0x60, 0x88, 0x32, 0x49, 0x40, 0xF0, 0x80, 0x00, 0x60, 0x80, 0x43, 0x46, 0x02, 0x22, 0x90, 0x31, 0x48, 0x46, 0x00, 0x97, 0xFB, 0xF5, 0x15, 0xFF, 0x78, 0x19, 0x07, 0x46, 0x29, 0x05, 0x0B, 0xD0, + 0xC5, 0xF3, 0x0B, 0x01, 0x31, 0x44, 0x4F, 0xF4, 0x80, 0x52, 0x91, 0x42, 0x07, 0xD9, 0x96, 0x42, 0x05, 0xD8, 0xB8, 0x19, 0x6F, 0xF3, 0x0B, 0x00, 0xFF, 0xF7, 0x67, 0xFE, 0x08, 0xB1, 0x00, 0x25, 0x22, 0xE0, 0x40, 0xF2, 0xF6, 0x20, 0x1B, 0xE0, + 0x78, 0x19, 0x80, 0x46, 0x21, 0x68, 0x00, 0xF6, 0x22, 0xFC, 0x48, 0xF0, 0x80, 0x70, 0x03, 0xA9, 0x00, 0xF6, 0x55, 0xFC, 0x20, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0F, 0xD0, 0x78, 0x19, 0xCD, 0xE9, 0x00, 0x10, 0x03, 0x22, 0x17, 0x49, 0x00, 0xE0, + 0x0C, 0xE0, 0xD8, 0x31, 0x48, 0x46, 0x23, 0x68, 0xFB, 0xF5, 0xE3, 0xFE, 0x40, 0xF2, 0x07, 0x30, 0x02, 0x90, 0x03, 0xE0, 0x24, 0x1D, 0x2D, 0x1D, 0xB5, 0x42, 0xDD, 0xD3, 0x01, 0x22, 0x10, 0x49, 0x50, 0x46, 0x02, 0x9B, 0xFB, 0xF5, 0xD5, 0xFE, + 0x02, 0x98, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x46, 0x01, 0x20, 0xA1, 0xF5, 0x7F, 0x42, 0xFE, 0x3A, 0x02, 0xD0, 0x08, 0x46, 0x3B, 0xF6, 0x13, 0xBD, 0x08, 0x4A, 0x00, 0x21, 0x11, 0x60, 0x70, 0x47, 0x00, 0x00, 0x88, 0x2E, 0x80, 0x08, + 0x03, 0x31, 0x10, 0x21, 0x88, 0xE7, 0x20, 0x00, 0xA4, 0x2F, 0x80, 0x08, 0xA8, 0x30, 0x80, 0x08, 0xBC, 0x31, 0x80, 0x08, 0xC4, 0xF2, 0x20, 0x00, 0xF8, 0xB5, 0x04, 0x46, 0xA0, 0xF5, 0x7F, 0x40, 0x4F, 0xF4, 0x00, 0x15, 0xFE, 0x38, 0x17, 0xD0, + 0xFF, 0xF7, 0xF0, 0xFD, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0xF6, 0xF9, 0x20, 0x46, 0x3B, 0xF6, 0x8B, 0xFD, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0x3F, 0xFA, + 0xFF, 0xF7, 0xF4, 0xFD, 0x30, 0x46, 0xF8, 0xBD, 0x20, 0x46, 0xFF, 0xF7, 0xC1, 0xFF, 0x05, 0x20, 0x00, 0xF6, 0x00, 0xF9, 0x40, 0xF0, 0x80, 0x74, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0xD8, 0xF9, 0x20, 0x46, + 0x00, 0xF6, 0x22, 0xFD, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0x21, 0xFA, 0x6A, 0x46, 0x04, 0x21, 0x20, 0x46, 0x00, 0xF6, 0xC4, 0xFB, 0x00, 0x98, 0x6A, 0x46, 0x20, 0xF4, 0x00, 0x00, 0x00, 0x90, + 0x04, 0x21, 0x20, 0x46, 0x00, 0xF6, 0x83, 0xFB, 0xD4, 0xE7, 0x00, 0x00, 0x2D, 0xE9, 0xFC, 0x41, 0x1C, 0x46, 0x16, 0x46, 0x13, 0x46, 0x0F, 0x46, 0x0A, + 0x46, 0x08, 0x9D, 0x80, 0x46, 0x01, 0x46, 0x14, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x1B, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x13, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x13, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x12, + 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x0B, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x11, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x03, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x10, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xFB, + 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x23, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xF3, 0xFA, 0xBD, 0xE8, 0xFC, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0x1C, 0x46, 0x16, 0x46, 0x13, 0x46, 0x0F, 0x46, 0x0A, + 0x46, 0x08, 0x9D, 0x80, 0x46, 0x01, 0x46, 0x22, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xE2, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x21, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xDA, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x20, + 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xD2, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x07, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xCA, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x06, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xC2, + 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x05, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xBA, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xB2, 0xFA, 0xBD, 0xE7, 0x10, 0xB5, 0x08, 0x20, 0x05, + 0xF6, 0xF4, 0xFA, 0x01, 0x22, 0x11, 0x46, 0x14, 0x20, 0x05, 0xF6, 0x39, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x13, 0x20, 0x05, 0xF6, 0x34, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x12, 0x20, 0x05, 0xF6, 0x2F, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x11, 0x20, 0x05, + 0xF6, 0x2A, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x10, 0x20, 0x05, 0xF6, 0x25, 0xFB, 0x01, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x11, 0x46, 0x23, 0x20, 0x05, 0xF6, 0x1E, 0xBB, 0x10, 0xB5, 0x14, 0x20, 0x05, 0xF6, 0x33, 0xFB, 0x13, 0x20, 0x05, 0xF6, 0x30, + 0xFB, 0x12, 0x20, 0x05, 0xF6, 0x2D, 0xFB, 0x11, 0x20, 0x05, 0xF6, 0x2A, 0xFB, 0x10, 0x20, 0x05, 0xF6, 0x27, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x23, 0x20, 0x05, 0xF6, 0x22, 0xBB, 0x10, 0xB5, 0x2C, 0x21, 0x78, 0x48, 0x4E, 0xF6, 0xB5, 0xF8, 0x77, + 0x48, 0x01, 0x21, 0x41, 0x70, 0xC1, 0x70, 0x10, 0xBD, 0x70, 0xB5, 0x75, 0x4C, 0x75, 0x4E, 0x05, 0x46, 0x8E, 0xB0, 0x00, 0x22, 0x21, 0x46, 0x30, 0x46, 0x10, 0xF0, 0x54, 0xF9, 0x01, 0x22, 0x21, 0x46, 0x30, 0x46, 0x10, 0xF0, 0x4F, 0xF9, 0x6D, + 0x48, 0x00, 0x24, 0x04, 0x70, 0x68, 0x46, 0x10, 0xF0, 0xE7, 0xF8, 0x07, 0x20, 0xAD, 0xF8, 0x02, 0x00, 0x06, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x26, 0x20, 0xAD, 0xF8, 0x2C, 0x00, 0x0F, 0x20, 0x8D, 0xF8, 0x2E, 0x00, 0x0A, + 0x94, 0xCD, 0xE9, 0x03, 0x54, 0x4F, 0xF4, 0xC8, 0x70, 0xAD, 0xF8, 0x0A, + 0x00, 0x40, 0x20, 0x05, 0x94, 0x8D, 0xF8, 0x32, 0x00, 0x01, 0x20, 0x61, 0x4C, 0x8D, 0xF8, 0x33, 0x00, 0x69, 0x46, 0x20, 0x46, 0x10, 0xF0, 0x70, 0xF8, 0x01, 0x22, 0x04, 0x21, 0x20, 0x46, 0x10, 0xF0, 0xE2, 0xF8, 0xE0, 0x69, 0x40, 0xF0, 0x04, + 0x00, 0xE0, 0x61, 0x00, 0x22, 0x04, 0x21, 0x20, 0x46, 0x10, 0xF0, 0xE1, 0xF8, 0x01, 0x21, 0x20, 0x46, 0x10, 0xF0, 0xF0, 0xF8, 0x0E, 0xB0, 0x70, 0xBD, 0x0E, 0xB5, 0x36, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x03, 0x20, 0x01, 0x90, 0x01, 0x20, 0x8D, + 0xF8, 0x08, 0x00, 0x68, 0x46, 0x05, 0xF6, 0x8C, 0xF9, 0x0E, 0xBD, 0x10, 0xB5, 0x4E, 0x21, 0x14, 0x20, 0x05, 0xF6, 0xE0, 0xF9, 0x4F, 0x21, 0x13, 0x20, 0x05, 0xF6, 0xDC, 0xF9, 0x50, 0x21, 0x12, 0x20, 0x05, 0xF6, 0xD8, 0xF9, 0x51, 0x21, 0x11, + 0x20, 0x05, 0xF6, 0xD4, 0xF9, 0x52, 0x21, 0x10, 0x20, 0x05, 0xF6, 0xD0, 0xF9, 0x53, 0x21, 0x23, 0x20, 0x05, 0xF6, 0xCC, 0xF9, 0x3A, 0x21, 0x22, 0x20, 0x05, 0xF6, 0xC8, 0xF9, 0x3B, 0x21, 0x21, 0x20, 0x05, 0xF6, 0xC4, 0xF9, 0x3C, 0x21, 0x20, + 0x20, 0x05, 0xF6, 0xC0, 0xF9, 0x3D, 0x21, 0x07, 0x20, 0x05, 0xF6, 0xBC, 0xF9, 0x3E, 0x21, 0x06, 0x20, 0x05, 0xF6, 0xB8, 0xF9, 0x3F, 0x21, 0x05, 0x20, 0x05, 0xF6, 0xB4, 0xF9, 0x40, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x20, 0x05, 0xF6, 0xAE, + 0xB9, 0x38, 0xB5, 0x00, 0x24, 0x01, 0x22, 0x23, 0x46, 0x11, 0x46, 0x10, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0xAF, 0xFE, 0x01, 0x23, 0x00, 0x22, 0x19, 0x46, 0x18, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0xE1, 0xFE, 0x38, 0xBD, 0x38, 0xB5, 0x00, 0x24, 0x01, + 0x23, 0x22, 0x46, 0x19, 0x46, 0x20, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0xD7, 0xFE, 0x21, 0x48, 0xC0, 0x78, 0x01, 0x28, 0x09, 0xD0, 0xFF, 0xF7, 0x35, 0xFF, 0x00, 0x23, 0x02, 0x22, 0x00, 0x94, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0x91, 0xFE, 0x38, + 0xBD, 0xFF, 0xF7, 0x07, 0xFF, 0x00, 0x23, 0x01, 0x22, 0x00, 0x94, 0xF4, 0xE7, 0x38, 0xB5, 0x00, 0x24, 0x01, 0x22, 0x23, 0x46, 0x11, 0x46, 0x10, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0x81, 0xFE, 0x01, 0x23, 0x00, 0x22, 0x19, 0x46, 0x18, 0x46, 0x00, + 0x94, 0xFF, 0xF7, 0xB3, 0xFE, 0x0F, 0x48, 0xC0, 0x78, 0x01, 0x28, 0x03, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0xC0, 0x07, 0x2D, 0xE7, 0x38, 0xBD, 0x1C, 0xB5, 0x0E, 0x49, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x08, 0x48, 0x32, 0x23, 0x01, 0x22, 0x0C, + 0xA1, 0x00, 0x1F, 0x1A, 0xF6, 0x8C, 0xFD, 0x00, 0x28, 0x07, 0xD1, 0x02, 0xB0, 0x00, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x0B, 0x49, 0x0B, 0x48, 0xFB, 0xF5, 0xC6, 0xBC, 0x1C, 0xBD, 0xCC, 0xF2, 0x20, 0x00, 0x40, 0x00, 0x00, 0x60, 0x00, 0x00, 0x08, + 0x08, 0x00, 0x50, 0x00, 0x40, 0xC1, 0x85, 0x20, 0x00, 0x6B, 0x65, 0x79, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0xB0, 0x32, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x2D, 0xE9, 0xFF, 0x47, 0x06, 0x46, 0xD0, + 0x48, 0xDF, 0xF8, 0x48, 0x83, 0x00, 0x25, 0x30, 0xF8, 0x16, 0x40, 0xCE, 0x48, 0x33, 0x46, 0x03, 0x22, 0x47, 0x78, 0xCD, 0x49, 0xCD, 0xE9, 0x00, 0x47, 0x40, 0x46, 0xFB, 0xF5, 0x9C, 0xFC, 0x00, 0x20, 0xCB, 0x49, 0x01, 0x22, 0xA8, 0xF1, 0x01, + 0x09, 0x16, 0xB1, 0x14, 0x2E, 0x02, 0xD3, 0x1A, 0xE0, 0x14, 0x2F, 0x18, 0xD2, 0x4B, 0x78, 0x93, 0xB1, 0x02, 0x90, 0x03, 0x90, 0x08, 0x20, 0xCD, 0xE9, 0x00, 0x02, 0x8D, 0xF8, 0x0A, + 0x40, 0x09, 0x7B, 0x02, 0xAB, 0x0A, + 0x22, 0x00, 0x20, 0x43, 0xF6, 0x25, 0xFB, 0x05, 0x00, 0x20, 0xD1, 0xBC, 0x49, 0x00, 0x22, 0x50, 0x31, 0x22, 0xE0, 0xBA, 0x49, 0x00, 0x22, 0x8C, 0x31, 0x1E, 0xE0, 0x0B, 0x79, 0xD3, 0xB1, 0x02, 0x90, 0x8D, 0xF8, 0x08, 0x40, 0x20, 0x0A, + 0x8D, 0xF8, 0x09, 0x00, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x02, 0x09, 0x7B, 0x02, 0xAB, 0x15, 0x22, 0x00, 0x20, 0x43, 0xF6, 0x0A, + 0xFB, 0x05, 0x00, 0x05, 0xD1, 0xAE, 0x49, 0x00, 0x22, 0xD0, 0x31, 0x40, 0x46, 0xFB, 0xF5, 0x5F, 0xFC, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xAC, 0x49, 0x00, 0x22, 0x48, 0x46, 0xF5, 0xE7, 0xF8, 0xB5, 0xA9, 0x4C, 0xA7, 0x4E, 0x05, + 0x46, 0xA3, 0x7C, 0x01, 0x22, 0xA8, 0x49, 0x30, 0x46, 0xFB, 0xF5, 0x4D, 0xFC, 0xA1, 0x7C, 0xA1, 0x4A, 0x49, 0xB1, 0x01, 0x29, 0x1B, 0xD0, 0x04, 0x29, 0x0F, 0xD1, 0x06, 0x2D, 0x31, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0x90, 0xE7, 0x20, + 0x78, 0x50, 0xB1, 0x15, 0x70, 0x01, 0x2D, 0x05, 0xD0, 0x01, 0x20, 0xFE, 0xF7, 0xAB, 0xFF, 0x01, 0x20, 0xA0, 0x71, 0xF8, 0xBD, 0x05, 0x20, 0x02, 0xE0, 0x00, 0x20, 0x60, 0x72, 0x03, 0x20, 0xBD, 0xE8, 0xF8, 0x40, 0xFE, 0xF7, 0x9F, 0xBF, 0x60, + 0x7D, 0x01, 0x2D, 0x05, 0xD0, 0x01, 0x28, 0x01, 0xD0, 0x02, 0x28, 0xEE, 0xD1, 0x15, 0x70, 0xF8, 0xBD, 0x01, 0x28, 0x0B, 0xD0, 0x02, 0x28, 0x01, 0xD0, 0x04, 0x28, 0xF8, 0xD1, 0x8F, 0x48, 0x1A, 0xF6, 0x1D, 0xFD, 0xBD, 0xE8, 0xF8, 0x40, 0x03, + 0x20, 0xFF, 0xF7, 0x51, 0xB9, 0x03, 0x20, 0xA0, 0x75, 0xF8, 0xBD, 0x63, 0x78, 0x2B, 0xB1, 0xA0, 0x78, 0x18, 0xB1, 0xBD, 0xE8, 0xF8, 0x40, 0x00, 0xF0, 0xF1, 0xB9, 0xA0, 0x78, 0x84, 0x49, 0x00, 0x90, 0x02, 0x22, 0x34, 0x31, 0x30, 0x46, 0xFB, + 0xF5, 0x02, 0xFC, 0xF8, 0xBD, 0x7E, 0x48, 0x10, 0xB5, 0x01, 0x78, 0x19, 0xB1, 0x00, 0x21, 0x01, 0x70, 0x3F, 0xF6, 0x72, 0xFF, 0xD9, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0xFC, 0xF7, 0x2F, 0xBB, 0x75, 0x49, 0x10, 0xB5, 0x00, 0x22, 0xE0, + 0x39, 0x74, 0x48, 0xFB, 0xF5, 0xEC, 0xFB, 0x71, 0x48, 0x08, 0x38, 0x00, 0x21, 0x81, 0x60, 0xC1, 0x60, 0x10, 0xBD, 0x7C, 0xB5, 0x6E, 0x49, 0x00, 0x22, 0xBC, 0x39, 0x6E, 0x48, 0xFB, 0xF5, 0xDF, 0xFB, 0x71, 0x48, 0x00, 0x24, 0xCD, 0xE9, 0x00, + 0x40, 0x68, 0x48, 0x4F, 0xF4, 0xFA, 0x63, 0x01, 0x22, 0x6E, 0xA1, 0x08, 0x38, 0x1A, 0xF6, 0x8F, 0xFC, 0x66, 0x4D, 0xAD, 0x1E, 0x28, 0xB9, 0x64, 0x49, 0x00, 0x22, 0x94, 0x39, 0x28, 0x46, 0xFB, 0xF5, 0xCA, 0xFB, 0x70, 0x48, 0x4F, 0xF4, 0x96, + 0x73, 0xCD, 0xE9, 0x00, 0x40, 0x5D, 0x48, 0x01, 0x22, 0x6D, 0xA1, 0x00, 0x1F, 0x1A, 0xF6, 0x7B, 0xFC, 0x00, 0x28, 0x08, 0xD1, 0x02, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x58, 0x49, 0x00, 0x22, 0x4C, 0x39, 0xFB, 0xF5, 0xB4, 0xBB, 0x7C, + 0xBD, 0x10, 0xB5, 0x07, 0x21, 0x26, 0x20, 0x00, 0xF0, 0x70, 0xFB, 0x52, 0x4C, 0x60, 0x78, 0x00, 0x28, 0x15, 0xD0, 0x00, 0x22, 0x69, 0x49, 0x51, 0x48, 0xFB, 0xF5, 0xA5, 0xFB, 0x68, 0x48, 0x40, 0x78, 0x01, 0x28, 0x04, 0xD0, 0x4E, 0x48, 0x80, + 0x7C, 0x04, 0x28, 0x03, 0xD0, 0x05, 0xE0, 0x00, 0xF0, 0x96, 0xF9, 0x02, 0xE0, 0x00, 0x20, 0xFF, 0xF7, 0xE7, 0xFE, 0x00, 0x20, 0x60, 0x70, 0x10, 0xBD, 0x2D, 0xE9, 0xFE, 0x43, 0x47, 0x49, 0x45, 0x4F, 0x04, 0x46, 0x03, 0x68, 0x01, 0x22, 0x48, + 0x31, 0x38, 0x46, 0xFB, 0xF5, 0x88, 0xFB, 0x00, 0x22, 0x07, 0x21, 0x26, 0x20, 0x00, 0xF0, 0x0C, 0xFB, 0x3B, 0x4E, 0x00, 0x25, 0x2A, 0x3E, 0xB8, 0x46, 0x15, 0xE0, 0x04, 0xEB, 0x45, 0x00, 0x2B, 0x46, 0x81, 0x88, 0xC1, 0xF3, 0x43, 0x10, 0xC0, + 0xEB, 0xC0, 0x02, 0x32, 0x44, 0x01, 0xF0, 0x1F, 0x01, 0x52, 0x5C, 0x8D, 0xE8, 0x07, 0x00, 0x37, 0x49, 0x04, 0x22, 0x80, 0x31, 0x40, 0x46, 0xFB, 0xF5, 0x6A, 0xFB, 0x6D, 0x1C, 0xED, 0xB2, 0x20, 0x68, 0xA8, 0x42, 0xE6, 0xD8, 0xA0, 0x88, 0xC0, + 0xF3, 0x43, 0x11, 0xC1, 0xEB, 0xC1, 0x01, 0x31, 0x44, 0x00, 0xF0, 0x1F, 0x00, 0x0D, 0x5C, 0xE0, 0x88, 0xC0, 0xF3, 0x43, 0x11, 0xC1, 0xEB, 0xC1, 0x01, 0x31, 0x44, 0x00, 0xF0, 0x1F, 0x00, 0x25, 0x4E, 0x0F, 0x5C, 0x70, 0x78, 0x30, 0xB1, 0x21, + 0x68, 0x01, 0x29, 0x01, 0xD1, 0xA8, 0x42, 0x01, 0xD0, 0xFF, 0xF7, 0x96, 0xFF, 0x18, 0x20, 0x11, 0xF0, 0x22, 0xFA, 0x21, 0x48, 0x80, 0x7C, 0x06, 0x28, 0x33, 0xD0, 0x20, 0x68, 0x40, 0xB1, 0x01, 0x28, 0x10, 0xD0, 0x02, 0x28, 0x2D, 0xD1, 0x4F, + 0xF4, 0xFA, 0x64, 0x07, 0x2D, 0x0F, 0xD0, 0x10, 0xE0, 0x03, 0xB0, 0x30, 0x49, 0xBD, 0xE8, 0xF0, 0x43, 0x16, 0x48, 0x00, 0x22, 0x30, 0x39, 0x40, 0x1E, 0xFB, 0xF5, 0x2D, 0xBB, 0x75, 0x70, 0x28, 0x46, 0xBD, 0xE8, 0xFE, 0x43, 0xD0, 0xE6, 0x0F, + 0x2F, 0x03, 0xD0, 0x07, 0x2F, 0x03, 0xD1, 0x0F, 0x2D, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x60, 0x10, 0x49, 0x01, 0x22, 0x80, 0x31, 0x40, 0x46, 0x73, 0x68, 0xFB, 0xF5, 0x19, 0xFB, 0x70, 0x68, 0x00, 0x28, 0x07, 0xD0, 0x03, 0xB0, 0x21, 0x46, 0xBD, + 0xE8, 0xF0, 0x43, 0x04, 0x48, 0x08, 0x38, 0x1A, 0xF6, 0xFE, 0xBB, 0xBD, 0xE8, 0xFE, 0x83, 0x00, 0x00, 0x92, 0xE1, 0x20, 0x00, 0x00, 0xF3, 0x20, 0x00, 0xE4, 0x35, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x70, 0xF2, 0x20, 0x00, 0xF0, 0x36, 0x80, + 0x08, 0x24, 0x33, 0x80, 0x08, 0xA0, 0xF2, 0x20, 0x00, 0x25, 0x86, 0x20, 0x00, 0x63, 0x6F, 0x6D, 0x62, 0x69, 0x6E, 0x65, 0x5F, 0x6B, 0x65, 0x79, 0x73, 0x5F, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x74, 0x69, 0x6D, 0x65, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x95, 0x86, 0x20, 0x00, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5F, 0x72, 0x65, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x74, 0x69, + 0x6D, 0x65, 0x72, 0x00, 0x00, 0xF4, 0x37, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x00, 0x25, 0x8D, 0xF8, 0x08, 0x50, 0x02, 0xA9, 0x40, 0xF2, 0x33, 0x20, 0x40, 0xF6, 0x60, 0xFC, 0x00, 0xF0, 0x2F, 0xF9, 0xDF, 0xF8, 0xA8, + 0xC3, 0x18, 0xB1, 0x00, 0x22, 0xE9, 0x49, 0x60, 0x46, 0x55, 0xE0, 0xE9, 0x4F, 0xDF, 0xF8, 0x98, 0xA3, 0x3B, 0x7A, 0xAA, 0xF1, 0x01, 0x0A, + 0xD8, 0x1E, 0x78, 0x28, 0x03, 0xDA, 0xE3, 0x49, 0x01, 0x22, 0x34, 0x31, 0x06, 0xE0, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x2B, 0x06, 0xD8, 0xDF, 0x49, 0x01, 0x22, 0x6C, 0x31, 0x50, 0x46, 0xFB, 0xF5, 0xA7, 0xFA, 0x37, 0xE0, 0xDE, 0x4E, 0xD6, 0xE9, + 0x01, 0x01, 0x81, 0x42, 0x01, 0xD2, 0x32, 0x68, 0x11, 0x44, 0x08, 0x1A, 0x59, 0x1E, 0x88, 0x42, 0x01, 0xD8, 0x04, 0x46, 0x00, 0xE0, 0x0C, 0x46, 0xCD, 0xE9, 0x00, 0x04, 0xD4, 0x49, 0x03, 0x22, 0xAC, 0x31, 0x60, 0x46, 0xFB, 0xF5, 0x90, 0xFA, + 0x4F, 0xF0, 0x01, 0x09, 0x4F, 0xF0, 0x78, 0x08, 0x17, 0xE0, 0xCD, 0xE9, 0x00, 0x89, 0x70, 0x68, 0xF1, 0x68, 0xC0, 0xEB, 0x00, 0x10, 0x01, 0xEB, 0xC0, 0x03, 0x39, 0x7B, 0x0E, 0x22, 0x00, 0x20, 0x64, 0x1E, 0x43, 0xF6, 0x20, 0xF9, 0x05, 0x00, + 0x0F, 0xD0, 0xD6, 0xE9, 0x00, 0x10, 0x40, 0x1C, 0xB0, 0xFB, 0xF1, 0xF2, 0x01, 0xFB, 0x12, 0x00, 0x70, 0x60, 0x1C, 0xB1, 0x00, 0xF0, 0xDA, 0xF8, 0x00, 0x28, 0xE2, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xFE, 0x8F, 0x00, 0x22, 0xC1, 0x49, 0x50, 0x46, + 0xFB, 0xF5, 0x66, 0xFA, 0xF6, 0xE7, 0xBF, 0x48, 0x10, 0xB5, 0x41, 0x78, 0xB9, 0x48, 0x01, 0x29, 0x4F, 0xF0, 0x00, 0x02, 0x20, 0xD0, 0xBA, 0x49, 0x04, 0x46, 0x78, 0x31, 0xFB, 0xF5, 0x58, 0xFA, 0xB5, 0x49, 0x00, 0x22, 0x64, 0x39, 0x20, 0x46, + 0xFB, 0xF5, 0x52, 0xFA, 0xB7, 0x49, 0x00, 0x20, 0x3C, 0x22, 0x48, 0x60, 0x88, 0x60, 0xB1, 0x49, 0xC1, 0xE9, 0x00, 0x20, 0x88, 0x60, 0xA1, 0xF5, 0xE1, 0x50, 0xC8, 0x60, 0x11, 0xF0, 0xA1, 0xFB, 0x01, 0x21, 0x02, 0x20, 0xFD, 0xF7, 0x90, 0xFF, + 0x10, 0xF0, 0xF9, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0xAA, 0x49, 0x34, 0x31, 0xFB, 0xF5, 0x38, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xA6, 0x49, 0xA2, 0x4C, 0x00, 0x22, 0xA8, 0x31, 0x20, 0x46, 0xFB, 0xF5, 0x2E, 0xFA, 0x00, 0x21, 0x02, 0x20, + 0xFD, 0xF7, 0x7A, 0xFF, 0xA2, 0x49, 0x49, 0x78, 0x29, 0xB1, 0x10, 0xF0, 0x08, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x5A, 0xBF, 0x9C, 0x49, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0xD4, 0x31, 0xFB, 0xF5, 0x19, 0xBA, 0x99, 0x48, + 0x10, 0xB5, 0x40, 0x78, 0x01, 0x24, 0x01, 0x28, 0x06, 0xD0, 0xFF, 0xF7, 0xAC, 0xFF, 0x06, 0x20, 0xFF, 0xF7, 0x5F, 0xFD, 0x20, 0x46, 0x10, 0xBD, 0x8E, 0x48, 0x00, 0x22, 0x94, 0x49, 0x40, 0x1E, 0xFB, 0xF5, 0x06, 0xFA, 0x00, 0x20, 0x10, 0xBD, + 0x8F, 0x48, 0x10, 0xB5, 0x40, 0x78, 0x18, 0xB1, 0x00, 0xF0, 0x68, 0xF8, 0x90, 0xB9, 0x08, 0xE0, 0x8D, 0x49, 0x85, 0x48, 0x00, 0x22, 0x54, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x40, 0x1E, 0xFB, 0xF5, 0xF3, 0xB9, 0x87, 0x48, 0x00, 0x1D, 0x01, 0x78, + 0x21, 0xB1, 0x81, 0x49, 0x09, 0x7A, 0xC9, 0x1E, 0x78, 0x29, 0x05, 0xDA, 0x00, 0x20, 0xFF, 0xF7, 0x38, 0xFD, 0xBD, 0xE8, 0x10, 0x40, 0xAD, 0xE7, 0x01, 0x21, 0x41, 0x70, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, 0x7E, 0x49, 0x76, 0x4F, + 0x04, 0x46, 0x01, 0x25, 0x03, 0x46, 0x2A, 0x46, 0x94, 0x31, 0x38, 0x46, 0xFB, 0xF5, 0xD4, 0xF9, 0x20, 0x46, 0x77, 0x4C, 0x24, 0x1D, 0x01, 0x28, 0x11, 0xD0, 0x02, 0x28, 0x15, 0xD0, 0x03, 0x28, 0x08, 0xD0, 0x00, 0x22, 0x75, 0x49, 0x38, 0x46, + 0xFB, 0xF5, 0xC6, 0xF9, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0xD6, 0xE9, 0x00, 0x01, 0x00, 0xF0, 0x31, 0xF8, 0xF7, 0xE7, 0x20, 0x78, 0x00, 0x28, 0xF4, 0xD0, 0xFF, 0xF7, 0xE7, 0xFE, 0xF1, 0xE7, 0x33, 0x78, 0x01, 0x2B, 0x08, 0xD0, + 0x4F, 0xF0, 0x01, 0x02, 0x83, 0xB1, 0x68, 0x49, 0x38, 0x46, 0x40, 0x39, 0xFB, 0xF5, 0xAC, 0xF9, 0xE5, 0xE7, 0x65, 0x49, 0x01, 0x22, 0xB8, 0x39, 0x38, 0x46, 0xFB, 0xF5, 0xA5, 0xF9, 0xFF, 0xF7, 0x3E, 0xFF, 0x01, 0x20, 0x20, 0x70, 0xDA, 0xE7, + 0x60, 0x49, 0x38, 0x46, 0x7C, 0x39, 0xFB, 0xF5, 0x9B, 0xF9, 0x00, 0x20, 0x20, 0x70, 0xFF, 0xF7, 0x61, 0xFF, 0xD0, 0xE7, 0x56, 0x48, 0x81, 0x68, 0x40, 0x68, 0x81, 0x42, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, + 0x54, 0x4C, 0xA0, 0xB0, 0x00, 0x22, 0x24, 0x1D, 0x1E, 0x92, 0x62, 0x78, 0x08, 0x46, 0x01, 0x2A, 0x11, 0xD0, 0x1E, 0xAB, 0x6A, 0x46, 0x4F, 0xF4, 0xF0, 0x71, 0x00, 0xF0, 0x56, 0xF8, 0x1E, 0x9B, 0x78, 0x2B, 0x16, 0xD0, 0x4C, 0x49, 0x44, 0x48, + 0x01, 0x22, 0x40, 0x39, 0x40, 0x1E, 0xFB, 0xF5, 0x73, 0xF9, 0x20, 0xB0, 0x10, 0xBD, 0xFF, 0xF7, 0xD9, 0xFF, 0x08, 0xB9, 0x20, 0x78, 0x28, 0xB9, 0x00, 0x20, 0xFF, 0xF7, 0xBA, 0xFC, 0xFF, 0xF7, 0x31, 0xFF, 0xF2, 0xE7, 0xFF, 0xF7, 0x93, 0xFE, + 0xEF, 0xE7, 0x68, 0x46, 0x00, 0xF0, 0x0A, + 0xF8, 0x20, 0x78, 0x01, 0x28, 0xF6, 0xD0, 0x3D, 0x49, 0x00, 0x22, 0x80, 0x39, 0x35, 0x48, 0xFB, 0xF5, 0x57, 0xF9, 0xE2, 0xE7, 0x70, 0xB5, 0x35, 0x4C, 0x05, 0x46, 0xA2, 0x68, 0x20, 0x68, 0x52, 0x1C, 0xB2, 0xFB, 0xF0, 0xF1, 0x00, 0xFB, 0x11, + 0x20, 0x61, 0x68, 0x88, 0x42, 0x0D, 0xD1, 0x2D, 0x49, 0x00, 0x22, 0x3C, 0x39, 0x2B, 0x48, 0xFB, 0xF5, 0x43, 0xF9, 0xD4, 0xE9, 0x00, 0x02, 0x52, 0x1C, 0xB2, 0xFB, 0xF0, 0xF1, 0x00, 0xFB, 0x11, 0x20, 0x60, 0x60, 0xD4, 0xE9, 0x02, 0x01, 0xC0, + 0xEB, 0x00, 0x10, 0x01, 0xEB, 0xC0, 0x00, 0x78, 0x22, 0x29, 0x46, 0x4D, 0xF6, 0x4F, 0xFB, 0xA0, 0x68, 0x21, 0x68, 0x40, 0x1C, 0xB0, 0xFB, 0xF1, 0xF2, 0x01, 0xFB, 0x12, 0x00, 0xA0, 0x60, 0x01, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xFC, 0x47, 0x00, + 0x26, 0x01, 0xAF, 0xCD, 0xE9, 0x00, 0x76, 0x9A, 0x46, 0x14, 0x46, 0x81, 0x46, 0x39, 0x23, 0x92, 0x1C, 0xF0, 0x21, 0x11, 0xF0, 0x3C, 0xFA, 0x4F, 0xF0, 0x01, 0x08, 0x19, 0x4D, 0x84, 0xF8, 0x00, 0x80, 0x84, 0xF8, 0x3B, 0x60, 0x28, 0x78, 0xC0, + 0x07, 0x1B, 0xD0, 0xC8, 0x20, 0x60, 0x70, 0x39, 0x23, 0x04, 0xF1, 0x3E, 0x02, 0xF0, 0x21, 0x09, 0xF1, 0xF0, 0x00, 0x00, 0x97, 0x11, 0xF0, 0x27, 0xFA, 0x84, 0xF8, 0x3C, 0x80, 0x84, 0xF8, 0x77, 0x60, 0x28, 0x78, 0xC1, 0x07, 0x0B, 0xD0, 0xF8, + 0x21, 0x78, 0x22, 0x84, 0xF8, 0x3D, 0x10, 0x40, 0x1C, 0xCA, 0xF8, 0x00, 0x20, 0x28, 0x70, 0xBD, 0xE8, 0xFC, 0x87, 0x08, 0x20, 0xE2, 0xE7, 0x38, 0x21, 0xF2, 0xE7, 0x02, 0x30, 0x10, 0x21, 0x1C, 0x39, 0x80, 0x08, 0x70, 0xF2, 0x20, 0x00, 0x1C, + 0x13, 0x21, 0x00, 0x24, 0x3A, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0xF0, 0xF6, 0x20, 0x00, 0xC0, 0x3B, 0x80, 0x08, 0x38, 0x3D, 0x80, 0x08, 0x2D, 0xE9, 0xFC, 0x41, 0x00, 0xEB, 0x40, 0x01, 0x5E, 0x48, 0x00, 0x24, 0x00, 0xEB, 0xC1, 0x05, 0x68, + 0x69, 0x00, 0x28, 0x2C, 0xD0, 0x01, 0x26, 0x69, 0x69, 0x06, 0xFA, 0x04, 0xF3, 0x19, 0x42, 0x22, 0xD0, 0x05, 0xEB, 0x44, 0x00, 0x81, 0x78, 0xF1, 0xB1, 0x57, 0x4A, 0x55, 0x4F, 0x02, 0xEB, 0xC4, 0x02, 0x08, 0x3F, 0x52, 0x78, 0x3F, 0x68, 0xB7, + 0xFB, 0xF2, 0xFC, 0x02, 0xFB, 0x1C, 0x72, 0xC7, 0x78, 0xBA, 0x42, 0x10, 0xD1, 0x49, 0x1E, 0x11, 0xF0, 0xFF, 0x01, 0x81, 0x70, 0x0B, 0xD1, 0x68, 0x69, 0x01, 0x22, 0x98, 0x43, 0x68, 0x61, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x60, 0x00, 0x23, 0x68, + 0x78, 0x19, 0x46, 0x04, 0xF6, 0x68, 0xFD, 0x64, 0x1C, 0xE4, 0xB2, 0x08, 0x2C, 0xD3, 0xD3, 0xBD, 0xE8, 0xFC, 0x81, 0x02, 0x46, 0x00, 0x20, 0x01, 0x23, 0x03, 0xFA, 0x00, 0xF1, 0x11, 0x42, 0x03, 0xD1, 0x40, 0x1C, 0x08, 0x28, 0xF8, 0xD3, 0x00, + 0x20, 0x70, 0x47, 0x1C, 0xB5, 0x00, 0x24, 0x01, 0x20, 0xCD, 0xE9, 0x00, 0x04, 0x02, 0x46, 0x23, 0x46, 0x21, 0x46, 0x26, 0x20, 0x04, 0xF6, 0x4B, 0xFD, 0x3A, 0x48, 0x32, 0x23, 0xCD, 0xE9, 0x00, 0x40, 0x36, 0x48, 0x01, 0x22, 0x38, 0xA1, 0x00, + 0x1F, 0x1A, 0xF6, 0x3E, 0xF9, 0x03, 0x00, 0x07, 0xD1, 0x02, 0xB0, 0x01, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x37, 0x49, 0x37, 0x48, 0xFB, 0xF5, 0x78, 0xB8, 0x1C, 0xBD, 0xF8, 0xB5, 0x00, 0x24, 0x00, 0x94, 0x09, 0xB1, 0x08, 0x29, 0x01, 0xD3, 0x01, + 0x20, 0xF8, 0xBD, 0x03, 0x0A, + 0x01, 0xD0, 0x02, 0x20, 0xF8, 0xBD, 0x03, 0x0A, + 0x03, 0xEB, 0x43, 0x05, 0x26, 0x4B, 0x01, 0x26, 0x03, 0xEB, 0xC5, 0x03, 0x8E, 0x40, 0x5D, 0x69, 0x35, 0x43, 0x5D, 0x61, 0x58, 0x70, 0x03, 0xEB, 0x41, 0x00, 0x6A, 0xB1, 0x82, 0x70, 0x20, 0x4A, 0x02, 0xEB, 0xC1, 0x01, 0x1E, 0x4A, 0x49, 0x78, + 0x08, 0x3A, 0x12, 0x68, 0xB2, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, 0x13, 0x21, 0xC1, 0x70, 0x01, 0xE0, 0x84, 0x70, 0xC4, 0x70, 0x18, 0x48, 0x69, 0x46, 0x00, 0x1F, 0x1A, 0xF6, 0x7A, 0xF9, 0x00, 0x98, 0x20, 0xB9, 0x14, 0x48, 0x32, 0x21, 0x00, 0x1F, + 0x1A, 0xF6, 0x30, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x7C, 0xB5, 0x09, 0xB1, 0x08, 0x29, 0x01, 0xD3, 0x01, 0x20, 0x7C, 0xBD, 0x02, 0x0A, + 0x01, 0xD0, 0x02, 0x20, 0x7C, 0xBD, 0x00, 0x0A, + 0x00, 0xEB, 0x40, 0x02, 0x0A, + 0x48, 0x00, 0xEB, 0xC2, 0x04, 0x01, 0x20, 0x62, 0x69, 0x00, 0xFA, 0x01, 0xF5, 0x2A, 0x42, 0x0A, + 0xD0, 0x00, 0x21, 0xCD, 0xE9, 0x00, 0x01, 0x60, 0x78, 0x0B, 0x46, 0x01, 0x22, 0x04, 0xF6, 0xDF, 0xFC, 0x60, 0x69, 0xA8, 0x43, 0x60, 0x61, 0x00, 0x20, 0x7C, 0xBD, 0x34, 0x13, 0x21, 0x00, 0xEC, 0xE1, 0x20, 0x00, 0x95, 0x87, 0x20, 0x00, 0x6C, + 0x65, 0x64, 0x5F, 0x63, 0x74, 0x72, 0x6C, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x68, 0x3D, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x1C, 0xB5, 0x01, 0x23, 0x00, 0x24, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x18, 0x46, 0x01, 0x94, 0x04, + 0xF6, 0xBE, 0xFC, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x02, 0x20, 0x01, 0x94, 0x04, 0xF6, 0xB6, 0xFC, 0x17, 0x21, 0x01, 0x20, 0x04, 0xF6, 0x7E, 0xFC, 0xBD, 0xE8, 0x1C, 0x40, 0x18, 0x21, 0x02, 0x20, 0x04, 0xF6, 0x78, 0xBC, 0x30, + 0xB5, 0x4F, 0xF0, 0x40, 0x25, 0x8B, 0xB0, 0x28, 0x46, 0xFC, 0xF7, 0xC0, 0xFA, 0x01, 0x22, 0x7A, 0x49, 0x7B, 0x48, 0x0F, 0xF0, 0x90, 0xFB, 0x68, 0x46, 0xFC, 0xF7, 0xBD, 0xFA, 0x01, 0x24, 0x46, 0xF2, 0xA8, 0x10, 0xAD, 0xF8, 0x1C, 0x00, 0x8D, + 0xF8, 0x05, 0x40, 0xAD, 0xF8, 0x12, 0x40, 0x69, 0x46, 0x28, 0x46, 0xFC, 0xF7, 0x7A, 0xFA, 0x01, 0x22, 0x04, 0x21, 0x28, 0x46, 0xFC, 0xF7, 0xC1, 0xFA, 0x01, 0x22, 0x04, 0x21, 0x28, 0x46, 0xFC, 0xF7, 0x3C, 0xFB, 0x35, 0x20, 0x8D, 0xF8, 0x20, + 0x00, 0x03, 0x20, 0x09, 0x90, 0x8D, 0xF8, 0x28, 0x40, 0x08, 0xA8, 0x04, 0xF6, 0xEE, 0xFB, 0x0B, 0xB0, 0x30, 0xBD, 0x67, 0x48, 0x00, 0x78, 0x70, 0x47, 0x30, 0xB5, 0x87, 0xB0, 0x5A, 0x21, 0x01, 0x20, 0x04, 0xF6, 0x3D, 0xFC, 0x5A, 0x21, 0x02, + 0x20, 0x04, 0xF6, 0x39, 0xFC, 0x01, 0x23, 0x00, 0x24, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x18, 0x46, 0x01, 0x94, 0x04, 0xF6, 0x64, 0xFC, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x02, 0x20, 0x01, 0x94, 0x04, 0xF6, 0x5C, 0xFC, 0x01, + 0x22, 0x4F, 0xF0, 0x04, 0x51, 0x58, 0x48, 0x0F, 0xF0, 0x46, 0xFB, 0x01, 0x20, 0xFC, 0xF7, 0x02, 0xFA, 0x05, 0x46, 0x02, 0x20, 0xFC, 0xF7, 0xFE, 0xF9, 0x05, 0x43, 0x8D, 0xF8, 0x0C, 0x40, 0x02, 0x95, 0x8D, 0xF8, 0x0D, 0x40, 0x02, 0xA8, 0xFC, + 0xF7, 0x74, 0xF9, 0x01, 0x20, 0xFC, 0xF7, 0xF2, 0xF9, 0x00, 0xF0, 0x8B, 0xF8, 0x4B, 0x4C, 0x60, 0x70, 0x02, 0x20, 0xFC, 0xF7, 0xEB, 0xF9, 0x00, 0xF0, 0x84, 0xF8, 0xA0, 0x70, 0x07, 0xB0, 0x30, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xBD, 0xFF, 0x00, + 0x21, 0x01, 0x20, 0x04, 0xF6, 0x88, 0xFD, 0x00, 0x21, 0x02, 0x20, 0x04, 0xF6, 0x84, 0xFD, 0x40, 0x48, 0x4F, 0xF0, 0x00, 0x02, 0x40, 0x78, 0x08, 0xB1, 0x01, 0x21, 0x00, 0xE0, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0x04, 0xF6, 0xB0, + 0xBC, 0x10, 0xB5, 0x17, 0x21, 0x01, 0x20, 0x04, 0xF6, 0xE6, 0xFB, 0x18, 0x21, 0x02, 0x20, 0x04, 0xF6, 0xE2, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0xF6, 0xEF, 0xBC, 0x10, 0xB5, 0x35, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFA, 0xF5, 0xF6, 0xFE, 0xAF, + 0xF2, 0xDF, 0x00, 0xFB, 0xF5, 0x19, 0xFD, 0x20, 0xB9, 0x00, 0x22, 0x33, 0x49, 0x34, 0x48, 0xFA, 0xF5, 0x43, 0xFF, 0xAF, 0xF2, 0x6D, 0x00, 0x32, 0x49, 0x08, 0x60, 0xAF, 0xF2, 0x45, 0x00, 0x31, 0x49, 0x08, 0x60, 0xFB, 0xF7, 0x6C, 0xFF, 0x02, + 0x20, 0xFB, 0xF5, 0x36, 0xFE, 0x00, 0x22, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x04, 0xF6, 0x7F, 0xBC, 0x10, 0xB5, 0xFF, 0xF7, 0x23, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x3B, 0xE7, 0x70, 0xB5, 0x4F, 0xF0, 0x40, 0x24, 0x02, 0x21, 0x20, + 0x46, 0xFC, 0xF7, 0x63, 0xFA, 0x1B, 0x4D, 0x4F, 0xF0, 0x04, 0x56, 0x01, 0x28, 0x1C, 0xD1, 0x22, 0xA1, 0x30, 0x46, 0xFA, 0xF5, 0xC2, 0xFE, 0x24, 0xA1, 0x30, 0x46, 0xFA, 0xF5, 0xBE, 0xFE, 0x01, 0x22, 0x02, 0x21, 0x20, 0x46, 0xFC, 0xF7, 0x79, + 0xFA, 0x27, 0x48, 0x81, 0x68, 0xC1, 0xF3, 0x00, 0x41, 0xE9, 0x80, 0x80, 0x68, 0xA8, 0x80, 0x60, 0x6A, 0x40, 0xF0, 0x02, 0x00, 0x60, 0x62, 0x00, 0x22, 0x02, 0x21, 0x20, 0x46, 0xFC, 0xF7, 0x69, 0xFA, 0xB5, 0xF9, 0x04, 0x30, 0xEA, 0x88, 0x30, + 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x1D, 0xA1, 0xFA, 0xF5, 0xA0, 0xBE, 0x23, 0x4A, 0x01, 0x46, 0x00, 0x20, 0x12, 0x6D, 0x0A, + 0x42, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x10, 0x00, 0x00, 0x60, 0x00, 0x00, 0x04, 0x08, 0x5C, 0x13, 0x21, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x71, 0x64, 0x65, 0x63, 0x5F, 0x64, 0x6C, 0x70, 0x73, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x00, 0x04, + 0x3F, 0x80, 0x08, 0x00, 0x04, 0x10, 0x21, 0xB4, 0xE7, 0x20, 0x00, 0xB0, 0xE7, 0x20, 0x00, 0x51, 0x64, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x5F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x51, 0x44, 0x45, 0x43, 0x5F, 0x46, 0x4C, 0x41, 0x47, + 0x5F, 0x4E, 0x45, 0x57, 0x5F, 0x43, 0x54, 0x5F, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5F, 0x59, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x40, 0x51, 0x44, 0x45, 0x43, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x25, 0x64, + 0x2C, 0x20, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x70, 0xB5, 0x02, 0x24, 0x05, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x40, 0xF6, 0x2C, 0xFF, 0x00, + 0x28, 0xF9, 0xD1, 0xFB, 0x48, 0x01, 0x78, 0xC8, 0x07, 0xF5, 0xD0, 0x11, 0xF0, 0x0C, 0x0F, 0xF2, 0xD0, 0x11, 0xF0, 0x30, 0x0F, 0xEF, 0xD1, 0x88, 0x09, 0xED, 0xD1, 0x28, 0x46, 0x14, 0xF6, 0xD4, 0xFC, 0x00, 0x28, 0xE8, 0xD0, 0x00, 0x24, 0xE6, + 0xE7, 0x38, 0xB5, 0x04, 0x00, 0x07, 0xD1, 0xF0, 0x49, 0x08, 0x78, 0x20, 0xF0, 0x0E, 0x00, 0x08, 0x70, 0xFC, 0x20, 0x40, 0xF6, 0xB5, 0xF8, 0xED, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0xAD, 0xF8, 0x00, 0x40, 0x69, 0x46, 0xA5, 0x20, 0x90, + 0x47, 0x38, 0xBD, 0x30, 0xB5, 0x8B, 0xB0, 0x4F, 0xF0, 0x00, 0x01, 0xE7, 0x4D, 0x04, 0x00, 0x06, 0x91, 0x07, 0x91, 0x08, 0x91, 0x09, 0x91, 0x02, 0xD0, 0x20, 0x78, 0x01, 0x28, 0x08, 0xD0, 0x01, 0x23, 0x01, 0x22, 0xE2, 0x49, 0x28, 0x46, 0xFA, + 0xF5, 0x65, 0xFE, 0x00, 0x20, 0x0B, 0xB0, 0x30, 0xBD, 0xA0, 0x78, 0x00, 0x07, 0x18, 0xD5, 0x6A, 0x46, 0x14, 0x21, 0x20, 0x46, 0x43, 0xF6, 0xDD, 0xFA, 0x80, 0xB1, 0x10, 0x22, 0x06, 0xA9, 0x68, 0x46, 0x4D, 0xF6, 0x27, 0xF8, 0x40, 0xB1, 0xD7, + 0x49, 0x63, 0x78, 0x01, 0x22, 0x30, 0x39, 0x28, 0x46, 0xFA, 0xF5, 0x4C, 0xFE, 0x01, 0x20, 0xE5, 0xE7, 0x05, 0x23, 0xDD, 0xE7, 0x04, 0x23, 0xDB, 0xE7, 0x02, 0x23, 0xD9, 0xE7, 0x0A, + 0x46, 0x00, 0xEB, 0x40, 0x01, 0xCF, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x00, 0xEB, 0x01, 0x10, 0x01, 0x78, 0x29, 0xB1, 0x81, 0x79, 0xC0, 0x1D, 0x14, 0xF6, 0x34, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0xF0, 0xB5, 0x85, 0xB0, 0x0C, + 0x46, 0x06, 0x00, 0x05, 0xD0, 0x15, 0xF6, 0x75, 0xF9, 0x78, 0xB3, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0x27, 0x44, 0xB3, 0x0F, 0xF0, 0xFE, 0xF8, 0x20, 0x70, 0x01, 0x0A, + 0x61, 0x70, 0x01, 0x0C, 0xA1, 0x70, 0x00, 0x0E, 0x65, 0x1C, 0xE0, 0x70, 0x0F, 0xF0, 0xF4, 0xF8, 0xE8, 0x70, 0x00, 0x0A, + 0x28, 0x71, 0x40, 0xF0, 0xC0, 0x00, 0x60, 0x71, 0xB9, 0xA0, 0x06, 0x22, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x01, 0x10, 0xB8, 0xA0, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x03, 0x10, 0x01, 0xA9, 0x20, 0x46, 0x4C, 0xF6, 0xD7, 0xFF, 0x48, 0xB1, + 0x06, 0x22, 0x03, 0xA9, 0x20, 0x46, 0x4C, 0xF6, 0xD1, 0xFF, 0x18, 0xB1, 0x04, 0xE0, 0x03, 0x20, 0xD0, 0xE7, 0x0F, 0xE0, 0x66, 0x20, 0x20, 0x70, 0x21, 0x46, 0xAF, 0x48, 0xFA, 0xF5, 0xB0, 0xFF, 0xA7, 0x49, 0x03, 0x46, 0x02, 0x22, 0x38, 0x31, + 0xA4, 0x48, 0x00, 0x96, 0xFA, 0xF5, 0xEB, 0xFD, 0x38, 0x46, 0xBF, 0xE7, 0x07, 0x20, 0xBD, 0xE7, 0x70, 0xB5, 0x0D, 0x46, 0x40, 0xF6, 0x2E, 0xFD, 0x04, 0x00, 0x2A, 0xD0, 0xA5, 0x48, 0x9E, 0x49, 0x01, 0x22, 0x03, 0x78, 0x9B, 0x48, 0x74, 0x31, + 0x40, 0x1C, 0xFA, 0xF5, 0xD8, 0xFD, 0x97, 0x49, 0x01, 0x22, 0x08, 0x78, 0xB2, 0xEB, 0x90, 0x1F, 0x0A, + 0xD1, 0x62, 0x78, 0x03, 0x2A, 0x07, 0xD1, 0xA2, 0x78, 0x01, 0x2A, 0x04, 0xD1, 0x22, 0x8A, 0x12, 0xB9, 0x20, 0xF0, 0xC0, 0x00, 0x08, 0x70, 0xE0, 0x78, 0x2A, 0x46, 0x00, 0x21, 0x45, 0xF6, 0xE0, 0xFB, 0x00, 0x20, 0x3F, 0xF6, 0xF1, 0xFF, 0xE0, + 0x6A, 0x08, 0xB1, 0x18, 0xF6, 0xC7, 0xFF, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x40, 0xF6, 0xF0, 0xBC, 0x89, 0x49, 0xBD, 0xE8, 0x70, 0x40, 0x86, 0x48, 0x00, 0x22, 0xA4, 0x31, 0x80, 0x1E, 0xFA, 0xF5, 0xAD, 0xBD, 0x43, 0x88, 0x33, 0xB1, 0x83, + 0x49, 0x82, 0x48, 0x01, 0x22, 0xD4, 0x31, 0x80, 0x1E, 0xFA, 0xF5, 0xA4, 0xBD, 0x81, 0x88, 0x00, 0x88, 0xB9, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x41, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xB4, 0xFF, 0x20, 0x88, 0xBD, 0xE8, 0x10, 0x40, 0x14, 0xF6, 0x6F, + 0xBC, 0x10, 0xB5, 0x8A, 0xB0, 0x0C, 0x46, 0x00, 0x21, 0x21, 0x70, 0x09, 0xAA, 0x07, 0xA9, 0x40, 0xF6, 0x55, 0xFE, 0xB8, 0xB1, 0x9D, 0xF8, 0x24, 0x10, 0x07, 0xA8, 0x43, 0xF6, 0x1F, 0xF9, 0x88, 0xB1, 0x6A, 0x46, 0x11, 0x21, 0x43, 0xF6, 0x05, + 0xFA, 0x60, 0xB1, 0x9D, 0xF8, 0x1B, 0x30, 0x01, 0x22, 0x75, 0x49, 0x6B, 0x48, 0xFA, 0xF5, 0x7A, 0xFD, 0x9D, 0xF8, 0x1B, 0x00, 0x20, 0x70, 0x00, 0x20, 0x0A, + 0xB0, 0x10, 0xBD, 0x03, 0x20, 0xFB, 0xE7, 0x70, 0x48, 0x00, 0x88, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, 0x0F, 0x46, 0x05, 0x00, 0x08, 0xD0, 0x62, 0x4B, 0x28, 0x78, 0x9B, 0x1E, 0x01, 0x28, 0x06, 0xD0, 0x68, 0x49, 0x00, 0x22, 0x48, 0x31, 0x0B, + 0xE0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x67, 0x48, 0x69, 0x78, 0x00, 0x78, 0x40, 0x1E, 0x81, 0x42, 0x06, 0xDD, 0x62, 0x49, 0x00, 0x22, 0x20, 0x31, 0x18, 0x46, 0xFA, 0xF5, 0x52, 0xFD, 0xEF, 0xE7, 0xDF, 0xF8, 0x7C, 0x81, 0x38, 0x46, 0xB8, + 0xF8, 0x00, 0x10, 0x8E, 0x08, 0x4D, 0xF6, 0x28, 0xF8, 0x00, 0x24, 0xDF, 0xF8, 0x74, 0x91, 0xDF, 0xF8, 0x74, 0xA1, 0x11, 0xE0, 0x68, 0x78, 0x00, 0x90, 0xB9, 0xF8, 0x00, 0x10, 0xBA, 0xF8, 0x00, 0x00, 0x04, 0x23, 0x08, 0x44, 0x00, 0xEB, 0x84, + 0x00, 0x81, 0xB2, 0x07, 0xEB, 0x84, 0x00, 0xB8, 0xF8, 0x00, 0x20, 0x44, 0xF6, 0x17, 0xF8, 0x64, 0x1C, 0xB4, 0x42, 0xEB, 0xDB, 0x01, 0x20, 0xCC, 0xE7, 0x30, 0xB5, 0xA7, 0xB0, 0x04, 0x00, 0x07, 0xD0, 0x04, 0xF1, 0x08, 0x00, 0x61, 0x78, 0x05, + 0x46, 0x44, 0xF6, 0xDC, 0xF8, 0x18, 0xB1, 0x14, 0xE0, 0x00, 0x20, 0x27, 0xB0, 0x30, 0xBD, 0xE0, 0x7B, 0xC1, 0x07, 0x0E, 0xD0, 0x01, 0x21, 0x21, 0x70, 0x62, 0x88, 0x83, 0x07, 0x42, 0xF0, 0x01, 0x02, 0x62, 0x80, 0x02, 0xD5, 0x42, 0xF0, 0x80, + 0x02, 0x62, 0x80, 0x40, 0x07, 0x04, 0xD5, 0x21, 0x71, 0x02, 0xE0, 0x20, 0x78, 0x01, 0x28, 0x5D, 0xD1, 0x61, 0x78, 0x0A, + 0xA8, 0x44, 0xF6, 0x00, 0xF9, 0x30, 0xB9, 0x9D, 0xF8, 0x28, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x02, 0x00, 0x60, 0x80, 0x61, 0x78, 0x12, 0xA8, 0x44, 0xF6, 0x3D, 0xF9, 0x30, 0xB9, 0x9D, 0xF8, 0x48, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, + 0xF0, 0x04, 0x00, 0x60, 0x80, 0x61, 0x78, 0x04, 0xA8, 0x44, 0xF6, 0x9F, 0xF9, 0x70, 0xB9, 0x9D, 0xF8, 0x27, 0x00, 0x58, 0xB1, 0x08, 0x98, 0x20, 0x61, 0xBD, 0xF8, 0x24, 0x00, 0xA0, 0x82, 0x9D, 0xF8, 0x26, 0x00, 0xA0, 0x75, 0x60, 0x88, 0x40, + 0xF0, 0x08, 0x00, 0x60, 0x80, 0x61, 0x78, 0x1A, 0xA8, 0x44, 0xF6, 0x54, 0xFA, 0x30, 0xB9, 0x9D, 0xF8, 0x7D, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x10, 0x00, 0x60, 0x80, 0x61, 0x78, 0x20, 0xA8, 0x44, 0xF6, 0xB5, 0xFA, 0x30, 0xB9, 0x9D, + 0xF8, 0x95, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x20, 0x00, 0x60, 0x80, 0x60, 0x78, 0x44, 0xF6, 0x1F, 0xFB, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x40, 0x00, 0x60, 0x80, 0x29, 0x46, 0x12, 0x48, 0xFA, 0xF5, 0x76, 0xFE, 0x22, 0x79, 0x61, + 0x88, 0xA3, 0x7B, 0xCD, 0xE9, 0x02, 0x12, 0xCD, 0xE9, 0x00, 0x03, 0x0F, 0x49, 0x63, 0x78, 0x05, 0x22, 0x7C, 0x31, 0x04, 0x48, 0xFA, 0xF5, 0xAB, 0xFC, 0x01, 0x20, 0x88, 0xE7, 0x38, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0x02, 0x35, 0x10, + 0x21, 0x60, 0x3F, 0x80, 0x08, 0x64, 0x2E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x30, 0x21, 0x60, 0x2E, 0x20, 0x00, 0x68, 0x40, 0x80, 0x08, 0xEE, 0x2E, 0x20, + 0x00, 0xBC, 0x2E, 0x20, 0x00, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x2D, 0xE9, 0xFE, 0x43, 0x88, 0x46, 0x89, 0x4D, 0x00, 0x21, 0x11, 0x70, 0x29, 0x88, 0x88, 0x4E, 0x17, 0x46, 0x88, 0x42, 0x02, 0xD0, 0x00, 0x22, 0x86, 0x49, 0x49, + 0xE0, 0xD8, 0xF8, 0x00, 0x10, 0x01, 0x91, 0xD8, 0xF8, 0x04, 0x00, 0x02, 0x90, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x43, 0xF6, 0x08, 0xF8, 0x04, 0x00, 0x06, 0xD1, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x43, 0xF6, 0x61, 0xFB, 0x04, 0x00, 0x08, 0xD0, 0x01, 0x20, 0x7B, 0x49, 0x38, 0x70, 0x00, 0x22, 0x34, 0x31, 0x30, 0x46, 0xFA, 0xF5, 0x5F, 0xFC, 0x39, 0xE0, 0x9D, 0xF8, 0x0B, 0x00, 0x00, 0x27, 0x40, 0x07, 0x00, 0xD5, 0x01, + 0x27, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x43, 0xF6, 0x83, 0xF8, 0x04, 0x00, 0x0D, 0xD1, 0x43, 0xF6, 0xEF, 0xFA, 0x50, 0xB3, 0x40, 0x78, 0x3E, 0xF6, 0xD1, 0xFF, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x43, 0xF6, 0x75, 0xF8, 0x04, 0x00, 0x1F, 0xD0, 0x60, 0x78, 0x00, 0x90, 0x69, 0x48, 0x69, 0x49, 0x2A, 0x88, 0x00, 0x88, 0x09, 0x88, 0xD3, 0xB2, 0x08, 0x44, 0x81, 0xB2, 0x40, 0x46, 0x43, 0xF6, 0xFA, 0xFE, 0x40, + 0xB1, 0x62, 0x49, 0x00, 0x22, 0x64, 0x31, 0x30, 0x46, 0xFA, 0xF5, 0x2E, 0xFC, 0x00, 0x20, 0xBD, 0xE8, 0xFE, 0x83, 0x61, 0x78, 0x01, 0x20, 0x43, 0xF6, 0x05, 0xFE, 0x20, 0x46, 0xFF, 0xF7, 0xF7, 0xFE, 0x20, 0x46, 0xF4, 0xE7, 0x59, 0x49, 0x00, + 0x22, 0xA4, 0x31, 0xEC, 0xE7, 0x00, 0xB5, 0x91, 0xB0, 0x4F, 0xF4, 0xE8, 0x71, 0xAD, 0xF8, 0x00, 0x10, 0xAD, 0xF8, 0x04, 0x00, 0x01, 0x21, 0x68, 0x46, 0x14, 0xF6, 0xDC, 0xF8, 0x11, 0xB0, 0x00, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x01, 0x46, 0x51, + 0x48, 0x40, 0xF6, 0xE7, 0xFB, 0x68, 0xB1, 0x50, 0x49, 0x04, 0xEB, 0x44, 0x00, 0x09, 0x68, 0x01, 0xEB, 0x00, 0x10, 0x00, 0x8A, 0xFF, 0xF7, 0xE2, 0xFF, 0x08, 0xB1, 0x00, 0x20, 0x10, 0xBD, 0x07, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0x7F, + 0xB5, 0x49, 0x4D, 0x04, 0x46, 0x28, 0x68, 0x00, 0x28, 0x19, 0xD0, 0x60, 0x88, 0x40, 0xF6, 0x3B, 0xFB, 0x00, 0x28, 0x14, 0xD0, 0xC0, 0x78, 0x8D, 0xF8, 0x00, 0x00, 0x20, 0x88, 0xAD, 0xF8, 0x02, 0x00, 0x20, 0x79, 0x8D, 0xF8, 0x04, 0x00, 0xE0, + 0x88, 0xAD, 0xF8, 0x06, 0x00, 0x20, 0x89, 0xAD, 0xF8, 0x08, 0x00, 0xCD, 0xF8, 0x0C, 0xD0, 0x2A, 0x68, 0x03, 0xA9, 0x1B, 0x20, 0x90, 0x47, 0x7F, 0xBD, 0x10, 0xB5, 0x41, 0x88, 0x01, 0x24, 0xA1, 0xF5, 0x80, 0x71, 0xD1, 0x39, 0x02, 0xD0, 0x00, + 0x24, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x1D, 0xFF, 0xF7, 0xD2, 0xFF, 0xF9, 0xE7, 0x70, 0xB5, 0x0C, 0x46, 0x05, 0x46, 0x01, 0x46, 0x2E, 0x48, 0x86, 0xB0, 0x17, 0x30, 0x40, 0xF6, 0x9E, 0xFB, 0x90, 0xB3, 0x61, 0x1E, 0x4F, 0xF6, 0xFF, 0x72, 0x2A, + 0x4B, 0x05, 0xEB, 0x45, 0x00, 0x91, 0x42, 0x0E, 0xD2, 0x19, 0x68, 0x01, 0xEB, 0x00, 0x11, 0x8A, 0x8A, 0x02, 0xEB, 0x82, 0x02, 0x96, 0x08, 0xCA, 0x8A, 0x52, 0x1C, 0x56, 0x43, 0x04, 0xEB, 0x84, 0x02, 0xB6, 0xEB, 0x42, 0x0F, 0x1C, 0xDD, 0x19, + 0x68, 0x01, 0xEB, 0x00, 0x10, 0x81, 0x8A, 0xC0, 0x8A, 0x01, 0xEB, 0x81, 0x02, 0x92, 0x08, 0x43, 0x1C, 0x5A, 0x43, 0x04, 0xEB, 0x84, 0x03, 0x5B, 0x00, 0xCD, 0xE9, 0x00, 0x41, 0xCD, 0xE9, 0x02, 0x03, 0x14, 0x49, 0x04, 0x92, 0x2B, 0x46, 0x06, + 0x22, 0xC4, 0x31, 0x10, 0x48, 0xFA, 0xF5, 0x90, 0xFB, 0x03, 0x20, 0x06, 0xB0, 0x70, 0xBD, 0x15, 0xE0, 0x08, 0x8A, 0x8D, 0xF8, 0x14, 0x00, 0x00, 0x0A, + 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x20, 0x0A, + 0x8D, 0xF8, 0x17, 0x00, 0x05, 0xAA, 0x04, 0x21, 0x40, 0xF6, 0x7C, 0x40, 0x14, 0xF6, 0xC2, 0xF8, 0x08, 0xB1, 0x00, 0x20, 0xE8, 0xE7, 0x07, 0x20, 0xE6, 0xE7, 0x04, 0x20, 0xE4, 0xE7, 0x00, 0x00, 0xEE, 0x2E, 0x20, 0x00, 0x00, 0x35, 0x10, 0x21, + 0x40, 0x41, 0x80, 0x08, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x2C, 0xE2, 0x20, 0x00, 0x64, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0x70, 0xB5, 0x06, 0x46, 0x0D, 0x46, 0x00, 0x24, 0x07, 0x20, 0x10, 0xF0, 0x29, 0xFC, 0x00, 0x28, + 0x0A, + 0xD0, 0x29, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x09, 0xF8, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x10, 0xF0, 0x57, 0xFC, 0x20, 0x46, 0x70, 0xBD, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x5F, 0x8B, 0x46, 0x80, 0x46, 0x29, 0x4C, 0xFE, 0xF5, 0xB4, + 0xFD, 0x04, 0x28, 0x02, 0xD2, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x9F, 0x25, 0x7A, 0x94, 0xF8, 0x00, 0x90, 0x66, 0x68, 0x28, 0xF0, 0x80, 0x74, 0x00, 0x27, 0x4F, 0xF4, 0x00, 0x0A, + 0x06, 0xF5, 0x00, 0x08, 0x54, 0x45, 0x01, 0xD3, 0x44, 0x45, 0x02, 0xD9, 0x6F, 0xF0, 0x02, 0x00, 0xEB, 0xE7, 0x58, 0x46, 0xFD, 0xF5, 0x9A, 0xF8, 0x01, 0x28, 0xE6, 0xD1, 0x9B, 0xF8, 0x00, 0x00, 0x78, 0xB3, 0xB9, 0xF1, 0xFF, 0x0F, 0x06, 0xD0, + 0xB9, 0xF1, 0x7F, 0x0F, 0x06, 0xD0, 0x44, 0x45, 0x0B, 0xD1, 0x2F, 0x46, 0x22, 0xE0, 0x44, 0x45, 0xFB, 0xD0, 0x1F, 0xE0, 0x0A, + 0xEB, 0x56, 0x00, 0xA0, 0x42, 0x1B, 0xD8, 0x6D, 0x1E, 0xEF, 0xB2, 0x18, 0xE0, 0x01, 0x20, 0x6A, 0x1E, 0x00, 0xFA, 0x02, 0xF1, 0x11, 0xE0, 0xB6, 0xFB, 0xF1, 0xF3, 0x42, 0x1E, 0x93, 0x40, 0xB6, 0xFB, 0xF1, 0xF2, 0x82, 0x40, 0x03, 0xF5, 0x00, + 0x03, 0x02, 0xF5, 0x00, 0x02, 0x9C, 0x42, 0x03, 0xD3, 0x94, 0x42, 0x01, 0xD2, 0xC7, 0xB2, 0x02, 0xE0, 0x40, 0x1C, 0xA8, 0x42, 0xEB, 0xDB, 0x38, 0x46, 0xFD, 0xF5, 0x8F, 0xF8, 0x01, 0x20, 0xB1, 0xE7, 0xDC, 0x0C, 0x20, 0x00, 0x30, 0xB5, 0x14, + 0x4C, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x45, 0x28, 0x46, 0x00, 0x21, 0x04, 0xEB, 0x41, 0x13, 0x03, 0xEB, 0x82, 0x03, 0xD3, 0xF8, 0xBC, 0x32, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, 0x0B, 0xB1, 0x5B, 0x1E, 0x18, 0x43, 0x49, 0x1C, 0xC9, 0xB2, 0x0F, + 0x29, 0xEF, 0xD3, 0x00, 0x21, 0x01, 0xE0, 0x40, 0x08, 0x49, 0x1C, 0x00, 0x28, 0xFB, 0xD1, 0xC1, 0xF1, 0x20, 0x00, 0x04, 0xEB, 0x82, 0x01, 0x52, 0x1C, 0xC0, 0xF1, 0x10, 0x00, 0xD2, 0xB2, 0xC1, 0xF8, 0x9C, 0x02, 0x08, 0x2A, 0xDB, 0xD3, 0x30, + 0xBD, 0x64, 0x13, 0x21, 0x00, 0x01, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x64, 0x13, 0x21, 0x00, 0x70, 0xB5, 0x64, 0x4E, 0x78, 0x25, 0x04, 0x46, 0xB1, 0x68, 0x78, 0x29, 0x09, 0xDA, 0x06, 0xEB, 0x41, 0x01, 0x90, 0x22, 0x06, 0xF5, 0x03, + 0x70, 0x0C, 0x31, 0x4C, 0xF6, 0xD0, 0xFC, 0x4F, 0xF4, 0x80, 0x71, 0x5D, 0x48, 0x08, 0x40, 0x08, 0x28, 0x2C, 0xD1, 0x08, 0x39, 0xA2, 0x7B, 0xE3, 0x7B, 0x06, 0xEB, 0x41, 0x00, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x81, 0x22, 0x7B, 0x63, 0x7B, 0x70, + 0x25, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x82, 0x22, 0x78, 0x63, 0x78, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x82, 0xA2, 0x7A, 0xE3, 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x82, 0xA2, 0x78, 0xE3, 0x78, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x82, 0x22, 0x7A, 0x63, + 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x83, 0x22, 0x79, 0x63, 0x79, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x83, 0xA2, 0x79, 0xE3, 0x79, 0x10, 0x34, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x83, 0x10, 0x39, 0xA2, 0x7F, 0xE3, 0x7F, 0x06, 0xEB, 0x41, 0x00, 0x02, + 0xEB, 0x03, 0x22, 0x82, 0x81, 0xA2, 0x7B, 0xE3, 0x7B, 0x10, 0x3D, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x81, 0x22, 0x7F, 0x63, 0x7F, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x82, 0x22, 0x7C, 0x63, 0x7C, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x82, 0xA2, 0x7E, 0xE3, + 0x7E, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x82, 0xA2, 0x7C, 0xE3, 0x7C, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x82, 0x22, 0x7E, 0x63, 0x7E, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x83, 0x22, 0x7D, 0x63, 0x7D, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x83, 0xA2, 0x7D, 0xE3, + 0x7D, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x83, 0xA2, 0x79, 0xE3, 0x79, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x83, 0x22, 0x7B, 0x63, 0x7B, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x84, 0x22, 0x78, 0x63, 0x78, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x84, 0xA2, 0x7A, 0xE3, + 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x84, 0xA2, 0x78, 0xE3, 0x78, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x84, 0x22, 0x7A, 0x63, 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x85, 0x22, 0x79, 0x63, 0x79, 0x20, 0x34, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x85, 0x10, + 0x2D, 0xA8, 0xDA, 0x08, 0x2D, 0x2B, 0xD1, 0x08, 0x39, 0xA2, 0x7B, 0xE3, 0x7B, 0x06, 0xEB, 0x41, 0x00, 0x02, 0xEB, 0x03, 0x22, 0x20, 0xF8, 0x02, 0x2C, 0xA2, 0x79, 0xE3, 0x79, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x81, 0x22, 0x7B, 0x63, 0x7B, 0x02, + 0xEB, 0x03, 0x22, 0x02, 0x82, 0x22, 0x78, 0x63, 0x78, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x82, 0xA2, 0x7A, 0xE3, 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x82, 0xA2, 0x78, 0xE3, 0x78, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x82, 0x22, 0x7A, 0x63, 0x7A, 0x02, + 0xEB, 0x03, 0x22, 0x02, 0x83, 0x22, 0x79, 0x63, 0x79, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x83, 0x08, 0x46, 0x70, 0xBD, 0x00, 0x00, 0x64, 0x13, 0x21, 0x00, 0x0F, 0x00, 0x00, 0x80, 0xF0, 0xB5, 0x86, 0x4B, 0x8C, 0xB0, 0x5A, 0x68, 0xD4, 0x07, 0x7D, + 0xD0, 0x84, 0x4D, 0x52, 0x1C, 0x5A, 0x60, 0x4F, 0xF4, 0x00, 0x42, 0x07, 0x92, 0x06, 0x92, 0x05, 0x92, 0x04, 0x92, 0x03, 0x92, 0x02, 0x92, 0x01, 0x92, 0x00, 0x24, 0x00, 0x92, 0x30, 0xF8, 0x14, 0x30, 0x35, 0xF8, 0x14, 0x60, 0x00, 0x9A, 0x13, + 0xFB, 0x06, 0x26, 0x00, 0xEB, 0x44, 0x03, 0x05, 0xEB, 0x44, 0x02, 0x5F, 0x88, 0xB2, 0xF8, 0x02, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x00, 0x96, 0x9F, 0x88, 0xB2, 0xF8, 0x04, 0xC0, 0x01, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDF, 0x88, 0xB2, 0xF8, 0x06, + 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x01, 0x96, 0x1F, 0x89, 0xB2, 0xF8, 0x08, 0xC0, 0x02, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0x5F, 0x89, 0xB2, 0xF8, 0x0A, + 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x02, 0x96, 0x9F, 0x89, 0xB2, 0xF8, 0x0C, 0xC0, 0x03, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDF, 0x89, 0xB2, 0xF8, 0x0E, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x03, 0x96, 0x1F, 0x8A, 0xB2, 0xF8, 0x10, 0xC0, 0x04, 0x9E, 0x17, + 0xFB, 0x0C, 0x66, 0x5F, 0x8A, 0xB2, 0xF8, 0x12, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x04, 0x96, 0x9F, 0x8A, 0xB2, 0xF8, 0x14, 0xC0, 0x05, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDF, 0x8A, 0xB2, 0xF8, 0x16, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x05, 0x96, 0x1F, + 0x8B, 0xB2, 0xF8, 0x18, 0xC0, 0x06, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0x5F, 0x8B, 0xB2, 0xF8, 0x1A, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x06, 0x96, 0x9F, 0x8B, 0xB2, 0xF8, 0x1C, 0xC0, 0x07, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDB, 0x8B, 0xD2, 0x8B, 0x13, + 0xFB, 0x02, 0x62, 0x10, 0x34, 0x07, 0x92, 0x50, 0x2C, 0x98, 0xDB, 0x00, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x20, 0x00, 0x01, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x22, 0x00, 0x00, 0xE0, 0x85, 0xE0, 0x02, 0x98, 0x08, 0xAE, 0x00, 0x14, 0xAD, 0xF8, 0x24, + 0x00, 0x03, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x26, 0x00, 0x04, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x28, 0x00, 0x05, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x2A, 0x00, 0x06, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x2C, 0x00, 0x10, 0x14, 0xAD, 0xF8, 0x2E, 0x00, 0x00, + 0x20, 0x07, 0x90, 0x06, 0x90, 0x05, 0x90, 0x04, 0x90, 0x03, 0x90, 0x02, 0x90, 0x01, 0x90, 0x04, 0x46, 0x00, 0x90, 0x05, 0xEB, 0x44, 0x10, 0x36, 0xF8, 0x24, 0x30, 0x00, 0x9A, 0x30, 0xF8, 0xA0, 0x7F, 0x13, 0xFB, 0x07, 0x27, 0x06, 0xEB, 0x84, + 0x02, 0xB0, 0xF8, 0x02, 0xC0, 0x52, 0x88, 0x12, 0xFB, 0x0C, 0x77, 0x00, 0x97, 0xB0, 0xF8, 0x04, 0xC0, 0x01, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x06, 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x01, 0x97, 0xB0, 0xF8, 0x08, 0xC0, 0x02, 0x9F, 0x13, + 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x0A, + 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x02, 0x97, 0xB0, 0xF8, 0x0C, 0xC0, 0x03, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x0E, 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x03, 0x97, 0xB0, 0xF8, 0x10, 0xC0, 0x04, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x12, + 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x04, 0x97, 0xB0, 0xF8, 0x14, 0xC0, 0x05, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x16, 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x05, 0x97, 0xB0, 0xF8, 0x18, 0xC0, 0x06, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x1A, + 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x06, 0x97, 0xB0, 0xF8, 0x1C, 0xC0, 0x07, 0x9F, 0x13, 0xFB, 0x0C, 0x73, 0xC0, 0x8B, 0x12, 0xFB, 0x00, 0x30, 0x64, 0x1C, 0x07, 0x90, 0x04, 0x2C, 0xA6, 0xDB, 0x00, 0x20, 0x6A, 0x46, 0x52, 0xF8, 0x20, 0x30, 0x41, + 0xF8, 0x20, 0x30, 0x40, 0x1C, 0x08, 0x28, 0xF8, 0xDB, 0x0C, 0xB0, 0xF0, 0xBD, 0x03, 0x4D, 0xF9, 0xE6, 0x00, 0x00, 0x64, 0x13, 0x21, 0x00, 0x64, 0xE2, 0x20, 0x00, 0x84, 0xE3, 0x20, 0x00, 0x10, 0xB5, 0x91, 0xEA, 0x03, 0x0F, 0x48, 0xBF, 0x83, + 0xF0, 0x00, 0x43, 0x00, 0xF1, 0xD2, 0x80, 0x84, 0x1A, 0x71, 0xEB, 0x03, 0x0C, 0x05, 0xD2, 0x12, 0x19, 0x43, 0xEB, 0x0C, 0x03, 0x00, 0x1B, 0x61, 0xEB, 0x0C, 0x01, 0xDF, 0xF8, 0x24, 0xE1, 0x4F, 0xEA, 0x11, 0x54, 0xA4, 0xEB, 0x13, 0x5C, 0x1E, + 0xEA, 0x43, 0x0F, 0x18, 0xBF, 0x9E, 0xEA, 0x44, 0x5F, 0x73, 0xD0, 0x23, 0xEA, 0x0E, 0x03, 0xDC, 0xF1, 0x20, 0x0E, 0x21, 0xEA, 0x04, 0x51, 0x43, 0xF4, 0x80, 0x13, 0x32, 0xD3, 0x22, 0xFA, 0x0C, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x23, 0xFA, 0x0C, + 0xFE, 0x41, 0xEB, 0x0E, 0x01, 0xCC, 0xF1, 0x20, 0x0E, 0x03, 0xFA, 0x0E, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x51, 0xF1, 0x00, 0x01, 0xB1, 0xF5, 0x80, 0x1F, 0xCC, 0xF1, 0x20, 0x0E, 0x32, 0xD2, 0x01, 0xEB, 0x04, 0x51, 0x12, 0xFA, 0x0E, 0xF2, 0xBD, + 0xE8, 0x10, 0x40, 0x58, 0xBF, 0x70, 0x47, 0x40, 0x1C, 0x38, 0xBF, 0x5F, 0xEA, 0x42, 0x02, 0x18, 0xBF, 0x70, 0x47, 0x00, 0x28, 0x14, 0xBF, 0x20, 0xF0, 0x01, 0x00, 0x41, 0xF1, 0x00, 0x01, 0x4F, 0xEA, 0x41, 0x03, 0x13, 0xF5, 0x00, 0x1F, 0x38, + 0xBF, 0x70, 0x47, 0xA1, 0xF1, 0xC0, 0x41, 0x10, 0xF0, 0x80, 0xBC, 0x01, 0x2A, 0x43, 0xEB, 0x03, 0x02, 0xAC, 0xF1, 0x20, 0x0C, 0xDC, 0xF1, 0x1F, 0x0E, 0x32, 0xBF, 0x4F, 0xF0, 0x00, 0x0E, 0x23, 0xFA, 0x0C, 0xF3, 0x10, 0xEB, 0x03, 0x00, 0x41, + 0xEB, 0x04, 0x51, 0xB4, 0xEB, 0x11, 0x5F, 0xD0, 0xD0, 0xA1, 0xEB, 0x04, 0x51, 0x01, 0xF5, 0x80, 0x11, 0x49, 0x08, 0x5F, 0xEA, 0x30, 0x00, 0x01, 0xEB, 0x04, 0x51, 0x0E, 0xD3, 0x50, 0xF1, 0x00, 0x00, 0x38, 0xBF, 0x12, 0xFA, 0x0E, 0xFE, 0x08, + 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0xC9, 0xE7, 0x40, 0x1C, 0x38, 0xBF, 0x5F, 0xEA, 0x42, 0x02, 0xCA, 0xD1, 0xC3, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xEA, 0x41, 0x03, 0x13, 0xF5, 0x00, 0x1F, 0x38, 0xBF, 0x70, 0x47, 0xA1, 0xF1, 0xC0, 0x41, 0x10, + 0xF0, 0x48, 0xBC, 0x9E, 0xEA, 0x44, 0x5F, 0x08, 0xD0, 0x11, 0xEA, 0x5E, 0x0F, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0xBF, 0x01, 0xF0, 0x00, 0x41, 0x00, 0x20, 0x70, 0x47, 0xBD, 0xE8, 0x10, 0x40, 0x70, 0xB5, 0x10, 0xF0, 0xE9, 0xFB, 0x00, 0xBF, 0x64, + 0xFB, 0xBE, 0x3E, 0x00, 0x00, 0xE0, 0xFF, 0x10, 0xF0, 0x00, 0x42, 0x48, 0xBF, 0x40, 0x42, 0xB0, 0xFA, 0x80, 0xF3, 0x10, 0xFA, 0x03, 0xF1, 0x0A, + 0xD0, 0xC3, 0xF1, 0x1D, 0x03, 0x03, 0xF5, 0x80, 0x63, 0x4F, 0xEA, 0x41, 0x50, 0x02, 0xEB, 0x03, 0x52, 0x02, 0xEB, 0xD1, 0x21, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0xB0, 0xFA, 0x80, 0xF3, 0x10, 0xFA, 0x03, 0xF1, 0x0A, + 0xD0, 0xC3, 0xF1, 0x1D, 0x03, 0x03, 0xF5, 0x80, 0x63, 0x4F, 0xEA, 0x41, 0x50, 0x4F, 0xEA, 0x03, 0x52, 0x02, 0xEB, 0xD1, 0x21, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0x10, 0xB5, 0x91, 0xEA, 0x03, 0x0F, 0x48, 0xBF, 0x83, 0xF0, 0x00, + 0x43, 0x3F, 0xF5, 0x2E, 0xAF, 0x84, 0x1A, 0x71, 0xEB, 0x03, 0x0C, 0x07, 0xD2, 0x12, 0x19, 0x8C, 0xF0, 0x00, 0x4C, 0x43, 0xEB, 0x0C, 0x03, 0x00, 0x1B, 0x61, 0xEB, 0x0C, 0x01, 0xDF, 0xF8, 0xA4, 0xE1, 0x4F, 0xEA, 0x11, 0x54, 0xA4, 0xEB, 0x13, + 0x5C, 0x1E, 0xEA, 0x43, 0x0F, 0x18, 0xBF, 0x9E, 0xEA, 0x44, 0x5F, 0x00, 0xF0, 0xB0, 0x80, 0x23, 0xEA, 0x6E, 0x03, 0x52, 0x42, 0x21, 0xEA, 0x04, 0x51, 0xC3, 0xEB, 0x6E, 0x03, 0x38, 0xBF, 0x5B, 0x1E, 0xDC, 0xF1, 0x20, 0x0E, 0x25, 0xD3, 0x22, + 0xFA, 0x0C, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x43, 0xFA, 0x0C, 0xFE, 0x41, 0xEB, 0x0E, 0x01, 0xCC, 0xF1, 0x20, 0x0E, 0x03, 0xFA, 0x0E, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x51, 0xF1, 0x00, 0x01, 0xCC, 0xF1, 0x20, 0x0E, 0x29, 0xD4, 0x12, 0xFA, 0x0E, + 0xF2, 0x01, 0xEB, 0x04, 0x51, 0xBD, 0xE8, 0x10, 0x40, 0x58, 0xBF, 0x70, 0x47, 0x40, 0x1C, 0x1C, 0xBF, 0xB2, 0xF1, 0x00, 0x4F, 0x70, 0x47, 0x00, 0x28, 0x0C, 0xBF, 0x49, 0x1C, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x12, 0xEB, 0x02, 0x0E, 0x43, + 0xEB, 0x03, 0x02, 0x18, 0xBF, 0x4F, 0xF0, 0x01, 0x0E, 0x4E, 0xEA, 0x42, 0x02, 0xAC, 0xF1, 0x20, 0x0C, 0xDC, 0xF1, 0x1E, 0x0E, 0x54, 0xD9, 0x43, 0xFA, 0x0C, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x51, 0xF1, 0xFF, 0x31, 0xCC, 0xF1, 0x1E, 0x0E, 0xD5, + 0xD5, 0x0E, 0xF1, 0x01, 0x0E, 0x12, 0xFA, 0x0E, 0xFE, 0x40, 0x41, 0x41, 0xEB, 0x01, 0x01, 0x01, 0xEB, 0x44, 0x5C, 0x5F, 0xEA, 0x5C, 0x5C, 0x10, 0xD9, 0x10, 0xEB, 0xDE, 0x70, 0x01, 0xEB, 0x04, 0x51, 0x38, 0xBF, 0xBE, 0xF1, 0x00, 0x4F, 0xBD, + 0xE8, 0x10, 0x40, 0x18, 0xBF, 0x70, 0x47, 0x00, 0x28, 0x0C, 0xBF, 0x49, 0x1C, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x30, 0xD2, 0x4F, 0xEA, 0xD4, 0x2C, 0x11, 0xF5, 0x00, 0x11, 0x24, 0xF4, 0x00, 0x64, 0x1B, 0xD0, 0xB1, 0xFA, 0x81, 0xF2, 0x0B, + 0x3A, 0xA4, 0x1A, 0xA4, 0x1E, 0xD2, 0xF1, 0x20, 0x03, 0x91, 0x40, 0x30, 0xFA, 0x03, 0xF3, 0x19, 0x43, 0x90, 0x40, 0x01, 0xEB, 0xCC, 0x71, 0x00, 0x2C, 0x01, 0xEB, 0x04, 0x51, 0xBD, 0xE8, 0x10, 0x40, 0xA8, 0xBF, 0x70, 0x47, 0x01, 0xF1, 0xC0, + 0x41, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x41, 0x70, 0x47, 0xB0, 0xFA, 0x80, 0xF3, 0x10, 0xFA, 0x03, 0xF1, 0x00, 0xD1, 0x10, 0xBD, 0xE4, 0x1A, 0x17, 0x3C, 0x48, 0x05, 0xC9, 0x0A, + 0xE4, 0xE7, 0x01, 0xEB, 0x04, 0x51, 0x10, 0xBD, 0x49, 0x10, 0x01, 0xEB, 0x04, 0x51, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xEA, 0x30, 0x00, 0x02, 0xE0, 0x4F, 0xF0, 0x00, 0x01, 0x70, 0x47, 0x4A, 0x00, 0x08, 0xBF, 0x00, 0x42, 0xF8, 0xD0, 0xB2, 0xF5, + 0x00, 0x1F, 0x28, 0xBF, 0x70, 0x47, 0x01, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0x9E, 0xEA, 0x44, 0x5F, 0x07, 0xD0, 0x11, 0xEA, 0x5E, 0x0F, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0xBF, 0x00, 0x21, 0x00, 0x20, 0x70, 0x47, 0xBD, 0xE8, + 0x10, 0x40, 0x70, 0xB5, 0x10, 0xF0, 0xD9, 0xFA, 0x00, 0xBF, 0x40, 0xDF, 0xF6, 0x3E, 0x83, 0xF0, 0x00, 0x41, 0x10, 0x46, 0x70, 0x47, 0x00, 0x00, 0xE0, 0xFF, 0x4F, 0xF0, 0x40, 0x70, 0xE1, 0xEE, 0x10, 0x0A, + 0x70, 0x47, 0xFF, 0x21, 0x41, 0xEA, 0xD0, 0x50, 0xC0, 0x05, 0x70, 0x47, 0x02, 0x08, 0x00, 0x28, 0x0A, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x29, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x24, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x25, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x27, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x26, 0x2A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x23, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x2A, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x50, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0x92, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x09, 0x06, 0xA1, 0x01, 0x85, 0x01, 0x95, 0x08, 0x75, 0x08, 0x15, 0x00, 0x25, + 0xFF, 0x19, 0x00, 0x29, 0xFF, 0x81, 0x00, 0xC0, 0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x02, 0x95, 0x02, 0x75, 0x10, 0x15, 0x00, 0x26, 0x9C, 0x02, 0x19, 0x00, 0x2A, 0x9C, 0x02, 0x81, 0x00, 0xC0, 0x06, 0x00, 0xFF, 0x09, 0x00, 0xA1, 0x01, + 0x85, 0x5A, 0x95, 0xFF, 0x75, 0x08, 0x15, 0x00, 0x25, 0xFF, 0x19, 0x00, 0x29, 0xFF, 0x81, 0x00, 0xC0, 0xC0, 0x00, 0x02, 0x08, 0x00, 0x28, 0x12, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4A, 0x2A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4C, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4E, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x4B, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x1A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x5A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x5A, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x69, 0xCC, 0x21, 0x00, 0x4D, 0xCD, 0x21, 0x00, 0x1B, 0xCE, 0x21, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xD1, 0x00, 0x00, 0x12, + 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x62, 0x00, 0x00, 0x12, 0x08, 0x07, 0x0D, 0x0A, + 0x0C, 0x0C, 0x01, 0x0F, 0x0C, 0x0A, + 0x0A, + 0x0C, 0x0C, 0x13, 0x10, 0x06, 0x04, 0x0A, + 0x0C, 0x0C, 0x0B, 0x03, 0x05, 0x02, 0x0A, + 0x0C, 0x0C, 0x09, 0x00, 0x00, 0x00, 0x0A, + 0x0C, 0x0C, 0x09, 0x00, 0x00, 0x00, 0x0A, + 0x0C, 0x0C, 0x00, 0x00, 0x66, 0x00, 0x4B, 0x00, 0x4E, 0x00, 0x76, 0x00, 0x4A, 0x00, 0x3E, 0x00, 0x28, 0x00, 0x29, 0x00, 0x50, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x51, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0x00, 0x81, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, 0xCD, 0x00, 0xE2, 0x00, 0xE5, 0x00, 0xE7, 0x00, 0xE9, 0x00, 0xEA, 0x00, 0x52, 0x01, 0x53, 0x01, 0x54, 0x01, 0x55, 0x01, 0x83, 0x01, 0x8A, 0x01, 0x92, 0x01, 0x94, 0x01, 0x21, 0x02, 0x23, 0x02, + 0x24, 0x02, 0x25, 0x02, 0x26, 0x02, 0x27, 0x02, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x03, 0x20, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x20, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x05, 0x20, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x20, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x07, 0x20, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x65, 0x5F, 0x72, + 0x65, 0x61, 0x64, 0x5F, 0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x6C, 0x65, 0x5F, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x5F, 0x70, 0x61, 0x79, 0x6C, 0x6F, + 0x61, 0x64, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0x19, 0x00, 0x1C, 0x01, 0x3F, 0x00, 0x0F, 0x01, 0x73, 0x00, 0xED, 0x00, 0x77, 0xFF, 0x00, 0x00, 0x4F, 0x01, 0x2C, 0x02, 0x6E, 0x01, 0x2F, 0x01, + 0x50, 0x01, 0x25, 0x00, 0x0B, 0x04, 0x3E, 0x09, 0xFD, 0x04, 0x84, 0x09, 0x80, 0x07, 0xA2, 0x0B, 0x59, 0x0A, + 0xE9, 0x0C, 0x7B, 0xF6, 0x00, 0x00, 0x81, 0x05, 0x0C, 0x21, 0x19, 0x02, 0x06, 0x1C, 0x02, 0xFC, 0x32, 0x15, 0x94, 0x30, 0xFC, 0x68, 0x8F, 0x33, 0x55, 0x5A, 0xFB, 0x45, 0xF3, 0x64, 0x45, 0x5A, 0x2F, 0x6C, 0xEB, 0xAF, 0x00, 0x00, 0x55, 0x5A, + 0x71, 0xCC, 0xF3, 0x64, 0x05, 0xBA, 0x2F, 0x6C, 0xBB, 0xA5, 0x6C, 0xCF, 0x3E, 0x09, 0xF4, 0xDE, 0x81, 0x05, 0xFA, 0xE3, 0x19, 0x02, 0xCE, 0xEA, 0x02, 0xFC, 0x83, 0x09, 0x00, 0x00, 0x84, 0x09, 0x03, 0xFB, 0xA2, 0x0B, 0x80, 0xF8, 0xE9, 0x0C, + 0xA7, 0xF5, 0xF5, 0xFB, 0x70, 0x01, 0xD4, 0xFD, 0x4F, 0x01, 0xD1, 0xFE, 0x6E, 0x01, 0xDB, 0xFF, 0x50, 0x01, 0x6A, 0xFF, 0x00, 0x00, 0x1C, 0x01, 0xE7, 0xFF, 0x0F, 0x01, 0xC1, 0xFF, 0xED, 0x00, 0x8D, 0xFF, 0x6F, 0x20, 0xDA, 0x2B, 0x91, 0xDF, + 0xB6, 0xF5, 0x91, 0xDF, 0x46, 0xCC, 0x6F, 0x20, 0xB3, 0xE2, 0x6F, 0x20, 0x4D, 0x1D, 0x91, 0xDF, 0xBA, 0x33, 0x91, 0xDF, 0x4A, 0x0A, + 0x6F, 0x20, 0x26, 0xD4, 0x36, 0x2A, 0x97, 0x27, 0x7C, 0x11, 0x90, 0x21, 0x84, 0xEE, 0x6D, 0x16, 0xCA, 0xD5, 0xE0, 0x07, 0xCA, 0xD5, 0x20, 0xF8, 0x84, 0xEE, 0x93, 0xE9, 0x7C, 0x11, 0x70, 0xDE, 0x36, 0x2A, 0x69, 0xD8, 0x90, 0xCD, 0x4D, 0x1D, + 0x90, 0xCD, 0x46, 0xCC, 0x90, 0xCD, 0x4A, 0x0A, + 0x90, 0xCD, 0xDA, 0x2B, 0x90, 0xCD, 0x26, 0xD4, 0x90, 0xCD, 0xB6, 0xF5, 0x90, 0xCD, 0xBA, 0x33, 0x90, 0xCD, 0xB3, 0xE2, 0x7C, 0x11, 0xE0, 0x07, 0xCA, 0xD5, 0x93, 0xE9, 0x36, 0x2A, 0x90, 0x21, 0x84, 0xEE, 0x69, 0xD8, 0x84, 0xEE, 0x97, 0x27, + 0x36, 0x2A, 0x70, 0xDE, 0xCA, 0xD5, 0x6D, 0x16, 0x7C, 0x11, 0x20, 0xF8, 0x00, 0x00, 0x77, 0xFF, 0x19, 0x00, 0x1C, 0x01, 0x3F, 0x00, 0x0F, 0x01, 0x73, 0x00, 0xED, 0x00, 0x70, 0x01, 0x0B, 0x04, 0x4F, 0x01, 0x2C, 0x02, 0x6E, 0x01, 0x2F, 0x01, + 0x50, 0x01, 0x25, 0x00, 0x00, 0x00, 0x7B, 0xF6, 0xFD, 0x04, 0x84, 0x09, 0x80, 0x07, 0xA2, 0x0B, 0x59, 0x0A, + 0xE9, 0x0C, 0x3E, 0x09, 0x94, 0x30, 0x81, 0x05, 0x0C, 0x21, 0x19, 0x02, 0x06, 0x1C, 0x02, 0xFC, 0x32, 0x15, 0x00, 0x00, 0xEB, 0xAF, 0x8F, 0x33, 0x55, 0x5A, 0xFB, 0x45, 0xF3, 0x64, 0x45, 0x5A, 0x2F, 0x6C, 0xFC, 0x68, 0x6C, 0xCF, 0x55, 0x5A, + 0x71, 0xCC, 0xF3, 0x64, 0x05, 0xBA, 0x2F, 0x6C, 0xBB, 0xA5, 0x00, 0x00, 0x83, 0x09, 0xF4, 0xDE, 0x81, 0x05, 0xFA, 0xE3, 0x19, 0x02, 0xCE, 0xEA, 0x02, 0xFC, 0x3E, 0x09, 0xF5, 0xFB, 0x84, 0x09, 0x03, 0xFB, 0xA2, 0x0B, 0x80, 0xF8, 0xE9, 0x0C, + 0xA7, 0xF5, 0x00, 0x00, 0x6A, 0xFF, 0xD4, 0xFD, 0x4F, 0x01, 0xD1, 0xFE, 0x6E, 0x01, 0xDB, 0xFF, 0x50, 0x01, 0x70, 0x01, 0x00, 0x00, 0x1C, 0x01, 0xE7, 0xFF, 0x0F, 0x01, 0xC1, 0xFF, 0xED, 0x00, 0x8D, 0xFF, 0x90, 0xCD, 0xDA, 0x2B, 0x90, 0xCD, + 0xB6, 0xF5, 0x90, 0xCD, 0x46, 0xCC, 0x90, 0xCD, 0xB3, 0xE2, 0x90, 0xCD, 0x4D, 0x1D, 0x90, 0xCD, 0xBA, 0x33, 0x90, 0xCD, 0x4A, 0x0A, + 0x90, 0xCD, 0x26, 0xD4, 0x36, 0x2A, 0x97, 0x27, 0x7C, 0x11, 0x90, 0x21, 0x84, 0xEE, 0x6D, 0x16, 0xCA, 0xD5, 0xE0, 0x07, 0xCA, 0xD5, 0x20, 0xF8, 0x84, 0xEE, 0x93, 0xE9, 0x7C, 0x11, 0x70, 0xDE, 0x36, 0x2A, 0x69, 0xD8, 0x6F, 0x20, 0x4D, 0x1D, + 0x91, 0xDF, 0x46, 0xCC, 0x91, 0xDF, 0x4A, 0x0A, + 0x6F, 0x20, 0xDA, 0x2B, 0x6F, 0x20, 0x26, 0xD4, 0x91, 0xDF, 0xB6, 0xF5, 0x91, 0xDF, 0xBA, 0x33, 0x6F, 0x20, 0xB3, 0xE2, 0x7C, 0x11, 0xE0, 0x07, 0xCA, 0xD5, 0x93, 0xE9, 0x36, 0x2A, 0x90, 0x21, 0x84, 0xEE, 0x69, 0xD8, 0x84, 0xEE, 0x97, 0x27, + 0x36, 0x2A, 0x70, 0xDE, 0xCA, 0xD5, 0x6D, 0x16, 0x7C, 0x11, 0x20, 0xF8, 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, 0x25, 0x38, 0x1F, 0x02, + 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, + 0x67, 0x7A, 0x5D, 0x40, 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, + 0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, + 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, + 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, + 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, + 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x42, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x43, 0x00, 0x42, 0x6F, 0x6F, 0x74, 0x4F, 0x6E, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x72, 0x01, + 0x0E, 0x01, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x03, 0x04, 0x05, 0xFE, 0x00, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6D, 0x65, 0x6E, 0x74, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x58, 0xE1, 0x20, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, + 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x19, 0x80, 0x01, 0x02, 0x01, 0x05, 0x03, 0x03, 0x12, 0x18, 0x03, 0x19, 0x80, 0x01, 0x0B, + 0x09, 0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, 0x05, 0xFF, 0x5D, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x03, 0x03, 0x12, 0x18, 0x03, 0x19, 0x80, 0x01, 0x0B, 0x09, 0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, + 0x05, 0xFF, 0x5D, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x03, 0x03, 0x12, 0x18, 0x03, 0x19, 0x80, 0x01, 0x0D, 0xFF, 0x5D, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0xE5, 0x20, 0x00, 0x1C, 0x53, 0x81, 0x00, + 0x1C, 0x53, 0x81, 0x00, 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xE5, 0x20, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x1C, 0x53, 0x81, 0x00, + 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xE5, 0x20, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x58, 0x19, 0x21, 0x00, + 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x5A, 0x00, 0x00, 0xEC, 0xF7, 0x24, 0xFC, 0x11, 0x46, 0xEB, 0xF7, 0xFB, 0xFD, 0x01, 0xF0, 0x7D, 0xF9, 0x3E, 0xF6, + 0x09, 0xFF, 0x00, 0x00, 0x0B, 0x49, 0xD1, 0xF8, 0x00, 0xC0, 0x4A, 0x68, 0x5C, 0xF8, 0x04, 0x3B, 0x10, 0x68, 0x18, 0x44, 0x42, 0xF8, 0x04, 0x0B, 0x8C, 0x45, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x0C, 0x8A, 0x42, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x02, + 0xC1, 0xF8, 0x00, 0xC0, 0x4A, 0x60, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x50, 0x19, 0x21, 0x00, 0x30, 0xB5, 0x82, 0x68, 0x22, 0xF0, 0x00, 0x42, 0x82, 0x60, 0x82, 0x69, 0x42, 0xF0, 0x1F, 0x02, 0x82, 0x61, 0x02, 0x68, 0x53, 0x4B, 0x1A, 0x40, + 0x02, 0x60, 0x02, 0x68, 0x91, 0xF8, 0x2E, 0x30, 0x1A, 0x43, 0x8B, 0x8D, 0x42, 0xEA, 0x03, 0x22, 0x02, 0x60, 0xCB, 0x69, 0x8A, 0x6A, 0x1A, 0x43, 0x0B, 0x6A, 0x1A, 0x43, 0x82, 0x60, 0x82, 0x68, 0x0B, 0x8E, 0x42, 0xEA, 0x43, 0x12, 0x82, 0x60, + 0x82, 0x68, 0x91, 0xF8, 0x34, 0x30, 0x42, 0xEA, 0xC3, 0x52, 0x82, 0x60, 0x4B, 0x69, 0xCA, 0x68, 0x1A, 0x43, 0x0B, 0x69, 0x1A, 0x43, 0x42, 0x60, 0x42, 0x68, 0x91, 0xF8, 0x33, 0x30, 0x4C, 0x89, 0x1A, 0x43, 0x91, 0xF8, 0x32, 0x30, 0x9B, 0x04, + 0x43, 0xEA, 0x44, 0x23, 0x1A, 0x43, 0x42, 0x60, 0x4A, 0x88, 0x01, 0x25, 0x05, 0xFA, 0x02, 0xF3, 0x1C, 0x02, 0x52, 0x1E, 0xA4, 0xF5, 0x80, 0x74, 0x14, 0x43, 0xC4, 0x60, 0x09, 0x88, 0x05, 0xFA, 0x01, 0xF3, 0x49, 0x1E, 0x5B, 0x1E, 0x43, 0xEA, + 0x01, 0x41, 0x01, 0x61, 0xC1, 0x69, 0x41, 0xF0, 0xFF, 0x01, 0xC1, 0x61, 0x81, 0x69, 0x21, 0xF0, 0x1F, 0x01, 0x81, 0x61, 0x30, 0xBD, 0x00, 0x22, 0x2F, 0x49, 0x30, 0x48, 0x00, 0xF0, 0x62, 0xB8, 0x02, 0x21, 0x10, 0xB5, 0x41, 0x80, 0x01, 0x80, + 0x0B, 0x07, 0x4A, 0x07, 0xC3, 0x61, 0x4F, 0xF4, 0xFC, 0x71, 0x82, 0x62, 0x81, 0x85, 0x01, 0x21, 0x80, 0xF8, 0x2E, 0x10, 0x01, 0x86, 0x0C, 0x07, 0x04, 0x62, 0xCC, 0x07, 0xC4, 0x60, 0xC0, 0xE9, 0x04, 0x23, 0x10, 0x22, 0x42, 0x81, 0x80, 0xF8, + 0x32, 0x20, 0x80, 0xF8, 0x33, 0x10, 0x03, 0x21, 0x80, 0xF8, 0x34, 0x10, 0x10, 0xBD, 0x01, 0x2A, 0x82, 0x68, 0x02, 0xD0, 0x8A, 0x43, 0x82, 0x60, 0x70, 0x47, 0x0A, + 0x43, 0xFB, 0xE7, 0x01, 0x2A, 0x82, 0x69, 0x02, 0xD0, 0x8A, 0x43, 0x82, 0x61, 0x70, 0x47, 0x0A, + 0x43, 0xFB, 0xE7, 0x10, 0xB5, 0x00, 0x23, 0x04, 0xE0, 0x44, 0x69, 0x5B, 0x1C, 0x21, 0xF8, 0x02, 0x4B, 0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD3, 0x10, 0xBD, 0x00, 0x29, 0x81, 0x68, 0x02, 0xD0, 0x41, 0xF0, 0x00, 0x41, 0x01, 0xE0, 0x21, 0xF0, 0x00, + 0x41, 0x81, 0x60, 0x70, 0x47, 0x01, 0x2A, 0x0D, 0x4B, 0x82, 0x68, 0xC1, 0xF3, 0x08, 0x01, 0x22, 0xF4, 0x00, 0x12, 0x82, 0x60, 0x82, 0x68, 0x02, 0xEA, 0x03, 0x02, 0x82, 0x60, 0x82, 0x68, 0x42, 0xEA, 0x01, 0x31, 0x03, 0xD1, 0x81, 0x60, 0x81, + 0x68, 0x41, 0xF4, 0x00, 0x11, 0x81, 0x60, 0x70, 0x47, 0xE0, 0x00, 0xFC, 0xFF, 0x40, 0x00, 0x00, 0x60, 0x00, 0x00, 0x08, 0x08, 0xFF, 0x0F, 0xE0, 0xFF, 0xF0, 0xB5, 0x4F, 0xF4, 0x90, 0x77, 0x7B, 0x06, 0xC0, 0xF3, 0x81, 0x66, 0xC1, 0xF3, 0x41, + 0x75, 0x4F, 0xF4, 0xA0, 0x7E, 0x40, 0xEA, 0x01, 0x04, 0x01, 0x2A, 0x06, 0xD0, 0xB9, 0x42, 0x6C, 0xD0, 0x71, 0x45, 0x6A, 0xD0, 0x10, 0x29, 0x68, 0xD0, 0x49, 0xE0, 0xA1, 0xF1, 0xC0, 0x4C, 0xBC, 0xF1, 0x40, 0x0C, 0x16, 0xD0, 0xB1, 0xF1, 0xC2, + 0x4F, 0x1E, 0xD0, 0x1C, 0xF1, 0x30, 0x0C, 0x03, 0xD0, 0xDF, 0xF8, 0xF0, 0xC2, 0x61, 0x45, 0x24, 0xD1, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x80, 0x6C, 0xC3, 0xF8, 0x0C, 0xC2, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x00, 0x6C, 0xC3, 0xF8, 0x0C, + 0xC2, 0x27, 0xE0, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x80, 0x6C, 0xC3, 0xF8, 0x0C, 0xC2, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x00, 0x5C, 0xF1, 0xE7, 0xD3, 0xF8, 0x0C, 0x42, 0x44, 0xF0, 0x80, 0x64, 0xC3, 0xF8, 0x0C, 0x42, 0xD3, 0xF8, 0x0C, + 0x42, 0x44, 0xF0, 0x80, 0x54, 0xC3, 0xF8, 0x0C, 0x42, 0x15, 0xE0, 0xDF, 0xF8, 0xA4, 0xC2, 0x61, 0x45, 0x0B, 0xD1, 0xD3, 0xF8, 0x60, 0xC3, 0x4C, 0xF4, 0x00, 0x7C, 0xC3, 0xF8, 0x60, 0xC3, 0xD3, 0xF8, 0x48, 0xC3, 0x4C, 0xF0, 0x10, 0x0C, 0xC3, + 0xF8, 0x48, 0xC3, 0xB9, 0x42, 0x1D, 0xD0, 0x71, 0x45, 0x1B, 0xD0, 0x10, 0x29, 0x19, 0xD0, 0x20, 0xF0, 0x40, 0x63, 0x21, 0xF0, 0xC0, 0x40, 0x4F, 0xEA, 0x86, 0x01, 0x01, 0xF1, 0x80, 0x41, 0x01, 0x2A, 0xD1, 0xF8, 0x10, 0x22, 0x17, 0xD0, 0x9A, + 0x43, 0xC1, 0xF8, 0x10, 0x22, 0xA9, 0x00, 0x01, 0xF1, 0x80, 0x41, 0xD1, 0xF8, 0x2C, 0x22, 0x82, 0x43, 0x22, 0xEA, 0x40, 0x00, 0xC1, 0xF8, 0x2C, 0x02, 0xF0, 0xBD, 0xD3, 0xF8, 0x20, 0x02, 0x20, 0x43, 0x02, 0xE0, 0xD3, 0xF8, 0x20, 0x02, 0xA0, + 0x43, 0xC3, 0xF8, 0x20, 0x02, 0xF0, 0xBD, 0x1A, 0x43, 0xC1, 0xF8, 0x10, 0x22, 0xA9, 0x00, 0x01, 0xF1, 0x80, 0x41, 0xD1, 0xF8, 0x2C, 0x22, 0x02, 0x43, 0x42, 0xEA, 0x40, 0x00, 0xE6, 0xE7, 0x87, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x42, 0x16, + 0xD1, 0xD2, 0xF8, 0x34, 0x02, 0x20, 0xF4, 0x80, 0x30, 0xC2, 0xF8, 0x34, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x10, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0xC1, 0x40, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x34, + 0x02, 0x40, 0xF4, 0x80, 0x30, 0x18, 0xE0, 0x7A, 0x4B, 0x98, 0x42, 0x17, 0xD1, 0xD2, 0xF8, 0x34, 0x02, 0x20, 0xF4, 0x80, 0x20, 0xC2, 0xF8, 0x34, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x00, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, + 0x03, 0x40, 0xEA, 0x41, 0x50, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x34, 0x02, 0x40, 0xF4, 0x80, 0x20, 0xC2, 0xF8, 0x34, 0x02, 0x70, 0x47, 0x6D, 0x4B, 0x9A, 0x04, 0x98, 0x42, 0x16, 0xD1, 0xD2, 0xF8, 0x38, 0x02, 0x20, 0xF0, 0x01, 0x00, 0xC2, + 0xF8, 0x38, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x30, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0xC1, 0x30, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x38, 0x02, 0x40, 0xF0, 0x01, 0x00, 0x18, 0xE0, 0x60, 0x4B, 0x98, + 0x42, 0x17, 0xD1, 0xD2, 0xF8, 0x38, 0x02, 0x20, 0xF0, 0x04, 0x00, 0xC2, 0xF8, 0x38, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x20, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0x41, 0x40, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, + 0xF8, 0x38, 0x02, 0x40, 0xF0, 0x04, 0x00, 0xC2, 0xF8, 0x38, 0x02, 0x70, 0x47, 0x53, 0x4B, 0x5A, 0x04, 0x98, 0x42, 0x18, 0xD1, 0xD2, 0xF8, 0x34, 0x02, 0x20, 0xF0, 0x01, 0x00, 0xC2, 0xF8, 0x34, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, + 0x60, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0x41, 0x20, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x34, 0x02, 0x40, 0xF0, 0x01, 0x00, 0xC2, 0xF8, 0x34, 0x02, 0x70, 0x47, 0x46, 0x4B, 0x98, 0x42, 0xFB, 0xD1, 0xD2, 0xF8, 0x30, + 0x02, 0x20, 0xF4, 0x80, 0x50, 0xC2, 0xF8, 0x30, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x50, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0xC1, 0x20, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF4, 0x80, + 0x50, 0xC2, 0xF8, 0x30, 0x02, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0xA0, 0x74, 0x23, 0x06, 0xC0, 0xF3, 0x41, 0x72, 0x4F, 0xF4, 0x90, 0x75, 0x01, 0x29, 0x06, 0xD0, 0xA8, 0x42, 0x1E, 0xD0, 0xA0, 0x42, 0x1C, 0xD0, 0x10, 0x28, 0x1A, 0xD0, 0x05, + 0xE0, 0xA8, 0x42, 0x13, 0xD0, 0xA0, 0x42, 0x11, 0xD0, 0x10, 0x28, 0x0F, 0xD0, 0x01, 0x29, 0x4F, 0xEA, 0x82, 0x01, 0x01, 0xF1, 0x80, 0x41, 0x20, 0xF0, 0xC0, 0x40, 0xD1, 0xF8, 0x2C, 0x22, 0x0F, 0xD0, 0x82, 0x43, 0x22, 0xEA, 0x40, 0x00, 0xC1, + 0xF8, 0x2C, 0x02, 0x30, 0xBD, 0xD3, 0xF8, 0x20, 0x12, 0x01, 0x43, 0x02, 0xE0, 0xD3, 0xF8, 0x20, 0x12, 0x81, 0x43, 0xC3, 0xF8, 0x20, 0x12, 0x30, 0xBD, 0x02, 0x43, 0x42, 0xEA, 0x40, 0x00, 0xEE, 0xE7, 0xC0, 0xF3, 0x81, 0x62, 0x4F, 0xF0, 0x80, + 0x43, 0x01, 0x29, 0x06, 0xD0, 0x02, 0x28, 0x1C, 0xD0, 0x04, 0x28, 0x1A, 0xD0, 0x01, 0x28, 0x18, 0xD0, 0x05, 0xE0, 0x02, 0x28, 0x11, 0xD0, 0x04, 0x28, 0x0F, 0xD0, 0x01, 0x28, 0x0D, 0xD0, 0x01, 0x29, 0x4F, 0xEA, 0x82, 0x01, 0x01, 0xF1, 0x80, + 0x41, 0x20, 0xF0, 0x40, 0x60, 0xD1, 0xF8, 0x10, 0x22, 0x0D, 0xD0, 0x82, 0x43, 0xC1, 0xF8, 0x10, 0x22, 0x70, 0x47, 0xD3, 0xF8, 0x20, 0x12, 0x01, 0x43, 0x02, 0xE0, 0xD3, 0xF8, 0x20, 0x12, 0x81, 0x43, 0xC3, 0xF8, 0x20, 0x12, 0x70, 0x47, 0x02, + 0x43, 0xF0, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x60, 0x00, 0x40, 0x00, 0x20, 0x00, 0x30, 0x01, 0x40, 0x00, 0x34, 0x01, 0x40, 0x00, 0x50, 0x01, 0x40, 0x00, 0x54, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00, 0x10, 0x01, 0x40, 0x4D, 0x49, 0x88, + 0x42, 0x04, 0xD1, 0x00, 0x22, 0x4F, 0xF4, 0x90, 0x71, 0x02, 0x20, 0x06, 0xE0, 0x4A, 0x49, 0x88, 0x42, 0x05, 0xD1, 0x00, 0x22, 0x4F, 0xF4, 0xA0, 0x71, 0x04, 0x20, 0xFF, 0xF7, 0x45, 0xBE, 0x70, 0x47, 0x10, 0xB5, 0x42, 0x68, 0x42, 0xF0, 0x01, + 0x02, 0x42, 0x60, 0x42, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x42, 0x60, 0x0B, 0x89, 0x4F, 0xF0, 0x00, 0x44, 0x4A, 0x68, 0x44, 0xEA, 0x03, 0x43, 0x1A, 0x43, 0xC2, 0x61, 0x4B, 0x69, 0xCA, 0x6A, 0x1A, 0x43, 0xD1, 0xE9, 0x08, 0x43, 0x23, 0x43, 0x1A, + 0x43, 0x8B, 0x69, 0x1A, 0x43, 0x8B, 0x6A, 0x1A, 0x43, 0x0B, 0x69, 0x1A, 0x43, 0xCB, 0x69, 0x1A, 0x43, 0xCB, 0x68, 0x1A, 0x43, 0x0B, 0x6B, 0x1A, 0x43, 0x34, 0x4B, 0x1A, 0x43, 0x42, 0x60, 0x0A, + 0x68, 0x43, 0xF2, 0x81, 0x03, 0x1A, 0x43, 0x82, 0x60, 0x82, 0x68, 0x22, 0xF4, 0x40, 0x52, 0x82, 0x60, 0xD1, 0xE9, 0x0D, 0x21, 0x42, 0xEA, 0x01, 0x21, 0x01, 0x62, 0x10, 0xBD, 0x4F, 0xF4, 0x80, 0x31, 0x01, 0x60, 0x40, 0xF2, 0x71, 0x21, 0x41, + 0x60, 0x10, 0x21, 0x81, 0x60, 0x00, 0x21, 0x4F, 0xF4, 0x00, 0x62, 0xC0, 0xE9, 0x03, 0x12, 0x41, 0x61, 0x81, 0x61, 0xC1, 0x61, 0x01, 0x62, 0x41, 0x62, 0x81, 0x62, 0xC1, 0x62, 0x01, 0x63, 0x01, 0x21, 0x41, 0x63, 0x81, 0x63, 0x70, 0x47, 0x01, + 0x2A, 0x4F, 0xEA, 0x81, 0x32, 0x0F, 0xD0, 0x00, 0x2A, 0x03, 0xDA, 0x42, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x42, 0x60, 0x8A, 0x01, 0x03, 0xD5, 0x42, 0x68, 0x42, 0xF0, 0x80, 0x72, 0x42, 0x60, 0x42, 0x68, 0x8A, 0x43, 0x42, 0x60, 0x70, 0x47, 0x00, + 0x2A, 0x03, 0xDA, 0x42, 0x68, 0x22, 0xF4, 0x80, 0x32, 0x42, 0x60, 0x8A, 0x01, 0x03, 0xD5, 0x42, 0x68, 0x22, 0xF0, 0x80, 0x72, 0x42, 0x60, 0x42, 0x68, 0x0A, + 0x43, 0xEE, 0xE7, 0x01, 0x2A, 0x82, 0x68, 0x02, 0xD0, 0x8A, 0x43, 0x82, 0x60, 0x70, 0x47, 0x0A, + 0x43, 0xFB, 0xE7, 0x02, 0x46, 0x00, 0x20, 0x52, 0x6A, 0x12, 0xEA, 0x11, 0x6F, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0xC2, 0x68, 0x0A, + 0x43, 0xC2, 0x60, 0xC2, 0x68, 0x8A, 0x43, 0xC2, 0x60, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x10, 0x02, 0x40, 0x00, 0x00, 0x01, 0x01, 0x6B, 0x48, 0x10, 0xB5, 0x01, 0x78, 0x29, 0xB1, 0x00, 0x21, 0x01, 0x70, 0x41, 0x78, 0x26, + 0x20, 0x22, 0xF6, 0xEF, 0xFB, 0x00, 0x22, 0x10, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xA5, 0xFD, 0x4F, 0xF4, 0x88, 0x74, 0x20, 0x46, 0x22, 0xF6, 0xC4, 0xFB, 0x20, 0xF0, 0x01, 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x22, 0xF6, 0xCD, 0xBB, 0x2D, + 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x0C, 0x46, 0x26, 0x20, 0x22, 0xF6, 0xB6, 0xFB, 0x5A, 0x49, 0x02, 0x07, 0x4F, 0xF0, 0x01, 0x06, 0x48, 0x70, 0x05, 0xD5, 0x0E, 0x70, 0x20, 0xF0, 0x08, 0x01, 0x26, 0x20, 0x22, 0xF6, 0xCB, 0xFB, 0x20, 0x68, 0xB0, + 0xF5, 0x10, 0x6F, 0x44, 0xD1, 0x4F, 0xF4, 0x88, 0x78, 0x40, 0x46, 0x22, 0xF6, 0xA1, 0xFB, 0x40, 0xF0, 0x01, 0x01, 0x40, 0x46, 0x22, 0xF6, 0xAC, 0xFB, 0x4E, 0x49, 0x0A, + 0x20, 0x09, 0x68, 0x88, 0x47, 0x40, 0xF2, 0x13, 0x17, 0x38, 0x46, 0x22, 0xF6, 0x93, 0xFB, 0x40, 0xF0, 0x01, 0x01, 0x38, 0x46, 0x22, 0xF6, 0x9E, 0xFB, 0x40, 0x46, 0x22, 0xF6, 0x8B, 0xFB, 0x40, 0xF0, 0x04, 0x01, 0x40, 0x46, 0x22, 0xF6, 0x96, + 0xFB, 0x44, 0x49, 0x02, 0x20, 0x09, 0x68, 0x88, 0x47, 0x38, 0x46, 0x22, 0xF6, 0x7F, 0xFB, 0x20, 0xF0, 0x01, 0x01, 0x38, 0x46, 0x22, 0xF6, 0x8A, 0xFB, 0x60, 0x6A, 0x38, 0xB9, 0x38, 0x46, 0x22, 0xF6, 0x75, 0xFB, 0x40, 0xF0, 0x02, 0x01, 0x38, + 0x46, 0x22, 0xF6, 0x80, 0xFB, 0x40, 0xF2, 0x01, 0x60, 0x28, 0x60, 0x61, 0x6A, 0x20, 0x69, 0x38, 0x4A, 0x08, 0x43, 0x21, 0x6A, 0x11, 0x43, 0x08, 0x43, 0x68, 0x60, 0x4F, 0xF4, 0x88, 0x50, 0xA8, 0x60, 0x2E, 0x61, 0x00, 0x20, 0xA8, 0x61, 0xAE, + 0x61, 0xA1, 0x6A, 0x20, 0x68, 0x62, 0x68, 0x08, 0x43, 0x21, 0x6B, 0x11, 0x43, 0x08, 0x43, 0x40, 0xF0, 0x0A, + 0x00, 0xE8, 0x61, 0xD4, 0xE9, 0x02, 0x01, 0x08, 0x43, 0x40, 0xF0, 0xA0, 0x00, 0x68, 0x61, 0xE1, 0x69, 0xE0, 0x6A, 0x08, 0x43, 0xD4, 0xE9, 0x05, 0x21, 0x11, 0x43, 0x08, 0x43, 0x40, 0xF4, 0x40, 0x50, 0x68, 0x62, 0x60, 0x6B, 0xB0, 0xF5, 0x00, + 0x6F, 0x03, 0xD0, 0xE8, 0x69, 0x40, 0xF0, 0x01, 0x00, 0xE8, 0x61, 0xE1, 0x6B, 0x60, 0x6B, 0x08, 0x43, 0xA1, 0x6B, 0x41, 0xF4, 0x80, 0x61, 0x08, 0x43, 0x28, 0x62, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, 0x80, 0x62, 0x00, 0x21, 0xC0, 0xE9, 0x00, + 0x21, 0xC2, 0x61, 0x81, 0x60, 0x4F, 0xF4, 0xC0, 0x52, 0xC0, 0xE9, 0x03, 0x12, 0x4F, 0xF4, 0x80, 0x32, 0xC0, 0xE9, 0x08, 0x21, 0x81, 0x62, 0x2F, 0x22, 0xC1, 0x62, 0xC0, 0xE9, 0x05, 0x21, 0x4F, 0xF4, 0x00, 0x62, 0xC0, 0xE9, 0x0C, 0x12, 0xFF, + 0x22, 0xC0, 0xE9, 0x0E, 0x21, 0x70, 0x47, 0x4A, 0x68, 0x02, 0x60, 0x8A, 0x68, 0x42, 0x60, 0xCA, 0x68, 0x82, 0x60, 0x0A, + 0x69, 0xC2, 0x60, 0x4A, 0x69, 0x09, 0x68, 0x0A, + 0x43, 0x02, 0x61, 0x70, 0x47, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x81, 0x60, 0xC1, 0x60, 0x01, 0x61, 0x41, 0x61, 0x70, 0x47, 0x00, 0x00, 0x5C, 0xE9, 0x20, 0x00, 0x54, 0x01, 0x20, 0x00, 0x58, 0x01, 0x20, 0x00, 0x00, 0x86, 0x20, 0x0A, + 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x4F, 0xF4, 0x88, 0x77, 0x0C, 0x46, 0x00, 0x26, 0x38, 0x46, 0x22, 0xF6, 0xEE, 0xFA, 0x40, 0xF0, 0x04, 0x01, 0x38, 0x46, 0x22, 0xF6, 0xF9, 0xFA, 0xE8, 0x68, 0x20, 0xF0, 0x1F, 0x00, 0xE8, 0x60, 0x61, 0x6C, + 0xA0, 0x6B, 0xA2, 0x8F, 0x08, 0x43, 0xA1, 0x6C, 0x41, 0xEA, 0x82, 0x11, 0x08, 0x43, 0x28, 0x65, 0xA0, 0x6B, 0x48, 0xB9, 0x28, 0x6D, 0xE1, 0x8F, 0xB4, 0xF8, 0x42, 0x20, 0x08, 0x43, 0xB4, 0xF8, 0x40, 0x10, 0x11, 0x43, 0x08, 0x43, 0x28, 0x65, + 0xA8, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0xA8, 0x60, 0x04, 0xEB, 0x86, 0x00, 0x05, 0xEB, 0x86, 0x01, 0xD0, 0xF8, 0x0A, + 0x00, 0x08, 0x61, 0x76, 0x1C, 0xF6, 0xB2, 0x08, 0x2E, 0xF4, 0xD3, 0x60, 0x8D, 0xA8, 0x60, 0xE0, 0x88, 0xA1, 0x88, 0xE2, 0x78, 0x08, 0x43, 0xA1, 0x78, 0x09, 0x05, 0x41, 0xEA, 0x82, 0x31, 0x08, 0x43, 0x94, 0xF8, 0x34, 0x10, 0x40, 0xEA, 0xC1, + 0x60, 0x68, 0x60, 0x94, 0xF8, 0x35, 0x00, 0x21, 0x6B, 0x94, 0xF8, 0x36, 0x20, 0x08, 0x43, 0x94, 0xF8, 0x2C, 0x10, 0x49, 0x07, 0x41, 0xEA, 0x02, 0x41, 0x08, 0x43, 0x21, 0x78, 0x40, 0xEA, 0x41, 0x20, 0x61, 0x78, 0x08, 0x43, 0x68, 0x65, 0xA8, + 0x6D, 0x40, 0xF4, 0x40, 0x60, 0xA8, 0x65, 0x68, 0x68, 0x40, 0xF0, 0x80, 0x60, 0x68, 0x60, 0xE8, 0x68, 0x40, 0xF4, 0xF8, 0x50, 0xE8, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x21, 0x01, 0x70, 0x80, 0x22, 0x42, 0x70, 0xC1, 0x80, 0x92, 0x01, 0x82, + 0x80, 0x80, 0xF8, 0x2C, 0x10, 0x80, 0xF8, 0x34, 0x10, 0x01, 0x63, 0x80, 0xF8, 0x35, 0x10, 0x80, 0xF8, 0x36, 0x10, 0x41, 0x81, 0x81, 0x81, 0xC1, 0x81, 0x01, 0x82, 0x41, 0x82, 0x81, 0x82, 0xC1, 0x82, 0x01, 0x83, 0x41, 0x83, 0x81, 0x83, 0xC1, + 0x83, 0x01, 0x84, 0x41, 0x84, 0x81, 0x84, 0xC1, 0x84, 0x01, 0x85, 0x41, 0x85, 0x06, 0x22, 0x82, 0x70, 0x01, 0x22, 0xC2, 0x70, 0x41, 0x64, 0x81, 0x63, 0x82, 0x87, 0xC1, 0x87, 0xA0, 0xF8, 0x40, 0x10, 0xA0, 0xF8, 0x42, 0x10, 0x81, 0x64, 0x70, + 0x47, 0x00, 0x22, 0x4F, 0xF0, 0xC2, 0x41, 0x4E, 0x48, 0xFF, 0xF7, 0x38, 0xBC, 0x00, 0x2A, 0xC2, 0x68, 0x01, 0xD0, 0x0A, + 0x43, 0x00, 0xE0, 0x8A, 0x43, 0xC2, 0x60, 0x70, 0x47, 0xCA, 0x07, 0x4F, 0xEA, 0x51, 0x01, 0x00, 0xEB, 0x81, 0x00, 0x00, 0x6B, 0x01, 0xD0, 0x00, 0x0C, 0x70, 0x47, 0x80, 0xB2, 0x70, 0x47, 0x70, 0xB5, 0x0E, 0x46, 0x04, 0x46, 0x01, 0x2A, 0x03, + 0xD0, 0x60, 0x68, 0x20, 0xF0, 0x03, 0x00, 0x23, 0xE0, 0x20, 0x6D, 0xC0, 0x02, 0x1A, 0xD5, 0x20, 0x6D, 0x40, 0xF4, 0x70, 0x50, 0x20, 0x65, 0x3C, 0x4D, 0x50, 0x20, 0x29, 0x68, 0x88, 0x47, 0x20, 0x6D, 0x40, 0xF4, 0x40, 0x40, 0x20, 0x65, 0x29, + 0x68, 0x4F, 0xF4, 0xA0, 0x70, 0x88, 0x47, 0x20, 0x6D, 0x40, 0xF4, 0x40, 0x30, 0x20, 0x65, 0x29, 0x68, 0xF0, 0x20, 0x88, 0x47, 0x20, 0x6D, 0x40, 0xF4, 0x80, 0x20, 0x20, 0x65, 0x60, 0x68, 0x20, 0xF0, 0x03, 0x00, 0x60, 0x60, 0x60, 0x68, 0x30, + 0x43, 0x60, 0x60, 0x70, 0xBD, 0xCB, 0x07, 0x4F, 0xEA, 0x51, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x08, 0x69, 0x02, 0xD0, 0x40, 0xEA, 0x02, 0x40, 0x00, 0xE0, 0x10, 0x43, 0x08, 0x61, 0x70, 0x47, 0x02, 0xE0, 0x03, 0x68, 0x21, 0xF8, 0x02, 0x3B, 0x52, + 0x1E, 0x92, 0xB2, 0xF9, 0xD2, 0x70, 0x47, 0x23, 0x4B, 0x01, 0x22, 0x10, 0x30, 0x82, 0x40, 0x98, 0x6D, 0x09, 0xB1, 0x10, 0x43, 0x00, 0xE0, 0x90, 0x43, 0x98, 0x65, 0x70, 0x47, 0x08, 0xB5, 0x0B, 0x46, 0x00, 0x22, 0x8D, 0xF8, 0x00, 0x20, 0x01, + 0x46, 0x6A, 0x46, 0x18, 0x46, 0x01, 0xF0, 0x6A, 0xF8, 0xBD, 0xEE, 0xC0, 0x0A, + 0x10, 0xEE, 0x10, 0x0A, + 0x01, 0xB2, 0x9D, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x00, 0xD1, 0x08, 0x46, 0x08, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x88, 0x74, 0x00, 0x28, 0x20, 0x46, 0x04, 0xD0, 0x22, 0xF6, 0xDD, 0xF9, 0x40, 0xF0, 0x04, 0x01, 0x03, 0xE0, 0x22, 0xF6, 0xD8, 0xF9, + 0x20, 0xF0, 0x04, 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x22, 0xF6, 0xE1, 0xB9, 0x01, 0x29, 0x01, 0x6D, 0x03, 0xD0, 0x21, 0xF4, 0x00, 0x21, 0x01, 0x65, 0x70, 0x47, 0x41, 0xF4, 0x00, 0x21, 0xFA, 0xE7, 0x80, 0x6D, 0x00, 0xF0, 0x01, 0x00, + 0x70, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x54, 0x01, 0x20, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x22, 0x63, 0x49, 0x4F, 0xF4, 0x80, 0x30, 0xFF, 0xF7, 0x92, 0xBB, 0x61, 0x4A, 0x14, 0x23, 0x02, 0x44, 0xB2, 0xFB, 0xF3, 0xF2, 0xF0, 0xB5, + 0x1B, 0x07, 0xD3, 0xF8, 0x60, 0x43, 0x44, 0xF4, 0x00, 0x74, 0xC3, 0xF8, 0x60, 0x43, 0xD3, 0xF8, 0x60, 0x43, 0x64, 0x05, 0x05, 0xD5, 0xD3, 0xF8, 0x60, 0x43, 0x24, 0xF4, 0x80, 0x64, 0xC3, 0xF8, 0x60, 0x43, 0x07, 0x25, 0x02, 0x2A, 0x04, 0xD2, + 0xD3, 0xF8, 0x60, 0x63, 0x02, 0xEB, 0x42, 0x04, 0x07, 0xE0, 0x94, 0x1E, 0x06, 0x2C, 0x0F, 0xD2, 0xD3, 0xF8, 0x60, 0x63, 0x02, 0xEB, 0x42, 0x04, 0xE4, 0x1D, 0xA5, 0x40, 0xAE, 0x43, 0xC3, 0xF8, 0x60, 0x63, 0x8D, 0x88, 0xA5, 0x40, 0xD3, 0xF8, + 0x60, 0x43, 0x25, 0x43, 0xC3, 0xF8, 0x60, 0x53, 0x03, 0x2A, 0x03, 0xD0, 0x05, 0x2A, 0x01, 0xD0, 0x07, 0x2A, 0x10, 0xD1, 0x91, 0xF8, 0x24, 0x50, 0x01, 0x24, 0xA7, 0x1E, 0x01, 0x2D, 0xD3, 0xF8, 0x5C, 0x53, 0xA2, 0xF1, 0x01, 0x06, 0x07, 0xEB, + 0x56, 0x06, 0x04, 0xFA, 0x06, 0xF4, 0x18, 0xD0, 0xA5, 0x43, 0xC3, 0xF8, 0x5C, 0x53, 0x4C, 0x89, 0x00, 0x2C, 0x0C, 0x89, 0x13, 0xD0, 0x0C, 0x25, 0x45, 0xEA, 0x44, 0x04, 0x84, 0x60, 0x3A, 0x4C, 0x0D, 0x69, 0x44, 0xF8, 0x22, 0x50, 0x4C, 0x69, + 0x04, 0x60, 0x8C, 0x8D, 0x01, 0x2C, 0x0C, 0xD0, 0x02, 0x2A, 0x27, 0xD0, 0x03, 0x2A, 0x2C, 0xD0, 0x31, 0xE0, 0x25, 0x43, 0xE5, 0xE7, 0x04, 0x25, 0x45, 0xEA, 0x44, 0x04, 0x84, 0x60, 0xCC, 0x68, 0xEE, 0xE7, 0x4F, 0xF4, 0x80, 0x54, 0x02, 0x2A, + 0x02, 0xD0, 0x03, 0x2A, 0x0B, 0xD0, 0x22, 0xE0, 0x0D, 0x8E, 0x8A, 0x6A, 0xC9, 0x8D, 0x42, 0xEA, 0x45, 0x22, 0x44, 0xEA, 0x81, 0x21, 0x0A, + 0x43, 0xC3, 0xF8, 0x64, 0x23, 0x17, 0xE0, 0x0D, 0x8E, 0x8A, 0x6A, 0xC9, 0x8D, 0x42, 0xEA, 0x45, 0x22, 0x44, 0xEA, 0x81, 0x21, 0x0A, + 0x43, 0xC3, 0xF8, 0x68, 0x23, 0x0C, 0xE0, 0xD3, 0xF8, 0x64, 0x13, 0x21, 0xF4, 0x80, 0x51, 0xC3, 0xF8, 0x64, 0x13, 0x05, 0xE0, 0xD3, 0xF8, 0x68, 0x13, 0x21, 0xF4, 0x80, 0x51, 0xC3, 0xF8, 0x68, 0x13, 0xC0, 0x68, 0xF0, 0xBD, 0x01, 0x22, 0x02, + 0x81, 0x40, 0xF6, 0xFF, 0x71, 0xC1, 0x60, 0x00, 0x21, 0x81, 0x80, 0x80, 0xF8, 0x24, 0x10, 0x02, 0x86, 0xC1, 0x85, 0x41, 0x81, 0x81, 0x85, 0x70, 0x47, 0x00, 0x29, 0x81, 0x68, 0x02, 0xD0, 0x41, 0xF0, 0x01, 0x01, 0x01, 0xE0, 0x21, 0xF0, 0x01, + 0x01, 0x81, 0x60, 0x70, 0x47, 0x01, 0x60, 0x70, 0x47, 0x00, 0x29, 0x81, 0x68, 0x02, 0xD0, 0x21, 0xF0, 0x04, 0x01, 0x01, 0xE0, 0x41, 0xF0, 0x04, 0x01, 0x81, 0x60, 0x70, 0x47, 0x10, 0xB5, 0x05, 0x4B, 0x14, 0x24, 0x03, 0x44, 0xB3, 0xFB, 0xF4, + 0xF3, 0x02, 0x60, 0x03, 0x48, 0x40, 0xF8, 0x23, 0x10, 0x10, 0xBD, 0x00, 0x40, 0x00, 0x20, 0x00, 0xE0, 0xFF, 0xBF, 0xB0, 0x20, 0x00, 0x40, 0x10, 0xB5, 0x01, 0x24, 0x13, 0x46, 0x01, 0x28, 0x09, 0xD0, 0xA6, 0x4A, 0x02, 0x28, 0x0A, + 0xD0, 0x03, 0x28, 0x0B, 0xD0, 0x04, 0x28, 0x10, 0xD0, 0x00, 0x24, 0x20, 0x46, 0x10, 0xBD, 0xA2, 0x49, 0x10, 0x78, 0x08, 0x70, 0xF9, 0xE7, 0x18, 0x78, 0x10, 0x70, 0xF6, 0xE7, 0x9E, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x00, 0x1D, 0x3D, 0xF6, 0x1D, 0xF9, 0xEF, 0xE7, 0x51, 0x80, 0x93, 0x60, 0xEC, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0x86, 0xB0, 0x00, 0x26, 0xDD, 0xE9, 0x0E, 0x45, 0x90, 0x46, 0x26, 0x80, 0x00, 0x93, 0x8A, 0x46, 0x13, 0x46, 0x02, + 0x22, 0x94, 0x49, 0x95, 0x48, 0xEA, 0xF5, 0xEB, 0xFE, 0x02, 0x20, 0x04, 0x27, 0xDF, 0xF8, 0x3C, 0x92, 0x8D, 0xF8, 0x04, 0x00, 0xB8, 0xF1, 0x0A, + 0x0F, 0x1A, 0xD0, 0x0D, 0xDC, 0xB8, 0xF1, 0x02, 0x0F, 0x29, 0xD0, 0x01, 0x27, 0xB8, 0xF1, 0x04, 0x0F, 0x31, 0xD0, 0xB8, 0xF1, 0x06, 0x0F, 0x3A, 0xD0, 0xB8, 0xF1, 0x08, 0x0F, 0x09, 0xD1, 0x41, 0xE0, 0xB8, 0xF1, 0x0E, 0x0F, 0x08, 0xD0, 0xB8, + 0xF1, 0x12, 0x0F, 0x05, 0xD0, 0xB8, 0xF1, 0x15, 0x0F, 0x02, 0xD0, 0x40, 0xF2, 0x0A, + 0x46, 0x39, 0xE0, 0x8D, 0xF8, 0x08, 0x70, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, 0x47, 0xD9, 0xF8, 0x08, 0x00, 0x28, 0x60, 0xB9, 0xF8, 0x02, 0x10, 0x21, 0x80, 0x01, 0xB1, 0x48, 0xBB, 0x4F, 0xF4, 0x90, 0x66, 0x26, + 0xE0, 0x03, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, 0x47, 0x71, 0x48, 0x00, 0x1D, 0x14, 0xE0, 0x8D, 0xF8, 0x08, 0x00, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, + 0x47, 0xC5, 0xF8, 0x00, 0x90, 0x27, 0x80, 0x0E, 0xE0, 0x8D, 0xF8, 0x08, 0x70, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, 0x47, 0x66, 0x48, 0x28, 0x60, 0xF2, 0xE7, 0x67, 0x48, 0x28, 0x60, 0x4F, 0x20, 0x20, 0x80, 0x06, + 0xB0, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x41, 0x86, 0xB0, 0x88, 0x46, 0xDD, 0xE9, 0x0C, 0x14, 0x00, 0x25, 0x64, 0xB1, 0x60, 0x48, 0x03, 0x26, 0x5A, 0x4F, 0x0E, 0x2A, 0x49, 0xD0, 0x14, 0xDC, 0x04, 0x2A, 0x37, 0xD0, 0x06, + 0x2A, 0x26, 0xD0, 0x0A, + 0x2A, 0x12, 0xD1, 0x41, 0xE0, 0x00, 0x91, 0x56, 0x49, 0x57, 0x48, 0x23, 0x46, 0x02, 0x22, 0x34, 0x31, 0x80, 0x1E, 0xEA, 0xF5, 0x6B, 0xFE, 0x40, 0xF2, 0x04, 0x40, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x12, 0x2A, 0x04, 0xD0, 0x15, 0x2A, 0x2F, + 0xD0, 0x40, 0xF2, 0x0A, + 0x45, 0x34, 0xE0, 0x4C, 0x49, 0x23, 0x78, 0x01, 0x22, 0x64, 0x31, 0xEA, 0xF5, 0x59, 0xFE, 0x01, 0x20, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x00, 0x20, 0x78, 0x8D, 0xF8, 0x0C, 0x00, 0x25, 0xE0, 0x44, 0x49, 0x23, 0x78, 0x01, 0x22, 0x0B, + 0x70, 0x02, 0x21, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x10, 0x21, 0x78, 0x8D, 0xF8, 0x0C, 0x10, 0x3F, 0x49, 0x8C, 0x31, 0x0B, 0xE0, 0x23, 0x78, 0x3B, 0x70, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x60, 0x21, 0x78, 0x8D, 0xF8, 0x0C, + 0x10, 0x39, 0x49, 0x01, 0x22, 0xB8, 0x31, 0xEA, 0xF5, 0x33, 0xFE, 0x07, 0xE0, 0x05, 0x20, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x00, 0x8D, 0xF8, 0x0C, 0x10, 0x04, 0x94, 0x7A, 0x68, 0x1A, 0xB1, 0x15, 0xB9, 0x01, 0xA9, 0x40, 0x46, 0x90, + 0x47, 0x28, 0x46, 0xB8, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x86, 0xB0, 0x88, 0x46, 0x1C, 0x46, 0x01, 0x27, 0x00, 0x93, 0x2A, 0x49, 0x15, 0x46, 0x13, 0x46, 0x8D, 0xF8, 0x04, 0x70, 0x3E, 0x46, 0x02, 0x22, 0xE0, 0x31, 0x27, 0x48, 0xEA, 0xF5, 0x10, + 0xFE, 0x0B, 0x2D, 0x0E, 0xD0, 0x0F, 0x2D, 0x13, 0xD0, 0x16, 0x2D, 0x17, 0xD0, 0x00, 0x26, 0x1F, 0x48, 0x42, 0x68, 0x00, 0x2A, 0x9B, 0xD0, 0x00, 0x2E, 0x99, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0x95, 0xE7, 0xE0, 0x07, 0x02, 0xD0, 0x8D, + 0xF8, 0x08, 0x70, 0xF0, 0xE7, 0x02, 0x20, 0x0A, + 0xE0, 0xE0, 0x07, 0x01, 0xD0, 0x03, 0x20, 0x06, 0xE0, 0x04, 0x20, 0x04, 0xE0, 0xE0, 0x07, 0x01, 0xD0, 0x05, 0x20, 0x00, 0xE0, 0x06, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xE0, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x15, 0x48, 0xD0, 0xE9, 0x1D, 0x12, 0xCD, + 0xE9, 0x00, 0x12, 0x03, 0x6F, 0x0D, 0x48, 0x0F, 0x49, 0x42, 0x88, 0x50, 0x31, 0x02, 0xA8, 0x32, 0xF6, 0xE3, 0xFB, 0x50, 0xB9, 0x0D, 0x48, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x0D, 0x49, 0x80, 0x1E, 0xEA, 0xF5, 0xD2, 0xFD, 0xFF, 0x20, 0x8D, + 0xF8, 0x08, 0x00, 0x02, 0x48, 0x44, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x00, 0x00, 0xEC, 0xE9, 0x20, 0x00, 0x12, 0xE6, 0x20, 0x00, 0x84, 0x02, 0x80, 0x08, 0x02, 0x33, 0x10, 0x21, 0x4C, 0xDE, 0x20, 0x00, 0x02, 0x30, 0x10, 0x21, 0xCC, + 0xE0, 0x20, 0x00, 0x94, 0x03, 0x80, 0x08, 0x2D, 0xE9, 0xFF, 0x41, 0xB9, 0x4C, 0xDD, 0xE9, 0x0A, + 0x30, 0x0E, 0x46, 0x00, 0x25, 0x03, 0x27, 0x24, 0x68, 0x40, 0xF2, 0x0D, 0x41, 0x02, 0x2A, 0x12, 0xD0, 0x4F, 0xF0, 0x02, 0x0C, 0x10, 0x2A, 0x17, 0xD0, 0x0C, 0x2A, 0x2C, 0xD0, 0x00, 0x93, 0x13, 0x46, 0x02, 0x22, 0xB0, 0x49, 0xB1, 0x48, 0xEA, + 0xF5, 0x9F, 0xFD, 0x40, 0xF2, 0x0A, + 0x45, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x01, 0x2B, 0x2D, 0xD1, 0x60, 0xB3, 0x8D, 0xF8, 0x04, 0x70, 0x01, 0x21, 0x8D, 0xF8, 0x06, 0x10, 0x1D, 0xE0, 0x05, 0x2B, 0x24, 0xD1, 0x18, 0xB3, 0x8D, 0xF8, 0x04, 0x70, 0x8D, 0xF8, 0x06, + 0xC0, 0x01, 0x78, 0x8D, 0xF8, 0x08, 0x10, 0x41, 0x78, 0x82, 0x78, 0x01, 0xEB, 0x02, 0x21, 0xAD, 0xF8, 0x0A, + 0x10, 0xC1, 0x78, 0x00, 0x79, 0x01, 0xEB, 0x00, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x09, 0xE0, 0x01, 0x2B, 0x0D, 0xD1, 0x60, 0xB1, 0x8D, 0xF8, 0x04, 0x70, 0x8D, 0xF8, 0x06, 0xC0, 0x00, 0x78, 0x8D, 0xF8, 0x08, 0x00, 0x00, 0x2C, 0xCF, 0xD0, 0x01, + 0xA9, 0x30, 0x46, 0xA0, 0x47, 0xCB, 0xE7, 0x0D, 0x46, 0xC9, 0xE7, 0x2D, 0xE9, 0xFE, 0x4F, 0x92, 0x4F, 0xDD, 0xE9, 0x0C, 0x54, 0x4F, 0xF0, 0x00, 0x09, 0x0A, + 0x2A, 0x19, 0xD0, 0x09, 0xDC, 0x8C, 0x4E, 0x04, 0x2A, 0x16, 0xD0, 0x4F, 0xF0, 0x04, 0x08, 0x06, 0x2A, 0x2B, 0xD0, 0x08, 0x2A, 0x06, 0xD1, 0x40, 0xE0, 0x42, 0xF2, 0x90, 0x78, 0x0E, 0x2A, 0x57, 0xD0, 0x12, 0x2A, 0x7D, 0xD0, 0x85, 0x49, 0x13, + 0x46, 0x01, 0x22, 0x3C, 0x31, 0x38, 0x46, 0xEA, 0xF5, 0x46, 0xFD, 0x40, 0xF2, 0x0A, + 0x49, 0xDC, 0xE0, 0x7F, 0x49, 0x4F, 0xF4, 0x00, 0x70, 0x0C, 0x31, 0x2F, 0xF6, 0x29, 0xF8, 0x7C, 0x4A, 0x00, 0x20, 0x69, 0x46, 0x0C, 0x32, 0xC0, 0xF1, 0x05, 0x03, 0xD3, 0x5C, 0x0B, 0x54, 0x40, 0x1C, 0x06, 0x28, 0xF8, 0xDB, 0x00, 0x98, 0xF0, + 0x60, 0xBD, 0xF8, 0x04, 0x00, 0x30, 0x82, 0x06, 0x20, 0x22, 0x60, 0x6F, 0xE0, 0x42, 0xF2, 0x92, 0x70, 0xEF, 0xF5, 0xE9, 0xFB, 0x72, 0x49, 0x82, 0x46, 0x03, 0x46, 0x01, 0x22, 0x6C, 0x31, 0x38, 0x46, 0xEA, 0xF5, 0x1E, 0xFD, 0x6E, 0x49, 0xDA, + 0xF8, 0x60, 0x30, 0x01, 0x22, 0x80, 0x31, 0x38, 0x46, 0x73, 0x60, 0xEA, 0xF5, 0x15, 0xFD, 0x68, 0x48, 0x00, 0x1D, 0x16, 0xE0, 0x42, 0xF2, 0x93, 0x70, 0xEF, 0xF5, 0xD1, 0xFB, 0x66, 0x49, 0x82, 0x46, 0x03, 0x46, 0x01, 0x22, 0x98, 0x31, 0x38, + 0x46, 0xEA, 0xF5, 0x06, 0xFD, 0x62, 0x49, 0xDA, 0xF8, 0x60, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x38, 0x46, 0xB3, 0x60, 0xEA, 0xF5, 0xFD, 0xFC, 0x5C, 0x48, 0x08, 0x30, 0x20, 0x60, 0xA5, 0xF8, 0x00, 0x80, 0x90, 0xE0, 0x40, 0x46, 0xEF, 0xF5, 0xB7, + 0xFB, 0x58, 0x4E, 0x41, 0x78, 0x14, 0x36, 0x80, 0x46, 0xB1, 0x70, 0x05, 0x21, 0x31, 0x70, 0x01, 0x21, 0x71, 0x70, 0x40, 0x78, 0xB0, 0x70, 0x49, 0x05, 0xF0, 0x78, 0x91, 0xF8, 0x14, 0x13, 0x40, 0xF0, 0x01, 0x00, 0x49, 0x09, 0x61, 0xF3, 0x41, + 0x00, 0x20, 0xF0, 0x08, 0x00, 0x40, 0xF0, 0x04, 0x00, 0xF0, 0x70, 0xEF, 0xF5, 0xCB, 0xFB, 0xF1, 0x78, 0x43, 0x46, 0x60, 0xF3, 0x04, 0x11, 0xF1, 0x70, 0x4F, 0xF4, 0x00, 0x60, 0xB0, 0x80, 0x01, 0x22, 0x00, 0xE0, 0x18, 0xE0, 0x46, 0x49, 0x38, + 0x46, 0xC0, 0x31, 0xEA, 0xF5, 0xC9, 0xFC, 0xEF, 0xF5, 0xB9, 0xFB, 0x68, 0xB1, 0x44, 0x49, 0xB1, 0xEB, 0x08, 0x2F, 0x02, 0xD1, 0x4F, 0xF4, 0xAA, 0x60, 0x01, 0xE0, 0x4F, 0xF4, 0x2A, 0x60, 0xB0, 0x60, 0x0C, 0x20, 0x26, 0x60, 0x28, 0x80, 0x51, + 0xE0, 0x4F, 0xF4, 0x7F, 0x60, 0xF7, 0xE7, 0xEF, 0xF5, 0xA5, 0xFB, 0x37, 0x4E, 0x10, 0x27, 0x20, 0x36, 0xDF, 0xF8, 0xE8, 0xB0, 0x00, 0x28, 0x42, 0xF2, 0x91, 0x7A, 0x40, 0x46, 0x1F, 0xD0, 0xEF, 0xF5, 0x6A, 0xFB, 0xD0, 0xF8, 0x94, 0x01, 0x30, + 0x60, 0x50, 0x46, 0xEF, 0xF5, 0x64, 0xFB, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x92, 0x70, 0xEF, 0xF5, 0x5E, 0xFB, 0x00, 0x6E, 0xB0, 0x60, 0x42, 0xF2, 0x93, 0x70, 0xEF, 0xF5, 0x58, 0xFB, 0x00, 0x6E, 0xF0, 0x60, 0xD6, 0xE9, 0x01, 0x12, 0x00, + 0x91, 0xCD, 0xE9, 0x01, 0x20, 0x26, 0x49, 0x04, 0x22, 0xD8, 0x31, 0x33, 0x68, 0x1D, 0xE0, 0xEF, 0xF5, 0x4A, 0xFB, 0xD0, 0xF8, 0x94, 0x01, 0x30, 0x60, 0x50, 0x46, 0xEF, 0xF5, 0x44, 0xFB, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x92, 0x70, 0xEF, + 0xF5, 0x3E, 0xFB, 0x00, 0x6E, 0xB0, 0x60, 0x42, 0xF2, 0x93, 0x70, 0xEF, 0xF5, 0x38, 0xFB, 0x00, 0x6E, 0xF0, 0x60, 0xD6, 0xE9, 0x01, 0x12, 0x00, 0x91, 0xCD, 0xE9, 0x01, 0x20, 0x1A, 0x49, 0x33, 0x68, 0x04, 0x22, 0x58, 0x46, 0xEA, 0xF5, 0x68, + 0xFC, 0x26, 0x60, 0x2F, 0x80, 0x48, 0x46, 0xBD, 0xE8, 0xFE, 0x8F, 0x3E, 0xB5, 0x04, 0x46, 0x14, 0x48, 0xD0, 0xE9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF5, 0x00, 0x71, 0x43, 0x69, 0x4F, 0xF4, 0x05, 0x72, 0x02, 0xA8, 0x32, 0xF6, 0x5C, + 0xFA, 0x20, 0xB1, 0x07, 0x48, 0x04, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x0A, + 0x49, 0x06, 0x48, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x40, 0x31, 0x80, 0x1E, 0xEA, 0xF5, 0x45, 0xFC, 0xFF, 0x20, 0x3E, 0xBD, 0x0C, 0xEA, 0x20, 0x00, 0x50, 0x04, 0x80, 0x08, 0x02, 0x33, 0x10, 0x21, 0x00, 0x00, 0x20, 0x80, 0x02, 0x30, 0x10, + 0x21, 0x68, 0x05, 0x80, 0x08, 0xCC, 0xE6, 0x21, 0x00, 0x10, 0xB5, 0xED, 0xF7, 0x47, 0xFA, 0xEE, 0xF7, 0x77, 0xFE, 0xEF, 0xF7, 0x3B, 0xF8, 0x00, 0xF0, 0xBB, 0xF8, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xC6, 0xB8, 0x51, 0x48, 0x90, 0xF8, 0x26, + 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0xEE, 0xF7, 0xC6, 0xBE, 0x70, 0x47, 0x4C, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0xEE, 0xF7, 0xF4, 0xBE, 0x70, 0x47, 0xEE, 0xF7, 0xAD, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xE9, + 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0xEE, 0xE7, 0x10, 0xB5, 0x00, 0xF0, 0xE1, 0xF9, 0xEF, 0xF7, 0x72, 0xFB, 0x41, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x05, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF0, 0x00, 0x40, 0xEE, 0xF7, 0x4E, + 0xBE, 0x10, 0xBD, 0x10, 0xB5, 0x3B, 0x48, 0xEB, 0xF5, 0xC8, 0xF9, 0x20, 0xB9, 0x00, 0x22, 0x3A, 0x49, 0x3A, 0x48, 0xEA, 0xF5, 0xF2, 0xFB, 0x3B, 0x49, 0x39, 0x48, 0x08, 0x60, 0x3B, 0x49, 0x3A, 0x48, 0x08, 0x60, 0xEB, 0xF7, 0x1D, 0xFC, 0xBD, + 0xE8, 0x10, 0x40, 0x02, 0x20, 0xEB, 0xF5, 0xE5, 0xBA, 0x10, 0xB5, 0x06, 0x20, 0x32, 0xF6, 0x34, 0xF9, 0x35, 0x48, 0xEC, 0xF7, 0x37, 0xF9, 0x2C, 0x4C, 0xA0, 0x72, 0x33, 0x48, 0xEC, 0xF7, 0x77, 0xF8, 0xE0, 0x72, 0x31, 0x48, 0xFF, 0xF7, 0xEB, + 0xFD, 0x20, 0x73, 0x2F, 0x48, 0xEC, 0xF7, 0xB7, 0xF9, 0x60, 0x73, 0x2D, 0x48, 0xFF, 0xF7, 0x6A, 0xFF, 0xA0, 0x73, 0x2B, 0x48, 0xEC, 0xF7, 0x30, 0xFF, 0xE0, 0x73, 0xBD, 0xE8, 0x10, 0x40, 0x28, 0x48, 0x32, 0xF6, 0x2F, 0xB9, 0xEE, 0xF7, 0x7C, + 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0xAA, 0xFF, 0xFF, 0xF7, 0xAE, 0xFF, 0x01, 0x20, 0x2F, 0xF6, 0x68, 0xFC, 0xED, 0xF7, 0x7A, 0xFE, 0xFF, 0xF7, 0xD0, 0xFF, 0xFF, 0xF7, 0xB7, 0xFF, 0xEE, 0xF7, 0x7C, 0xF9, 0xEE, 0xF7, 0x6A, 0xFA, 0xBD, 0xE8, 0x10, + 0x40, 0xEF, 0xF7, 0x7C, 0xBC, 0x1B, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x00, 0xF0, 0x55, 0xFC, 0xFF, 0xF7, 0x6F, 0xFF, 0x16, 0x20, 0x21, 0xF6, 0x74, 0xFD, 0x0D, 0x4C, 0x40, 0x09, 0x04, 0xF8, 0x26, 0x0F, 0x16, 0x20, 0x21, 0xF6, 0x6D, 0xFD, 0x20, + 0xF0, 0xE0, 0x01, 0x16, 0x20, 0x21, 0xF6, 0x89, 0xFD, 0x09, 0x49, 0x0A, + 0x48, 0x23, 0x78, 0x01, 0x22, 0xA4, 0x31, 0x80, 0x1C, 0xEA, 0xF5, 0x8D, 0xFB, 0x20, 0x78, 0x08, 0xB9, 0xFF, 0xF7, 0xC8, 0xFF, 0x09, 0xF6, 0x39, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xF2, 0x20, 0x00, 0x55, 0x83, 0x20, 0x00, 0xB8, 0x10, 0x80, + 0x08, 0x00, 0x30, 0x10, 0x21, 0x31, 0x83, 0x20, 0x00, 0xB4, 0xE7, 0x20, 0x00, 0x43, 0x83, 0x20, 0x00, 0xB0, 0xE7, 0x20, 0x00, 0xA1, 0xAD, 0x20, 0x00, 0x98, 0xE7, 0x20, 0x00, 0x10, 0xB5, 0x00, 0x22, 0x80, 0x49, 0x81, 0x48, 0xEA, 0xF5, 0x6B, + 0xFB, 0x40, 0xF2, 0xC3, 0x31, 0x7F, 0x48, 0x3C, 0xF6, 0x67, 0xFE, 0x7E, 0x49, 0x01, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x7A, 0x49, 0x10, 0xB5, 0x00, 0x22, 0x28, 0x31, 0x79, 0x48, 0xEA, 0xF5, 0x5B, 0xFB, 0x24, 0x21, 0x79, 0x48, 0x3C, 0xF6, 0x58, + 0xFE, 0x77, 0x48, 0x00, 0x21, 0x41, 0x60, 0x4F, 0xF4, 0x10, 0x61, 0x01, 0x60, 0x4F, 0xF4, 0x80, 0x41, 0x81, 0x60, 0x4F, 0xF4, 0xC0, 0x51, 0xC1, 0x60, 0x4F, 0xF4, 0x00, 0x31, 0x01, 0x61, 0x2F, 0x21, 0x41, 0x61, 0x10, 0xBD, 0x7C, 0xB5, 0xFF, + 0xF7, 0xD1, 0xFF, 0x00, 0x24, 0x6B, 0x48, 0x01, 0x25, 0x23, 0x46, 0x04, 0x70, 0x45, 0x70, 0x00, 0x95, 0x22, 0x46, 0x21, 0x46, 0x24, 0x20, 0x01, 0x95, 0xF3, 0xF5, 0xF4, 0xFF, 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0x16, 0x20, 0xCD, 0xE9, 0x00, + 0x45, 0xF3, 0xF5, 0xEC, 0xFF, 0x00, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x17, 0x20, 0x01, 0x94, 0xF3, 0xF5, 0xE4, 0xFF, 0x00, 0xF0, 0x18, 0xF8, 0x00, 0xF0, 0x48, 0xF8, 0xBD, 0xE8, 0x7C, 0x40, 0x00, 0xF0, 0x72, 0xB8, 0x59, 0x48, 0x10, + 0xB5, 0x01, 0x21, 0x01, 0x70, 0x00, 0x21, 0x41, 0x70, 0x58, 0x48, 0xFF, 0xF7, 0x6D, 0xF8, 0x58, 0x48, 0xFF, 0xF7, 0x0C, 0xF9, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0xEB, 0xF7, 0x7A, 0xBC, 0x10, 0xB5, 0x90, 0xB0, 0x01, 0x22, 0x4F, + 0xF4, 0x90, 0x71, 0x02, 0x20, 0xFE, 0xF7, 0xB2, 0xFE, 0x68, 0x46, 0xFF, 0xF7, 0xA1, 0xF8, 0x4F, 0xF4, 0x80, 0x30, 0x00, 0x90, 0x4A, 0x48, 0x08, 0x21, 0x40, 0xF2, 0x71, 0x22, 0x40, 0x68, 0x04, 0x28, 0x01, 0xD0, 0x18, 0xB1, 0x05, 0xE0, 0xCD, + 0xE9, 0x01, 0x21, 0x02, 0xE0, 0x10, 0x20, 0xCD, 0xE9, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x62, 0xCD, 0xE9, 0x03, 0x02, 0x07, 0x90, 0x04, 0x20, 0xCD, 0xE9, 0x0D, 0x10, 0x3F, 0x4C, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x4B, 0xF8, 0x01, + 0x22, 0x3E, 0x49, 0x20, 0x46, 0xFF, 0xF7, 0x95, 0xF8, 0x10, 0xB0, 0x10, 0xBD, 0x00, 0xB5, 0x01, 0x22, 0x91, 0xB0, 0x10, 0x21, 0x10, 0x46, 0xFE, 0xF7, 0x81, 0xFE, 0x68, 0x46, 0xFF, 0xF7, 0x70, 0xF9, 0x33, 0x49, 0x48, 0x68, 0x01, 0x90, 0x08, + 0x68, 0x00, 0x90, 0xB0, 0xF5, 0x10, 0x6F, 0x03, 0xD0, 0xB0, 0xF5, 0x80, 0x6F, 0x09, 0xD0, 0x0E, 0xE0, 0xC8, 0x68, 0x04, 0x90, 0x88, 0x68, 0x09, 0x90, 0x08, 0x69, 0x08, 0x90, 0x48, 0x69, 0x05, 0x90, 0x05, 0xE0, 0x88, 0x69, 0x0A, + 0x90, 0xC8, 0x69, 0x0B, 0x90, 0x08, 0x6A, 0x06, 0x90, 0x00, 0x20, 0x02, 0x90, 0x03, 0x90, 0x69, 0x46, 0x26, 0x48, 0xFF, 0xF7, 0xC3, 0xF8, 0x11, 0xB0, 0x00, 0xBD, 0x70, 0xB5, 0x01, 0x22, 0x96, 0xB0, 0x24, 0x49, 0x50, 0x03, 0xFE, 0xF7, 0x53, + 0xFE, 0x68, 0x46, 0xEB, 0xF7, 0xEE, 0xFB, 0x02, 0x20, 0x78, 0x21, 0x01, 0x24, 0x01, 0x91, 0x8D, 0xF8, 0x00, 0x40, 0x8D, 0xF8, 0x08, 0x00, 0x00, 0x21, 0x03, 0xAA, 0x8D, 0xF8, 0x01, 0x00, 0x8D, 0xF8, 0x09, 0x10, 0x03, 0x26, 0x82, 0xE8, 0x53, + 0x00, 0x15, 0x48, 0x15, 0x25, 0x10, 0x30, 0x07, 0x90, 0x11, 0x48, 0x69, 0x46, 0xC0, 0x1C, 0x08, 0x90, 0x11, 0x20, 0x8D, 0xF8, 0x44, 0x00, 0x8D, 0xF8, 0x45, 0x50, 0x12, 0x48, 0xEB, 0xF7, 0xC9, 0xFA, 0x01, 0x22, 0x11, 0x46, 0x10, 0x46, 0xEB, + 0xF7, 0xFD, 0xFB, 0x8D, 0xF8, 0x48, 0x50, 0x13, 0x96, 0x8D, 0xF8, 0x50, 0x40, 0x12, 0xA8, 0xF3, 0xF5, 0xA4, 0xFE, 0x01, 0x21, 0x08, 0x46, 0xEB, 0xF7, 0xDE, 0xFB, 0x16, 0xB0, 0x70, 0xBD, 0x24, 0x38, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x08, + 0xF3, 0x20, 0x00, 0xCC, 0xF6, 0x20, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x20, 0x02, 0x40, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x20, 0x58, 0x70, 0x02, 0x40, 0x01, 0x20, 0x70, 0x47, 0x9F, 0xED, 0xCC, 0x0A, + 0xCC, 0x48, 0x80, 0xED, 0x00, 0x0A, + 0x9F, 0xED, 0xCC, 0x0A, + 0x80, 0xED, 0x01, 0x0A, + 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0xC9, 0x4C, 0x94, 0xB0, 0x20, 0x46, 0xFF, 0xF7, 0xB9, 0xF9, 0x01, 0x22, 0x4F, 0xF0, 0xC2, 0x41, 0xC6, 0x48, 0xFE, 0xF7, 0xF1, 0xFD, 0x68, 0x46, 0xFF, 0xF7, 0x81, 0xF9, 0x10, 0x21, 0x0F, 0x20, 0xAD, 0xF8, + 0x2A, 0x00, 0xAD, 0xF8, 0x0C, 0x10, 0x80, 0x20, 0xAD, 0xF8, 0x0A, + 0x10, 0xAD, 0xF8, 0x0E, 0x10, 0xAD, 0xF8, 0x10, 0x10, 0x8D, 0xF8, 0x01, 0x00, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x07, 0xF9, 0x14, 0xB0, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xD9, 0xFF, 0xFF, 0xF7, 0xCC, 0xFF, 0xB3, 0x48, 0x4F, 0xF4, 0xFA, + 0x61, 0x08, 0x30, 0xC1, 0x80, 0x00, 0x21, 0x41, 0x70, 0x10, 0xBD, 0xAF, 0x48, 0x08, 0x30, 0x40, 0x78, 0x70, 0x47, 0x70, 0xB5, 0x06, 0x46, 0x2D, 0xED, 0x04, 0x8B, 0x82, 0xB0, 0x00, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0xAD, 0x48, 0x41, 0x79, 0x9F, + 0xED, 0xAD, 0x8B, 0x06, 0xFB, 0x06, 0xF5, 0xA5, 0xEB, 0x45, 0x10, 0x00, 0xEB, 0x80, 0x00, 0x84, 0x00, 0xAB, 0x4D, 0x9F, 0xED, 0xAB, 0x9B, 0x01, 0x29, 0x0D, 0xD1, 0x6A, 0x46, 0x31, 0x46, 0x01, 0x20, 0x00, 0xF0, 0x49, 0xFA, 0x9D, 0xF9, 0x00, + 0x30, 0x00, 0x2B, 0x1D, 0xDA, 0x01, 0x22, 0xA6, 0x49, 0xA7, 0x48, 0xEA, 0xF5, 0xF3, 0xF9, 0x30, 0x46, 0xF0, 0xF7, 0xD0, 0xF9, 0x53, 0xEC, 0x18, 0x2B, 0x00, 0xF0, 0xEF, 0xFC, 0x41, 0xEC, 0x18, 0x0B, 0x94, 0xFB, 0xF5, 0xF0, 0xF0, 0xF7, 0xAF, + 0xF9, 0x53, 0xEC, 0x18, 0x2B, 0xF0, 0xF7, 0x03, 0xF9, 0x53, 0xEC, 0x19, 0x2B, 0xF0, 0xF7, 0xD1, 0xF9, 0x00, 0xF0, 0xAD, 0xFC, 0x00, 0xEE, 0x10, 0x0A, + 0x02, 0xB0, 0xBC, 0xEE, 0xC0, 0x0A, + 0xBD, 0xEC, 0x04, 0x8B, 0x10, 0xEE, 0x10, 0x0A, + 0x80, 0xB2, 0x70, 0xBD, 0x38, 0xB5, 0xFF, 0xF7, 0xB5, 0xFF, 0x88, 0x4C, 0x40, 0xF6, 0x1C, 0x42, 0x08, 0x34, 0x64, 0x21, 0xA0, 0x80, 0x03, 0x46, 0x90, 0x42, 0x01, 0xD3, 0xA1, 0x70, 0x2D, 0xE0, 0x40, 0xF6, 0xB8, 0x30, 0x83, 0x42, 0x08, 0xD3, + 0xA3, 0xF6, 0xB8, 0x30, 0x00, 0xEB, 0x80, 0x00, 0x80, 0x00, 0x90, 0xFB, 0xF1, 0xF0, 0x50, 0x30, 0x1F, 0xE0, 0x40, 0xF6, 0xC4, 0x10, 0x83, 0x42, 0x09, 0xD3, 0x32, 0x21, 0xA3, 0xF6, 0xC4, 0x10, 0x48, 0x43, 0x4F, 0xF4, 0xFA, 0x71, 0x90, 0xFB, + 0xF1, 0xF0, 0x1E, 0x30, 0x11, 0xE0, 0x40, 0xF6, 0x98, 0x00, 0x83, 0x42, 0x09, 0xD3, 0xA3, 0xF6, 0x98, 0x00, 0xC0, 0xEB, 0x00, 0x10, 0x4F, 0xF4, 0x96, 0x71, 0x90, 0xFB, 0xF1, 0xF0, 0x0F, 0x30, 0x03, 0xE0, 0xC3, 0xEB, 0x03, 0x11, 0xB1, 0xFB, + 0xF0, 0xF0, 0xA0, 0x70, 0xA0, 0x78, 0x00, 0x90, 0x74, 0x49, 0x75, 0x48, 0x02, 0x22, 0x60, 0x39, 0x40, 0x1E, 0xEA, 0xF5, 0x8C, 0xF9, 0xA0, 0x88, 0xE1, 0x88, 0x88, 0x42, 0x01, 0xD2, 0x01, 0x20, 0x00, 0xE0, 0x00, 0x20, 0x60, 0x70, 0x38, 0xBD, + 0x2D, 0xE9, 0xFC, 0x5F, 0x00, 0x27, 0xDF, 0xF8, 0x8C, 0x81, 0x89, 0x46, 0x82, 0x46, 0x00, 0x97, 0x4F, 0xF6, 0xFF, 0x76, 0x3D, 0x46, 0x01, 0x22, 0x10, 0x21, 0x40, 0x46, 0x01, 0x97, 0xFF, 0xF7, 0xE9, 0xF8, 0x01, 0x22, 0x02, 0x21, 0x40, 0x46, + 0xFF, 0xF7, 0xF7, 0xF8, 0x00, 0x20, 0x41, 0xF2, 0x88, 0x32, 0xD8, 0xF8, 0x0C, 0x10, 0x11, 0xF4, 0x80, 0x1F, 0x03, 0xD1, 0x01, 0x46, 0x40, 0x1C, 0x91, 0x42, 0xF6, 0xD3, 0xD8, 0xF8, 0x0C, 0x00, 0x40, 0xF4, 0x80, 0x50, 0xC8, 0xF8, 0x0C, 0x00, + 0xC3, 0x46, 0x00, 0x24, 0xE8, 0x46, 0x21, 0x46, 0x58, 0x46, 0xFF, 0xF7, 0xD3, 0xF8, 0x28, 0xF8, 0x14, 0x00, 0x07, 0x44, 0xB0, 0x42, 0x00, 0xD2, 0x06, 0x46, 0xA8, 0x42, 0x00, 0xD9, 0x05, 0x46, 0x64, 0x1C, 0xE4, 0xB2, 0x04, 0x2C, 0xEE, 0xD3, + 0xB8, 0x1B, 0x40, 0x1B, 0xC0, 0xF3, 0x4F, 0x00, 0xFF, 0xF7, 0x70, 0xFF, 0x41, 0x49, 0x08, 0x31, 0xB9, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0xBA, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0x8A, 0x88, 0xA9, 0xF8, 0x00, 0x20, 0x8A, 0x78, 0xAA, 0xF8, 0x00, 0x20, + 0x8B, 0x88, 0x44, 0x49, 0x44, 0x48, 0x01, 0x22, 0x2C, 0x39, 0x40, 0x1E, 0xEA, 0xF5, 0x2B, 0xF9, 0xBD, 0xE8, 0xFC, 0x9F, 0x05, 0x22, 0x01, 0x21, 0x26, 0x20, 0xEF, 0xF7, 0xAD, 0xB8, 0x2D, 0xE9, 0xFC, 0x47, 0x80, 0x46, 0x03, 0x46, 0x3B, 0x49, + 0x3B, 0x48, 0x01, 0x22, 0x2C, 0x31, 0x40, 0x1E, 0xEA, 0xF5, 0x19, 0xF9, 0x2D, 0x4D, 0x01, 0x26, 0x06, 0x27, 0x00, 0x20, 0x08, 0x35, 0x2F, 0x4C, 0x4F, 0xF4, 0xFA, 0x69, 0xB8, 0xF1, 0x16, 0x0F, 0x29, 0xD0, 0xB8, 0xF1, 0x17, 0x0F, 0x26, 0xD0, + 0xB8, 0xF1, 0x18, 0x0F, 0x21, 0xD1, 0x80, 0x46, 0xAD, 0xF8, 0x04, 0x00, 0xA0, 0x7C, 0x06, 0x28, 0x28, 0xD0, 0xE8, 0x78, 0x0A, + 0x21, 0x40, 0x1C, 0xC0, 0xB2, 0xB0, 0xFB, 0xF1, 0xF2, 0xE8, 0x70, 0x01, 0xFB, 0x12, 0x00, 0x00, 0x28, 0x10, 0xD1, 0x69, 0x46, 0x01, 0xA8, 0xFF, 0xF7, 0x70, 0xFF, 0xBD, 0xF8, 0x00, 0x00, 0x48, 0x45, 0x08, 0xD2, 0x6E, 0x70, 0xA0, 0x7C, 0x01, + 0x28, 0x09, 0xD0, 0x03, 0x28, 0x0B, 0xD0, 0x04, 0x28, 0x09, 0xD0, 0xA7, 0x74, 0xBD, 0xE8, 0xFC, 0x87, 0xAD, 0xF8, 0x04, 0x00, 0xE9, 0xE7, 0x05, 0x20, 0xED, 0xF7, 0x1A, 0xFE, 0xF6, 0xE7, 0x05, 0x20, 0xED, 0xF7, 0x3A, 0xFE, 0xF2, 0xE7, 0xFF, + 0xF7, 0xAE, 0xFF, 0x69, 0x46, 0x01, 0xA8, 0xFF, 0xF7, 0x50, 0xFF, 0x15, 0x48, 0xBD, 0xF8, 0x00, 0x10, 0x40, 0xF6, 0x98, 0x02, 0x40, 0x1C, 0x91, 0x42, 0x05, 0xD3, 0x10, 0x49, 0x00, 0x22, 0x84, 0xF8, 0x12, 0x80, 0x54, 0x31, 0x02, 0xE0, 0x0D, + 0x49, 0x00, 0x22, 0x74, 0x31, 0xEA, 0xF5, 0xC0, 0xF8, 0xD8, 0xE7, 0x48, 0xBF, 0x4D, 0x3F, 0x4C, 0x13, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x00, 0x00, 0x0C, 0x70, 0xF2, 0x20, 0x00, 0xCD, 0xE9, 0xB2, 0x98, 0xD8, + 0x7C, 0xEF, 0x3F, 0x00, 0xE1, 0xF5, 0x05, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5F, 0x40, 0xEC, 0x3D, 0x80, 0x08, 0x01, 0x30, 0x10, 0x21, 0x10, 0xB5, 0x4A, 0x78, 0x02, 0x80, 0x0B, 0x78, 0x03, 0xEB, 0x02, 0x22, 0x02, 0x80, 0x0A, + 0x79, 0xD4, 0x09, 0x84, 0x72, 0x0A, + 0x79, 0x42, 0x60, 0xCB, 0x78, 0x03, 0xEB, 0x02, 0x22, 0x42, 0x60, 0x8B, 0x78, 0x03, 0xEB, 0x02, 0x23, 0x43, 0x60, 0x8A, 0x79, 0x02, 0x81, 0x49, 0x79, 0x01, 0xEB, 0x02, 0x21, 0x01, 0x81, 0x02, 0xD0, 0x43, 0xF0, 0x7F, 0x41, 0x41, 0x60, 0x10, + 0xBD, 0x01, 0xFB, 0x01, 0xF2, 0x00, 0xEE, 0x10, 0x2A, 0xB8, 0xEE, 0xC0, 0x0A, + 0x9F, 0xED, 0x91, 0x1A, 0xB0, 0xF9, 0x00, 0x20, 0xC0, 0xEE, 0x01, 0x0A, + 0x00, 0xEE, 0x10, 0x2A, 0x42, 0x68, 0xB8, 0xEE, 0xC0, 0x0A, + 0x4A, 0x43, 0x20, 0xEE, 0x80, 0x0A, + 0x00, 0xEE, 0x90, 0x2A, 0xB8, 0xEE, 0xE0, 0x1A, 0xDF, 0xED, 0x89, 0x1A, 0xB0, 0xF9, 0x08, 0x00, 0xC1, 0xEE, 0x21, 0x0A, + 0xF2, 0xEE, 0x04, 0x1A, 0x30, 0xEE, 0x80, 0x0A, + 0x00, 0xEE, 0x90, 0x0A, + 0xB8, 0xEE, 0xE0, 0x1A, 0xC1, 0xEE, 0x21, 0x0A, + 0x30, 0xEE, 0x80, 0x0A, + 0x70, 0x47, 0x70, 0xB5, 0x00, 0x24, 0x7F, 0x49, 0x80, 0x4D, 0x22, 0x46, 0x50, 0x18, 0xD0, 0xF8, 0x91, 0x08, 0xAB, 0x18, 0x52, 0x1C, 0xD2, 0xB2, 0x58, 0x70, 0x1F, 0x2A, 0xF6, 0xD3, 0x55, 0x20, 0x28, 0x70, 0xAA, 0x20, 0x85, 0xF8, 0x20, 0x00, + 0x68, 0x7F, 0x6F, 0xF0, 0x01, 0x02, 0x51, 0x10, 0xFF, 0x28, 0x0A, + 0xD1, 0xA8, 0x7F, 0xFF, 0x28, 0x02, 0xD0, 0x80, 0xB1, 0x03, 0xD0, 0x04, 0xE0, 0xE8, 0x7F, 0xFF, 0x28, 0x08, 0xD0, 0xE8, 0x7F, 0x70, 0xB1, 0xE8, 0x7F, 0xFF, 0x28, 0x35, 0xD0, 0x68, 0x78, 0xFF, 0x28, 0x1F, 0xD1, 0x15, 0xE0, 0x6F, 0xF0, 0x02, + 0x00, 0x1F, 0xE0, 0xE8, 0x7F, 0xFF, 0x28, 0xF5, 0xD1, 0x10, 0x46, 0x1A, 0xE0, 0xE8, 0x7D, 0xFF, 0x28, 0xF0, 0xD1, 0x28, 0x7E, 0xFF, 0x28, 0xED, 0xD1, 0x68, 0x7E, 0xFF, 0x28, 0xEA, 0xD1, 0xA8, 0x7E, 0xFF, 0x28, 0xE7, 0xD1, 0x08, 0x46, 0x0C, + 0xE0, 0x28, 0x7A, 0xFF, 0x28, 0x05, 0xD1, 0xE8, 0x7B, 0xFF, 0x28, 0x02, 0xD1, 0xA8, 0x7D, 0xFF, 0x28, 0x12, 0xD0, 0x95, 0xF9, 0x1F, 0x00, 0x5A, 0x28, 0x0E, 0xD0, 0x5B, 0x4B, 0x01, 0x24, 0x90, 0x42, 0x18, 0x70, 0x0B, 0xD0, 0x58, 0x4E, 0x08, + 0x36, 0x88, 0x42, 0x2B, 0xD0, 0x80, 0xB3, 0x01, 0x28, 0x2F, 0xD0, 0x5A, 0x20, 0x18, 0x70, 0x00, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x52, 0x49, 0x51, 0x4A, 0x2E, 0x31, 0x50, 0x7A, 0x08, 0x80, 0x93, 0x7A, 0x03, 0xEB, 0x00, 0x20, 0x08, 0x80, 0xD0, + 0x7A, 0xC0, 0x09, 0x88, 0x72, 0xD0, 0x7A, 0x48, 0x60, 0x13, 0x7B, 0x03, 0xEB, 0x00, 0x20, 0x48, 0x60, 0x53, 0x7B, 0x03, 0xEB, 0x00, 0x20, 0x48, 0x60, 0x90, 0x7B, 0x08, 0x81, 0xD2, 0x7B, 0x02, 0xEB, 0x00, 0x20, 0x08, 0x81, 0x88, 0x7A, 0x01, + 0x28, 0xDE, 0xD1, 0x48, 0x68, 0x40, 0xF0, 0x7F, 0x40, 0x48, 0x60, 0xD9, 0xE7, 0x40, 0x48, 0x31, 0x46, 0x2E, 0x30, 0xFF, 0xF7, 0x2E, 0xFF, 0xD3, 0xE7, 0xFF, 0xE7, 0x3C, 0x48, 0x69, 0x1C, 0x22, 0x30, 0xFF, 0xF7, 0x27, 0xFF, 0x3A, 0x48, 0x31, + 0x46, 0x2E, 0x30, 0xFF, 0xF7, 0x22, 0xFF, 0x37, 0x49, 0x0F, 0x31, 0x01, 0xF1, 0x2B, 0x00, 0xFF, 0xF7, 0x1C, 0xFF, 0x34, 0x49, 0x16, 0x31, 0x01, 0xF1, 0x30, 0x00, 0xFF, 0xF7, 0x16, 0xFF, 0x31, 0x49, 0xA8, 0x7F, 0x6A, 0x7F, 0x89, 0x1E, 0x02, + 0xEB, 0x00, 0x20, 0x08, 0x80, 0xB4, 0xE7, 0x70, 0xB5, 0x00, 0x23, 0x2D, 0xED, 0x02, 0x8B, 0x4F, 0xF0, 0xFF, 0x34, 0x9F, 0xED, 0x2C, 0x8A, 0x13, 0x70, 0x43, 0x1E, 0xB0, 0xEE, 0x48, 0x0A, + 0x04, 0x2B, 0x21, 0xD2, 0x00, 0x29, 0x1F, 0xDB, 0xB1, 0xF5, 0x80, 0x5F, 0x1C, 0xDA, 0x24, 0x4B, 0x1D, 0x78, 0x55, 0x2D, 0x05, 0xD0, 0x93, 0xF8, 0x20, 0x30, 0xAA, 0x2B, 0x01, 0xD0, 0xFE, 0x20, 0x04, 0xE0, 0x20, 0x4B, 0x1B, 0x78, 0x01, 0x2B, + 0x04, 0xD0, 0xFC, 0x20, 0x10, 0x70, 0xBD, 0xEC, 0x02, 0x8B, 0x70, 0xBD, 0x01, 0x28, 0x09, 0xD0, 0x02, 0x28, 0x0A, + 0xD0, 0xA1, 0xF5, 0x00, 0x61, 0x03, 0x28, 0x12, 0xD0, 0x04, 0x28, 0x13, 0xD0, 0x14, 0x70, 0xF0, 0xE7, 0x14, 0x48, 0x22, 0x30, 0x01, 0xE0, 0x13, 0x48, 0x2E, 0x30, 0xFF, 0xF7, 0xF4, 0xFE, 0xB5, 0xEE, 0xC0, 0x0A, + 0xF1, 0xEE, 0x10, 0xFA, 0xE4, 0xD2, 0xB0, 0xEE, 0x48, 0x0A, + 0xE1, 0xE7, 0x0D, 0x48, 0x3A, 0x30, 0x01, 0xE0, 0x0B, 0x48, 0x46, 0x30, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0x70, 0x40, 0xE1, 0xE6, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x05, 0x48, 0x80, 0x1E, 0x00, 0x88, + 0x70, 0x47, 0x00, 0x00, 0x20, 0xBC, 0xBE, 0x4C, 0x00, 0x50, 0xC3, 0x47, 0x00, 0x20, 0x20, 0x00, 0x22, 0x18, 0x21, 0x00, 0x89, 0xE7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x49, 0x10, 0xB5, 0xA1, 0xF1, 0x7C, 0x02, 0x0A, + 0x4C, 0xC2, 0xE9, 0x37, 0x12, 0x37, 0x21, 0x06, 0xE0, 0x00, 0xEB, 0x10, 0x43, 0x42, 0xF8, 0x21, 0x30, 0x07, 0x4B, 0x00, 0xFB, 0x03, 0x40, 0x0B, 0x1E, 0xA1, 0xF1, 0x01, 0x01, 0xF4, 0xDC, 0x10, 0xBD, 0x01, 0x20, 0xE8, 0xE7, 0x00, 0x00, 0xF0, + 0x18, 0x21, 0x00, 0xE1, 0x19, 0xD6, 0x66, 0xCD, 0x0D, 0x01, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x0E, 0x48, 0x00, 0x68, 0x28, 0xB1, 0x4F, 0xF0, 0xFF, 0x31, 0x08, 0xF6, 0x65, 0xFE, 0x00, 0x28, 0x10, 0xD0, 0x0B, 0x48, 0x04, 0x70, 0x4F, 0xF4, 0x00, + 0x10, 0x90, 0xF8, 0x50, 0x03, 0x41, 0x07, 0x09, 0xD0, 0xEF, 0xF3, 0x11, 0x81, 0x07, 0x4A, 0x40, 0x07, 0x00, 0x0E, 0x80, 0xF3, 0x11, 0x88, 0x11, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x72, 0xB6, 0xFB, 0xE7, 0x00, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, + 0x04, 0x20, 0x00, 0xAC, 0x0C, 0x20, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x00, 0x24, 0x07, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x00, 0x28, 0x09, 0xD0, 0x28, 0x46, 0xEC, 0xF5, 0x9A, 0xFC, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x00, 0xF0, 0x03, + 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x50, 0x03, 0x40, 0x07, 0x0C, 0xD0, 0x07, 0x48, 0x00, 0x78, 0x80, 0xF3, 0x11, 0x88, 0x06, 0x48, 0x00, 0x68, 0x08, 0xB1, 0x08, 0xF6, 0x37, 0xFE, 0x04, + 0x49, 0xFF, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x62, 0xB6, 0xF4, 0xE7, 0xAC, 0x0C, 0x20, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, 0x04, 0x20, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x1A, 0x4F, 0x91, 0x46, 0x08, 0x9E, 0x3A, 0x78, 0x98, 0x46, 0x01, 0x2A, 0x03, + 0xD0, 0x4F, 0xF0, 0xFF, 0x30, 0xBD, 0xE8, 0xF0, 0x87, 0x38, 0xB1, 0xF0, 0x29, 0x05, 0xDB, 0xB9, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0xB8, 0xF1, 0x39, 0x0F, 0x02, 0xDA, 0x6F, 0xF0, 0x01, 0x00, 0xF1, 0xE7, 0x0F, 0x49, 0x0C, 0x31, 0xEF, 0xF7, 0xFF, + 0xFB, 0x07, 0xEB, 0x40, 0x05, 0x00, 0x24, 0xEC, 0x35, 0xB8, 0x60, 0x07, 0xEB, 0x44, 0x11, 0x28, 0x46, 0x01, 0xF5, 0x2F, 0x71, 0xEF, 0xF7, 0xC1, 0xFC, 0x64, 0x1C, 0xE4, 0xB2, 0x10, 0x3D, 0x0F, 0x2C, 0xF3, 0xD3, 0xEF, 0xF7, 0xBA, 0xFB, 0x41, + 0x46, 0x48, 0x46, 0x00, 0xF0, 0x16, 0xF8, 0x06, 0xB1, 0x30, 0x60, 0xF0, 0x20, 0xD2, 0xE7, 0x64, 0x13, 0x21, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x24, 0x71, 0x05, 0x48, 0x3C, 0xF6, 0x9E, 0xF9, 0x03, 0x48, 0x4F, 0xF4, 0x80, 0x71, 0x0C, 0x38, 0x81, + 0x60, 0x01, 0x21, 0x01, 0x70, 0x10, 0xBD, 0x70, 0x13, 0x21, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x9B, 0xB0, 0xAD, 0x20, 0x38, 0x70, 0x00, 0x20, 0x78, 0x70, 0xB8, 0x70, 0x00, 0x90, 0x01, 0x90, 0x06, 0x46, 0x04, 0x46, 0x02, 0x90, 0x78, + 0x78, 0x8D, 0xF8, 0x00, 0x00, 0xB8, 0x78, 0x8D, 0xF8, 0x01, 0x00, 0x10, 0x20, 0x3D, 0x1D, 0xDF, 0xF8, 0x78, 0x81, 0x00, 0x21, 0xEA, 0x46, 0x08, 0xEB, 0x81, 0x0C, 0x24, 0x1D, 0xDC, 0xF8, 0x9C, 0x22, 0x10, 0x2C, 0x66, 0xF3, 0x1F, 0x12, 0x16, + 0x46, 0x0A, + 0xD3, 0xA4, 0xF1, 0x08, 0x02, 0x26, 0xFA, 0x02, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x10, 0x3C, 0x26, 0xFA, 0x04, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x0A, + 0xEB, 0xD0, 0x02, 0x00, 0x1D, 0x13, 0x78, 0x49, 0x1C, 0x1B, 0x01, 0x13, 0x70, 0x9C, 0xF8, 0x9C, 0xC2, 0xC9, 0xB2, 0x0C, 0xF0, 0x0F, 0x0C, 0x43, 0xEA, 0x0C, 0x03, 0xC1, 0x46, 0x13, 0x70, 0xC0, 0xB2, 0x08, 0x29, 0xD7, 0xD3, 0x41, 0x07, 0x08, + 0xD0, 0x0A, + 0xEB, 0xD0, 0x01, 0x00, 0xF0, 0x07, 0x03, 0x0A, + 0x78, 0xC3, 0xF1, 0x08, 0x03, 0x9A, 0x40, 0x0A, + 0x70, 0x52, 0x46, 0x0F, 0x21, 0xC3, 0x08, 0x00, 0xF0, 0x07, 0x0C, 0x00, 0x20, 0xDF, 0xF8, 0x04, 0xA1, 0x06, 0xE0, 0x12, 0xF8, 0x00, 0x80, 0x40, 0x1C, 0x88, 0xEA, 0x01, 0x08, 0x1A, 0xF8, 0x08, 0x10, 0x98, 0x42, 0xF6, 0xD3, 0x10, 0x5C, 0x00, + 0x22, 0x0B, 0xE0, 0x80, 0xEA, 0x01, 0x03, 0xDB, 0x09, 0x00, 0xD0, 0x1D, 0x23, 0x40, 0x06, 0x01, 0xF0, 0x7F, 0x01, 0x00, 0x0E, 0x83, 0xEA, 0x41, 0x01, 0x52, 0x1C, 0x62, 0x45, 0xF1, 0xD3, 0xF9, 0x70, 0x08, 0x21, 0x03, 0xA8, 0x00, 0xF0, 0x63, + 0xF8, 0x00, 0x20, 0x4F, 0xF0, 0x01, 0x0E, 0x0D, 0xF1, 0x0C, 0x0C, 0x0D, 0xF1, 0x2C, 0x0A, + 0x0D, 0xF1, 0x4C, 0x0B, 0x1C, 0xF8, 0x20, 0x10, 0x0E, 0xFA, 0x01, 0xF2, 0x09, 0xEB, 0x80, 0x01, 0x52, 0x1E, 0xD1, 0xF8, 0x9C, 0x12, 0xC1, 0xF1, 0x0F, 0x08, 0x02, 0xFA, 0x08, 0xF2, 0x10, 0x31, 0x4A, 0xF8, 0x20, 0x20, 0x0E, 0xFA, 0x01, 0xF3, + 0x4B, 0xF8, 0x20, 0x30, 0x40, 0x1C, 0xC0, 0xB2, 0x08, 0x28, 0xE7, 0xD3, 0x00, 0x21, 0xE6, 0x46, 0x00, 0x20, 0x5E, 0xF8, 0x20, 0x20, 0xE2, 0xB1, 0x09, 0xEB, 0x41, 0x13, 0x03, 0xEB, 0x80, 0x03, 0x5A, 0xF8, 0x20, 0xC0, 0xD3, 0xF8, 0xBC, 0x82, + 0x5B, 0xF8, 0x20, 0x30, 0x96, 0x40, 0x43, 0x44, 0xAC, 0xFB, 0x03, 0xC3, 0x1E, 0x43, 0x14, 0x44, 0x10, 0x2C, 0x0A, + 0xD3, 0xA4, 0xF1, 0x08, 0x02, 0x26, 0xFA, 0x02, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x10, 0x3C, 0x26, 0xFA, 0x04, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x40, 0x1C, 0xC0, 0xB2, 0x08, 0x28, 0xDB, 0xD3, 0x49, 0x1C, 0xC9, 0xB2, 0x0F, 0x29, 0xD6, 0xD3, 0x04, + 0xE0, 0x08, 0x3C, 0x26, 0xFA, 0x04, 0xF0, 0x05, 0xF8, 0x01, 0x0B, 0x08, 0x2C, 0xF8, 0xD2, 0x24, 0xB1, 0xC4, 0xF1, 0x08, 0x00, 0x86, 0x40, 0x05, 0xF8, 0x01, 0x6B, 0x1B, 0xB0, 0xE8, 0x1B, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x00, 0x64, 0x13, 0x21, + 0x00, 0xA4, 0xE4, 0x20, 0x00, 0xF0, 0xB5, 0x00, 0x23, 0x88, 0xB0, 0x42, 0x4C, 0x42, 0x4E, 0x19, 0x46, 0x5D, 0x1F, 0xEC, 0x46, 0x04, 0xEB, 0x81, 0x02, 0xD2, 0xF8, 0x9C, 0x22, 0x02, 0xB3, 0x56, 0xF8, 0x21, 0x70, 0xD2, 0x1B, 0x00, 0x2A, 0x00, + 0xDD, 0x52, 0x10, 0x4C, 0xF8, 0x21, 0x20, 0x9A, 0x42, 0x00, 0xDD, 0x13, 0x46, 0x49, 0x1C, 0xC9, 0xB2, 0x08, 0x29, 0xEB, 0xD3, 0x00, 0x21, 0x0A, + 0x46, 0x5B, 0x1C, 0x11, 0x44, 0x00, 0x22, 0x03, 0xF1, 0x0F, 0x07, 0x1E, 0x46, 0x14, 0x46, 0x5B, 0x1E, 0x5C, 0xF8, 0x24, 0x50, 0xB5, 0x42, 0x08, 0xDD, 0xBD, 0x42, 0x06, 0xDA, 0x52, 0x1C, 0x07, 0xE0, 0x4C, 0xF8, 0x21, 0x50, 0x5C, 0xF8, 0x21, + 0x20, 0xE1, 0xE7, 0xB5, 0x42, 0x00, 0xD1, 0x92, 0x1C, 0x64, 0x1C, 0xE4, 0xB2, 0x08, 0x2C, 0xEB, 0xD3, 0x8C, 0x18, 0x1A, 0x2C, 0xE1, 0xDB, 0x0A, + 0x44, 0x1A, 0x2A, 0x01, 0xD1, 0x11, 0x46, 0x5B, 0x1E, 0x00, 0x22, 0x9E, 0x1C, 0x17, 0x46, 0x10, 0x25, 0x5C, 0xF8, 0x22, 0x40, 0xB4, 0x42, 0x02, 0xDA, 0x40, 0xF8, 0x22, 0x70, 0x06, 0xE0, 0xE4, 0x1A, 0x40, 0xF8, 0x22, 0x40, 0x10, 0x2C, 0x01, + 0xDD, 0x40, 0xF8, 0x22, 0x50, 0x52, 0x1C, 0xD2, 0xB2, 0x08, 0x2A, 0xED, 0xD3, 0x00, 0x22, 0x02, 0x25, 0x5B, 0x1C, 0x15, 0xE0, 0x50, 0xF8, 0x22, 0x40, 0xA6, 0x1E, 0x0E, 0x2E, 0x04, 0xD2, 0x64, 0x1C, 0x40, 0xF8, 0x22, 0x40, 0x49, 0x1C, 0x09, + 0xE0, 0x5C, 0xF8, 0x22, 0x40, 0x9C, 0x42, 0x05, 0xD1, 0x4C, 0x1C, 0x1A, 0x2C, 0x02, 0xDA, 0x40, 0xF8, 0x22, 0x50, 0x89, 0x1C, 0x52, 0x1C, 0xD2, 0xB2, 0x1A, 0x29, 0x01, 0xDA, 0x08, 0x2A, 0xE5, 0xD3, 0x00, 0x22, 0x09, 0xE0, 0x50, 0xF8, 0x22, + 0x30, 0x10, 0x2B, 0x03, 0xDA, 0x5B, 0x1C, 0x40, 0xF8, 0x22, 0x30, 0x49, 0x1C, 0x52, 0x1C, 0xD2, 0xB2, 0x1A, 0x29, 0x01, 0xDA, 0x08, 0x2A, 0xF1, 0xD3, 0x08, 0xB0, 0xF0, 0xBD, 0x64, 0x13, 0x21, 0x00, 0xA4, 0xE5, 0x20, 0x00, 0x21, 0xF0, 0x00, + 0x42, 0xA2, 0xF1, 0x60, 0x52, 0xB2, 0xF5, 0x80, 0x1F, 0x01, 0xF0, 0x00, 0x43, 0x28, 0xBF, 0xD2, 0xF1, 0x7F, 0x6C, 0x0B, 0xD9, 0x5F, 0xEA, 0x00, 0x1C, 0x43, 0xEA, 0xC2, 0x02, 0x42, 0xEB, 0x50, 0x70, 0x18, 0xBF, 0x70, 0x47, 0x28, 0xBF, 0x20, + 0xF0, 0x01, 0x00, 0x70, 0x47, 0xB2, 0xF5, 0x80, 0x1F, 0xBC, 0xBF, 0x18, 0x46, 0x70, 0x47, 0x4F, 0xEA, 0x41, 0x0C, 0x1C, 0xF5, 0x00, 0x1F, 0x02, 0xD2, 0x08, 0x46, 0xEF, 0xF7, 0xEC, 0xBD, 0x70, 0xB5, 0x00, 0xF0, 0xB4, 0xF8, 0x00, 0x00, 0x00, + 0x89, 0xFF, 0xF7, 0xF6, 0xBF, 0x4F, 0xF0, 0x00, 0x40, 0xA0, 0xF5, 0x80, 0x00, 0x70, 0x47, 0x00, 0x00, 0xDF, 0xF8, 0x48, 0xC1, 0x70, 0xB5, 0x1C, 0xEA, 0x11, 0x1E, 0x1E, 0xBF, 0x1C, 0xEA, 0x13, 0x15, 0x9E, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, + 0x0F, 0x00, 0xF0, 0x6F, 0x80, 0x81, 0xEA, 0x03, 0x04, 0x23, 0xEA, 0x4C, 0x13, 0x4E, 0xEA, 0xD4, 0x7E, 0x21, 0xEA, 0x4C, 0x11, 0x41, 0xF4, 0x80, 0x11, 0x43, 0xF4, 0x80, 0x13, 0xAE, 0x44, 0xA1, 0xFB, 0x02, 0x4C, 0xA0, 0xFB, 0x03, 0x65, 0xAE, + 0xF1, 0x7F, 0x7E, 0x36, 0x19, 0x55, 0xEB, 0x0C, 0x05, 0xA1, 0xFB, 0x03, 0x4C, 0x4C, 0xF1, 0x00, 0x03, 0xA0, 0xFB, 0x02, 0x1C, 0x16, 0xEB, 0x0C, 0x06, 0x65, 0x41, 0x53, 0xF1, 0x00, 0x03, 0x09, 0x42, 0x18, 0xBF, 0x46, 0xF0, 0x01, 0x06, 0x13, + 0xF4, 0x00, 0x7F, 0x0B, 0xD1, 0x4F, 0xEA, 0x03, 0x31, 0x4F, 0xEA, 0x05, 0x30, 0x34, 0x03, 0x41, 0xEA, 0x15, 0x51, 0x40, 0xEA, 0x16, 0x50, 0x6F, 0xF0, 0x03, 0x02, 0x0A, + 0xE0, 0x4F, 0xEA, 0xC3, 0x21, 0x4F, 0xEA, 0xC5, 0x20, 0xF4, 0x02, 0x41, 0xEA, 0x55, 0x51, 0x40, 0xEA, 0x56, 0x50, 0x6F, 0xF0, 0x02, 0x02, 0x02, 0xEB, 0x2E, 0x42, 0x01, 0xEB, 0x02, 0x55, 0x85, 0xEA, 0xCE, 0x71, 0x0A, + 0xD0, 0x5F, 0xEA, 0x44, 0x0C, 0x18, 0xBF, 0x24, 0xF0, 0x00, 0x44, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xF1, 0x00, 0x01, 0x20, 0xEA, 0xD4, 0x70, 0x40, 0xF2, 0xFE, 0x7C, 0x62, 0x45, 0x00, 0xD2, 0x70, 0xBD, 0xA8, 0x42, 0x14, 0xBF, 0x4F, 0xF0, 0x80, + 0x44, 0x4F, 0xF0, 0x40, 0x44, 0x00, 0x2E, 0x08, 0xBF, 0x00, 0x24, 0xBE, 0xF1, 0x80, 0x6F, 0xA8, 0xBF, 0xA1, 0xF1, 0xC0, 0x41, 0xBD, 0xE8, 0x70, 0x40, 0x80, 0xF2, 0x82, 0x80, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0xF1, 0xC0, 0x41, 0x01, 0xF0, 0x00, + 0x41, 0x70, 0x47, 0x9E, 0xEA, 0x0C, 0x0F, 0x0C, 0xEA, 0x13, 0x15, 0x18, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, 0x06, 0xD0, 0x4F, 0xF0, 0x00, 0x00, 0x81, 0xEA, 0x03, 0x0E, 0x0E, 0xF0, 0x00, 0x41, 0x70, 0xBD, 0x00, 0xF0, 0x1C, 0xF8, 0x89, 0x00, 0x01, + 0x3E, 0x00, 0xF0, 0x07, 0xB8, 0x00, 0xF0, 0x09, 0xB8, 0x4F, 0xEA, 0x43, 0x0C, 0x5F, 0xEA, 0x5C, 0x5C, 0x08, 0xD0, 0x81, 0xEA, 0x03, 0x01, 0x00, 0xF0, 0x5B, 0xB8, 0x4F, 0xEA, 0x41, 0x0C, 0x5F, 0xEA, 0x5C, 0x5C, 0xF6, 0xD1, 0x4F, 0xF0, 0x00, + 0x00, 0x01, 0x49, 0x70, 0x47, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0xF8, 0x7F, 0x0E, 0xF1, 0x02, 0x0E, 0x2E, 0xF0, 0x03, 0x0E, 0x5E, 0xF8, 0x04, 0x6B, 0x36, 0x42, 0x05, 0xD4, 0x01, 0x2A, 0x43, 0xEB, 0x03, 0x05, 0x15, 0xF5, 0x00, 0x1F, 0x12, + 0xD8, 0x01, 0x28, 0x41, 0xEB, 0x01, 0x0C, 0x1C, 0xF5, 0x00, 0x1F, 0x0C, 0xD8, 0x0E, 0xD1, 0x4F, 0xEA, 0xD1, 0x7C, 0x15, 0xF5, 0x00, 0x1F, 0x0C, 0xEB, 0x4C, 0x0C, 0x0C, 0xF1, 0x02, 0x0C, 0x08, 0xBF, 0x4C, 0xEB, 0xD3, 0x7C, 0x04, 0xE0, 0x4F, + 0xF0, 0x08, 0x0C, 0x01, 0xE0, 0x4F, 0xEA, 0xD3, 0x7C, 0x0C, 0xEB, 0x4C, 0x05, 0x26, 0xFA, 0x05, 0xF6, 0x06, 0xF0, 0x07, 0x06, 0xB6, 0xF1, 0x04, 0x0C, 0x06, 0xD2, 0x0E, 0xEB, 0x86, 0x0C, 0xBD, 0xE8, 0x70, 0x40, 0x4C, 0xF0, 0x01, 0x0C, 0x60, + 0x47, 0xDF, 0xE8, 0x0C, 0xF0, 0x09, 0x0B, 0x02, 0x02, 0x4F, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, 0xA1, 0xF5, 0x00, 0x21, 0x70, 0xBD, 0x19, 0x46, 0x10, 0x46, 0x01, 0x28, 0x51, 0xEB, 0x01, 0x04, 0x18, 0xBF, 0xD4, 0xF5, 0x00, 0x14, 0x84, + 0xBF, 0x00, 0x20, 0x01, 0xF0, 0x00, 0x41, 0x70, 0xBD, 0x08, 0x08, 0xA0, 0xF5, 0x00, 0x11, 0x4F, 0xEA, 0x31, 0x01, 0x70, 0x47, 0x01, 0xD1, 0x85, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x51, 0x89, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x89, 0x20, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x72, 0x65, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x00, 0x68, 0xE8, 0x21, + 0x00, 0x14, 0xE9, 0x21, 0x00, 0x5C, 0xE8, 0x21, 0x00, 0x1C, 0xE9, 0x21, 0x00, 0xC0, 0xE8, 0x21, 0x00, 0x34, 0xE9, 0x21, 0x00, 0x28, 0xE9, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0xB0, 0xE8, 0x21, + 0x00, 0x50, 0xE8, 0x21, 0x00, 0x08, 0xE9, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0x78, 0xE8, 0x21, 0x00, 0xD8, 0xE8, 0x21, 0x00, 0xEC, 0xE8, 0x21, 0x00, 0x58, 0xE8, 0x21, 0x00, 0x40, 0xE8, 0x21, 0x00, 0xC0, 0xE7, 0x21, 0x00, 0x94, 0xE7, 0x21, + 0x00, 0xF4, 0xE8, 0x21, 0x00, 0xA8, 0xE8, 0x21, 0x00, 0x94, 0xE8, 0x21, 0x00, 0x2C, 0xE8, 0x21, 0x00, 0xEC, 0xE7, 0x21, 0x00, 0x0C, 0xE8, 0x21, 0x00, 0x70, 0xE7, 0x21, 0x00, 0x3C, 0xE7, 0x21, 0x00, 0x4C, 0xE8, 0x21, 0x00, 0x34, 0xE7, 0x21, + 0x00, 0x68, 0xE7, 0x21, 0x00, 0x2C, 0xE7, 0x21, 0x00, 0x60, 0xE7, 0x21, 0x00, 0x48, 0xE8, 0x21, 0x00, 0xE0, 0xE8, 0x21, 0x00, 0x44, 0xE7, 0x21, 0x00, 0x78, 0xE7, 0x21, 0x00, 0xA4, 0xE7, 0x21, 0x00, 0xC8, 0xE7, 0x21, 0x00, 0xF4, 0xE7, 0x21, + 0x00, 0x14, 0xE8, 0x21, 0x00, 0xD8, 0xE7, 0x21, 0x00, 0xB4, 0xE7, 0x21, 0x00, 0x74, 0xE8, 0x21, 0x00, 0x88, 0xE7, 0x21, 0x00, 0x54, 0xE7, 0x21, 0x00, 0x9C, 0xE7, 0x21, 0x00, 0xE4, 0xE7, 0x21, 0x00, 0x04, 0xE8, 0x21, 0x00, 0x24, 0xE8, 0x21, + 0x00, 0x38, 0xE8, 0x21, 0x00, 0xCC, 0xE8, 0x21, 0x00, 0xB8, 0xE8, 0x21, 0x00, 0x00, 0xE9, 0x21, 0x00, 0x80, 0xE8, 0x21, 0x00, 0x60, 0xE8, 0x21, 0x00, 0x40, 0xE9, 0x21, 0x00, 0x9C, 0xE8, 0x21, 0x00, 0x88, 0xE8, 0x21, 0x00, 0x54, 0xE8, 0x21, + 0x00, 0x02, 0x08, 0x00, 0x28, 0x0F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x19, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x53, 0x94, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xBB, 0x94, 0x20, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x48, 0xE1, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0x28, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x95, 0x20, 0x00, 0xD3, 0x95, 0x20, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xD0, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xBC, 0xE4, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x00, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF1, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x91, 0xCF, 0x21, 0x00, 0xED, 0xCE, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xA0, 0x20, 0x00, 0xD5, 0xA0, 0x20, 0x00, 0x52, 0x65, 0x61, + 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, 0x00, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x6D, 0x73, 0x67, 0x5F, 0x74, 0x6F, 0x5F, 0x61, 0x70, 0x70, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x6D, 0x61, 0x69, + 0x6E, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x00, 0x00, 0x49, 0x32, 0x43, 0x30, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x30, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x30, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, + 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x30, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x30, 0x00, 0x49, 0x32, 0x43, 0x31, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x31, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, + 0x54, 0x31, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x31, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x00, 0x54, 0x49, 0x4D, 0x32, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x41, 0x52, 0x54, 0x32, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x32, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x32, 0x00, 0x54, 0x49, 0x4D, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x33, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x33, 0x00, 0x54, 0x49, 0x4D, 0x34, 0x00, 0x00, 0x00, + 0x00, 0x47, 0x50, 0x49, 0x4F, 0x34, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x34, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x35, 0x00, 0x00, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x35, 0x00, 0x00, + 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x35, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x36, 0x00, 0x00, 0x00, 0x00, 0x54, 0x69, 0x6D, 0x65, 0x72, 0x34, 0x2D, 0x37, 0x00, 0x00, 0x00, 0x00, 0x54, 0x49, 0x4D, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x4D, 0x41, 0x43, 0x00, 0x00, 0x00, 0x41, 0x44, 0x43, 0x00, 0x52, 0x54, 0x43, 0x00, 0x53, 0x56, 0x43, 0x00, 0x4C, 0x43, 0x44, 0x00, 0x57, 0x44, 0x47, 0x00, 0x4E, 0x4D, 0x49, 0x00, 0x4C, 0x50, 0x43, + 0x4F, 0x4D, 0x50, 0x00, 0x00, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x53, 0x50, 0x00, 0x00, 0x00, 0x49, 0x52, 0x00, 0x00, 0x50, 0x65, 0x6E, 0x64, 0x53, 0x56, 0x00, 0x00, 0x53, 0x50, 0x49, 0x32, 0x57, 0x00, 0x00, 0x00, 0x53, 0x50, 0x4F, + 0x52, 0x54, 0x31, 0x20, 0x52, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, 0x53, 0x30, 0x5F, 0x52, 0x58, 0x00, 0x53, 0x50, 0x4F, 0x52, 0x54, 0x31, 0x20, 0x54, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, 0x53, 0x30, 0x5F, 0x54, 0x58, 0x00, 0x52, 0x73, 0x76, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x51, 0x64, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x5F, 0x46, 0x6C, 0x61, 0x73, 0x68, 0x00, 0x00, 0x00, 0x53, 0x79, 0x73, + 0x54, 0x69, 0x63, 0x6B, 0x00, 0x50, 0x65, 0x72, 0x69, 0x70, 0x68, 0x65, 0x72, 0x61, 0x6C, 0x00, 0x00, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x00, 0x00, 0x50, 0x6C, 0x61, 0x74, 0x66, 0x6F, 0x72, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, + 0x73, 0x63, 0x61, 0x6E, 0x00, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4D, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x48, 0x61, 0x72, 0x64, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, + 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x50, 0x54, 0x41, 0x5F, 0x4D, 0x61, 0x69, 0x6C, 0x62, 0x6F, 0x78, 0x00, 0x00 +}; + +#else // default silent ota test image +{ + 0x05, 0x00, 0x01, 0x01, 0x93, 0x27, 0x00, 0x00, 0xF0, 0x40, 0x00, 0x00, 0x6D, 0x67, 0xDE, 0xF1, 0x3E, 0x33, 0xE8, 0x11, 0xB1, 0x02, 0x4D, 0x2D, 0xF4, 0x0C, 0xDE, 0x01, 0x00, 0xE4, 0x80, 0x00, 0x00, 0xE4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x00, 0x08, 0x50, 0x43, 0x46, 0x1E, 0x73, 0x64, 0x6B, 0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0xCA, 0xB4, 0x1E, 0xC9, 0x4B, 0xE5, 0xD1, 0xCD, 0x6C, 0xEE, 0x4F, 0xBA, 0xE2, 0x43, 0x96, 0x88, 0x91, 0x44, 0x53, 0x6B, 0x91, 0x3F, 0x7B, 0xEA, 0xEF, 0xB7, + 0xFD, 0x95, 0x03, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD1, 0x85, 0x0E, 0xE0, 0xAF, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x00, 0x47, 0x5F, 0xE5, 0x80, 0x00, 0xAF, 0xF3, 0x00, 0x80, 0xF9, 0xF5, 0xFE, 0xF3, + 0x10, 0xB5, 0x7B, 0x4A, 0x7B, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0x3F, 0xF5, 0x7B, 0x4A, 0x7C, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0x3A, 0xF5, 0x7C, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0xF7, 0xF5, 0x7C, 0x4A, 0x7C, 0x49, 0x7D, 0x48, 0x4B, 0xF4, 0x31, 0xF5, + 0x7C, 0x4A, 0x7D, 0x49, 0x7D, 0x48, 0x4B, 0xF4, 0x2C, 0xF5, 0xBD, 0xE8, 0x10, 0x40, 0x7C, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0xE7, 0xB5, 0x7F, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF0, 0xE9, 0xE0, 0x12, 0x11, 0x44, 0x80, 0x68, 0x10, 0x22, 0x0D, 0x18, + 0x29, 0x46, 0x68, 0x46, 0x4B, 0xF4, 0x19, 0xF5, 0x10, 0x22, 0x69, 0x46, 0x00, 0x20, 0xF8, 0xF7, 0xB1, 0xDF, 0x73, 0x49, 0xD1, 0xF8, 0x7C, 0x11, 0x72, 0x4E, 0x60, 0xF3, 0x1F, 0x41, 0x4F, 0xF0, 0xFF, 0x30, 0x31, 0x61, 0xF9, 0xF7, 0x95, 0xD9, + 0x31, 0x69, 0x48, 0x43, 0x30, 0x61, 0xFC, 0xF5, 0xBF, 0xF4, 0x00, 0x24, 0xF9, 0xF5, 0xC4, 0xF3, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0x04, 0x2C, 0xF8, 0xDB, 0xF9, 0xF5, 0xBD, 0xF3, 0x30, 0x61, 0x7F, 0xBD, 0x70, 0xB5, 0x66, 0x4D, 0x67, 0x49, + 0x67, 0x4C, 0x28, 0x68, 0x4F, 0xF0, 0x00, 0x02, 0xB1, 0xEB, 0x00, 0x2F, 0x05, 0xD0, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x63, 0x49, 0xF9, 0xF7, 0xCA, 0x9A, 0x00, 0x21, 0x45, 0xF2, 0x06, 0x00, 0xFD, 0xF7, 0xCF, 0xDD, 0x10, 0xF0, 0xFF, 0x03, + 0x03, 0xD0, 0x5E, 0x49, 0x01, 0x22, 0x1C, 0x31, 0x04, 0xE0, 0x28, 0x68, 0x5B, 0x49, 0x03, 0x0E, 0x01, 0x22, 0x50, 0x31, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xF9, 0xF7, 0xB4, 0x9A, 0x38, 0xB5, 0x72, 0xB6, 0xFF, 0xF7, 0xD6, 0xFF, 0xFF, 0xF7, + 0x87, 0xFF, 0xFF, 0xF7, 0xA4, 0xFF, 0x00, 0x20, 0xFB, 0xF5, 0x08, 0xF1, 0x16, 0x20, 0xF9, 0xF5, 0xA8, 0xF5, 0x17, 0x20, 0xF9, 0xF5, 0xA5, 0xF5, 0x4F, 0xA1, 0x1F, 0x20, 0x4B, 0xF4, 0x6A, 0xF4, 0x4F, 0xF0, 0x05, 0x55, 0x4D, 0xA1, 0x28, 0x46, + 0xF9, 0xF7, 0x9F, 0xDC, 0x04, 0x46, 0x52, 0xA1, 0x28, 0x46, 0xF9, 0xF7, 0x9A, 0xDC, 0x03, 0x46, 0x46, 0x49, 0x45, 0x48, 0x02, 0x22, 0x7C, 0x31, 0x80, 0x1E, 0x00, 0x94, 0xF9, 0xF7, 0x8B, 0xDA, 0xF9, 0xF5, 0x96, 0xF5, 0x4C, 0x48, 0x00, 0x68, + 0x00, 0x28, 0x03, 0xD0, 0x01, 0xB0, 0xBD, 0xE8, 0x30, 0x40, 0x00, 0x47, 0x38, 0xBD, 0x10, 0xB5, 0xFE, 0xF7, 0xFE, 0xD8, 0x00, 0x28, 0x4A, 0xD1, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0xDC, 0x12, 0xC9, 0x07, 0x44, 0xD0, 0xAF, 0xF2, 0x81, 0x01, + 0x42, 0x4A, 0x11, 0x60, 0x43, 0x4A, 0x42, 0x49, 0x11, 0x60, 0x4F, 0xF4, 0x0C, 0x41, 0xC0, 0xF8, 0x84, 0x13, 0x47, 0xF2, 0xF0, 0x71, 0xC0, 0xF8, 0x88, 0x13, 0x3F, 0x49, 0xC0, 0xF8, 0xCC, 0x13, 0x90, 0xF8, 0x4D, 0x13, 0x41, 0xF0, 0x08, 0x01, + 0x80, 0xF8, 0x4D, 0x13, 0x06, 0x21, 0x80, 0xF8, 0x4F, 0x13, 0x90, 0xF8, 0x78, 0x23, 0x90, 0xF8, 0x9A, 0x13, 0x42, 0xF0, 0x26, 0x02, 0x80, 0xF8, 0x78, 0x23, 0x21, 0xF0, 0x21, 0x01, 0x80, 0xF8, 0x9A, 0x13, 0x90, 0xF8, 0x34, 0x13, 0x41, 0xF0, + 0x01, 0x01, 0x80, 0xF8, 0x34, 0x13, 0x90, 0xF8, 0x7A, 0x13, 0x21, 0xF0, 0x10, 0x01, 0x80, 0xF8, 0x7A, 0x13, 0x90, 0xF8, 0xC3, 0x13, 0x21, 0xF0, 0xC0, 0x01, 0x80, 0xF8, 0xC3, 0x13, 0xF0, 0x21, 0x80, 0xF8, 0x20, 0x13, 0x3C, 0x21, 0x80, 0xF8, + 0x21, 0x13, 0xC8, 0x21, 0x80, 0xF8, 0x22, 0x13, 0xFF, 0x21, 0x80, 0xF8, 0x23, 0x13, 0x10, 0xBD, 0x2C, 0x3C, 0x00, 0x00, 0x88, 0xE7, 0x80, 0x00, 0x00, 0x7C, 0x20, 0x00, 0x3C, 0x01, 0x00, 0x00, 0xB4, 0x23, 0x81, 0x00, 0x2C, 0xB8, 0x20, 0x00, + 0x84, 0x0B, 0x00, 0x00, 0x68, 0xB9, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x81, 0x00, 0x00, 0xC0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x81, 0x00, 0x00, 0xC0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x21, 0x00, + 0x00, 0x80, 0x05, 0x40, 0x68, 0xB9, 0x20, 0x00, 0x2C, 0xB8, 0x20, 0x00, 0x00, 0x74, 0x65, 0x72, 0x02, 0x03, 0x10, 0x21, 0x00, 0x00, 0x80, 0x08, 0x43, 0x00, 0x00, 0x00, 0x54, 0x68, 0x75, 0x20, 0x4D, 0x61, 0x79, 0x20, 0x20, 0x37, 0x20, 0x31, + 0x37, 0x3A, 0x31, 0x37, 0x3A, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x32, 0x2E, 0x32, 0x2E, 0x31, 0x00, 0x74, 0xB9, 0x20, 0x00, 0x38, 0x0C, 0x20, 0x00, 0x55, 0x7F, 0x20, 0x00, 0x3C, 0x0C, 0x20, 0x00, + 0x03, 0x00, 0xAA, 0xA2, 0x00, 0x38, 0x20, 0x00, 0x01, 0xE4, 0x80, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x55, 0x7C, 0x20, 0x00, 0xA1, 0x7C, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0xED, 0x7C, 0x20, 0x00, 0x31, 0x7D, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x1F, 0xB5, 0x03, 0xF0, 0xE7, 0xF9, 0x03, 0xF0, 0x18, 0xF9, 0x1F, 0xBD, 0x00, 0xF0, 0x82, 0xF9, 0x11, 0x46, 0xFF, 0xF7, 0xF5, 0xFF, 0x01, 0xF0, 0x45, 0xFD, 0x53, 0xF6, 0x03, 0xF9, 0x00, 0x00, + 0x0B, 0x49, 0xD1, 0xF8, 0x00, 0xC0, 0x4A, 0x68, 0x5C, 0xF8, 0x04, 0x3B, 0x10, 0x68, 0x18, 0x44, 0x42, 0xF8, 0x04, 0x0B, 0x8C, 0x45, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x0C, 0x8A, 0x42, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x02, 0xC1, 0xF8, 0x00, 0xC0, + 0x4A, 0x60, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0xE4, 0xC4, 0x20, 0x00, 0x47, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x20, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x51, 0xF9, 0x20, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0x4D, 0xF9, 0x20, 0x05, 0x01, 0xD5, 0x00, 0xF0, + 0x49, 0xF9, 0x20, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0x45, 0xF9, 0x20, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x41, 0xF9, 0x20, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0x3D, 0xF9, 0x20, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0x39, 0xF9, 0x00, 0x2C, 0x03, 0xDA, 0xBD, 0xE8, + 0x10, 0x40, 0x00, 0xF0, 0x33, 0xB9, 0x10, 0xBD, 0x34, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x60, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x2B, 0xF9, 0x60, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0x27, 0xF9, 0x60, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x23, 0xF9, 0x60, 0x04, + 0x01, 0xD5, 0x00, 0xF0, 0x1F, 0xF9, 0x60, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x1B, 0xF9, 0x60, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0x17, 0xF9, 0x60, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0x13, 0xF9, 0x60, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, + 0x0D, 0xB9, 0x10, 0xBD, 0x21, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xA0, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x05, 0xF9, 0xA0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x01, 0xF9, 0xA0, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0xFD, 0xF8, 0xA0, 0x03, 0x01, 0xD5, 0x00, 0xF0, + 0xF9, 0xF8, 0xA0, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xF5, 0xF8, 0xA0, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0xF1, 0xF8, 0xA0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xEB, 0xB8, 0x10, 0xBD, 0x10, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xE0, 0x07, + 0x01, 0xD0, 0x00, 0xF0, 0xE3, 0xF8, 0xE0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0xDF, 0xF8, 0xE0, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0xDB, 0xF8, 0xE0, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0xD7, 0xF8, 0xE0, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xD3, 0xF8, 0xE0, 0x01, + 0x01, 0xD5, 0x00, 0xF0, 0xCF, 0xF8, 0xE0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xC9, 0xB8, 0x10, 0xBD, 0x00, 0x10, 0x00, 0x40, 0x7C, 0xB5, 0x00, 0x24, 0x4F, 0xF0, 0xE0, 0x20, 0x01, 0x21, 0xC0, 0xF8, 0x80, 0x11, 0xD0, 0xF8, + 0x00, 0x21, 0x59, 0x49, 0x0A, + 0x60, 0xD0, 0xF8, 0x00, 0x22, 0x4A, 0x60, 0xD0, 0xF8, 0x00, 0x03, 0x88, 0x60, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x92, 0xF8, 0x00, 0x24, 0x41, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0x20, 0x28, 0xF6, 0xD3, 0x51, 0x48, 0x00, 0x68, 0xC1, 0xF8, 0x80, + 0x00, 0x50, 0x48, 0xC0, 0x68, 0x4D, 0x4B, 0x0C, 0x3B, 0x03, 0xF1, 0x90, 0x01, 0x18, 0x60, 0x00, 0x20, 0x82, 0x00, 0x02, 0xF1, 0x80, 0x42, 0xD2, 0xF8, 0x80, 0x22, 0x41, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x98, 0x68, 0x00, 0xB1, 0x80, 0x47, 0x4F, 0xF4, 0x00, 0x15, 0x95, 0xF8, 0x34, 0x03, 0xC0, 0x07, 0x0F, 0xD0, 0x00, 0x94, 0x02, 0x23, 0x01, 0x22, 0x00, 0x21, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xEF, 0xFA, 0x00, 0x94, 0x02, + 0x23, 0x01, 0x22, 0x00, 0x21, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xE7, 0xFA, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x23, 0x00, 0xF0, 0x3F, 0x00, 0x1A, 0x46, 0x00, 0x21, 0x09, 0xF6, 0xDC, 0xFA, 0x7C, 0xBD, 0x30, 0xB5, 0x31, + 0x49, 0x00, 0x20, 0x85, 0xB0, 0x84, 0x31, 0x82, 0x00, 0x02, 0xF1, 0x80, 0x42, 0x51, 0xF8, 0x20, 0x30, 0xC2, 0xF8, 0x80, 0x32, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x00, 0x24, 0x4F, 0xF4, 0x00, 0x15, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x22, 0x00, 0xF0, 0x3F, 0x00, 0x23, 0x46, 0x11, 0x46, 0x05, 0xF5, 0x66, 0x75, 0x09, 0xF6, 0xBB, 0xFA, 0x15, 0xF8, 0x64, 0x0C, 0xC0, + 0x07, 0x0F, 0xD0, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xAF, 0xFA, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xA7, 0xFA, 0x18, 0x4D, 0x0C, 0x3D, 0x68, + 0x68, 0x00, 0xB1, 0x80, 0x47, 0x01, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x03, 0x20, 0x03, 0x90, 0x8D, 0xF8, 0x08, 0x40, 0x02, 0xA8, 0x09, 0xF6, 0x0A, + 0xFA, 0x10, 0x4C, 0x63, 0x68, 0x58, 0x08, 0x04, 0xD0, 0x01, 0x22, 0x11, 0x49, 0x11, 0x48, 0xFF, 0xF5, 0xD0, 0xFD, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x14, 0xF8, 0x20, 0x10, 0x82, 0xF8, 0x00, 0x14, 0x40, 0x1C, 0x20, 0x28, 0xF6, 0xD3, 0x08, + 0x49, 0xD4, 0xF8, 0x80, 0x00, 0x08, 0x60, 0x07, 0x49, 0x28, 0x68, 0xC8, 0x60, 0x4F, 0xF0, 0xE0, 0x21, 0x20, 0x68, 0xC1, 0xF8, 0x00, 0x01, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0x00, 0x98, 0xB9, 0x20, 0x00, 0x08, 0xED, 0x00, 0xE0, 0x00, 0x60, 0x00, + 0x40, 0xE8, 0x00, 0x80, 0x08, 0x01, 0x04, 0x10, 0x21, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0x49, 0xEF, 0xF3, 0x05, 0x82, 0x10, 0x4B, 0x98, 0x47, 0xFE, 0xE7, 0x70, 0x47, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, + 0x20, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x20, 0x49, 0x53, 0x52, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64, 0x21, 0x0A, + 0x00, 0x16, 0x7F, 0x20, 0x00, 0xB1, 0x79, 0x00, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x94, 0xF8, 0x9B, 0x03, 0x40, 0xF0, 0x80, 0x00, 0x84, 0xF8, 0x9B, 0x03, 0x94, 0xF8, 0xDC, 0x02, 0xC1, 0x07, 0x4F, 0xF0, 0x04, 0x50, 0x03, 0xD0, 0x6F, + 0xA1, 0xFF, 0xF5, 0x1C, 0xFD, 0x06, 0xE0, 0x70, 0xA1, 0xFF, 0xF5, 0x18, 0xFD, 0x09, 0xF6, 0xDF, 0xFC, 0x1E, 0xF6, 0x1D, 0xFC, 0x94, 0xF8, 0x9A, 0x03, 0xC0, 0x07, 0x02, 0xD0, 0x00, 0x20, 0x00, 0xF6, 0x1F, 0xF9, 0xBD, 0xE8, 0x10, 0x40, 0x06, + 0xF2, 0x35, 0xB2, 0x40, 0xEA, 0x01, 0x21, 0x01, 0x20, 0xFF, 0xF5, 0x7C, 0xB9, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x00, 0x22, 0x94, 0xF8, 0x4C, 0x13, 0x60, 0xF3, 0x01, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x11, 0x46, 0x45, 0xF2, 0x02, 0x00, 0x04, + 0xF6, 0x56, 0xF8, 0x00, 0x28, 0x05, 0xD1, 0x94, 0xF8, 0x4C, 0x13, 0x21, 0xF0, 0x03, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x10, 0xBD, 0x01, 0x46, 0x40, 0xF2, 0x71, 0x43, 0x62, 0x4A, 0x00, 0x20, 0x1D, 0xF6, 0xBD, 0xBE, 0x60, 0x4A, 0x41, 0x43, 0xD2, + 0x1D, 0x40, 0xF2, 0x76, 0x43, 0x00, 0x20, 0x1D, 0xF6, 0xE1, 0xBE, 0x10, 0xB5, 0x0C, 0x46, 0x08, 0xB1, 0x1D, 0xF6, 0x3B, 0xFF, 0x59, 0x4A, 0x21, 0x46, 0x0E, 0x32, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF4, 0x90, 0x63, 0x00, 0x20, 0x1D, 0xF6, 0xA6, + 0xBE, 0x1D, 0xF6, 0x2F, 0xBF, 0x54, 0x4A, 0xD1, 0x70, 0x54, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x52, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x50, 0x48, 0x00, 0x68, 0x00, 0x28, 0x00, + 0xD0, 0x00, 0x47, 0x70, 0x47, 0x4E, 0x48, 0x00, 0x68, 0x70, 0x47, 0x4A, 0x48, 0x10, 0xB5, 0x0E, 0x22, 0x4C, 0x49, 0x14, 0x30, 0x51, 0xF6, 0x23, 0xFF, 0x46, 0x48, 0x14, 0x30, 0x10, 0xBD, 0x49, 0x48, 0x80, 0x1E, 0x00, 0x78, 0x70, 0x47, 0x00, + 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x3A, 0x49, 0xBE, 0xB0, 0x40, 0x22, 0x18, 0x31, 0x2D, 0xA8, 0x51, 0xF6, 0x8F, 0xFF, 0x37, + 0x49, 0xB4, 0x22, 0x58, 0x31, 0x68, 0x46, 0x51, 0xF6, 0x89, 0xFF, 0x3D, 0x49, 0x4F, 0xF4, 0x00, 0x10, 0x39, 0x4E, 0x3A, 0x4F, 0x09, 0x68, 0x05, 0x46, 0x00, 0x24, 0xA9, 0x42, 0x01, 0xD0, 0xFC, 0xF5, 0xFD, 0xFD, 0xDF, 0xF8, 0xE0, 0x80, 0x4F, + 0xF0, 0x05, 0x59, 0xDF, 0xF8, 0xDC, 0xA0, 0x2F, 0xE0, 0x6C, 0xB3, 0x01, 0x2C, 0x2B, 0xD0, 0x56, 0xF8, 0x24, 0x00, 0x40, 0x45, 0x00, 0xD0, 0x38, 0xB9, 0x40, 0x45, 0x24, 0xD1, 0x55, 0xF8, 0x24, 0x00, 0xA0, 0xF5, 0x80, 0x71, 0x55, 0x39, 0x1E, + 0xD1, 0x10, 0x2C, 0x09, 0xD2, 0x2D, 0xA8, 0x50, 0xF8, 0x24, 0x10, 0x48, 0x46, 0xFF, 0xF5, 0xBF, 0xFE, 0x03, 0x46, 0x01, 0x22, 0x29, 0x49, 0x0B, 0xE0, 0x68, 0x46, 0x00, 0xEB, 0x84, 0x00, 0x50, 0xF8, 0x40, 0x1C, 0x48, 0x46, 0xFF, 0xF5, 0xB3, + 0xFE, 0x24, 0x49, 0x01, 0x22, 0x03, 0x46, 0x24, 0x31, 0x50, 0x46, 0xFF, 0xF5, 0xA6, 0xFC, 0x56, 0xF8, 0x24, 0x00, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0xB4, 0xEB, 0x97, 0x0F, 0xCC, 0xD3, 0xBF, 0xF3, 0x5F, 0x8F, 0xBF, 0xF3, 0x4F, 0x8F, 0x3E, + 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x49, 0x6E, 0x20, 0x53, 0x6F, 0x43, 0x20, 0x4D, 0x6F, 0x64, 0x65, 0x00, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x3A, 0x20, 0x49, 0x6E, 0x20, 0x48, 0x43, 0x49, 0x20, 0x4D, 0x6F, 0x64, 0x65, 0x2C, 0x20, 0x77, + 0x69, 0x6C, 0x6C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x41, 0x50, 0x50, 0x20, 0x54, 0x61, 0x73, 0x6B, 0x00, 0x04, 0xB0, 0x20, 0x00, 0x2C, 0xB8, 0x20, 0x00, 0x68, 0xB9, 0x20, 0x00, 0x6C, 0xB9, 0x20, 0x00, 0x70, 0xB9, 0x20, + 0x00, 0xF4, 0x00, 0x20, 0x00, 0xF5, 0x28, 0x20, 0x00, 0x94, 0xE6, 0x80, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x08, 0xED, 0x00, 0xE0, 0x05, 0x7F, 0x20, 0x00, 0x01, 0x01, 0x10, 0x21, 0x9C, 0x00, 0x80, 0x08, 0x10, 0xB5, 0x00, 0x21, 0x04, 0x48, 0x00, + 0xF6, 0xA4, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x02, 0x48, 0x00, 0xF6, 0x9E, 0xBA, 0x00, 0x00, 0x79, 0x7D, 0x20, 0x00, 0x27, 0x7E, 0x20, 0x00, 0x70, 0xB5, 0x01, 0x24, 0x13, 0x46, 0x0D, 0x46, 0x01, 0x28, 0x06, 0xD0, 0x00, 0x24, 0x22, + 0x46, 0x82, 0x49, 0x83, 0x48, 0xFF, 0xF5, 0x45, 0xFC, 0x09, 0xE0, 0xB5, 0xF5, 0x96, 0x7F, 0xF5, 0xD8, 0x0A, + 0x46, 0x19, 0x46, 0x7F, 0x48, 0x51, 0xF6, 0x5A, 0xFE, 0x7F, 0x48, 0x05, 0x80, 0x20, 0x46, 0x70, 0xBD, 0xFE, 0xB5, 0x00, 0x24, 0xDD, 0xE9, 0x08, 0x65, 0x0B, 0x46, 0x02, 0x2A, 0x09, 0xD0, 0x76, 0x49, 0x13, 0x46, 0x01, 0x22, 0x2C, 0x31, 0x75, + 0x48, 0xFF, 0xF5, 0x2A, 0xFC, 0x40, 0xF2, 0x0A, + 0x44, 0x13, 0xE0, 0x02, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x8D, 0xF8, 0x00, 0x00, 0x71, 0x48, 0x01, 0x21, 0x08, 0x38, 0x8D, 0xF8, 0x04, 0x10, 0x42, 0x68, 0x12, 0xB1, 0x69, 0x46, 0x18, 0x46, 0x90, 0x47, 0x6C, 0x48, 0x28, 0x60, 0x6C, 0x48, 0x00, + 0x88, 0x30, 0x80, 0x20, 0x46, 0xFE, 0xBD, 0x0E, 0xB5, 0x8D, 0xE8, 0x0E, 0x00, 0x03, 0x46, 0x64, 0x49, 0x65, 0x48, 0x04, 0x22, 0x68, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0x06, 0xFC, 0x0E, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x8B, 0x46, 0x80, 0x46, 0xDD, + 0xE9, 0x0E, 0x65, 0x5D, 0x49, 0x5E, 0x48, 0x17, 0x46, 0x99, 0x46, 0x00, 0x24, 0x01, 0x22, 0xC0, 0x31, 0x80, 0x1C, 0xDD, 0xF8, 0x40, 0xA0, 0xFF, 0xF5, 0xF3, 0xFB, 0xAF, 0xF2, 0x3F, 0x01, 0xCA, 0xF8, 0x00, 0x10, 0x05, 0x2F, 0x0D, 0xD0, 0x54, + 0x49, 0x3B, 0x46, 0x02, 0x22, 0xF4, 0x31, 0x53, 0x48, 0x00, 0x96, 0xFF, 0xF5, 0xE5, 0xFB, 0x40, 0xF2, 0x0A, + 0x44, 0x04, 0xB0, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0xAD, 0xB1, 0x03, 0x20, 0x8D, 0xF8, 0x05, 0x00, 0x01, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x4C, 0x48, 0x8D, 0xF8, 0x09, 0x90, 0x08, 0x38, 0x8D, 0xF8, 0x04, 0x80, 0xAD, 0xF8, 0x0A, + 0x60, 0x03, 0x95, 0x42, 0x68, 0x00, 0x2A, 0xE8, 0xD0, 0x01, 0xA9, 0x58, 0x46, 0x90, 0x47, 0xE4, 0xE7, 0x40, 0xF2, 0x0D, 0x44, 0xE1, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x07, 0x46, 0x40, 0x48, 0x15, 0x46, 0x0E, 0x46, 0x1C, 0x46, 0x00, 0x22, 0x40, + 0x49, 0x80, 0x1C, 0xFF, 0xF5, 0xB9, 0xFB, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x40, 0x2B, 0x46, 0x07, 0x22, 0x31, 0x46, 0x38, 0x46, 0x47, 0xF6, 0x53, 0xFA, 0xBD, 0xE8, 0xFC, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0x0E, 0x46, 0x07, 0x46, 0x37, 0x49, 0x33, + 0x48, 0x15, 0x46, 0x1C, 0x46, 0x00, 0x22, 0x24, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0xA1, 0xFB, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x40, 0x2B, 0x46, 0x0A, + 0x22, 0x31, 0x46, 0x38, 0x46, 0x47, 0xF6, 0x3B, 0xFA, 0xE6, 0xE7, 0x2D, 0xE9, 0xFF, 0x41, 0x88, 0x46, 0x8D, 0xF8, 0x04, 0x00, 0x1D, 0x46, 0x00, 0x93, 0x2A, 0x49, 0x26, 0x48, 0x16, 0x46, 0x01, 0x27, 0x13, 0x46, 0x00, 0x24, 0x8D, 0xF8, 0x05, + 0x70, 0x02, 0x22, 0x4C, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0x83, 0xFB, 0x08, 0x2E, 0x02, 0xD0, 0x0B, 0x2E, 0x08, 0xD1, 0x13, 0xE0, 0xE8, 0x07, 0x02, 0xD0, 0x8D, 0xF8, 0x08, 0x70, 0x01, 0xE0, 0x02, 0x20, 0x11, 0xE0, 0x01, 0x24, 0x1B, 0x48, 0x08, + 0x38, 0x42, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xFF, 0x81, 0xA8, 0x07, 0x01, 0xD5, 0x03, 0x20, 0x00, 0xE0, 0x04, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xEA, 0xE7, 0x7C, 0xB5, 0x13, + 0x49, 0x05, 0x46, 0xD1, 0xE9, 0x15, 0x02, 0xCD, 0xE9, 0x00, 0x02, 0x0D, 0x48, 0x0B, 0x6D, 0x4F, 0xF4, 0xA8, 0x72, 0xA1, 0xF5, 0x80, 0x71, 0x08, 0x38, 0x47, 0xF6, 0x5A, 0xF9, 0x09, 0x4C, 0x08, 0x3C, 0x10, 0xB1, 0x65, 0x60, 0x20, 0x78, 0x7C, + 0xBD, 0x08, 0x49, 0x00, 0x22, 0x8C, 0x31, 0x03, 0x48, 0xFF, 0xF5, 0x46, 0xFB, 0xFF, 0x20, 0x20, 0x70, 0x7C, 0xBD, 0x14, 0x01, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x4C, 0xBA, 0x20, 0x00, 0x30, 0xB8, 0x20, 0x00, 0x50, 0x02, 0x80, 0x08, 0x10, + 0xB2, 0x20, 0x00, 0x10, 0xB5, 0x01, 0x24, 0x01, 0x28, 0x06, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x53, 0x49, 0x54, 0x48, 0xFF, 0xF5, 0x2D, 0xFB, 0x06, 0xE0, 0x01, 0x29, 0x01, 0xD0, 0x00, 0x24, 0x02, 0xE0, 0x51, 0x49, 0x10, 0x78, 0x08, 0x70, 0x20, + 0x46, 0x10, 0xBD, 0x07, 0xB5, 0x82, 0xB0, 0x00, 0x23, 0x01, 0x22, 0xCD, 0xE9, 0x00, 0x23, 0x04, 0xAB, 0x02, 0x22, 0x47, 0xF6, 0xBC, 0xF9, 0x05, 0xB0, 0x00, 0xBD, 0x07, 0xB5, 0x48, 0x4B, 0x82, 0xB0, 0x5A, 0x78, 0x4A, 0xB1, 0x00, 0x22, 0x5A, + 0x70, 0x01, 0x23, 0xCD, 0xE9, 0x00, 0x32, 0x04, 0xAB, 0x02, 0x22, 0x47, 0xF6, 0x23, 0xF9, 0xEE, 0xE7, 0x00, 0x20, 0xEC, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0xDD, 0xE9, 0x08, 0x67, 0x00, 0x20, 0x30, 0x80, 0x88, 0x46, 0x00, 0x93, 0x39, + 0x49, 0x3A, 0x48, 0x14, 0x46, 0x13, 0x46, 0x02, 0x22, 0x1C, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0xF4, 0xFA, 0x02, 0x2C, 0x0A, + 0xD0, 0x34, 0x49, 0x23, 0x46, 0x01, 0x22, 0x4C, 0x31, 0x33, 0x48, 0xFF, 0xF5, 0xEB, 0xFA, 0x40, 0xF2, 0x0A, + 0x40, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x8D, 0xF8, 0x00, 0x50, 0x2E, 0x4D, 0x01, 0x24, 0x8D, 0xF8, 0x02, 0x40, 0x6A, 0x68, 0x69, 0x46, 0x40, 0x46, 0x90, 0x47, 0xA0, 0xF5, 0x50, 0x61, 0x01, 0x39, 0x00, 0xD1, 0x6C, + 0x70, 0x3D, 0x60, 0x34, 0x80, 0xE8, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x26, 0x8D, 0xF8, 0x05, 0x60, 0x88, 0x46, 0x8D, 0xF8, 0x04, 0x00, 0x1D, 0x46, 0x00, 0x93, 0x1F, 0x49, 0x1F, 0x48, 0x17, 0x46, 0x13, 0x46, 0x34, 0x46, 0x02, 0x22, 0x7C, + 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0xBE, 0xFA, 0x03, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x1A, 0x48, 0x42, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xE8, 0x07, 0x02, 0xD0, 0x8D, + 0xF8, 0x06, 0x60, 0xEF, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xEB, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x10, 0x48, 0xD0, 0xE9, 0x1D, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0x01, 0x46, 0x03, 0x6F, 0x70, 0x22, 0x02, 0xA8, 0x47, 0xF6, 0xA2, 0xF8, 0x50, + 0xB9, 0x07, 0x49, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x06, 0x48, 0xFF, 0xF5, 0x91, 0xFA, 0xFF, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x04, 0x48, 0x44, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x04, 0x03, 0x80, 0x08, 0x00, 0x33, 0x10, + 0x21, 0x78, 0xBB, 0x20, 0x00, 0x6C, 0xB2, 0x20, 0x00, 0x2D, 0xE9, 0xFF, 0x41, 0xC3, 0x4C, 0x0E, 0x46, 0xDD, 0xE9, 0x0A, + 0x30, 0x00, 0x25, 0x03, 0x21, 0x24, 0x68, 0x40, 0xF2, 0x0D, 0x47, 0x02, 0x2A, 0x0F, 0xD0, 0x10, 0x2A, 0x14, 0xD0, 0x0C, 0x2A, 0x29, 0xD0, 0x00, 0x93, 0x13, 0x46, 0x02, 0x22, 0xBB, 0x49, 0xBC, 0x48, 0xFF, 0xF5, 0x69, 0xFA, 0xFD, 0x1E, 0x04, + 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x01, 0x2B, 0x2C, 0xD1, 0x58, 0xB3, 0x8D, 0xF8, 0x04, 0x10, 0x01, 0x21, 0x1C, 0xE0, 0x05, 0x2B, 0x25, 0xD1, 0x20, 0xB3, 0x8D, 0xF8, 0x04, 0x10, 0x8D, 0xF8, 0x06, 0x10, 0x01, 0x78, 0x8D, 0xF8, 0x08, + 0x10, 0x41, 0x78, 0x82, 0x78, 0x01, 0xEB, 0x02, 0x21, 0xAD, 0xF8, 0x0A, + 0x10, 0xC1, 0x78, 0x00, 0x79, 0x01, 0xEB, 0x00, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x0A, + 0xE0, 0x01, 0x2B, 0x0E, 0xD1, 0x68, 0xB1, 0x8D, 0xF8, 0x04, 0x10, 0x02, 0x21, 0x8D, 0xF8, 0x06, 0x10, 0x00, 0x78, 0x8D, 0xF8, 0x08, 0x00, 0x00, 0x2C, 0xD0, 0xD0, 0x01, 0xA9, 0x30, 0x46, 0xA0, 0x47, 0xCC, 0xE7, 0x3D, 0x46, 0xCA, 0xE7, 0x2D, + 0xE9, 0xFF, 0x4F, 0x87, 0xB0, 0x4F, 0xF0, 0x00, 0x0A, + 0xDD, 0xE9, 0x14, 0x54, 0x9C, 0x4E, 0xDF, 0xF8, 0x64, 0x82, 0x57, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x0A, + 0x2A, 0x1A, 0xD0, 0x08, 0xDC, 0x04, 0x2A, 0x18, 0xD0, 0x4F, 0xF0, 0x04, 0x09, 0x06, 0x2A, 0x30, 0xD0, 0x08, 0x2A, 0x08, 0xD1, 0x46, 0xE0, 0x42, 0xF2, 0x90, 0x70, 0x4F, 0xF0, 0x0C, 0x0B, 0x0E, 0x2A, 0x5A, 0xD0, 0x12, 0x2A, 0x7D, 0xD0, 0x8E, + 0x49, 0x13, 0x46, 0x01, 0x22, 0x3C, 0x31, 0x30, 0x46, 0xFF, 0xF5, 0x0B, 0xFA, 0x40, 0xF2, 0x0A, + 0x4A, 0xE2, 0xE0, 0x88, 0x49, 0x4F, 0xF4, 0x00, 0x70, 0x0C, 0x31, 0x43, 0xF6, 0xEE, 0xFC, 0x85, 0x4A, 0x00, 0x20, 0x69, 0x46, 0x0C, 0x32, 0xC0, 0xF1, 0x05, 0x03, 0xD3, 0x5C, 0x0B, 0x54, 0x40, 0x1C, 0x06, 0x28, 0xF8, 0xDB, 0x00, 0x99, 0xC8, + 0xF8, 0x0C, 0x10, 0xBD, 0xF8, 0x04, 0x10, 0xA8, 0xF8, 0x10, 0x10, 0x22, 0x60, 0xA5, 0xF8, 0x00, 0x90, 0xC6, 0xE0, 0x42, 0xF2, 0x92, 0x70, 0x04, 0xF6, 0xAB, 0xF8, 0x79, 0x49, 0x83, 0x46, 0x03, 0x46, 0x01, 0x22, 0x6C, 0x31, 0x30, 0x46, 0xFF, + 0xF5, 0xE0, 0xF9, 0x75, 0x49, 0xDB, 0xF8, 0x60, 0x30, 0x01, 0x22, 0x80, 0x31, 0x30, 0x46, 0xC8, 0xF8, 0x04, 0x30, 0xFF, 0xF5, 0xD6, 0xF9, 0x6F, 0x48, 0x00, 0x1D, 0x17, 0xE0, 0x42, 0xF2, 0x93, 0x70, 0x04, 0xF6, 0x92, 0xF8, 0x6C, 0x49, 0x83, + 0x46, 0x03, 0x46, 0x01, 0x22, 0x98, 0x31, 0x30, 0x46, 0xFF, 0xF5, 0xC7, 0xF9, 0x68, 0x49, 0xDB, 0xF8, 0x60, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x30, 0x46, 0xC8, 0xF8, 0x08, 0x30, 0xFF, 0xF5, 0xBD, 0xF9, 0x62, 0x48, 0x08, 0x30, 0x20, 0x60, 0xC9, + 0xE7, 0x04, 0xF6, 0x7A, 0xF8, 0x5F, 0x4E, 0x41, 0x78, 0x14, 0x36, 0x81, 0x46, 0xB1, 0x70, 0x05, 0x21, 0x31, 0x70, 0x01, 0x21, 0x71, 0x70, 0x40, 0x78, 0xB0, 0x70, 0x49, 0x05, 0xF0, 0x78, 0x91, 0xF8, 0x14, 0x13, 0x40, 0xF0, 0x01, 0x00, 0x49, + 0x09, 0x61, 0xF3, 0x41, 0x00, 0x20, 0xF0, 0x08, 0x00, 0x40, 0xF0, 0x04, 0x00, 0xF0, 0x70, 0x04, 0xF6, 0x8E, 0xF8, 0xF1, 0x78, 0x60, 0xF3, 0x04, 0x11, 0xF1, 0x70, 0x4F, 0xF4, 0x00, 0x60, 0xB0, 0x80, 0x00, 0xE0, 0x13, 0xE0, 0x04, 0xF6, 0x83, + 0xF8, 0x68, 0xB1, 0x4F, 0x49, 0xB1, 0xEB, 0x09, 0x2F, 0x02, 0xD1, 0x4F, 0xF4, 0xA2, 0x60, 0x01, 0xE0, 0x4F, 0xF4, 0x22, 0x60, 0xB0, 0x60, 0x26, 0x60, 0xA5, 0xF8, 0x00, 0xB0, 0x5C, 0xE0, 0x4F, 0xF4, 0x7F, 0x60, 0xF7, 0xE7, 0x04, 0xF6, 0x40, + 0xF8, 0x43, 0x49, 0x07, 0x46, 0x03, 0x46, 0x01, 0x22, 0xC0, 0x31, 0x42, 0x48, 0xFF, 0xF5, 0x75, 0xF9, 0x3E, 0x4E, 0x20, 0x36, 0x17, 0xB1, 0xD7, 0xF8, 0x94, 0x01, 0x30, 0x60, 0x04, 0xF6, 0x5F, 0xF8, 0xE8, 0xB1, 0x42, 0xF2, 0x92, 0x70, 0x04, + 0xF6, 0x2B, 0xF8, 0x08, 0xB1, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x93, 0x70, 0x04, 0xF6, 0x24, 0xF8, 0x78, 0xB1, 0x00, 0x6E, 0xB0, 0x60, 0x71, 0x68, 0xCD, 0xE9, 0x00, 0x10, 0x32, 0x49, 0x03, 0x22, 0xD8, 0x31, 0x32, 0x48, 0x33, 0x68, 0xFF, + 0xF5, 0x54, 0xF9, 0x26, 0x60, 0xA5, 0xF8, 0x00, 0xB0, 0x24, 0xE0, 0xB0, 0x68, 0xEF, 0xE7, 0x42, 0xF2, 0x91, 0x70, 0x04, 0xF6, 0x0D, 0xF8, 0x08, 0xB1, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x92, 0x70, 0x04, 0xF6, 0x06, 0xF8, 0x08, 0xB1, 0x00, + 0x6E, 0xB0, 0x60, 0x42, 0xF2, 0x93, 0x70, 0x03, 0xF6, 0xFF, 0xFF, 0x00, 0xB3, 0x00, 0x6E, 0xF0, 0x60, 0xD6, 0xE9, 0x01, 0x12, 0x00, 0x91, 0xCD, 0xE9, 0x01, 0x20, 0x04, 0x22, 0x21, 0x49, 0x1F, 0x48, 0x33, 0x68, 0xFF, 0xF5, 0x2E, 0xF9, 0x10, + 0x20, 0x26, 0x60, 0x28, 0x80, 0x02, 0x20, 0x8D, 0xF8, 0x0C, 0x00, 0x8D, 0xF8, 0x0E, 0x90, 0x01, 0x27, 0xD8, 0xF8, 0x00, 0x20, 0x1A, 0xB1, 0x17, 0xB1, 0x03, 0xA9, 0x08, 0x98, 0x90, 0x47, 0x0B, 0xB0, 0x50, 0x46, 0xBD, 0xE8, 0xF0, 0x8F, 0xF0, + 0x68, 0xDE, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x14, 0x48, 0xD0, 0xE9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF5, 0x00, 0x71, 0x43, 0x69, 0x4F, 0xF4, 0x05, 0x72, 0x02, 0xA8, 0x46, 0xF6, 0x11, 0xFF, 0x20, 0xB1, 0x08, 0x48, 0x04, 0x60, 0x9D, + 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x09, 0x49, 0x07, 0x48, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x44, 0x31, 0x80, 0x1E, 0xFF, 0xF5, 0xFA, 0xF8, 0xFF, 0x20, 0x3E, 0xBD, 0x00, 0x00, 0x80, 0xBB, 0x20, 0x00, 0xFC, 0x07, 0x80, 0x08, 0x02, 0x33, 0x10, + 0x21, 0x00, 0x00, 0x20, 0x80, 0x04, 0x09, 0x80, 0x08, 0xF8, 0xB4, 0x20, 0x00, 0x2D, 0xE9, 0xF7, 0x4F, 0x86, 0xB0, 0x00, 0x24, 0x03, 0x94, 0x10, 0x20, 0x8D, 0xF8, 0x0C, 0x00, 0xDF, 0xF8, 0x24, 0x94, 0x0A, + 0x20, 0x96, 0x46, 0x04, 0x94, 0x8D, 0xF8, 0x0D, 0x00, 0x4F, 0xF4, 0x00, 0x62, 0x01, 0x26, 0x07, 0x27, 0xDF, 0xF8, 0x0C, 0xB4, 0xD9, 0xF8, 0x14, 0x00, 0x25, 0x46, 0xA9, 0xF6, 0x14, 0x0A, + 0x91, 0x42, 0x20, 0xD9, 0xCD, 0xE9, 0x00, 0x20, 0x0B, 0x46, 0x4C, 0x46, 0x03, 0x22, 0xFE, 0x49, 0x58, 0x46, 0xFF, 0xF5, 0xC6, 0xF8, 0xAA, 0xF8, 0x02, 0x50, 0x02, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x9A, 0xF8, 0x01, 0x10, 0x32, 0xE0, 0xBA, 0xF8, 0x02, 0x30, 0x8B, 0x42, 0x06, 0xD0, 0xD9, 0xF8, + 0x0C, 0x20, 0x00, 0xEB, 0x03, 0x0C, 0xC8, 0x46, 0x94, 0x45, 0x75, 0xD1, 0x72, 0x46, 0xD0, 0x46, 0x19, 0x46, 0xDA, 0xF8, 0x10, 0x00, 0x3E, 0xF6, 0x22, 0xFF, 0x28, 0xB3, 0xE6, 0x49, 0x4C, 0x46, 0x01, 0x22, 0x48, 0x31, 0x58, 0x46, 0xD9, 0xF8, + 0x14, 0x30, 0xFF, 0xF5, 0x92, 0xF8, 0xA8, 0xF8, 0x02, 0x50, 0x05, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x98, 0xF8, 0x01, 0x10, 0x03, 0xAB, 0x04, 0x22, 0x06, 0x98, 0x46, 0xF6, 0x1B, 0xFF, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0x82, 0x46, 0xB8, 0xF8, 0x02, 0x00, 0x00, 0x1B, 0x10, 0x28, 0x11, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0xCB, 0x48, 0x08, 0xF6, + 0x41, 0xF9, 0xD8, 0xF8, 0x10, 0x00, 0x20, 0x44, 0x01, 0x46, 0x00, 0xF6, 0x33, 0xFA, 0x10, 0x34, 0xA4, 0xB2, 0xE8, 0xE7, 0x01, 0xF0, 0x00, 0xFA, 0xB9, 0xF8, 0x04, 0x00, 0x44, 0x46, 0xD9, 0xF8, 0x14, 0x10, 0xB8, 0xF8, 0x02, 0x20, 0xD8, 0xF8, + 0x10, 0x30, 0x01, 0xF0, 0x54, 0xFB, 0x03, 0x00, 0x4F, 0xF4, 0x80, 0x5A, 0x19, 0xD0, 0xBC, 0x49, 0x01, 0x22, 0x7C, 0x31, 0x58, 0x46, 0xFF, 0xF5, 0x40, 0xF8, 0xC8, 0x46, 0xB9, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x61, 0x68, 0x01, 0xF0, 0x89, 0xFA, + 0x4F, 0xF0, 0x08, 0x09, 0xD0, 0xB1, 0x65, 0x80, 0xB3, 0x49, 0x63, 0x68, 0x01, 0x22, 0x45, 0x46, 0xB4, 0x31, 0xC8, 0xF8, 0x14, 0x30, 0x2E, 0xE0, 0x58, 0xE0, 0x62, 0x88, 0xD9, 0xF8, 0x14, 0x00, 0x10, 0x44, 0xC9, 0xF8, 0x14, 0x00, 0x61, 0x68, + 0x42, 0x1A, 0x52, 0x45, 0x02, 0xD3, 0x01, 0xF5, 0x80, 0x51, 0x61, 0x60, 0x65, 0x80, 0x8D, 0xF8, 0x0E, 0x60, 0x22, 0xE0, 0xD8, 0xF8, 0x14, 0x00, 0x61, 0x68, 0x40, 0x1A, 0x50, 0x45, 0x32, 0xD9, 0xA3, 0x49, 0xA1, 0x48, 0x00, 0x22, 0xF4, 0x31, + 0x80, 0x1C, 0xFF, 0xF5, 0x0E, 0xF8, 0x61, 0x68, 0xB8, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x01, 0xF5, 0x80, 0x51, 0x01, 0xF0, 0x56, 0xFA, 0x10, 0xB3, 0x65, 0x80, 0x63, 0x68, 0x9C, 0x49, 0x45, 0x46, 0x01, 0x22, 0xC8, 0xF8, 0x14, 0x30, 0x58, 0x46, + 0xFE, 0xF5, 0xFB, 0xFF, 0x8D, 0xF8, 0x0E, 0x90, 0x68, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x06, 0x98, 0x46, 0xF6, 0x88, 0xFE, 0x01, 0xF0, 0xA6, 0xF9, 0x69, 0xE7, 0x65, 0x80, + 0x8B, 0x49, 0x87, 0x48, 0x63, 0x68, 0x45, 0x46, 0x01, 0x22, 0x40, 0x31, 0x80, 0x1C, 0xC8, 0xF8, 0x14, 0x30, 0xFE, 0xF5, 0xD6, 0xFF, 0x8D, 0xF8, 0x0E, 0x70, 0xD9, 0xE7, 0xCD, 0xE9, 0x00, 0x30, 0x0B, 0x46, 0x83, 0x49, 0x02, 0x92, 0x54, 0x46, + 0x04, 0x22, 0x70, 0x31, 0x58, 0x46, 0xFE, 0xF5, 0xC8, 0xFF, 0x65, 0x80, 0x06, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0xD8, 0xF8, 0x14, 0x00, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x35, 0xE7, 0x3E, 0xB5, 0x70, 0x4B, 0x04, 0x46, 0x58, 0x7E, 0x01, 0x28, 0x1D, 0xD1, + 0x00, 0x22, 0x5A, 0x76, 0x02, 0x92, 0x10, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x07, 0x20, 0x8D, 0xF8, 0x09, 0x00, 0x8D, 0xF8, 0x0A, + 0x10, 0x0B, 0x46, 0x6A, 0x49, 0x66, 0x48, 0x01, 0x22, 0xD8, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0x98, 0xFF, 0x01, 0x21, 0x03, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x66, 0x48, 0x02, 0xAB, 0x04, 0x22, 0x41, 0x78, 0x20, 0x46, 0x46, 0xF6, 0x30, 0xFE, 0x3E, + 0xBD, 0x3E, 0xB5, 0x05, 0x46, 0x00, 0x20, 0x02, 0x90, 0x5C, 0x48, 0x80, 0x88, 0x01, 0xF0, 0x35, 0xFB, 0x04, 0x46, 0x03, 0x46, 0x58, 0x48, 0x01, 0x22, 0x5D, 0x49, 0x80, 0x1C, 0xFE, 0xF5, 0x7C, 0xFF, 0x01, 0x20, 0x14, 0xB1, 0x8D, 0xF8, 0x0A, + 0x00, 0x02, 0xE0, 0x05, 0x21, 0x8D, 0xF8, 0x0A, + 0x10, 0x10, 0x21, 0x8D, 0xF8, 0x08, 0x10, 0x03, 0x21, 0xCD, 0xE9, 0x00, 0x10, 0x53, 0x48, 0x8D, 0xF8, 0x09, 0x10, 0x02, 0xAB, 0x41, 0x78, 0x04, 0x22, 0x28, 0x46, 0x46, 0xF6, 0x08, 0xFE, 0x3E, 0xBD, 0x2D, 0xE9, 0xF7, 0x4F, 0x8C, 0xB0, 0x00, + 0x20, 0x05, 0x90, 0x06, 0x90, 0x07, 0x90, 0x92, 0xF8, 0x00, 0x80, 0x0E, 0x46, 0x00, 0x91, 0x49, 0x49, 0x43, 0x48, 0x15, 0x46, 0x57, 0x1C, 0x43, 0x46, 0x02, 0x22, 0xCD, 0xF8, 0x20, 0x80, 0x40, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0x4D, 0xFF, 0xDF, + 0xF8, 0x08, 0x91, 0x01, 0x24, 0x4F, 0xF0, 0x10, 0x0A, + 0x4F, 0xF0, 0x03, 0x0B, 0xB8, 0xF1, 0x0D, 0x0F, 0x0D, 0xD2, 0x08, 0x98, 0x58, 0xB1, 0xDF, 0xF8, 0xE0, 0x80, 0x0C, 0x28, 0x6A, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x69, 0x0D, 0xDD, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0x69, 0xF8, 0xF7, 0xF6, 0x8D, 0xF8, + 0x14, 0xA0, 0x08, 0x98, 0x8D, 0xF8, 0x15, 0x00, 0xFF, 0x20, 0x96, 0xE0, 0x11, 0x2E, 0x6A, 0xD1, 0x4F, 0xF4, 0x00, 0x16, 0x96, 0xF8, 0x14, 0x03, 0x80, 0x06, 0x26, 0xD5, 0x3A, 0x46, 0x10, 0x21, 0x30, 0x48, 0xFF, 0xF5, 0x77, 0xF9, 0x27, 0x4D, + 0x2D, 0x49, 0x03, 0x46, 0xED, 0x1C, 0x01, 0x22, 0x84, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0x18, 0xFF, 0x96, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x23, 0x48, 0x07, 0xF6, 0xF0, 0xFF, 0x39, 0x46, 0x08, 0x46, 0x00, 0xF6, + 0xE4, 0xF8, 0x3A, 0x46, 0x10, 0x21, 0x22, 0x48, 0xFF, 0xF5, 0x5C, 0xF9, 0x20, 0x49, 0x03, 0x46, 0x01, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0xFF, 0xFE, 0x3B, 0x78, 0x0A, + 0x93, 0xB8, 0x78, 0xFA, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x02, 0x20, 0x86, 0xB2, 0x38, 0x79, 0x7A, 0x79, 0x0D, 0xF1, 0x08, 0x0C, 0x00, 0xEB, 0x02, 0x20, 0x80, 0xB2, 0x09, 0x90, 0xB8, 0x79, 0xFA, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x85, 0xB2, 0x38, + 0x7A, 0x7A, 0x7A, 0x00, 0xEB, 0x02, 0x20, 0xBA, 0x7A, 0xFF, 0x7A, 0x12, 0x04, 0x02, 0xEB, 0x07, 0x62, 0xCD, 0xE9, 0x00, 0x16, 0x87, 0x18, 0x09, 0x98, 0x0B, 0x49, 0x8C, 0xE8, 0xA1, 0x00, 0x04, 0x48, 0x06, 0x22, 0xD4, 0x31, 0xC0, 0x1C, 0xFE, + 0xF5, 0xD4, 0xFE, 0x0A, + 0x9B, 0x11, 0xE0, 0x4F, 0xE2, 0x00, 0x31, 0x10, 0x21, 0xC8, 0xC3, 0x20, 0x00, 0x70, 0x09, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x94, 0x0A, + 0x80, 0x08, 0xB4, 0xBB, 0x20, 0x00, 0xA4, 0x0B, 0x80, 0x08, 0x00, 0x00, 0x50, 0x21, 0xF2, 0xE1, 0x88, 0xF8, 0x00, 0x30, 0xA8, 0xF8, 0x02, 0x60, 0x09, 0x98, 0xA8, 0xF8, 0x04, 0x00, 0xA8, 0xF8, 0x06, 0x50, 0xC8, 0xF8, 0x08, 0x70, 0x07, 0xF5, + 0x80, 0x67, 0xC8, 0xF8, 0x0C, 0x70, 0x05, 0x2B, 0x02, 0xD0, 0x01, 0x22, 0xFD, 0x49, 0x0C, 0xE0, 0xA0, 0xF5, 0x1C, 0x51, 0x90, 0x39, 0x0A, + 0x29, 0x1C, 0xD3, 0xA0, 0xF5, 0x7F, 0x41, 0xFE, 0x39, 0x18, 0xD0, 0xF7, 0x49, 0x01, 0x22, 0x03, 0x46, 0x30, 0x39, 0xF6, 0x48, 0xFE, 0xF5, 0x9C, 0xFE, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, + 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x46, 0xF6, 0x2F, 0xFD, 0x0F, 0xB0, 0x12, 0xE6, 0x01, 0xF0, 0x33, 0xF8, 0xB8, 0xF8, 0x04, 0x00, 0xEB, 0x4B, 0x0C, 0x22, 0x00, 0x21, 0x01, 0xF0, 0x8B, 0xF9, 0x05, + 0x46, 0x01, 0xF0, 0x41, 0xF8, 0xC5, 0xB1, 0x2A, 0x46, 0xE7, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFE, 0xF5, 0x20, 0xFE, 0xB8, 0xF8, 0x04, 0x00, 0x01, 0xF0, 0x08, 0xFA, 0x3E, 0xF6, 0xCB, 0xFC, 0xDE, 0x49, 0x00, 0x22, 0x54, 0x39, 0xEC, 0x48, 0xFE, + 0xF5, 0x6B, 0xFE, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x8D, 0xF8, 0x16, 0x40, 0x01, 0xE1, 0xD8, 0xF8, 0x14, 0x00, 0x0C, 0x30, 0xC8, 0xF8, 0x14, 0x00, 0xEC, 0xE7, 0x07, 0x2E, 0x04, 0xD0, 0xD4, 0x49, 0x01, 0x22, 0x33, 0x46, 0x70, + 0x31, 0x92, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xA8, 0xF8, 0x04, 0x30, 0xB8, 0x78, 0xFA, 0x78, 0x7C, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x3A, 0x79, 0x12, 0x04, 0x02, 0xEB, 0x04, 0x62, 0x80, 0x18, 0x07, 0xE0, 0x7F, + 0xE1, 0x5D, 0xE1, 0x2E, 0xE1, 0xCE, 0xE0, 0x75, 0xE0, 0x53, 0xE0, 0x4A, 0xE0, 0x12, 0xE0, 0xC8, 0xF8, 0x14, 0x00, 0x01, 0xD0, 0x0C, 0x28, 0x04, 0xD1, 0x00, 0x21, 0xA9, 0xF8, 0x02, 0x10, 0xC9, 0xF8, 0x04, 0x10, 0x00, 0x90, 0xBF, 0x49, 0xBF, + 0x48, 0x02, 0x22, 0x30, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0x2B, 0xFE, 0x5C, 0xE1, 0x03, 0x2E, 0x03, 0xD0, 0x33, 0x46, 0x01, 0x22, 0xC9, 0x49, 0x5F, 0xE0, 0x38, 0x78, 0x79, 0x78, 0xB8, 0x4D, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xC5, 0x49, 0xED, + 0x1C, 0x44, 0x46, 0xA8, 0xF8, 0x04, 0x30, 0x01, 0x22, 0x64, 0x39, 0x28, 0x46, 0xFE, 0xF5, 0x14, 0xFE, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x7A, 0x03, 0xC0, 0x06, 0xE2, 0xD5, 0xE0, 0x68, 0xB0, 0xF5, 0x80, 0x1F, 0xDE, 0xD9, 0x6F, 0xF0, 0x7F, + 0x61, 0x08, 0x44, 0xC0, 0xF3, 0x07, 0x50, 0x09, 0x17, 0x01, 0xEB, 0x40, 0x11, 0x8C, 0xB2, 0xB6, 0x49, 0x83, 0x00, 0x02, 0x22, 0x40, 0x39, 0x28, 0x46, 0x00, 0x94, 0xFE, 0xF5, 0xF9, 0xFD, 0x03, 0x22, 0x0F, 0x21, 0x20, 0x46, 0x08, 0xF6, 0x46, + 0xFD, 0x25, 0xE1, 0xAF, 0x49, 0xA0, 0x48, 0x00, 0x22, 0x2C, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0xEC, 0xFD, 0x1D, 0xE1, 0xAB, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x9B, 0x48, 0xFE, 0xF5, 0xE5, 0xFD, 0xB8, 0xF8, 0x04, 0x00, 0xA0, 0xF5, 0x1C, 0x51, 0x90, + 0x39, 0x0A, + 0x29, 0x0A, + 0xD2, 0x03, 0xF6, 0xED, 0xFC, 0x38, 0xB1, 0x81, 0x78, 0x09, 0x06, 0x04, 0xD4, 0x20, 0xF0, 0x7F, 0x41, 0x02, 0x20, 0x03, 0xF6, 0xB7, 0xF8, 0x4F, 0xF4, 0xFA, 0x60, 0x1D, 0xF6, 0x58, 0xFC, 0xD4, 0x21, 0x03, 0x20, 0xFF, 0xF7, 0x6B, 0xF8, 0xFC, + 0xE0, 0x03, 0x2E, 0x07, 0xD0, 0x9A, 0x49, 0x01, 0x22, 0x33, 0x46, 0xE4, 0x31, 0x89, 0x48, 0xFE, 0xF5, 0xC1, 0xFD, 0xF2, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x94, 0x4F, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0x93, 0x49, 0x45, 0x46, 0xA8, 0xF8, 0x04, + 0x30, 0x01, 0x22, 0x68, 0x31, 0x38, 0x46, 0xFE, 0xF5, 0xB1, 0xFD, 0xA8, 0x88, 0x80, 0x4E, 0xA0, 0xF5, 0x7F, 0x41, 0x10, 0x36, 0xFE, 0x39, 0x2E, 0xD0, 0x32, 0x1D, 0x31, 0x46, 0x3E, 0xF6, 0xF1, 0xFA, 0x00, 0x20, 0x68, 0x61, 0x00, 0x90, 0x87, + 0x49, 0x02, 0x22, 0x9C, 0x31, 0x38, 0x46, 0x2B, 0x69, 0xFE, 0xF5, 0x9C, 0xFD, 0x8D, 0xF8, 0x14, 0xA0, 0x06, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x28, 0x69, 0x8D, 0xF8, 0x17, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x18, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x19, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1A, 0x00, 0x68, 0x69, 0x8D, 0xF8, 0x1B, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x1C, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x1D, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1E, 0x00, 0x0B, 0x20, 0xF4, 0xE0, 0x05, 0x20, 0x02, 0xF6, 0xE9, 0xFF, 0x32, 0x46, 0x04, 0x21, 0x60, 0x30, 0x03, 0xF6, 0xC1, 0xFA, 0xCB, 0xE7, 0x07, 0x20, + 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x00, 0x09, 0x2E, 0x0D, 0xD0, 0x33, 0x46, 0x01, 0x22, 0x6B, 0x49, 0x5B, 0x48, 0xFE, 0xF5, 0x65, 0xFD, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x43, 0xE0, + 0x98, 0xF8, 0x19, 0x00, 0xC2, 0x46, 0x30, 0xB1, 0x63, 0x49, 0x00, 0x22, 0xA0, 0x39, 0x52, 0x48, 0xFE, 0xF5, 0x53, 0xFD, 0x26, 0xE0, 0x68, 0x78, 0xA9, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x87, 0xB2, 0xE8, 0x78, 0x29, 0x79, 0x00, 0xEB, 0x01, 0x20, + 0x86, 0xB2, 0x68, 0x79, 0xA9, 0x79, 0x32, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x1F, 0xFA, 0x80, 0xF8, 0xE8, 0x79, 0x29, 0x7A, 0x43, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x85, 0xB2, 0x6F, 0xF0, 0x01, 0x00, 0x00, 0xEB, 0x46, 0x01, 0x00, 0xEB, 0x47, 0x00, + 0x89, 0xB2, 0x80, 0xB2, 0x00, 0x95, 0xCD, 0xE9, 0x01, 0x01, 0x39, 0x46, 0x00, 0x20, 0x44, 0xF6, 0x42, 0xFE, 0x18, 0xB1, 0x58, 0x46, 0x8D, 0xF8, 0x16, 0xB0, 0xA0, 0xE0, 0x8A, 0xF8, 0x19, 0x40, 0x00, 0x96, 0x49, 0x49, 0x38, 0x48, 0xCD, 0xE9, + 0x01, 0x85, 0x3B, 0x46, 0x04, 0x22, 0x5C, 0x39, 0x80, 0x1C, 0xFE, 0xF5, 0x1A, 0xFD, 0x4B, 0xE0, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x46, 0xF6, 0xB7, 0xFB, 0x45, 0xE0, 0x31, 0x49, 0x40, 0xF2, 0x75, 0x20, 0x18, 0x31, 0x0C, 0x9A, 0x44, 0xF6, + 0x1C, 0xFD, 0x4F, 0xF4, 0x00, 0x60, 0x00, 0x90, 0x3B, 0x49, 0x2B, 0x48, 0x45, 0x46, 0x98, 0xF8, 0x18, 0x30, 0x02, 0x22, 0x3C, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0xFF, 0xFC, 0x89, 0xF8, 0x00, 0x40, 0x8D, 0xF8, 0x14, 0xA0, 0x09, 0x21, 0x8D, 0xF8, + 0x15, 0x10, 0x8D, 0xF8, 0x16, 0x40, 0x00, 0x21, 0x08, 0x22, 0x8D, 0xF8, 0x17, 0x10, 0x8D, 0xF8, 0x18, 0x20, 0x2A, 0x7E, 0x8D, 0xF8, 0x19, 0x20, 0x8D, 0xF8, 0x1A, 0x10, 0x07, 0x21, 0xCD, 0xE9, 0x00, 0x14, 0x05, 0xAB, 0x04, 0x22, 0xCB, 0xE7, + 0x38, 0x78, 0x79, 0x78, 0x02, 0x22, 0x00, 0xEB, 0x01, 0x20, 0x85, 0xB2, 0xB8, 0x78, 0xF9, 0x78, 0x2B, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x84, 0xB2, 0x23, 0x49, 0x13, 0x48, 0x7C, 0x31, 0xC0, 0x1C, 0x00, 0x94, 0xFE, 0xF5, 0xD2, 0xFC, 0x22, 0x46, + 0x29, 0x46, 0x0C, 0x98, 0xFF, 0xF7, 0xE2, 0xFB, 0x1E, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x3C, 0xAE, 0x08, 0x99, 0x0C, 0x98, 0x90, 0x47, 0x37, 0xE6, 0x8D, 0xF8, 0x14, 0xA0, 0x0B, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x02, 0xA9, 0x42, 0xF2, + 0x90, 0x70, 0x3E, 0xF6, 0xE0, 0xF9, 0x20, 0xB1, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xFF, 0x20, 0x2A, 0xE0, 0x25, 0xE0, 0x44, 0x0D, 0x80, 0x08, 0x00, 0x31, 0x10, 0x21, 0xC8, 0xC3, 0x20, 0x00, 0x44, 0x46, 0x55, 0x5F, 0x4F, 0x50, 0x43, 0x4F, + 0x44, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5F, 0x44, 0x46, 0x55, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x00, + 0x02, 0x33, 0x10, 0x21, 0x50, 0x0E, 0x80, 0x08, 0x08, 0x10, 0x80, 0x08, 0x60, 0xB9, 0x20, 0x00, 0x9D, 0xF8, 0x08, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x8D, 0xF8, 0x17, 0x00, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x04, 0x05, 0xAB, 0x04, 0x22, 0x67, 0xE7, + 0x03, 0x46, 0x01, 0x22, 0x88, 0x49, 0x89, 0x48, 0xB8, 0xE6, 0x2D, 0xE9, 0xFE, 0x4F, 0x88, 0x4F, 0x05, 0x46, 0xA7, 0xF6, 0x14, 0x04, 0x88, 0x46, 0x78, 0x69, 0x61, 0x88, 0xFA, 0x68, 0x8D, 0xE8, 0x07, 0x00, 0x81, 0x49, 0x2B, 0x46, 0x04, 0x22, + 0x3C, 0x31, 0x80, 0x48, 0xFE, 0xF5, 0x69, 0xFC, 0xDF, 0xF8, 0xF8, 0xA1, 0x20, 0x78, 0xAA, 0xF1, 0x03, 0x0A, + 0xC0, 0xB1, 0x60, 0x88, 0x43, 0x19, 0x4F, 0xF4, 0x00, 0x60, 0x83, 0x42, 0x08, 0xD9, 0x77, 0x49, 0x00, 0x90, 0x02, 0x22, 0xAC, 0x31, 0x50, 0x46, 0xFE, 0xF5, 0x56, 0xFC, 0x3E, 0xF6, 0xAE, 0xFA, 0x61, 0x88, 0x20, 0x69, 0x2A, 0x46, 0x08, 0x44, + 0x41, 0x46, 0x50, 0xF6, 0x6B, 0xFE, 0x60, 0x88, 0x28, 0x44, 0x70, 0xE0, 0x60, 0x88, 0x4F, 0xF4, 0xFF, 0x66, 0x43, 0x19, 0xB3, 0x42, 0x07, 0xD9, 0x02, 0x22, 0x6D, 0x49, 0x50, 0x46, 0x00, 0x96, 0xFE, 0xF5, 0x3E, 0xFC, 0x3E, 0xF6, 0x96, 0xFA, + 0x60, 0x88, 0x79, 0x69, 0x28, 0x44, 0xFB, 0x68, 0x08, 0x44, 0xA1, 0x46, 0x98, 0x42, 0x07, 0xD9, 0x66, 0x49, 0x01, 0x22, 0x68, 0x31, 0x50, 0x46, 0xFE, 0xF5, 0x2E, 0xFC, 0x3E, 0xF6, 0x86, 0xFA, 0x10, 0x2D, 0x1D, 0xD3, 0x4F, 0xF4, 0x00, 0x10, + 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0xDF, 0xF8, 0x7C, 0xB1, 0x00, 0x24, 0x82, 0x46, 0x28, 0x1B, 0x10, 0x28, 0x10, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x58, 0x46, 0x07, 0xF6, 0xF5, 0xFC, + 0x08, 0xEB, 0x04, 0x00, 0x01, 0x46, 0xFF, 0xF5, 0xE8, 0xFD, 0x10, 0x34, 0xA4, 0xB2, 0xEB, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xD9, 0xF8, 0x10, 0x00, 0x4C, 0x46, 0x08, 0x44, 0x2A, 0x46, 0x41, 0x46, 0x50, 0xF6, 0x20, 0xFE, 0x60, 0x88, 0x28, 0x44, + 0x80, 0xB2, 0x60, 0x80, 0xB0, 0x42, 0x04, 0xD0, 0x79, 0x69, 0x01, 0x44, 0xF8, 0x68, 0x81, 0x42, 0x1E, 0xD1, 0x00, 0xF0, 0xA0, 0xFD, 0xB8, 0x88, 0x79, 0x69, 0x62, 0x88, 0x23, 0x69, 0x00, 0xF0, 0xF9, 0xFE, 0x05, 0x46, 0x00, 0xF0, 0xAF, 0xFD, + 0x65, 0xB1, 0x2A, 0x46, 0x43, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFE, 0xF5, 0x8E, 0xFB, 0xB8, 0x88, 0x00, 0xF0, 0x77, 0xFF, 0xBD, 0xE8, 0xFE, 0x4F, 0x3E, 0xF6, 0x38, 0xBA, 0x61, 0x88, 0x78, 0x69, 0x08, 0x44, 0x78, 0x61, 0x00, 0x20, 0x60, 0x80, + 0xBD, 0xE8, 0xFE, 0x8F, 0x10, 0xB5, 0x03, 0x46, 0xDD, 0xE9, 0x02, 0x01, 0x00, 0x24, 0x04, 0x2A, 0x0B, 0xD0, 0x02, 0x2A, 0x0F, 0xD0, 0x32, 0x49, 0x13, 0x46, 0x01, 0x22, 0xD0, 0x31, 0x40, 0x48, 0xFE, 0xF5, 0xC6, 0xFB, 0x40, 0xF2, 0x0A, + 0x40, 0x10, 0xBD, 0x0A, + 0x46, 0x01, 0x46, 0x18, 0x46, 0xFF, 0xF7, 0x5A, 0xFC, 0x01, 0xE0, 0xFF, 0xF7, 0x3F, 0xFF, 0x20, 0x46, 0x10, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x25, 0x88, 0x46, 0x1E, 0x46, 0x8D, 0xF8, 0x05, 0x50, 0x00, 0x93, 0x24, 0x49, 0x17, 0x46, 0x8D, + 0xF8, 0x04, 0x00, 0x13, 0x46, 0x2C, 0x46, 0x02, 0x22, 0xFC, 0x31, 0x30, 0x48, 0xFE, 0xF5, 0xA6, 0xFB, 0x05, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x2E, 0x48, 0x82, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, + 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xF0, 0x07, 0x8D, 0xF8, 0x05, 0x50, 0x02, 0xD0, 0x8D, 0xF8, 0x06, 0x50, 0xED, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xE9, 0xE7, 0x7C, 0xB5, 0x24, 0x49, 0x05, 0x46, 0xD1, 0xE9, 0x01, 0x02, 0xCD, 0xE9, 0x00, + 0x02, 0x20, 0x48, 0x0B, 0x68, 0xA8, 0x22, 0x20, 0x49, 0x40, 0x1C, 0x46, 0xF6, 0x87, 0xF9, 0x1C, 0x4C, 0x28, 0xB1, 0x04, 0xF1, 0x14, 0x00, 0xA5, 0x60, 0x20, 0x61, 0x60, 0x78, 0x7C, 0xBD, 0x17, 0x48, 0x63, 0x78, 0x01, 0x22, 0x1A, 0x49, 0x80, + 0x1E, 0xFE, 0xF5, 0x70, 0xFB, 0xFF, 0x20, 0x60, 0x70, 0x7C, 0xBD, 0xC0, 0x10, 0x80, 0x08, 0x03, 0x31, 0x10, 0x21, 0xC8, 0xC3, 0x20, 0x00, 0xD4, 0x11, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x64, 0x66, 0x75, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x70, 0x61, 0x63, 0x6B, 0x65, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, + 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x02, 0x33, 0x10, 0x21, 0xB4, 0xBB, 0x20, 0x00, 0x28, 0xB5, 0x20, 0x00, 0x4C, 0xB8, 0x20, 0x00, 0x00, 0x13, 0x80, 0x08, 0x1F, 0xB5, 0x4A, 0x20, 0x00, 0x90, 0x38, 0x4B, 0x08, 0x22, 0x20, 0x21, 0x37, + 0x48, 0x1C, 0xF6, 0x7F, 0xFD, 0x4B, 0x20, 0x00, 0x90, 0x35, 0x48, 0x33, 0x4B, 0x01, 0x22, 0x40, 0x21, 0x00, 0x1F, 0x1C, 0xF6, 0x76, 0xFD, 0x31, 0x4C, 0x20, 0x22, 0x08, 0x3C, 0xD4, 0xE9, 0x01, 0x01, 0x42, 0xF6, 0x2A, 0xFD, 0x00, 0xF0, 0x30, + 0xF9, 0x52, 0x25, 0x4F, 0xF0, 0xFF, 0x37, 0x57, 0x26, 0x00, 0x95, 0x29, 0x4B, 0x3A, 0x46, 0x03, 0xA9, 0x60, 0x68, 0x1C, 0xF6, 0x0A, + 0xFE, 0x00, 0x28, 0xF6, 0xD0, 0x9D, 0xF8, 0x0C, 0x00, 0x02, 0x28, 0x02, 0xD0, 0x42, 0xF6, 0x82, 0xFD, 0xEF, 0xE7, 0x00, 0x96, 0x21, 0x4B, 0x00, 0x22, 0x01, 0xA9, 0xA0, 0x68, 0x1C, 0xF6, 0xFA, 0xFD, 0x00, 0x28, 0xE6, 0xD0, 0xDD, 0xE9, 0x01, + 0x01, 0x00, 0xF0, 0x52, 0xFB, 0xE1, 0xE7, 0x1C, 0xB5, 0x01, 0x21, 0x88, 0x02, 0x00, 0x23, 0xAF, 0xF2, 0x83, 0x02, 0xCD, 0xE9, 0x00, 0x01, 0x18, 0x48, 0x18, 0xA1, 0x08, 0x38, 0x1D, 0xF6, 0xAC, 0xFA, 0x1C, 0xBD, 0x7C, 0xB5, 0x02, 0x22, 0x8D, + 0xF8, 0x04, 0x20, 0x13, 0x4C, 0x68, 0x22, 0x11, 0x4B, 0x00, 0x92, 0x08, 0x3C, 0x01, 0x46, 0x0E, 0x33, 0x00, 0x22, 0xA0, 0x68, 0x1C, 0xF6, 0xA6, 0xFD, 0x0F, 0x4D, 0x58, 0xB1, 0x6D, 0x20, 0x0B, 0x4B, 0x00, 0x90, 0x0E, 0x33, 0x00, 0x22, 0x01, + 0xA9, 0x60, 0x68, 0x1C, 0xF6, 0x9B, 0xFD, 0x20, 0xB1, 0x01, 0x20, 0x7C, 0xBD, 0x00, 0x22, 0x09, 0x49, 0x02, 0xE0, 0x08, 0x49, 0x00, 0x22, 0x1C, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0xCC, 0xFA, 0x00, 0x20, 0x7C, 0xBD, 0x00, 0x00, 0x34, 0xB5, 0x20, + 0x00, 0xEC, 0xC3, 0x20, 0x00, 0x61, 0x70, 0x70, 0x00, 0x00, 0x30, 0x10, 0x21, 0x2C, 0x13, 0x80, 0x08, 0x00, 0xB5, 0x9D, 0xB0, 0x28, 0x22, 0x7D, 0x49, 0x68, 0x46, 0x50, 0xF6, 0x5D, 0xFD, 0x00, 0x20, 0x8D, 0xF8, 0x44, 0x00, 0x07, 0x21, 0x8D, + 0xF8, 0x40, 0x00, 0x8D, 0xF8, 0x30, 0x10, 0x0B, 0x90, 0x4F, 0xF4, 0xB0, 0x71, 0xAD, 0xF8, 0x68, 0x10, 0x4F, 0xF4, 0xC0, 0x71, 0xAD, 0xF8, 0x6C, 0x10, 0x01, 0x21, 0x8D, 0xF8, 0x3C, 0x00, 0x0A, + 0x90, 0xAD, 0xF8, 0x38, 0x00, 0x8D, 0xF8, 0x34, 0x00, 0x03, 0x22, 0x8D, 0xF8, 0x48, 0x10, 0xAD, 0xF8, 0x4C, 0x10, 0x8D, 0xF8, 0x50, 0x20, 0x8D, 0xF8, 0x54, 0x00, 0x8D, 0xF8, 0x58, 0x00, 0x17, 0x90, 0x8D, 0xF8, 0x60, 0x00, 0xAD, 0xF8, 0x64, + 0x10, 0x6A, 0x46, 0x28, 0x21, 0x40, 0xF2, 0x22, 0x20, 0x43, 0xF6, 0x7E, 0xFB, 0x0E, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x21, 0x20, 0x43, 0xF6, 0x78, 0xFB, 0x0F, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x23, 0x20, 0x43, 0xF6, 0x72, 0xFB, 0x10, 0xAA, 0x01, + 0x21, 0x40, 0xF2, 0x63, 0x20, 0x48, 0xF6, 0x90, 0xFC, 0x11, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x19, 0x70, 0x48, 0xF6, 0x8A, 0xFC, 0x0A, + 0xAA, 0x06, 0x21, 0x40, 0xF2, 0x65, 0x20, 0x48, 0xF6, 0x84, 0xFC, 0x0C, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x48, 0xF6, 0x7E, 0xFC, 0x0D, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x48, 0xF6, 0x78, 0xFC, 0x1A, 0xAA, 0x02, 0x21, 0x4F, + 0xF4, 0x1A, 0x70, 0x48, 0xF6, 0x72, 0xFC, 0x1B, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x48, 0xF6, 0x6C, 0xFC, 0x48, 0x4A, 0x13, 0x21, 0x14, 0x3A, 0x40, 0xF2, 0x61, 0x20, 0x48, 0xF6, 0x65, 0xFC, 0x45, 0x4A, 0x04, 0x21, 0x18, 0x3A, 0x40, + 0xF2, 0x62, 0x20, 0x48, 0xF6, 0x5E, 0xFC, 0x12, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x02, 0x20, 0x42, 0xF6, 0xE5, 0xFC, 0x13, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x03, 0x20, 0x42, 0xF6, 0xDF, 0xFC, 0x14, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x01, 0x70, 0x42, + 0xF6, 0xD9, 0xFC, 0x15, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x05, 0x20, 0x42, 0xF6, 0xD3, 0xFC, 0x17, 0xAA, 0x04, 0x21, 0x40, 0xF2, 0x11, 0x20, 0x42, 0xF6, 0xEF, 0xFD, 0x16, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x12, 0x20, 0x42, 0xF6, 0xE9, 0xFD, 0x18, + 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x13, 0x20, 0x42, 0xF6, 0xE3, 0xFD, 0x19, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0x42, 0xF6, 0xDD, 0xFD, 0x2A, 0x48, 0x43, 0xF6, 0x04, 0xFB, 0x1D, 0xB0, 0x00, 0xBD, 0x10, 0xB5, 0x04, 0x20, 0x45, 0xF6, 0x5F, + 0xFF, 0x27, 0x48, 0xFE, 0xF7, 0xA7, 0xFE, 0x26, 0x49, 0x08, 0x70, 0x24, 0x48, 0xFE, 0xF7, 0x5D, 0xFF, 0x25, 0x49, 0x08, 0x70, 0x22, 0x48, 0xFF, 0xF7, 0xE7, 0xF8, 0x23, 0x49, 0x08, 0x70, 0x1F, 0x48, 0xFF, 0xF7, 0x6D, 0xFE, 0x22, 0x49, 0x08, + 0x70, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0x48, 0x45, 0xF6, 0x5F, 0xBF, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x10, 0xB5, 0xAF, 0xF2, 0x07, 0x00, 0x1C, 0x49, 0x08, 0x60, 0xAF, 0xF2, 0x0D, 0x00, 0x1B, 0x49, 0x08, 0x60, 0xFE, 0xF7, 0x83, + 0xFD, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0x20, 0xFF, 0xF5, 0xDF, 0xB8, 0xFF, 0xF7, 0xDD, 0xBE, 0x16, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x01, 0xF0, 0xB1, 0xFB, 0x01, 0x20, 0x43, 0xF6, 0x84, 0xFA, 0x00, 0xF0, 0x07, 0xFE, 0xFF, 0xF7, 0x12, 0xFF, 0xFF, + 0xF7, 0xBF, 0xFF, 0xFF, 0xF7, 0xDE, 0xFF, 0xFF, 0xF7, 0xCB, 0xFE, 0x0E, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFE, 0xF5, 0x6F, 0xF9, 0x1D, 0xF6, 0x76, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0x74, 0xB5, 0x20, 0x00, 0x2B, 0x9B, 0x20, 0x00, 0x7B, + 0x9B, 0x20, 0x00, 0xFC, 0xC3, 0x20, 0x00, 0xFD, 0xC3, 0x20, 0x00, 0xFE, 0xC3, 0x20, 0x00, 0xFF, 0xC3, 0x20, 0x00, 0x94, 0xB9, 0x20, 0x00, 0x90, 0xB9, 0x20, 0x00, 0x78, 0xB9, 0x20, 0x00, 0x43, 0x6F, 0x6D, 0x70, 0x6C, 0x65, 0x74, 0x65, 0x64, + 0x20, 0x4F, 0x54, 0x41, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x21, 0x00, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x28, 0x01, 0xD3, 0x00, 0x20, 0x10, 0xBD, 0x1A, 0x49, 0x00, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x80, 0x04, 0x08, 0x22, 0x18, 0x49, 0x20, + 0x68, 0x50, 0xF6, 0x65, 0xFB, 0x98, 0xB1, 0xA2, 0x69, 0x61, 0x68, 0xE0, 0x68, 0x50, 0xF6, 0xAA, 0xFB, 0xE2, 0x69, 0xA1, 0x68, 0x20, 0x69, 0x50, 0xF6, 0xA5, 0xFB, 0x21, 0x6A, 0x60, 0x69, 0x50, 0xF6, 0x62, 0xFC, 0x20, 0x68, 0x0E, 0x49, 0x02, + 0x68, 0x0A, + 0x60, 0x40, 0x68, 0x48, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x09, 0x4D, 0x00, 0x24, 0x04, 0xEB, 0xC4, 0x00, 0x08, 0x22, 0x55, 0xF8, 0x20, 0x00, 0x06, 0x49, 0x50, 0xF6, 0x43, 0xFB, 0x20, 0xB1, 0x64, 0x1C, 0x03, 0x2C, 0xF3, 0xDB, 0x03, + 0x20, 0x70, 0xBD, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0x00, 0xF4, 0xB8, 0x20, 0x00, 0xF0, 0xC3, 0x20, 0x00, 0xF8, 0xB5, 0x0C, 0x46, 0x15, 0x46, 0x00, 0x92, 0xFE, 0x49, 0x03, 0x46, 0x02, 0x22, 0xFE, 0x4E, 0x30, 0x46, 0xFE, 0xF5, 0x58, 0xF9, 0x54, + 0xB1, 0x01, 0x2C, 0x0C, 0xD0, 0x01, 0x22, 0x01, 0xB0, 0x23, 0x46, 0xB0, 0x1E, 0xBD, 0xE8, 0xF0, 0x40, 0xF8, 0x49, 0xFE, 0xF5, 0x4C, 0xB9, 0xF5, 0x49, 0x00, 0x22, 0x38, 0x31, 0x04, 0xE0, 0x4F, 0xF0, 0x00, 0x02, 0x35, 0xB1, 0xF3, 0x49, 0x48, + 0x39, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xFE, 0xF5, 0x3E, 0xB9, 0xEE, 0x49, 0x74, 0x31, 0xF7, 0xE7, 0x30, 0xB5, 0xED, 0x4C, 0x85, 0xB0, 0x05, 0x46, 0x59, 0xB1, 0x01, 0x29, 0x2B, 0xD0, 0x02, 0x29, 0x27, 0xD1, 0x05, 0xB0, 0x20, 0x46, 0xBD, + 0xE8, 0x30, 0x40, 0x00, 0x22, 0xE8, 0x49, 0xFE, 0xF5, 0x2A, 0xB9, 0x02, 0x46, 0x04, 0xA9, 0x40, 0xF2, 0x72, 0x20, 0x44, 0xF6, 0x34, 0xF9, 0x2A, 0x46, 0x03, 0xA9, 0x40, 0xF2, 0x73, 0x20, 0x44, 0xF6, 0x2E, 0xF9, 0x2A, 0x46, 0x02, 0xA9, 0x4F, + 0xF4, 0x1D, 0x70, 0x44, 0xF6, 0x28, 0xF9, 0xBD, 0xF8, 0x08, 0x10, 0xBD, 0xF8, 0x0C, 0x00, 0xCD, 0xE9, 0x00, 0x01, 0xDA, 0x49, 0xBD, 0xF8, 0x10, 0x30, 0x03, 0x22, 0x70, 0x31, 0x20, 0x46, 0xFE, 0xF5, 0x0A, + 0xF9, 0x05, 0xB0, 0x30, 0xBD, 0x05, 0xB0, 0xD5, 0x49, 0x13, 0x46, 0xD2, 0x48, 0xBD, 0xE8, 0x30, 0x40, 0x01, 0x22, 0x40, 0x39, 0x80, 0x1E, 0xFE, 0xF5, 0xFD, 0xB8, 0x08, 0xB5, 0x03, 0x46, 0x00, 0x91, 0xCE, 0x49, 0x02, 0x22, 0x34, 0x31, 0xCB, + 0x48, 0xFE, 0xF5, 0xF4, 0xF8, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0xCB, 0x4E, 0x80, 0x46, 0x8A, 0xB0, 0x0D, 0x46, 0xF0, 0x78, 0xCD, 0xE9, 0x00, 0x05, 0xC4, 0x49, 0xC4, 0x4F, 0x14, 0x46, 0x02, 0x92, 0x43, 0x46, 0x04, 0x22, 0xF8, 0x39, 0x38, + 0x46, 0xFE, 0xF5, 0xE0, 0xF8, 0x15, 0xB1, 0x02, 0x2D, 0x49, 0xD1, 0x1C, 0xE0, 0xA4, 0xF5, 0x80, 0x70, 0x13, 0x38, 0x0A, + 0xD0, 0xB4, 0xF5, 0x8B, 0x7F, 0x07, 0xD0, 0xB9, 0x49, 0xBA, 0x48, 0x23, 0x46, 0x01, 0x22, 0xA4, 0x39, 0x80, 0x1E, 0xFE, 0xF5, 0xCD, 0xF8, 0x30, 0x78, 0x40, 0xB1, 0x00, 0x20, 0x30, 0x70, 0x3E, 0xF6, 0x03, 0xF9, 0xD2, 0x21, 0x01, 0x20, 0xFE, + 0xF7, 0x63, 0xFB, 0x2E, 0xE0, 0x48, 0xF6, 0xF4, 0xFB, 0x2B, 0xE0, 0x42, 0x46, 0x06, 0xA9, 0x40, 0xF2, 0x72, 0x20, 0x44, 0xF6, 0xC9, 0xF8, 0x42, 0x46, 0x08, 0xA9, 0x40, 0xF2, 0x73, 0x20, 0x44, 0xF6, 0xC3, 0xF8, 0x42, 0x46, 0x09, 0xA9, 0x4F, + 0xF4, 0x1D, 0x70, 0x44, 0xF6, 0xBD, 0xF8, 0x07, 0xAA, 0x04, 0xA9, 0x40, 0x46, 0x44, 0xF6, 0x70, 0xF9, 0x04, 0xA9, 0xA7, 0x48, 0xFE, 0xF5, 0x61, 0xFA, 0x03, 0x46, 0x9D, 0xF8, 0x1C, 0x00, 0xBD, 0xF8, 0x24, 0x40, 0xBD, 0xF8, 0x20, 0x20, 0xBD, + 0xF8, 0x18, 0x10, 0x8D, 0xE8, 0x17, 0x00, 0x9B, 0x49, 0x05, 0x22, 0x84, 0x39, 0x38, 0x46, 0xFE, 0xF5, 0x93, 0xF8, 0xF5, 0x70, 0x0A, + 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0xC4, 0xB2, 0xC4, 0xF3, 0x81, 0x05, 0xCD, 0xE9, 0x00, 0x51, 0xDF, 0xF8, 0x50, 0x82, 0x04, 0xF0, 0x01, 0x06, 0x33, 0x46, 0x03, 0x22, 0x96, 0x49, 0x40, 0x46, 0xFE, 0xF5, 0x7E, 0xF8, 0x92, + 0x4F, 0xBF, 0x1C, 0x38, 0x78, 0x00, 0xF0, 0x01, 0x00, 0xB0, 0x42, 0x09, 0xD0, 0xE0, 0x07, 0x07, 0xD0, 0x8F, 0x49, 0x00, 0x22, 0x48, 0x31, 0x40, 0x46, 0xFE, 0xF5, 0x6F, 0xF8, 0x48, 0xF6, 0xA1, 0xFB, 0x38, 0x78, 0xC0, 0xF3, 0x81, 0x00, 0xA8, + 0x42, 0x15, 0xD0, 0x14, 0xF0, 0x0C, 0x0F, 0x02, 0xD0, 0x02, 0x2D, 0x0A, + 0xD0, 0x0F, 0xE0, 0xA0, 0x07, 0x4F, 0xF0, 0x00, 0x02, 0x02, 0xD5, 0x84, 0x49, 0x5C, 0x31, 0x05, 0xE0, 0x82, 0x49, 0x8C, 0x31, 0x02, 0xE0, 0x81, 0x49, 0x00, 0x22, 0xA0, 0x31, 0x40, 0x46, 0xFE, 0xF5, 0x52, 0xF8, 0x7C, 0x48, 0x84, 0x70, 0xBD, + 0xE8, 0xFC, 0x81, 0x7F, 0xB5, 0x05, 0x46, 0x43, 0x88, 0x44, 0x68, 0x77, 0x49, 0x74, 0x48, 0x01, 0x22, 0x34, 0x31, 0x40, 0x1C, 0xFE, 0xF5, 0x43, 0xF8, 0x6B, 0x88, 0x00, 0x20, 0x70, 0x4D, 0x0B, 0x2B, 0x7E, 0xD2, 0xDF, 0xE8, 0x03, 0xF0, 0x83, + 0x06, 0x0C, 0x1A, 0x14, 0x22, 0x37, 0x5B, 0x6C, 0x49, 0x2A, 0x00, 0x04, 0xB0, 0x20, 0x46, 0x21, 0x0C, 0xBD, 0xE8, 0x70, 0x40, 0xA0, 0xE7, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x34, 0xE7, 0x04, + 0xB0, 0x21, 0x0C, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x24, 0xE7, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0xDE, 0xE6, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, + 0x40, 0xAE, 0xE6, 0xE0, 0xB2, 0x01, 0x21, 0x00, 0xF0, 0xD6, 0xFC, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x57, 0x49, 0x00, 0x22, 0x54, 0x31, 0xFE, 0xF5, 0x05, 0xB8, 0xE4, 0xB2, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, 0x42, 0xF6, 0xC5, + 0xFC, 0x51, 0x49, 0x01, 0x22, 0x74, 0x31, 0x28, 0x46, 0x00, 0x9B, 0xFD, 0xF5, 0xF8, 0xFF, 0x01, 0x21, 0x20, 0x46, 0x42, 0xF6, 0xFF, 0xFC, 0x7F, 0xBD, 0xE4, 0xB2, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, 0x42, 0xF6, 0xB3, 0xFC, 0x48, 0x49, 0x01, + 0x22, 0xA4, 0x31, 0x28, 0x46, 0x00, 0x9B, 0xFD, 0xF5, 0xE6, 0xFF, 0x01, 0x21, 0x20, 0x46, 0x42, 0xF6, 0xBD, 0xFC, 0x7F, 0xBD, 0x42, 0x49, 0xE4, 0xB2, 0x45, 0x4E, 0x23, 0x46, 0x01, 0x22, 0xD8, 0x31, 0x28, 0x46, 0xFD, 0xF5, 0xD8, 0xFF, 0x04, + 0xB0, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x22, 0x42, 0xF6, 0x62, 0xBC, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0xE4, 0xB2, 0x00, 0x22, 0x3C, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0xC6, 0xFF, 0x6A, 0x46, 0x10, 0x21, 0x4F, + 0xF4, 0x04, 0x70, 0x42, 0xF6, 0x88, 0xFB, 0x00, 0xE0, 0x04, 0xE0, 0x01, 0x21, 0x20, 0x46, 0x42, 0xF6, 0x66, 0xFC, 0x7F, 0xBD, 0x04, 0xB0, 0x33, 0x49, 0xBD, 0xE8, 0x70, 0x40, 0x2A, 0x48, 0x01, 0x22, 0x20, 0x31, 0x80, 0x1E, 0xFD, 0xF5, 0xAF, + 0xBF, 0x13, 0xB5, 0xBD, 0xF8, 0x00, 0x00, 0x60, 0xB1, 0x21, 0x28, 0x09, 0xD1, 0x29, 0x49, 0x00, 0x22, 0x1C, 0x39, 0x23, 0x48, 0xFD, 0xF5, 0xA3, 0xFF, 0x01, 0x98, 0xC0, 0xB2, 0xFF, 0xF7, 0x13, 0xF8, 0x1C, 0xBD, 0x68, 0x46, 0xFF, 0xF7, 0x4D, + 0xFF, 0x1C, 0xBD, 0x7C, 0xB5, 0x00, 0x24, 0x1C, 0x4D, 0x01, 0x28, 0x17, 0xD0, 0x14, 0x28, 0x08, 0xD0, 0x20, 0x49, 0x03, 0x46, 0x01, 0x22, 0xDC, 0x31, 0xA8, 0x1E, 0xFD, 0xF5, 0x8C, 0xFF, 0x20, 0x46, 0x7C, 0xBD, 0x08, 0x68, 0x82, 0x88, 0x41, + 0x88, 0xCD, 0xE9, 0x00, 0x12, 0x19, 0x49, 0x03, 0x78, 0x03, 0x22, 0x4C, 0x31, 0x28, 0x46, 0xFD, 0xF5, 0x7E, 0xFF, 0xF0, 0xE7, 0x08, 0x68, 0x02, 0x22, 0x41, 0x88, 0x00, 0x91, 0x13, 0x49, 0x03, 0x78, 0xA0, 0x31, 0x28, 0x46, 0xFD, 0xF5, 0x73, + 0xFF, 0xE5, 0xE7, 0x7F, 0xB5, 0x02, 0x46, 0x00, 0x25, 0x07, 0x48, 0x0C, 0x46, 0xFF, 0x2A, 0x1E, 0xD0, 0x08, 0x49, 0x0B, 0x79, 0x9A, 0x42, 0x73, 0xD1, 0x61, 0x78, 0x01, 0x29, 0x3B, 0xD0, 0x02, 0x29, 0x52, 0xD0, 0x11, 0xE0, 0x2C, 0x15, 0x80, + 0x08, 0x02, 0x30, 0x10, 0x21, 0x30, 0x16, 0x80, 0x08, 0x60, 0x17, 0x80, 0x08, 0xF8, 0xC3, 0x20, 0x00, 0x00, 0x00, 0x30, 0x21, 0x80, 0x13, 0x80, 0x08, 0x38, 0x90, 0x0D, 0x00, 0x68, 0x18, 0x80, 0x08, 0x03, 0x29, 0x0A, + 0xD1, 0x4D, 0xE0, 0x21, 0x78, 0x11, 0xB1, 0x01, 0x29, 0x05, 0xD1, 0x05, 0xE0, 0xA3, 0x78, 0x01, 0x22, 0x6A, 0x49, 0xFD, 0xF5, 0x42, 0xFF, 0xAE, 0xE0, 0x21, 0x89, 0x66, 0x88, 0xE3, 0x88, 0x62, 0x79, 0x8D, 0xE8, 0x4E, 0x00, 0x65, 0x49, 0x23, + 0x79, 0x05, 0x22, 0x2C, 0x31, 0x06, 0x46, 0xFD, 0xF5, 0x34, 0xFF, 0x20, 0x89, 0x4F, 0xF0, 0x00, 0x02, 0x18, 0xB1, 0x60, 0x49, 0x60, 0x48, 0xC0, 0x31, 0x4E, 0xE0, 0x5E, 0x49, 0x30, 0x46, 0x94, 0x31, 0x4A, 0xE0, 0x21, 0x79, 0x01, 0x29, 0x06, + 0xD0, 0x02, 0x29, 0x08, 0xD0, 0x03, 0x29, 0x09, 0xD0, 0x04, 0x29, 0x1F, 0xD1, 0x0A, + 0xE0, 0x57, 0x49, 0x00, 0x22, 0xEC, 0x31, 0x3C, 0xE0, 0x00, 0x22, 0x56, 0x49, 0x39, 0xE0, 0x55, 0x49, 0x00, 0x22, 0x24, 0x31, 0x35, 0xE0, 0x53, 0x49, 0x00, 0x22, 0x48, 0x31, 0x31, 0xE0, 0x21, 0x79, 0x01, 0x29, 0x79, 0xD1, 0x51, 0xA1, 0x00, + 0x22, 0x09, 0x68, 0x00, 0x91, 0x4E, 0x49, 0x6C, 0x31, 0xFD, 0xF5, 0x04, 0xFF, 0x6A, 0x46, 0x02, 0x21, 0x01, 0x20, 0xFE, 0xF7, 0xAE, 0xFA, 0x6B, 0xE0, 0x21, 0x79, 0x01, 0x29, 0x68, 0xD1, 0xE1, 0x88, 0x00, 0x91, 0x46, 0x49, 0x02, 0x22, 0x63, + 0x79, 0x7C, 0x31, 0x57, 0xE0, 0xFF, 0xE7, 0x4B, 0x79, 0x9A, 0x42, 0x26, 0xD1, 0x61, 0x78, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x58, 0xD1, 0x0F, 0xE0, 0xA1, 0x78, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x52, 0xD1, 0x03, 0xE0, 0x3C, 0x49, 0x00, + 0x22, 0xA4, 0x31, 0x02, 0xE0, 0x3A, 0x49, 0x00, 0x22, 0xC8, 0x31, 0xFD, 0xF5, 0xDB, 0xFE, 0x47, 0xE0, 0xA1, 0x78, 0x01, 0x29, 0x44, 0xD1, 0x35, 0x49, 0x5A, 0x23, 0x8D, 0xF8, 0x00, 0x30, 0x01, 0x22, 0xEC, 0x31, 0xFD, 0xF5, 0xCF, 0xFE, 0x01, + 0x21, 0x6A, 0x46, 0x08, 0x46, 0xFE, 0xF7, 0x93, 0xFB, 0x36, 0xE0, 0x8B, 0x79, 0x9A, 0x42, 0x2C, 0xD1, 0x00, 0x22, 0x2E, 0x49, 0x06, 0x46, 0xFD, 0xF5, 0xC1, 0xFE, 0x20, 0x78, 0x02, 0x28, 0x2B, 0xD0, 0x03, 0x28, 0x29, 0xD1, 0xA3, 0x78, 0x01, + 0x2B, 0x04, 0xD0, 0x02, 0x2B, 0x14, 0xD0, 0x03, 0x2B, 0x22, 0xD1, 0x05, 0xE0, 0x26, 0x49, 0x20, 0x79, 0x02, 0x22, 0x18, 0x31, 0x00, 0x90, 0x10, 0xE0, 0x21, 0x89, 0xE0, 0x88, 0xCD, 0xE9, 0x00, 0x01, 0x21, 0x49, 0x23, 0x79, 0x03, 0x22, 0x50, + 0x31, 0x30, 0x46, 0xFD, 0xF5, 0xA3, 0xFE, 0x0F, 0xE0, 0x1D, 0x49, 0x20, 0x79, 0x02, 0x22, 0xB0, 0x31, 0x00, 0x90, 0x30, 0x46, 0xFD, 0xF5, 0x9A, 0xFE, 0x06, 0xE0, 0xC9, 0x79, 0x8A, 0x42, 0x03, 0xD1, 0x17, 0x49, 0x00, 0x22, 0xF4, 0x31, 0xB4, + 0xE7, 0x04, 0xB0, 0x28, 0x46, 0x70, 0xBD, 0x1C, 0xB5, 0x03, 0x29, 0x0C, 0xD0, 0x04, 0x29, 0x09, 0xD1, 0x4F, 0xF4, 0x7A, 0x70, 0x1C, 0xF6, 0x0F, 0xFD, 0x00, 0x20, 0x43, 0xF6, 0x66, 0xFF, 0x0E, 0x49, 0x01, 0x20, 0x48, 0x70, 0x1C, 0xBD, 0x21, + 0x21, 0x01, 0x90, 0xAD, 0xF8, 0x00, 0x10, 0x68, 0x46, 0xFF, 0xF7, 0x86, 0xFB, 0x00, 0x28, 0xF5, 0xD1, 0x09, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFD, 0xF5, 0x1A, 0xFE, 0x1C, 0xBD, 0x00, 0x00, 0x70, 0x19, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x80, + 0x1A, 0x80, 0x08, 0x01, 0x02, 0x00, 0x00, 0x98, 0x1B, 0x80, 0x08, 0xF8, 0xC3, 0x20, 0x00, 0x44, 0x46, 0x55, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x66, 0x77, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x66, 0x61, 0x69, + 0x6C, 0x21, 0x00, 0x10, 0xB5, 0xFC, 0x4C, 0x00, 0x22, 0xFA, 0x49, 0x20, 0x46, 0xFD, 0xF5, 0x4E, 0xFE, 0xFA, 0x49, 0x4F, 0xF4, 0x00, 0x00, 0x01, 0xF0, 0x79, 0xF8, 0x00, 0x28, 0x08, 0xD0, 0xF6, 0x48, 0xF4, 0x49, 0x01, 0x22, 0x03, 0x78, 0x30, + 0x31, 0x20, 0x46, 0xFD, 0xF5, 0x3F, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0xF1, 0x48, 0x00, 0x78, 0xFF, 0x28, 0x01, 0xD0, 0x01, 0xF0, 0x54, 0xB8, 0x70, 0x47, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x02, 0x20, 0x02, 0xF6, 0x14, 0xF9, 0x04, 0x46, 0x00, + 0x90, 0xE8, 0x49, 0xE8, 0x48, 0x2B, 0x46, 0x02, 0x22, 0x70, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0x26, 0xFE, 0x20, 0x46, 0x38, 0xBD, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x04, 0x20, 0x02, 0xF6, 0x02, 0xF9, 0x04, 0x46, 0x00, 0x90, 0xDF, 0x49, 0xDF, + 0x48, 0x2B, 0x46, 0x02, 0x22, 0xAC, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0x14, 0xFE, 0x20, 0x46, 0x38, 0xBD, 0x70, 0xB5, 0x0D, 0x46, 0x00, 0x24, 0x02, 0xF6, 0x1E, 0xFD, 0x20, 0xB1, 0x28, 0x44, 0xFF, 0xF7, 0xD3, 0xFF, 0x10, 0xB1, 0x02, 0xE0, 0x66, + 0x24, 0x00, 0xE0, 0x6C, 0x24, 0xD3, 0x49, 0xD3, 0x48, 0x23, 0x46, 0x01, 0x22, 0xE8, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0xFC, 0xFD, 0x20, 0x46, 0x70, 0xBD, 0x2D, 0xE9, 0xFC, 0x47, 0x16, 0x46, 0x0D, 0x46, 0xDF, 0xF8, 0x34, 0x93, 0xCD, 0xE9, 0x00, + 0x56, 0x04, 0x46, 0x03, 0x46, 0xA9, 0xF1, 0x01, 0x09, 0x00, 0x27, 0x03, 0x22, 0xCA, 0x49, 0x48, 0x46, 0xFD, 0xF5, 0xE8, 0xFD, 0xA4, 0xF5, 0x7F, 0x40, 0xFE, 0x38, 0x15, 0xD0, 0x1C, 0xF6, 0xDB, 0xFC, 0x80, 0x46, 0x32, 0x46, 0x29, 0x46, 0x20, + 0x46, 0x3D, 0xF6, 0x92, 0xFC, 0x07, 0x46, 0x40, 0x46, 0x1C, 0xF6, 0xDE, 0xFC, 0xC0, 0x49, 0x3B, 0x46, 0x01, 0x22, 0x70, 0x31, 0x48, 0x46, 0xFD, 0xF5, 0xD1, 0xFD, 0x38, 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x00, 0x24, 0x05, 0x20, 0x02, 0xF6, 0x3B, + 0xF8, 0x05, 0x44, 0x13, 0xE0, 0x6A, 0x46, 0x04, 0x21, 0x28, 0x46, 0x02, 0xF6, 0x11, 0xFB, 0x00, 0x98, 0x40, 0x1C, 0x09, 0xD0, 0xB4, 0x49, 0xB1, 0x48, 0x23, 0x46, 0x01, 0x22, 0x44, 0x31, 0xC0, 0x1E, 0xFD, 0xF5, 0xB8, 0xFD, 0x85, 0x27, 0xDD, + 0xE7, 0x64, 0x1C, 0x2D, 0x1D, 0xB4, 0xEB, 0x96, 0x0F, 0xE8, 0xD3, 0xD7, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x0E, 0x46, 0x00, 0x24, 0xA0, 0xF5, 0x7F, 0x41, 0x91, 0x46, 0x80, 0x46, 0xFE, 0x39, 0x1B, 0xD0, 0x02, 0xF6, 0xB5, 0xFC, 0xE0, 0xB1, 0x87, + 0x19, 0x38, 0x46, 0xFF, 0xF7, 0x69, 0xFF, 0x4A, 0x46, 0x31, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xA0, 0xFF, 0x05, 0x00, 0x02, 0xD0, 0x64, 0x1C, 0x03, 0x2C, 0xF2, 0xD3, 0x9E, 0x49, 0x23, 0x46, 0x02, 0x22, 0x98, 0x31, 0x9A, 0x48, 0x00, 0x95, 0xFD, + 0xF5, 0x8D, 0xFD, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x20, 0x01, 0xF6, 0xF8, 0xFF, 0xE1, 0xE7, 0xB1, 0x25, 0xEE, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, 0x04, 0x46, 0x00, 0x25, 0x02, 0xF6, 0x70, 0xFC, 0x90, 0xF0, 0x01, 0x0F, 0x42, 0xF2, 0x91, + 0x77, 0x42, 0xF2, 0x92, 0x78, 0x42, 0xF2, 0x93, 0x79, 0x42, 0xF2, 0x94, 0x7A, 0x42, 0xF2, 0x95, 0x7B, 0x0E, 0xD0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x2E, 0xD1, 0x04, + 0x20, 0x02, 0xF6, 0x11, 0xF8, 0x05, 0x46, 0x29, 0xE0, 0x02, 0x20, 0x01, 0xF6, 0xD0, 0xFF, 0x06, 0x46, 0xF7, 0xF5, 0x13, 0xF9, 0xB0, 0x42, 0x03, 0xD1, 0x03, 0x20, 0x01, 0xF6, 0xC8, 0xFF, 0x06, 0x46, 0x42, 0xF2, 0x90, 0x71, 0x8C, 0x42, 0x02, + 0xD1, 0x4F, 0xF4, 0x80, 0x55, 0x16, 0xE0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x0C, 0xD1, 0x30, 0x46, 0x02, 0xF6, 0xE7, 0xFB, 0x40, 0xB1, 0x06, 0xEB, 0xC4, 0x00, 0xA0, + 0xF5, 0xA0, 0x30, 0xD0, 0xF8, 0x14, 0x55, 0x68, 0x1C, 0x00, 0xD1, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFC, 0x41, 0x0E, 0x46, 0x08, 0x9C, 0x4F, 0xF0, 0x00, 0x01, 0x1D, 0x00, 0x17, 0x46, 0x21, 0x60, 0x0F, 0xD0, 0xA0, + 0xF5, 0x7F, 0x41, 0xFE, 0x39, 0x07, 0xD0, 0xFF, 0xF7, 0xA1, 0xFF, 0xDF, 0xF8, 0x90, 0xC1, 0xAC, 0xF1, 0x03, 0x0C, 0x3E, 0xB1, 0x15, 0xE0, 0x05, 0x20, 0x01, 0xF6, 0xC9, 0xFF, 0xF5, 0xE7, 0x4F, 0xF4, 0xE3, 0x70, 0x1B, 0xE0, 0xAB, 0x68, 0x03, + 0xF5, 0x80, 0x63, 0x83, 0x42, 0x09, 0xD9, 0x5D, 0x49, 0x00, 0x90, 0x02, 0x22, 0xC4, 0x31, 0x60, 0x46, 0xFD, 0xF5, 0x0C, 0xFD, 0x40, 0xF2, 0xDD, 0x10, 0x0C, 0xE0, 0xF1, 0x19, 0x81, 0x42, 0x0D, 0xD9, 0xCD, 0xE9, 0x00, 0x70, 0x33, 0x46, 0x03, + 0x22, 0x56, 0x49, 0x60, 0x46, 0xFD, 0xF5, 0xFE, 0xFC, 0x4F, 0xF4, 0xF3, 0x70, 0x20, 0x60, 0x00, 0x20, 0xBD, 0xE8, 0xFC, 0x81, 0x01, 0x20, 0xFB, 0xE7, 0x2D, 0xE9, 0xFF, 0x47, 0x80, 0x46, 0x00, 0x91, 0x16, 0x46, 0x00, 0x20, 0x0D, 0x46, 0xDF, + 0xF8, 0x24, 0xA1, 0xCD, 0xE9, 0x01, 0x60, 0x4A, 0x49, 0x1C, 0x46, 0xAA, 0xF1, 0x01, 0x0A, + 0x43, 0x46, 0x03, 0x22, 0x54, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0xE1, 0xFC, 0xB0, 0x07, 0x02, 0xD0, 0x40, 0xF2, 0x4F, 0x20, 0x60, 0xE0, 0x3C, 0xB1, 0xA8, 0xF5, 0x7F, 0x41, 0x40, 0x46, 0xFE, 0x39, 0x05, 0xD0, 0x02, 0xF6, 0xE5, 0xFB, 0x05, 0xE0, + 0x40, 0xF2, 0x55, 0x20, 0x54, 0xE0, 0x05, 0x20, 0x01, 0xF6, 0x3E, 0xFF, 0x07, 0x00, 0x0C, 0xD0, 0x02, 0xA8, 0x00, 0x90, 0x23, 0x46, 0x32, 0x46, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x8E, 0xFF, 0xF0, 0xB3, 0xDF, 0xF8, 0xCC, 0x90, 0x1D, 0xB1, + 0x0E, 0xE0, 0x4F, 0xF4, 0x1C, 0x70, 0x3F, 0xE0, 0x60, 0x88, 0x32, 0x49, 0x40, 0xF0, 0x80, 0x00, 0x60, 0x80, 0x43, 0x46, 0x02, 0x22, 0x90, 0x31, 0x48, 0x46, 0x00, 0x97, 0xFD, 0xF5, 0xAF, 0xFC, 0x78, 0x19, 0x07, 0x46, 0x29, 0x05, 0x0B, 0xD0, + 0xC5, 0xF3, 0x0B, 0x01, 0x31, 0x44, 0x4F, 0xF4, 0x80, 0x52, 0x91, 0x42, 0x07, 0xD9, 0x96, 0x42, 0x05, 0xD8, 0xB8, 0x19, 0x6F, 0xF3, 0x0B, 0x00, 0xFF, 0xF7, 0x67, 0xFE, 0x08, 0xB1, 0x00, 0x25, 0x22, 0xE0, 0x40, 0xF2, 0xF6, 0x20, 0x1B, 0xE0, + 0x78, 0x19, 0x80, 0x46, 0x21, 0x68, 0x02, 0xF6, 0xBC, 0xF9, 0x48, 0xF0, 0x80, 0x70, 0x03, 0xA9, 0x02, 0xF6, 0xEF, 0xF9, 0x20, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0F, 0xD0, 0x78, 0x19, 0xCD, 0xE9, 0x00, 0x10, 0x03, 0x22, 0x17, 0x49, 0x00, 0xE0, + 0x0C, 0xE0, 0xD8, 0x31, 0x48, 0x46, 0x23, 0x68, 0xFD, 0xF5, 0x7D, 0xFC, 0x40, 0xF2, 0x07, 0x30, 0x02, 0x90, 0x03, 0xE0, 0x24, 0x1D, 0x2D, 0x1D, 0xB5, 0x42, 0xDD, 0xD3, 0x01, 0x22, 0x10, 0x49, 0x50, 0x46, 0x02, 0x9B, 0xFD, 0xF5, 0x6F, 0xFC, + 0x02, 0x98, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x46, 0x01, 0x20, 0xA1, 0xF5, 0x7F, 0x42, 0xFE, 0x3A, 0x02, 0xD0, 0x08, 0x46, 0x3D, 0xF6, 0xAD, 0xBA, 0x08, 0x4A, 0x00, 0x21, 0x11, 0x60, 0x70, 0x47, 0x00, 0x00, 0xA4, 0x1C, 0x80, 0x08, + 0x03, 0x31, 0x10, 0x21, 0x64, 0xB9, 0x20, 0x00, 0xC0, 0x1D, 0x80, 0x08, 0xC4, 0x1E, 0x80, 0x08, 0xD8, 0x1F, 0x80, 0x08, 0x00, 0xC4, 0x20, 0x00, 0xF8, 0xB5, 0x04, 0x46, 0xA0, 0xF5, 0x7F, 0x40, 0x4F, 0xF4, 0x00, 0x15, 0xFE, 0x38, 0x17, 0xD0, + 0xFF, 0xF7, 0xF0, 0xFD, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0x90, 0xFF, 0x20, 0x46, 0x3D, 0xF6, 0x25, 0xFB, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0xD9, 0xFF, + 0xFF, 0xF7, 0xF4, 0xFD, 0x30, 0x46, 0xF8, 0xBD, 0x20, 0x46, 0xFF, 0xF7, 0xC1, 0xFF, 0x05, 0x20, 0x01, 0xF6, 0x9A, 0xFE, 0x40, 0xF0, 0x80, 0x74, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0x72, 0xFF, 0x20, 0x46, + 0x02, 0xF6, 0xBC, 0xFA, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0xBB, 0xFF, 0x6A, 0x46, 0x04, 0x21, 0x20, 0x46, 0x02, 0xF6, 0x5E, 0xF9, 0x00, 0x98, 0x6A, 0x46, 0x20, 0xF4, 0x00, 0x00, 0x00, 0x90, + 0x04, 0x21, 0x20, 0x46, 0x02, 0xF6, 0x1D, 0xF9, 0xD4, 0xE7, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x46, 0x01, 0x20, 0x08, 0x70, 0x60, 0x88, 0x00, 0x25, 0xB0, 0xF5, 0x97, 0x7F, 0x1A, 0xD0, 0x06, 0xDC, 0x0E, 0x28, 0x0B, 0xD0, 0x0F, 0x28, 0x11, 0xD0, + 0x22, 0x28, 0x26, 0xD1, 0x0A, + 0xE0, 0xA0, 0xF5, 0x80, 0x70, 0x2F, 0x38, 0x16, 0xD0, 0xA2, 0x28, 0x1F, 0xD1, 0x1A, 0xE0, 0x20, 0x1D, 0x00, 0xF0, 0xE8, 0xFB, 0x1A, 0xE0, 0xA0, 0x88, 0x00, 0xF0, 0x64, 0xF8, 0x09, 0xE0, 0x20, 0x1D, 0x00, 0xF0, 0x65, 0xFC, 0x12, 0xE0, 0x20, + 0x46, 0x45, 0xF6, 0xD1, 0xF8, 0x20, 0x1D, 0x00, 0xF0, 0x3A, 0xF9, 0x01, 0x25, 0x0A, + 0xE0, 0x20, 0x46, 0x45, 0xF6, 0xC9, 0xF8, 0x20, 0x1D, 0x00, 0xF0, 0x3E, 0xF9, 0xF6, 0xE7, 0x20, 0x46, 0x00, 0xF0, 0x03, 0xFB, 0x05, 0x46, 0x28, 0x46, 0x70, 0xBD, 0x30, 0xB5, 0x87, 0xB0, 0x00, 0x20, 0x05, 0x90, 0x01, 0x24, 0x06, 0x90, 0xCD, + 0xE9, 0x00, 0x40, 0x10, 0x4D, 0x03, 0x90, 0x04, 0x90, 0x02, 0x90, 0x1C, 0x23, 0x08, 0x22, 0x0C, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0xBA, 0xFB, 0x0A, + 0x49, 0x05, 0x94, 0x06, 0x94, 0x03, 0x94, 0x04, 0x94, 0x00, 0x94, 0x01, 0x94, 0x00, 0x23, 0x08, 0x22, 0xF0, 0x31, 0x28, 0x46, 0x02, 0x94, 0xFD, 0xF5, 0xAC, 0xFB, 0xAF, 0xF2, 0xB3, 0x00, 0x07, 0xB0, 0xBD, 0xE8, 0x30, 0x40, 0x41, 0xF6, 0x7E, + 0xBD, 0xF8, 0x1F, 0x80, 0x08, 0x00, 0x35, 0x10, 0x21, 0x70, 0xB5, 0x02, 0x24, 0x05, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x43, 0xF6, 0x20, 0xFC, 0x00, 0x28, 0xF9, 0xD1, 0xFB, 0x48, 0x01, 0x78, 0xC8, 0x07, 0xF5, + 0xD0, 0x11, 0xF0, 0x0C, 0x0F, 0xF2, 0xD0, 0x11, 0xF0, 0x30, 0x0F, 0xEF, 0xD1, 0x88, 0x09, 0xED, 0xD1, 0x28, 0x46, 0x17, 0xF6, 0xC8, 0xF9, 0x00, 0x28, 0xE8, 0xD0, 0x00, 0x24, 0xE6, 0xE7, 0x38, 0xB5, 0x04, 0x00, 0x07, 0xD1, 0xF0, 0x49, 0x08, + 0x78, 0x20, 0xF0, 0x0E, 0x00, 0x08, 0x70, 0xFC, 0x20, 0x42, 0xF6, 0xA9, 0xFD, 0xED, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0xAD, 0xF8, 0x00, 0x40, 0x69, 0x46, 0xA5, 0x20, 0x90, 0x47, 0x38, 0xBD, 0x30, 0xB5, 0x8B, 0xB0, 0x4F, 0xF0, 0x00, + 0x01, 0xE7, 0x4D, 0x04, 0x00, 0x06, 0x91, 0x07, 0x91, 0x08, 0x91, 0x09, 0x91, 0x02, 0xD0, 0x20, 0x78, 0x01, 0x28, 0x08, 0xD0, 0x01, 0x23, 0x01, 0x22, 0xE2, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0x59, 0xFB, 0x00, 0x20, 0x0B, 0xB0, 0x30, 0xBD, 0xA0, + 0x78, 0x00, 0x07, 0x18, 0xD5, 0x6A, 0x46, 0x14, 0x21, 0x20, 0x46, 0x45, 0xF6, 0xD1, 0xFF, 0x80, 0xB1, 0x10, 0x22, 0x06, 0xA9, 0x68, 0x46, 0x4F, 0xF6, 0x1B, 0xFD, 0x40, 0xB1, 0xD7, 0x49, 0x63, 0x78, 0x01, 0x22, 0x30, 0x39, 0x28, 0x46, 0xFD, + 0xF5, 0x40, 0xFB, 0x01, 0x20, 0xE5, 0xE7, 0x05, 0x23, 0xDD, 0xE7, 0x04, 0x23, 0xDB, 0xE7, 0x02, 0x23, 0xD9, 0xE7, 0x0A, + 0x46, 0x00, 0xEB, 0x40, 0x01, 0xCF, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x00, 0xEB, 0x01, 0x10, 0x01, 0x78, 0x29, 0xB1, 0x81, 0x79, 0xC0, 0x1D, 0x17, 0xF6, 0x28, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0xF0, 0xB5, 0x85, 0xB0, 0x0C, + 0x46, 0x06, 0x00, 0x05, 0xD0, 0x17, 0xF6, 0x69, 0xFE, 0x78, 0xB3, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0x27, 0x44, 0xB3, 0xFD, 0xF7, 0xF8, 0xFB, 0x20, 0x70, 0x01, 0x0A, + 0x61, 0x70, 0x01, 0x0C, 0xA1, 0x70, 0x00, 0x0E, 0x65, 0x1C, 0xE0, 0x70, 0xFD, 0xF7, 0xEE, 0xFB, 0xE8, 0x70, 0x00, 0x0A, + 0x28, 0x71, 0x40, 0xF0, 0xC0, 0x00, 0x60, 0x71, 0xB9, 0xA0, 0x06, 0x22, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x01, 0x10, 0xB8, 0xA0, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x03, 0x10, 0x01, 0xA9, 0x20, 0x46, 0x4F, 0xF6, 0xCB, 0xFC, 0x48, 0xB1, + 0x06, 0x22, 0x03, 0xA9, 0x20, 0x46, 0x4F, 0xF6, 0xC5, 0xFC, 0x18, 0xB1, 0x04, 0xE0, 0x03, 0x20, 0xD0, 0xE7, 0x0F, 0xE0, 0x66, 0x20, 0x20, 0x70, 0x21, 0x46, 0xAF, 0x48, 0xFD, 0xF5, 0xA4, 0xFC, 0xA7, 0x49, 0x03, 0x46, 0x02, 0x22, 0x38, 0x31, + 0xA4, 0x48, 0x00, 0x96, 0xFD, 0xF5, 0xDF, 0xFA, 0x38, 0x46, 0xBF, 0xE7, 0x07, 0x20, 0xBD, 0xE7, 0x70, 0xB5, 0x0D, 0x46, 0x43, 0xF6, 0x22, 0xFA, 0x04, 0x00, 0x2A, 0xD0, 0xA5, 0x48, 0x9E, 0x49, 0x01, 0x22, 0x03, 0x78, 0x9B, 0x48, 0x74, 0x31, + 0x40, 0x1C, 0xFD, 0xF5, 0xCC, 0xFA, 0x97, 0x49, 0x01, 0x22, 0x08, 0x78, 0xB2, 0xEB, 0x90, 0x1F, 0x0A, + 0xD1, 0x62, 0x78, 0x03, 0x2A, 0x07, 0xD1, 0xA2, 0x78, 0x01, 0x2A, 0x04, 0xD1, 0x22, 0x8A, 0x12, 0xB9, 0x20, 0xF0, 0xC0, 0x00, 0x08, 0x70, 0xE0, 0x78, 0x2A, 0x46, 0x00, 0x21, 0x48, 0xF6, 0xD4, 0xF8, 0x00, 0x20, 0x42, 0xF6, 0xE5, 0xFC, 0xE0, + 0x6A, 0x08, 0xB1, 0x1B, 0xF6, 0xBB, 0xFC, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x43, 0xF6, 0xE4, 0xB9, 0x89, 0x49, 0xBD, 0xE8, 0x70, 0x40, 0x86, 0x48, 0x00, 0x22, 0xA4, 0x31, 0x80, 0x1E, 0xFD, 0xF5, 0xA1, 0xBA, 0x43, 0x88, 0x33, 0xB1, 0x83, + 0x49, 0x82, 0x48, 0x01, 0x22, 0xD4, 0x31, 0x80, 0x1E, 0xFD, 0xF5, 0x98, 0xBA, 0x81, 0x88, 0x00, 0x88, 0xB9, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x41, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xB4, 0xFF, 0x20, 0x88, 0xBD, 0xE8, 0x10, 0x40, 0x17, 0xF6, 0x63, + 0xB9, 0x10, 0xB5, 0x8A, 0xB0, 0x0C, 0x46, 0x00, 0x21, 0x21, 0x70, 0x09, 0xAA, 0x07, 0xA9, 0x43, 0xF6, 0x49, 0xFB, 0xB8, 0xB1, 0x9D, 0xF8, 0x24, 0x10, 0x07, 0xA8, 0x45, 0xF6, 0x13, 0xFE, 0x88, 0xB1, 0x6A, 0x46, 0x11, 0x21, 0x45, 0xF6, 0xF9, + 0xFE, 0x60, 0xB1, 0x9D, 0xF8, 0x1B, 0x30, 0x01, 0x22, 0x75, 0x49, 0x6B, 0x48, 0xFD, 0xF5, 0x6E, 0xFA, 0x9D, 0xF8, 0x1B, 0x00, 0x20, 0x70, 0x00, 0x20, 0x0A, + 0xB0, 0x10, 0xBD, 0x03, 0x20, 0xFB, 0xE7, 0x70, 0x48, 0x00, 0x88, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, 0x0F, 0x46, 0x05, 0x00, 0x08, 0xD0, 0x62, 0x4B, 0x28, 0x78, 0x9B, 0x1E, 0x01, 0x28, 0x06, 0xD0, 0x68, 0x49, 0x00, 0x22, 0x48, 0x31, 0x0B, + 0xE0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x67, 0x48, 0x69, 0x78, 0x00, 0x78, 0x40, 0x1E, 0x81, 0x42, 0x06, 0xDD, 0x62, 0x49, 0x00, 0x22, 0x20, 0x31, 0x18, 0x46, 0xFD, 0xF5, 0x46, 0xFA, 0xEF, 0xE7, 0xDF, 0xF8, 0x7C, 0x81, 0x38, 0x46, 0xB8, + 0xF8, 0x00, 0x10, 0x8E, 0x08, 0x4F, 0xF6, 0x1C, 0xFD, 0x00, 0x24, 0xDF, 0xF8, 0x74, 0x91, 0xDF, 0xF8, 0x74, 0xA1, 0x11, 0xE0, 0x68, 0x78, 0x00, 0x90, 0xB9, 0xF8, 0x00, 0x10, 0xBA, 0xF8, 0x00, 0x00, 0x04, 0x23, 0x08, 0x44, 0x00, 0xEB, 0x84, + 0x00, 0x81, 0xB2, 0x07, 0xEB, 0x84, 0x00, 0xB8, 0xF8, 0x00, 0x20, 0x46, 0xF6, 0x0B, 0xFD, 0x64, 0x1C, 0xB4, 0x42, 0xEB, 0xDB, 0x01, 0x20, 0xCC, 0xE7, 0x30, 0xB5, 0xA7, 0xB0, 0x04, 0x00, 0x07, 0xD0, 0x04, 0xF1, 0x08, 0x00, 0x61, 0x78, 0x05, + 0x46, 0x46, 0xF6, 0xD0, 0xFD, 0x18, 0xB1, 0x14, 0xE0, 0x00, 0x20, 0x27, 0xB0, 0x30, 0xBD, 0xE0, 0x7B, 0xC1, 0x07, 0x0E, 0xD0, 0x01, 0x21, 0x21, 0x70, 0x62, 0x88, 0x83, 0x07, 0x42, 0xF0, 0x01, 0x02, 0x62, 0x80, 0x02, 0xD5, 0x42, 0xF0, 0x80, + 0x02, 0x62, 0x80, 0x40, 0x07, 0x04, 0xD5, 0x21, 0x71, 0x02, 0xE0, 0x20, 0x78, 0x01, 0x28, 0x5D, 0xD1, 0x61, 0x78, 0x0A, + 0xA8, 0x46, 0xF6, 0xF4, 0xFD, 0x30, 0xB9, 0x9D, 0xF8, 0x28, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x02, 0x00, 0x60, 0x80, 0x61, 0x78, 0x12, 0xA8, 0x46, 0xF6, 0x31, 0xFE, 0x30, 0xB9, 0x9D, 0xF8, 0x48, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, + 0xF0, 0x04, 0x00, 0x60, 0x80, 0x61, 0x78, 0x04, 0xA8, 0x46, 0xF6, 0x93, 0xFE, 0x70, 0xB9, 0x9D, 0xF8, 0x27, 0x00, 0x58, 0xB1, 0x08, 0x98, 0x20, 0x61, 0xBD, 0xF8, 0x24, 0x00, 0xA0, 0x82, 0x9D, 0xF8, 0x26, 0x00, 0xA0, 0x75, 0x60, 0x88, 0x40, + 0xF0, 0x08, 0x00, 0x60, 0x80, 0x61, 0x78, 0x1A, 0xA8, 0x46, 0xF6, 0x48, 0xFF, 0x30, 0xB9, 0x9D, 0xF8, 0x7D, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x10, 0x00, 0x60, 0x80, 0x61, 0x78, 0x20, 0xA8, 0x46, 0xF6, 0xA9, 0xFF, 0x30, 0xB9, 0x9D, + 0xF8, 0x95, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x20, 0x00, 0x60, 0x80, 0x60, 0x78, 0x47, 0xF6, 0x13, 0xF8, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x40, 0x00, 0x60, 0x80, 0x29, 0x46, 0x12, 0x48, 0xFD, 0xF5, 0x6A, 0xFB, 0x22, 0x79, 0x61, + 0x88, 0xA3, 0x7B, 0xCD, 0xE9, 0x02, 0x12, 0xCD, 0xE9, 0x00, 0x03, 0x0F, 0x49, 0x63, 0x78, 0x05, 0x22, 0x7C, 0x31, 0x04, 0x48, 0xFD, 0xF5, 0x9F, 0xF9, 0x01, 0x20, 0x88, 0xE7, 0x38, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0x02, 0x35, 0x10, + 0x21, 0x00, 0x22, 0x80, 0x08, 0x64, 0x2E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x30, 0x21, 0x60, 0x2E, 0x20, 0x00, 0x08, 0x23, 0x80, 0x08, 0xEE, 0x2E, 0x20, + 0x00, 0xBC, 0x2E, 0x20, 0x00, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x2D, 0xE9, 0xFE, 0x43, 0x88, 0x46, 0x98, 0x4D, 0x00, 0x21, 0x11, 0x70, 0x29, 0x88, 0x97, 0x4E, 0x17, 0x46, 0x88, 0x42, 0x02, 0xD0, 0x00, 0x22, 0x95, 0x49, 0x49, + 0xE0, 0xD8, 0xF8, 0x00, 0x10, 0x01, 0x91, 0xD8, 0xF8, 0x04, 0x00, 0x02, 0x90, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x45, 0xF6, 0xFC, 0xFC, 0x04, 0x00, 0x06, 0xD1, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x46, 0xF6, 0x55, 0xF8, 0x04, 0x00, 0x08, 0xD0, 0x01, 0x20, 0x8A, 0x49, 0x38, 0x70, 0x00, 0x22, 0x34, 0x31, 0x30, 0x46, 0xFD, 0xF5, 0x53, 0xF9, 0x39, 0xE0, 0x9D, 0xF8, 0x0B, 0x00, 0x00, 0x27, 0x40, 0x07, 0x00, 0xD5, 0x01, + 0x27, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x45, 0xF6, 0x77, 0xFD, 0x04, 0x00, 0x0D, 0xD1, 0x45, 0xF6, 0xE3, 0xFF, 0x50, 0xB3, 0x40, 0x78, 0x41, 0xF6, 0xC5, 0xFC, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x45, 0xF6, 0x69, 0xFD, 0x04, 0x00, 0x1F, 0xD0, 0x60, 0x78, 0x00, 0x90, 0x78, 0x48, 0x78, 0x49, 0x2A, 0x88, 0x00, 0x88, 0x09, 0x88, 0xD3, 0xB2, 0x08, 0x44, 0x81, 0xB2, 0x40, 0x46, 0x46, 0xF6, 0xEE, 0xFB, 0x40, + 0xB1, 0x71, 0x49, 0x00, 0x22, 0x64, 0x31, 0x30, 0x46, 0xFD, 0xF5, 0x22, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xFE, 0x83, 0x61, 0x78, 0x01, 0x20, 0x46, 0xF6, 0xF9, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xF7, 0xFE, 0x20, 0x46, 0xF4, 0xE7, 0x68, 0x49, 0x00, + 0x22, 0xA4, 0x31, 0xEC, 0xE7, 0x00, 0xB5, 0x91, 0xB0, 0x4F, 0xF4, 0xE8, 0x71, 0xAD, 0xF8, 0x00, 0x10, 0xAD, 0xF8, 0x04, 0x00, 0x01, 0x21, 0x68, 0x46, 0x16, 0xF6, 0xD0, 0xFD, 0x11, 0xB0, 0x00, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x01, 0x46, 0x60, + 0x48, 0x43, 0xF6, 0xDB, 0xF8, 0x68, 0xB1, 0x5F, 0x49, 0x04, 0xEB, 0x44, 0x00, 0x09, 0x68, 0x01, 0xEB, 0x00, 0x10, 0x00, 0x8A, 0xFF, 0xF7, 0xE2, 0xFF, 0x08, 0xB1, 0x00, 0x20, 0x10, 0xBD, 0x07, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0x7F, + 0xB5, 0x58, 0x4D, 0x04, 0x46, 0x28, 0x68, 0x00, 0x28, 0x19, 0xD0, 0x60, 0x88, 0x43, 0xF6, 0x2F, 0xF8, 0x00, 0x28, 0x14, 0xD0, 0xC0, 0x78, 0x8D, 0xF8, 0x00, 0x00, 0x20, 0x88, 0xAD, 0xF8, 0x02, 0x00, 0x20, 0x79, 0x8D, 0xF8, 0x04, 0x00, 0xE0, + 0x88, 0xAD, 0xF8, 0x06, 0x00, 0x20, 0x89, 0xAD, 0xF8, 0x08, 0x00, 0xCD, 0xF8, 0x0C, 0xD0, 0x2A, 0x68, 0x03, 0xA9, 0x1B, 0x20, 0x90, 0x47, 0x7F, 0xBD, 0x10, 0xB5, 0x41, 0x88, 0x01, 0x24, 0xA1, 0xF5, 0x80, 0x71, 0xD1, 0x39, 0x02, 0xD0, 0x00, + 0x24, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x1D, 0xFF, 0xF7, 0xD2, 0xFF, 0xF9, 0xE7, 0x70, 0xB5, 0x0C, 0x46, 0x05, 0x46, 0x01, 0x46, 0x3D, 0x48, 0x86, 0xB0, 0x17, 0x30, 0x43, 0xF6, 0x92, 0xF8, 0x90, 0xB3, 0x61, 0x1E, 0x4F, 0xF6, 0xFF, 0x72, 0x39, + 0x4B, 0x05, 0xEB, 0x45, 0x00, 0x91, 0x42, 0x0E, 0xD2, 0x19, 0x68, 0x01, 0xEB, 0x00, 0x11, 0x8A, 0x8A, 0x02, 0xEB, 0x82, 0x02, 0x96, 0x08, 0xCA, 0x8A, 0x52, 0x1C, 0x56, 0x43, 0x04, 0xEB, 0x84, 0x02, 0xB6, 0xEB, 0x42, 0x0F, 0x1C, 0xDD, 0x19, + 0x68, 0x01, 0xEB, 0x00, 0x10, 0x81, 0x8A, 0xC0, 0x8A, 0x01, 0xEB, 0x81, 0x02, 0x92, 0x08, 0x43, 0x1C, 0x5A, 0x43, 0x04, 0xEB, 0x84, 0x03, 0x5B, 0x00, 0xCD, 0xE9, 0x00, 0x41, 0xCD, 0xE9, 0x02, 0x03, 0x23, 0x49, 0x04, 0x92, 0x2B, 0x46, 0x06, + 0x22, 0xC4, 0x31, 0x1F, 0x48, 0xFD, 0xF5, 0x84, 0xF8, 0x03, 0x20, 0x06, 0xB0, 0x70, 0xBD, 0x15, 0xE0, 0x08, 0x8A, 0x8D, 0xF8, 0x14, 0x00, 0x00, 0x0A, + 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x20, 0x0A, + 0x8D, 0xF8, 0x17, 0x00, 0x05, 0xAA, 0x04, 0x21, 0x40, 0xF6, 0x7C, 0x40, 0x16, 0xF6, 0xB6, 0xFD, 0x08, 0xB1, 0x00, 0x20, 0xE8, 0xE7, 0x07, 0x20, 0xE6, 0xE7, 0x04, 0x20, 0xE4, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x01, 0x46, 0x12, 0x48, 0x37, 0x30, + 0x43, 0xF6, 0x3E, 0xF8, 0xA0, 0xB1, 0x11, 0x49, 0x04, 0xEB, 0x44, 0x00, 0x09, 0x68, 0x01, 0xEB, 0x00, 0x10, 0x00, 0x8A, 0x14, 0xF6, 0x21, 0xFD, 0x40, 0xB1, 0x41, 0x8D, 0x17, 0x29, 0x03, 0xD3, 0x11, 0xF6, 0xF7, 0xFE, 0x00, 0x20, 0x10, 0xBD, + 0x03, 0x20, 0x10, 0xBD, 0x0A, + 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0xEE, 0x2E, 0x20, 0x00, 0x00, 0x35, 0x10, 0x21, 0xE0, 0x23, 0x80, 0x08, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x9C, 0xB5, 0x20, 0x00, 0x64, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0xFD, + 0x49, 0x08, 0x60, 0x70, 0x47, 0x08, 0xB5, 0xC1, 0x1E, 0x40, 0xF2, 0xFE, 0x72, 0x91, 0x42, 0x01, 0xD3, 0x00, 0x20, 0x08, 0xBD, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x8D, 0xF8, 0x01, 0x00, 0x00, 0x0A, + 0x8D, 0xF8, 0x02, 0x00, 0x6A, 0x46, 0x03, 0x21, 0x4F, 0xF6, 0x6E, 0x40, 0x16, 0xF6, 0x67, 0xFD, 0x00, 0x28, 0xEE, 0xD0, 0x01, 0x20, 0x08, 0xBD, 0x30, 0xB5, 0xEF, 0x4B, 0x1D, 0x68, 0x1B, 0x1D, 0x1C, 0x68, 0x1B, 0x1D, 0x1B, 0x68, 0x05, 0x60, + 0x0C, 0x60, 0x13, 0x60, 0x30, 0xBD, 0x08, 0xB5, 0x0F, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x6A, 0x46, 0x01, 0x21, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, 0x4E, 0xFD, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x2D, 0xE9, 0xF8, 0x43, + 0x01, 0x88, 0x4F, 0xF6, 0x80, 0x58, 0xE1, 0x4D, 0x04, 0x46, 0x41, 0x45, 0x21, 0xD1, 0xA0, 0x79, 0x0F, 0x28, 0x04, 0xD0, 0x13, 0x28, 0x07, 0xD0, 0x14, 0x28, 0x1A, 0xD1, 0x09, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAC, 0x20, 0x10, 0xE0, + 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xA8, 0x20, 0x0B, 0xE0, 0xE0, 0x79, 0x21, 0x7A, 0xA2, 0x7A, 0x00, 0xEB, 0x01, 0x20, 0x61, 0x7A, 0x09, 0x04, 0x01, 0xEB, 0x02, 0x61, 0x08, 0x44, 0x00, 0x90, 0xAE, 0x20, 0x2A, 0x68, 0x0A, + 0xB1, 0x69, 0x46, 0x90, 0x47, 0x20, 0x88, 0x4F, 0xF6, 0x6E, 0x46, 0xB0, 0x42, 0x07, 0xD1, 0x60, 0x79, 0x28, 0xB9, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0x2A, 0x68, 0xA6, 0x20, 0x62, 0xBB, 0x20, 0x88, 0x4F, 0xF6, 0x82, 0x57, 0xB8, 0x42, 0x1C, + 0xD1, 0xA0, 0x79, 0x05, 0x28, 0x19, 0xD1, 0xE0, 0x79, 0x09, 0x28, 0x04, 0xD0, 0x1E, 0x28, 0x07, 0xD0, 0x1F, 0x28, 0x12, 0xD1, 0x09, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAB, 0x20, 0x08, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAA, + 0x20, 0x03, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAD, 0x20, 0x2A, 0x68, 0x0A, + 0xB1, 0x69, 0x46, 0x90, 0x47, 0x20, 0x88, 0xA0, 0xF5, 0x7D, 0x41, 0x87, 0x39, 0x09, 0xD1, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0x2A, 0x68, 0xAF, 0x20, 0x1A, 0xB1, 0x69, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xF8, 0x83, 0x20, 0x88, 0x40, 0x45, 0xFA, + 0xD0, 0xA0, 0xF5, 0x7D, 0x41, 0x81, 0x39, 0xF6, 0xD0, 0xB8, 0x42, 0xF4, 0xD0, 0xB0, 0x42, 0xF2, 0xD0, 0xAB, 0x48, 0x02, 0x68, 0x00, 0x2A, 0xEE, 0xD0, 0x03, 0x20, 0x69, 0x46, 0x00, 0x94, 0x90, 0x47, 0xE9, 0xE7, 0x10, 0xB5, 0x16, 0xF6, 0xC9, + 0xFC, 0x08, 0xB1, 0x00, 0x20, 0x10, 0xBD, 0x07, 0x20, 0x10, 0xBD, 0x01, 0x46, 0xA2, 0x48, 0x08, 0xB5, 0x02, 0x68, 0x00, 0x2A, 0x03, 0xD0, 0x00, 0x91, 0x04, 0x20, 0x69, 0x46, 0x90, 0x47, 0x08, 0xBD, 0x0E, 0xB5, 0x10, 0x22, 0x8D, 0xF8, 0x00, + 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x02, 0x20, 0x02, 0x0C, 0x00, 0x0E, 0x8D, 0xF8, 0x04, 0x00, 0x8D, 0xF8, 0x05, 0x10, 0x08, 0x0A, + 0x8D, 0xF8, 0x06, 0x00, 0x08, 0x0C, 0x8D, 0xF8, 0x07, 0x00, 0x08, 0x0E, 0x8D, 0xF8, 0x03, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x6A, 0x46, 0x09, 0x21, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, 0x99, 0xFC, 0x08, 0xB1, 0x00, 0x20, 0x0E, 0xBD, 0x07, 0x20, + 0x0E, 0xBD, 0x0A, + 0x28, 0x01, 0xD9, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x30, 0xB5, 0x8B, 0xB0, 0x04, 0x46, 0x2C, 0x21, 0x68, 0x46, 0x4F, 0xF6, 0x41, 0xFA, 0x13, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x20, 0x78, 0x00, 0x22, 0x01, 0x21, 0x02, 0x28, 0x03, + 0xD0, 0x01, 0x28, 0x07, 0xD0, 0x48, 0xB1, 0x90, 0xE0, 0x8D, 0xF8, 0x01, 0x10, 0x8D, 0xF8, 0x02, 0x20, 0x03, 0x21, 0x82, 0xE0, 0x8D, 0xF8, 0x01, 0x10, 0x01, 0xE0, 0x8D, 0xF8, 0x01, 0x20, 0xE0, 0x79, 0x02, 0x28, 0x0D, 0xD1, 0x20, 0x7A, 0xFF, + 0xF7, 0xD6, 0xFF, 0x00, 0x28, 0x7D, 0xD0, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x01, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0x20, 0x7A, 0x8D, 0xF8, 0x03, 0x00, 0x60, 0x78, 0x01, 0x28, 0x0D, 0xD1, 0xA0, 0x78, 0xFF, 0xF7, 0xC5, 0xFF, 0x00, 0x28, 0x6C, + 0xD0, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x04, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0xA0, 0x78, 0x8D, 0xF8, 0x04, 0x00, 0x60, 0x79, 0x01, 0x28, 0x0C, 0xD1, 0xA0, 0x79, 0xFF, 0xF7, 0xB4, 0xFF, 0xE0, 0xB3, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x08, + 0x00, 0x8D, 0xF8, 0x02, 0x00, 0xA0, 0x79, 0x8D, 0xF8, 0x05, 0x00, 0xE0, 0x78, 0x01, 0x28, 0x0C, 0xD1, 0x20, 0x79, 0xFF, 0xF7, 0xA4, 0xFF, 0x60, 0xB3, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x10, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0x20, 0x79, 0x8D, + 0xF8, 0x06, 0x00, 0xE0, 0x79, 0x07, 0x21, 0x01, 0x28, 0x37, 0xD1, 0x60, 0x7A, 0x40, 0x1E, 0x0B, 0x28, 0x3B, 0xD2, 0x9D, 0xF8, 0x02, 0x00, 0x00, 0x21, 0x40, 0xF0, 0x02, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0x60, 0x7A, 0x8D, 0xF8, 0x07, 0x00, 0x1F, + 0xE0, 0x04, 0xEB, 0x41, 0x00, 0x82, 0x7A, 0x02, 0xEB, 0x42, 0x03, 0x4C, 0x4A, 0x12, 0x68, 0x02, 0xEB, 0x03, 0x13, 0x1A, 0x8A, 0x5D, 0x78, 0xC3, 0x7A, 0x02, 0x2D, 0x03, 0xD0, 0x02, 0x20, 0x0B, 0xB0, 0x30, 0xBD, 0x1E, 0xE0, 0x18, 0x46, 0xFF, + 0xF7, 0x72, 0xFF, 0xD0, 0xB1, 0x01, 0xEB, 0x41, 0x05, 0x68, 0x46, 0x28, 0x44, 0x02, 0x72, 0x12, 0x0A, + 0x42, 0x72, 0x49, 0x1C, 0x83, 0x72, 0xC9, 0xB2, 0x9D, 0xF8, 0x07, 0x00, 0x88, 0x42, 0xDB, 0xD8, 0xC0, 0xB2, 0x00, 0xEB, 0x40, 0x00, 0x08, 0x30, 0xC1, 0xB2, 0x6A, 0x46, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, 0xED, 0xFB, 0x18, 0xB1, 0x00, 0x20, + 0xDD, 0xE7, 0x03, 0x20, 0xDB, 0xE7, 0x07, 0x20, 0xD9, 0xE7, 0x08, 0xB5, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x09, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x00, 0xB1, 0x01, 0x20, 0x8D, 0xF8, 0x02, 0x00, 0x6A, 0x46, 0x03, 0x21, 0x4F, 0xF6, 0x82, 0x50, + 0x16, 0xF6, 0xD5, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x1E, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x00, 0xB1, 0x01, 0x20, 0x8D, 0xF8, 0x02, 0x00, 0x6A, 0x46, 0x03, 0x21, + 0x4F, 0xF6, 0x82, 0x50, 0x16, 0xF6, 0xBF, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x1F, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x00, 0xB1, 0x01, 0x20, 0x8D, 0xF8, 0x02, 0x00, + 0x6A, 0x46, 0x03, 0x21, 0x4F, 0xF6, 0x82, 0x50, 0x16, 0xF6, 0xA9, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x14, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x6A, 0x46, 0x01, 0x21, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, + 0x9A, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x1C, 0xB5, 0x0A, + 0x00, 0x4F, 0xF0, 0x08, 0x01, 0x8D, 0xF8, 0x00, 0x10, 0x8D, 0xF8, 0x01, 0x00, 0x11, 0xD0, 0x10, 0x68, 0xCD, 0xF8, 0x02, 0x00, 0x10, 0x79, 0x07, 0x21, 0x8D, 0xF8, 0x06, 0x00, 0x0A, + 0xE0, 0x04, 0xC4, 0x20, 0x00, 0x1C, 0x1B, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0xF4, 0x2D, 0x20, 0x00, 0x64, 0x2E, 0x20, 0x00, 0x02, 0x21, 0x6A, 0x46, 0x4F, 0xF6, 0x87, 0x50, 0x16, 0xF6, 0x74, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x1C, 0xBD, 0x07, + 0x20, 0x1C, 0xBD, 0x00, 0x00, 0x0B, 0x49, 0x10, 0xB5, 0xA1, 0xF1, 0x7C, 0x02, 0x0A, + 0x4C, 0xC2, 0xE9, 0x37, 0x12, 0x37, 0x21, 0x06, 0xE0, 0x00, 0xEB, 0x10, 0x43, 0x42, 0xF8, 0x21, 0x30, 0x07, 0x4B, 0x00, 0xFB, 0x03, 0x40, 0x0B, 0x1E, 0xA1, 0xF1, 0x01, 0x01, 0xF4, 0xDC, 0x10, 0xBD, 0x01, 0x20, 0xE8, 0xE7, 0x00, 0x00, 0x84, + 0xC4, 0x20, 0x00, 0xE1, 0x19, 0xD6, 0x66, 0xCD, 0x0D, 0x01, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x0E, 0x48, 0x00, 0x68, 0x28, 0xB1, 0x4F, 0xF0, 0xFF, 0x31, 0x1B, 0xF6, 0x3B, 0xFD, 0x00, 0x28, 0x10, 0xD0, 0x0B, 0x48, 0x04, 0x70, 0x4F, 0xF4, 0x00, + 0x10, 0x90, 0xF8, 0x50, 0x03, 0x41, 0x07, 0x09, 0xD0, 0xEF, 0xF3, 0x11, 0x81, 0x07, 0x4A, 0x40, 0x07, 0x00, 0x0E, 0x80, 0xF3, 0x11, 0x88, 0x11, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x72, 0xB6, 0xFB, 0xE7, 0x00, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, + 0x04, 0x20, 0x00, 0xAC, 0x0C, 0x20, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x00, 0x24, 0x07, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x00, 0x28, 0x09, 0xD0, 0x28, 0x46, 0xFF, 0xF5, 0x70, 0xFB, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x00, 0xF0, 0x71, + 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x70, 0xB5, 0x06, 0x46, 0x0D, 0x46, 0x00, 0x24, 0x07, 0x20, 0xFF, 0xF7, 0xC0, 0xFF, 0x00, 0x28, 0x0A, + 0xD0, 0x29, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x08, 0xF8, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x00, 0xF0, 0x5C, 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x5F, 0x8B, 0x46, 0x80, 0x46, 0x29, 0x4C, 0x01, 0xF6, 0x22, 0xF8, 0x04, + 0x28, 0x02, 0xD2, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x9F, 0x25, 0x7A, 0x94, 0xF8, 0x00, 0x90, 0x66, 0x68, 0x28, 0xF0, 0x80, 0x74, 0x00, 0x27, 0x4F, 0xF4, 0x00, 0x0A, + 0x06, 0xF5, 0x00, 0x08, 0x54, 0x45, 0x01, 0xD3, 0x44, 0x45, 0x02, 0xD9, 0x6F, 0xF0, 0x02, 0x00, 0xEB, 0xE7, 0x58, 0x46, 0xFF, 0xF5, 0x08, 0xFB, 0x01, 0x28, 0xE6, 0xD1, 0x9B, 0xF8, 0x00, 0x00, 0x78, 0xB3, 0xB9, 0xF1, 0xFF, 0x0F, 0x06, 0xD0, + 0xB9, 0xF1, 0x7F, 0x0F, 0x06, 0xD0, 0x44, 0x45, 0x0B, 0xD1, 0x2F, 0x46, 0x22, 0xE0, 0x44, 0x45, 0xFB, 0xD0, 0x1F, 0xE0, 0x0A, + 0xEB, 0x56, 0x00, 0xA0, 0x42, 0x1B, 0xD8, 0x6D, 0x1E, 0xEF, 0xB2, 0x18, 0xE0, 0x01, 0x20, 0x6A, 0x1E, 0x00, 0xFA, 0x02, 0xF1, 0x11, 0xE0, 0xB6, 0xFB, 0xF1, 0xF3, 0x42, 0x1E, 0x93, 0x40, 0xB6, 0xFB, 0xF1, 0xF2, 0x82, 0x40, 0x03, 0xF5, 0x00, + 0x03, 0x02, 0xF5, 0x00, 0x02, 0x9C, 0x42, 0x03, 0xD3, 0x94, 0x42, 0x01, 0xD2, 0xC7, 0xB2, 0x02, 0xE0, 0x40, 0x1C, 0xA8, 0x42, 0xEB, 0xDB, 0x38, 0x46, 0xFF, 0xF5, 0xFD, 0xFA, 0x01, 0x20, 0xB1, 0xE7, 0xDC, 0x0C, 0x20, 0x00, 0x10, 0xB5, 0x4F, + 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x50, 0x03, 0x40, 0x07, 0x0C, 0xD0, 0x07, 0x48, 0x00, 0x78, 0x80, 0xF3, 0x11, 0x88, 0x06, 0x48, 0x00, 0x68, 0x08, 0xB1, 0x1B, 0xF6, 0x9F, 0xFC, 0x04, 0x49, 0xFF, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x62, 0xB6, 0xF4, + 0xE7, 0xAC, 0x0C, 0x20, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, 0x04, 0x20, 0x00, 0x4F, 0xF0, 0x40, 0x70, 0xE1, 0xEE, 0x10, 0x0A, + 0x70, 0x47, 0x00, 0x00, 0x01, 0xD1, 0x85, 0x0E, 0x07, 0x00, 0x00, 0x00, 0x19, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x80, 0x20, 0x00, 0x35, 0x80, 0x20, 0x00, + 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x72, 0x65, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x00, 0x2C, 0xB7, 0x20, 0x00, 0xD8, 0xB7, 0x20, 0x00, 0x20, 0xB7, 0x20, 0x00, 0xE0, 0xB7, 0x20, 0x00, + 0x84, 0xB7, 0x20, 0x00, 0xF8, 0xB7, 0x20, 0x00, 0xEC, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x14, 0xB7, 0x20, 0x00, 0xCC, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, + 0x3C, 0xB7, 0x20, 0x00, 0x9C, 0xB7, 0x20, 0x00, 0xB0, 0xB7, 0x20, 0x00, 0x1C, 0xB7, 0x20, 0x00, 0x04, 0xB7, 0x20, 0x00, 0x84, 0xB6, 0x20, 0x00, 0x58, 0xB6, 0x20, 0x00, 0xB8, 0xB7, 0x20, 0x00, 0x6C, 0xB7, 0x20, 0x00, 0x58, 0xB7, 0x20, 0x00, + 0xF0, 0xB6, 0x20, 0x00, 0xB0, 0xB6, 0x20, 0x00, 0xD0, 0xB6, 0x20, 0x00, 0x34, 0xB6, 0x20, 0x00, 0x00, 0xB6, 0x20, 0x00, 0x10, 0xB7, 0x20, 0x00, 0xF8, 0xB5, 0x20, 0x00, 0x2C, 0xB6, 0x20, 0x00, 0xF0, 0xB5, 0x20, 0x00, 0x24, 0xB6, 0x20, 0x00, + 0x0C, 0xB7, 0x20, 0x00, 0xA4, 0xB7, 0x20, 0x00, 0x08, 0xB6, 0x20, 0x00, 0x3C, 0xB6, 0x20, 0x00, 0x68, 0xB6, 0x20, 0x00, 0x8C, 0xB6, 0x20, 0x00, 0xB8, 0xB6, 0x20, 0x00, 0xD8, 0xB6, 0x20, 0x00, 0x9C, 0xB6, 0x20, 0x00, 0x78, 0xB6, 0x20, 0x00, + 0x38, 0xB7, 0x20, 0x00, 0x4C, 0xB6, 0x20, 0x00, 0x18, 0xB6, 0x20, 0x00, 0x60, 0xB6, 0x20, 0x00, 0xA8, 0xB6, 0x20, 0x00, 0xC8, 0xB6, 0x20, 0x00, 0xE8, 0xB6, 0x20, 0x00, 0xFC, 0xB6, 0x20, 0x00, 0x90, 0xB7, 0x20, 0x00, 0x7C, 0xB7, 0x20, 0x00, + 0xC4, 0xB7, 0x20, 0x00, 0x44, 0xB7, 0x20, 0x00, 0x24, 0xB7, 0x20, 0x00, 0x04, 0xB8, 0x20, 0x00, 0x60, 0xB7, 0x20, 0x00, 0x4C, 0xB7, 0x20, 0x00, 0x18, 0xB7, 0x20, 0x00, 0x02, 0x08, 0x00, 0x28, 0x0A, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x01, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x32, 0xB8, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xEF, 0x81, 0x20, 0x00, 0x55, 0x82, 0x20, 0x00, 0x31, 0x83, 0x20, 0x00, 0x02, 0x08, 0x00, 0x28, 0x0F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x19, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x53, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x84, 0x20, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0xFF, + 0xD0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xE8, 0xB2, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD2, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF1, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF9, 0x85, 0x20, 0x00, 0x5D, 0x85, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, + 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x92, 0x20, 0x00, 0xED, 0x92, 0x20, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x6D, 0x73, + 0x67, 0x5F, 0x74, 0x6F, 0x5F, 0x61, 0x70, 0x70, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x00, 0x00, 0x03, 0x19, 0x00, 0x00, 0x02, 0x01, 0x05, 0x03, 0x03, 0x0A, + 0xA0, 0x0B, 0x09, 0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, 0x00, 0x42, 0x4C, 0x45, 0x5F, 0x4F, 0x54, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x65, 0x5F, 0x72, 0x65, 0x61, 0x64, 0x5F, 0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x6C, 0x65, 0x5F, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x5F, 0x70, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x00, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x5F, 0x73, 0x65, 0x6E, 0x64, + 0x5F, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x5F, 0x6D, 0x74, 0x75, 0x5F, 0x72, 0x65, 0x71, 0x00, 0x49, 0x32, 0x43, 0x30, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x30, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x30, 0x00, + 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x30, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x30, 0x00, 0x49, 0x32, 0x43, 0x31, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, + 0x49, 0x31, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x31, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x31, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, + 0x31, 0x00, 0x54, 0x49, 0x4D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x32, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x32, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, + 0x72, 0x6F, 0x75, 0x70, 0x32, 0x00, 0x54, 0x49, 0x4D, 0x33, 0x00, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x33, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, + 0x33, 0x00, 0x54, 0x49, 0x4D, 0x34, 0x00, 0x00, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x34, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x34, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x35, 0x00, 0x00, + 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x35, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x35, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x36, 0x00, 0x00, 0x00, 0x00, 0x54, 0x69, 0x6D, 0x65, 0x72, 0x34, + 0x2D, 0x37, 0x00, 0x00, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x37, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x4D, 0x41, 0x43, 0x00, 0x00, 0x00, 0x41, 0x44, 0x43, 0x00, 0x52, 0x54, 0x43, 0x00, 0x53, 0x56, 0x43, 0x00, 0x4C, 0x43, 0x44, 0x00, 0x57, 0x44, + 0x47, 0x00, 0x4E, 0x4D, 0x49, 0x00, 0x4C, 0x50, 0x43, 0x4F, 0x4D, 0x50, 0x00, 0x00, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x53, 0x50, 0x00, 0x00, 0x00, 0x49, 0x52, 0x00, 0x00, 0x50, 0x65, 0x6E, 0x64, 0x53, 0x56, 0x00, 0x00, 0x53, 0x50, + 0x49, 0x32, 0x57, 0x00, 0x00, 0x00, 0x53, 0x50, 0x4F, 0x52, 0x54, 0x31, 0x20, 0x52, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, 0x53, 0x30, 0x5F, 0x52, 0x58, 0x00, 0x53, 0x50, 0x4F, 0x52, 0x54, 0x31, 0x20, 0x54, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, + 0x53, 0x30, 0x5F, 0x54, 0x58, 0x00, 0x52, 0x73, 0x76, 0x64, 0x00, 0x00, 0x00, 0x00, 0x51, 0x64, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x5F, 0x46, 0x6C, + 0x61, 0x73, 0x68, 0x00, 0x00, 0x00, 0x53, 0x79, 0x73, 0x54, 0x69, 0x63, 0x6B, 0x00, 0x50, 0x65, 0x72, 0x69, 0x70, 0x68, 0x65, 0x72, 0x61, 0x6C, 0x00, 0x00, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x00, 0x00, 0x50, 0x6C, 0x61, 0x74, 0x66, 0x6F, + 0x72, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, 0x73, 0x63, 0x61, 0x6E, 0x00, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4D, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x48, 0x61, 0x72, 0x64, 0x46, 0x61, + 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x50, 0x54, 0x41, 0x5F, 0x4D, 0x61, 0x69, 0x6C, 0x62, 0x6F, + 0x78, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x42, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x43, 0x00, 0x42, 0x6F, 0x6F, 0x74, 0x4F, 0x6E, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x72, 0x01, 0x01, 0x00, 0x56, 0x31, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x69, 0x73, 0x74, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x18, 0xB5, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0xB8, 0x20, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xF0, 0x24, + 0x81, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x20, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xEC, 0xC4, + 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xB8, 0x20, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, + 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x9D, 0x20, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/insert_write.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/insert_write.c new file mode 100644 index 00000000..b9e3fe1c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/insert_write.c @@ -0,0 +1,198 @@ +#include +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "platform_stdlib.h" +#include +#include +#include +#include + +T_OS_QUEUE write_req_queue[4]; + +uint8_t request_in_process_flag[4] = {0, 0, 0, 0}; //e.g if send request then flag=1, receive response then flag=0 + +extern void bt_ota_central_client_app_discov_services(uint8_t conn_id, bool start); + +/* user write request example */ +int user_write_request_example(uint8_t conn_id, uint16_t handle, T_CLIENT_ID client_id) +{ + uint8_t data[3] = {1,2,3}; + int ret = -1; + uint16_t length = 3; + + if(if_queue_in(0, conn_id, client_id, handle, length, data) == 0) + { + request_in_process_flag[conn_id] = 1; + ret = client_attr_write(conn_id, client_id, GATT_WRITE_TYPE_REQ, handle, length, data); + if(ret != 0) //if write fail + { + request_in_process_flag[conn_id] = 0; + printf("(conn_id %d) user write request(handle %x) fail, please check! ret=%d\r\n", conn_id, handle, ret); + } + } + + return ret; // return -1 -- add write request info to queue, 0 -- send write request success, others -- send write request fail +} + +/* if add write request information to queue */ +/* @return 0 -- queue is empty + * 1 -- add write request info to queue + 2 -- add discovery service info to queue + * -1 -- add data to queue fail + */ +int if_queue_in(uint8_t type, uint8_t conn_id, T_CLIENT_ID client_id, uint16_t handle, uint16_t length, uint8_t *p_data) +{ + if(os_queue_peek(&write_req_queue[conn_id]) == NULL && request_in_process_flag[conn_id] == 0) // queue empty, and no requesting + { + return 0; + } + else //if (user_req_flag == 1) //queue empty and exist requesting, or queue not empty and no requesting, or queue not empty and exist requesting + { + if(type == 0) //write request info queue in + { + /* for send data to queue */ + WRITE_REQ_INFO *add_write_data = NULL; + + add_write_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(WRITE_REQ_INFO)); + if(add_write_data == NULL) + { + printf("WRITE_REQ_INFO malloc fail\r\n"); + return -1; + } + memset(add_write_data, 0, sizeof(WRITE_REQ_INFO)); + + add_write_data->conn_id = conn_id; + add_write_data->client_id = client_id; + add_write_data->handle = handle; + add_write_data->length = length; + if(add_write_data->length != 0) + { + add_write_data->p_data = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if(add_write_data->p_data == NULL) + { + printf("malloc fail\r\n"); + os_mem_free(add_write_data); + return -1; + } + memcpy(add_write_data->p_data, p_data, length); + } + + os_queue_in(&write_req_queue[conn_id], (void *) add_write_data); + printf("(conn_id %d, client_id %d)add write request to queue\r\n", conn_id, client_id); + + return 1; + } + + if(type == 1) //discovery service info queue in + { + WRITE_REQ_INFO *add_service_info = NULL; + + add_service_info = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(WRITE_REQ_INFO)); + if(add_service_info == NULL) + { + printf("WRITE_REQ_INFO(of service info) malloc fail\r\n"); + return -1; + } + memset(add_service_info, 0, sizeof(WRITE_REQ_INFO)); + add_service_info->conn_id = conn_id; + add_service_info->status = 1; //flag: exist a write request before discovery service. + + os_queue_in(&write_req_queue[conn_id], (void *) add_service_info); + printf("(conn_id %d) add discovery service info to queue\r\n", conn_id); + + return 2; + } + } + + return -1; +} + + +/* if take out write request(or discovery service) information from queue */ +int if_queue_out_and_send(uint8_t conn_id) +{ + WRITE_REQ_INFO *out_write_data = NULL; + out_write_data = os_queue_out(&write_req_queue[conn_id]); + + if(out_write_data) + { + if(out_write_data->status == 1) + { + printf("exist discovery service info, os_queue_out\r\n"); + + //after user write request send success, then start discovery service + bt_ota_central_client_app_discov_services(conn_id, true); + + os_mem_free(out_write_data); + + return 1; + } + else + { + printf("(conn_id %d, client_id %d) os_queue_out\r\n", conn_id, out_write_data->client_id); + + if(out_write_data->p_data) + { + request_in_process_flag[conn_id] = 1; + if(client_attr_write(out_write_data->conn_id, out_write_data->client_id, GATT_WRITE_TYPE_REQ, out_write_data->handle, + out_write_data->length, out_write_data->p_data) != GAP_CAUSE_SUCCESS) + { + request_in_process_flag[conn_id] = 0; + printf("(conn_id %d, queue out)write request fail, please check!!!\r\n", conn_id); + } + os_mem_free(out_write_data->p_data); + } + + os_mem_free(out_write_data); + + return 2; + } + } + + return 0; +} + +/* if disconnected during ota process, then need queue out and free memory */ +void disconnect_and_queue_out(uint8_t conn_id) +{ + WRITE_REQ_INFO *out_req = NULL; + int i = 0; + + while(true) + { + out_req = os_queue_out(&write_req_queue[conn_id]); + if(out_req) + { + printf("exist items in queue, queue out item %d\r\n", i++); + + if(out_req->p_data) + { + os_mem_free(out_req->p_data); + out_req->p_data = NULL; + } + + os_mem_free(out_req); + out_req = NULL; + } + else + { + /* clear flag and queue */ + request_in_process_flag[conn_id] = 0; + memset(&write_req_queue[conn_id], 0, sizeof(T_OS_QUEUE)); + + break; + } + } + +} + +void connect_and_init(uint8_t conn_id) +{ + /* init flag and queue*/ + request_in_process_flag[conn_id] = 0; + memset(&write_req_queue[conn_id], 0, sizeof(T_OS_QUEUE)); + + os_queue_init(&write_req_queue[conn_id]); +} +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/insert_write.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/insert_write.h new file mode 100644 index 00000000..62f6f7d3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/bt_mesh_provisioner_ota_client/insert_write.h @@ -0,0 +1,48 @@ +#ifndef _INSERT_WRITE_H_ +#define _INSERT_WRITE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include + +/* used for storage write request info during ota process */ +typedef struct write_req_info_t +{ + struct write_req_info_t *p_next; // Pointer to the next item, must be the first field. + uint8_t status; //0 -- default, 1 -- mark service discovery process. + T_CLIENT_ID client_id; + uint8_t conn_id; + uint16_t handle; + uint16_t length; + uint8_t *p_data; +} WRITE_REQ_INFO; + +typedef struct +{ + uint8_t conn_id; + uint16_t handle; +} T_OTA_WRITE_MSG; + +extern T_OS_QUEUE write_req_queue[4]; + +extern uint8_t request_in_process_flag[4]; //if send request then flag=1, receive response then flag=0 + +int if_queue_in(uint8_t type, uint8_t conn_id, T_CLIENT_ID client_id, uint16_t handle, uint16_t length, uint8_t *p_data); + +int if_queue_out_and_send(uint8_t conn_id); + +void disconnect_and_queue_out(uint8_t conn_id); + +void connect_and_init(uint8_t conn_id); + +int user_write_request_example(uint8_t conn_id, uint16_t handle, T_CLIENT_ID client_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_flags.h new file mode 100644 index 00000000..279446b6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_flags.h @@ -0,0 +1,65 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_DEVICE_MULTIPLE_PROFILE_APP_FLAGS_H_ +#define _BT_MESH_DEVICE_MULTIPLE_PROFILE_APP_FLAGS_H_ + +#include "platform_opts_bt.h" + +#include + +/** + * @addtogroup MESH_APP_CONFIG + * @{ + */ + +/** + * @defgroup Mesh_App_Config Mesh App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#if defined(CONFIG_PLATFORM_8721D) +#define BLE_SCATTERNET_APP_MAX_LINKS 4 +#define BLE_SCATTERNET_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BLE_SCATTERNET_CENTRAL_APP_MAX_LINKS 3 //for max master link num +#elif defined(CONFIG_PLATFORM_8710C) +#define BLE_SCATTERNET_APP_MAX_LINKS 2 +#define BLE_SCATTERNET_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BLE_SCATTERNET_CENTRAL_APP_MAX_LINKS 1 //for max master link num +#endif +/** @brief Config the discovery table number of gcs_client */ +#define BLE_SCATTERNET_APP_MAX_DISCOV_TABLE_NUM 40 +#elif defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** @brief Config APP LE link number */ +#if defined(CONFIG_PLATFORM_8721D) +#define BLE_CENTRAL_APP_MAX_LINKS 3 +#elif defined(CONFIG_PLATFORM_8710C) +#define BLE_CENTRAL_APP_MAX_LINKS 1 +#endif +/** @brief Config the discovery table number of gcs_client */ +#define BLE_CENTRAL_APP_MAX_DISCOV_TABLE_NUM 40 +#else +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +#endif + +/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/ +#define F_BT_AIRPLANE_MODE_SUPPORT 0 + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_main.c new file mode 100644 index 00000000..f47273b8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_main.c @@ -0,0 +1,1065 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mesh_api.h" +#include +#include +#include +#include +#include +#include +#include + +#include "mesh_cmd.h" +#include "device_multiple_profile_app.h" +#include "health.h" +#include "generic_on_off.h" +#include "light_server_app.h" +#include "time_server_app.h" +#include "scheduler_server_app.h" +#include "scene_server_app.h" +#include "ping.h" +#include "ping_app.h" +#include "tp.h" +#include "datatrans_server.h" +#include "health.h" +#include "datatrans_app.h" +#include "bt_mesh_device_multiple_profile_app_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +#include "bt_mesh_device_api.h" +#include "generic_on_off.h" +#include "gpio_api.h" +#include "gpio_irq_api.h" +#endif +#include "osdep_service.h" +#include "wifi_constants.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_device_api.h" +#endif +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK +#include "device_idle_check.h" +#endif +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_updater_app.h" +#endif +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL +#include +#include +#include "platform_stdlib.h" +#include +#include "rtk_coex.h" +#include "bas.h" +#endif + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +#include +#include +#include +#include "rtk_coex.h" +#include "platform_stdlib.h" +#include "ble_central_at_cmd.h" +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#include +#include +#include "trace_uart.h" +#include +#include +#include +#include "rtk_coex.h" +#include +#include "bas.h" +#endif + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#include "bt_mesh_device_test.h" +#include "bt_mesh_test_result.h" +#include "gpio_api.h" +#endif + +/*============================================================================* + * Constants + *============================================================================*/ +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 400 +#endif + +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief Default scan interval (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_INTERVAL 0x520 +/** @brief Default scan window (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_WINDOW 0x520 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; +plt_timer_t bt_mesh_multiple_profile_peripheral_adv_timer = NULL; +uint8_t le_adv_start_enable = 0; +uint16_t bt_mesh_peripheral_adv_interval = 352; +extern int array_count_of_adv_data; +#endif + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +#if defined(CONFIG_PLATFORM_8721D) +#define GPIO_LED_PIN PA_25 +#elif defined(CONFIG_PLATFORM_8710C) +#define GPIO_LED_PIN PA_19 +#endif +#define GPIO_IRQ_PIN PA_13 +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +#if defined(CONFIG_PLATFORM_8721D) +#define GPIO_LED_PIN PA_25 +#elif defined(CONFIG_PLATFORM_8710C) +#define GPIO_LED_PIN PA_19 +#endif +#endif +#define COMPANY_ID 0x005D +#define PRODUCT_ID 0x0000 +#define VERSION_ID 0x0000 + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +plt_timer_t device_publish_timer = NULL; +#endif + +mesh_model_info_t health_server_model; +mesh_model_info_t generic_on_off_server_model; + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +gpio_t gpio_led; +gpio_irq_t gpio_btn; + +uint32_t last_push_button_time = 0; +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +gpio_t gpio_led; +#endif + +generic_on_off_t current_on_off = GENERIC_OFF; + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +void device_publish_api(generic_on_off_t on_off) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + /* _generic_on_off_publish */ + puserItem = bt_mesh_alloc_hdl(USER_API_ASYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + } + puserItem->pparseValue->dw_parameter[0] = on_off; + puserItem->pparseValue->para_count = 1; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_generic_on_off_publish), puserItem->pparseValue, NULL, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + } +} + +void device_publish_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + device_publish_api(current_on_off); +} +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +extern void *bt_mesh_device_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_device_multiple_profile_io_queue_handle; //!< IO queue handle + +void bt_mesh_multiple_profile_peripheral_adv_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + uint16_t adv_interval = bt_mesh_peripheral_adv_interval * 625 / 1000; + + io_msg.type = IO_MSG_TYPE_ADV; + if (os_msg_send(bt_mesh_device_multiple_profile_io_queue_handle, &io_msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } + if (le_adv_start_enable) { + plt_timer_change_period(bt_mesh_multiple_profile_peripheral_adv_timer, adv_interval, 0xFFFFFFFF); + } +} + +void mesh_le_adv_start(void) +{ + uint16_t adv_interval = bt_mesh_peripheral_adv_interval * 625 / 1000; + + le_adv_start_enable = 1; + plt_timer_change_period(bt_mesh_multiple_profile_peripheral_adv_timer, adv_interval, 0xFFFFFFFF); +} + +void mesh_le_adv_stop(void) +{ + le_adv_start_enable = 0; +} +#endif + +static int32_t generic_on_off_server_data(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + /* avoid gcc compile warning */ + (void)pmodel_info; + + switch (type) + { + case GENERIC_ON_OFF_SERVER_GET: + { + generic_on_off_server_get_t *pdata = pargs; + pdata->on_off = current_on_off; + } + break; + case GENERIC_ON_OFF_SERVER_GET_DEFAULT_TRANSITION_TIME: + break; + case GENERIC_ON_OFF_SERVER_SET: + { + generic_on_off_server_set_t *pdata = pargs; + if (pdata->total_time.num_steps == pdata->remaining_time.num_steps) + { + if (pdata->on_off != current_on_off) + { + current_on_off = pdata->on_off; + if (current_on_off == GENERIC_OFF) + { + printf("Provisioner turn light OFF!\r\n"); +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + gpio_write(&gpio_led, 0); + plt_timer_change_period(device_publish_timer, 200, 0xFFFFFFFF); +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + gpio_write(&gpio_led, 0); +#endif + } + else if (current_on_off == GENERIC_ON) + { + printf("Provisioner turn light ON!\r\n"); +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + gpio_write(&gpio_led, 1); + plt_timer_change_period(device_publish_timer, 200, 0xFFFFFFFF); +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + gpio_write(&gpio_led, 1); +#endif + } + } + } + } + break; + default: + break; + } + + return 0; +} + +void generic_on_off_server_model_init(void) +{ + generic_on_off_server_model.model_data_cb = generic_on_off_server_data; + generic_on_off_server_reg(0, &generic_on_off_server_model); +} + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO +#if 0 +void push_button_handler(uint32_t id, gpio_irq_event event) +{ + /* avoid gcc compile warning */ + (void)event; + gpio_t *gpio_led = (gpio_t *)id; + uint32_t current_time = rtw_get_current_time(); + //mesh_model_info_t pmodel_info = generic_on_off_server_model; + + gpio_irq_disable(&gpio_btn); + + if (current_time > last_push_button_time && rtw_systime_to_ms(current_time - last_push_button_time) > 100) { + if (current_on_off == GENERIC_OFF) { + current_on_off = GENERIC_ON; + gpio_write(gpio_led, 1); + printf("User turn light ON!\r\n"); + device_publish_api(GENERIC_ON); + } else if (current_on_off == GENERIC_ON) { + current_on_off = GENERIC_OFF; + gpio_write(gpio_led, 0); + printf("User turn light OFF!\r\n"); + device_publish_api(GENERIC_OFF); + } + } + + last_push_button_time = current_time; + gpio_irq_enable(&gpio_btn); +} +#endif + +void light_button_init(void) +{ + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); + gpio_mode(&gpio_led, PullNone); + +#if 0 + gpio_irq_init(&gpio_btn, GPIO_IRQ_PIN, push_button_handler, (uint32_t)(&gpio_led)); + gpio_irq_set(&gpio_btn, IRQ_FALL, 1); + gpio_irq_enable(&gpio_btn); +#endif + + if (current_on_off == GENERIC_OFF) + gpio_write(&gpio_led, 0); + else if (current_on_off == GENERIC_ON) + gpio_write(&gpio_led, 1); +} +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST +void light_init(void) +{ + gpio_init(&gpio_led, GPIO_LED_PIN); + gpio_dir(&gpio_led, PIN_OUTPUT); + gpio_mode(&gpio_led, PullNone); + if (current_on_off == GENERIC_OFF) + gpio_write(&gpio_led, 0); + else if (current_on_off == GENERIC_ON) + gpio_write(&gpio_led, 1); +} +#endif + +#if defined(MESH_DFU) && MESH_DFU +extern void blob_transfer_server_caps_set(blob_server_capabilites_t *pcaps); +#endif + +/****************************************************************** + * @fn Initial gap parameters + * @brief Initialize peripheral and gap bond manager related parameters + * + * @return void + */ +void bt_mesh_device_multiple_profile_stack_init(void) +{ + /** set ble stack log level, disable nonsignificant log */ + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + // log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_ERROR, 0); + // log_module_trace_set(TRACE_MODULE_SNOOP, TRACE_LEVEL_ERROR, 0); + + /** set mesh stack log level, default all on, disable the log of level LEVEL_TRACE */ + uint32_t module_bitmap[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(TRACE_LEVEL_TRACE, module_bitmap); + + /** mesh stack needs rand seed */ + plt_srand(platform_random(0xffffffff)); + + /** configure provisioning parameters */ + prov_capabilities_t prov_capabilities = + { + .algorithm = PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE, + .public_key = 0, + .static_oob = 0, + .output_oob_size = 0, + .output_oob_action = 0, + .input_oob_size = 0, + .input_oob_action = 0 + }; + prov_params_set(PROV_PARAMS_CAPABILITIES, &prov_capabilities, sizeof(prov_capabilities_t)); + prov_params_set(PROV_PARAMS_CALLBACK_FUN, (void *)prov_cb, sizeof(prov_cb_pf)); + + /** config node parameters */ + mesh_node_features_t features = + { + .role = MESH_ROLE_DEVICE, + .relay = 1, + .proxy = 1, + .fn = 1, + .lpn = 1, + .prov = 1, + .udb = 1, + .snb = 1, + .bg_scan = 1, + .flash = 1, + .flash_rpl = 1 + }; + + mesh_node_cfg_t node_cfg = + { + .dev_key_num = 2, + .net_key_num = 10, + .app_key_num = 3, + .vir_addr_num = 3, + .rpl_num = 20, + .sub_addr_num = 5, + .proxy_num = 1, + .prov_interval = 2, + .udb_interval = 2, + .proxy_interval = 5 + }; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + features.flash_rpl = 0; + node_cfg.rpl_num = 50; +#endif + + mesh_node_cfg(features, &node_cfg); + proxy_server_support_prov_on_proxy(true); + mesh_node.net_trans_count = 6; + mesh_node.relay_retrans_count = 2; + mesh_node.trans_retrans_count = 4; + mesh_node.ttl = 5; +#if MESH_LPN + mesh_node.frnd_poll_retry_times = 32; +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); +#endif + + /** create elements and register models */ + mesh_element_create(GATT_NS_DESC_UNKNOWN); +#if !defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) || (!CONFIG_BT_MESH_DEVICE_RTK_DEMO) + health_server_reg(0, &health_server_model); + health_server_set_company_id(&health_server_model, COMPANY_ID); + ping_control_reg(ping_app_ping_cb, pong_receive); + trans_ping_pong_init(ping_app_ping_cb, pong_receive); + tp_control_reg(tp_reveive); + datatrans_model_init(); + light_server_models_init(); + time_server_models_init(); + scene_server_model_init(); + scheduler_server_model_init(); +#endif + generic_on_off_server_model_init(); +#if defined(MESH_DFU) && MESH_DFU + dfu_updater_models_init(); + blob_server_capabilites_t caps = { + 6, //BLOB_TRANSFER_CPAS_MIN_BLOCK_SIZE_LOG + 12, //BLOB_TRANSFER_CPAS_MAX_BLOCK_SIZE_LOG + 20, //BLOB_TRANSFER_CPAS_MAX_TOTAL_CHUNKS + 256, //BLOB_TRANSFER_CPAS_MAX_CHUNK_SIZE + 1000000, //!< supported max size + 350, //BLOB_TRANSFER_CPAS_SERVER_MTU_SIZE + 1, //BLOB_TRANSFER_CPAS_MODE_PULL_SUPPORT + 1, //BLOB_TRANSFER_CPAS_MODE_PUSH_SUPPORT + 0 //RFU + }; + blob_transfer_server_caps_set(&caps); +#endif +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + init_bt_mesh_test_parameter(); + link_list_init(); + light_init(); +#endif + +#if defined(CONFIG_BT_MESH_DEVICE_RTK_DEMO) && CONFIG_BT_MESH_DEVICE_RTK_DEMO + light_button_init(); + device_publish_timer = plt_timer_create("device_publish_timer", 0xFFFFFFFF, FALSE, NULL, device_publish_timer_handler); + if (!device_publish_timer) { + printf("[BT Mesh Device] Create device publish timer failed\n\r"); + } + datatrans_model_init(); +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + bt_mesh_multiple_profile_peripheral_adv_timer = plt_timer_create("bt_mesh_multiple_profile_peripheral_adv_timer", 0xFFFFFFFF, FALSE, NULL, bt_mesh_multiple_profile_peripheral_adv_timer_handler); + if (!bt_mesh_multiple_profile_peripheral_adv_timer) { + printf("[BT Mesh Device] Create adv timer failed\n\r"); + } +#endif + + compo_data_page0_header_t compo_data_page0_header = {COMPANY_ID, PRODUCT_ID, VERSION_ID}; + compo_data_page0_gen(&compo_data_page0_header); + + /** init mesh stack */ + mesh_init(); + + /** register proxy adv callback */ + device_info_cb_reg(device_info_cb); + hb_init(hb_cb); +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_mesh_device_multiple_profile_app_le_gap_init(void) +{ + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + uint16_t scan_window = 0x100; /* 160ms */ + uint16_t scan_interval = 0x120; /* 180ms */ + + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); + +#if 1 + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, array_count_of_adv_data, (void *)adv_data); + // le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); +#endif + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + } +#endif + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_CENTRAL_CLIENT"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Scan parameters */ + //uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + //uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + //uint16_t scan_window = DEFAULT_SCAN_WINDOW; + //uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + //uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); +#if 0 + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + +#if 1 + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); +#endif +#if F_BT_LE_USE_STATIC_RANDOM_ADDR + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (ble_central_app_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + ble_central_app_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + //le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer +#if 0 + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#endif +#endif + } +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_SCATTERNET"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* Scan parameters */ + //uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + //uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + //uint16_t scan_window = DEFAULT_SCAN_WINDOW; + //uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + //uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, array_count_of_adv_data, (void *)adv_data); + // le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + +#if 0 + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_USE_STATIC_RANDOM_ADDR + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (ble_scatternet_app_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + ble_scatternet_app_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer +#if 0 + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#endif +#endif +#if F_BT_GAPS_CHAR_WRITEABLE + uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; + uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; + T_LOCAL_APPEARANCE appearance_local; + T_LOCAL_NAME local_device_name; + if (flash_load_local_appearance(&appearance_local) == 0) + { + gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance); + } + + if (flash_load_local_name(&local_device_name) == 0) + { + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name); + } + gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop); + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop); + gatt_register_callback((void*)bt_mesh_scatternet_gap_service_callback); +#endif + } +#endif + + vendor_cmd_init(bt_mesh_device_multiple_profile_app_vendor_callback); + /* register gap message callback */ + le_register_app_cb(bt_mesh_device_multiple_profile_app_gap_callback); + +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_mesh_device_multiple_profile_app_le_profile_init(void) +{ + server_init(MESH_GATT_SERVER_COUNT + 2); + + /* Register Server Callback */ + server_register_app_cb(bt_mesh_device_multiple_profile_app_profile_callback); + + client_init(MESH_GATT_CLIENT_COUNT + 1); + /* Add Client Module */ + + /* Register Client Callback--App_ClientCallback to handle events from Profile Client layer. */ + client_register_general_client_cb(bt_mesh_device_multiple_profile_app_client_callback); + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + bt_mesh_simp_srv_id = simp_ble_service_add_service((void *)bt_mesh_device_multiple_profile_app_profile_callback); + bt_mesh_bas_srv_id = bas_add_service((void *)bt_mesh_device_multiple_profile_app_profile_callback); +#endif +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + bt_mesh_central_gcs_client_id = gcs_add_client(bt_mesh_central_gcs_client_callback, BLE_CENTRAL_APP_MAX_LINKS, BLE_CENTRAL_APP_MAX_DISCOV_TABLE_NUM); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + bt_mesh_scatternet_gcs_client_id = gcs_add_client(bt_mesh_scatternet_gcs_client_callback, BLE_SCATTERNET_APP_MAX_LINKS, BLE_SCATTERNET_APP_MAX_DISCOV_TABLE_NUM); +#endif + +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void bt_mesh_device_multiple_profile_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_mesh_device_multiple_profile_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void bt_mesh_device_multiple_profile_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void bt_mesh_device_multiple_profile_task_init(void) +{ + bt_mesh_device_multiple_profile_app_task_init(); +} + +void bt_mesh_device_multiple_profile_task_deinit(void) +{ + bt_mesh_device_multiple_profile_app_task_deinit(); +} + +void bt_mesh_device_multiple_profile_stack_config_init(void) +{ +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + gap_config_max_le_link_num(BLE_CENTRAL_APP_MAX_LINKS); + gap_config_max_le_paired_device(BLE_CENTRAL_APP_MAX_LINKS); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + gap_config_max_le_link_num(BLE_SCATTERNET_APP_MAX_LINKS); + gap_config_max_le_paired_device(BLE_SCATTERNET_APP_MAX_LINKS); +#else + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); +#endif +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_mesh_device_multiple_profile_app_main(void) +{ + bt_trace_init(); +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + bt_mesh_device_multiple_profile_stack_config_init(); +#endif + bte_init(); + bt_mesh_device_multiple_profile_board_init(); + bt_mesh_device_multiple_profile_driver_init(); +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + le_gap_init(BLE_CENTRAL_APP_MAX_LINKS); +#elif defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + le_gap_init(APP_MAX_LINKS); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + le_gap_init(BLE_SCATTERNET_APP_MAX_LINKS); +#else + le_gap_init(APP_MAX_LINKS); +#endif + bt_mesh_device_multiple_profile_app_le_gap_init(); + bt_mesh_device_multiple_profile_app_le_profile_init(); + bt_mesh_device_multiple_profile_stack_init(); + bt_mesh_device_multiple_profile_pwr_mgr_init(); + bt_mesh_device_multiple_profile_task_init(); + + return 0; +} + +int bt_mesh_device_multiple_profile_app_init(void) +{ + //int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT Mesh Device]BT Stack already on\n\r"); + return 0; + } + else + bt_mesh_device_multiple_profile_app_main(); + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_device_api_init()) { + printf("[BT Mesh Device] bt_mesh_device_api_init fail ! \n\r"); + return 1; + } +#endif + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK + bt_mesh_idle_check_init(); +#endif + + return 0; +} + +extern void mesh_deinit(void); +extern bool mesh_initial_state; +extern bool bt_trace_uninit(void); +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +extern void gcs_delete_client(void); +#endif + +extern T_GAP_DEV_STATE bt_mesh_device_multiple_profile_gap_dev_state; + +void bt_mesh_device_multiple_profile_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + bt_mesh_device_api_deinit(); +#endif + bt_mesh_device_multiple_profile_task_deinit(); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Device] BT Stack is not running\n\r"); + mesh_initial_state = FALSE; + bt_mesh_device_multiple_profile_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; + return; + } +#if F_BT_DEINIT + else { +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + gcs_delete_client(); +#endif + bte_deinit(); + printf("[BT Mesh Device] BT Stack deinitalized\n\r"); + } +#endif + mesh_deinit(); + bt_trace_uninit(); + +#if defined(CONFIG_BT_MESH_IDLE_CHECK) && CONFIG_BT_MESH_IDLE_CHECK + bt_mesh_idle_check_deinit(); +#endif +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + plt_timer_delete(bt_mesh_multiple_profile_peripheral_adv_timer, 0xFFFFFFFF); + bt_mesh_multiple_profile_peripheral_adv_timer = NULL; +#endif + mesh_initial_state = FALSE; + bt_mesh_device_multiple_profile_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.c new file mode 100644 index 00000000..033ed803 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.c @@ -0,0 +1,245 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif + +#include "mesh_api.h" +#include "device_multiple_profile_app.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "device_cmd.h" +#include "platform_opts.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#include "ble_scatternet_user_cmd.h" +#endif +/*============================================================================* + * Macros + *============================================================================*/ +#define EVENT_MESH 0x80 +#define APP_TASK_PRIORITY 4 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#else +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#endif + +#if defined(CONFIG_PLATFORM_8721D) +#define UART_TX _PA_18 +#define UART_RX _PA_19 +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +#define UART_TX PA_14 +#define UART_RX PA_13 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_mesh_device_multiple_profile_app_task_handle; //!< APP Task handle +void *bt_mesh_device_multiple_profile_evt_queue_handle; //!< Event queue handle +void *bt_mesh_device_multiple_profile_io_queue_handle; //!< IO queue handle +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +void *bt_mesh_device_multiple_profile_user_cmd_io_queue_handle; //!< user cmd queue handle +#endif + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_mesh_device_multiple_profile_app_main_task(void *p_param); + +void app_send_uart_msg(uint8_t data) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = IO_MSG_TYPE_UART; + msg.subtype = data; + if (os_msg_send(bt_mesh_device_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_device_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +} + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern CMD_MOD_INFO_S btMeshCmdPriv; +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg) +{ + uint8_t event = EVENT_USER_API_REQ; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)p_io_msg->u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + //trace commands transmitted to mesh stack + btMeshCmdPriv.cmdTransmittedNum ++; + if (os_msg_send(bt_mesh_device_multiple_profile_user_cmd_io_queue_handle, p_io_msg, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_device_multiple_profile_user_cmd_io_queue_handle fail!\r\n"); + return 1; + } + else if (os_msg_send(bt_mesh_device_multiple_profile_evt_queue_handle, &event, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_device_multiple_profile_evt_queue_handle fail!\r\n"); + return 1; + } + + return 0; +} +#endif + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_device_multiple_profile_app_task_init() +{ + os_task_create(&bt_mesh_device_multiple_profile_app_task_handle, "bt_mesh_device_multiple_profile_app", bt_mesh_device_multiple_profile_app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_mesh_device_multiple_profile_app_main_task(void *p_param) +{ + /* avoid gcc compile warning */ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_mesh_device_multiple_profile_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_mesh_device_multiple_profile_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + os_msg_queue_create(&bt_mesh_device_multiple_profile_user_cmd_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); +#endif + gap_start_bt_stack(bt_mesh_device_multiple_profile_evt_queue_handle, bt_mesh_device_multiple_profile_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + mesh_start(EVENT_MESH, EVENT_IO_TO_APP, bt_mesh_device_multiple_profile_evt_queue_handle, bt_mesh_device_multiple_profile_io_queue_handle); + + mesh_data_uart_init(UART_TX, UART_RX, app_send_uart_msg); + mesh_user_cmd_init("MeshDevice"); + + while (true) + { + if (os_msg_recv(bt_mesh_device_multiple_profile_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_multiple_profile_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_device_multiple_profile_app_handle_io_msg(io_msg); + } + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + else if (event == EVENT_USER_API_REQ) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_multiple_profile_user_cmd_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_io_msg_handler(io_msg); + } + } +#endif +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + else if (event == EVENT_USER_HTTP_SERVER) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_device_multiple_profile_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_demo_io_msg_handler(io_msg); + } + } +#endif + else if (event == EVENT_MESH) + { + mesh_inner_msg_handle(event); + } + else + { + gap_handle_msg(event); + } + } + } +} + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +extern int bt_mesh_scatternet_peripheral_app_max_links; +extern int bt_mesh_scatternet_central_app_max_links; +#endif +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_device_multiple_profile_app_task_deinit(void) +{ + if (bt_mesh_device_multiple_profile_app_task_handle) { + os_task_delete(bt_mesh_device_multiple_profile_app_task_handle); + } + if (bt_mesh_device_multiple_profile_io_queue_handle) { + os_msg_queue_delete(bt_mesh_device_multiple_profile_io_queue_handle); + } + if (bt_mesh_device_multiple_profile_evt_queue_handle) { + os_msg_queue_delete(bt_mesh_device_multiple_profile_evt_queue_handle); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_device_multiple_profile_user_cmd_io_queue_handle) { + os_msg_queue_delete(bt_mesh_device_multiple_profile_user_cmd_io_queue_handle); + } + bt_mesh_device_multiple_profile_user_cmd_io_queue_handle = NULL; +#endif + bt_mesh_device_multiple_profile_io_queue_handle = NULL; + bt_mesh_device_multiple_profile_evt_queue_handle = NULL; + bt_mesh_device_multiple_profile_app_task_handle = NULL; +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + bt_mesh_scatternet_peripheral_app_max_links = 0; + bt_mesh_scatternet_central_app_max_links = 0; +#endif + mesh_user_cmd_deinit("MeshDevice"); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.h new file mode 100644 index 00000000..c4f260f7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.h @@ -0,0 +1,27 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_DEVICE_MULTIPLE_PROFILE_APP_TASK_H_ +#define _BT_MESH_DEVICE_MULTIPLE_PROFILE_APP_TASK_H_ + +#include "mesh_config.h" + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_device_multiple_profile_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_device_multiple_profile_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.c new file mode 100644 index 00000000..1c5ec79d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.c @@ -0,0 +1,2660 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.c +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "device_multiple_profile_app.h" +#include "trace_app.h" +#include "gap_wrapper.h" +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "device_cmd.h" +#include "mesh_cmd.h" +#include "ping_app.h" +#include "datatrans_server.h" +#include "bt_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#include "bt_mesh_device_api.h" +#endif + +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL +#include +#include +#include +#include "platform_stdlib.h" +#include "ble_peripheral_at_cmd.h" +#include +#include +#include +#endif + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +#include +#include "ble_central_at_cmd.h" +#include +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#include "platform_stdlib.h" +#include +#include +#include "gatt_builtin_services.h" +#include "ble_central_at_cmd.h" +#include "ble_peripheral_at_cmd.h" +#include +#include +#include +#include +#endif + +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +T_CLIENT_ID bt_mesh_central_gcs_client_id; /**< General Common Services client client id*/ +#endif +int bt_mesh_multiple_profile_scan_state = 0; +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +int bt_mesh_scatternet_peripheral_app_max_links = 0; +int bt_mesh_scatternet_central_app_max_links = 0; +T_CLIENT_ID bt_mesh_scatternet_gcs_client_id; /**< General Common Services client client id*/ +#endif + +#if ((!defined(CONFIG_BT_MESH_CENTRAL) || !CONFIG_BT_MESH_CENTRAL) && \ + (!defined(CONFIG_BT_MESH_SCATTERNET) || !CONFIG_BT_MESH_SCATTERNET)) +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined (CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; +int array_count_of_adv_data = sizeof(adv_data) / sizeof(adv_data[0]); +T_SERVER_ID bt_mesh_simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bt_mesh_bas_srv_id; /**< Battery service id */ +#endif + +T_GAP_DEV_STATE bt_mesh_device_multiple_profile_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +T_APP_LINK bt_mesh_multiple_profile_app_link_table[BLE_CENTRAL_APP_MAX_LINKS]; +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +T_APP_LINK bt_mesh_multiple_profile_app_link_table[BLE_SCATTERNET_APP_MAX_LINKS]; +#else +T_APP_LINK bt_mesh_multiple_profile_app_link_table[APP_MAX_LINKS]; +#endif + +prov_auth_value_type_t prov_auth_value_type; + +void bt_mesh_device_multiple_profile_app_handle_gap_msg(T_IO_MSG *p_gap_msg); + +static uint8_t datatrans_sample_data[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xa, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; + +uint8_t lpn_disable_scan_flag = 0; + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +extern uint8_t le_adv_start_enable; +extern void mesh_le_adv_start(void); +extern void mesh_le_adv_stop(void); +#endif +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_mesh_device_multiple_profile_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + { + /* We handle user command informations from Data UART in this branch. */ + uint8_t data = io_msg.subtype; + mesh_user_cmd_collect(&data, sizeof(data), device_cmd_table); + } + break; + case PING_TIMEOUT_MSG: + { + ping_handle_timeout(); + } + break; + case PING_APP_TIMEOUT_MSG: + { + ping_app_handle_timeout(); + } + break; + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (ble_central_app_handle_at_cmd(subtype, arg) != 1) { + ble_peripheral_app_handle_at_cmd(subtype, arg); + } +#elif defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + ble_central_app_handle_at_cmd(subtype, arg); +#elif defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + ble_peripheral_app_handle_at_cmd(subtype, arg); +#endif + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 2) { + gap_sched_scan(false); + } else if (io_msg.subtype == 3) { + gap_sched_scan(true); + } + } + break; +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined (CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + case IO_MSG_TYPE_ADV: + { + if (le_adv_start_enable) { + uint8_t *padv_data = gap_sched_task_get(); + + if (NULL == padv_data) + { + printf("[BT Mesh Device] bt_mesh_multiple_profile_peripheral_adv_timer_handler allocate padv_data fail ! \n\r"); + break; + } + + gap_sched_task_p ptask = CONTAINER_OF(padv_data, gap_sched_task_t, adv_data); + + memcpy(padv_data, (uint8_t *)adv_data, sizeof(adv_data)); + + ptask->adv_len += 23; + ptask->adv_type = GAP_SCHED_ADV_TYPE_IND; + + gap_sched_try(ptask); + } + } + break; +#endif + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_mesh_device_multiple_profile_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_mesh_device_multiple_profile_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + /*stack ready*/ + mesh_le_adv_start(); +#endif + } + } + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + if (bt_mesh_device_multiple_profile_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("\n\rGAP adv stoped: because connection created\n\r"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + printf("\n\rGAP adv stopped\n\r"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("\n\rGAP adv start\n\r"); + } + } +#endif + +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + if (bt_mesh_device_multiple_profile_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + //data_uart_debug("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + //data_uart_debug("GAP scan start\r\n"); + } + } +#endif + + bt_mesh_device_multiple_profile_gap_dev_state = new_state; +} + +uint8_t mesh_device_conn_state = 0; + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + T_GAP_CONN_INFO conn_info; +#endif +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + if (conn_id >= BLE_CENTRAL_APP_MAX_LINKS) + { + return; + } +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (conn_id >= BLE_SCATTERNET_APP_MAX_LINKS) + { + return; + } +#else + if (conn_id >= APP_MAX_LINKS) + { + return; + } +#endif + + APP_PRINT_INFO4("bt_mesh_device_multiple_profile_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, bt_mesh_multiple_profile_app_link_table[conn_id].conn_state, new_state, disc_cause); + + bt_mesh_multiple_profile_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_mesh_device_multiple_profile_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + data_uart_debug("Disconnect conn_id %d\r\n", conn_id); + mesh_device_conn_state = 0; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + goto next; + } + } else { + goto next; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_disconnect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_disconnect)); + goto next; + } + } else { + goto next; + } +#endif +next: +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + mesh_le_adv_start(); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + /*stack ready*/ + mesh_le_adv_start(); + } +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + bt_mesh_scatternet_central_app_max_links --; + } else if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + bt_mesh_scatternet_peripheral_app_max_links --; + } +#endif + memset(&bt_mesh_multiple_profile_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, bt_mesh_multiple_profile_app_link_table[conn_id].bd_addr, + &bt_mesh_multiple_profile_app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(bt_mesh_multiple_profile_app_link_table[conn_id].bd_addr), bt_mesh_multiple_profile_app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_debug("Connected success conn_id %d\r\n", conn_id); + mesh_device_conn_state = 1; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + } +#endif +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + //get device role + if (le_get_conn_info(conn_id, &conn_info)){ + bt_mesh_multiple_profile_app_link_table[conn_id].role = conn_info.role; + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) + bt_mesh_scatternet_central_app_max_links ++; + else if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) + bt_mesh_scatternet_peripheral_app_max_links ++; + } + + ////print bt address type + uint8_t local_bd_type; + //uint8_t features[8]; + uint8_t remote_bd_type; + le_get_conn_param(GAP_PARAM_CONN_LOCAL_BD_TYPE, &local_bd_type, conn_id); + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR_TYPE, &remote_bd_type, conn_id); + APP_PRINT_INFO3("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); + data_uart_debug("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); +#endif + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, 251, 2120); +#endif +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + mesh_le_adv_stop(); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + mesh_le_adv_stop(); + } +#endif + } + break; + + default: + break; + + } + +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_mesh_device_multiple_profile_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_mesh_device_multiple_profile_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_debug("Pair success\r\n"); + APP_PRINT_INFO0("bt_mesh_device_multiple_profile_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_debug("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_mesh_device_multiple_profile_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_mesh_device_multiple_profile_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_mesh_device_multiple_profile_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_mesh_device_multiple_profile_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_debug("\n\rbt_mesh_device_multiple_profile_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x \r\n", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_mesh_device_multiple_profile_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + data_uart_debug("\n\rbt_mesh_device_multiple_profile_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x\r\n", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_mesh_device_multiple_profile_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + data_uart_debug("\n\rbt_mesh_device_multiple_profile_app_handle_conn_param_update_evt update pending: conn_id %d\r\n", conn_id); + } + break; + + default: + break; + } +} + +bool mesh_initial_state = FALSE; + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * sub_type of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_mesh_device_multiple_profile_app_handle_gap_msg: sub_type %d", p_gap_msg->subtype); + mesh_inner_msg_t mesh_inner_msg; + mesh_inner_msg.type = MESH_BT_STATUS_UPDATE; + mesh_inner_msg.sub_type = p_gap_msg->subtype; + mesh_inner_msg.parm = p_gap_msg->u.param; + gap_sched_handle_bt_status_msg(&mesh_inner_msg); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + if (!mesh_initial_state) + { + mesh_initial_state = TRUE; + /** set device uuid according to bt address */ + uint8_t bt_addr[6]; + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + memcpy(dev_uuid, bt_addr, sizeof(bt_addr)); + device_uuid_set(dev_uuid); + } + bt_mesh_device_multiple_profile_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_mesh_device_multiple_profile_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_mesh_device_multiple_profile_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_mesh_device_multiple_profile_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_mesh_device_multiple_profile_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_debug("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_device_app_handle_gap_msg: unknown sub_type %d", p_gap_msg->subtype); + break; + } +} + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void bt_mesh_central_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("ble_central_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_central_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, + *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, + data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", + *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); +// BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +/** @} */ /* End of group CENTRAL_CLIENT_GAP_MSG */ + +/** @defgroup CENTRAL_CLIENT_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void bt_mesh_scatternet_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("ble_scatternet_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_scatternet_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, + *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, + data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", + *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); +// BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} +#endif + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_multiple_profile_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + char adv_type[20]; + char remote_addr_type[10]; +#endif + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + if (bt_mesh_multiple_profile_scan_state) { + /* If you want to parse the scan info, please reference function ble_central_app_parse_scan_info. */ + sprintf(adv_type,"%s",(p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_UNDIRECTED)? "CON_UNDIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_DIRECTED)? "CON_DIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCANNABLE)? "SCANABLE_UNDIRCT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_NON_CONNECTABLE)? "NON_CONNECTABLE": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCAN_RSP)? "SCAN_RSP":"unknown"); + sprintf(remote_addr_type,"%s",(p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_PUBLIC)? "public": + (p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_RANDOM)? "random":"unknown"); + + BLE_PRINT("ADVType\t\t\t| AddrType\t|%s\t\t\t|rssi\n\r","BT_Addr"); + BLE_PRINT("%s\t\t%s\t"BD_ADDR_FMT"\t%d\n\r",adv_type,remote_addr_type,BD_ADDR_ARG(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->rssi); +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + bt_mesh_central_app_parse_scan_info(p_data->p_le_scan_info); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + bt_mesh_scatternet_app_parse_scan_info(p_data->p_le_scan_info); +#endif + } +#endif + gap_sched_handle_adv_report(p_data->p_le_scan_info); + break; + +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + gap_sched_adv_params_set_done(); + break; + /* + case GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: cause 0x%x", + p_data->le_cause.cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + break; + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; + + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; + */ +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + data_uart_print("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d\r\n", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_device_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#if F_BT_GAPS_CHAR_WRITEABLE +/** @defgroup SCATTERNET_GAPS_WRITE GAP Service Callback Handler + * @brief Use @ref F_BT_GAPS_CHAR_WRITEABLE to open + * @{ + */ +/** + * @brief All the BT GAP service callback events are handled in this function + * @param[in] service_id Profile service ID + * @param[in] p_para Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_scatternet_gap_service_callback(T_SERVER_ID service_id, void *p_para) +{ + (void) service_id; + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; + APP_PRINT_INFO2("bt_mesh_scatternet_gap_service_callback: conn_id = %d msg_type = %d\n", p_gap_data->conn_id, + p_gap_data->msg_type); + APP_PRINT_INFO2("bt_mesh_scatternet_gap_service_callback: len = 0x%x,opcode = %d\n", p_gap_data->msg_data.len, + p_gap_data->msg_data.opcode); + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) + { + switch (p_gap_data->msg_data.opcode) + { + case GAPS_WRITE_DEVICE_NAME: + { + T_LOCAL_NAME device_name; + memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); + device_name.local_name[p_gap_data->msg_data.len] = 0; + //data_uart_debug("GAPS_WRITE_DEVICE_NAME:device_name = %s \n\r",device_name.local_name); + flash_save_local_name(&device_name); + } + break; + + case GAPS_WRITE_APPEARANCE: + { + uint16_t appearance_val; + T_LOCAL_APPEARANCE appearance; + + LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); + appearance.local_appearance = appearance_val; + //data_uart_debug("GAPS_WRITE_APPEARANCE:appearance = %s \n\r",appearance.local_appearance); + flash_save_local_appearance(&appearance); + } + break; + default: + APP_PRINT_ERROR1("bt_mesh_scatternet_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + //data_uart_debug("bt_mesh_scatternet_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + break; + } + } + return result; +} +/** @} */ +#endif + +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void bt_mesh_scatternet_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + data_uart_debug("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + data_uart_debug("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + data_uart_debug("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + data_uart_debug("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + data_uart_debug("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + data_uart_debug("Invalid disc type: conn_id %d, discov_type %d\n\r", + conn_id, discov_result.discov_type); + break; + } +} + +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_scatternet_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_scatternet_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_mesh_scatternet_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_mesh_scatternet_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_debug("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\n\r", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_debug("READ VALUE: "); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_debug("\n\r"); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_debug("WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("INDICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("INDICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("NOTIFICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + + return result; +} +#endif + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_multiple_profile_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_device_multiple_profile_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_device_multiple_profile_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + data_uart_debug("\n\rPROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE success\r\n"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE failed\r\n"); + } + break; + + default: + break; + } + } + else if (service_id == datatrans_server_id) + { + datatrans_server_data_t *pdata = p_data; + switch (pdata->type) + { + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + pdata->len = sizeof(datatrans_sample_data); + pdata->data = datatrans_sample_data; + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + if (pdata->len > sizeof(datatrans_sample_data)) + { + pdata->len = sizeof(datatrans_sample_data); + } + memcpy(datatrans_sample_data, pdata->data, pdata->len); + break; + default: + break; + } + } +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + else if (service_id == bt_mesh_simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V3_ENABLE\r\n"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V3_DISABLE\r\n"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V4_ENABLE\r\n"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V4_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + data_uart_debug("SIMP_READ_V1: value 0x%02x 0x%02x\r\n", value[0], value[1]); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_debug("SIMP_WRITE_V2: write type %d, len %d\r\n", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_debug("SIMP_WRITE_V2: value "); + for(int i = 0; i < p_simp_cb_data->msg_data.write.len; i ++){ + data_uart_debug("0x%02x ", *(p_simp_cb_data->msg_data.write.p_value + i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bt_mesh_bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + data_uart_debug("\n\rBAS_NOTIFY_BATTERY_LEVEL_ENABLE\r\n"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + data_uart_debug("\n\rBAS_NOTIFY_BATTERY_LEVEL_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + data_uart_debug("\n\rBAS_READ_BATTERY_LEVEL: battery_level %d\r\n", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } +#endif + + return app_result; +} + +/****************************************************************** + * @fn device_info_cb + * @brief device_info_cb callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return void + */ +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + if (!dev_info_show_flag) + { + return; + } + data_uart_debug("bt addr=0x%02x%02x%02x%02x%02x%02x type=%d rssi=%d ", bt_addr[5], bt_addr[4], + bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0], bt_addr_type, rssi); + switch (pinfo->type) + { + case DEVICE_INFO_UDB: + data_uart_debug("udb="); + data_uart_dump(pinfo->pbeacon_udb->dev_uuid, 16); + break; + case DEVICE_INFO_PROV_ADV: + data_uart_debug("prov="); + data_uart_dump(pinfo->pservice_data->provision.dev_uuid, 16); + break; + case DEVICE_INFO_PROXY_ADV: + data_uart_debug("proxy="); + data_uart_dump((uint8_t *)&pinfo->pservice_data->proxy, pinfo->len); + break; + default: + break; + } +} + +/****************************************************************** + * @fn prov_cb + * @brief Provisioning callbacks are handled in this function. + * + * @param cb_data - @ref TProvisioningCbData + * @return the operation result + */ +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data) +{ + APP_PRINT_INFO1("prov_cb: type = %d", cb_type); + + switch (cb_type) + { + case PROV_CB_TYPE_PB_ADV_LINK_STATE: + switch (cb_data.pb_generic_cb_type) + { + case PB_GENERIC_CB_LINK_OPENED: + data_uart_debug("PB-ADV Link Opened!\r\n>"); + break; + case PB_GENERIC_CB_LINK_OPEN_FAILED: + data_uart_debug("PB-ADV Link Open Failed!\r\n>"); + break; + case PB_GENERIC_CB_LINK_CLOSED: + data_uart_debug("PB-ADV Link Closed!\r\n>"); + break; + default: + break; + } + break; + case PROV_CB_TYPE_UNPROV: + data_uart_debug("unprov device!\r\n>"); + break; + case PROV_CB_TYPE_START: + data_uart_debug("being prov-ed!\r\n"); + break; + case PROV_CB_TYPE_PUBLIC_KEY: + { + uint8_t public_key[64] = {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79}; + uint8_t private_key[32] = {0x52, 0x9a, 0xa0, 0x67, 0x0d, 0x72, 0xcd, 0x64, 0x97, 0x50, 0x2e, 0xd4, 0x73, 0x50, 0x2b, 0x03, 0x7e, 0x88, 0x03, 0xb5, 0xc6, 0x08, 0x29, 0xa5, 0xa3, 0xca, 0xa2, 0x19, 0x50, 0x55, 0x30, 0xba}; + prov_params_set(PROV_PARAMS_PUBLIC_KEY, public_key, sizeof(public_key)); + prov_params_set(PROV_PARAMS_PRIVATE_KEY, private_key, sizeof(private_key)); + APP_PRINT_INFO0("prov_cb: Please show the public key to the provisioner"); + } + break; + case PROV_CB_TYPE_AUTH_DATA: + { + prov_start_p pprov_start = cb_data.pprov_start; + prov_auth_value_type = prov_auth_value_type_get(pprov_start); + /* use cmd to set auth data */ + data_uart_debug("auth method=%d[nsoi] action=%d size=%d type=%d[nbNa]\r\n>", + pprov_start->auth_method, + pprov_start->auth_action, pprov_start->auth_size, prov_auth_value_type); + //uint8_t auth_data[16] = {1}; + switch (pprov_start->auth_method) + { + case PROV_AUTH_METHOD_STATIC_OOB: + //prov_auth_value_set(auth_data, sizeof(auth_data)); + APP_PRINT_INFO0("prov_cb: Please exchange the oob data with the provisioner"); + break; + case PROV_AUTH_METHOD_OUTPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.output_oob_size); + APP_PRINT_INFO2("prov_cb: Please output the oob data to the provisioner, output size = %d, action = %d", + pprov_start->auth_size.output_oob_size, pprov_start->auth_action.output_oob_action); + break; + case PROV_AUTH_METHOD_INPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.input_oob_size); + APP_PRINT_INFO2("prov_cb: Please input the oob data provided by the provisioner, input size = %d, action = %d", + pprov_start->auth_size.input_oob_size, pprov_start->auth_action.input_oob_action); + break; + default: + break; + } + } + break; + case PROV_CB_TYPE_COMPLETE: + { + mesh_node.iv_timer_count = MESH_IV_INDEX_48W; + prov_data_p pprov_data = cb_data.pprov_data; + data_uart_debug("been prov-ed with addr 0x%04x!\r\n", pprov_data->unicast_address); + } + break; + case PROV_CB_TYPE_FAIL: + data_uart_debug("provision fail, type=%d!\r\n", cb_data.prov_fail.fail_type); + break; + case PROV_CB_TYPE_PROV: + /* stack ready */ + data_uart_debug("ms addr: 0x%04x\r\n>", mesh_node.unicast_addr); + break; + default: + break; + } + return true; +} + +/****************************************************************** + * @fn fn_cb + * @brief fn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"establishing with lpn 0x%04x\r\n", "no poll from 0x%04x\r\n", "established with lpn 0x%04x\r\n", "lpn 0x%04x lost\r\n"}; + data_uart_debug(string[type], lpn_addr); + if (type == FN_CB_TYPE_ESTABLISH_SUCCESS || type == FN_CB_TYPE_FRND_LOST) + { + user_cmd_time(NULL); + } +} + +/****************************************************************** + * @fn lpn_cb + * @brief lpn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"established with fn 0x%04x\r\n", "no frnd offer\r\n", "no frnd update\r\n", "fn 0x%04x lost\r\n"}; + data_uart_debug(string[type], fn_addr); + if (type == LPN_CB_TYPE_ESTABLISH_SUCCESS || type == LPN_CB_TYPE_FRIENDSHIP_LOST) + { + user_cmd_time(NULL); + } + + if (type == LPN_CB_TYPE_ESTABLISH_SUCCESS) + { + gap_sched_scan(false); + lpn_disable_scan_flag = 1; + mesh_service_adv_stop(); + } + else if (type == LPN_CB_TYPE_FRIENDSHIP_LOST) + { + if (lpn_disable_scan_flag){ + gap_sched_scan(true); + lpn_disable_scan_flag = 0; + } + mesh_service_adv_start(); + } +} + +/****************************************************************** + * @fn hb_cb + * @brief heartbeat callbacks are handled in this function. + * + * @param type + * @param pdata + * @return void + */ +void hb_cb(hb_data_type_t type, void *pargs) +{ + switch (type) + { + case HB_DATA_PUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat publish timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat publish timer stop\r\n"); + } + } + break; + case HB_DATA_SUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat subscription timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat subscription timer stop\r\n"); + } + } + break; + case HB_DATA_PUB_COUNT_UPDATE: + { + hb_data_pub_count_update_t *pdata = pargs; + data_uart_debug("heartbeat publish count update: %d\r\n", pdata->count); + } + break; + case HB_DATA_SUB_PERIOD_UPDATE: + { + hb_data_sub_period_update_t *pdata = pargs; + data_uart_debug("heartbeat subscription period update: %d\r\n", pdata->period); + } + break; + case HB_DATA_SUB_RECEIVE: + { + hb_data_sub_receive_t *pdata = pargs; + data_uart_debug("receive heartbeat: src = %d, init_ttl = %d, features = %d-%d-%d-%d, ttl = %d\r\n", + pdata->src, pdata->init_ttl, pdata->features.relay, pdata->features.proxy, + pdata->features.frnd, pdata->features.lpn, pdata->ttl); + } + break; + default: + break; + } +} + +void bt_mesh_device_multiple_profile_app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("bt_mesh_device_multiple_profile_app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_ERROR1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void bt_mesh_central_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + BLE_PRINT("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + BLE_PRINT("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + BLE_PRINT("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + BLE_PRINT("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + BLE_PRINT("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + + + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + BLE_PRINT("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + BLE_PRINT("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + BLE_PRINT("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + BLE_PRINT("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + BLE_PRINT("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + BLE_PRINT("Invalid disc type: conn_id %d, discov_type %d\n\r", + conn_id, discov_result.discov_type); + break; + } +} + +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_central_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("ble_central_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_mesh_central_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_mesh_central_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_debug("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\n\r", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_debug("READ VALUE: "); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_debug("\n\r"); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_debug("WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("INDICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("INDICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("NOTIFICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + + return result; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.h new file mode 100644 index 00000000..a2951ee4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.h @@ -0,0 +1,128 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.h +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _MESH_APPLICATION__ +#define _MESH_APPLICATION__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "app_msg.h" +#include "mesh_api.h" +#include "bt_mesh_device_multiple_profile_app_flags.h" + +/*============================================================================* + * Variables + *============================================================================*/ +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +extern T_CLIENT_ID bt_mesh_central_gcs_client_id; /**< General Common Services client client id*/ +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] +#endif +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL +extern T_SERVER_ID bt_mesh_simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bt_mesh_bas_srv_id; /**< Battery service id */ +extern const uint8_t adv_data[]; +#endif +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] +extern T_SERVER_ID bt_mesh_simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bt_mesh_bas_srv_id; /**< Battery service id */ +extern const uint8_t adv_data[]; +extern T_CLIENT_ID bt_mesh_scatternet_gcs_client_id; /**< General Common Services client client id*/ +#endif +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_device_multiple_profile_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_multiple_profile_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_device_multiple_profile_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_device_multiple_profile_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_central_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_scatternet_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#if F_BT_GAPS_CHAR_WRITEABLE +T_APP_RESULT bt_mesh_scatternet_gap_service_callback(T_SERVER_ID service_id, void *p_para); +#endif +#endif + +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo); +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +void hb_cb(hb_data_type_t type, void *pargs); +void bt_mesh_device_multiple_profile_app_vendor_callback(uint8_t cb_type, void *p_cb_data); +#ifdef __cplusplus +} +#endif + +#endif /* _MESH_APPLICATION__S */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.c new file mode 100644 index 00000000..dffabc45 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.c @@ -0,0 +1,346 @@ +/** +************************************************************************************************************ +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +************************************************************************************************************ +* @file device_cmd.c +* @brief User defined Mesh test commands. +* @details User command interfaces. +* @author +* @date 2015-03-19 +* @version v0.1 +************************************************************************************************************* +*/ +#include +#include "trace.h" +#include "gap_wrapper.h" +#include "mesh_cmd.h" +#include "test_cmd.h" +#include "mesh_api.h" +#include "device_cmd.h" +#include "device_app.h" +#include "datatrans_model.h" +#include "datatrans_app.h" +#include "generic_on_off.h" +#include "datatrans_server.h" + +extern mesh_model_info_t health_server_model; +extern mesh_model_info_t generic_on_off_server_model; +extern uint8_t lpn_disable_scan_flag; + +static user_cmd_parse_result_t user_cmd_node_reset(user_cmd_parse_value_t *pparse_value) +{ + switch (pparse_value->dw_parameter[0]) + { + case 0: + mesh_node_reset(); + break; + case 1: + mesh_node_clean(); + break; + case 2: + mesh_node_restore(); + break; + default: + break; + } + return USER_CMD_RESULT_OK; +} + +user_cmd_parse_result_t user_cmd_prov_capa_set(user_cmd_parse_value_t *pparse_value) +{ + prov_capabilities_t prov_capabilities; + prov_capabilities.algorithm = PROV_CAP_ALGO_FIPS_P256_ELLIPTIC_CURVE; + prov_capabilities.public_key = pparse_value->dw_parameter[0] ? PROV_CAP_PUBLIC_KEY_OOB : 0; + prov_capabilities.static_oob = pparse_value->dw_parameter[1] ? PROV_CAP_STATIC_OOB : 0; + prov_capabilities.output_oob_size = pparse_value->dw_parameter[2]; + prov_capabilities.output_oob_action = pparse_value->dw_parameter[3]; + prov_capabilities.input_oob_size = pparse_value->dw_parameter[4]; + prov_capabilities.input_oob_action = pparse_value->dw_parameter[5]; + if (prov_capabilities.output_oob_size > OUTPUT_OOB_SIZE_MAX || + prov_capabilities.input_oob_size > INPUT_OOB_SIZE_MAX) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + else + { + prov_params_set(PROV_PARAMS_CAPABILITIES, &prov_capabilities, sizeof(prov_capabilities_t)); + return USER_CMD_RESULT_OK; + } +} + +#if MESH_LPN +static user_cmd_parse_result_t user_cmd_lpn_init(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_num = pparse_value->dw_parameter[0]; + return lpn_init(fn_num, lpn_cb) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_lpn_deinit(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + lpn_deinit(); + if (lpn_disable_scan_flag){ + gap_sched_scan(true); + lpn_disable_scan_flag = 0; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_lpn_req(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + lpn_req_params_t req_params = {50, 100, {1, 0, 0, 0}}; + + if(le_get_active_link_num() != 0) + { + data_uart_debug("Have BLE active link, cannot establish friendship\n\r"); + return (USER_CMD_RESULT_ERROR); + } + + if (pparse_value->dw_parameter[2]) + { + req_params.poll_interval = pparse_value->dw_parameter[2]; + } + if (pparse_value->dw_parameter[3]) + { + req_params.poll_timeout = pparse_value->dw_parameter[3]; + } + if (pparse_value->dw_parameter[4] >= 0xa && pparse_value->dw_parameter[4] <= 0xff) + { + mesh_node.frnd_rx_delay = pparse_value->dw_parameter[4]; + } + if (pparse_value->para_count >= 6 && pparse_value->dw_parameter[5] <= 0xff) + { + mesh_node.frnd_rx_widen = pparse_value->dw_parameter[5]; + } + return lpn_req(fn_index, net_key_index, + &req_params) == LPN_REQ_REASON_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_lpn_sub(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + uint16_t addr = pparse_value->dw_parameter[1]; + bool add_rm = pparse_value->dw_parameter[2]; + frnd_sub_list_add_rm(fn_index, &addr, 1, add_rm); + return (USER_CMD_RESULT_OK); +} + +static user_cmd_parse_result_t user_cmd_lpn_clear(user_cmd_parse_value_t *pparse_value) +{ + uint8_t fn_index = pparse_value->dw_parameter[0]; + lpn_clear(fn_index); + return (USER_CMD_RESULT_OK); +} +#endif + +#if MESH_RMT_PRO_CLIENT +static user_cmd_parse_result_t user_cmd_rmt_pro_scan(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t mode = 0; + if (pparse_value->para_count > 1) + { + mode = pparse_value->dw_parameter[1]; + } + switch (mode) + { + case 0: + RmtProClient_ScanStart(dst); + break; + case 1: + { + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + RmtProClient_ScanStartWithFilter(dst, dev_uuid); + } + break; + case 2: + RmtProClient_ScanUnproDeviceNum(dst, 3); + break; + default: + break; + } + + return (USER_CMD_RESULT_OK); +} +#endif + +static user_cmd_parse_result_t user_cmd_data_transmission_notify(user_cmd_parse_value_t + *pparse_value) +{ + uint8_t conn_id = pparse_value->dw_parameter[0]; + uint8_t data_len = pparse_value->para_count - 1; + uint8_t data[20]; + if (data_len > 20) + { + data_len = 20; + } + + for (uint8_t i = 0; i < data_len; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + + datatrans_server_notify(conn_id, data, data_len); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_generic_on_off_publish(user_cmd_parse_value_t *pparse_value) +{ + generic_on_off_t on_off = (generic_on_off_t)pparse_value->dw_parameter[0]; + mesh_model_p pmodel = generic_on_off_server_model.pmodel; + + pmodel->pub_params.pub_addr = 0xFEFF; + pmodel->pub_params.pub_ttl = 0x3F; + generic_on_off_publish(&generic_on_off_server_model, on_off); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_write(user_cmd_parse_value_t *pparse_value) +{ + uint8_t para_count = pparse_value->para_count; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + uint8_t data[75]; +#else + uint8_t data[18]; +#endif + + for (uint8_t i = 0; i < para_count - 3; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + datatrans_write(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[para_count - 2], para_count - 3, data, + pparse_value->dw_parameter[para_count - 1]); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_read(user_cmd_parse_value_t *pparse_value) +{ + datatrans_read(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const user_cmd_table_entry_t device_cmd_table[] = +{ + // mesh common cmd + MESH_COMMON_CMD, + TEST_CMD, + // device cmd + { + "nr", + "nr [mode]\n\r", + "node reset\n\r", + user_cmd_node_reset + }, + // prov + { + "pcs", + "pcs [public key oob] [static oob] [output size] [output action] [input size] [input action]\n\r", + "provision capability set\n\r", + user_cmd_prov_capa_set + }, +#if MESH_LPN + { + "lpninit", + "lpninit [fn_num]\n\r", + "low power node init\n\r", + user_cmd_lpn_init + }, + { + "lpndeinit", + "lpndeinit\n\r", + "low power node deinit\n\r", + user_cmd_lpn_deinit + }, + { + "lpnreq", + "lpnreq [fn_index] [net_key_index] [poll int(100ms)] [poll to(100ms)] [rx delay(ms)] [rx widen(ms)]\n\r", + "LPN request to estabish a friendship\n\r", + user_cmd_lpn_req + }, + { + "lpnsub", + "lpnsub [fn_index] [addr] [add/rm]\n\r", + "LPN subsript list add or rm\n\r", + user_cmd_lpn_sub + }, + { + "lpnclear", + "lpnclear [fn_index]\n\r", + "LPN clear\n\r", + user_cmd_lpn_clear + }, +#endif +#if MESH_RMT_PRO_CLIENT + { + "rmtproscan", + "rmtproscan [dst addr]\n\r", + "command remote server to scan\n\r", + user_cmd_rmt_pro_scan + }, +#endif + { + "dtn", + "dtn [conn_id] [value...]\n\r", + "data transmission notify\n\r", + user_cmd_data_transmission_notify + }, + { + "dtw", + "dtw [dst] [data...] [app_key_index] [ack] \n\r", + "data transmission write data\n\r", + user_cmd_datatrans_write + }, + { + "dtr", + "dtr [dst] [len] [app_key_index]\n\r", + "data transmission read data\n\r", + user_cmd_datatrans_read + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +const struct bt_mesh_api_hdl devicecmds[] = +{ + GEN_MESH_HANDLER(_node_reset) + GEN_MESH_HANDLER(_prov_capa_set) +#if MESH_LPN + GEN_MESH_HANDLER(_lpn_init) + GEN_MESH_HANDLER(_lpn_deinit) + GEN_MESH_HANDLER(_lpn_req) + GEN_MESH_HANDLER(_lpn_sub) + GEN_MESH_HANDLER(_lpn_clear) +#endif +#if MESH_FN + GEN_MESH_HANDLER(_fn_init) + GEN_MESH_HANDLER(_fn_deinit) +#endif + GEN_MESH_HANDLER(_data_transmission_notify) + GEN_MESH_HANDLER(_generic_on_off_publish) + GEN_MESH_HANDLER(_datatrans_write) + GEN_MESH_HANDLER(_datatrans_read) + GEN_MESH_HANDLER(_connect) + GEN_MESH_HANDLER(_disconnect) + GEN_MESH_HANDLER(_list) + GEN_MESH_HANDLER(_dev_info_show) +}; +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.h new file mode 100644 index 00000000..6e831ea0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.h @@ -0,0 +1,36 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _DEV_CMD_H_ +#define _DEV_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_config.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_cmd_types.h" +#endif + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +extern const user_cmd_table_entry_t device_cmd_table[]; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern const struct bt_mesh_api_hdl devicecmds[]; +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_flags.h new file mode 100644 index 00000000..a8012b5b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_flags.h @@ -0,0 +1,66 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_MESH_PROVISIONER_MULTIPLE_PROFILE_APP_FLAGS_H_ +#define _BT_MESH_PROVISIONER_MULTIPLE_PROFILE_APP_FLAGS_H_ + +#include "platform_opts_bt.h" + +#include + +/** + * @addtogroup MESH_APP_CONFIG + * @{ + */ + +/** + * @defgroup Mesh_App_Config Mesh App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#if defined(CONFIG_PLATFORM_8721D) +#define BLE_SCATTERNET_APP_MAX_LINKS 4 +#define BLE_SCATTERNET_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BLE_SCATTERNET_CENTRAL_APP_MAX_LINKS 3 //for max master link num +#elif defined(CONFIG_PLATFORM_8710C) +#define BLE_SCATTERNET_APP_MAX_LINKS 2 +#define BLE_SCATTERNET_PERIPHERAL_APP_MAX_LINKS 1 //for max slave link num +#define BLE_SCATTERNET_CENTRAL_APP_MAX_LINKS 1 //for max master link num +#endif +/** @brief Config the discovery table number of gcs_client */ +#define BLE_SCATTERNET_APP_MAX_DISCOV_TABLE_NUM 40 +#elif defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** @brief Config APP LE link number */ +#if defined(CONFIG_PLATFORM_8721D) +#define BLE_CENTRAL_APP_MAX_LINKS 3 +#elif defined(CONFIG_PLATFORM_8710C) +#define BLE_CENTRAL_APP_MAX_LINKS 1 +#endif +/** @brief Config the discovery table number of gcs_client */ +#define BLE_CENTRAL_APP_MAX_DISCOV_TABLE_NUM 40 +#else +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 1 +#endif + +/** @brief Config airplane mode support: 0-Not built in, 1-built in, use user command to set*/ +#define F_BT_AIRPLANE_MODE_SUPPORT 0 + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_main.c new file mode 100644 index 00000000..29cf9d41 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_main.c @@ -0,0 +1,877 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "provisioner_multiple_profile_app.h" +#include "health.h" +#include "ping.h" +#include "ping_app.h" +#include "tp.h" +#include "generic_client_app.h" +#include "light_client_app.h" +#include "provision_client.h" +#include "proxy_client.h" +#include "datatrans_app.h" +#include "bt_mesh_provisioner_multiple_profile_app_flags.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" +#include "wifi_constants.h" +#if defined(MESH_RPR) && MESH_RPR +#include "rmt_prov_client_app.h" +#endif +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_distributor_app.h" +#endif +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO +#include "bt_mesh_app_list_intf.h" +#endif + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_provisioner_api.h" +#endif + +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL +#include +#include +#include "platform_stdlib.h" +#include +#include "rtk_coex.h" +#include "bas.h" +#endif + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +#include +#include +#include +#include "rtk_coex.h" +#include "platform_stdlib.h" +#include "ble_central_at_cmd.h" +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#include +#include +#include "trace_uart.h" +#include +#include +#include +#include "rtk_coex.h" +#include +#include "bas.h" +#endif + +#define COMPANY_ID 0x005D +#define PRODUCT_ID 0x0000 +#define VERSION_ID 0x0000 + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; + +void bt_mesh_example_device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + /* avoid gcc compile warning */ + (void)bt_addr; + (void)bt_addr_type; + (void)rssi; + uint8_t NULL_UUID[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + if (pinfo->type == DEVICE_INFO_UDB) { + if (rtw_memcmp(pinfo->pbeacon_udb->dev_uuid, NULL_UUID, 16) == 0) + add_unproed_dev(pinfo->pbeacon_udb->dev_uuid); + } +} + +void generic_on_off_client_subscribe(void) +{ + uint16_t sub_addr = 0xFEFF; + mesh_model_p pmodel = model_goo_client.pmodel; + + if (pmodel == NULL || MESH_NOT_SUBSCRIBE_ADDR(sub_addr)) { + return; + } else { + mesh_model_sub(pmodel, sub_addr); + } +} +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 400 +#endif + +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief Default scan interval (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_INTERVAL 0x520 +/** @brief Default scan window (units of 0.625ms, 0x520=820ms) */ +#define DEFAULT_SCAN_WINDOW 0x520 +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + GAP_ADTYPE_APPEARANCE, /* type="Appearance" */ + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; +plt_timer_t bt_mesh_multiple_profile_peripheral_adv_timer = NULL; +uint8_t le_adv_start_enable = 0; +uint16_t bt_mesh_peripheral_adv_interval = 352; +extern int array_count_of_adv_data; +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + +extern void *bt_mesh_provisioner_multiple_profile_evt_queue_handle; //!< Event queue handle +extern void *bt_mesh_provisioner_multiple_profile_io_queue_handle; //!< IO queue handle +extern void rtw_set_timer(_timer *ptimer,u32 delay_time); +extern void rtw_init_timer(_timer *ptimer, void *adapter, TIMER_FUN pfunc,void* cntx, const char *name); + +void bt_mesh_multiple_profile_peripheral_adv_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + uint16_t adv_interval = bt_mesh_peripheral_adv_interval * 625 / 1000; + + io_msg.type = IO_MSG_TYPE_ADV; + + if (os_msg_send(bt_mesh_provisioner_multiple_profile_io_queue_handle, &io_msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } + if (le_adv_start_enable) { + plt_timer_change_period(bt_mesh_multiple_profile_peripheral_adv_timer, adv_interval, 0xFFFFFFFF); + } +} + +void mesh_le_adv_start(void) +{ + uint16_t adv_interval = bt_mesh_peripheral_adv_interval * 625 / 1000; + + le_adv_start_enable = 1; + plt_timer_change_period(bt_mesh_multiple_profile_peripheral_adv_timer, adv_interval, 0xFFFFFFFF); +} + +void mesh_le_adv_stop(void) +{ + le_adv_start_enable = 0; +} +#endif + +/****************************************************************** + * @fn Initial gap parameters + * @brief Initialize peripheral and gap bond manager related parameters + * + * @return void + */ +void bt_mesh_provisioner_multiple_profile_stack_init(void) +{ + /** set ble stack log level, disable nonsignificant log */ + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + // log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + // log_module_trace_set(TRACE_MODULE_LOWERSTACK, TRACE_LEVEL_ERROR, 0); + // log_module_trace_set(TRACE_MODULE_SNOOP, TRACE_LEVEL_ERROR, 0); + + /** set mesh stack log level, default all on, disable the log of level LEVEL_TRACE */ + uint32_t module_bitmap[MESH_LOG_LEVEL_SIZE] = {0}; + diag_level_set(TRACE_LEVEL_TRACE, module_bitmap); + + /** mesh stack needs rand seed */ + plt_srand(platform_random(0xffffffff)); + + /** configure provisioning parameters */ + prov_params_set(PROV_PARAMS_CALLBACK_FUN, (void *)prov_cb, sizeof(prov_cb_pf)); + + /** config node parameters */ + mesh_node_features_t features = + { + .role = MESH_ROLE_PROVISIONER, + .relay = 1, + .proxy = 1, + .fn = 1, + .lpn = 2, + .prov = 1, + .udb = 0, + .snb = 1, + .bg_scan = 1, + .flash = 1, + .flash_rpl = 1 + }; + + mesh_node_cfg_t node_cfg = + { + .dev_key_num = 20, + .net_key_num = 10, + .app_key_num = 3, + .vir_addr_num = 3, + .rpl_num = 20, + .sub_addr_num = 5, + .proxy_num = 1 + }; + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + features.relay = 0; + features.flash_rpl = 0; + node_cfg.dev_key_num = 50; + node_cfg.rpl_num = 50; + node_cfg.sub_addr_num = 0; +#endif + + node_cfg.proxy_interval = 5; + mesh_node_cfg(features, &node_cfg); + mesh_node.net_trans_count = 6; + mesh_node.relay_retrans_count = 2; + mesh_node.trans_retrans_count = 4; + mesh_node.ttl = 5; + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + +#endif + + /** create elements and register models */ + mesh_element_create(GATT_NS_DESC_UNKNOWN); + mesh_element_create(GATT_NS_DESC_UNKNOWN); + cfg_client_reg(); + generic_client_models_init(); +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + init_bt_mesh_priv(); +#else + tp_control_reg(tp_reveive); + ping_control_reg(ping_app_ping_cb, pong_receive); + trans_ping_pong_init(ping_app_ping_cb, pong_receive); + light_client_models_init(); + datatrans_model_init(); +#endif +#if defined(MESH_DFU) && MESH_DFU + dfu_dist_models_init(); +#endif +#if defined(MESH_RPR) && MESH_RPR + rmt_prov_client_init(); +#endif +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + bt_mesh_multiple_profile_peripheral_adv_timer = plt_timer_create("bt_mesh_multiple_profile_peripheral_adv_timer", 0xFFFFFFFF, FALSE, NULL, bt_mesh_multiple_profile_peripheral_adv_timer_handler); + if (!bt_mesh_multiple_profile_peripheral_adv_timer) { + printf("[BT Mesh Provisioner] Create adv timer failed\n\r"); + } +#endif + + compo_data_page0_header_t compo_data_page0_header = {COMPANY_ID, PRODUCT_ID, VERSION_ID}; + compo_data_page0_gen(&compo_data_page0_header); + + /** init mesh stack */ + mesh_init(); + + /** register udb/provision adv/proxy adv callback */ +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + device_info_cb_reg(bt_mesh_example_device_info_cb); + hb_init(hb_cb); + generic_on_off_client_subscribe(); +#else + device_info_cb_reg(device_info_cb); + hb_init(hb_cb); +#endif +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_le_gap_init(void) +{ + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + uint16_t scan_window = 0x100; /* 160ms */ + uint16_t scan_interval = 0x120; /* 180ms */ + + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_INTERWAVE_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_WINDOW, &scan_window, sizeof(scan_window)); + gap_sched_params_set(GAP_SCHED_PARAMS_SCAN_INTERVAL, &scan_interval, sizeof(scan_interval)); + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_PERIPHERAL"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_mtu_req = false; + + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_mtu_req), + &slave_init_mtu_req); +#if 1 + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, array_count_of_adv_data, (void *)adv_data); + // le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); +#endif + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + } +#endif + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_CENTRAL_CLIENT"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Scan parameters */ + //uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + //uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + //uint16_t scan_window = DEFAULT_SCAN_WINDOW; + //uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + //uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); +#if 0 + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + +#if 1 + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); +#endif +#if F_BT_LE_USE_STATIC_RANDOM_ADDR + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (ble_central_app_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + ble_central_app_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + //le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer +#if 0 + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#endif +#endif + } +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + { + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_SCATTERNET"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MAX; + + /* Scan parameters */ + //uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + //uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + //uint16_t scan_window = DEFAULT_SCAN_WINDOW; + //uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + //uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, array_count_of_adv_data, (void *)adv_data); + // le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + +#if 0 + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + +#if F_BT_LE_USE_STATIC_RANDOM_ADDR + T_APP_STATIC_RANDOM_ADDR random_addr; + bool gen_addr = true; + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + if (ble_scatternet_app_load_static_random_address(&random_addr) == 0) + { + if (random_addr.is_exist == true) + { + gen_addr = false; + } + } + if (gen_addr) + { + if (le_gen_rand_addr(GAP_RAND_ADDR_STATIC, random_addr.bd_addr) == GAP_CAUSE_SUCCESS) + { + random_addr.is_exist = true; + ble_scatternet_app_save_static_random_address(&random_addr); + } + } + le_cfg_local_identity_address(random_addr.bd_addr, GAP_IDENT_ADDR_RAND); + le_set_gap_param(GAP_PARAM_RANDOM_ADDR, 6, random_addr.bd_addr); + //only for peripheral,broadcaster + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + //only for central,observer +#if 0 + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); +#endif +#endif +#if F_BT_GAPS_CHAR_WRITEABLE + uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; + uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; + T_LOCAL_APPEARANCE appearance_local; + T_LOCAL_NAME local_device_name; + if (flash_load_local_appearance(&appearance_local) == 0) + { + gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance); + } + + if (flash_load_local_name(&local_device_name) == 0) + { + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name); + } + gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop); + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop); + gatt_register_callback((void*)bt_mesh_scatternet_gap_service_callback); +#endif + } +#endif + + vendor_cmd_init(bt_mesh_provisioner_multiple_profile_app_vendor_callback); + /* register gap message callback */ + le_register_app_cb(bt_mesh_provisioner_multiple_profile_app_gap_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_le_profile_init(void) +{ + server_init(MESH_GATT_SERVER_COUNT + 2); + /* Add Server Module */ + + /* Register Server Callback */ + server_register_app_cb(bt_mesh_provisioner_multiple_profile_app_profile_callback); + + client_init(MESH_GATT_CLIENT_COUNT + 1); + /* Add Client Module */ + prov_client_add(bt_mesh_provisioner_multiple_profile_app_client_callback); + proxy_client_add(bt_mesh_provisioner_multiple_profile_app_client_callback); + + /* Register Client Callback--App_ClientCallback to handle events from Profile Client layer. */ + client_register_general_client_cb(bt_mesh_provisioner_multiple_profile_app_client_callback); + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + bt_mesh_simp_srv_id = simp_ble_service_add_service((void *)bt_mesh_provisioner_multiple_profile_app_profile_callback); + bt_mesh_bas_srv_id = bas_add_service((void *)bt_mesh_provisioner_multiple_profile_app_profile_callback); +#endif +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + bt_mesh_central_gcs_client_id = gcs_add_client(bt_mesh_central_gcs_client_callback, BLE_CENTRAL_APP_MAX_LINKS, BLE_CENTRAL_APP_MAX_DISCOV_TABLE_NUM); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + bt_mesh_scatternet_gcs_client_id = gcs_add_client(bt_mesh_scatternet_gcs_client_callback, BLE_SCATTERNET_APP_MAX_LINKS, BLE_SCATTERNET_APP_MAX_DISCOV_TABLE_NUM); +#endif + +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void bt_mesh_provisioner_multiple_profile_board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void bt_mesh_provisioner_multiple_profile_driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void bt_mesh_provisioner_multiple_profile_pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void bt_mesh_provisioner_multiple_profile_task_init(void) +{ + bt_mesh_provisioner_multiple_profile_app_task_init(); +} + +void bt_mesh_provisioner_multiple_profile_task_deinit(void) +{ + bt_mesh_provisioner_multiple_profile_app_task_deinit(); +} + +void bt_mesh_provisioner_multiple_profile_stack_config_init(void) +{ +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + gap_config_max_le_link_num(BLE_CENTRAL_APP_MAX_LINKS); + gap_config_max_le_paired_device(BLE_CENTRAL_APP_MAX_LINKS); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + gap_config_max_le_link_num(BLE_SCATTERNET_APP_MAX_LINKS); + gap_config_max_le_paired_device(BLE_SCATTERNET_APP_MAX_LINKS); +#else + gap_config_max_le_link_num(APP_MAX_LINKS); + gap_config_max_le_paired_device(APP_MAX_LINKS); +#endif +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_mesh_provisioner_multiple_profile_app_main(void) +{ + bt_trace_init(); +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + bt_mesh_provisioner_multiple_profile_stack_config_init(); +#endif + bte_init(); + bt_mesh_provisioner_multiple_profile_board_init(); + bt_mesh_provisioner_multiple_profile_driver_init(); +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + le_gap_init(BLE_CENTRAL_APP_MAX_LINKS); +#elif defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + le_gap_init(APP_MAX_LINKS); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + le_gap_init(BLE_SCATTERNET_APP_MAX_LINKS); +#else + le_gap_init(APP_MAX_LINKS); +#endif + bt_mesh_provisioner_multiple_profile_app_le_gap_init(); + bt_mesh_provisioner_multiple_profile_app_le_profile_init(); + bt_mesh_provisioner_multiple_profile_stack_init(); + bt_mesh_provisioner_multiple_profile_pwr_mgr_init(); + bt_mesh_provisioner_multiple_profile_task_init(); + + return 0; +} + +int bt_mesh_provisioner_multiple_profile_app_init(void) +{ + int bt_stack_already_on = 0; + T_GAP_DEV_STATE new_state; + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + bt_stack_already_on = 1; + printf("[BT Mesh Provisioner]BT Stack already on\n\r"); + return 0; + } + else + bt_mesh_provisioner_multiple_profile_app_main(); + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + if (bt_stack_already_on) { + uint8_t bt_addr[6]; + uint8_t net_key[16] = MESH_NET_KEY; + uint8_t net_key1[16] = MESH_NET_KEY1; + uint8_t app_key[16] = MESH_APP_KEY; + uint8_t app_key1[16] = MESH_APP_KEY1; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /** configure provisioner */ + mesh_node.node_state = PROV_NODE; + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + memcpy(&net_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&net_key1[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key1[10], bt_addr, sizeof(bt_addr)); + uint16_t net_key_index = net_key_add(0, net_key); + app_key_add(net_key_index, 0, app_key); + uint8_t net_key_index1 = net_key_add(1, net_key1); + app_key_add(net_key_index1, 1, app_key1); + mesh_model_bind_all_key(); + } + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_provisioner_api_init()) { + printf("[BT Mesh Provisioner] bt_mesh_provisioner_api_init fail ! \n\r"); + return 1; + } +#endif + + return 0; +} + +extern void mesh_deinit(void); +extern bool mesh_initial_state; +extern bool bt_trace_uninit(void); +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +extern void gcs_delete_client(void); +#endif + +extern T_GAP_DEV_STATE bt_mesh_provisioner_multiple_profile_gap_dev_state; + +void bt_mesh_provisioner_multiple_profile_app_deinit(void) +{ + T_GAP_DEV_STATE new_state; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + bt_mesh_provisioner_api_deinit(); +#endif + bt_mesh_provisioner_multiple_profile_task_deinit(); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Provisioner] BT Stack is not running\n\r"); + mesh_initial_state = FALSE; + bt_mesh_provisioner_multiple_profile_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; + return; + } +#if F_BT_DEINIT + else { +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + gcs_delete_client(); +#endif + bte_deinit(); + printf("[BT Mesh Provisioner] BT Stack deinitalized\n\r"); + } +#endif + mesh_deinit(); + bt_trace_uninit(); + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + plt_timer_delete(bt_mesh_multiple_profile_peripheral_adv_timer, 0xFFFFFFFF); + bt_mesh_multiple_profile_peripheral_adv_timer = NULL; +#endif + mesh_initial_state = FALSE; + bt_mesh_provisioner_multiple_profile_gap_dev_state.gap_init_state = GAP_INIT_STATE_INIT; +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.c new file mode 100644 index 00000000..556c3603 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.c @@ -0,0 +1,246 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif + +#include "mesh_api.h" +#include "provisioner_multiple_profile_app.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "provisioner_cmd.h" +#include "platform_opts.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#endif +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#include "ble_scatternet_user_cmd.h" +#endif +/*============================================================================* + * Macros + *============================================================================*/ +#define EVENT_MESH 0x80 +#define APP_TASK_PRIORITY 4 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 10 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x40 //!< IO message queue size +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#else +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE + MESH_INNER_MSG_NUM) //!< Event message queue size +#endif + +#if defined(CONFIG_PLATFORM_8721D) +#define UART_TX _PA_18 +#define UART_RX _PA_19 +#elif defined(CONFIG_PLATFORM_8710C) +#include "serial_api.h" +#define UART_TX PA_14 +#define UART_RX PA_13 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_mesh_provisioner_multiple_profile_app_task_handle; //!< APP Task handle +void *bt_mesh_provisioner_multiple_profile_evt_queue_handle; //!< Event queue handle +void *bt_mesh_provisioner_multiple_profile_io_queue_handle; //!< IO queue handle +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +void *bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle; //!< user cmd queue handle +#endif + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_mesh_provisioner_multiple_profile_app_main_task(void *p_param); + +void app_send_uart_msg(uint8_t data) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG msg; + msg.type = IO_MSG_TYPE_UART; + msg.subtype = data; + if (os_msg_send(bt_mesh_provisioner_multiple_profile_io_queue_handle, &msg, 0) == false) + { + } + else if (os_msg_send(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0) == false) + { + } +} + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern CMD_MOD_INFO_S btMeshCmdPriv; +int bt_mesh_send_io_msg(T_IO_MSG *p_io_msg) +{ + uint8_t event = EVENT_USER_API_REQ; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + PUSER_ITEM puserItem = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)p_io_msg->u.buf; + puserItem = (PUSER_ITEM)pmeshCmdItem_s->pmeshCmdItem->userData; + //trace commands transmitted to mesh stack + btMeshCmdPriv.cmdTransmittedNum ++; + if (os_msg_send(bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle, p_io_msg, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle fail!\r\n"); + return 1; + } + else if (os_msg_send(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0) == false) + { + pmeshCmdItem_s->msgRecvFlag = 1; + if (btMeshCmdPriv.cmdTransmittedNum) { + btMeshCmdPriv.cmdTransmittedNum --; + } + printf("[BT_MESH] Send io_msg to bt_mesh_provisioner_multiple_profile_evt_queue_handle fail!\r\n"); + return 1; + } + + return 0; +} +#endif + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_task_init() +{ + os_task_create(&bt_mesh_provisioner_multiple_profile_app_task_handle, "bt_mesh_provisioner_multiple_profile_app", bt_mesh_provisioner_multiple_profile_app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_main_task(void *p_param) +{ + /* avoid gcc compile warning */ + (void)p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_mesh_provisioner_multiple_profile_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_mesh_provisioner_multiple_profile_evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + os_msg_queue_create(&bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); +#endif + gap_start_bt_stack(bt_mesh_provisioner_multiple_profile_evt_queue_handle, bt_mesh_provisioner_multiple_profile_io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + mesh_start(EVENT_MESH, EVENT_IO_TO_APP, bt_mesh_provisioner_multiple_profile_evt_queue_handle, bt_mesh_provisioner_multiple_profile_io_queue_handle); + + mesh_data_uart_init(UART_TX, UART_RX, app_send_uart_msg); + mesh_user_cmd_init("MeshProvisioner"); + + while (true) + { + if (os_msg_recv(bt_mesh_provisioner_multiple_profile_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_multiple_profile_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_provisioner_multiple_profile_app_handle_io_msg(io_msg); + } + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + else if (event == EVENT_USER_API_REQ) { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_io_msg_handler(io_msg); + } + } +#endif +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + else if (event == EVENT_USER_HTTP_SERVER) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_mesh_provisioner_multiple_profile_io_queue_handle, &io_msg, 0) == true) + { + bt_mesh_demo_io_msg_handler(io_msg); + } + } +#endif + else if (event == EVENT_MESH) + { + mesh_inner_msg_handle(event); + } + else + { + gap_handle_msg(event); + } + + } + } +} + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +extern int bt_mesh_scatternet_peripheral_app_max_links; +extern int bt_mesh_scatternet_central_app_max_links; +#endif +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_task_deinit(void) +{ + if (bt_mesh_provisioner_multiple_profile_app_task_handle) { + os_task_delete(bt_mesh_provisioner_multiple_profile_app_task_handle); + } + if (bt_mesh_provisioner_multiple_profile_io_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_multiple_profile_io_queue_handle); + } + if (bt_mesh_provisioner_multiple_profile_evt_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_multiple_profile_evt_queue_handle); + } +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle) { + os_msg_queue_delete(bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle); + } + bt_mesh_provisioner_multiple_profile_user_cmd_io_queue_handle = NULL; +#endif + bt_mesh_provisioner_multiple_profile_io_queue_handle = NULL; + bt_mesh_provisioner_multiple_profile_evt_queue_handle = NULL; + bt_mesh_provisioner_multiple_profile_app_task_handle = NULL; +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + bt_mesh_scatternet_central_app_max_links = 0; + bt_mesh_scatternet_peripheral_app_max_links = 0; +#endif + mesh_user_cmd_deinit("MeshProvisioner"); +} + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.h new file mode 100644 index 00000000..6ae32f8b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.h @@ -0,0 +1,27 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2013 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _BT_MESH_PROVISIONER_MULTIPLE_PROFILE_APP_TASK_H_ +#define _BT_MESH_PROVISIONER_MULTIPLE_PROFILE_APP_TASK_H_ + +#include "mesh_config.h" + +/** + * @brief Initialize App task + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_task_init(void); + +/** + * @brief Deinitialize App task + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.c new file mode 100644 index 00000000..8e402475 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.c @@ -0,0 +1,2838 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.c +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_PLATFORM_8721D) +#include "ameba_soc.h" +#endif +#include "provisioner_multiple_profile_app.h" +#include "trace_app.h" +#include "gap_wrapper.h" +#include "mesh_api.h" +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_cmd.h" +#include "ping_app.h" +#include "provisioner_cmd.h" +#include "provision_provisioner.h" +#include "provision_client.h" +#include "proxy_client.h" +#include "bt_flags.h" +#include "platform_opts.h" +#include "vendor_cmd.h" +#include "vendor_cmd_bt.h" + +#if defined(MESH_DFU) && MESH_DFU +#include "dfu_distributor_app.h" +#endif + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_user_api.h" +#include "bt_mesh_provisioner_api.h" +#endif + +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL +#include +#include +#include +#include "platform_stdlib.h" +#include "ble_peripheral_at_cmd.h" +#include +#include +#include +#endif + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +#include +#include "ble_central_at_cmd.h" +#include +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#include "platform_stdlib.h" +#include +#include +#include "gatt_builtin_services.h" +#include "ble_central_at_cmd.h" +#include "ble_peripheral_at_cmd.h" +#include +#include +#include +#include +#endif + +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +T_CLIENT_ID bt_mesh_central_gcs_client_id; /**< General Common Services client client id*/ +#endif +int bt_mesh_multiple_profile_scan_state = 0; +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +int bt_mesh_scatternet_peripheral_app_max_links = 0; +int bt_mesh_scatternet_central_app_max_links = 0; +T_CLIENT_ID bt_mesh_scatternet_gcs_client_id; /**< General Common Services client client id*/ +#endif + +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO +#include "bt_mesh_app_lib_intf.h" +extern struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; +#endif + +bool prov_manual; +uint32_t prov_start_time; +prov_auth_value_type_t prov_auth_value_type; + +#if ((!defined(CONFIG_BT_MESH_CENTRAL) || !CONFIG_BT_MESH_CENTRAL) && \ + (!defined(CONFIG_BT_MESH_SCATTERNET) || !CONFIG_BT_MESH_SCATTERNET)) +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +const uint8_t adv_data[] = +{ + /* Flags */ + 0x02, /* length */ + GAP_ADTYPE_FLAGS, /* type="Flags" */ + GAP_ADTYPE_FLAGS_LIMITED | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + /* Service */ + 0x03, /* length */ + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + /* Local name */ + 0x0F, /* length */ + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'L', 'E', '_', 'P', 'E', 'R', 'I', 'P', 'H', 'E', 'R', 'A', 'L', +}; +int array_count_of_adv_data = sizeof(adv_data) / sizeof(adv_data[0]); +T_SERVER_ID bt_mesh_simp_srv_id; /**< Simple ble service id*/ +T_SERVER_ID bt_mesh_bas_srv_id; /**< Battery service id */ +#endif + +T_GAP_DEV_STATE bt_mesh_provisioner_multiple_profile_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +T_APP_LINK bt_mesh_multiple_profile_app_link_table[BLE_CENTRAL_APP_MAX_LINKS]; +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +T_APP_LINK bt_mesh_multiple_profile_app_link_table[BLE_SCATTERNET_APP_MAX_LINKS]; +#else +T_APP_LINK bt_mesh_multiple_profile_app_link_table[APP_MAX_LINKS]; +#endif + +void bt_mesh_provisioner_multiple_profile_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +#if defined(MESH_DFU) && MESH_DFU +extern void dfu_dist_handle_timeout(void); +#endif + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) +extern uint8_t le_adv_start_enable; +extern void mesh_le_adv_start(void); +extern void mesh_le_adv_stop(void); +#endif + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_mesh_provisioner_multiple_profile_app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + { + /* We handle user command informations from Data UART in this branch. */ + uint8_t data = io_msg.subtype; + mesh_user_cmd_collect(&data, sizeof(data), provisioner_cmd_table); + } + break; + case PING_TIMEOUT_MSG: + { + ping_handle_timeout(); + } + break; + case PING_APP_TIMEOUT_MSG: + { + ping_app_handle_timeout(); + } + break; + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (ble_central_app_handle_at_cmd(subtype, arg) != 1) { + ble_peripheral_app_handle_at_cmd(subtype, arg); + } +#elif defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + ble_central_app_handle_at_cmd(subtype, arg); +#elif defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + ble_peripheral_app_handle_at_cmd(subtype, arg); +#endif + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 2) { + gap_sched_scan(false); + } else if (io_msg.subtype == 3) { + gap_sched_scan(true); + } + } + break; +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined (CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + case IO_MSG_TYPE_ADV: + { + if (le_adv_start_enable) { + uint8_t *padv_data = gap_sched_task_get(); + + if (NULL == padv_data) + { + printf("[BT Mesh Provisioner] bt_mesh_multiple_profile_peripheral_adv_timer_handler allocate padv_data fail ! \n\r"); + break; + } + + gap_sched_task_p ptask = CONTAINER_OF(padv_data, gap_sched_task_t, adv_data); + + memcpy(padv_data, (uint8_t *)adv_data, sizeof(adv_data)); + + ptask->adv_len += 23; + ptask->adv_type = GAP_SCHED_ADV_TYPE_IND; + + gap_sched_try(ptask); + } + } + break; +#endif +#if defined(MESH_DFU) && MESH_DFU + case DFU_DIST_APP_TIMEOUT_MSG: + dfu_dist_handle_timeout(); + break; +#endif + default: + break; + } +} + +#if defined (GAP_SCHED_TASK_GUARD) && GAP_SCHED_TASK_GUARD +void gap_sched_task_guard_func(void) +{ + printf("gap_sched_task_guard_func enter \r\n"); +} +#endif + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("bt_mesh_provisioner_multiple_profile_app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, cause); + if (bt_mesh_provisioner_multiple_profile_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + uint8_t net_key[16] = MESH_NET_KEY; + uint8_t net_key1[16] = MESH_NET_KEY1; + uint8_t app_key[16] = MESH_APP_KEY; + uint8_t app_key1[16] = MESH_APP_KEY1; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_debug("bt addr: 0x%02x%02x%02x%02x%02x%02x\r\n>", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /** configure provisioner */ + mesh_node.node_state = PROV_NODE; + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + memcpy(&net_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&net_key1[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key[10], bt_addr, sizeof(bt_addr)); + memcpy(&app_key1[10], bt_addr, sizeof(bt_addr)); + uint16_t net_key_index = net_key_add(0, net_key); + app_key_add(net_key_index, 0, app_key); + uint8_t net_key_index1 = net_key_add(1, net_key1); + app_key_add(net_key_index1, 1, app_key1); + mesh_model_bind_all_key(); +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + /*stack ready*/ + mesh_le_adv_start(); +#endif +#if defined (GAP_SCHED_TASK_GUARD) && GAP_SCHED_TASK_GUARD + gap_sched_task_guard_set(gap_sched_task_guard_func, 0); +#endif + } + } + +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + if (bt_mesh_provisioner_multiple_profile_gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + printf("\n\rGAP adv stoped: because connection created\n\r"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + printf("\n\rGAP adv stopped\n\r"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + printf("\n\rGAP adv start\n\r"); + } + } +#endif + + if (bt_mesh_provisioner_multiple_profile_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + //data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + //data_uart_print("GAP scan start\r\n"); + } + } + + bt_mesh_provisioner_multiple_profile_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + T_GAP_CONN_INFO conn_info; +#endif +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + if (conn_id >= BLE_CENTRAL_APP_MAX_LINKS) + { + return; + } +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (conn_id >= BLE_SCATTERNET_APP_MAX_LINKS) + { + return; + } +#else + if (conn_id >= APP_MAX_LINKS) + { + return; + } +#endif + + APP_PRINT_INFO4("bt_mesh_provisioner_multiple_profile_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, bt_mesh_multiple_profile_app_link_table[conn_id].conn_state, new_state, disc_cause); + + bt_mesh_multiple_profile_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_mesh_provisioner_multiple_profile_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + + data_uart_debug("Disconnect conn_id %d\r\n", conn_id); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + uint8_t ret = USER_API_RESULT_ERROR; + ret = bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + goto next; + } + } else { + goto next; + } + ret = bt_mesh_indication(GEN_MESH_CODE(_disconnect), BT_MESH_USER_CMD_FAIL, NULL); + if (ret != USER_API_RESULT_OK) { + if (ret != USER_API_RESULT_INCORRECT_CODE) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_disconnect)); + goto next; + } + } else { + goto next; + } +#endif +next: +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + mesh_le_adv_start(); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + /*stack ready*/ + mesh_le_adv_start(); + } +#endif + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) { + bt_mesh_scatternet_central_app_max_links --; + } else if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + bt_mesh_scatternet_peripheral_app_max_links --; + } +#endif + memset(&bt_mesh_multiple_profile_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, bt_mesh_multiple_profile_app_link_table[conn_id].bd_addr, + &bt_mesh_multiple_profile_app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(bt_mesh_multiple_profile_app_link_table[conn_id].bd_addr), bt_mesh_multiple_profile_app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_debug("Connected success conn_id %d\r\n", conn_id); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_connect), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_connect)); + } +#endif +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + //get device role + if (le_get_conn_info(conn_id, &conn_info)){ + bt_mesh_multiple_profile_app_link_table[conn_id].role = conn_info.role; + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_MASTER) + bt_mesh_scatternet_central_app_max_links ++; + else if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) + bt_mesh_scatternet_peripheral_app_max_links ++; + } + + ////print bt address type + uint8_t local_bd_type; + //uint8_t features[8]; + uint8_t remote_bd_type; + le_get_conn_param(GAP_PARAM_CONN_LOCAL_BD_TYPE, &local_bd_type, conn_id); + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR_TYPE, &remote_bd_type, conn_id); + APP_PRINT_INFO3("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); + data_uart_debug("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d\n", + conn_id, local_bd_type, remote_bd_type); +#endif + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, 251, 2120); +#endif +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL + mesh_le_adv_stop(); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + if (bt_mesh_multiple_profile_app_link_table[conn_id].role == GAP_LINK_ROLE_SLAVE) { + mesh_le_adv_stop(); + } +#endif + } + break; + + default: + break; + + } + +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_debug("Pair success\r\n"); + APP_PRINT_INFO0("bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_debug("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_mesh_provisioner_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_debug("\n\rbt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x \r\n", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + data_uart_debug("\n\rbt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x\r\n", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + data_uart_debug("\n\rbt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt update pending: conn_id %d\r\n", conn_id); + } + break; + + default: + break; + } +} + +bool mesh_initial_state = FALSE; + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * sub_type of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_mesh_provisioner_multiple_profile_app_handle_gap_msg: sub_type %d", p_gap_msg->subtype); + mesh_inner_msg_t mesh_inner_msg; + mesh_inner_msg.type = MESH_BT_STATUS_UPDATE; + mesh_inner_msg.sub_type = p_gap_msg->subtype; + mesh_inner_msg.parm = p_gap_msg->u.param; + gap_sched_handle_bt_status_msg(&mesh_inner_msg); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + //static bool start = FALSE; + if (!mesh_initial_state) + { + mesh_initial_state = TRUE; + /** set device uuid according to bt address */ + uint8_t bt_addr[6]; + uint8_t dev_uuid[16] = MESH_DEVICE_UUID; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + memcpy(dev_uuid, bt_addr, sizeof(bt_addr)); + device_uuid_set(dev_uuid); + /** configure provisioner */ + mesh_node.unicast_addr = bt_addr[0] % 99 + 1; + } + bt_mesh_provisioner_multiple_profile_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_mesh_provisioner_multiple_profile_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_mesh_provisioner_multiple_profile_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_mesh_provisioner_multiple_profile_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_mesh_provisioner_multiple_profile_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_debug("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_app_handle_gap_msg: unknown sub_type %d", p_gap_msg->subtype); + break; + } +} + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void bt_mesh_central_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("ble_central_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_central_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, + *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, + data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", + *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); +// BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +/** @} */ /* End of group CENTRAL_CLIENT_GAP_MSG */ + +/** @defgroup CENTRAL_CLIENT_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void bt_mesh_scatternet_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("ble_scatternet_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_scatternet_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, + *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, + data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", + *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); +// BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} +#endif + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_multiple_profile_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + char adv_type[20]; + char remote_addr_type[10]; +#endif + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, tx octets 0x%x, max_tx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time); + break; +#endif + + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO1("GAP_MSG_LE_BOND_MODIFY_INFO: type 0x%x", + p_data->p_le_bond_modify_info->type); + break; + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + /* central reference msg*/ + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); +#if ((defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + if (bt_mesh_multiple_profile_scan_state) { + /* If you want to parse the scan info, please reference function ble_central_app_parse_scan_info. */ + sprintf(adv_type,"%s",(p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_UNDIRECTED)? "CON_UNDIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_DIRECTED)? "CON_DIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCANNABLE)? "SCANABLE_UNDIRCT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_NON_CONNECTABLE)? "NON_CONNECTABLE": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCAN_RSP)? "SCAN_RSP":"unknown"); + sprintf(remote_addr_type,"%s",(p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_PUBLIC)? "public": + (p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_RANDOM)? "random":"unknown"); + + BLE_PRINT("ADVType\t\t\t| AddrType\t|%s\t\t\t|rssi\n\r","BT_Addr"); + BLE_PRINT("%s\t\t%s\t"BD_ADDR_FMT"\t%d\n\r",adv_type,remote_addr_type,BD_ADDR_ARG(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->rssi); +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL + bt_mesh_central_app_parse_scan_info(p_data->p_le_scan_info); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET + bt_mesh_scatternet_app_parse_scan_info(p_data->p_le_scan_info); +#endif + } +#endif + gap_sched_handle_adv_report(p_data->p_le_scan_info); + break; + +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif + /* peripheral reference msg*/ + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + gap_sched_adv_params_set_done(); + break; + /* + case GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ONE_SHOT_ADV: cause 0x%x", + p_data->le_cause.cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + break; + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; + + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; + */ +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + data_uart_print("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d\r\n", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif + default: + APP_PRINT_ERROR1("bt_mesh_provisioner_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#if F_BT_GAPS_CHAR_WRITEABLE +/** @defgroup SCATTERNET_GAPS_WRITE GAP Service Callback Handler + * @brief Use @ref F_BT_GAPS_CHAR_WRITEABLE to open + * @{ + */ +/** + * @brief All the BT GAP service callback events are handled in this function + * @param[in] service_id Profile service ID + * @param[in] p_para Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_scatternet_gap_service_callback(T_SERVER_ID service_id, void *p_para) +{ + (void) service_id; + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; + APP_PRINT_INFO2("bt_mesh_scatternet_gap_service_callback: conn_id = %d msg_type = %d\n", p_gap_data->conn_id, + p_gap_data->msg_type); + APP_PRINT_INFO2("bt_mesh_scatternet_gap_service_callback: len = 0x%x,opcode = %d\n", p_gap_data->msg_data.len, + p_gap_data->msg_data.opcode); + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) + { + switch (p_gap_data->msg_data.opcode) + { + case GAPS_WRITE_DEVICE_NAME: + { + T_LOCAL_NAME device_name; + memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); + device_name.local_name[p_gap_data->msg_data.len] = 0; + //data_uart_print("GAPS_WRITE_DEVICE_NAME:device_name = %s \n\r",device_name.local_name); + flash_save_local_name(&device_name); + } + break; + + case GAPS_WRITE_APPEARANCE: + { + uint16_t appearance_val; + T_LOCAL_APPEARANCE appearance; + + LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); + appearance.local_appearance = appearance_val; + //data_uart_print("GAPS_WRITE_APPEARANCE:appearance = %s \n\r",appearance.local_appearance); + flash_save_local_appearance(&appearance); + } + break; + default: + APP_PRINT_ERROR1("bt_mesh_scatternet_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + //data_uart_print("bt_mesh_scatternet_gap_service_callback: unhandled msg_data.opcode 0x%x", p_gap_data->msg_data.opcode); + break; + } + } + return result; +} +/** @} */ +#endif + +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void bt_mesh_scatternet_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + data_uart_debug("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + data_uart_debug("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + data_uart_debug("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + data_uart_debug("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + data_uart_debug("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + data_uart_debug("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + data_uart_debug("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + data_uart_debug("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + data_uart_debug("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + data_uart_debug("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + data_uart_debug("Invalid disc type: conn_id %d, discov_type %d\n\r", + conn_id, discov_result.discov_type); + break; + } +} + +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_scatternet_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_scatternet_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_mesh_scatternet_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_mesh_scatternet_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_debug("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\n\r", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_debug("READ VALUE: "); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_debug("\n\r"); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_debug("WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("INDICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("INDICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("NOTIFICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + + } + break; + default: + break; + } + } + + return result; +} +#endif +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_multiple_profile_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_mesh_provisioner_multiple_profile_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + else if (client_id == prov_client_id) + { + prov_client_cb_data_t *pcb_data = (prov_client_cb_data_t *)p_data; + switch (pcb_data->cb_type) + { + case PROV_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case PROV_DISC_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + data_uart_debug("Prov service discovery end!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + case PROV_DISC_FAIL: + /* Discovery Request failed. */ + data_uart_debug("Prov service discovery fail!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + case PROV_DISC_NOT_FOUND: + /* Discovery Request failed. */ + data_uart_debug("Prov service not found!\r\n"); +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov_discover), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov_discover)); + } +#endif + break; + default: + break; + } + break; + case PROV_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case PROV_READ_DATA_OUT_CCCD: + if (pcb_data->cb_content.read_result.cause == 0) + { + data_uart_debug("Prov data out cccd = %d.\r\n", + pcb_data->cb_content.read_result.data.prov_data_out_cccd); + } + break; + default: + break; + } + break; + case PROV_CLIENT_CB_TYPE_WRITE_RESULT: + break; + default: + break; + } + } + else if (client_id == proxy_client_id) + { + proxy_client_cb_data_t *pcb_data = (proxy_client_cb_data_t *)p_data; + switch (pcb_data->cb_type) + { + case PROXY_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case PROXY_DISC_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + data_uart_debug("Proxy service discovery end!\r\n"); + break; + case PROXY_DISC_FAIL: + /* Discovery Request failed. */ + data_uart_debug("Proxy service discovery fail!\r\n"); + break; + case PROXY_DISC_NOT_FOUND: + /* Discovery Request failed. */ + data_uart_debug("Proxy service not found!\r\n"); + break; + default: + break; + } + break; + case PROXY_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case PROXY_READ_DATA_OUT_CCCD: + if (pcb_data->cb_content.read_result.cause == 0) + { + data_uart_debug("Proxy data out cccd = %d.\r\n", + pcb_data->cb_content.read_result.data.proxy_data_out_cccd); + } + break; + default: + break; + } + break; + case PROXY_CLIENT_CB_TYPE_WRITE_RESULT: + break; + default: + break; + } + } + return result; +} + +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id + * @param service_id Profile service ID + * @param p_data Pointer to callback data + * @return T_APP_RESULT, which indicates the function call is successful or not + * @retval APP_RESULT_SUCCESS Function run successfully + * @retval others Function run failed, and return number indicates the reason + */ +T_APP_RESULT bt_mesh_provisioner_multiple_profile_app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + data_uart_debug("\n\rPROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d\r\n", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE success\r\n"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + data_uart_debug("PROFILE_EVT_SEND_DATA_COMPLETE failed\r\n"); + } + break; + + default: + break; + } + } +#if ((defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET)) + else if (service_id == bt_mesh_simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V3_ENABLE\r\n"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V3_DISABLE\r\n"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V4_ENABLE\r\n"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + data_uart_debug("\n\rSIMP_NOTIFY_INDICATE_V4_DISABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value[2] = {0x01, 0x02}; + APP_PRINT_INFO0("SIMP_READ_V1"); + data_uart_debug("SIMP_READ_V1: value 0x%02x 0x%02x\r\n", value[0], value[1]); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 2, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_debug("SIMP_WRITE_V2: write type %d, len %d\r\n", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + data_uart_debug("SIMP_WRITE_V2: value "); + for(int i = 0; i < p_simp_cb_data->msg_data.write.len; i ++){ + data_uart_debug("0x%02x ", *(p_simp_cb_data->msg_data.write.p_value + i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } + else if (service_id == bt_mesh_bas_srv_id) + { + T_BAS_CALLBACK_DATA *p_bas_cb_data = (T_BAS_CALLBACK_DATA *)p_data; + switch (p_bas_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_bas_cb_data->msg_data.notification_indification_index) + { + case BAS_NOTIFY_BATTERY_LEVEL_ENABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_ENABLE"); + data_uart_debug("\n\rBAS_NOTIFY_BATTERY_LEVEL_ENABLE\r\n"); + } + break; + + case BAS_NOTIFY_BATTERY_LEVEL_DISABLE: + { + APP_PRINT_INFO0("BAS_NOTIFY_BATTERY_LEVEL_DISABLE"); + data_uart_debug("\n\rBAS_NOTIFY_BATTERY_LEVEL_ENABLE\r\n"); + } + break; + default: + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_bas_cb_data->msg_data.read_value_index == BAS_READ_BATTERY_LEVEL) + { + uint8_t battery_level = 90; + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery_level %d", battery_level); + data_uart_debug("\n\rBAS_READ_BATTERY_LEVEL: battery_level %d\r\n", battery_level); + bas_set_parameter(BAS_PARAM_BATTERY_LEVEL, 1, &battery_level); + } + } + break; + + default: + break; + } + } +#endif + + return app_result; +} + +/****************************************************************** + * @fn device_info_cb + * @brief device_info_cb callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return void + */ +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo) +{ + if (!dev_info_show_flag) + { + return; + } + data_uart_debug("bt addr=0x%02x%02x%02x%02x%02x%02x type=%d rssi=%d ", bt_addr[5], bt_addr[4], + bt_addr[3], bt_addr[2], bt_addr[1], bt_addr[0], bt_addr_type, rssi); + switch (pinfo->type) + { + case DEVICE_INFO_UDB: + data_uart_debug("udb="); + data_uart_dump(pinfo->pbeacon_udb->dev_uuid, 16); + break; + case DEVICE_INFO_PROV_ADV: + data_uart_debug("prov="); + data_uart_dump(pinfo->pservice_data->provision.dev_uuid, 16); + break; + case DEVICE_INFO_PROXY_ADV: + data_uart_debug("proxy="); + data_uart_dump((uint8_t *)&pinfo->pservice_data->proxy, pinfo->len); + break; + default: + break; + } +} + +/****************************************************************** + * @fn prov_cb + * @brief Provisioning callbacks are handled in this function. + * + * @param cb_data - @ref prov_cb_data_t + * @return the operation result + */ +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data) +{ + APP_PRINT_INFO1("prov_cb: type = %d", cb_type); + + switch (cb_type) + { + case PROV_CB_TYPE_PB_ADV_LINK_STATE: + switch (cb_data.pb_generic_cb_type) + { + case PB_GENERIC_CB_LINK_OPENED: + data_uart_debug("PB-ADV Link Opened!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_flag = 1; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_pb_adv_con), BT_MESH_USER_CMD_SUCCESS, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_pb_adv_con)); + } +#endif + break; + case PB_GENERIC_CB_LINK_OPEN_FAILED: + data_uart_debug("PB-ADV Link Open Failed!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_flag = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_pb_adv_con), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_pb_adv_con)); + } +#endif + break; + case PB_GENERIC_CB_LINK_CLOSED: + data_uart_debug("PB-ADV Link Closed!\r\n>"); + send_coex_mailbox_to_wifi_from_BtAPP(0); + break; + default: + break; + } + break; + case PROV_CB_TYPE_PATH_CHOOSE: + { + if (prov_manual) + { + /* use cmd "authpath" to select oob/no oob public key and no oob/static oob/input oob/output oob auth data according to the device capabilities */ + prov_capabilities_p pprov_capabilities = cb_data.pprov_capabilities; + data_uart_debug("prov capabilities: en-%d al-%d pk-%d so-%d os-%d oa-%d is-%d ia-%d\r\n", + pprov_capabilities->element_num, pprov_capabilities->algorithm, + pprov_capabilities->public_key, pprov_capabilities->static_oob, + pprov_capabilities->output_oob_size, pprov_capabilities->output_oob_action, + pprov_capabilities->input_oob_size, pprov_capabilities->input_oob_action); + } + else + { + /* select no oob public key and no oob auth data as default provision method */ + prov_start_t prov_start; + memset(&prov_start, 0, sizeof(prov_start_t)); + prov_path_choose(&prov_start); + } + } + break; + case PROV_CB_TYPE_PUBLIC_KEY: + { + APP_PRINT_INFO0("prov_cb: get the public key from the device"); + uint8_t public_key[64] = {0xf4, 0x65, 0xe4, 0x3f, 0xf2, 0x3d, 0x3f, 0x1b, 0x9d, 0xc7, 0xdf, 0xc0, 0x4d, 0xa8, 0x75, 0x81, 0x84, 0xdb, 0xc9, 0x66, 0x20, 0x47, 0x96, 0xec, 0xcf, 0x0d, 0x6c, 0xf5, 0xe1, 0x65, 0x00, 0xcc, 0x02, 0x01, 0xd0, 0x48, 0xbc, 0xbb, 0xd8, 0x99, 0xee, 0xef, 0xc4, 0x24, 0x16, 0x4e, 0x33, 0xc2, 0x01, 0xc2, 0xb0, 0x10, 0xca, 0x6b, 0x4d, 0x43, 0xa8, 0xa1, 0x55, 0xca, 0xd8, 0xec, 0xb2, 0x79}; + prov_device_public_key_set(public_key); + } + break; + case PROV_CB_TYPE_AUTH_DATA: + { + prov_start_p pprov_start = cb_data.pprov_start; + prov_auth_value_type = prov_auth_value_type_get(pprov_start); + /* use cmd to set auth data */ + data_uart_debug("auth method=%d[nsoi] action=%d size=%d type=%d[nbNa]\r\n>", + pprov_start->auth_method, + pprov_start->auth_action, pprov_start->auth_size, prov_auth_value_type); + //uint8_t auth_data[16] = {1}; + switch (pprov_start->auth_method) + { + case PROV_AUTH_METHOD_STATIC_OOB: + //prov_auth_value_set(auth_data, sizeof(auth_data)); + APP_PRINT_INFO0("prov_cb: Please share the oob data with the device"); + break; + case PROV_AUTH_METHOD_OUTPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.output_oob_size); + APP_PRINT_INFO2("prov_cb: Please input the oob data provided by the device, output size = %d, action = %d", + pprov_start->auth_size.output_oob_size, pprov_start->auth_action.output_oob_action); + break; + case PROV_AUTH_METHOD_INPUT_OOB: + //prov_auth_value_set(auth_data, pprov_start->auth_size.input_oob_size); + APP_PRINT_INFO2("prov_cb: Please output the oob data to the device, input size = %d, action = %d", + pprov_start->auth_size.input_oob_size, pprov_start->auth_action.input_oob_action); + break; + default: + break; + } + } + break; + case PROV_CB_TYPE_CONF_CHECK: + { + /* check confirmation value when using OOB */ + uint8_t rand[16] = {0}; + uint8_t confirmation[16] = {0}; + prov_check_conf_t prov_check_conf = cb_data.prov_check_conf; + + memcpy((void *)rand, (void *)prov_check_conf.rand, sizeof(rand)); + memcpy((void *)confirmation, (void *)prov_check_conf.conf, sizeof(confirmation)); + printf("confimation %02x %02x %02x %02x %02x %02x \r\n", confirmation[0], confirmation[1], confirmation[2], confirmation[3], confirmation[4], confirmation[5]); + printf("rand %02x %02x %02x %02x %02x %02x \r\n", rand[0], rand[1], rand[2], rand[3], rand[4], rand[5]); + + /* if confirmation from device is correct invoke prov_send_prov_data() */ + /* if confirmation from device is wrong invoke prov_reject() */ + // if (success) { + // prov_send_prov_data(); + // } else { + // prov_reject(); + // } + } + break; + case PROV_CB_TYPE_COMPLETE: + { + prov_data_p pprov_data = cb_data.pprov_data; + data_uart_debug("Has provisioned device with addr 0x%04x in %dms!\r\n", pprov_data->unicast_address, + plt_time_read_ms() - prov_start_time); + /* the spec requires to disconnect, but you can remove it as you like! :) */ + prov_disconnect(PB_ADV_LINK_CLOSE_SUCCESS); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_mesh_addr = pprov_data->unicast_address; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + printf("\r\n %s() pprov_data->unicast_address = %x",__func__,pprov_data->unicast_address); + if (bt_mesh_indication(GEN_MESH_CODE(_prov), BT_MESH_USER_CMD_SUCCESS, (void *)&pprov_data->unicast_address) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov)); + } +#endif + } + break; + case PROV_CB_TYPE_FAIL: + data_uart_debug("provision fail, type=%d!\r\n", cb_data.prov_fail.fail_type); +#if defined(CONFIG_EXAMPLE_BT_MESH_DEMO) && CONFIG_EXAMPLE_BT_MESH_DEMO + if (bt_mesh_lib_priv.connect_device_sema) { + bt_mesh_lib_priv.connect_device_mesh_addr = 0; + rtw_up_sema(&bt_mesh_lib_priv.connect_device_sema); + } +#endif +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API + if (bt_mesh_indication(GEN_MESH_CODE(_prov), BT_MESH_USER_CMD_FAIL, NULL) != USER_API_RESULT_OK) { + data_uart_debug("[BT_MESH] %s(): user cmd %d fail !\r\n", __func__, GEN_MESH_CODE(_prov)); + } +#endif + + break; + case PROV_CB_TYPE_PROV: + /* stack ready */ + data_uart_debug("ms addr: 0x%04x\r\n>", mesh_node.unicast_addr); + break; + default: + break; + } + return true; +} + +/****************************************************************** + * @fn fn_cb + * @brief fn callbacks are handled in this function. + * + * @param frnd_index + * @param type + * @param fn_addr + * @return void + */ +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr) +{ + /* avoid gcc compile warning */ + (void)frnd_index; + char *string[] = {"establishing with lpn 0x%04x\r\n", "no poll from 0x%04x\r\n", "established with lpn 0x%04x\r\n", "lpn 0x%04x lost\r\n"}; + data_uart_debug(string[type], lpn_addr); + if (type == FN_CB_TYPE_ESTABLISH_SUCCESS || type == FN_CB_TYPE_FRND_LOST) + { + user_cmd_time(NULL); + } +} + +/****************************************************************** + * @fn hb_cb + * @brief heartbeat callbacks are handled in this function. + * + * @param type + * @param pdata + * @return void + */ +void hb_cb(hb_data_type_t type, void *pargs) +{ + switch (type) + { + case HB_DATA_PUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat publish timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat publish timer stop\r\n"); + } + } + break; + case HB_DATA_SUB_TIMER_STATE: + { + hb_data_timer_state_t *pdata = pargs; + if (HB_TIMER_STATE_START == pdata->state) + { + data_uart_debug("heartbeat subscription timer start, period = %d\r\n", pdata->period); + } + else + { + data_uart_debug("heartbeat subscription timer stop\r\n"); + } + } + break; + case HB_DATA_PUB_COUNT_UPDATE: + { + hb_data_pub_count_update_t *pdata = pargs; + data_uart_debug("heartbeat publish count update: %d\r\n", pdata->count); + } + break; + case HB_DATA_SUB_PERIOD_UPDATE: + { + hb_data_sub_period_update_t *pdata = pargs; + data_uart_debug("heartbeat subscription period update: %d\r\n", pdata->period); + } + break; + case HB_DATA_SUB_RECEIVE: + { + hb_data_sub_receive_t *pdata = pargs; + data_uart_debug("receive heartbeat: src = %d, init_ttl = %d, features = %d-%d-%d-%d, ttl = %d\r\n", + pdata->src, pdata->init_ttl, pdata->features.relay, pdata->features.proxy, + pdata->features.frnd, pdata->features.lpn, pdata->ttl); + } + break; + default: + break; + } +} + +void bt_mesh_provisioner_multiple_profile_app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("bt_mesh_provisioner_multiple_profile_app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_INFO1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + gap_sched_adv_done(GAP_SCHED_ADV_END_TYPE_SUCCESS); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void bt_mesh_central_gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + BLE_PRINT("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + BLE_PRINT("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + UUID_128(p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + BLE_PRINT("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + BLE_PRINT("SRV DATA[%d]: service range: 0x%x-0x%x\n\r", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + BLE_PRINT("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + + + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + BLE_PRINT("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + BLE_PRINT("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + BLE_PRINT("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + UUID_128(p_result_table->result_data.char_uuid128_disc_data.uuid128)); + BLE_PRINT("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\n\r", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + BLE_PRINT("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\n\r", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + BLE_PRINT("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>\n\r", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + BLE_PRINT("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128="UUID_128_FORMAT"\n\r", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + UUID_128(p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + BLE_PRINT("Invalid Discovery Result Type!\n\r"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + BLE_PRINT("Invalid disc type: conn_id %d, discov_type %d\n\r", + conn_id, discov_result.discov_type); + break; + } +} + +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_central_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("ble_central_gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == bt_mesh_central_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + bt_mesh_central_gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + data_uart_debug("READ RESULT: cause 0x%x, handle 0x%x, value_len %d\n\r", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + data_uart_debug("READ VALUE: "); + for(int i=0; i< p_gcs_cb_data->cb_content.read_result.value_size; i++) + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.read_result.p_value + i)); + data_uart_debug("\n\r"); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_debug("WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("INDICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("INDICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION: value %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + data_uart_debug("NOTIFICATION: handle 0x%x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + data_uart_debug("NOTIFICATION: value "); + for (int i = 0; i < p_gcs_cb_data->cb_content.notif_ind.value_size; i++) { + data_uart_debug("0x%02x ", *(p_gcs_cb_data->cb_content.notif_ind.p_value+ i)); + } + data_uart_debug("\n\r"); + } + break; + default: + break; + } + } + + return result; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.h new file mode 100644 index 00000000..53d79828 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.h @@ -0,0 +1,125 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file device_app.h +* @brief Smart mesh demo application +* @details +* @author bill +* @date 2015-11-12 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _MESH_APPLICATION__ +#define _MESH_APPLICATION__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mesh_api.h" +#include +#include +#include "app_msg.h" +#include "bt_mesh_provisioner_multiple_profile_app_flags.h" + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_provisioner_api.h" +#endif + +extern bool dev_info_show_flag; +extern bool prov_manual; +extern uint32_t prov_start_time; + +/*============================================================================* + * Variables + *============================================================================*/ +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +extern T_CLIENT_ID bt_mesh_central_gcs_client_id; /**< General Common Services client client id*/ +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] +#endif +#if defined(CONFIG_BT_MESH_PERIPHERAL) && CONFIG_BT_MESH_PERIPHERAL +extern T_SERVER_ID bt_mesh_simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bt_mesh_bas_srv_id; /**< Battery service id */ +extern const uint8_t adv_data[]; +#endif +#if defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] +extern T_SERVER_ID bt_mesh_simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID bt_mesh_bas_srv_id; /**< Battery service id */ +extern const uint8_t adv_data[]; +extern T_CLIENT_ID bt_mesh_scatternet_gcs_client_id; /**< General Common Services client client id*/ +#endif +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_mesh_provisioner_multiple_profile_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_multiple_profile_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_provisioner_multiple_profile_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +T_APP_RESULT bt_mesh_provisioner_multiple_profile_app_profile_callback(T_SERVER_ID service_id, void *p_data); + +#if defined(CONFIG_BT_MESH_CENTRAL) && CONFIG_BT_MESH_CENTRAL +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_central_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#elif defined(CONFIG_BT_MESH_SCATTERNET) && CONFIG_BT_MESH_SCATTERNET +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_mesh_scatternet_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#if F_BT_GAPS_CHAR_WRITEABLE +extern T_APP_RESULT bt_mesh_scatternet_gap_service_callback(T_SERVER_ID service_id, void *p_para); +#endif +#endif + +void device_info_cb(uint8_t bt_addr[6], uint8_t bt_addr_type, int8_t rssi, device_info_t *pinfo); +bool prov_cb(prov_cb_type_t cb_type, prov_cb_data_t cb_data); +void fn_cb(uint8_t frnd_index, fn_cb_type_t type, uint16_t lpn_addr); +void lpn_cb(uint8_t frnd_index, lpn_cb_type_t type, uint16_t fn_addr); +void hb_cb(hb_data_type_t type, void *pargs); +void bt_mesh_provisioner_multiple_profile_app_vendor_callback(uint8_t cb_type, void *p_cb_data); +#ifdef __cplusplus +} +#endif + +#endif /* _MESH_APPLICATION__S */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.c new file mode 100644 index 00000000..2e19f1da --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.c @@ -0,0 +1,809 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file provisioner_cmd.c + * @brief Source file for provisioner cmd. + * @details User command interfaces. + * @author bill + * @date 2017-3-31 + * @version v1.0 + * ************************************************************************************* + */ + +#include +#include "trace.h" +#include "gap_wrapper.h" +#include "provisioner_cmd.h" +#include "provisioner_app.h" +#include "provision_client.h" +#include "provision_provisioner.h" +#include "mesh_api.h" +#include "mesh_cmd.h" +#include "test_cmd.h" +#include "client_cmd.h" +#include "generic_client_app.h" +#include "datatrans_model.h" +#include "datatrans_app.h" +#include "remote_provisioning.h" + +static user_cmd_parse_result_t user_cmd_prov_discover(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("Prov Start Discover\r\n"); + prov_client_conn_id = pparse_value->dw_parameter[0]; + prov_client_start_discovery(prov_client_conn_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_read_char(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char to be read. */ + prov_read_type_t read_char_type = (prov_read_type_t)pparse_value->dw_parameter[0]; + /* Read by handle or UUID, 1--by UUID, 0--by handle. */ + uint8_t read_pattern = (uint8_t)pparse_value->dw_parameter[1]; + data_uart_debug("Pro Read Char\r\n"); + if (read_pattern) + { + prov_client_read_by_uuid(prov_client_conn_id, read_char_type); + } + else + { + prov_client_read_by_handle(prov_client_conn_id, read_char_type); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_cccd_operate(user_cmd_parse_value_t *pparse_value) +{ + /* Indicate which char CCCD command. */ + uint8_t cmd_type = (uint8_t)pparse_value->dw_parameter[0]; + /* Enable or disable, 1--enable, 0--disable. */ + bool cmd_data = (bool)pparse_value->dw_parameter[1]; + data_uart_debug("Prov Cccd Operate\r\n"); + switch (cmd_type) + { + case 0:/* V3 Notify char notif enable/disable. */ + { + prov_client_data_out_cccd_set(prov_client_conn_id, cmd_data); + proxy_ctx_set_link(prov_proxy_ctx_id, prov_client_conn_id); + } + break; + default: + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_prov_list(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Prov Server Handle List:\r\nidx\thandle\r\n"); + for (prov_handle_type_t hdl_idx = HDL_PROV_SRV_START; hdl_idx < HDL_PROV_CACHE_LEN; hdl_idx++) + { + data_uart_debug("%d\t0x%x\r\n", hdl_idx, prov_client_handle_get(prov_client_conn_id, hdl_idx)); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_pb_adv_con(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + + send_coex_mailbox_to_wifi_from_BtAPP(1); + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[0], sizeof(dev_uuid)); + if (!pb_adv_link_open(0, dev_uuid)) + { + data_uart_debug("PB_ADV: Link Busy!\r\n"); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_pb_adv_disc(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + if (pb_adv_link_close(0, PB_ADV_LINK_CLOSE_SUCCESS)) + { + data_uart_debug("PB_ADV: Link Closed!\r\n"); + } + else + { + data_uart_debug("PB_ADV: Link Closed Already!\r\n"); + } + return USER_CMD_RESULT_OK; +} + +#if defined(MESH_RPR) && MESH_RPR +static user_cmd_parse_result_t user_cmd_rmt_prov_client_scan_start(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t scanned_items_limit = pparse_value->dw_parameter[2]; + uint8_t scan_timeout = pparse_value->dw_parameter[3]; + uint8_t ret = 0; + + if (pparse_value->para_count == 5) { + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[4], sizeof(dev_uuid)); + ret = rmt_prov_client_scan_start(dst, net_key_index, scanned_items_limit, scan_timeout, dev_uuid); + } else if (pparse_value->para_count == 4) { + ret = rmt_prov_client_scan_start(dst, net_key_index, scanned_items_limit, scan_timeout, NULL); + } else { + data_uart_debug("invalid param\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + if (ret == MESH_MSG_SEND_CAUSE_SUCCESS) { + return USER_CMD_RESULT_OK; + } else { + data_uart_debug("fail\r\n"); + return USER_CMD_RESULT_ERROR; + } +} + +static user_cmd_parse_result_t user_cmd_rmt_prov_client_link_open_prov(user_cmd_parse_value_t *pparse_value) +{ + uint8_t dev_uuid[16]; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t link_open_timeout = pparse_value->dw_parameter[3]; + + if (pparse_value->para_count == 4) { + plt_hex_to_bin(dev_uuid, (uint8_t *)pparse_value->pparameter[2], sizeof(dev_uuid)); + } else { + data_uart_debug("invalid uuid\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + return rmt_prov_client_link_open_prov(dst, net_key_index, dev_uuid, link_open_timeout) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_rmt_prov_client_close(user_cmd_parse_value_t *pparse_value) +{ + rmt_prov_link_close_reason_t reason; + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t net_key_index = pparse_value->dw_parameter[1]; + + if (pparse_value->para_count == 3) { + reason = (rmt_prov_link_close_reason_t)pparse_value->dw_parameter[2]; + } else { + data_uart_debug("invalid reason\r\n"); + return USER_CMD_RESULT_WRONG_PARAMETER; + } + + return rmt_prov_client_link_close(dst, net_key_index, reason) == MESH_MSG_SEND_CAUSE_SUCCESS ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} +#endif + +static user_cmd_parse_result_t user_cmd_prov(user_cmd_parse_value_t *pparse_value) +{ + data_uart_debug("provision...\r\n"); + uint32_t attn_dur = pparse_value->dw_parameter[0]; + prov_manual = pparse_value->dw_parameter[1]; + prov_start_time = plt_time_read_ms(); + return prov_invite(attn_dur) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_prov_stop(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + return prov_reject() ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; +} + +static user_cmd_parse_result_t user_cmd_prov_auth_path(user_cmd_parse_value_t *pparse_value) +{ + prov_start_algorithm_t algo = (prov_start_algorithm_t)pparse_value->dw_parameter[0]; + prov_start_public_key_t public_key = (prov_start_public_key_t)pparse_value->dw_parameter[1]; + prov_auth_method_t auth_method = (prov_auth_method_t)pparse_value->dw_parameter[2]; + uint8_t oob_action = pparse_value->dw_parameter[3]; + uint8_t oob_size = pparse_value->dw_parameter[4]; + + prov_start_t prov_start; + prov_start.algorithm = algo; + prov_start.public_key = public_key; + prov_start.auth_method = auth_method; + prov_start.auth_action.oob_action = oob_action; + prov_start.auth_size.oob_size = oob_size; + return prov_path_choose(&prov_start) == true ? USER_CMD_RESULT_OK : USER_CMD_RESULT_WRONG_PARAMETER; +} + +static user_cmd_parse_result_t user_cmd_unprov(user_cmd_parse_value_t *pparse_value) +{ + /* avoid gcc compile warning */ + (void)pparse_value; + + data_uart_debug("Unprovision...\r\n"); +#if MESH_UNPROVISIONING_SUPPORT + prov_unprovisioning(); +#endif + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_cfg_client_key_set(user_cmd_parse_value_t + *pparse_value) +{ + uint8_t key_index = pparse_value->dw_parameter[0]; + bool use_app_key = pparse_value->dw_parameter[1] ? TRUE : FALSE; + mesh_node.features.cfg_model_use_app_key = use_app_key; + return cfg_client_key_set(key_index) ? USER_CMD_RESULT_OK : + USER_CMD_RESULT_VALUE_OUT_OF_RANGE; +} + +static user_cmd_parse_result_t user_cmd_compo_data_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t page = pparse_value->dw_parameter[1]; + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + data_uart_debug("CDP0 len=%d, data=", mesh_node.compo_data_size[0]); + data_uart_dump(mesh_node.compo_data[0], mesh_node.compo_data_size[0]); + } + else + { + cfg_compo_data_get(dst, page); + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_node_reset(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + bool clear = pparse_value->dw_parameter[1]; + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + mesh_node_reset(); + } + else + { + cfg_node_reset(dst); + if (clear) + { + int dev_key_index = dev_key_find(dst); + if (dev_key_index >= 0) + { + dev_key_delete(dev_key_index); + mesh_flash_store(MESH_FLASH_PARAMS_DEV_KEY, &dev_key_index); + } + } + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_net_key_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 2) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + cfg_net_key_add(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_new_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_net_key_update(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t net_key[MESH_COMMON_KEY_SIZE]; + plt_hex_to_bin(net_key, (uint8_t *)pparse_value->pparameter[2], MESH_COMMON_KEY_SIZE); + return net_key_update(net_key_index, mesh_node.net_key_list[net_key_index].net_key_index_g, + net_key) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; + } + else + { + cfg_net_key_update(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.net_key_list[net_key_index].pnet_key[key_state_to_new_loop( + mesh_node.net_key_list[net_key_index].key_state)]->net_key); + return USER_CMD_RESULT_OK; + } +} + +static user_cmd_parse_result_t user_cmd_app_key_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + data_uart_debug("\r\n %s() dst = %x",__func__,dst); + cfg_app_key_add(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.app_key_list[app_key_index].app_key_index_g, + mesh_node.app_key_list[app_key_index].papp_key[key_state_to_new_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_app_key_update(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint16_t app_key_index = pparse_value->dw_parameter[2]; + if (net_key_index >= mesh_node.net_key_num || + mesh_node.net_key_list[net_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + if (MESH_IS_UNASSIGNED_ADDR(dst)) + { + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint8_t app_key[MESH_COMMON_KEY_SIZE]; + plt_hex_to_bin(app_key, (uint8_t *)pparse_value->pparameter[3], MESH_COMMON_KEY_SIZE); + return app_key_update(app_key_index, net_key_index, + mesh_node.app_key_list[app_key_index].app_key_index_g, + app_key) ? USER_CMD_RESULT_OK : USER_CMD_RESULT_ERROR; + } + else + { + cfg_app_key_update(dst, mesh_node.net_key_list[net_key_index].net_key_index_g, + mesh_node.app_key_list[app_key_index].app_key_index_g, + mesh_node.app_key_list[app_key_index].papp_key[key_state_to_new_loop( + mesh_node.app_key_list[app_key_index].key_state)]->app_key); + return USER_CMD_RESULT_OK; + } +} + +static user_cmd_parse_result_t user_cmd_model_app_bind(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t app_key_index = pparse_value->dw_parameter[3]; + if (app_key_index >= mesh_node.app_key_num || + mesh_node.app_key_list[app_key_index].key_state == MESH_KEY_STATE_INVALID) + { + return USER_CMD_RESULT_VALUE_OUT_OF_RANGE; + } + cfg_model_app_bind(dst, dst + element_index, mesh_node.app_key_list[app_key_index].app_key_index_g, + model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_pub_set(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 11) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + pub_key_info_t pub_key_info = {pparse_value->dw_parameter[4], pparse_value->dw_parameter[5], 0}; + pub_period_t pub_period = {pparse_value->dw_parameter[7] & 0x3f, pparse_value->dw_parameter[7] >> 6}; + pub_retrans_info_t pub_retrans_info = {pparse_value->dw_parameter[8], pparse_value->dw_parameter[9]}; + uint8_t addr[16]; + if (0 == pparse_value->dw_parameter[2]) + { + uint16_t element_addr = (uint16_t)(pparse_value->dw_parameter[3]); + LE_WORD2EXTRN(addr, element_addr); + } + else + { + plt_hex_to_bin(addr, (uint8_t *)pparse_value->pparameter[3], 16); + } + cfg_model_pub_set(dst, pparse_value->dw_parameter[1], pparse_value->dw_parameter[2], + addr, pub_key_info, pparse_value->dw_parameter[6], pub_period, + pub_retrans_info, pparse_value->dw_parameter[10]); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_add(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 4) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t group_addr = pparse_value->dw_parameter[3]; + if (MESH_NOT_GROUP_ADDR(group_addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + cfg_model_sub_add(dst, dst + element_index, false, (uint8_t *)&group_addr, model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_get(user_cmd_parse_value_t *pparse_value) +{ + if (pparse_value->para_count != 3) + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + cfg_model_sub_get(dst, dst + element_index, model_id); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_model_sub_delete(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint8_t element_index = pparse_value->dw_parameter[1]; + uint32_t model_id = pparse_value->dw_parameter[2]; + uint16_t group_addr = pparse_value->dw_parameter[3]; + if (pparse_value->para_count == 4) + { + if (MESH_NOT_GROUP_ADDR(group_addr)) + { + return USER_CMD_RESULT_WRONG_PARAMETER; + } + cfg_model_sub_delete(dst, dst + element_index, false, (uint8_t *)&group_addr, model_id); + } + else if (pparse_value->para_count == 3) + { + cfg_model_sub_delete_all(dst, dst + element_index, model_id); + } + else + { + return USER_CMD_RESULT_WRONG_NUM_OF_PARAMETERS; + } + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_key_refresh_phase_get(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + cfg_key_refresh_phase_get(dst, net_key_index_to_global(net_key_index)); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_key_refresh_phase_set(user_cmd_parse_value_t *pparse_value) +{ + uint16_t dst = pparse_value->dw_parameter[0]; + uint16_t net_key_index = pparse_value->dw_parameter[1]; + uint8_t phase = pparse_value->dw_parameter[2]; + cfg_key_refresh_phase_set(dst, net_key_index_to_global(net_key_index), phase); + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_write(user_cmd_parse_value_t *pparse_value) +{ + uint8_t para_count = pparse_value->para_count; + uint8_t data[18]; + + for (uint8_t i = 0; i < para_count - 3; ++i) + { + data[i] = pparse_value->dw_parameter[i + 1]; + } + datatrans_write(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[para_count - 2], para_count - 3, data, + pparse_value->dw_parameter[para_count - 1]); + + return USER_CMD_RESULT_OK; +} + +static user_cmd_parse_result_t user_cmd_datatrans_read(user_cmd_parse_value_t *pparse_value) +{ + datatrans_read(&datatrans, pparse_value->dw_parameter[0], + pparse_value->dw_parameter[2], pparse_value->dw_parameter[1]); + + return USER_CMD_RESULT_OK; +} + + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const user_cmd_table_entry_t provisioner_cmd_table[] = +{ + // mesh common cmd + MESH_COMMON_CMD, + CLIENT_CMD, + TEST_CMD, + // provisioner cmd + // pb-adv + { + "pbadvcon", + "pbadvcon [dev uuid]\n\r", + "create a pb-adv link with the device uuid\n\r", + user_cmd_pb_adv_con + }, + { + "pbadvdisc", + "pbadvdisc\n\r", + "disconnect the pb-adv link\n\r", + user_cmd_pb_adv_disc + }, + // pb-gatt + { + "provdis", + "provdis [conn id]\n\r", + "Start discovery provisioning service\n\r", + user_cmd_prov_discover + }, + { + "provread", + "provread [char] [pattern: handle/UUID16]\n\r", + "Read all related chars by user input\n\r", + user_cmd_prov_read_char + }, + { + "provcmd", + "provcmd [char CCCD] [command: enable/disable]\n\r", + "Provisioning notify/ind switch command\n\r", + user_cmd_prov_cccd_operate + }, + { + "provls", + "provls\n\r", + "Provision server handle list\n\r", + user_cmd_prov_list + }, + // provisioner + { + "prov", + "prov [attn_dur] [manual]\n\r", + "provision a new mesh device\n\r", + user_cmd_prov + }, + { + "provs", + "provs\n\r", + "provision stop\n\r", + user_cmd_prov_stop + }, + { + "pap", + "pap [algorithm] [pubkey] [method: nsoi] [action] [size]\n\r", + "provision authentication path\n\r", + user_cmd_prov_auth_path + }, + { + "unprov", + "unprov\n\r", + "unprovision the mesh device\n\r", + user_cmd_unprov + }, + // cfg client key set + { + "ccks", + "ccks [key_index] [use_app_key]\n\r", + "cfg client key set\n\r", + user_cmd_cfg_client_key_set + }, + // cfg client or local setting + { + "cdg", + "cdg [dst]\n\r", + "compo data get\n\r", + user_cmd_compo_data_get + }, + { + "nr", + "nr [dst] [clear]\n\r", + "node reset\n\r", + user_cmd_node_reset + }, + { + "nka", + "nka [dst] [net_key_index]\n\r", + "net key add\n\r", + user_cmd_net_key_add + }, + { + "nku", + "nku [dst] [net_key_index] [net key]\n\r", + "net key update\n\r", + user_cmd_net_key_update + }, + { + "aka", + "aka [dst] [net_key_index] [app_key_index]\n\r", + "app key add\n\r", + user_cmd_app_key_add + }, + { + "aku", + "aku [dst] [net_key_index] [app_key_index] [app key]\n\r", + "app key update\n\r", + user_cmd_app_key_update + }, + { + "mab", + "mab [dst] [element index] [model_id] [app_key_index]\n\r", + "model app bind\n\r", + user_cmd_model_app_bind + }, + { + "msa", + "msa [dst] [element index] [model_id] [group addr]\n\r", + "model subsribe add\n\r", + user_cmd_model_sub_add + }, + { + "msd", + "msd [dst] [element index] [model_id] \n\r", + "model subsribe delete\n\r", + user_cmd_model_sub_delete + }, + { + "krpg", + "krpg [dst] [net key index]\n\r", + "key refresh phase get\n\r", + user_cmd_key_refresh_phase_get + }, + { + "krps", + "krps [dst] [net key index] [phase]\n\r", + "key refresh phase set\n\r", + user_cmd_key_refresh_phase_set + }, + { + "dtw", + "dtw [dst] [data...] [app_key_index] [ack] \n\r", + "data transmission write data\n\r", + user_cmd_datatrans_write + }, + { + "dtr", + "dtr [dst] [len] [app_key_index]\n\r", + "data transmission read data\n\r", + user_cmd_datatrans_read + }, +#if defined(MESH_RPR) && MESH_RPR + { + "rmtscan", + "rmtscan [dst] [net key index] [scanned items limit] [scan timeout] [dev uuid]\n\r", + "romte provision scan start\n\r", + user_cmd_rmt_prov_client_scan_start + }, + { + "rmtcon", + "rmtcon [dst] [net key index] [dev uuid] [link open timeout]\n\r", + "romte link open for provision\n\r", + user_cmd_rmt_prov_client_link_open_prov + }, + { + "rmtdisc", + "rmtdisc [dst] [net_key_index] [reason]\n\r", + "romte link close for provision\n\r", + user_cmd_rmt_prov_client_close + }, +#endif + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; + +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +const struct bt_mesh_api_hdl provisionercmds[] = +{ + GEN_MESH_HANDLER(_pb_adv_con) + GEN_MESH_HANDLER(_prov) + GEN_MESH_HANDLER(_prov_stop) + GEN_MESH_HANDLER(_app_key_add) + GEN_MESH_HANDLER(_model_app_bind) + GEN_MESH_HANDLER(_model_pub_set) + GEN_MESH_HANDLER(_generic_on_off_set) + GEN_MESH_HANDLER(_generic_on_off_get) + GEN_MESH_HANDLER(_node_reset) + GEN_MESH_HANDLER(_model_sub_delete) + GEN_MESH_HANDLER(_model_sub_add) + GEN_MESH_HANDLER(_model_sub_get) + GEN_MESH_HANDLER(_prov_discover) + GEN_MESH_HANDLER(_prov_cccd_operate) + GEN_MESH_HANDLER(_proxy_discover) + GEN_MESH_HANDLER(_proxy_cccd_operate) + GEN_MESH_HANDLER(_datatrans_write) + GEN_MESH_HANDLER(_datatrans_read) + GEN_MESH_HANDLER(_connect) + GEN_MESH_HANDLER(_disconnect) + GEN_MESH_HANDLER(_list) + GEN_MESH_HANDLER(_dev_info_show) + GEN_MESH_HANDLER(_fn_init) + GEN_MESH_HANDLER(_fn_deinit) + GEN_MESH_HANDLER(_light_lightness_get) + GEN_MESH_HANDLER(_light_lightness_set) + GEN_MESH_HANDLER(_light_lightness_linear_get) + GEN_MESH_HANDLER(_light_lightness_linear_set) + GEN_MESH_HANDLER(_light_lightness_last_get) + GEN_MESH_HANDLER(_light_lightness_default_get) + GEN_MESH_HANDLER(_light_lightness_default_set) + GEN_MESH_HANDLER(_light_lightness_range_get) + GEN_MESH_HANDLER(_light_lightness_range_set) + GEN_MESH_HANDLER(_light_ctl_get) + GEN_MESH_HANDLER(_light_ctl_set) + GEN_MESH_HANDLER(_light_ctl_temperature_get) + GEN_MESH_HANDLER(_light_ctl_temperature_set) + GEN_MESH_HANDLER(_light_ctl_temperature_range_get) + GEN_MESH_HANDLER(_light_ctl_temperature_range_set) + GEN_MESH_HANDLER(_light_ctl_default_get) + GEN_MESH_HANDLER(_light_ctl_default_set) + GEN_MESH_HANDLER(_light_hsl_get) + GEN_MESH_HANDLER(_light_hsl_set) + GEN_MESH_HANDLER(_light_hsl_target_get) + GEN_MESH_HANDLER(_light_hsl_hue_get) + GEN_MESH_HANDLER(_light_hsl_hue_set) + GEN_MESH_HANDLER(_light_hsl_saturation_get) + GEN_MESH_HANDLER(_light_hsl_saturation_set) + GEN_MESH_HANDLER(_light_hsl_default_get) + GEN_MESH_HANDLER(_light_hsl_default_set) + GEN_MESH_HANDLER(_light_hsl_range_get) + GEN_MESH_HANDLER(_light_hsl_range_set) + GEN_MESH_HANDLER(_light_xyl_get) + GEN_MESH_HANDLER(_light_xyl_set) + GEN_MESH_HANDLER(_light_xyl_target_get) + GEN_MESH_HANDLER(_light_xyl_default_get) + GEN_MESH_HANDLER(_light_xyl_default_set) + GEN_MESH_HANDLER(_light_xyl_range_get) + GEN_MESH_HANDLER(_light_xyl_range_set) + GEN_MESH_HANDLER(_time_set) + GEN_MESH_HANDLER(_time_get) + GEN_MESH_HANDLER(_time_zone_set) + GEN_MESH_HANDLER(_time_zone_get) + GEN_MESH_HANDLER(_time_tai_utc_delta_set) + GEN_MESH_HANDLER(_time_tai_utc_delta_get) + GEN_MESH_HANDLER(_time_role_set) + GEN_MESH_HANDLER(_time_role_get) + GEN_MESH_HANDLER(_scene_store) + GEN_MESH_HANDLER(_scene_recall) + GEN_MESH_HANDLER(_scene_get) + GEN_MESH_HANDLER(_scene_register_get) + GEN_MESH_HANDLER(_scene_delete) + GEN_MESH_HANDLER(_scheduler_get) + GEN_MESH_HANDLER(_scheduler_action_get) + GEN_MESH_HANDLER(_scheduler_action_set) +#if defined(MESH_RPR) && MESH_RPR + GEN_MESH_HANDLER(_rmt_prov_client_scan_start) + GEN_MESH_HANDLER(_rmt_prov_client_link_open_prov) + GEN_MESH_HANDLER(_rmt_prov_client_close) +#endif +#if defined(MESH_DFU) && MESH_DFU + GEN_MESH_HANDLER(_fw_update_info_get) + GEN_MESH_HANDLER(_fw_update_start) + GEN_MESH_HANDLER(_fw_update_cancel) +#endif +}; +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.h new file mode 100644 index 00000000..f08c0dbd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.h @@ -0,0 +1,36 @@ +/* + * Routines to access hardware + * + * Copyright (c) 2014 Realtek Semiconductor Corp. + * + * This module is a confidential and proprietary property of RealTek and + * possession or use of this module requires written permission of RealTek. + */ +#ifndef _PRO_CMD_H_ +#define _PRO_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "mesh_data_uart.h" +#include "mesh_user_cmd_parse.h" +#include "mesh_config.h" +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +#include "bt_mesh_cmd_types.h" +#endif + +/**************************************************************************************************************** +* exported variables other .c files may use all defined here. +****************************************************************************************************************/ +extern const user_cmd_table_entry_t provisioner_cmd_table[]; +#if defined(CONFIG_BT_MESH_USER_API) && CONFIG_BT_MESH_USER_API +extern const struct bt_mesh_api_hdl provisionercmds[]; +#endif +void light_cwrgb_process(void); +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.c new file mode 100644 index 00000000..592b45a8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.c @@ -0,0 +1,67 @@ +#include "platform_opts.h" +#include "platform_os.h" +#include "os_task.h" +#include +#include +#include +#if defined(CONFIG_PLATFORM_8721D) || defined(CONFIG_PLATFORM_8710C) +#include +#endif +#include "bt_config_wifi.h" + +#include + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + +//media +extern void amebacam_broadcast_demo_thread(void *param); +//httpd +extern void httpd_demo_init_thread(void *param); +extern int bt_config_app_init(void); +extern uint8_t get_bt_config_state(void); + +void bt_mesh_example_init_thread(void *param) +{ + /* avoid gcc compile warning */ + (void)param; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + /*Init BT config*/ + bt_config_app_init(); + /*Wait BT config complete*/ + while(get_bt_config_state() != BC_DEV_DISABLED) { + os_delay(500); + } + + os_task_delete(NULL); +} + +void *httpd_demo_init_task = NULL; +void *amebacam_broadcast_demo_task = NULL; +void *bt_mesh_example_init_task = NULL; + +void example_bt_mesh(void) +{ + //init httpd + if (os_task_create(&httpd_demo_init_task, "httpd_demo_init_thread", httpd_demo_init_thread, + NULL, 2048, 1) != true) { + printf("\n\r%s xTaskCreate(httpd_demo_init_thread) failed", __FUNCTION__); + } + //init amebacam_broadcast + if (os_task_create(&amebacam_broadcast_demo_task, "amebacam_broadcast_demo_thread", amebacam_broadcast_demo_thread, + NULL, 2048, 1) != true) { + printf("\n\r%s xTaskCreate(amebacam_broadcast_demo_thread) failed", __FUNCTION__); + } + //init bt config/bt mesh + if (os_task_create(&bt_mesh_example_init_task, "bt_mesh_example_demo_init_thread", bt_mesh_example_init_thread, + NULL, 1024, 5) != true) { + printf("\n\r%s xTaskCreate(bt_mesh_example_demo_init_thread) failed", __FUNCTION__); + } +} + +#endif /* CONFIG_EXAMPLE_BT_MESH_DEMO */ + + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.h new file mode 100644 index 00000000..e77501b0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.h @@ -0,0 +1,7 @@ +#ifndef _EXAMPLE_BT_MESH_H_ +#define _EXAMPLE_BT_MESH_H_ + +void example_bt_mesh(void); + +#endif /* _EXAMPLE_BT_MESH_DEMO_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_http_intf.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_http_intf.h new file mode 100644 index 00000000..d1831738 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_http_intf.h @@ -0,0 +1,31 @@ +#ifndef _BT_MESH_APP_HTTP_INTF_H_ +#define _BT_MESH_APP_HTTP_INTF_H_ + +typedef enum +{ + RTW_BT_MESH_CMD = 0x1, + RTW_BT_MESH_EVENT = 0x2, +} T_MESH_CMD_EVENT_TYPE; + +typedef enum +{ + RTW_BT_MESH_CMD_START_PROVISIONER = 0x1, + RTW_BT_MESH_CMD_GET_UNPROVISIONED_DEVICE = 0x2, + RTW_BT_MESH_CMD_CONNECT_DEVICE = 0x3, + RTW_BT_MESH_CMD_DELETE_NODE = 0x4, + RTW_BT_MESH_CMD_GET_NODE_STATUS = 0x5, + RTW_BT_MESH_CMD_SET_NODE_STATE = 0x6, + RTW_BT_MESH_CMD_SET_NODE_GROUP = 0x7, +} T_MESH_CMD_TYPE; + +typedef enum +{ + RTW_BT_MESH_EVENT_PROVISIONER_STATE = 0x1, + RTW_BT_MESH_EVENT_UNPROVISIONED_DEVICE = 0x2, + RTW_BT_MESH_EVENT_DEVICE_CONNECT_INFO = 0x3, + RTW_BT_MESH_EVENT_NODE_DELETE_INFO = 0x4, + RTW_BT_MESH_EVENT_NODE_STATUS = 0x5, +} T_MESH_VENT_TYPE; + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_lib_intf.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_lib_intf.h new file mode 100644 index 00000000..09fd7415 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_lib_intf.h @@ -0,0 +1,60 @@ +#ifndef _BT_MESH_APP_LIB_INTF_H_ +#define _BT_MESH_APP_LIB_INTF_H_ + +#include "osdep_service.h" +#include "app_msg.h" + +typedef enum +{ + API_PB_ADV_LINK_OPEN = 0x0, + API_PROV_INVITE = 0x1, + API_CFG_APP_KEY_ADD = 0x2, + API_CFG_MODEL_APP_BIND = 0x3, + API_CFG_MODEL_PUB_SET = 0x4, + API_CFG_MODEL_SUB_ADD = 0x5, + API_CFG_MODEL_SUB_GET = 0x6, + API_CFG_MODEL_SUB_DELETE_ALL = 0x7, + API_CFG_NODE_RESET = 0x8, + API_GENERIC_ON_OFF_GET = 0x9, + API_GENERIC_ON_OFF_SET = 0xA, + API_GENERIC_ON_OFF_PUBLISH = 0xB, +} T_MESH_API_TYPE; + +struct BT_MESH_LIB_PRIV { + _sema connect_device_sema; + _sema connect_device_goog_sema; + _sema connect_device_nr_sema; + _sema delete_node_sema; + _sema set_node_state_sema; + _sema set_node_group_sema; + + uint16_t connect_device_mesh_addr; + uint16_t connect_device_goog_mesh_addr; + uint16_t connect_device_nr_mesh_addr; + uint16_t delete_node_mesh_addr; + uint16_t set_node_state_mesh_addr; + uint16_t set_node_group_mesh_addr; + + uint8_t connect_device_flag; + uint8_t set_node_group_flag; + + uint8_t connect_device_goog_light_state; + uint8_t set_node_state_light_state; +}; + +uint8_t bt_mesh_cmd_start_provisioner_api(void); + +uint8_t bt_mesh_cmd_connect_device_api(uint8_t *dev_uuid, uint16_t *mesh_addr, uint8_t *light_state); + +uint8_t bt_mesh_cmd_delete_node_api(uint16_t mesh_addr); + +uint8_t bt_mesh_cmd_set_node_state_api(uint16_t mesh_addr, uint16_t group_addr, uint8_t light_state, uint8_t flag); + +uint8_t bt_mesh_cmd_get_node_state_api(uint16_t mesh_addr); + +uint8_t bt_mesh_cmd_set_node_group_api(uint16_t mesh_addr, uint16_t group_addr); + +uint8_t bt_mesh_cmd_get_node_group_api(uint16_t mesh_addr); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_list_intf.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_list_intf.h new file mode 100644 index 00000000..a75286e6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_app_list_intf.h @@ -0,0 +1,101 @@ +#ifndef _BT_MESH_APP_LIST_INTF_H_ +#define _BT_MESH_APP_LIST_INTF_H_ + +#include "osdep_service.h" + +struct BT_MESH_DEVICE_INFO { + struct list_head list; + uint8_t dev_uuid[16]; + uint16_t mesh_addr; + uint16_t group_addr; + uint32_t last_scan_time; + uint32_t last_active_time; + uint8_t connect_status; //0: Fail, 1: Success + uint8_t delete_status; //0: Fail, 1: Success + uint8_t active_state; //0: Inactive, 1: Active + uint8_t light_state; //0: Off, 1: On + uint16_t target_group_addr; + uint8_t target_light_state; //0: Off, 1: On + uint8_t get_group_addr_flag;//0: No need to get group address, 1: Need to get group address + uint8_t set_node_state_flag;//0: Use mesh address, 1: Use group address +}; + +struct BT_MESH_PRIV { + _list unproed_dev_list; + _list proed_active_dev_list; + _list proed_inactive_dev_list; + _list processing_dev_list; + + _lock dev_list_lock; + + _timer list_flushing_timer; + + bool provisioner_started_flag; +}; + +typedef struct meshFlushInfo +{ + struct list_head meshFlushList; //!< List contains flush contants. + uint8_t meshFlushEvent; //!< Indicate currently flush event. + uint8_t eventListNum; //!< user command num included in .meshCmdList. + _mutex eventMutex; //!< mesh flush private struct mutex. +} MESH_FLUSH_INFO_S; + +typedef struct meshFlushItem +{ + struct list_head list; //!< list of .meshFlushItem. + struct list_head *plist; //!< pointer to list. + uint8_t meshFlushEvent; //!< Indicate currently flush event. +} MESH_FLUSH_ITEM_S; + +enum +{ + CONNECTION_CHECK_EVENT , + GET_NODE_GROUP , + COMBO_CHECK +}; + +void init_bt_mesh_priv(void); + +void add_unproed_dev(uint8_t *dev_uuid); + +void update_proed_dev(uint16_t mesh_addr, uint8_t light_state); + +void update_node_group(uint16_t mesh_addr, uint16_t group_addr); + +/* RTW_BT_CMD_START_PROVISIONER */ +void bt_mesh_cmd_start_provisioner_handler(uint8_t *bt_mesh_event_value); + +/* RTW_BT_CMD_GET_UNPROVISIONED_DEVICE */ +void bt_mesh_cmd_get_unprovisioned_device_handler(uint8_t *bt_mesh_event_value); + +/* RTW_BT_CMD_CONNECT_DEVICE */ +void bt_mesh_cmd_connect_device_pre_handler(uint8_t *dev_uuid); +void bt_mesh_cmd_connect_device_handler(void); +void bt_mesh_cmd_connect_device_post_handler(uint8_t *bt_mesh_event_value); + +/* RTW_BT_CMD_DELETE_NODE */ +void bt_mesh_cmd_delete_node_pre_handler(uint16_t mesh_addr); +void bt_mesh_cmd_delete_node_handler(void); +void bt_mesh_cmd_delete_node_post_handler(uint8_t *bt_mesh_event_value); + +/* RTW_BT_CMD_GET_NODE_STATUS */ +void bt_mesh_cmd_get_node_status_handler(uint8_t *bt_mesh_event_value); + +/* RTW_BT_CMD_SET_NODE_STATE */ +void bt_mesh_cmd_set_node_state_pre_handler(uint16_t mesh_addr, uint8_t light_state); +void bt_mesh_cmd_set_node_state_handler(void); +void bt_mesh_cmd_set_node_state_post_handler(uint8_t *bt_mesh_event_value); + +/* RTW_BT_CMD_SET_NODE_GROUP */ +void bt_mesh_cmd_set_node_group_pre_handler(uint16_t mesh_addr, uint16_t group_addr); +void bt_mesh_cmd_set_node_group_handler(void); +void bt_mesh_cmd_set_node_group_post_handler(uint8_t *bt_mesh_event_value); + +uint8_t bt_mesh_enqueue_flush_event(struct list_head *queue); +struct list_head *bt_mesh_dequeue_flush_event(void); +uint8_t bt_mesh_demo_start_drv_thread(void); +void bt_mesh_demo_stop_drv_thread(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_broadcast_demo.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_broadcast_demo.h new file mode 100644 index 00000000..c113c202 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc/bt_mesh_broadcast_demo.h @@ -0,0 +1,7 @@ +#ifndef __BT_MESH_MEDIA_BROADCAST_DEMO_H__ +#define __BT_MESH_MEDIA_BROADCAST_DEMO_H__ + +void amebacam_broadcast_demo_init_thread(void); + +#endif //#ifndef __MEDIA_AMEBACAM_BROADCAST_DEMO_H__ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_http_intf.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_http_intf.c new file mode 100644 index 00000000..fdbf0e79 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_http_intf.c @@ -0,0 +1,772 @@ +#include +#include +#include "bt_mesh_app_http_intf.h" +#include "bt_mesh_app_list_intf.h" +#include "platform_os.h" +#include "os_task.h" + +#define USE_HTTPS 0 + +#if USE_HTTPS +// use test_srv_crt, test_srv_key, test_ca_list in PolarSSL certs.c +#if (HTTPD_USE_TLS == HTTPD_TLS_POLARSSL) +#include +#elif (HTTPD_USE_TLS == HTTPD_TLS_MBEDTLS) +#include +#endif +#endif + +extern uint8_t stop_list_flushing_flag; +extern struct BT_MESH_PRIV bt_mesh_priv; + +int chartodec(char value) +{ + int data = 0; + if((value >= '0') && (value <= '9')) + data = value - '0'; + else if((value >= 'a') && (value <= 'f')) + data = value - 'a' + 10; + else if((value >= 'A') && (value <= 'F')) + data = value - 'A' + 10; + + return data; +} + +int dectochar(uint8_t value) +{ + char data; + if(value <= 9) + data = value + '0'; + else if((value >= 10) && (value <= 15)) + data = value + 'a' - 10; + + return data; +} + +extern void *httpd_malloc(size_t size); + +char *OneBytetoTwoByte(char *value, uint8_t flag) +{ + char *bt_mesh_event_value = NULL; + int i = 0, j = 0,k = 0; + uint8_t *ptr = NULL; + //get length + uint16_t length= 0; + + if(flag == RTW_BT_MESH_EVENT_PROVISIONER_STATE) + length = 5; + else if(flag == RTW_BT_MESH_EVENT_UNPROVISIONED_DEVICE) + length = 4 + 1 + (*(value + 4)) * 16; + else if(flag == RTW_BT_MESH_EVENT_DEVICE_CONNECT_INFO) + length = 4 + 1 + (*(value + 4)) * 20; + else if(flag == RTW_BT_MESH_EVENT_NODE_DELETE_INFO) + length = 4 + 1 + (*(value + 4)) * 3; + else if(flag == RTW_BT_MESH_EVENT_NODE_STATUS) + length = 4 + 1 + (*(value + 4)) * 6; + + //malloc char type bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(2 * length + 1); + memset(bt_mesh_event_value,0,2 * length + 1); + + ///filled bt_mesh_event_value's event 0-1 byte + *bt_mesh_event_value = (*(value) & 0xf0) >> 4; + *(bt_mesh_event_value + 1) = (*(value) & 0x0f); + //filled bt_mesh_event_value's event id 2-3 byte + *(bt_mesh_event_value + 2)= (*(value + 1) & 0xf0) >> 4; + *(bt_mesh_event_value + 3) = (*(value + 1) & 0x0f); + + ///fill Length filed 4-7 byte + *(bt_mesh_event_value + 4) = ((2 * length) & 0xf000) >> 12 ; + *(bt_mesh_event_value + 5) = ((2 * length) & 0x0f00) >> 8 ; + *(bt_mesh_event_value + 6) = ((2 * length) & 0x00f0) >> 4 ; + *(bt_mesh_event_value + 7) = ((2 * length) & 0x000f) ; + + switch(flag){ + case RTW_BT_MESH_EVENT_PROVISIONER_STATE: + *(bt_mesh_event_value + 8) = (*(value + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 9) = (*(value + 4) & 0x0f); + break; + case RTW_BT_MESH_EVENT_UNPROVISIONED_DEVICE: + ///fill device number filed 8-9 byte + *(bt_mesh_event_value + 8) = (*(value + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 9) = (*(value + 4) & 0x0f); + + ptr = (uint8_t *)(value + 5);//point to first uuid + for(i = 0; i < *(value + 4) * 16; i ++){ + *(bt_mesh_event_value + 10 + j) = (*(ptr + i) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 1) = (*(ptr + i) & 0x0f); + j = j + 2; + } + + break; + case RTW_BT_MESH_EVENT_DEVICE_CONNECT_INFO: + ///fill device number filed 8-9 byte + *(bt_mesh_event_value + 8) = (*(value + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 9) = (*(value + 4) & 0x0f); + ptr = (uint8_t *)(value + 5);//point to first uuid + + //fill uuid + for(i = 0,j = 0; i < *(value + 4) * 20;){ + ///fill uuid addr + for(k = i; k < 16 + i; k ++){ + *(bt_mesh_event_value + 10 + j) = (*(ptr + k ) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 1) = (*(ptr + k ) & 0x0f); + j = j + 2; + } + //fill connect status + *(bt_mesh_event_value + 10 + j) = (*(ptr + k) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 1) = (*(ptr + k) & 0x0f); + + //fill mesh addr + *(bt_mesh_event_value + 10 + j + 2) = (*(ptr + k + 2) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 3) = (*(ptr + k + 2) & 0x0f) ; + *(bt_mesh_event_value + 10 + j + 4) = (*(ptr + k + 1) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 5) = (*(ptr + k + 1) & 0x0f) ; + + //fill light state + *(bt_mesh_event_value + 10 + j + 6) = (*(ptr + k + 3) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 7) = (*(ptr + k + 3) & 0x0f); + + i = i + 20; + j = j + 8; + } + + break; + case RTW_BT_MESH_EVENT_NODE_DELETE_INFO: + ///fill device number filed 8-9 byte + *(bt_mesh_event_value + 8) = (*(value + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 9) = (*(value + 4) & 0x0f) ; + ptr = (uint8_t *)(value + 5); + for(i = 0; i < *(value + 4) * 3;){ + //fill mesh addr + *(bt_mesh_event_value + 10 + j) = (*(ptr + i + 1) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 1) = (*(ptr + i + 1) & 0x0f) ; + *(bt_mesh_event_value + 10 + j + 2) = (*(ptr + i ) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 3) = (*(ptr + i) & 0x0f) ; + //fill delete note + *(bt_mesh_event_value + 10 + j + 4) = (*(ptr + i + 2) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 5) = (*(ptr + i + 2) & 0x0f); + + i = i + 3; + j = j + 6; + } + break; + case RTW_BT_MESH_EVENT_NODE_STATUS: + ///fill device number filed 8-9 byte + *(bt_mesh_event_value + 8) = (*(value + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 9) = (*(value + 4) & 0x0f); + ptr = (uint8_t *)(value + 5); + for(i = 0; i < *(value + 4) * 6;){ + //fill mesh addr + *(bt_mesh_event_value + 10 + j) = (*(ptr + i + 1) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 1) = (*(ptr + i + 1 ) & 0x0f) ; + *(bt_mesh_event_value + 10 + j + 2) = (*(ptr + i) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 3) = (*(ptr + i) & 0x0f) ; + //fill group addr + *(bt_mesh_event_value + 10 + j + 4) = (*(ptr + i + 3) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 5) = (*(ptr + i + 3) & 0x0f) ; + *(bt_mesh_event_value + 10 + j + 6) = (*(ptr + i + 2) & 0xf0) >> 4 ; + *(bt_mesh_event_value + 10 + j + 7) = (*(ptr + i + 2) & 0x0f) ; + //fill active state + *(bt_mesh_event_value + 10 + j + 8) = (*(ptr + i + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 9) = (*(ptr + i + 4) & 0x0f); + //fill light state + *(bt_mesh_event_value + 10 + j + 10) = (*(ptr + i + 5) & 0xf0) >> 4; + *(bt_mesh_event_value + 10 + j + 11) = (*(ptr + i + 5) & 0x0f); + + i = i + 6; + j = j + 12; + } + break; + default: + printf("\r\n unknow flag \n"); + } + ///dec to char + for(int i = 0; i < 2 * length; i ++) + { + *(bt_mesh_event_value + i) = dectochar(*(bt_mesh_event_value + i)); + } + + return bt_mesh_event_value; +} + +char *TwoBytetoOneByte(char *value, uint8_t flag) +{ + char *bt_mesh_event_value = NULL; + uint8_t cmd_event = 0; //judge is a cmd or event + uint8_t cmd_event_id = 0; + uint16_t length = 0; + //char *ptr = NULL; + uint8_t device_number = 0; + uint8_t dev_uuid[16] = {0}; + int i = 0,j = 0,dev_A = 0; + uint16_t mesh_addr = 0, group_addr = 0; + uint8_t light_state = 0; + + + switch(flag){ + case RTW_BT_MESH_CMD_START_PROVISIONER: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_PROVISIONER_STATE; + length = 1 + 1 + 2 + 1; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + ///event 0 byte + *bt_mesh_event_value = cmd_event; + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 8; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + break; + case RTW_BT_MESH_CMD_GET_UNPROVISIONED_DEVICE: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_UNPROVISIONED_DEVICE; + length = 4 + 1 + 20 * 16; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + + ///event 0 byte + *bt_mesh_event_value = cmd_event; + + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 4; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + break; + case RTW_BT_MESH_CMD_CONNECT_DEVICE: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_DEVICE_CONNECT_INFO; + device_number = (chartodec(*(value)) << 4 ) + chartodec(*(value + 1)); + length = 4 + 1 + device_number * 20; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + + //fill event + *bt_mesh_event_value = cmd_event; + + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 8; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + + //fill device number 4 byte + *(bt_mesh_event_value + 4) = device_number; + //value point the first mesh addr + value = value + 2; + //according to device_numberget the dev_uuid circulatory + for(i = 0,j = 0;i < (device_number * 32);j ++){ + *(dev_uuid + j) = (chartodec(*(value + i)) << 4 ) + chartodec(*(value + i + 1)) ; + if((i + 1 - dev_A) % 31 == 0){ + dev_A = dev_A + 32; + bt_mesh_cmd_connect_device_pre_handler(dev_uuid); + memset(dev_uuid,0,16); + j = -1; + } + i = i + 2; + } + break; + case RTW_BT_MESH_CMD_DELETE_NODE: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_NODE_DELETE_INFO; + device_number = (chartodec(*(value)) << 4 ) + chartodec(*(value + 1)); + length = 4 + 1 + (2 + 1) * device_number; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + + //fill event + *bt_mesh_event_value = cmd_event; + + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 8; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + + //fill device number 4 byte + *(bt_mesh_event_value + 4) = device_number; + value = value + 2; + for(i = 0;i < device_number * 4;){ + mesh_addr = (chartodec(*(value + i)) << 12) + (chartodec(*(value + i + 1)) << 8) + (chartodec(*(value + i + 2)) << 4) + (chartodec(*(value + i + 3)));//analynis length filed + i = i + 4; + + bt_mesh_cmd_delete_node_pre_handler(mesh_addr); + mesh_addr = 0; + } + break; + case RTW_BT_MESH_CMD_GET_NODE_STATUS: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_NODE_STATUS; + length = 4 + 1 + 20 * 6; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + + //fill event + *bt_mesh_event_value = cmd_event; + + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 8; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + break; + case RTW_BT_MESH_CMD_SET_NODE_STATE: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_NODE_STATUS; + device_number = (chartodec(*(value)) << 4 ) + chartodec(*(value + 1)); + length = 4 + 1 + 20 * 6; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + + //fill event + *bt_mesh_event_value = cmd_event; + + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 8; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + + //fill device number 4 byte + *(bt_mesh_event_value + 4) = device_number; + value = value + 2; + for(i = 0;i < device_number * 6;){ + mesh_addr = (chartodec(*(value + i)) << 12) + (chartodec(*(value + i + 1)) << 8) + (chartodec(*(value + i + 2)) << 4) + (chartodec(*(value + i + 3))); + light_state = (chartodec(*(value + i + 4)) << 4) + chartodec(*(value + i + 5)); + + i = i + 6; + + bt_mesh_cmd_set_node_state_pre_handler(mesh_addr,light_state); + mesh_addr = 0; + light_state = 0; + } + break; + case RTW_BT_MESH_CMD_SET_NODE_GROUP: + cmd_event = RTW_BT_MESH_EVENT; + cmd_event_id = RTW_BT_MESH_EVENT_NODE_STATUS; + device_number = (chartodec(*(value)) << 4 ) + chartodec(*(value + 1)); + length = 4 + 1 + device_number * 6; + + //malloc bt_mesh_event_value + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value,0,length + 1); + + //fill event + *bt_mesh_event_value = cmd_event; + + //event id 1byte + *(bt_mesh_event_value + 1) = cmd_event_id; + + //length 2-3 byte + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 8; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + + //fill device number 4 byte + *(bt_mesh_event_value + 4) = device_number; + value = value + 2; + for(i = 0;i < device_number * 8;){ + mesh_addr = (chartodec(*(value + i)) << 12) + (chartodec(*(value + i + 1)) << 8) + (chartodec(*(value + i + 2)) << 4) + (chartodec(*(value + i + 3))); + group_addr = (chartodec(*(value + i + 4)) << 12) + (chartodec(*(value + i + 5)) << 8) + (chartodec(*(value + i + 6)) << 4) + (chartodec(*(value + i + 7))); + i = i + 8; + + bt_mesh_cmd_set_node_group_pre_handler(mesh_addr,group_addr); + mesh_addr = 0; + group_addr = 0; + } + break; + + default: + printf("\r\nUnknow cmd id\n"); + break; + } + + return bt_mesh_event_value; +} + +char *ErrorOneBytetoTwoByte(char *value) +{ + char *bt_mesh_event_value = NULL; + uint16_t length = (*(value + 2) << 8) + (*(value + 3)); + + bt_mesh_event_value = (char *)httpd_malloc(2 * length + 1); + memset(bt_mesh_event_value, 0, 2 * length + 1); + + *bt_mesh_event_value = (*(value) & 0xf0) >> 4; + *(bt_mesh_event_value + 1) = (*(value) & 0x0f); + + *(bt_mesh_event_value + 2)= (*(value + 1) & 0xf0) >> 4; + *(bt_mesh_event_value + 3) = (*(value + 1) & 0x0f); + + *(bt_mesh_event_value + 4) = ((2 * length) & 0xf000) >> 12; + *(bt_mesh_event_value + 5) = ((2 * length) & 0x0f00) >> 8; + *(bt_mesh_event_value + 6) = ((2 * length) & 0x00f0) >> 4; + *(bt_mesh_event_value + 7) = ((2 * length) & 0x000f); + + *(bt_mesh_event_value + 8) = (*(value + 4) & 0xf0) >> 4; + *(bt_mesh_event_value + 9) = (*(value + 4) & 0x0f); + + for(int i = 0; i < 2 * length; i ++) + { + *(bt_mesh_event_value + i) = dectochar(*(bt_mesh_event_value + i)); + } + + return bt_mesh_event_value; +} + +char *ErrorTwoBytetoOneByte(uint8_t flag) +{ + char *bt_mesh_event_value = NULL; + uint8_t cmd_event = 0; + uint8_t cmd_event_id = 0; + uint16_t length = 0; + uint8_t device_number = 0; + + cmd_event = RTW_BT_MESH_EVENT; + + switch(flag) { + case RTW_BT_MESH_CMD_GET_UNPROVISIONED_DEVICE: + cmd_event_id = RTW_BT_MESH_EVENT_UNPROVISIONED_DEVICE; + break; + case RTW_BT_MESH_CMD_CONNECT_DEVICE: + cmd_event_id = RTW_BT_MESH_EVENT_DEVICE_CONNECT_INFO; + break; + case RTW_BT_MESH_CMD_DELETE_NODE: + cmd_event_id = RTW_BT_MESH_EVENT_NODE_DELETE_INFO; + break; + case RTW_BT_MESH_CMD_GET_NODE_STATUS: + case RTW_BT_MESH_CMD_SET_NODE_STATE: + case RTW_BT_MESH_CMD_SET_NODE_GROUP: + cmd_event_id = RTW_BT_MESH_EVENT_NODE_STATUS; + break; + } + + length = 1 + 1 + 2 + 1; + device_number = 0xff; + + bt_mesh_event_value = (char *)httpd_malloc(length + 1); + memset(bt_mesh_event_value, 0, length + 1); + + *bt_mesh_event_value = cmd_event; + + *(bt_mesh_event_value + 1) = cmd_event_id; + + *(bt_mesh_event_value + 2) = (length & 0xff00) >> 4; + *(bt_mesh_event_value + 3) = (length & 0x00ff); + + *(bt_mesh_event_value + 4) = device_number; + + return bt_mesh_event_value; +} + +char * bt_mesh_cmd_start_provisioner_parsing(void) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + + bt_mesh_event_value_one = TwoBytetoOneByte(NULL, RTW_BT_MESH_CMD_START_PROVISIONER); + + bt_mesh_cmd_start_provisioner_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_PROVISIONER_STATE); + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +char *bt_mesh_cmd_get_unprovisioned_device_parsing(void) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + + if(bt_mesh_priv.provisioner_started_flag == _FALSE) { + bt_mesh_event_value_one = ErrorTwoBytetoOneByte(RTW_BT_MESH_CMD_GET_UNPROVISIONED_DEVICE); + + bt_mesh_event_value_two = ErrorOneBytetoTwoByte(bt_mesh_event_value_one); + } else { + bt_mesh_event_value_one = TwoBytetoOneByte(NULL, RTW_BT_MESH_CMD_GET_UNPROVISIONED_DEVICE); + + bt_mesh_cmd_get_unprovisioned_device_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_UNPROVISIONED_DEVICE); + } + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +char *bt_mesh_cmd_connect_device_parsing(char ** value) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + char *ptr = NULL; + + if(bt_mesh_priv.provisioner_started_flag == _FALSE) { + bt_mesh_event_value_one = ErrorTwoBytetoOneByte(RTW_BT_MESH_CMD_CONNECT_DEVICE); + + bt_mesh_event_value_two = ErrorOneBytetoTwoByte(bt_mesh_event_value_one); + } else { + ptr = *value; + bt_mesh_event_value_one = TwoBytetoOneByte(ptr, RTW_BT_MESH_CMD_CONNECT_DEVICE); + + bt_mesh_cmd_connect_device_handler(); + + bt_mesh_cmd_connect_device_post_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_DEVICE_CONNECT_INFO); + } + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +char *bt_mesh_cmd_delete_node_parsing(char ** value) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + char *ptr = NULL; + + if(bt_mesh_priv.provisioner_started_flag == _FALSE) { + bt_mesh_event_value_one = ErrorTwoBytetoOneByte(RTW_BT_MESH_CMD_DELETE_NODE); + + bt_mesh_event_value_two = ErrorOneBytetoTwoByte(bt_mesh_event_value_one); + } else { + ptr = *value; + bt_mesh_event_value_one = TwoBytetoOneByte(ptr, RTW_BT_MESH_CMD_DELETE_NODE); + + bt_mesh_cmd_delete_node_handler(); + + bt_mesh_cmd_delete_node_post_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_NODE_DELETE_INFO); + } + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +char *bt_mesh_cmd_get_node_status_parsing(char ** value) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + char *ptr = NULL; + + if(bt_mesh_priv.provisioner_started_flag == _FALSE) { + bt_mesh_event_value_one = ErrorTwoBytetoOneByte(RTW_BT_MESH_CMD_GET_NODE_STATUS); + + bt_mesh_event_value_two = ErrorOneBytetoTwoByte(bt_mesh_event_value_one); + } else { + ptr = *value; + bt_mesh_event_value_one = TwoBytetoOneByte(ptr, RTW_BT_MESH_CMD_GET_NODE_STATUS); + + bt_mesh_cmd_get_node_status_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_NODE_STATUS); + } + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +char *bt_mesh_cmd_set_node_state_parsing(char ** value) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + char *ptr = NULL; + + if(bt_mesh_priv.provisioner_started_flag == _FALSE) { + bt_mesh_event_value_one = ErrorTwoBytetoOneByte(RTW_BT_MESH_CMD_SET_NODE_STATE); + + bt_mesh_event_value_two = ErrorOneBytetoTwoByte(bt_mesh_event_value_one); + } else { + ptr = *value; + bt_mesh_event_value_one = TwoBytetoOneByte(ptr, RTW_BT_MESH_CMD_SET_NODE_STATE); + + bt_mesh_cmd_set_node_state_handler(); + + bt_mesh_cmd_set_node_state_post_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_NODE_STATUS); + } + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +char *bt_mesh_cmd_set_node_group_parsing(char ** value) +{ + char *bt_mesh_event_value_one = NULL, *bt_mesh_event_value_two = NULL; + char *ptr = NULL; + + if(bt_mesh_priv.provisioner_started_flag == _FALSE) { + bt_mesh_event_value_one = ErrorTwoBytetoOneByte(RTW_BT_MESH_CMD_SET_NODE_GROUP); + + bt_mesh_event_value_two = ErrorOneBytetoTwoByte(bt_mesh_event_value_one); + } else { + ptr = *value; + bt_mesh_event_value_one = TwoBytetoOneByte(ptr, RTW_BT_MESH_CMD_SET_NODE_GROUP); + + bt_mesh_cmd_set_node_group_handler(); + + bt_mesh_cmd_set_node_group_post_handler((uint8_t *)bt_mesh_event_value_one); + + bt_mesh_event_value_two = OneBytetoTwoByte(bt_mesh_event_value_one, RTW_BT_MESH_EVENT_NODE_STATUS); + } + + if(bt_mesh_event_value_one) + httpd_free(bt_mesh_event_value_one); + + return bt_mesh_event_value_two; +} + +void httpd_get_cb(struct httpd_conn *conn) +{ + stop_list_flushing_flag = 1; + // GET /test_post + if(httpd_request_is_method(conn, "GET")) { + char *bt_mesh_cmd_value = NULL,*ptr = NULL; //content after "bt_mesh=" + char *bt_mesh_event_value = NULL; //response to app + int cmd_event; //judge is a cmd or event + int cmd_event_id; + int colength_content = 0; + int length = 0; + // get 'bt_mesh' in query string + if(httpd_request_get_query_key(conn, "bt_mesh", &bt_mesh_cmd_value) != -1){ +#if 1 + printf("\n\rPrintf the httpd request there:"); + printf("%s",bt_mesh_cmd_value); + printf("\n\r"); +#endif + ///original address of bt_mesh_cmd_value + ptr = bt_mesh_cmd_value; + //cmd event 0-1 byte + cmd_event = (chartodec(*ptr) << 4) + chartodec(*(ptr + 1)); + //cmd id 2-3 byte + cmd_event_id = (chartodec(*(ptr + 2)) << 4) + chartodec(*(ptr + 3)); + ///length 4-7 byte + length = (chartodec(*(ptr + 4)) << 12) + (chartodec(*(ptr + 5)) << 8) + (chartodec(*(ptr + 6)) << 4) + (chartodec(*(ptr + 7)));//analynis length filed + colength_content = strlen(ptr); //the length of content + if(colength_content != length){ + printf("\r\nERROR: The Length is not fit\n"); + httpd_response_bad_request(conn, "Bad Request - The Length is not fit"); + return; + } + printf("\r\n %s() cmd_event=%d, cmd_event_id=%d, line=%d",__func__,cmd_event,cmd_event_id,__LINE__); + /////content filed--point to length's next byte + ptr = ptr + 8; + ///analysis CMD field + switch (cmd_event){ + case RTW_BT_MESH_CMD://is a cmd from app to provisioner + switch (cmd_event_id){ + case RTW_BT_MESH_CMD_START_PROVISIONER: + bt_mesh_event_value = bt_mesh_cmd_start_provisioner_parsing(); + break; + case RTW_BT_MESH_CMD_GET_UNPROVISIONED_DEVICE: + bt_mesh_event_value = bt_mesh_cmd_get_unprovisioned_device_parsing(); + break; + case RTW_BT_MESH_CMD_CONNECT_DEVICE: + bt_mesh_event_value = bt_mesh_cmd_connect_device_parsing(&ptr); + break; + case RTW_BT_MESH_CMD_DELETE_NODE: + bt_mesh_event_value = bt_mesh_cmd_delete_node_parsing(&ptr); + break; + case RTW_BT_MESH_CMD_GET_NODE_STATUS: + bt_mesh_event_value = bt_mesh_cmd_get_node_status_parsing(&ptr); + break; + case RTW_BT_MESH_CMD_SET_NODE_STATE: + bt_mesh_event_value = bt_mesh_cmd_set_node_state_parsing(&ptr); + break; + case RTW_BT_MESH_CMD_SET_NODE_GROUP: + bt_mesh_event_value = bt_mesh_cmd_set_node_group_parsing(&ptr); + break; + default: + printf("\r\nUnknow cmd id \n"); + } + } +#if 1 + printf("\n\rPrintf the httpd response there:"); + printf("%s",bt_mesh_event_value); + printf("\n\r"); +#endif +///write httpd response to app + httpd_response_write_header_start(conn, "200 OK", "text/plain", 0); + httpd_response_write_header(conn, "Connection", "close"); + httpd_response_write_header_finish(conn); + httpd_response_write_data(conn, (uint8_t*)"bt_mesh= ", strlen("bt_mesh= ")); + httpd_response_write_data(conn, (uint8_t*)bt_mesh_event_value, strlen(bt_mesh_event_value)); + + } + else { + // HTTP/1.1 400 Bad Request + httpd_response_bad_request(conn, "Bad Request - bt_mesh is not in query string"); + } + if(bt_mesh_cmd_value) + httpd_free(bt_mesh_cmd_value); + if(bt_mesh_event_value) + httpd_free(bt_mesh_event_value); + } + else { + // HTTP/1.1 405 Method Not Allowed + httpd_response_method_not_allowed(conn, NULL); + } + stop_list_flushing_flag = 0; + httpd_conn_close(conn); +} + +void httpd_demo_init_thread(void *param) +{ + /* To avoid gcc warnings */ + ( void ) param; +#if USE_HTTPS +#if (HTTPD_USE_TLS == HTTPD_TLS_POLARSSL) + if(httpd_setup_cert(test_srv_crt, test_srv_key, test_ca_crt) != 0) { +#elif (HTTPD_USE_TLS == HTTPD_TLS_MBEDTLS) + if(httpd_setup_cert(mbedtls_test_srv_crt, mbedtls_test_srv_key, mbedtls_test_ca_crt) != 0) { +#endif + printf("\nERROR: httpd_setup_cert\n"); + goto exit; + } +#endif + httpd_reg_page_callback("/test_get", httpd_get_cb); +#if USE_HTTPS + if(httpd_start(443, 5, 4096, HTTPD_THREAD_SINGLE, HTTPD_SECURE_TLS) != 0) { +#else + if(httpd_start(80, 5, 4096, HTTPD_THREAD_SINGLE, HTTPD_SECURE_NONE) != 0) { +#endif + printf("ERROR: httpd_start"); + httpd_clear_page_callbacks(); + } + if (bt_mesh_demo_start_drv_thread()) { + printf("ERROR: bt_mesh_demo_start_drv_thread fail !"); + } +#if USE_HTTPS +exit: +#endif + os_task_delete(NULL); +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_lib_intf.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_lib_intf.c new file mode 100644 index 00000000..22a82fbc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_lib_intf.c @@ -0,0 +1,492 @@ +#include "platform_opts.h" +#include "bt_mesh_app_lib_intf.h" +#include "wifi_conf.h" +#include "gap_conn_le.h" +#include "mesh_api.h" +#include "generic_on_off.h" +#include "bt_mesh_provisioner_api.h" +#include "provisioner_app.h" +#include "platform_os.h" + +#define CMD_REPEAT_TIMES 5 +#define BT_MESH_APP_LIB_INTF_DEBUG 1 + +struct BT_MESH_LIB_PRIV bt_mesh_lib_priv; + +uint8_t bt_mesh_user_cmd_cbk(uint16_t mesh_code, void *user_data) +{ + PUSER_ITEM puserItem = NULL; + CMD_ITEM_S *pmeshCmdItem_s = NULL; + + pmeshCmdItem_s = (CMD_ITEM_S *)user_data; + puserItem = pmeshCmdItem_s->pmeshCmdItem->userData; + if (pmeshCmdItem_s->userApiMode == USER_API_SYNCH) { + if (pmeshCmdItem_s->semaDownTimeOut) { + printf("\r\n %s() mesh code = %d fail caused user cmd timeout",__func__, mesh_code); + return USER_API_RESULT_TIMEOUT; + } + } + printf("\r\n %s() mesh code = %d userCmdResult = %d",__func__, mesh_code, puserItem->userCmdResult); + switch (mesh_code) { + case GEN_MESH_CODE(_pb_adv_con): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + bt_mesh_lib_priv.connect_device_flag = 1; + }else { + bt_mesh_lib_priv.connect_device_flag = 0; + } + } + break; + + case GEN_MESH_CODE(_prov): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + rtw_memcpy(&bt_mesh_lib_priv.connect_device_mesh_addr, (uint16_t *)puserItem->userParam, sizeof(uint16_t)); + }else { + bt_mesh_lib_priv.connect_device_mesh_addr = 0; + } + } + break; + + case GEN_MESH_CODE(_app_key_add): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + bt_mesh_lib_priv.connect_device_flag = 1; + }else { + bt_mesh_lib_priv.connect_device_flag = 0; + } + } + break; + + case GEN_MESH_CODE(_model_app_bind): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + bt_mesh_lib_priv.connect_device_flag = 1; + }else { + bt_mesh_lib_priv.connect_device_flag = 0; + } + } + break; + + case GEN_MESH_CODE(_model_pub_set): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + bt_mesh_lib_priv.connect_device_flag = 1; + bt_mesh_lib_priv.connect_device_goog_mesh_addr = bt_mesh_lib_priv.connect_device_mesh_addr; + bt_mesh_lib_priv.connect_device_goog_light_state = 0; + }else { + bt_mesh_lib_priv.connect_device_flag = 0; + } + } + break; + + case GEN_MESH_CODE(_generic_on_off_get): + { + + } + break; + + case GEN_MESH_CODE(_generic_on_off_set): + { + generic_on_off_client_status_t *pdata = (generic_on_off_client_status_t *)puserItem->userParam; + /* maybe the bt_mesh_indication is from node's publish */ + if (bt_mesh_lib_priv.set_node_state_mesh_addr != pdata->src) { + printf("\r\n %s() this goos indication is not matched",__func__); + return USER_API_RESULT_INDICATION_NOT_MATCHED; + } + bt_mesh_lib_priv.set_node_state_light_state = puserItem->userCmdResult; + } + break; + + case GEN_MESH_CODE(_node_reset): + { + + } + break; + + case GEN_MESH_CODE(_model_sub_delete): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + bt_mesh_lib_priv.set_node_group_flag = 1; + }else { + bt_mesh_lib_priv.set_node_group_flag = 0; + } + } + break; + + case GEN_MESH_CODE(_model_sub_add): + { + if (puserItem->userCmdResult == BT_MESH_USER_CMD_SUCCESS) { + bt_mesh_lib_priv.set_node_group_flag = 1; + }else { + bt_mesh_lib_priv.set_node_group_flag = 0; + } + } + break; + + default: + { + printf("[BT_MESH] %s(): user cmd %d not found !\r\n", __func__, mesh_code); + } + break; + } + + return USER_API_RESULT_OK; +} + +extern int bt_mesh_provisioner_app_main(void); +extern int bt_mesh_provisioner_multiple_profile_app_main(void); +extern void bt_coex_init(void); + +uint8_t bt_mesh_cmd_start_provisioner_api(void) +{ + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + printf("[BT Mesh Provisioner]BT Stack already on\n\r"); + return 0; + } + else +#if defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER + bt_mesh_provisioner_app_main(); +#elif defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE + bt_mesh_provisioner_multiple_profile_app_main(); +#endif + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + +#if defined(CONFIG_BT_MESH_PROVISIONER_RTK_DEMO) && CONFIG_BT_MESH_PROVISIONER_RTK_DEMO + if (bt_mesh_provisioner_api_init()) { + printf("[BT Mesh Provisioner] bt_mesh_provisioner_api_init fail ! \n\r"); + return 0; + } +#endif + + return 1; + +} + +uint8_t bt_mesh_cmd_connect_device_api(uint8_t *dev_uuid, uint16_t *mesh_addr, uint8_t *light_state) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + char devUuid[40]; + + /*_pb_adv_con */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto exit; + } + memset(devUuid, 0, sizeof(devUuid)); + user_cmd_array2string(dev_uuid, 16, devUuid); + puserItem->pparseValue->pparameter[0] = devUuid; + puserItem->pparseValue->para_count = 1; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_pb_adv_con), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + goto exit; + } + + /* _prov */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto exit; + } + puserItem->pparseValue->dw_parameter[0] = 0;//attn_dur + puserItem->pparseValue->dw_parameter[1] = 0;//prov_manual + puserItem->pparseValue->para_count = 2; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_prov), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + if (ret == USER_API_RESULT_TIMEOUT) { + /* _prov_stop */ + puserItem = bt_mesh_alloc_hdl(USER_API_ASYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto exit; + } + puserItem->pparseValue->para_count = 0; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_prov_stop), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + } + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + goto exit; + } + + /* _app_key_add */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto nr_exit; + } + puserItem->pparseValue->dw_parameter[0] = bt_mesh_lib_priv.connect_device_mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//net_key_index + puserItem->pparseValue->dw_parameter[2] = 0;//app_key_index + puserItem->pparseValue->para_count = 3; + //printf("\r\n %s() mesh_adr = %x",__func__,bt_mesh_lib_priv.connect_device_mesh_addr); + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_app_key_add), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + goto nr_exit; + } + + /* _model_app_bind */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto nr_exit; + } + puserItem->pparseValue->dw_parameter[0] = bt_mesh_lib_priv.connect_device_mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//element_index + puserItem->pparseValue->dw_parameter[2] = MESH_MODEL_GENERIC_ON_OFF_SERVER;//model_id + puserItem->pparseValue->dw_parameter[3] = 0;//app_key_index + puserItem->pparseValue->para_count = 4; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_model_app_bind), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + goto nr_exit; + } + + /* _model_pub_set */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto nr_exit; + } + puserItem->pparseValue->dw_parameter[0] = bt_mesh_lib_priv.connect_device_mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = bt_mesh_lib_priv.connect_device_mesh_addr + 0;//mesh_addr + mesh_index + puserItem->pparseValue->dw_parameter[2] = 0;//va_flag + puserItem->pparseValue->dw_parameter[3] = 0xFEFF;//element_addr + puserItem->pparseValue->dw_parameter[4] = 0;//app key index + puserItem->pparseValue->dw_parameter[5] = 0;//frnd_flag + puserItem->pparseValue->dw_parameter[6] = 0x3F;//pub_ttl + puserItem->pparseValue->dw_parameter[7] = 0x86; + puserItem->pparseValue->dw_parameter[8] = 0; + puserItem->pparseValue->dw_parameter[9] = 3; + puserItem->pparseValue->dw_parameter[10] = MESH_MODEL_GENERIC_ON_OFF_SERVER; + puserItem->pparseValue->para_count = 11; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_model_pub_set), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + goto nr_exit; + } + + /* _generic_on_off_get */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + goto nr_exit; + } + puserItem->pparseValue->dw_parameter[0] = bt_mesh_lib_priv.connect_device_mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//app_key_index + puserItem->pparseValue->para_count = 2; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_generic_on_off_get), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if ((ret != USER_API_RESULT_OK) && (ret != USER_API_RESULT_ERROR)) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + goto nr_exit; + } + *mesh_addr = bt_mesh_lib_priv.connect_device_goog_mesh_addr; + *light_state = bt_mesh_lib_priv.connect_device_goog_light_state; + bt_mesh_lib_priv.connect_device_goog_mesh_addr = 0; + bt_mesh_lib_priv.connect_device_mesh_addr = 0; + + return 1; + +nr_exit: + /* nr */ + if (bt_mesh_lib_priv.connect_device_mesh_addr == 0) { + printf("[BT_MESH_DEMO] There is no device provisioned!\r\n"); + goto exit; + } + bt_mesh_lib_priv.connect_device_nr_mesh_addr = bt_mesh_lib_priv.connect_device_mesh_addr; + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + bt_mesh_lib_priv.connect_device_nr_mesh_addr = 0; + goto exit; + } + puserItem->pparseValue->dw_parameter[0] = bt_mesh_lib_priv.connect_device_mesh_addr;//mesh_adr + puserItem->pparseValue->para_count = 1; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_node_reset), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + bt_mesh_lib_priv.connect_device_nr_mesh_addr = 0; + goto exit; + } + bt_mesh_lib_priv.connect_device_nr_mesh_addr = 0; + +exit: + bt_mesh_lib_priv.connect_device_mesh_addr = 0; + return 0; + +} + +uint8_t bt_mesh_cmd_delete_node_api(uint16_t mesh_addr) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + bt_mesh_lib_priv.delete_node_mesh_addr = mesh_addr; + + /* _node_reset */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return 0; + } + puserItem->pparseValue->dw_parameter[0] = mesh_addr;//attn_dur + puserItem->pparseValue->para_count = 1; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_node_reset), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return 0; + } + bt_mesh_lib_priv.delete_node_mesh_addr = 0; + + return 1; +} + +uint8_t bt_mesh_cmd_set_node_state_api(uint16_t mesh_addr, uint16_t group_addr, uint8_t light_state, uint8_t flag) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + bt_mesh_lib_priv.set_node_state_mesh_addr = mesh_addr; + bt_mesh_lib_priv.set_node_state_light_state = 0; + + /* _generic_on_off_set */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return 0; + } + if (flag && MESH_IS_GROUP_ADDR(group_addr)) { + puserItem->pparseValue->dw_parameter[0] = group_addr; + } else { + puserItem->pparseValue->dw_parameter[0] = mesh_addr; + } + puserItem->pparseValue->dw_parameter[1] = light_state;//light_state + puserItem->pparseValue->dw_parameter[2] = 1;//ack + puserItem->pparseValue->dw_parameter[3] = 0;//app_key_index + puserItem->pparseValue->dw_parameter[4] = 0;//trans_time + puserItem->pparseValue->dw_parameter[5] = 0;//trans_time + puserItem->pparseValue->dw_parameter[6] = 0;//delay + puserItem->pparseValue->para_count = 4; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_generic_on_off_set), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if ((ret != USER_API_RESULT_OK) && (ret != USER_API_RESULT_ERROR)) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return 0xFF; + } + ret = bt_mesh_lib_priv.set_node_state_light_state; + bt_mesh_lib_priv.set_node_state_mesh_addr = 0; + + return ret; +} + +uint8_t bt_mesh_cmd_get_node_state_api(uint16_t mesh_addr) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + /* _generic_on_off_get */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return 0xFF; + } + puserItem->pparseValue->dw_parameter[0] = mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//app_key_index + puserItem->pparseValue->para_count = 2; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_generic_on_off_get), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if ((ret != USER_API_RESULT_OK) && (ret != USER_API_RESULT_ERROR)) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return 0xFF; + } + + return ret; +} + +uint8_t bt_mesh_cmd_set_node_group_api(uint16_t mesh_addr, uint16_t group_addr) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + bt_mesh_lib_priv.set_node_group_flag = 0; + bt_mesh_lib_priv.set_node_group_mesh_addr = mesh_addr; + + /* _model_sub_delete */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return 0; + } + puserItem->pparseValue->dw_parameter[0] = mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//element_index + puserItem->pparseValue->dw_parameter[2] = MESH_MODEL_GENERIC_ON_OFF_SERVER;//model_id + puserItem->pparseValue->para_count = 3; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_model_sub_delete), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return 0; + } + + if (group_addr == 0) { + printf("[BT_MESH_DEMO] Delete mesh_addr 0x%x from Group \r\n", mesh_addr); + return 1; + } + /* _model_sub_add */ + puserItem = bt_mesh_alloc_hdl(USER_API_SYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return 0; + } + puserItem->pparseValue->dw_parameter[0] = mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//element_index + puserItem->pparseValue->dw_parameter[2] = MESH_MODEL_GENERIC_ON_OFF_SERVER;//model_id + puserItem->pparseValue->dw_parameter[3] = group_addr;//group_addr + puserItem->pparseValue->para_count = 4; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_model_sub_add), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return 0; + } + bt_mesh_lib_priv.set_node_group_mesh_addr = 0; + + return 1; +} + +uint8_t bt_mesh_cmd_get_node_group_api(uint16_t mesh_addr) +{ + PUSER_ITEM puserItem = NULL; + uint8_t ret; + + /* _model_sub_get */ + puserItem = bt_mesh_alloc_hdl(USER_API_ASYNCH); + if (!puserItem) { + printf("[BT_MESH_DEMO] bt_mesh_alloc_hdl fail!\r\n"); + return 0; + } + puserItem->pparseValue->dw_parameter[0] = mesh_addr;//mesh_adr + puserItem->pparseValue->dw_parameter[1] = 0;//element_index + puserItem->pparseValue->dw_parameter[2] = MESH_MODEL_GENERIC_ON_OFF_SERVER;//model_id + puserItem->pparseValue->para_count = 3; + ret = bt_mesh_set_user_cmd(GEN_MESH_CODE(_model_sub_get), puserItem->pparseValue, bt_mesh_user_cmd_cbk, puserItem); + if (ret != USER_API_RESULT_OK) { + printf("[BT_MESH_DEMO] bt_mesh_set_user_cmd fail! %d\r\n", ret); + return 0; + } + + return 1; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_list_intf.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_list_intf.c new file mode 100644 index 00000000..9a2254ac --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_list_intf.c @@ -0,0 +1,997 @@ +#include "bt_mesh_app_list_intf.h" +#include "bt_mesh_app_lib_intf.h" +#include "mesh_api.h" +#include "platform_os.h" +#include "os_task.h" + +#define BT_MESH_APP_LIST_INTF_DEBUG 1 +#define LIST_FLUSHING_TIMEOUT 5 +#define BT_MESH_EVENT_HEADER_LENGTH 4 + +struct mesh_task_struct { + void *task; /* I: workqueue thread */ + void *wakeup_sema; /* for internal use only */ + void *terminate_sema; /* for internal use only */ + u32 blocked; /* for internal use only */ +}; + +MESH_FLUSH_INFO_S btMeshFlushPriv; +struct mesh_task_struct meshFlushingThread; +struct BT_MESH_PRIV bt_mesh_priv; +uint8_t stop_list_flushing_flag = 0; + +void list_flushing_handler(_list *plist, uint8_t mesh_flush_event) +{ + MESH_FLUSH_ITEM_S *pmeshFlushItem_s = NULL; + + pmeshFlushItem_s = (MESH_FLUSH_ITEM_S *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(MESH_FLUSH_ITEM_S)); + if (pmeshFlushItem_s == NULL) { + printf("[BT_MESH_DEMO] %s(): alloc pmeshFlushItem_s fail !\r\n", __func__); + return; + } + pmeshFlushItem_s->plist = plist; + pmeshFlushItem_s->meshFlushEvent = mesh_flush_event; + bt_mesh_enqueue_flush_event(&pmeshFlushItem_s->list); + + return; +} + +extern int rtw_if_wifi_create_task(struct task_struct *ptask, const char *name, + u32 stack_size, u32 priority, thread_func_t func, void *thctx); +extern void rtw_if_wifi_delete_task(struct task_struct *ptask); +extern void rtw_if_wifi_wakeup_task(struct task_struct *ptask); + +void list_flushing_timer_handler(void *FunctionContext) +{ + /* avoid gcc compile warning */ + (void)FunctionContext; + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint32_t current_time = os_sys_time_get(); + uint8_t flag = 0; + + if (stop_list_flushing_flag) { +#if 0 //BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] APP is processing, stop list flushing to maintain the topology!\r\n"); +#endif + plt_timer_change_period(bt_mesh_priv.list_flushing_timer.timer_hdl, LIST_FLUSHING_TIMEOUT * 1000, 0xFFFFFFFF); + return; + } + +#if 0 //BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] list_flushing_timer timeout!\r\n"); +#endif + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.unproed_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.unproed_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (current_time > pbt_mesh_device_info->last_scan_time && rtw_systime_to_sec(current_time - pbt_mesh_device_info->last_scan_time) > 120) { + rtw_list_delete(plist); +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] UUID = 0x"); + for(uint8_t i = 0; i < 16; i++) + printf("%02X", pbt_mesh_device_info->dev_uuid[i]); + printf(" remove from unproed_dev_list & free in %s()!\r\n", __FUNCTION__); +#endif + os_mem_free((uint8_t *)pbt_mesh_device_info); + } + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (current_time > pbt_mesh_device_info->last_active_time && rtw_systime_to_sec(current_time - pbt_mesh_device_info->last_active_time) > 120) { + /* enqueue list to bt_mesh_flushing_thread for double check caused btc leak */ + if (pbt_mesh_device_info->get_group_addr_flag && pbt_mesh_device_info->active_state) { + list_flushing_handler(plist, COMBO_CHECK); + } else { + list_flushing_handler(plist, CONNECTION_CHECK_EVENT); + } + flag = 1; + } + if (!flag) { + if (pbt_mesh_device_info->get_group_addr_flag && pbt_mesh_device_info->active_state) { + list_flushing_handler(plist, GET_NODE_GROUP); + } + } + flag = 0; + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + plt_timer_change_period(bt_mesh_priv.list_flushing_timer.timer_hdl, LIST_FLUSHING_TIMEOUT * 1000, 0xFFFFFFFF); +} + +void init_bt_mesh_priv(void) +{ + rtw_memset(&bt_mesh_priv, 0, sizeof(bt_mesh_priv)); + + rtw_init_listhead(&bt_mesh_priv.unproed_dev_list); + rtw_init_listhead(&bt_mesh_priv.proed_active_dev_list); + rtw_init_listhead(&bt_mesh_priv.proed_inactive_dev_list); + rtw_init_listhead(&bt_mesh_priv.processing_dev_list); + + rtw_spinlock_init(&bt_mesh_priv.dev_list_lock); + + bt_mesh_priv.list_flushing_timer.timer_hdl = plt_timer_create("list_flushing_timer", 0xFFFFFFFF, FALSE, NULL, list_flushing_timer_handler); + if (!bt_mesh_priv.list_flushing_timer.timer_hdl) { + printf("[BT_MESH_DEMO] Create list flush timer failed\n\r"); + return; + } + plt_timer_change_period(bt_mesh_priv.list_flushing_timer.timer_hdl, LIST_FLUSHING_TIMEOUT * 1000, 0xFFFFFFFF); + + bt_mesh_priv.provisioner_started_flag = _FALSE; +} + +void add_unproed_dev(uint8_t *dev_uuid) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint32_t current_time = os_sys_time_get(); + uint8_t flag = 0; + + if (stop_list_flushing_flag) { +#if 0 //BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] APP is processing, stop add unproed dev to maintain the topology!\r\n"); +#endif + return; + } + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.unproed_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.unproed_dev_list, plist)) == _FALSE) { + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (rtw_memcmp(pbt_mesh_device_info->dev_uuid, dev_uuid, 16) == 1) { + flag = 1; + break; + } + + plist = get_next(plist); + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + if (flag) { + pbt_mesh_device_info->last_scan_time = current_time; +#if 0 //BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] UUID = 0x"); + for (uint8_t i = 0; i < 16; i++) + printf("%02X", dev_uuid[i]); + printf(" update last_scan_time in %s()!\r\n", __FUNCTION__); +#endif + } else { + pbt_mesh_device_info = (struct BT_MESH_DEVICE_INFO *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(struct BT_MESH_DEVICE_INFO)); + if (pbt_mesh_device_info == NULL) { + printf("[BT_MESH_DEMO] Malloc pbt_mesh_device_info fail!\r\n"); + return; + } + + rtw_memcpy(pbt_mesh_device_info->dev_uuid, dev_uuid, 16); + pbt_mesh_device_info->last_scan_time = current_time; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] UUID = 0x"); + for (uint8_t j = 0; j < 16; j++) + printf("%02X", dev_uuid[j]); + printf(" malloc & add to unproed_dev_list in %s()!\r\n", __FUNCTION__); +#endif + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.unproed_dev_list); + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + } +} + +void update_proed_dev(uint16_t mesh_addr, uint8_t light_state) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint32_t current_time = os_sys_time_get(); + uint8_t active_flag = 0, inactive_flag = 0; + + if (stop_list_flushing_flag) { +#if 0 //BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] APP is processing, stop update proed dev to maintain the topology!\r\n"); +#endif + return; + } + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (pbt_mesh_device_info->mesh_addr == mesh_addr) { + active_flag = 1; + break; + } + + plist = get_next(plist); + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + if (active_flag) { + pbt_mesh_device_info->last_active_time = current_time; + pbt_mesh_device_info->light_state = light_state; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x update last_active_time in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + } else { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_inactive_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_inactive_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (pbt_mesh_device_info->mesh_addr == mesh_addr) { + inactive_flag = 1; + rtw_list_delete(plist); + pbt_mesh_device_info->last_active_time = current_time; + pbt_mesh_device_info->light_state = light_state; + pbt_mesh_device_info->active_state = 1; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_inactive_dev_list to proed_active_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_active_dev_list); + break; + } + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + if (!inactive_flag) { + pbt_mesh_device_info = (struct BT_MESH_DEVICE_INFO *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(struct BT_MESH_DEVICE_INFO)); + if (pbt_mesh_device_info == NULL) { + printf("[BT_MESH_DEMO] Malloc pbt_mesh_device_info fail!\r\n"); + return; + } + + pbt_mesh_device_info->mesh_addr = mesh_addr; + pbt_mesh_device_info->last_active_time = current_time; + pbt_mesh_device_info->light_state = light_state; + pbt_mesh_device_info->active_state = 1; + pbt_mesh_device_info->get_group_addr_flag = 1; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x malloc & add to proed_active_dev_list in %s()!\r\n", mesh_addr, __FUNCTION__); +#endif + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + list_flushing_handler(&pbt_mesh_device_info->list, GET_NODE_GROUP); + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_active_dev_list); + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + } + } +} + +void update_node_group(uint16_t mesh_addr, uint16_t group_addr) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t flag = 0; + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (pbt_mesh_device_info->mesh_addr == mesh_addr) { + flag = 1; + break; + } + + plist = get_next(plist); + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + if (flag) { + pbt_mesh_device_info->group_addr = group_addr; + pbt_mesh_device_info->get_group_addr_flag = 0; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x update Group Addr = 0x%x in %s()!\r\n", pbt_mesh_device_info->mesh_addr, pbt_mesh_device_info->group_addr, __FUNCTION__); +#endif + } +} + +/* RTW_BT_CMD_START_PROVISIONER */ +void bt_mesh_cmd_start_provisioner_handler(uint8_t *bt_mesh_event_value) +{ + uint8_t ret; + + if (bt_mesh_priv.provisioner_started_flag == _TRUE) { + *(bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH) = 2; + return; + } + + ret = bt_mesh_cmd_start_provisioner_api(); + if (ret == 1) + bt_mesh_priv.provisioner_started_flag = _TRUE; + + *(bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH) = ret; +} + +/* RTW_BT_CMD_GET_UNPROVISIONED_DEVICE */ +void bt_mesh_cmd_get_unprovisioned_device_handler(uint8_t *bt_mesh_event_value) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t num = 0; + uint8_t *pnum = bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH; + + bt_mesh_event_value += BT_MESH_EVENT_HEADER_LENGTH + 1; + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.unproed_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.unproed_dev_list, plist)) == _FALSE) { + if (num < 20) { + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + rtw_memcpy(bt_mesh_event_value, pbt_mesh_device_info->dev_uuid, 16); + bt_mesh_event_value += 16; + + num ++; + + plist = get_next(plist); + } else { + printf(" list is not large enough for more than 20 devices in %s()!\r\n", __FUNCTION__); + break; + } + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + *pnum = num; + bt_mesh_event_value = pnum - BT_MESH_EVENT_HEADER_LENGTH; +} + +/* RTW_BT_CMD_CONNECT_DEVICE */ +void bt_mesh_cmd_connect_device_pre_handler(uint8_t *dev_uuid) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.unproed_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.unproed_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (rtw_memcmp(pbt_mesh_device_info->dev_uuid, dev_uuid, 16) == 1) { + rtw_list_delete(plist); +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] UUID = 0x"); + for (uint8_t i = 0; i < 16; i++) + printf("%02X", dev_uuid[i]); + printf(" move from unproed_dev_list to processing_dev_list in %s()!\r\n", __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.processing_dev_list); + break; + } + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); +} + +void bt_mesh_cmd_connect_device_handler(void) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint16_t mesh_addr; + uint8_t light_state; + uint32_t current_time = os_sys_time_get(); + + plist = &bt_mesh_priv.processing_dev_list; + while (1) { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(plist); + if ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _TRUE) { + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + break; + } + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + pbt_mesh_device_info->connect_status = bt_mesh_cmd_connect_device_api(pbt_mesh_device_info->dev_uuid, &mesh_addr, &light_state); + if (pbt_mesh_device_info->connect_status == 1) { + pbt_mesh_device_info->mesh_addr = mesh_addr; + pbt_mesh_device_info->last_active_time = current_time; + pbt_mesh_device_info->light_state = light_state; + pbt_mesh_device_info->active_state = 1; + } + } +} + +void bt_mesh_cmd_connect_device_post_handler(uint8_t *bt_mesh_event_value) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t num = 0; + uint8_t *pnum = bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH; + + bt_mesh_event_value += BT_MESH_EVENT_HEADER_LENGTH + 1; + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.processing_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + rtw_memcpy(bt_mesh_event_value, pbt_mesh_device_info->dev_uuid, 16); + bt_mesh_event_value += 16; + + *bt_mesh_event_value = pbt_mesh_device_info->connect_status; + bt_mesh_event_value += 1; + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->mesh_addr; + bt_mesh_event_value += 2; + + *bt_mesh_event_value = pbt_mesh_device_info->light_state; + bt_mesh_event_value += 1; + + rtw_list_delete(plist); + if (pbt_mesh_device_info->connect_status == 1) { +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] UUID = 0x"); + for (uint8_t i = 0; i < 16; i++) + printf("%02X", pbt_mesh_device_info->dev_uuid[i]); + printf(" move from processing_dev_list to proed_active_dev_list in %s()!\r\n", __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_active_dev_list); + } else { +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] UUID = 0x"); + for (uint8_t j = 0; j < 16; j++) + printf("%02X", pbt_mesh_device_info->dev_uuid[j]); + printf(" move from processing_dev_list to unproed_dev_list in %s()!\r\n", __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.unproed_dev_list); + } + + num ++; + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + *pnum = num; + bt_mesh_event_value = pnum - BT_MESH_EVENT_HEADER_LENGTH; +} + +/* RTW_BT_CMD_DELETE_NODE */ +void bt_mesh_cmd_delete_node_pre_handler(uint16_t mesh_addr) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (pbt_mesh_device_info->mesh_addr == mesh_addr) { + rtw_list_delete(plist); +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_active_dev_list to processing_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.processing_dev_list); + break; + } + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); +} + +void bt_mesh_cmd_delete_node_handler(void) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + + plist = &bt_mesh_priv.processing_dev_list; + while (1) { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(plist); + if ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _TRUE) { + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + break; + } + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + pbt_mesh_device_info->delete_status = bt_mesh_cmd_delete_node_api(pbt_mesh_device_info->mesh_addr); + } +} + +void bt_mesh_cmd_delete_node_post_handler(uint8_t *bt_mesh_event_value) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t num = 0; + uint8_t *pnum = bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH; + + bt_mesh_event_value += BT_MESH_EVENT_HEADER_LENGTH + 1; + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.processing_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->mesh_addr; + bt_mesh_event_value += 2; + + *bt_mesh_event_value = pbt_mesh_device_info->delete_status; + bt_mesh_event_value += 1; + + rtw_list_delete(plist); + if (pbt_mesh_device_info->delete_status == 1) { +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x remove from processing_dev_list & free in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + os_mem_free((uint8_t *)pbt_mesh_device_info); + } else { +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from processing_dev_list to proed_active_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_active_dev_list); + } + + num ++; + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + *pnum = num; + bt_mesh_event_value = pnum - BT_MESH_EVENT_HEADER_LENGTH; +} + +/* RTW_BT_CMD_GET_NODE_STATUS */ +void bt_mesh_cmd_get_node_status_handler(uint8_t *bt_mesh_event_value) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t num = 0; + uint8_t *pnum = bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH; + + bt_mesh_event_value += BT_MESH_EVENT_HEADER_LENGTH + 1; + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + if (num < 20) { + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->mesh_addr; + bt_mesh_event_value += 2; + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->group_addr; + bt_mesh_event_value += 2; + + *bt_mesh_event_value = pbt_mesh_device_info->active_state; + bt_mesh_event_value += 1; + + *bt_mesh_event_value = pbt_mesh_device_info->light_state; + bt_mesh_event_value += 1; + + num ++; + + plist = get_next(plist); + } else { + printf(" list is not large enough for more than 20 devices in %s()!\r\n", __FUNCTION__); + break; + } + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_inactive_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_inactive_dev_list, plist)) == _FALSE) { + if (num < 20) { + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->mesh_addr; + bt_mesh_event_value += 2; + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->group_addr; + bt_mesh_event_value += 2; + + *bt_mesh_event_value = pbt_mesh_device_info->active_state; + bt_mesh_event_value += 1; + + *bt_mesh_event_value = pbt_mesh_device_info->light_state; + bt_mesh_event_value += 1; + + num ++; + + plist = get_next(plist); + } else { + printf(" list is not large enough for more than 20 devices in %s()!\r\n", __FUNCTION__); + break; + } + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + *pnum = num; + bt_mesh_event_value = pnum - BT_MESH_EVENT_HEADER_LENGTH; +} + +/* RTW_BT_CMD_SET_NODE_STATE */ +void bt_mesh_cmd_set_node_state_pre_handler(uint16_t mesh_addr, uint8_t light_state) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (MESH_IS_UNICAST_ADDR(mesh_addr)) { + if (pbt_mesh_device_info->mesh_addr == mesh_addr) { + rtw_list_delete(plist); + pbt_mesh_device_info->target_light_state = light_state; + pbt_mesh_device_info->set_node_state_flag = 0; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_active_dev_list to processing_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.processing_dev_list); + + break; + } + } else if (MESH_IS_GROUP_ADDR(mesh_addr)) { + if (pbt_mesh_device_info->group_addr == mesh_addr) { + rtw_list_delete(plist); + pbt_mesh_device_info->target_light_state = light_state; + pbt_mesh_device_info->set_node_state_flag = 1; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_active_dev_list to processing_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.processing_dev_list); + + } + } + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); +} + +void bt_mesh_cmd_set_node_state_handler(void) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t light_state; + + plist = &bt_mesh_priv.processing_dev_list; + while (1) { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(plist); + if ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _TRUE) { + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + break; + } + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + light_state = bt_mesh_cmd_set_node_state_api(pbt_mesh_device_info->mesh_addr, pbt_mesh_device_info->group_addr, pbt_mesh_device_info->target_light_state, pbt_mesh_device_info->set_node_state_flag); + if (light_state != 0xFF) { + pbt_mesh_device_info->light_state = light_state; + } + } +} + +void bt_mesh_cmd_set_node_state_post_handler(uint8_t *bt_mesh_event_value) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t num = 0; + uint8_t *pnum = bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH; + + bt_mesh_event_value += BT_MESH_EVENT_HEADER_LENGTH + 1; + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.processing_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _FALSE) { + if (num < 20) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->mesh_addr; + bt_mesh_event_value += 2; + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->group_addr; + bt_mesh_event_value += 2; + + *bt_mesh_event_value = pbt_mesh_device_info->active_state; + bt_mesh_event_value += 1; + + *bt_mesh_event_value = pbt_mesh_device_info->light_state; + bt_mesh_event_value += 1; + + rtw_list_delete(plist); +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from processing_dev_list to proed_active_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_active_dev_list); + + num ++; + + plist = plist_next; + } else { + printf(" list is not large enough for more than 20 devices in %s()!\r\n", __FUNCTION__); + break; + } + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + *pnum = num; + bt_mesh_event_value = pnum - BT_MESH_EVENT_HEADER_LENGTH; +} + +/* RTW_BT_CMD_SET_NODE_GROUP */ +void bt_mesh_cmd_set_node_group_pre_handler(uint16_t mesh_addr, uint16_t group_addr) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + if (pbt_mesh_device_info->mesh_addr == mesh_addr) { + rtw_list_delete(plist); + pbt_mesh_device_info->target_group_addr = group_addr; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_active_dev_list to processing_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.processing_dev_list); + break; + } + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); +} + +void bt_mesh_cmd_set_node_group_handler(void) +{ + _list *plist; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + + plist = &bt_mesh_priv.processing_dev_list; + while (1) { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(plist); + if ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _TRUE) { + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + break; + } + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + if (bt_mesh_cmd_set_node_group_api(pbt_mesh_device_info->mesh_addr, pbt_mesh_device_info->target_group_addr)) { + pbt_mesh_device_info->group_addr = pbt_mesh_device_info->target_group_addr; + } + } +} + +void bt_mesh_cmd_set_node_group_post_handler(uint8_t *bt_mesh_event_value) +{ + _list *plist, *plist_next; + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t num = 0; + uint8_t *pnum = bt_mesh_event_value + BT_MESH_EVENT_HEADER_LENGTH; + + bt_mesh_event_value += BT_MESH_EVENT_HEADER_LENGTH + 1; + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.processing_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.processing_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + pbt_mesh_device_info = LIST_CONTAINOR(plist, struct BT_MESH_DEVICE_INFO, list); + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->mesh_addr; + bt_mesh_event_value += 2; + + *((uint16_t *)bt_mesh_event_value) = pbt_mesh_device_info->group_addr; + bt_mesh_event_value += 2; + + *bt_mesh_event_value = pbt_mesh_device_info->active_state; + bt_mesh_event_value += 1; + + *bt_mesh_event_value = pbt_mesh_device_info->light_state; + bt_mesh_event_value += 1; + + rtw_list_delete(plist); +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from processing_dev_list to proed_active_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_active_dev_list); + + num ++; + + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + + *pnum = num; + bt_mesh_event_value = pnum - BT_MESH_EVENT_HEADER_LENGTH; +} + +thread_return bt_mesh_flushing_thread(thread_context context) +{ + /* avoid gcc compile warning */ + (void)context; + MESH_FLUSH_ITEM_S *pmeshFlushItem_s = NULL; + struct list_head *plist, *plist_next; + struct mesh_task_struct *pcmdtask = &(meshFlushingThread); + struct BT_MESH_DEVICE_INFO *pbt_mesh_device_info; + uint8_t light_state; + + printf("[BT_MESH_DEMO] %s(): mesh flushing thread enter !\r\n", __func__); + while(1) + { + if (os_sem_take(pcmdtask->wakeup_sema, 0xFFFFFFFF) == _FAIL) { + printf("[BT_MESH_DEMO] %s(): down wakeup_sema fail !\r\n", __func__); + break; + } + if (pcmdtask->blocked == _TRUE) { + printf("[BT_MESH_DEMO] %s(): blocked(%d) !\r\n", __func__, pcmdtask->blocked); + break; + } + pmeshFlushItem_s = (MESH_FLUSH_ITEM_S *)bt_mesh_dequeue_flush_event(); + if (!pmeshFlushItem_s) { + printf("[BT_MESH_DEMO] %s(): bt_mesh_dequeue_flush_event fail !\r\n", __func__); + goto _next; + } + switch (pmeshFlushItem_s->meshFlushEvent) { + case CONNECTION_CHECK_EVENT: + { + pbt_mesh_device_info = LIST_CONTAINOR(pmeshFlushItem_s->plist, struct BT_MESH_DEVICE_INFO, list); + light_state = bt_mesh_cmd_get_node_state_api(pbt_mesh_device_info->mesh_addr); + /* node really inactive */ + if (light_state == 0xFF) { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + if (plist == pmeshFlushItem_s->plist) { + rtw_list_delete(plist); + pbt_mesh_device_info->active_state = 0; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_active_dev_list to proed_inactive_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_inactive_dev_list); + break; + } + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + } + } + break; + + case COMBO_CHECK: + { + pbt_mesh_device_info = LIST_CONTAINOR(pmeshFlushItem_s->plist, struct BT_MESH_DEVICE_INFO, list); + light_state = bt_mesh_cmd_get_node_state_api(pbt_mesh_device_info->mesh_addr); + /* node really inactive */ + if (light_state == 0xFF) { + rtw_enter_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + plist = get_next(&bt_mesh_priv.proed_active_dev_list); + while ((rtw_end_of_queue_search(&bt_mesh_priv.proed_active_dev_list, plist)) == _FALSE) { + plist_next = get_next(plist); + if (plist == pmeshFlushItem_s->plist) { + rtw_list_delete(plist); + pbt_mesh_device_info->active_state = 0; +#if BT_MESH_APP_LIST_INTF_DEBUG + printf("[BT_MESH_DEMO] Mesh Addr = 0x%x move from proed_active_dev_list to proed_inactive_dev_list in %s()!\r\n", pbt_mesh_device_info->mesh_addr, __FUNCTION__); +#endif + rtw_list_insert_tail(&pbt_mesh_device_info->list, &bt_mesh_priv.proed_inactive_dev_list); + break; + } + plist = plist_next; + } + rtw_exit_critical_bh(&bt_mesh_priv.dev_list_lock, NULL); + } + bt_mesh_cmd_get_node_group_api(pbt_mesh_device_info->mesh_addr); + } + break; + + case GET_NODE_GROUP: + { + pbt_mesh_device_info = LIST_CONTAINOR(pmeshFlushItem_s->plist, struct BT_MESH_DEVICE_INFO, list); + bt_mesh_cmd_get_node_group_api(pbt_mesh_device_info->mesh_addr); + } + break; + + default: + { + printf("[BT_MESH_DEMO] %s(): meshFlushEvent %d not found !\r\n", __func__, pmeshFlushItem_s->meshFlushEvent); + } + break; + } + os_mem_free((uint8_t *)pmeshFlushItem_s); + +_next: + /* make sure os shedule can switch out */ + os_delay(10); + } + /* free all pmeshCmdItem_s resources */ + do{ + plist = bt_mesh_dequeue_flush_event(); + if (plist == NULL) { + break; + } + os_mem_free((uint8_t *)plist); + }while(1); + os_sem_give(pcmdtask->terminate_sema); + printf("[BT_MESH_DEMO] %s(): mesh_demo_flushing_thread exit !\r\n", __func__); + os_task_delete(NULL); +} + +uint8_t bt_mesh_demo_start_drv_thread(void) +{ + rtw_init_listhead(&btMeshFlushPriv.meshFlushList); + os_mutex_create(&btMeshFlushPriv.eventMutex); + meshFlushingThread.blocked = 0; + os_sem_create(&meshFlushingThread.wakeup_sema, 0, 0xffffffff); + os_sem_create(&meshFlushingThread.terminate_sema, 0, 0xffffffff); + if (os_task_create(&meshFlushingThread.task, "mesh_demo_flushing_thread", bt_mesh_flushing_thread, + NULL, 1024, 6) != true) { + meshFlushingThread.blocked = 1; + os_sem_delete(meshFlushingThread.wakeup_sema); + os_sem_delete(meshFlushingThread.terminate_sema); + printf("[BT_MESH_DEMO] %s(): create bt_mesh_flushing_thread fail !\r\n", __func__); + os_mutex_delete(btMeshFlushPriv.eventMutex); + + return 1; + } + return 0; +} + +void bt_mesh_demo_stop_drv_thread(void) +{ + meshFlushingThread.blocked = 1; + os_sem_give(meshFlushingThread.wakeup_sema); + os_sem_take(meshFlushingThread.terminate_sema, 0xFFFFFFFF); + os_sem_delete(meshFlushingThread.wakeup_sema); + os_sem_delete(meshFlushingThread.terminate_sema); + os_mutex_delete(btMeshFlushPriv.eventMutex); +} + +uint8_t bt_mesh_enqueue_flush_event(struct list_head *queue) +{ + os_mutex_take(btMeshFlushPriv.eventMutex, 0xFFFFFFFF); + rtw_list_insert_tail(queue, &btMeshFlushPriv.meshFlushList); + btMeshFlushPriv.eventListNum ++; + os_mutex_give(btMeshFlushPriv.eventMutex); + os_sem_give(meshFlushingThread.wakeup_sema); + + return 0; +} + +struct list_head *bt_mesh_dequeue_flush_event(void) +{ + struct list_head *queue = NULL; + + os_mutex_take(btMeshFlushPriv.eventMutex, 0xFFFFFFFF); + if (rtw_is_list_empty(&btMeshFlushPriv.meshFlushList)) { + printf("[BT_MESH_DEMO] %s(): btMeshFlushPriv.meshFlushList is empty !\r\n", __func__); + os_mutex_give(btMeshFlushPriv.eventMutex); + return NULL; + } else { + queue = get_next(&btMeshFlushPriv.meshFlushList); + rtw_list_delete(queue); + } + btMeshFlushPriv.eventListNum --; + os_mutex_give(btMeshFlushPriv.eventMutex); + + return queue; +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_broadcast_demo.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_broadcast_demo.c new file mode 100644 index 00000000..4600d964 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_broadcast_demo.c @@ -0,0 +1,213 @@ + +/* +* Broadcast thread for AmebaCam app +*/ +#include "platform_os.h" +#include "rtsp/rtsp_api.h" +#include "bt_mesh_broadcast_demo.h" +#include "sockets.h" +#include "lwip_netconf.h" //for LwIP_GetIP, LwIP_GetMAC +#include "netif.h" +#include "platform_os.h" +#include "os_task.h" +#if defined(CONFIG_PLATFORM_8195A) +#include "mmf_sink.h" +#endif + +extern struct netif xnetif[NET_IF_NUM]; +//extern u8 AmebaCam_device_name[256]; +char AmebaCam_device_name_demo[256] = {0}; + + +#if defined(CONFIG_PLATFORM_8195A) + #if ENABLE_PROXY_SEVER + msink_context *rtsp_sink; + #endif +#endif + + +void media_amebacam_broadcast_all_demo(void); +void *media_amebacam_broadcast_task = NULL; + +static void amebacam_broadcast_thread_all_demo(void *param) +{ + /* avoid gcc compile warning */ + (void)param; + int socket = -1; + int broadcast = 1; + struct sockaddr_in bindAddr; + uint16_t port = 49154; + unsigned char packet[32]; + int broadcast_retry_count = 5; + int i = 0; + + printf("amebacam_broadcast_thread_all_demo\r\n"); + // Create socket + if((socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf("ERROR: socket failed\n"); + goto exit; + } + + // Set broadcast socket option + if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0){ + printf("ERROR: setsockopt failed\n"); + goto exit; + } + + // Set the bind address + memset(&bindAddr, 0, sizeof(bindAddr)); + bindAddr.sin_family = AF_INET; + bindAddr.sin_port = htons(port); + bindAddr.sin_addr.s_addr = INADDR_ANY; + if(bind(socket, (struct sockaddr *) &bindAddr, sizeof(bindAddr)) < 0){ + printf("ERROR: bind failed\n"); + goto exit; + } + + + while(1) { + int sendLen; + struct sockaddr to; + struct sockaddr_in *to_sin = (struct sockaddr_in*) &to; + to_sin->sin_family = AF_INET; + to_sin->sin_port = htons(49153); + to_sin->sin_addr.s_addr = INADDR_BROADCAST; + sprintf((char*)packet, "wake_up"); + for(i=0;idrv_priv; + u8 proxy_suffix[256]; + memset(proxy_suffix, 0, 256); + sprintf(proxy_suffix, "%s_%d",AmebaCam_device_name_demo,rtsp_ctx->id); + #endif +#endif + mac = (uint8_t*) LwIP_GetMAC(&xnetif[0]); + + // Create socket + if((socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + printf("ERROR: Broadcast thread of AmebaCam failed socket failed\n\r"); + goto err; + } + + // Set broadcast socket option + if(setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)) < 0){ + printf("ERROR: setsockopt failed\n"); + goto err; + } + + // Set the bind address + memset(&bindAddr, 0, sizeof(bindAddr)); + bindAddr.sin_family = AF_INET; + bindAddr.sin_port = htons(port); + bindAddr.sin_addr.s_addr = INADDR_ANY; + if(bind(socket, (struct sockaddr *) &bindAddr, sizeof(bindAddr)) < 0){ + printf("ERROR: bind failed\n"); + goto err; + } + + + while(1) { + // Receive broadcast + int packetLen = 0; + struct sockaddr from; + struct sockaddr_in *from_sin = (struct sockaddr_in*) &from; + u32_t fromLen = sizeof(from); + + if((packetLen = recvfrom(socket, packet, sizeof(packet), 0, &from, &fromLen)) >= 0) { + uint8_t *ip = (uint8_t *) &from_sin->sin_addr.s_addr; + //uint16_t from_port = ntohs(from_sin->sin_port); + printf("Broadcast from AmebaCam App (%d.%d.%d.%d)\n\r",ip[0], ip[1], ip[2], ip[3]); + } + + // Send broadcast + if(packetLen > 0) { + int sendLen; + struct sockaddr to; + struct sockaddr_in *to_sin = (struct sockaddr_in*) &to; + to_sin->sin_family = AF_INET; + to_sin->sin_port = htons(port2); + to_sin->sin_addr.s_addr = from_sin->sin_addr.s_addr;//INADDR_ANY; +#if defined(CONFIG_PLATFORM_8195A) + #if ENABLE_PROXY_SEVER + sprintf((char*)broadcast_to_app, "%02x%02x%02x%02x%02x%02x;%d;%s;", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + rtsp_ctx->proxy_port,proxy_suffix); + #else + sprintf((char*)broadcast_to_app, "%02x%02x%02x%02x%02x%02x;0;%s;", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + AmebaCam_device_name_demo); + #endif +#else + sprintf((char*)broadcast_to_app, "%02x%02x%02x%02x%02x%02x;0;%s;", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + AmebaCam_device_name_demo); +#endif + sendLen = sendto(socket, broadcast_to_app, strlen((const char*)broadcast_to_app), 0, &to, sizeof(struct sockaddr)); + if( sendLen < 0) + printf("ERROR: Send Broadcast to AmebaCam App Fail\n\r"); + else + printf("Broadcast to AmebaCam App: %s\n\r",broadcast_to_app); + //printf("sendto - %d bytes to broadcast:%d, data: %s\n", sendLen, port2,broadcast_to_app); + } + } + +err: + printf("ERROR: Broadcast thread of AmebaCam failed\n"); + close(socket); + + os_task_delete(NULL); +} + +void media_amebacam_broadcast_all_demo(void) +{ + /*user can start their own task here*/ + if (os_task_create(&media_amebacam_broadcast_task, "amebacam_broadcast_all", amebacam_broadcast_thread_all_demo, + NULL, 2048, 1) != true) { + printf("\r\n media_amebacam_broadcast_all: Create Task Error\n"); + } +} + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.c new file mode 100644 index 00000000..de7d492c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.c @@ -0,0 +1,91 @@ +#include "stdio.h" +#include "osdep_service.h" +#include "bt_mesh_user_api.h" + +#include "bt_mesh_malloc_free.h" +#include "bt_mesh_provisioner_api.h" +#include "bt_mesh_app_user_cmd_parse.h" +#include "bt_mesh_timer_handler.h" +#include "bt_mesh_datatrans_write_api.h" + +void config_cmd_parsing (char ** argv) +{ + uint16_t SrcAddr = 0; + uint16_t DstAddr = 0; + uint16_t TestItemIndex = atoi(argv[3]); + uint16_t SendPacketNum = atoi(argv[4]); + uint16_t PacketInterval = atoi(argv[5]); + uint16_t DelayTime = atoi(argv[6]); + + SrcAddr = user_cmd_string2uint32(argv[1]); + DstAddr = user_cmd_string2uint32(argv[2]); + + u8 *cmd_array = NULL; + int cmd_length = 0xB; + cmd_array = (u8 *)bt_mesh_test_malloc(cmd_length); + + if (!cmd_array) { + printf("config_cmd_parsing malloc fail!\r\n"); + return; + } + + cmd_array[0] = Configure_Test_Item_Request; + cmd_array[1] = cmd_length; + cmd_array[2] = TestItemIndex; + cmd_array[3] = (DstAddr >> 8) & 0xFF; + cmd_array[4] = DstAddr & 0xFF; + cmd_array[5] = (SendPacketNum >> 8) & 0xFF; + cmd_array[6] = SendPacketNum & 0xFF; + cmd_array[7] = (PacketInterval >> 8) & 0xFF; + cmd_array[8] = PacketInterval & 0xFF; + cmd_array[9] = (DelayTime >> 8) & 0xFF; + cmd_array[10] = DelayTime & 0xFF; + + bt_mesh_cmd_datatrans_write_api(SrcAddr, cmd_array, cmd_length); + bt_mesh_test_free(cmd_array); +} + +plt_timer_t start_cmd_timer; +u8 *start_cmd_array = NULL; + +void start_cmd_parsing (char ** argv) +{ + int cmd_length = 2; + + start_cmd_array = (u8 *)bt_mesh_test_malloc(cmd_length); + + if (!start_cmd_array) { + printf("start_cmd_parsing malloc fail!\r\n"); + return; + } + + start_cmd_array[0] = Start_Test; + start_cmd_array[1] = cmd_length; + + start_cmd_timer = plt_timer_create("start_cmd_timer_timer", CMD_SEND_INTERVAL, true, 0, start_cmd_timer_handler); + + if (start_cmd_timer != NULL) { + plt_timer_start(start_cmd_timer, 0); + } +} + +void report_cmd_parsing (char ** argv) +{ + u8 *cmd_array = NULL; + int cmd_length = 3; + uint16_t TestItemIndex = atoi(argv[1]); + + cmd_array = (u8 *)bt_mesh_test_malloc(cmd_length); + + if (!cmd_array) { + printf("report_cmd_parsing malloc fail!\r\n"); + return; + } + + cmd_array[0] = Report_Test_Result_Request; + cmd_array[1] = cmd_length; + cmd_array[2] = TestItemIndex; + + bt_mesh_cmd_datatrans_write_api(0xffff, cmd_array, cmd_length); + bt_mesh_test_free(cmd_array); +} \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.h new file mode 100644 index 00000000..61c9811c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.h @@ -0,0 +1,19 @@ +#ifndef BT_MESH_APP_USER_CMD_PARSE_H +#define BT_MESH_APP_USER_CMD_PARSE_H + +enum { + Configure_Test_Item_Request, + Configure_Test_Item_Response, + Start_Test, + Report_Test_Result_Request, + Report_Test_Result_Response, + Test_Data_Packet, + Test_Data_Packet_Response, + Clear_Test_Result +}; + +void config_cmd_parsing(char ** argv); +void start_cmd_parsing(char ** argv); +void report_cmd_parsing(char ** argv); + +#endif /* BT_MESH_APP_USER_CMD_PARSE_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.c new file mode 100644 index 00000000..ae778cb6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.c @@ -0,0 +1,43 @@ +#include "osdep_service.h" +#include "bt_mesh_user_api.h" + +#if (defined(CONFIG_BT_MESH_DEVICE) && CONFIG_BT_MESH_DEVICE || \ + defined(CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE) +#include "bt_mesh_device_api.h" +#endif + +#if (defined(CONFIG_BT_MESH_PROVISIONER) && CONFIG_BT_MESH_PROVISIONER || \ + defined(CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE) +#include "bt_mesh_provisioner_api.h" +#endif + +#include "bt_mesh_datatrans_write_api.h" +#include "datatrans_model.h" +#include "mesh_node.h" + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + +void bt_mesh_cmd_datatrans_write_api(uint16_t mesh_addr, uint8_t * data_array, uint16_t data_len) +{ + PUSER_ITEM puserItem = NULL; + /* _datatrans_write */ + puserItem = bt_mesh_alloc_hdl(USER_API_ASYNCH); + + if (!puserItem) { + printf("bt_mesh_cmd_datatrans_write_api malloc fail!\r\n"); + return; + } + + puserItem->pparseValue->dw_parameter[0] = mesh_addr; + + for (uint16_t i = 0; i < data_len; i++) { + puserItem->pparseValue->dw_parameter[i + 1] = data_array[i]; + } + + puserItem->pparseValue->dw_parameter[data_len + 1] = 0; + puserItem->pparseValue->dw_parameter[data_len + 2] = 0; + puserItem->pparseValue->para_count = data_len + 3; + /* Packet sending API defined by Datatrans Model */ + bt_mesh_set_user_cmd(GEN_MESH_CODE(_datatrans_write), puserItem->pparseValue, NULL, puserItem); +} +#endif \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.h new file mode 100644 index 00000000..6dfebbe0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.h @@ -0,0 +1,6 @@ +#ifndef BT_MESH_DATATRANS_WRITE_H +#define BT_MESH_DATATRANS_WRITE_H + +void bt_mesh_cmd_datatrans_write_api(uint16_t mesh_addr, uint8_t * data_array, uint16_t data_len); + +#endif /* BT_MESH_DATATRANS_WRITE_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.c new file mode 100644 index 00000000..b9e9d793 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.c @@ -0,0 +1,241 @@ +#include "stdio.h" +#include +#include +#include "bt_mesh_user_api.h" + +#include "bt_mesh_malloc_free.h" +#include "bt_mesh_device_test.h" +#include "bt_mesh_app_user_cmd_parse.h" +#include "bt_mesh_timer_handler.h" +#include "bt_mesh_test_result.h" +#include "bt_mesh_receive_response.h" +#include "bt_mesh_datatrans_write_api.h" +#include "datatrans_app.h" + +struct BT_MESH_TEST_PARAMETER Bt_Mesh_Test_Parameter; +uint16_t Current_TestItemIndex = 0; + +static int judge_test_item_index (uint8_t * data_array); + +void init_bt_mesh_test_parameter (void) +{ + Bt_Mesh_Test_Parameter.TestItemIndex = 0; + Bt_Mesh_Test_Parameter.DstAddr = 0; + Bt_Mesh_Test_Parameter.SendPacketNum = 0; + Bt_Mesh_Test_Parameter.PacketInterval = 0; + Bt_Mesh_Test_Parameter.DelayTime = 0; +} + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + +int32_t cmd_data_receive (const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + datatrans_server_write_t * pdata = pargs; + uint16_t dst = pdata->src; + uint8_t * data_array = pdata->data; + uint16_t data_len = pdata->data_len; + + static bool test_start_flag = false; + int cmd_index = data_array[0]; + + /* The integrity test for the received packet */ + if (data_len != data_array[1]) { + printf("cmd_data_receive - Error Integrity Test"); + return 1; + } + + switch(cmd_index) { + case Configure_Test_Item_Request: + config_test_item_request_post(data_array); + send_config_test_item_response(dst); + test_start_flag = true; + break; + case Start_Test: + destroy_list(); + if (test_start_flag != true) { + printf("The test is being started!\n"); + return 1; + } + + start_test_post(); + test_start_flag = false; + break; + case Report_Test_Result_Request: + report_test_result_request_post(dst, data_array); + break; + case Test_Data_Packet: + // printf("I receive the packet, the length is %d\n", data_len); + + Current_TestItemIndex = judge_test_item_index(data_array); + if(Current_TestItemIndex == 0){ + printf("Packet is from %x, Index is %d\r\n", dst, 0); + } + else{ + printf("Packet is from %x, Index is %d, Seq num is %d\r\n", dst, Current_TestItemIndex, (data_array[3] << 8) | data_array[4]); + } + + if (data_array[2] == 0x1) { /* Need Reply */ + int response_cmd_length = 20; + u8 response_cmd_array[20] = {Test_Data_Packet_Response, 20, 0}; + bt_mesh_cmd_datatrans_write_api(dst, response_cmd_array, response_cmd_length); + } + + test_data_packet_post(dst, data_array); + break; + case Test_Data_Packet_Response: + printf("DstAddr response succeed!\n"); + break; + case Clear_Test_Result: + printf("Clear test result succeed!\n"); + destroy_list(); + break; + default: + printf("Receive the error cmd\n"); + break; + } + + return 0; +} +#endif + +void config_test_item_request_post (uint8_t * data_array) +{ + Bt_Mesh_Test_Parameter.TestItemIndex = data_array[2]; + Bt_Mesh_Test_Parameter.DstAddr = (data_array[3] << 8) | data_array[4]; + Bt_Mesh_Test_Parameter.SendPacketNum = (data_array[5] << 8) | data_array[6]; + Bt_Mesh_Test_Parameter.PacketInterval = (data_array[7] << 8) | data_array[8]; + Bt_Mesh_Test_Parameter.DelayTime = (data_array[9] << 8) | data_array[10]; + + printf("\n-----------Config Test Item Request--------------\n"); + printf("TestItemIndex is %d\n", Bt_Mesh_Test_Parameter.TestItemIndex); + printf("DstAddr is %X\n", Bt_Mesh_Test_Parameter.DstAddr); + printf("SendPacketNum is %d\n", Bt_Mesh_Test_Parameter.SendPacketNum); + printf("PacketInterval is %d\n", Bt_Mesh_Test_Parameter.PacketInterval); + printf("DelayTime is %d\n", Bt_Mesh_Test_Parameter.DelayTime); + printf("--------------------------------------------------\n"); +} + +void send_config_test_item_response (uint16_t dst) +{ + uint8_t *cmd_array = NULL; + int cmd_length = 3; + cmd_array = (uint8_t *)bt_mesh_test_malloc(cmd_length); + + if (!cmd_array) { + printf("send_config_test_item_response malloc fail!\r\n"); + return; + } + + cmd_array[0] = Configure_Test_Item_Response; + cmd_array[1] = cmd_length; + cmd_array[2] = Bt_Mesh_Test_Parameter.TestItemIndex; + + bt_mesh_cmd_datatrans_write_api(dst, cmd_array, cmd_length); + bt_mesh_test_free(cmd_array); +} + +extern Bt_Mesh_Test_Node_Point Bt_Mesh_Test_Result; + +void report_test_result_request_post (uint16_t dst, uint8_t * data_array) +{ + int Node_Num = link_list_length(); + uint16_t test_item_index = data_array[2]; + + if (Node_Num == 0) { + printf("This is an empty LinkList\n"); + return; + } + + if (Current_TestItemIndex != test_item_index) { + printf("You use the wrong test item index!!!\n"); + return; + } + + if (test_item_index > 2) { + printf("test_item_index is not allowed to larger than 2!!!\n"); + return; + } + + uint8_t * cmd_array = NULL; + int cmd_length = 1 + 1 + 1 + 4 * Node_Num; + cmd_array = (uint8_t *)bt_mesh_test_malloc(cmd_length); + + if (!cmd_array) { + printf("report_test_result_request_post malloc fail!\r\n"); + return; + } + + cmd_array[0] = Report_Test_Result_Response; + cmd_array[1] = cmd_length; + cmd_array[2] = test_item_index; + + obtain_data_from_link_list(cmd_array, test_item_index); + + bt_mesh_cmd_datatrans_write_api(dst, cmd_array, cmd_length); + bt_mesh_test_free(cmd_array); +} + +plt_timer_t start_test_timer; +u8 *start_test_array = NULL; + +void start_test_post () +{ + printf("You are the DeviceSrc\n"); + + uint16_t cmd_length = 0x3; + + if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x0) { + cmd_length = 0x3; + } else if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x1) { + cmd_length = 0x42; /* No Reply */ + } else if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x2) { + cmd_length = 0x42; /* Need Reply */ + } + + start_test_array = (uint8_t *)bt_mesh_test_malloc(cmd_length); + + if (!start_test_array) { + printf("start_test_post malloc fail!\r\n"); + return; + } + + start_test_array[0] = Test_Data_Packet; + start_test_array[1] = cmd_length; + start_test_array[2] = 0x0; + + if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x2) { + start_test_array[2] = 0x1; /* Need Reply */ + } + + start_test_timer = plt_timer_create("start_test_timer_handler", ORIGINAL_DELAY_TIME + Bt_Mesh_Test_Parameter.DelayTime, true, 0, start_test_timer_handler); + + if (start_test_timer != NULL) { + plt_timer_start(start_test_timer, 0); + } +} + +void test_data_packet_post (uint16_t dst, uint8_t * data_array) +{ + uint16_t test_item_index = 0; + test_item_index = judge_test_item_index(data_array); + + insert_dst_link_list (dst, test_item_index); +#if 0 + print_link_list(); +#endif +} + +static int judge_test_item_index (uint8_t * data_array) +{ + uint16_t test_item_index = 0; + + if (data_array[1] == 0x3) { + test_item_index = 0; + } else if ((data_array[1] == 0x42) && (data_array[2] == 0x0)) { + test_item_index = 1; + } else if ((data_array[1] == 0x42) && (data_array[2] == 0x1)) { + test_item_index = 2; + } + + return test_item_index; +} \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.h new file mode 100644 index 00000000..1cb30c5d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.h @@ -0,0 +1,29 @@ +#ifndef BT_MESH_DEVICE_TEST_H +#define BT_MESH_DEVICE_TEST_H + +#include "datatrans_model.h" +#include "mesh_node.h" + +struct BT_MESH_TEST_PARAMETER { + uint16_t DstAddr; // Address of Device_DST + uint16_t TestItemIndex; // Index of test item + uint16_t SendPacketNum; // Number of packets sent by Device_SRC + uint16_t PacketInterval; // Interval of packets sent by Device_SRC + uint16_t DelayTime; // Delay time of sending packets for Device_SRC +}; + +void init_bt_mesh_test_parameter(void); + +int32_t cmd_data_receive (const mesh_model_info_p pmodel_info, uint32_t type, void *pargs); + +void config_test_item_request_post(uint8_t * data_array); + +void send_config_test_item_response(uint16_t dst); + +void report_test_result_request_post(uint16_t dst, uint8_t * data_array); + +void start_test_post(); + +void test_data_packet_post(uint16_t dst, uint8_t * data_array); + +#endif /* BT_MESH_DEVICE_TEST_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.c new file mode 100644 index 00000000..5024a1d1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.c @@ -0,0 +1,14 @@ +#include "platform_os.h" +#include "bt_mesh_user_api.h" +#include "bt_mesh_malloc_free.h" + +void *bt_mesh_test_malloc(size_t size) +{ + void *ptr = (void *)os_mem_zalloc(RAM_TYPE_DATA_ON, size); + return ptr; +} + +void bt_mesh_test_free(void *ptr) +{ + os_mem_free((u8 *)ptr); +} diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.h new file mode 100644 index 00000000..3866ad19 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.h @@ -0,0 +1,7 @@ +#ifndef BT_MESH_MALLOC_FREE_H +#define BT_MESH_MALLOC_FREE_H + +void *bt_mesh_test_malloc(size_t size); +void bt_mesh_test_free(void *ptr); + +#endif /* BT_MESH_MALLOC_FREE_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.c new file mode 100644 index 00000000..ca5339e4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.c @@ -0,0 +1,63 @@ +#include +#include "bt_mesh_user_api.h" + +#include "bt_mesh_app_user_cmd_parse.h" +#include "bt_mesh_timer_handler.h" +#include "bt_mesh_datatrans_write_api.h" +#include "bt_mesh_receive_response.h" +#include "bt_mesh_device_test.h" + +#if defined(CONFIG_BT_MESH_TEST) && CONFIG_BT_MESH_TEST + +int32_t common_receive_response(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs) +{ + datatrans_server_write_t * pdata = pargs; + uint16_t source_address = pdata->src; + uint8_t * data_array = pdata->data; + uint16_t data_length = pdata->data_len; + + int cmd_index = data_array[0]; + + /* The integrity test for the received packet */ + if (data_length != data_array[1]) { + printf("common_receive_response - Error Integrity Test\n"); + return 1; + } + + switch(cmd_index) { + case Configure_Test_Item_Response: + printf("\n---------------------------------\n"); + printf("Node %X received the configure item\n", source_address); + printf("Configure Test Item Response\n"); + printf("---------------------------------\n"); + break; + case Report_Test_Result_Response: + printf("\nReport Test Result Response\n"); + printf("These data is from %X\n", source_address); + printf("TestItemIndex is %X\n", data_array[2]); + printf("---------------------------------\n"); + int Node_Num = (data_length - 3) / 4; + + for(int i = 0; i < Node_Num; i++) { + int Source_Address = 0; + int Packet_Num = 0; + + Source_Address = (data_array[3 + 4 * i + 0] << 8) | \ + data_array[3 + 4 * i + 1]; + Packet_Num = (data_array[3 + 4 * i + 2] << 8) | \ + data_array[3 + 4 * i + 3]; + + printf("Source_Address is %X\n", Source_Address); + printf("Packet_Num is %d\n", Packet_Num); + printf("---------------------------------\n"); + } + + int response_cmd_length = 2; + u8 response_cmd_array[2] = {Clear_Test_Result, 2}; + bt_mesh_cmd_datatrans_write_api(source_address, response_cmd_array, response_cmd_length); + break; + } + + return 0; +} +#endif \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.h new file mode 100644 index 00000000..23d532aa --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.h @@ -0,0 +1,8 @@ +#ifndef BT_MESH_RECEIVE_RESPONSE_H +#define BT_MESH_RECEIVE_RESPONSE_H + +#include "datatrans_model.h" + +int32_t common_receive_response(const mesh_model_info_p pmodel_info, uint32_t type, void *pargs); + +#endif /* BT_MESH_RECEIVE_RESPONSE_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.c new file mode 100644 index 00000000..495badae --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.c @@ -0,0 +1,171 @@ +#include "stdio.h" +#include +#include "bt_mesh_user_api.h" + +#include "bt_mesh_malloc_free.h" +#include "bt_mesh_app_user_cmd_parse.h" +#include "bt_mesh_device_test.h" +#include "bt_mesh_timer_handler.h" +#include "bt_mesh_test_result.h" + +Bt_Mesh_Test_Node_Point Bt_Mesh_Test_Result = NULL; + +static Bt_Mesh_Test_Node_Point find_node_link_list (Bt_Mesh_Test_Node_Point L, int x); + +_lock BT_MEST_TEST_LOCK; + +void insert_dst_link_list (uint16_t insert_num, uint16_t test_item_index) +{ + rtw_enter_critical_bh(&BT_MEST_TEST_LOCK, NULL); + + Bt_Mesh_Test_Node_Point q = NULL, p = NULL; + p = find_node_link_list(Bt_Mesh_Test_Result, insert_num); + + if (p == NULL) { + q = (Bt_Mesh_Test_Node_Point) bt_mesh_test_malloc (sizeof(Bt_Mesh_Test_Node)); + + if (!q) { + printf("insert_dst_link_list malloc fail!\r\n"); + rtw_exit_critical_bh(&BT_MEST_TEST_LOCK, NULL); + return; + } + + rtw_memset(q, 0, sizeof(Bt_Mesh_Test_Node)); + + q->SrcAddr = insert_num; + + switch (test_item_index) { + case 0: q->Test0_PacketNum = 1; break; + case 1: q->Test1_PacketNum = 1; break; + case 2: q->Test2_PacketNum = 1; break; + } + + q->next = Bt_Mesh_Test_Result->next; + Bt_Mesh_Test_Result->next = q; + } else { + switch (test_item_index) { + case 0: p->Test0_PacketNum++; break; + case 1: p->Test1_PacketNum++; break; + case 2: p->Test2_PacketNum++; break; + } + } + + rtw_exit_critical_bh(&BT_MEST_TEST_LOCK, NULL); +} + +Bt_Mesh_Test_Node_Point find_node_link_list (Bt_Mesh_Test_Node_Point L, int x) +{ + Bt_Mesh_Test_Node_Point p; + p = L; + + while (p->next && p->next->SrcAddr != x) { + p = p->next; + } + + if (p->next) { + return p->next; + } else { + return NULL; + } +} + +void destroy_list (void) +{ + rtw_enter_critical_bh(&BT_MEST_TEST_LOCK, NULL); + + Bt_Mesh_Test_Node_Point p = Bt_Mesh_Test_Result->next; + Bt_Mesh_Test_Node_Point q = Bt_Mesh_Test_Result->next; + + while (q != NULL) { + q = p->next; + Bt_Mesh_Test_Result->next = q; + printf("Destroy the node, SrcAddr in this node is %X\n", p->SrcAddr); + bt_mesh_test_free(p); + p = q; + } + + rtw_exit_critical_bh(&BT_MEST_TEST_LOCK, NULL); +} + +void print_link_list (void) +{ + rtw_enter_critical_bh(&BT_MEST_TEST_LOCK, NULL); + + Bt_Mesh_Test_Node_Point p; + p = Bt_Mesh_Test_Result->next; + + while (p) { + printf ("SrcAddr is %X\n", p->SrcAddr); + printf ("Test0_PacketNum is %d\n", p->Test0_PacketNum); + printf ("Test1_PacketNum is %d\n", p->Test1_PacketNum); + printf ("Test2_PacketNum is %d\n", p->Test2_PacketNum); + printf ("------------------\n" ); + p = p->next; + } + + rtw_exit_critical_bh(&BT_MEST_TEST_LOCK, NULL); +} + +int link_list_length (void) +{ + rtw_enter_critical_bh(&BT_MEST_TEST_LOCK, NULL); + + int num = 0; + Bt_Mesh_Test_Node_Point p; + p = Bt_Mesh_Test_Result->next; + + while (p) { + num++; + p = p->next; + } + + rtw_exit_critical_bh(&BT_MEST_TEST_LOCK, NULL); + + return num; +} + +void link_list_init () +{ + rtw_spinlock_init(&BT_MEST_TEST_LOCK); + + Bt_Mesh_Test_Result = (Bt_Mesh_Test_Node_Point) bt_mesh_test_malloc (sizeof(Bt_Mesh_Test_Node)); + + if (!Bt_Mesh_Test_Result) { + printf("link_list_init malloc fail!\r\n"); + return; + } + + rtw_memset(Bt_Mesh_Test_Result, 0, sizeof(Bt_Mesh_Test_Node)); + Bt_Mesh_Test_Result->next = NULL; + Bt_Mesh_Test_Result->SrcAddr = 0; +} + +void obtain_data_from_link_list (uint8_t * cmd_array, uint16_t test_item_index) +{ + rtw_enter_critical_bh(&BT_MEST_TEST_LOCK, NULL); + + Bt_Mesh_Test_Node_Point p; + p = Bt_Mesh_Test_Result->next; + + int Node_Index = 0; + + while (p) { + int Source_Address = p->SrcAddr; + int Packet_Num = 0; + + switch (test_item_index) { + case 0: Packet_Num = p->Test0_PacketNum; break; + case 1: Packet_Num = p->Test1_PacketNum; break; + case 2: Packet_Num = p->Test2_PacketNum; break; + } + + cmd_array[3 + 4 * Node_Index + 0] = (Source_Address >> 8) & 0xFF; + cmd_array[3 + 4 * Node_Index + 1] = Source_Address & 0xFF; + cmd_array[3 + 4 * Node_Index + 2] = (Packet_Num >> 8) & 0xFF; + cmd_array[3 + 4 * Node_Index + 3] = Packet_Num & 0xFF; + p = p->next; + Node_Index++; + } + + rtw_exit_critical_bh(&BT_MEST_TEST_LOCK, NULL); +} \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.h new file mode 100644 index 00000000..86d0bee6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.h @@ -0,0 +1,24 @@ +#ifndef BT_MESH_TEST_RESULT_H +#define BT_MESH_TEST_RESULT_H + +typedef struct Node { + uint16_t SrcAddr; + uint32_t Test0_PacketNum; + uint32_t Test1_PacketNum; + uint32_t Test2_PacketNum; + struct Node *next; +} Bt_Mesh_Test_Node, *Bt_Mesh_Test_Node_Point; + +void link_list_init(void); + +void insert_dst_link_list(uint16_t insert_num, uint16_t test_item_index); + +void print_link_list(void); + +int link_list_length(void); + +void destroy_list(void); + +void obtain_data_from_link_list (uint8_t * cmd_array, uint16_t test_item_index); + +#endif /* BT_MESH_TEST_RESULT_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.c b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.c new file mode 100644 index 00000000..7195ba60 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.c @@ -0,0 +1,60 @@ +#include "osdep_service.h" +#include "bt_mesh_malloc_free.h" +#include "bt_mesh_timer_handler.h" +#include "bt_mesh_datatrans_write_api.h" +#include "bt_mesh_device_test.h" + +extern struct BT_MESH_TEST_PARAMETER Bt_Mesh_Test_Parameter; + +extern plt_timer_t start_cmd_timer; +extern u8 *start_cmd_array; + +void start_cmd_timer_handler(void *FunctionContext) +{ + static u32 test_count = 0; + int cmd_length = 2; + + if (test_count < CMD_SEND_NUM) { + bt_mesh_cmd_datatrans_write_api(0xffff, start_cmd_array, cmd_length); + test_count++; + } else { + test_count = 0; + plt_timer_stop(start_cmd_timer, 0); + bt_mesh_test_free(start_cmd_array); + start_cmd_array = NULL; + } +} + +extern plt_timer_t start_test_timer; +extern u8 *start_test_array; + +void start_test_timer_handler(void *FunctionContext) +{ + uint16_t cmd_length = 0x3; + static u32 test_count = 0; + + if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x0) { + cmd_length = 0x3; + } else if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x1) { + cmd_length = 0x42; /* No Reply */ + } else if (Bt_Mesh_Test_Parameter.TestItemIndex == 0x2) { + cmd_length = 0x42; /* Need Reply */ + } + + if (test_count < Bt_Mesh_Test_Parameter.SendPacketNum) { + test_count++; + printf("Current test_count is %d\n", test_count); + if(cmd_length >= 5){ + start_test_array[3] = (test_count >> 8) & 0xFF; + start_test_array[4] = test_count & 0xFF; + } + bt_mesh_cmd_datatrans_write_api(Bt_Mesh_Test_Parameter.DstAddr, start_test_array, cmd_length); + plt_timer_change_period(start_test_timer, Bt_Mesh_Test_Parameter.PacketInterval, 0); + } else { + test_count = 0; + plt_timer_stop(start_test_timer, 0); + printf("\n--------------Send Finished-----------\n"); + bt_mesh_test_free(start_test_array); + start_test_array = NULL; + } +} \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.h b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.h new file mode 100644 index 00000000..9e398306 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.h @@ -0,0 +1,11 @@ +#ifndef BT_MESH_TIMER_HANDLER_H +#define BT_MESH_TIMER_HANDLER_H + +#define CMD_SEND_NUM 5 +#define CMD_SEND_INTERVAL 1000 +#define ORIGINAL_DELAY_TIME 10000 + +void start_cmd_timer_handler(void *FunctionContext); +void start_test_timer_handler(void *FunctionContext); + +#endif /* BT_MESH_TIMER_HANDLER_H */ \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client.h new file mode 100644 index 00000000..60bd3c2f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client.h @@ -0,0 +1,31 @@ +#ifndef _BT_OTA_CENTRAL_CLIENT_H_ +#define _BT_OTA_CENTRAL_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +#define SILENT_OTA 1 + +#if (SILENT_OTA == 1) +#define RCU_SILENT_OTA 0 //if target is bee2 rcu, then open RCU_SILENT_OTA +#endif + +#if (SILENT_OTA == 1) +#define ENABLE_SILENT_OTA_PRESS_TEST 0 +#else +#define ENABLE_NORMAL_OTA_PRESS_TEST 0 +#endif + +/* +0: filter by device addr in adv data and device name in scan response data; +1: filter by device addr in adv data; +others: filter by device name in scan response data. +*/ +#define DFU_MODE_FILTER_SCAN_INFO_STRATEGY 1 + +#define ONLY_SUPPORT_UPGRADE 0 +//#define TEMP_OTA_IMG_ADDR 0x00844000 //ota img load address + +#endif \ No newline at end of file diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.c new file mode 100644 index 00000000..bc04afd0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.c @@ -0,0 +1,1615 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file central_client_app.c + * @brief This file handles BLE central application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include "platform_opts_bt.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include "platform_stdlib.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dfu_client.h" +#include "ota_client.h" +#include "gaps_client.h" +#include "bas_client.h" +#include "data_uart.h" +#include "bt_ota_central_client.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT +#include "bt_ota_central_client_at_cmd.h" +#endif +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "gcs_client.h" +#include "insert_write.h" +#endif +/** @defgroup CENTRAL_CLIENT_APP Central Client Application + * @brief This file handles BLE central client application routines. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup CENTRAL_CLIIENT_CALLBACK + * @{ + */ +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +T_CLIENT_ID bt_ota_central_client_gcs_client_id; /**< general client id */ +#endif +T_CLIENT_ID bt_ota_central_client_gaps_client_id; /**< Gaps Services client client id */ +T_CLIENT_ID bt_ota_central_client_bas_client_id; /**< Battery Services client client id*/ +T_CLIENT_ID bt_ota_central_client_ota_client_id; /**< OTA Services client client id */ +T_CLIENT_ID bt_ota_central_client_dfu_client_id; /**< DFU Services client client id */ +/** @} */ /* End of group CENTRAL_CLIIENT_CALLBACK */ + +/** @defgroup CENTRAL_CLIENT_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE bt_ota_central_client_gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ + +bool is_entered_dfu_mode = false; +uint8_t g_conn_bd_addr[6] = {0}; /**< Bluetooth address of remote device. */ +T_GAP_REMOTE_ADDR_TYPE g_conn_addr_type = GAP_REMOTE_ADDR_LE_ANONYMOUS; /**< Address type of remote device. */ + +uint8_t g_ota_mac_addr[6]; +uint32_t g_patch_version = 0; +uint32_t g_patch_ext_version = 0; +uint32_t g_app_version = 0; +T_OTA_DEVICE_INFO g_ota_device_info; + +#if (SILENT_OTA == 1) +#if (RCU_SILENT_OTA == 1) +char remote_name[9] = {'B', 'e', 'e', '2', ' ', 'R', 'C', 'U', '\0'};//bee2 rcu device name +#else +char remote_name[11] = {'R', 'e', 'a', 'l', 'T', 'e', 'k', 'D', 'f', 'u', '\0'}; +#endif +#else +char remote_name[8] = {'B', 'L', 'E', '_', 'O', 'T', 'A', '\0'}; +char dfu_remote_name[7] = {'B', 'e', 'e', 'T', 'g', 't', '\0'}; +#endif + +/*============================================================================* + * Functions + *============================================================================*/ +void bt_ota_central_client_app_handle_gap_msg(T_IO_MSG *p_gap_msg); +void bt_ota_central_client_app_discov_services(uint8_t conn_id, bool start); + +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +/* user write request example */ +int client_write_data_example(uint8_t conn_id, uint16_t handle) +{ + uint8_t data[3] = {1,2,3}; + int ret = -1; + uint16_t length = 3; + + if(if_queue_in(0, conn_id, bt_ota_central_client_gcs_client_id, handle, length, data) == 0) + { + request_in_process_flag[conn_id] = 1; + ret = client_attr_write(conn_id, bt_ota_central_client_gcs_client_id, GATT_WRITE_TYPE_REQ, handle, length, data); + if(ret != 0) //if write fail + { + request_in_process_flag[conn_id] = 0; + printf("(conn_id %d) user write request(handle %x) fail, please check! ret=%d\r\n", conn_id, handle, ret); + } + } + + return ret; // return -1 -- add write request info to queue, 0 -- send write request success, others -- send write request fail +} +#endif + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_ota_central_client_app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + bt_ota_central_client_app_handle_gap_msg(&io_msg); + } + break; +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT + case IO_MSG_TYPE_AT_CMD: + { + uint16_t subtype = io_msg.subtype; + void *arg = io_msg.u.buf; + bt_ota_central_client_app_handle_at_cmd(subtype, arg); + } + break; +#endif +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + case IO_MSG_TYPE_QDECODE: + { + printf("at cmd send data\r\n"); + T_OTA_WRITE_MSG *ota_write_msg = (T_OTA_WRITE_MSG *)io_msg.u.buf; + uint8_t conn_id = ota_write_msg->conn_id; + uint16_t handle = ota_write_msg->handle; + client_write_data_example(conn_id, handle); + } + break; +#endif + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void bt_ota_central_client_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("bt_ota_central_client_app_handle_dev_state_evt: init state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, + new_state.gap_scan_state, cause); + if (bt_ota_central_client_gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + uint8_t bt_addr[6]; + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], + bt_addr[4], + bt_addr[3], + bt_addr[2], + bt_addr[1], + bt_addr[0]); + APP_PRINT_INFO6("bt addr 0x%x:%x:%x:%x:%x:%x", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + bt_ota_central_client_link_mgr_clear_device_list(); +#if (!(defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT)) + le_scan_start(); +#endif + } + } + + if (bt_ota_central_client_gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + data_uart_print("GAP scan start\r\n"); + } + } + + bt_ota_central_client_gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void bt_ota_central_client_app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("bt_ota_central_client_app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, bt_ota_central_client_app_link_table[conn_id].conn_state, new_state, disc_cause); + + bt_ota_central_client_app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("bt_ota_central_client_app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + + data_uart_print("Disconnect conn_id %d\r\n", conn_id); + memset(&bt_ota_central_client_app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + + /* Clear all key information */ + le_bond_clear_all_keys(); + +#if (SILENT_OTA == 1) +#if (ENABLE_SILENT_OTA_PRESS_TEST == 1) + T_GAP_CAUSE status = le_scan_start(); + if (GAP_CAUSE_SUCCESS != status) + { + APP_PRINT_INFO1("LE Scan start status: 0x%x", status); + } +#endif +#else + T_GAP_CAUSE status = le_scan_start(); + if (GAP_CAUSE_SUCCESS != status) + { + APP_PRINT_INFO1("LE Scan start status: 0x%x", status); + } +#endif +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + /* if disconnected during ota process, then need queue out and free memory */ + disconnect_and_queue_out(conn_id); +#endif + dfu_client_disconnect_cb(conn_id); + } + break; + + case GAP_CONN_STATE_CONNECTING: + { + APP_PRINT_INFO0("Connecting!"); + data_uart_print("Connecting! \r\n"); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + le_get_conn_addr(conn_id, bt_ota_central_client_app_link_table[conn_id].bd_addr, + (void *)&bt_ota_central_client_app_link_table[conn_id].bd_type); + APP_PRINT_INFO5("GAP_CONN_STATE_CONNECTED:remote_bd %s, remote_addr_type %d, conn_interval 0x%x, conn_latency 0x%x, conn_supervision_timeout 0x%x", + TRACE_BDADDR(bt_ota_central_client_app_link_table[conn_id].bd_addr), bt_ota_central_client_app_link_table[conn_id].bd_type, + conn_interval, conn_latency, conn_supervision_timeout); + data_uart_print("GAP_CONN_STATE_CONNECTED: Connected success conn_id %d\r\n", conn_id); + +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + /* after connected, init flag and queue*/ + connect_and_init(conn_id); +#endif + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + data_uart_print("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d\r\n", tx_phy, rx_phy); + } +#endif + + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void bt_ota_central_client_app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("bt_ota_central_client_app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("bt_ota_central_client_app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_print("Pair success\r\n"); + APP_PRINT_INFO0("bt_ota_central_client_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_print("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("bt_ota_central_client_app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("bt_ota_central_client_app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void bt_ota_central_client_app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("bt_ota_central_client_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); + data_uart_print("bt_ota_central_client_app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d\r\n", conn_id, mtu_size); +#if (RCU_SILENT_OTA == 1) + le_bond_pair(conn_id); +#endif +#if (!(defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT)) +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(if_queue_in(1, conn_id, 0, 0, 0, NULL) == 0) +#endif + { + bt_ota_central_client_app_discov_services(conn_id, true); + } +#endif +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void bt_ota_central_client_app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("bt_ota_central_client_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + data_uart_print("\n\rbt_ota_central_client_app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x \r\n", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("bt_ota_central_client_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + data_uart_print("\n\rbt_ota_central_client_app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x\r\n", + conn_id, cause); + + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("bt_ota_central_client_app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + data_uart_print("\n\rbt_ota_central_client_app_handle_conn_param_update_evt update pending: conn_id %d\r\n", conn_id); + + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void bt_ota_central_client_app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("bt_ota_central_client_app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + bt_ota_central_client_app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + bt_ota_central_client_app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + bt_ota_central_client_app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + bt_ota_central_client_app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + bt_ota_central_client_app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + printf("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + printf("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %06d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_OOB_INPUT: + { +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); +#if F_BT_LE_SMP_OOB_SUPPORT + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); +#endif + } + break; + + default: + APP_PRINT_ERROR1("bt_ota_central_client_app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group CENTRAL_CLIENT_GAP_MSG */ + +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT +void bt_ota_central_client_app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("ble_central_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); +// BLE_PRINT("ble_central_app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d\n\r", type, +// length - 1); + + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + BLE_PRINT("GAP_ADTYPE_FLAGS: 0x%x\n\r", flags); + + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_16BIT_XXX: 0x%x\n\r", *p_uuid); + p_uuid ++; + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid); + BLE_PRINT("GAP_ADTYPE_32BIT_XXX: 0x%x\n\r", (unsigned int)*p_uuid); + p_uuid ++; + + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + BLE_PRINT("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x\n\r", + (unsigned int)p_uuid[3], (unsigned int)p_uuid[2], (unsigned int)p_uuid[1], (unsigned int)p_uuid[0]); + + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + BLE_PRINT("GAP_ADTYPE_LOCAL_NAME_XXX: %s\n\r", buffer); + + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + BLE_PRINT("GAP_ADTYPE_POWER_LEVEL: 0x%x\n\r", scan_info->data[pos + 1]); + + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + BLE_PRINT("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x\n\r", *p_min, + *p_max); + + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d\n\r", *p_uuid, + data_len); + + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + BLE_PRINT("GAP_ADTYPE_APPEARANCE: %d\n\r", *p_appearance); + + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + BLE_PRINT("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d\n\r", + *p_company_id, data_len); + + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); +// BLE_PRINT(" AD Data: Unhandled Data = 0x%x\n\r", scan_info->data[pos + i]); + + } + } + break; + } + } + + pos += length; + } +} +#endif + +bool filter_scan_info_by_local_name(T_LE_SCAN_INFO *scan_info, uint8_t *p_remote_name) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + APP_PRINT_INFO0("filter_scan_info_by_local_name"); + data_uart_print("filter_scan_info_by_local_name.\r\n"); + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length < 1) || (length >= 31)) + { + return false; + } + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + + if (memcmp(buffer, p_remote_name, length - 1) == 0) + { + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + data_uart_print("GAP_ADTYPE_LOCAL_NAME_XXX: %s.\r\n", buffer); + return true; + } + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} + +bool filter_scan_info_by_mac_addr(T_LE_SCAN_INFO *scan_info, uint8_t *p_mac_addr) +{ + APP_PRINT_INFO0("filter_scan_info_by_mac_addr"); + data_uart_print("filter_scan_info_by_mac_addr.\r\n"); + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length < 1) || (length >= 31)) + { + return false; + } + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + if (memcmp(buffer + 2, p_mac_addr, length - 3) == 0) + { + APP_PRINT_INFO1("GAP_ADTYPE_MANUFACTURER_SPECIFIC: %s", TRACE_BDADDR(buffer + 2)); + data_uart_print("GAP_ADTYPE_MANUFACTURER_SPECIFIC: [%02x:%02x:%02x:%02x:%02x:%02x].\r\n", + buffer[7], buffer[6], buffer[5], buffer[4], buffer[3], buffer[2]); + return true; + } + + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} + + +/** @defgroup CENTRAL_CLIENT_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_ota_central_client_app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + char adv_type[20]; + char remote_addr_type[10]; + + switch (cb_type) + { + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + /* If you want to parse the scan info, please reference function ble_central_app_parse_scan_info. */ + sprintf(adv_type,"%s",(p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_UNDIRECTED)? "CON_UNDIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_DIRECTED)? "CON_DIRECT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCANNABLE)? "SCANABLE_UNDIRCT": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_NON_CONNECTABLE)? "NON_CONNECTABLE": + (p_data->p_le_scan_info->adv_type ==GAP_ADV_EVT_TYPE_SCAN_RSP)? "SCAN_RSP":"unknown"); + sprintf(remote_addr_type,"%s",(p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_PUBLIC)? "public": + (p_data->p_le_scan_info->remote_addr_type == GAP_REMOTE_ADDR_LE_RANDOM)? "random":"unknown"); + +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT + BLE_PRINT("ADVType\t\t\t| AddrType\t|%s\t\t\t|rssi\n\r","BT_Addr"); + BLE_PRINT("%s\t\t%s\t"BD_ADDR_FMT"\t%d\n\r",adv_type,remote_addr_type,BD_ADDR_ARG(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->rssi); + + bt_ota_central_client_app_parse_scan_info(p_data->p_le_scan_info); + break; +#endif + +#if (!(defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT)) + /*get first scan info: silent ota and normal ota is same but remote name is different*/ + if (!is_entered_dfu_mode) + { + if (filter_scan_info_by_local_name(p_data->p_le_scan_info, (uint8_t *)remote_name)) + { + APP_PRINT_INFO0("first scaned target!"); + APP_PRINT_INFO1("Found %s", TRACE_STRING(remote_name)); + le_scan_stop(); + ota_client_connect_device(p_data->p_le_scan_info); + bt_ota_central_client_link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type); + } + } + else + { + //entered dfu mode + /* + 0: filter by device addr in adv data and device name in scan response data; + 1: filter by device addr in adv data; + others: filter by device name in scan response data. + */ +#if (DFU_MODE_FILTER_SCAN_INFO_STRATEGY == 0) + APP_PRINT_INFO0("entered dfu mode 0."); + + if (filter_scan_info_by_mac_addr(p_data->p_le_scan_info, g_ota_mac_addr)) + { + APP_PRINT_INFO2("Found BDADDR:%s, remote_addr_type=%d", TRACE_BDADDR(g_ota_mac_addr), + p_data->p_le_scan_info->remote_addr_type); + //record connect bd addr and addr type + memcpy(g_conn_bd_addr, p_data->p_le_scan_info->bd_addr, 6); + g_conn_addr_type = p_data->p_le_scan_info->remote_addr_type; + } + + if (g_conn_addr_type != GAP_REMOTE_ADDR_LE_ANONYMOUS) + { + if ((memcmp(p_data->p_le_scan_info->bd_addr, g_conn_bd_addr, 6) == 0) && + g_conn_addr_type == p_data->p_le_scan_info->remote_addr_type) + { + if (filter_scan_info_by_local_name(p_data->p_le_scan_info, (uint8_t *)dfu_remote_name)) + { + APP_PRINT_INFO1("Found %s", TRACE_STRING(dfu_remote_name)); + APP_PRINT_INFO0("Found OTA device in DFU Mode!"); + le_scan_stop(); + dfu_client_connect_device(p_data->p_le_scan_info); + bt_ota_central_client_link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type); + } + } + } + +#elif (DFU_MODE_FILTER_SCAN_INFO_STRATEGY == 1) + APP_PRINT_INFO0("entered dfu mode 1."); + + if (filter_scan_info_by_mac_addr(p_data->p_le_scan_info, g_ota_mac_addr)) + { + APP_PRINT_INFO2("Found BDADDR:%s, remote_addr_type=%d", TRACE_BDADDR(g_ota_mac_addr), + p_data->p_le_scan_info->remote_addr_type); + APP_PRINT_INFO0("Found OTA device in DFU Mode!"); + le_scan_stop(); + dfu_client_connect_device(p_data->p_le_scan_info); + is_entered_dfu_mode = false; + bt_ota_central_client_link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type); + } +#else + APP_PRINT_INFO0("entered dfu mode others."); + if (filter_scan_info_by_local_name(p_data->p_le_scan_info, (uint8_t *)dfu_remote_name)) + { + APP_PRINT_INFO1("Found %s", TRACE_STRING(dfu_remote_name)); + APP_PRINT_INFO0("Found OTA device in DFU Mode!"); + le_scan_stop(); + dfu_client_connect_device(p_data->p_le_scan_info); + bt_ota_central_client_link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type); + } +#endif + } + break; +#endif + + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + data_uart_print("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + data_uart_print("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d\r\n", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; + + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + data_uart_print("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M\r\n"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + data_uart_print("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED\r\n"); + } + } + } + break; +#endif + + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation 0x%x, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + data_uart_print("GAP_MSG_LE_MODIFY_WHITE_LIST: operation 0x%x, cause 0x%x\r\n", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; + + default: + APP_PRINT_ERROR1("bt_ota_central_client_app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group CENTRAL_CLIENT_GAP_CALLBACK */ + + + + +/** @defgroup CENTRAL_SRV_DIS GATT Services discovery and storage + * @brief GATT Services discovery and storage + * @{ + */ +/** + * @brief Discovery GATT services + * @param conn_id connection ID. + * @param start first call. true - first call this function after conncection, false - not first + * @retval None + */ +void bt_ota_central_client_app_discov_services(uint8_t conn_id, bool start) +{ +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + request_in_process_flag[conn_id] = 1; //protect discovery service process +#endif + if (bt_ota_central_client_app_link_table[conn_id].conn_state != GAP_CONN_STATE_CONNECTED) + { + //DBG_DIRECT("ota_central_client_app_discov_services conn_id %d not connected ", conn_id); + APP_PRINT_ERROR1("bt_ota_central_client_app_discov_services: conn_id %d not connected ", conn_id); + data_uart_print("bt_ota_central_client_app_discov_services: conn_id %d not connected \n\r", conn_id); +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + request_in_process_flag[conn_id] = 0; +#endif + return; + } + if (start) + { +#if F_BT_GATT_SRV_HANDLE_STORAGE + bool is_disc = true; + T_APP_SRVS_HDL_TABLE app_srvs_table; + if (bt_ota_central_client_app_load_srvs_hdl_table(&app_srvs_table) == 0) + { + if ((app_srvs_table.srv_found_flags != 0) && + (app_srvs_table.bd_type == bt_ota_central_client_app_link_table[conn_id].bd_type) && + (memcmp(app_srvs_table.bd_addr, bt_ota_central_client_app_link_table[conn_id].bd_addr, GAP_BD_ADDR_LEN) == 0)) + { + APP_PRINT_INFO1("bt_ota_central_client_app_discov_services: load from flash, srv_found_flags 0x%x", + app_srvs_table.srv_found_flags); + bt_ota_central_client_app_link_table[conn_id].srv_found_flags = app_srvs_table.srv_found_flags; + if (app_srvs_table.srv_found_flags & APP_DISCOV_OTA_FLAG) + { + ota_client_set_hdl_cache(conn_id, app_srvs_table.ota_hdl_cache, + sizeof(uint16_t) * HDL_OTA_CACHE_LEN); + } + if (app_srvs_table.srv_found_flags & APP_DISCOV_DFU_FLAG) + { + dfu_client_set_hdl_cache(conn_id, app_srvs_table.dfu_hdl_cache, + sizeof(uint16_t) * HDL_DFU_CACHE_LEN); + } + if (app_srvs_table.srv_found_flags & APP_DISCOV_BAS_FLAG) + { + bas_set_hdl_cache(conn_id, app_srvs_table.bas_hdl_cache, sizeof(uint16_t) * HDL_BAS_CACHE_LEN); + } + is_disc = false; + } + } + else + { + APP_PRINT_ERROR0("bt_ota_central_client_app_load_srvs_hdl_table: failed"); + } + + if (is_disc) + { + if (gaps_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_ota_central_client_app_discov_services: discover gaps failed conn_id %d", conn_id); + } + } +#else + if (gaps_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_ota_central_client_app_discov_services: discover gaps failed conn_id %d", conn_id); + data_uart_print("bt_ota_central_client_app_discov_services: discover gaps failed conn_id %d\n\r", conn_id); + } +#endif + return; + } + + if ((bt_ota_central_client_app_link_table[conn_id].discovered_flags & APP_DISCOV_BAS_FLAG) == 0) + { + if (bas_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_ota_central_client_app_discov_services: discover bas failed conn_id %d", conn_id); + data_uart_print("bt_ota_central_client_app_discov_services: discover bas failed conn_id %d\n\r", conn_id); + } + } + else if ((bt_ota_central_client_app_link_table[conn_id].discovered_flags & APP_DISCOV_OTA_FLAG) == 0) + { + if (ota_client_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_ota_central_client_app_discov_services: discover ota failed conn_id %d", conn_id); + data_uart_print("bt_ota_central_client_app_discov_services: discover ota failed conn_id %d\n\r", conn_id); + } + } + else if ((bt_ota_central_client_app_link_table[conn_id].discovered_flags & APP_DISCOV_DFU_FLAG) == 0) + { + if (dfu_client_start_discovery(conn_id) == false) + { + APP_PRINT_ERROR1("bt_ota_central_client_app_discov_services: discover dfu failed conn_id %d", conn_id); + data_uart_print("bt_ota_central_client_app_discov_services: discover dfu failed conn_id %d\n\r", conn_id); + } + } + else + { + APP_PRINT_INFO2("bt_ota_central_client_app_discov_services: discover complete, conn_id %d, srv_found_flags 0x%x", + conn_id, bt_ota_central_client_app_link_table[conn_id].srv_found_flags); + data_uart_print("bt_ota_central_client_app_discov_services: discover complete, conn_id %d, srv_found_flags 0x%x\n\r", + conn_id, bt_ota_central_client_app_link_table[conn_id].srv_found_flags); +#if F_BT_GATT_SRV_HANDLE_STORAGE + if (bt_ota_central_client_app_link_table[conn_id].srv_found_flags != 0) + { + T_APP_SRVS_HDL_TABLE app_srvs_table; + memset(&app_srvs_table, 0, sizeof(T_APP_SRVS_HDL_TABLE)); + app_srvs_table.bd_type = bt_ota_central_client_app_link_table[conn_id].bd_type; + app_srvs_table.srv_found_flags = bt_ota_central_client_app_link_table[conn_id].srv_found_flags; + memcpy(app_srvs_table.bd_addr, bt_ota_central_client_app_link_table[conn_id].bd_addr, GAP_BD_ADDR_LEN); + ota_client_get_hdl_cache(conn_id, app_srvs_table.ota_hdl_cache, + sizeof(uint16_t) * HDL_OTA_CACHE_LEN); + dfu_client_get_hdl_cache(conn_id, app_srvs_table.dfu_hdl_cache, + sizeof(uint16_t) * HDL_DFU_CACHE_LEN); + bas_get_hdl_cache(conn_id, app_srvs_table.bas_hdl_cache, sizeof(uint16_t) * HDL_BAS_CACHE_LEN); + if (bt_ota_central_client_app_save_srvs_hdl_table(&app_srvs_table) != 0) + { + APP_PRINT_ERROR0("bt_ota_central_client_app_save_srvs_hdl_table: failed"); + } + } +#endif + } + + return; +} + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_ota_central_client_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("bt_ota_central_client_app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + } +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + else if (client_id == bt_ota_central_client_gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("(GCS_CLIENT) WRITE RESULT: cause 0x%x, handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + data_uart_print("(GCS_CLIENT) WRITE RESULT: cause 0x%x, handle 0x%x, type %d\n\r", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + + if (p_gcs_cb_data->cb_content.write_result.type == GATT_WRITE_TYPE_REQ) + { + request_in_process_flag[conn_id] = 0; + if_queue_out_and_send(conn_id); + } + break; + default: + break; + } + } +#endif + else if (client_id == bt_ota_central_client_gaps_client_id) + { + T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data; + switch (p_gaps_cb_data->cb_type) + { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_gaps_cb_data->cb_content.disc_state) + { + case DISC_GAPS_DONE: + bt_ota_central_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_GAPS_FLAG; + bt_ota_central_client_app_link_table[conn_id].srv_found_flags |= APP_DISCOV_GAPS_FLAG; + bt_ota_central_client_app_discov_services(conn_id, false); + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: discover gaps procedure done."); + break; + case DISC_GAPS_FAILED: + bt_ota_central_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_GAPS_FLAG; + bt_ota_central_client_app_discov_services(conn_id, false); + /* Discovery Request failed. */ + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: discover gaps request failed."); + break; + default: + break; + } + break; + case GAPS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_gaps_cb_data->cb_content.read_result.type) + { + case GAPS_READ_DEVICE_NAME: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.", + TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value)); + } + else + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_APPEARANCE: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance %d", + p_gaps_cb_data->cb_content.read_result.data.appearance); + } + else + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_CENTRAL_ADDR_RESOLUTION: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d", + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + } + else + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + default: + break; + } + break; + + default: + break; + } + } + else if (client_id == bt_ota_central_client_bas_client_id) + { + T_BAS_CLIENT_CB_DATA *p_bas_cb_data = (T_BAS_CLIENT_CB_DATA *)p_data; + switch (p_bas_cb_data->cb_type) + { + case BAS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_bas_cb_data->cb_content.disc_state) + { + case DISC_BAS_DONE: + /* Discovery BAS procedure successfully done. */ + bt_ota_central_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_BAS_FLAG; + bt_ota_central_client_app_link_table[conn_id].srv_found_flags |= APP_DISCOV_BAS_FLAG; + bt_ota_central_client_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: discover bas procedure done"); + break; + case DISC_BAS_FAILED: + /* Discovery Request failed. */ + bt_ota_central_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_BAS_FLAG; + bt_ota_central_client_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: discover bas procedure failed"); + break; + default: + break; + } + break; + case BAS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_bas_cb_data->cb_content.read_result.type) + { + case BAS_READ_BATTERY_LEVEL: + if (p_bas_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("BAS_READ_BATTERY_LEVEL: battery level %d", + p_bas_cb_data->cb_content.read_result.data.battery_level); + } + else + { + APP_PRINT_ERROR1("BAS_READ_BATTERY_LEVEL: failed cause 0x%x", + p_bas_cb_data->cb_content.read_result.cause); + } + break; + case BAS_READ_NOTIFY: + if (p_bas_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("BAS_READ_NOTIFY: notify %d", + p_bas_cb_data->cb_content.read_result.data.notify); + } + else + { + APP_PRINT_ERROR1("BAS_READ_NOTIFY: failed cause 0x%x", + p_bas_cb_data->cb_content.read_result.cause); + }; + break; + + default: + break; + } + break; + case BAS_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_bas_cb_data->cb_content.write_result.type) + { + case BAS_WRITE_NOTIFY_ENABLE: + APP_PRINT_INFO1("BAS_WRITE_NOTIFY_ENABLE: write result 0x%x", + p_bas_cb_data->cb_content.write_result.cause); + break; + case BAS_WRITE_NOTIFY_DISABLE: + APP_PRINT_INFO1("BAS_WRITE_NOTIFY_DISABLE: write result 0x%x", + p_bas_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + case BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + APP_PRINT_INFO1("BAS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: battery level %d", + p_bas_cb_data->cb_content.notify_data.battery_level); + break; + + default: + break; + } + } + else if (client_id == bt_ota_central_client_ota_client_id) + { + T_OTA_CLIENT_CB_DATA *p_ota_client_cb_data = (T_OTA_CLIENT_CB_DATA *)p_data; + uint16_t read_value_size = p_ota_client_cb_data->cb_content.read_result.data.value_size; + uint8_t *p_read_value = p_ota_client_cb_data->cb_content.read_result.data.p_value; + switch (p_ota_client_cb_data->cb_type) + { + case OTA_CLIENT_CB_TYPE_DISC_STATE: + switch (p_ota_client_cb_data->cb_content.disc_state) + { + case DISC_OTA_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + bt_ota_central_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_OTA_FLAG; + bt_ota_central_client_app_link_table[conn_id].srv_found_flags |= APP_DISCOV_OTA_FLAG; + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: discover ota procedure done."); + + //start read ota target device info + ota_client_read_by_handle(conn_id, OTA_READ_DEVICE_MAC); + //app_discov_services(conn_id, false); //start find dfu service + + break; + case DISC_OTA_FAILED: + /* Discovery Request failed. */ + bt_ota_central_client_app_link_table[conn_id].discovered_flags |= APP_DISCOV_OTA_FLAG; + bt_ota_central_client_app_discov_services(conn_id, false); + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: discover ota request failed."); + break; + default: + break; + } + break; + case OTA_CLIENT_CB_TYPE_READ_RESULT: + switch (p_ota_client_cb_data->cb_content.read_result.type) + { + case OTA_READ_DEVICE_MAC: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + if (read_value_size == sizeof(g_ota_mac_addr)) + { + memcpy(g_ota_mac_addr, p_read_value, read_value_size); + LE_ARRAY_TO_UINT32(g_patch_version, p_read_value); + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA Target MAC ADDR=%s", TRACE_BDADDR(g_ota_mac_addr)); + ota_client_read_by_handle(conn_id, OTA_READ_DEVICE_INFO); + } + else + { + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA_READ_DEVICE_MAC invalid read value size=%d", + read_value_size); + } + } + else + { + APP_PRINT_ERROR1("bt_ota_central_client_app_client_callback: Type OTA_READ_DEVICE_MAC failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + } + break; + case OTA_READ_PATCH_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + if (read_value_size == sizeof(g_patch_version)) + { + LE_ARRAY_TO_UINT32(g_patch_version, p_read_value); + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA Target patch version=0x%x", g_patch_version); + } + else + { + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA_READ_PATCH_VER invalid read value size=%d", + read_value_size); + } + } + else + { + APP_PRINT_ERROR1("bt_ota_central_client_app_client_callback: Type OTA_READ_PATCH_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_APP_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + if (read_value_size == sizeof(g_app_version)) + { + LE_ARRAY_TO_UINT32(g_app_version, p_read_value); + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA Target app version=0x%x", g_app_version); + } + else + { + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA_READ_APP_VER invalid read value size=%d", + read_value_size); + } + } + else + { + APP_PRINT_ERROR1("bt_ota_central_client_app_client_callback: Type OTA_READ_APP_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_PATCH_EXT_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + if (read_value_size == sizeof(g_patch_ext_version)) + { + LE_ARRAY_TO_UINT32(g_patch_ext_version, p_read_value); + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA Target patch ext version=0x%x", g_patch_ext_version); + } + else + { + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA_READ_PATCH_EXT_VER invalid read value size=%d", + read_value_size); + } + } + else + { + APP_PRINT_ERROR1("bt_ota_central_client_app_client_callback: Type OTA_READ_PATCH_EXT_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_DEVICE_INFO: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + if (read_value_size == sizeof(g_ota_device_info)) + { + memcpy((uint8_t *)&g_ota_device_info, p_read_value, read_value_size); + APP_PRINT_INFO4("bt_ota_central_client_app_client_callback: aesflg=%d, aesmode=%d,buffercheck=%d, maxbuffersize=%d", + g_ota_device_info.mode.aesflg, g_ota_device_info.mode.aesmode, + g_ota_device_info.mode.buffercheck, g_ota_device_info.maxbuffersize); + g_dfu_ctx.mode.value = g_ota_device_info.mode.value; +#if (SILENT_OTA == 1) + g_dfu_ctx.maxbuffersize = g_ota_device_info.maxbuffersize; + bt_ota_central_client_app_discov_services(conn_id, false); //start find dfu service +#else + g_dfu_ctx.maxbuffersize = NORMAL_OTA_MAX_BUFFER_SIZE; + if (ota_client_write_char(conn_id, OTA_WRITE_CMD)) + { + is_entered_dfu_mode = true; + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: is_entered_dfu_mode=%d", is_entered_dfu_mode); + } +#endif + } + else + { + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: OTA_READ_DEVICE_INFO invalid read value size=%d", + read_value_size); + } + } + else + { + APP_PRINT_ERROR1("bt_ota_central_client_app_client_callback: Type OTA_READ_DEVICE_INFO failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + case OTA_READ_IMG_VER: + if (p_ota_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: g_app_version 0x%x", g_app_version); + } + else + { + APP_PRINT_ERROR1("bt_ota_central_client_app_client_callback: Type OTA_READ_IMG_VER failed cause 0x%x", + p_ota_client_cb_data->cb_content.read_result.cause); + }; + break; + + default: + break; + } + break; + case OTA_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_ota_client_cb_data->cb_content.write_result.type) + { + case OTA_WRITE_CMD: + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: Type OTA_WRITE_CMD write result 0x%x", + p_ota_client_cb_data->cb_content.write_result.cause); + + break; + case OTA_WRITE_TEST_MODE: + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: Type OTA_WRITE_TEST_MODE write result 0x%x", + p_ota_client_cb_data->cb_content.write_result.cause); + break; + case OTA_WRITE_IMG_COUNTER: + APP_PRINT_INFO1("bt_ota_central_client_app_client_callback: Type OTA_WRITE_IMG_COUNTER write result 0x%x", + p_ota_client_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + case OTA_CLIENT_CB_TYPE_INVALID: + APP_PRINT_ERROR0("BT_OTA_CENTRAL_CLIENT_CB_TYPE_INVALID!"); + } + } + else if (client_id == bt_ota_central_client_dfu_client_id) + { + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback: dfu_client."); + T_DFU_CB_MSG *pmsg = (T_DFU_CB_MSG *)p_data; + switch (pmsg->type) + { + case DFU_CB_START: + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback--dfu_client_start."); + //dfu_client_start(); //just notify app do something + break; + case DFU_CB_FAIL: + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback--dfu_client_fail."); + //dfu_client_fail(); + break; + case DFU_CB_END: + APP_PRINT_INFO0("bt_ota_central_client_app_client_callback--dfu_client_end."); + //dfu_client_end(); + break; + default: + break; + } + } + + return result; +} +#endif +/** @} */ /* End of group CENTRAL_CLIENT_APP */ + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.h new file mode 100644 index 00000000..1b52fc95 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.h @@ -0,0 +1,88 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file central_client_app.h + * @brief This file handles BLE central client application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _BT_OTA_CENTRAL_CLIENT_APP_H_ +#define _BT_OTA_CENTRAL_CLIENT_APP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include + +#if 1 +#define BLE_PRINT printf +#define BD_ADDR_FMT "%02x:%02x:%02x:%02x:%02x:%02x" +#define BD_ADDR_ARG(x) (x)[5],(x)[4],(x)[3],(x)[2],(x)[1],(x)[0] +#define UUID_128_FORMAT "0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X:0x%2X" +#define UUID_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10],x[11],x[12],x[13],x[14],x[15] +#endif + + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_CLIENT_ID bt_ota_central_client_gaps_client_id; /**< Gaps Services client client id */ +extern T_CLIENT_ID bt_ota_central_client_bas_client_id; /**< Battery Services client client id*/ +extern T_CLIENT_ID bt_ota_central_client_ota_client_id; /**< OTA Services client client id */ +extern T_CLIENT_ID bt_ota_central_client_dfu_client_id; /**< DFU Services client client id */ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void bt_ota_central_client_app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_ota_central_client_app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +//T_APP_RESULT bt_ota_central_client_gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT bt_ota_central_client_app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_flags.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_flags.h new file mode 100644 index 00000000..4908f693 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_flags.h @@ -0,0 +1,51 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_OTA_CENTRAL_CLIENT_APP_FLAGS_H_ +#define _BT_OTA_CENTRAL_CLIENT_APP_FLAGS_H_ + +#include +#include + +#include + +/** @defgroup CENTRAL_CLIENT_Config Central Client App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#if defined(CONFIG_PLATFORM_8721D) +#define BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS 3 +#elif defined(CONFIG_PLATFORM_8710C) +#define BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS 1 +#endif + +/** @brief Config the discovery table number of gcs_client */ +#define BT_OTA_CENTRAL_CLIENT_APP_MAX_DISCOV_TABLE_NUM 40 + +/** @brief Config GATT services storage: 0-Not save, 1-Save to flash + * + * If configure to 1, the GATT services discovery results will save to the flash. + */ +#if 1 +#define F_BT_GATT_SRV_HANDLE_STORAGE 0 +#endif + +/** @} */ /* End of group CENTRAL_CLIENT_Config */ + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_main.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_main.c new file mode 100644 index 00000000..ab0b53da --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_main.c @@ -0,0 +1,303 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE central client project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace_uart.h" +#include +#include "wifi_constants.h" +#include +#include "rtk_coex.h" +#include "platform_stdlib.h" +#include +#include "dfu_client.h" +#include "ota_client.h" +#include "gaps_client.h" +#include "bas_client.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "gcs_client.h" +#endif +extern bool bt_trace_uninit(void); + +/** @defgroup CENTRAL_CLIENT_DEMO_MAIN Central Client Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default scan interval (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_INTERVAL 0x520 +/** @brief Default scan window (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_WINDOW 0x520 + + +uint8_t* bt_ota_central_client_image = NULL; //OTA IMAGE +uint8_t* bt_ota_central_client_key = NULL; // AES KEY + +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +extern T_CLIENT_ID bt_ota_central_client_gcs_client_id; +#endif +/*============================================================================* + * Functions + *============================================================================*/ +/** + * NOTE: OTA Image and AEK KEY + */ +bool bt_ota_central_client_set_image(uint8_t* image) +{ + if (image == NULL) { + printf("bt_ota_central_client_set_image: image is NULL\r\n"); + return false; + } + + bt_ota_central_client_image = image; + return true; +} + +bool bt_ota_central_client_set_key(uint8_t* key) +{ + if (key == NULL) { + printf("bt_ota_central_client_set_key: key is NULL\r\n"); + return false; + } + + bt_ota_central_client_key = key; + return true; +} + +uint8_t* bt_ota_central_client_get_image(void) +{ + return bt_ota_central_client_image; +} + +uint8_t* bt_ota_central_client_get_key(void) +{ + return bt_ota_central_client_key; +} + + +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +//extern void gap_config_hci_task_secure_context(uint32_t size); +void bt_ota_central_client_bt_stack_config_init(void) +{ + gap_config_max_le_link_num(BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); + gap_config_max_le_paired_device(BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); + //gap_config_hci_task_secure_context (280); +} + +/** + * @brief Initialize central and gap bond manager related parameters + * @return void + */ +void bt_ota_central_client_app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_OTA_CLIENT"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Scan parameters */ + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(bt_ota_central_client_app_gap_callback); + +#if F_BT_LE_5_0_SET_PHY_SUPPORT + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + uint8_t rx_phys_prefer = GAP_PHYS_PREFER_1M_BIT; + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_phys_prefer), &tx_phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_phys_prefer), &rx_phys_prefer); +#endif + +} + +/** + * @brief Add GATT clients and register callbacks + * @return void + */ +void bt_ota_central_client_app_le_profile_init(void) +{ +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + client_init(5); + bt_ota_central_client_gcs_client_id = gcs_add_client(bt_ota_central_client_app_client_callback, BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS, BT_OTA_CENTRAL_CLIENT_APP_MAX_DISCOV_TABLE_NUM); +#else + client_init(4); +#endif + bt_ota_central_client_gaps_client_id = gaps_add_client(bt_ota_central_client_app_client_callback, BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); + bt_ota_central_client_bas_client_id = bas_add_client(bt_ota_central_client_app_client_callback, BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); + bt_ota_central_client_ota_client_id = ota_add_client(bt_ota_central_client_app_client_callback, BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); + bt_ota_central_client_dfu_client_id = dfu_add_client(bt_ota_central_client_app_client_callback, BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); +} + + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Central Client APP, thus only one APP task is init here + * @return void + */ +void bt_ota_central_client_task_init(void) +{ + bt_ota_central_client_app_task_init(); +} + + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int bt_ota_central_client_app_main(void) +{ + bt_trace_init(); + bt_ota_central_client_bt_stack_config_init(); + bte_init(); + le_gap_init(BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS); + bt_ota_central_client_app_le_gap_init(); + bt_ota_central_client_app_le_profile_init(); + bt_ota_central_client_task_init(); + + return 0; +} + +int bt_ota_central_client_app_init(void) +{ + //int bt_stack_already_on = 0; + //(void) bt_stack_already_on; + T_GAP_DEV_STATE new_state; + + /*Wait WIFI init complete*/ + while(!(wifi_is_up(RTW_STA_INTERFACE) || wifi_is_up(RTW_AP_INTERFACE))) { + os_delay(1000); + } + + //judge BLE central is already on + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) { + //bt_stack_already_on = 1; + printf("[BT OTA Central Client]BT Stack already on\n\r"); + return 0; + } + else + bt_ota_central_client_app_main(); + + bt_coex_init(); + + /*Wait BT init complete*/ + do { + os_delay(100); + le_get_gap_param(GAP_PARAM_DEV_STATE , &new_state); + }while(new_state.gap_init_state != GAP_INIT_STATE_STACK_READY); + + return 0; +} + +extern void gaps_delete_client(void); +extern void bas_delete_client(void); +extern void ota_delete_client(void); +extern void dfu_delete_client(void); +void bt_ota_central_client_app_deinit(void) +{ + bt_ota_central_client_image = NULL; + bt_ota_central_client_key = NULL; + + bt_ota_central_client_app_task_deinit(); + T_GAP_DEV_STATE state; + le_get_gap_param(GAP_PARAM_DEV_STATE , &state); + if (state.gap_init_state != GAP_INIT_STATE_STACK_READY) { + printf("[BT OTA Central Client]BT Stack is not running\n\r"); + } +#if F_BT_DEINIT + else { +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + extern void gcs_delete_client(void); + gcs_delete_client(); +#endif + gaps_delete_client(); + bas_delete_client(); + ota_delete_client(); + dfu_delete_client(); + bte_deinit(); + bt_trace_uninit(); + printf("[BT OTA Central Client]BT Stack deinitalized\n\r"); + } +#endif +} +#endif +/** @} */ /* End of group CENTRAL_CLIENT_DEMO_MAIN */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.c new file mode 100644 index 00000000..7c13db7d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.c @@ -0,0 +1,139 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @defgroup CENTRAL_CLIENT_APP_TASK Central Client App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define BT_OTA_CENTRAL_CLIENT_APP_TASK_PRIORITY 1 //!< Task priorities +#define BT_OTA_CENTRAL_CLIENT_APP_TASK_STACK_SIZE 256 * 6 //!< Task stack size +#define BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_EVENT_MESSAGE (BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_GAP_MESSAGE + BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *bt_ota_central_client_app_task_handle; //!< APP Task handle +void *bt_ota_central_client_evt_queue_handle; //!< Event queue handle +void *bt_ota_central_client_io_queue_handle; //!< IO queue handle + +extern T_GAP_DEV_STATE bt_ota_central_client_gap_dev_state; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief Initialize App task + * @return void + */ +void bt_ota_central_client_app_task_init() +{ + os_task_create(&bt_ota_central_client_app_task_handle, "bt_ota_central_client_app", bt_ota_central_client_app_main_task, 0, BT_OTA_CENTRAL_CLIENT_APP_TASK_STACK_SIZE, + BT_OTA_CENTRAL_CLIENT_APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void bt_ota_central_client_app_main_task(void *p_param) +{ + (void) p_param; + uint8_t event; + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) + extern void osif_create_secure_context(uint32_t size); + osif_create_secure_context(configMINIMAL_SECURE_STACK_SIZE + 256); +#endif + + os_msg_queue_create(&bt_ota_central_client_io_queue_handle, BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&bt_ota_central_client_evt_queue_handle, BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(bt_ota_central_client_evt_queue_handle, bt_ota_central_client_io_queue_handle, BT_OTA_CENTRAL_CLIENT_MAX_NUMBER_OF_GAP_MESSAGE); + + data_uart_init(bt_ota_central_client_evt_queue_handle, bt_ota_central_client_io_queue_handle); + + while (true) + { + if (os_msg_recv(bt_ota_central_client_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(bt_ota_central_client_io_queue_handle, &io_msg, 0) == true) + { + bt_ota_central_client_app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +void bt_ota_central_client_app_task_deinit(void) +{ + if (bt_ota_central_client_app_task_handle) { + os_task_delete(bt_ota_central_client_app_task_handle); + } + if (bt_ota_central_client_io_queue_handle) { + os_msg_queue_delete(bt_ota_central_client_io_queue_handle); + } + if (bt_ota_central_client_evt_queue_handle) { + os_msg_queue_delete(bt_ota_central_client_evt_queue_handle); + } + bt_ota_central_client_io_queue_handle = NULL; + bt_ota_central_client_evt_queue_handle = NULL; + bt_ota_central_client_app_task_handle = NULL; + + bt_ota_central_client_gap_dev_state.gap_init_state = 0; + bt_ota_central_client_gap_dev_state.gap_adv_sub_state = 0; + bt_ota_central_client_gap_dev_state.gap_adv_state = 0; + bt_ota_central_client_gap_dev_state.gap_scan_state = 0; + bt_ota_central_client_gap_dev_state.gap_conn_state = 0; + +} + +/** @} */ /* End of group CENTRAL_CLIENT_APP_TASK */ +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.h new file mode 100644 index 00000000..aba06ae4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.h @@ -0,0 +1,27 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_OTA_CENTRAL_CLIENT_APP_TASK_H_ +#define _BT_OTA_CENTRAL_CLIENT_APP_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void bt_ota_central_client_app_task_init(void); +void bt_ota_central_client_app_main_task(void *p_param); +void bt_ota_central_client_app_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.c new file mode 100644 index 00000000..56d304d8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.c @@ -0,0 +1,217 @@ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT) && CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT +#include +#include +#include +#include +#include +#include +#include +#include "bt_ota_central_client_app.h" +#include "log_service.h" +#include "atcmd_bt.h" +#include "bt_ota_central_client_at_cmd.h" +#include "os_msg.h" +#include +#include "os_sched.h" +#include "os_mem.h" +#include "bt_ota_central_client_app_flags.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "insert_write.h" +#endif + +extern void *bt_ota_central_client_io_queue_handle; +extern void *bt_ota_central_client_evt_queue_handle; +extern T_GAP_DEV_STATE bt_ota_central_client_gap_dev_state; + +#define BD_ADDR_LEN 6 + + +static u8 ctoi(char c) +{ + if((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 0x0A); + } + + if((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 0x0A); + } + + if((c >= '0') && (c <= '9')) { + return (c - '0' + 0x00); + } + + return 0xFF; +} + +static u8 hex_str_to_bd_addr(u32 str_len, s8 *str, u8 *num_arr) +{ + num_arr += str_len/2 -1; + u32 n = 0; + u8 num = 0; + + if (str_len < 2) { + return FALSE; + } + while (n < str_len) { + if ((num = ctoi(str[n++])) == 0xFF) { + return FALSE; + } + *num_arr = num << 4; + if ((num = ctoi(str[n++])) == 0xFF) { + return FALSE; + } + *num_arr |= num; + num_arr--; + } + return TRUE; +} + + +void bt_ota_central_client_at_cmd_send_msg(uint16_t sub_type) +{ + uint8_t event = EVENT_IO_TO_APP; + + T_IO_MSG io_msg; + + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + + if (bt_ota_central_client_evt_queue_handle != NULL && bt_ota_central_client_io_queue_handle != NULL) { + if (os_msg_send(bt_ota_central_client_io_queue_handle, &io_msg, 0) == false) { + BLE_PRINT("bt ota central client at cmd send msg fail: subtype 0x%x", io_msg.subtype); + } else if (os_msg_send(bt_ota_central_client_evt_queue_handle, &event, 0) == false) { + BLE_PRINT("bt ota central client at cmd send event fail: subtype 0x%x", io_msg.subtype); + } + } +} + +int bt_ota_central_client_at_cmd_connect(int argc, char **argv) +{ + (void) argc; + u8 DestAddr[6] = {0}; + u8 DestAddrType = GAP_REMOTE_ADDR_LE_PUBLIC; +#if (F_BT_LE_USE_RANDOM_ADDR==1) + T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_RANDOM; +#elif (F_BT_LE_USE_RANDOM_ADDR==2) && F_BT_LE_LOCAL_IRK_SETTING_SUPPORT + T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_RANDOM; +#else + T_GAP_LOCAL_ADDR_TYPE local_addr_type = GAP_LOCAL_ADDR_LE_PUBLIC; +#endif + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + if(strcmp(argv[1], "P") == 0) + DestAddrType = GAP_REMOTE_ADDR_LE_PUBLIC; + else if(strcmp(argv[1], "R") == 0) + DestAddrType = GAP_REMOTE_ADDR_LE_RANDOM; + + if (strlen(argv[2]) != 2*BD_ADDR_LEN) + return -1; + + hex_str_to_bd_addr(strlen(argv[2]), ( s8 *)argv[2], (u8*)DestAddr); + + conn_req_param.scan_interval = 0xA0; //100ms + conn_req_param.scan_window = 0x80; //80ms + conn_req_param.conn_interval_min = 0x60; //120ms + conn_req_param.conn_interval_max = 0x60; //120ms + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + BLE_PRINT("cmd_con, DestAddr: 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\r\n", + DestAddr[5], DestAddr[4], DestAddr[3], DestAddr[2], DestAddr[1], DestAddr[0]); + + le_connect(0, DestAddr, (T_GAP_REMOTE_ADDR_TYPE)DestAddrType, local_addr_type, 1000); + + return 0; +} + + +int bt_ota_central_client_at_cmd_scan(int argc, char **argv) +{ + u8 scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + u8 scan_enable = 0; + static u8 scan_is_processing = 0; + + if (argc >= 2) { + scan_enable = atoi(argv[1]); + if (scan_enable == 1) { + if (argc == 3) + scan_filter_policy = atoi(argv[2]); + else if (argc == 4) { + scan_filter_policy = atoi(argv[2]); + scan_filter_duplicate = atoi(argv[3]); + } + } + } + + if (bt_ota_central_client_gap_dev_state.gap_init_state) + { + if (scan_enable) { + if (scan_is_processing) { + BLE_PRINT("Scan is processing, please stop it first\n\r"); + } else { + scan_is_processing = 1; + BLE_PRINT("Start scan, scan_filter_policy = %d, scan_filter_duplicate = %d\n\r", scan_filter_policy, scan_filter_duplicate); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), &scan_filter_duplicate); + le_scan_start(); + } + } else { + if (scan_is_processing) { + le_scan_stop(); + BLE_PRINT("Stop scan\n\r"); + scan_is_processing = 0; + } else + BLE_PRINT("There is no scan\n\r"); + } + } + return 0; +} + +extern void bt_ota_central_client_app_discov_services(uint8_t conn_id, bool start); +int bt_ota_central_client_at_cmd_ota_start(int argc, char **argv) +{ + int conn_id = atoi(argv[1]); +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(if_queue_in(1, conn_id, 0, 0, 0, NULL) == 0) +#endif + { + bt_ota_central_client_app_discov_services(conn_id, true); + } + + return 0; +} + + +int bt_ota_central_client_app_handle_at_cmd(uint16_t subtype, void *arg) +{ + int common_cmd_flag = 0; + int argc = 0; + char *argv[MAX_ARGC] = {0}; + + if (arg) { + argc = parse_param(arg, argv); + } + switch (subtype) { + case BT_ATCMD_SCAN: + bt_ota_central_client_at_cmd_scan(argc, argv); + break; + case BT_ATCMD_CONNECT: + bt_ota_central_client_at_cmd_connect(argc, argv); + break; + case BT_ATCMD_OTA_START: + bt_ota_central_client_at_cmd_ota_start(argc, argv); + break; + default: + break; + } + + return common_cmd_flag; +} +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.h new file mode 100644 index 00000000..31978640 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.h @@ -0,0 +1,15 @@ +#ifndef _BLE_OTA_CENTRAL_CLIENT_AT_CMD_H_ +#define _BLE_OTA_CENTRAL_CLIENT_AT_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int bt_ota_central_client_app_handle_at_cmd(uint16_t subtype, void *arg); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.c new file mode 100644 index 00000000..945874c6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.c @@ -0,0 +1,145 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include +#include +#include + +/*============================================================================* + * Constants + *============================================================================*/ +#if F_BT_GATT_SRV_HANDLE_STORAGE +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** @brief Define start offset of the falsh to save GATT Server information. */ +#define APP_SRVS_HDL_TABLE_FLASH_OFFSET 0 +/** @} */ /* End of group CENTRAL_SRV_DIS */ +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup CENTRAL_CLIENT_GAP_MSG + * @{ + */ +T_APP_LINK bt_ota_central_client_app_link_table[BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS]; +/** @} */ + +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +T_DEV_INFO bt_ota_central_client_dev_list[BT_OTA_CENTRAL_CLIENT_APP_MAX_DEVICE_INFO]; +uint8_t bt_ota_central_client_dev_list_count = 0; +/** @} */ + + +/*============================================================================* + * Functions + *============================================================================*/ +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool bt_ota_central_client_link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (bt_ota_central_client_dev_list_count < BT_OTA_CENTRAL_CLIENT_APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < bt_ota_central_client_dev_list_count; i++) + { + if (memcmp(bd_addr, bt_ota_central_client_dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(bt_ota_central_client_dev_list[bt_ota_central_client_dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + bt_ota_central_client_dev_list[bt_ota_central_client_dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + bt_ota_central_client_dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void bt_ota_central_client_link_mgr_clear_device_list(void) +{ + bt_ota_central_client_dev_list_count = 0; +} +/** @} */ + +#if F_BT_GATT_SRV_HANDLE_STORAGE +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** + * @brief Save GATT Services information into flash. + * @param[in] p_info the buffer for saving data + * @retval 0 Save success. + * @retval other Failed. + */ +uint32_t bt_ota_central_client_app_save_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info) +{ + APP_PRINT_INFO0("bt_ota_central_client_app_save_srvs_hdl_table"); + return ftl_save(p_info, APP_SRVS_HDL_TABLE_FLASH_OFFSET, sizeof(T_APP_SRVS_HDL_TABLE)); +} + +/** + * @brief load GATT Services information from storage + * @param[out] p_info the buffer for loading data + * @retval 0 Load success. + * @retval other Failed. + */ +uint32_t bt_ota_central_client_app_load_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info) +{ + uint32_t result; + result = ftl_load(p_info, APP_SRVS_HDL_TABLE_FLASH_OFFSET, + sizeof(T_APP_SRVS_HDL_TABLE)); + APP_PRINT_INFO1("bt_ota_central_client_app_load_srvs_hdl_table: result %u", result); + if (result) + { + memset(p_info, 0, sizeof(T_APP_SRVS_HDL_TABLE)); + } + return result; +} +/** @} */ +#endif + +#endif + +/** @} */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.h new file mode 100644 index 00000000..6794e502 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.h @@ -0,0 +1,105 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _BT_OTA_CENTRAL_CLIENT_LINK_MANAGER_H_ +#define _BT_OTA_CENTRAL_CLIENT_LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +/** @defgroup APP_DISCOV_BITS Application discover services Bits +* @{ + */ +#define APP_DISCOV_GAPS_FLAG 0x01 +#define APP_DISCOV_BAS_FLAG 0x02 +#define APP_DISCOV_OTA_FLAG 0x04 +#define APP_DISCOV_DFU_FLAG 0x08 + +/** @brief Define device list table size. */ +#define BT_OTA_CENTRAL_CLIENT_APP_MAX_DEVICE_INFO 6 + +/*============================================================================* + * Constants + *============================================================================*/ +/** @addtogroup CENTRAL_CLIENT_GAP_MSG + * @{ + */ +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + uint8_t discovered_flags; /**< discovered flags. */ + uint8_t srv_found_flags; /**< service founded flogs. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; +/** @} */ /* End of group CENTRAL_CLIENT_GAP_MSG */ + +#if F_BT_GATT_SRV_HANDLE_STORAGE +/** @addtogroup CENTRAL_SRV_DIS + * @{ + */ +/** @brief App link table */ +typedef struct +{ + uint8_t srv_found_flags; + uint8_t bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint32_t reserved; + uint16_t ota_hdl_cache[HDL_OTA_CACHE_LEN]; + uint16_t dfu_hdl_cache[HDL_DFU_CACHE_LEN]; + uint16_t bas_hdl_cache[HDL_BAS_CACHE_LEN]; +} T_APP_SRVS_HDL_TABLE; +/** @} */ +#endif + +/** @addtogroup CENTRAL_CLIENT_SCAN_MGR + * @{ + */ +/** + * @brief Device list block definition. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/** @} */ + +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK bt_ota_central_client_app_link_table[BT_OTA_CENTRAL_CLIENT_APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO bt_ota_central_client_dev_list[BT_OTA_CENTRAL_CLIENT_APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t bt_ota_central_client_dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool bt_ota_central_client_link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void bt_ota_central_client_link_mgr_clear_device_list(void); + +#if F_BT_GATT_SRV_HANDLE_STORAGE +uint32_t bt_ota_central_client_app_save_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info); +uint32_t bt_ota_central_client_app_load_srvs_hdl_table(T_APP_SRVS_HDL_TABLE *p_info); +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_test_image.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_test_image.c new file mode 100644 index 00000000..0d72ac61 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_test_image.c @@ -0,0 +1,1628 @@ +/* + C-file generated by Bin2C + Compiled: Aug 9 2004 at 15:18:55 + + Copyright (C) 2004 + Segger Microcontroller Systeme GmbH + www.segger.com + + Solutions for real time microcontroller applications +*/ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include "bt_ota_central_client.h" +unsigned char rtl8762c_aes256_key[32] = +{ + 0x1a, 0x60, 0x8e, 0x11, 0xd3, 0x4c, 0x0d, 0x96, + 0x70, 0x7e, 0x7a, 0x80, 0xdf, 0x63, 0x67, 0x1f, + 0xfb, 0x10, 0xf6, 0xd1, 0x0c, 0x1a, 0x97, 0x9a, + 0xe2, 0x29, 0x2b, 0x09, 0xc5, 0xf8, 0x46, 0x4e +}; + +unsigned char rtl8762c_image[] = +#if (RCU_SILENT_OTA == 1) //rcu silent ota test image +{ + 0x05, 0x00, 0x01, 0x01, 0x93, 0x27, 0x00, 0x00, + 0x68, 0x98, 0x00, 0x00, 0x6D, 0x67, 0xDE, 0xF1, 0x3E, 0x33, 0xE8, 0x11, 0xB1, 0x02, 0x4D, 0x2D, 0xF4, 0x0C, 0xDE, 0x01, 0x00, 0xE4, 0x80, 0x00, 0x00, 0xE4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x00, 0x08, 0x50, 0x43, 0x46, 0x1E, 0x73, 0x64, 0x6B, 0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF5, 0xF8, 0x85, 0xED, 0x47, 0xD3, 0x1F, 0xC7, 0x59, 0x67, 0xC2, 0xDE, 0x7D, 0x87, 0x95, 0xC5, 0x9B, 0x32, 0x02, 0x63, 0xC8, 0x0D, 0xCA, 0x77, 0x60, 0x0B, 0x6C, 0x99, 0xAF, 0x18, 0xEB, 0xD1, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD1, 0x85, 0x0E, 0x60, 0xE2, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x00, 0x47, 0x5F, 0xE5, 0x80, 0x00, 0xAF, 0xF3, 0x00, 0x80, 0x0D, 0xF6, 0xF8, 0xF5, 0x10, 0xB5, 0x7D, 0x4A, 0x7D, 0x49, 0x7E, 0x48, + 0x4B, 0xF4, 0x3F, 0xF5, 0x7D, 0x4A, 0x7E, 0x49, 0x7E, 0x48, 0x4B, 0xF4, 0x3A, 0xF5, 0x7E, 0x49, 0x7E, 0x48, 0x4B, 0xF4, 0xF7, 0xF5, 0x7E, 0x4A, 0x7E, 0x49, 0x7F, 0x48, 0x4B, 0xF4, 0x31, 0xF5, 0x7E, 0x4A, 0x7F, 0x49, 0x7F, 0x48, 0x4B, 0xF4, + 0x2C, 0xF5, 0xBD, 0xE8, 0x10, 0x40, 0x7E, 0x49, 0x7E, 0x48, 0x4B, 0xF4, 0xE7, 0xB5, 0x7F, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF0, 0xE9, 0xE0, 0x12, 0x11, 0x44, 0x80, 0x68, 0x10, 0x22, 0x0D, 0x18, 0x29, 0x46, 0x68, 0x46, 0x4B, 0xF4, 0x19, 0xF5, + 0x10, 0x22, 0x69, 0x46, 0x00, 0x20, 0xF8, 0xF7, 0xB1, 0xDF, 0x75, 0x49, 0xD1, 0xF8, 0x7C, 0x11, 0x74, 0x4E, 0x60, 0xF3, 0x1F, 0x41, 0x4F, 0xF0, 0xFF, 0x30, 0xF1, 0x60, 0xF9, 0xF7, 0x95, 0xD9, 0xF1, 0x68, 0x48, 0x43, 0xF0, 0x60, 0x0F, 0xF6, + 0x95, 0xF3, 0x00, 0x24, 0x0D, 0xF6, 0xBE, 0xF5, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0x04, 0x2C, 0xF8, 0xDB, 0x0D, 0xF6, 0xB7, 0xF5, 0xF0, 0x60, 0x7F, 0xBD, 0x70, 0xB5, 0x68, 0x4D, 0x69, 0x49, 0x69, 0x4C, 0x28, 0x68, 0x4F, 0xF0, 0x00, 0x02, + 0xB1, 0xEB, 0x00, 0x2F, 0x05, 0xD0, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x65, 0x49, 0xF9, 0xF7, 0xCA, 0x9A, 0x00, 0x21, 0x45, 0xF2, 0x06, 0x00, 0xFD, 0xF7, 0xCF, 0xDD, 0x10, 0xF0, 0xFF, 0x03, 0x03, 0xD0, 0x60, 0x49, 0x01, 0x22, 0x1C, 0x31, + 0x04, 0xE0, 0x28, 0x68, 0x5D, 0x49, 0x03, 0x0E, 0x01, 0x22, 0x50, 0x31, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xF9, 0xF7, 0xB4, 0x9A, 0x38, 0xB5, 0x72, 0xB6, 0xFF, 0xF7, 0xD6, 0xFF, 0xFF, 0xF7, 0x87, 0xFF, 0xFF, 0xF7, 0xA4, 0xFF, 0x00, 0x20, + 0xFD, 0xF5, 0x7C, 0xF1, 0x16, 0x20, 0xFA, 0xF5, 0x3E, 0xF2, 0x17, 0x20, 0xFA, 0xF5, 0x3B, 0xF2, 0x51, 0xA1, 0x1F, 0x20, 0x4B, 0xF4, 0x6A, 0xF4, 0x4F, 0xF0, 0x05, 0x55, 0x4F, 0xA1, 0x28, 0x46, 0xF9, 0xF7, 0x9F, 0xDC, 0x04, 0x46, 0x54, 0xA1, + 0x28, 0x46, 0xF9, 0xF7, 0x9A, 0xDC, 0x03, 0x46, 0x48, 0x49, 0x47, 0x48, 0x02, 0x22, 0x7C, 0x31, 0x80, 0x1E, 0x00, 0x94, 0xF9, 0xF7, 0x8B, 0xDA, 0xFA, 0xF5, 0x2C, 0xF2, 0x4E, 0x48, 0x00, 0x68, 0x00, 0x28, 0x03, 0xD0, 0x01, 0xB0, 0xBD, 0xE8, + 0x30, 0x40, 0x00, 0x47, 0x38, 0xBD, 0x10, 0xB5, 0xFE, 0xF7, 0xFE, 0xD8, 0x00, 0x28, 0x4D, 0xD1, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0xDC, 0x12, 0xC9, 0x07, 0x47, 0xD0, 0xAF, 0xF2, 0x81, 0x01, 0x44, 0x4A, 0x11, 0x60, 0x45, 0x4A, 0x44, 0x49, + 0x11, 0x60, 0x4F, 0xF4, 0x34, 0x41, 0xC0, 0xF8, 0x84, 0x13, 0x44, 0xF6, 0xF0, 0x71, 0xC0, 0xF8, 0x88, 0x13, 0x41, 0x49, 0xC0, 0xF8, 0xCC, 0x13, 0x90, 0xF8, 0x4D, 0x13, 0x41, 0xF0, 0x08, 0x01, 0x80, 0xF8, 0x4D, 0x13, 0x06, 0x21, 0x80, 0xF8, + 0x4F, 0x13, 0x90, 0xF8, 0x78, 0x23, 0x90, 0xF8, 0x9A, 0x13, 0x42, 0xF0, 0x26, 0x02, 0x80, 0xF8, 0x78, 0x23, 0x21, 0xF0, 0x21, 0x01, 0x80, 0xF8, 0x9A, 0x13, 0x90, 0xF8, 0x34, 0x13, 0x1F, 0x22, 0x21, 0xF0, 0x01, 0x01, 0x80, 0xF8, 0x34, 0x13, + 0x90, 0xF8, 0x7A, 0x13, 0x80, 0xF8, 0x79, 0x23, 0x41, 0xF0, 0xDF, 0x01, 0x80, 0xF8, 0x7A, 0x13, 0x90, 0xF8, 0xC3, 0x13, 0x21, 0xF0, 0xC0, 0x01, 0x80, 0xF8, 0xC3, 0x13, 0xF0, 0x21, 0x80, 0xF8, 0x20, 0x13, 0x3C, 0x21, 0x80, 0xF8, 0x21, 0x13, + 0xC8, 0x21, 0x80, 0xF8, 0x22, 0x13, 0xFF, 0x21, 0x80, 0xF8, 0x23, 0x13, 0x10, 0xBD, 0x00, 0x00, 0xE0, 0x69, 0x00, 0x00, 0x90, 0xE7, 0x80, 0x00, 0x00, 0x7C, 0x20, 0x00, 0xAC, 0x01, 0x00, 0x00, 0x70, 0x51, 0x81, 0x00, 0xE0, 0xE5, 0x20, 0x00, + 0xCC, 0x31, 0x00, 0x00, 0x8C, 0xE7, 0x20, 0x00, 0x4C, 0x29, 0x00, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x00, 0xC0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x7C, 0x81, 0x00, 0x4C, 0xE9, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xE9, 0x21, 0x00, + 0x00, 0x80, 0x05, 0x40, 0x8C, 0xE7, 0x20, 0x00, 0xE0, 0xE5, 0x20, 0x00, 0x00, 0x74, 0x65, 0x72, 0x02, 0x03, 0x10, 0x21, 0x00, 0x00, 0x80, 0x08, 0x43, 0x00, 0x00, 0x00, 0x54, 0x68, 0x75, 0x20, 0x4D, 0x61, 0x79, 0x20, 0x20, 0x37, 0x20, 0x31, + 0x37, 0x3A, 0x31, 0x37, 0x3A, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x32, 0x2E, 0x32, 0x2E, 0x31, 0x00, 0x94, 0xE7, 0x20, 0x00, 0x38, 0x0C, 0x20, 0x00, 0x8D, 0x88, 0x20, 0x00, 0x3C, 0x0C, 0x20, 0x00, + 0x03, 0x00, 0xAA, 0xA2, 0x00, 0x38, 0x20, 0x00, 0x01, 0xE4, 0x80, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x71, 0x83, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x19, 0x87, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x0D, 0x7C, 0x20, 0x00, 0x59, 0x7C, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0xA5, 0x7C, 0x20, 0x00, 0xE9, 0x7C, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0xA9, 0x84, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x0D, 0xCC, 0x20, 0x00, 0xED, 0x84, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, + 0x3D, 0x88, 0x20, 0x00, 0x3D, 0x88, 0x20, 0x00, 0x1F, 0xB5, 0x06, 0xF0, 0x09, 0xF8, 0x15, 0xF0, 0xEE, 0xFF, 0x1F, 0xBD, 0x47, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x20, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x11, 0xFE, 0x20, 0x06, 0x01, 0xD5, 0x00, 0xF0, + 0x0D, 0xFE, 0x20, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x09, 0xFE, 0x20, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0x05, 0xFE, 0x20, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x01, 0xFE, 0x20, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xFD, 0xFD, 0x20, 0x01, 0x01, 0xD5, 0x00, 0xF0, + 0xF9, 0xFD, 0x00, 0x2C, 0x03, 0xDA, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xF3, 0xBD, 0x10, 0xBD, 0x34, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x60, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0xEB, 0xFD, 0x60, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0xE7, 0xFD, 0x60, 0x05, + 0x01, 0xD5, 0x00, 0xF0, 0xE3, 0xFD, 0x60, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0xDF, 0xFD, 0x60, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0xDB, 0xFD, 0x60, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xD7, 0xFD, 0x60, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0xD3, 0xFD, 0x60, 0x00, + 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xCD, 0xBD, 0x10, 0xBD, 0x21, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xA0, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0xC5, 0xFD, 0xA0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0xC1, 0xFD, 0xA0, 0x04, 0x01, 0xD5, 0x00, 0xF0, + 0xBD, 0xFD, 0xA0, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0xB9, 0xFD, 0xA0, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xB5, 0xFD, 0xA0, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0xB1, 0xFD, 0xA0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xAB, 0xBD, 0x10, 0xBD, + 0x10, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xE0, 0x07, 0x01, 0xD0, 0x00, 0xF0, 0xA3, 0xFD, 0xE0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x9F, 0xFD, 0xE0, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0x9B, 0xFD, 0xE0, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x97, 0xFD, 0xE0, 0x02, + 0x01, 0xD5, 0x00, 0xF0, 0x93, 0xFD, 0xE0, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0x8F, 0xFD, 0xE0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x89, 0xBD, 0x10, 0xBD, 0x00, 0x10, 0x00, 0x40, 0x4F, 0xF0, 0x80, 0x42, 0xD2, 0xF8, 0x10, 0x02, + 0x40, 0xF4, 0x80, 0x30, 0xC2, 0xF8, 0x10, 0x02, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF4, 0x40, 0x40, 0xC2, 0xF8, 0x30, 0x02, 0xFE, 0x49, 0x51, 0xF8, 0x50, 0x3B, 0xFE, 0x48, 0x03, 0x60, 0x51, 0xF8, 0x48, 0x3C, 0x43, 0x60, 0x0B, 0x6E, 0x83, 0x60, + 0x51, 0xF8, 0x3C, 0x3C, 0xC3, 0x60, 0x51, 0xF8, 0x34, 0x3C, 0x03, 0x61, 0x4B, 0x6E, 0x43, 0x61, 0x51, 0xF8, 0x28, 0x3C, 0x83, 0x61, 0x51, 0xF8, 0x20, 0x3C, 0xC3, 0x61, 0x8B, 0x6E, 0x03, 0x62, 0x51, 0xF8, 0x14, 0x3C, 0x43, 0x62, 0x51, 0xF8, + 0x0C, 0x3C, 0x83, 0x62, 0xCB, 0x6E, 0xC3, 0x62, 0x0B, 0x68, 0x03, 0x63, 0x8B, 0x68, 0x43, 0x63, 0x0B, 0x6F, 0x83, 0x63, 0x4B, 0x69, 0xC3, 0x63, 0xCB, 0x69, 0x03, 0x64, 0x4B, 0x6F, 0x43, 0x64, 0x8B, 0x6A, 0x83, 0x64, 0x0B, 0x6B, 0xC3, 0x64, + 0x8B, 0x6F, 0x03, 0x65, 0xCB, 0x6B, 0x43, 0x65, 0x4B, 0x6C, 0x83, 0x65, 0xC9, 0x6F, 0xC1, 0x65, 0xD2, 0xF8, 0x5C, 0x13, 0x01, 0x66, 0xD2, 0xF8, 0x60, 0x13, 0x41, 0x66, 0xD2, 0xF8, 0x64, 0x13, 0xF8, 0x38, 0xC1, 0x60, 0xD2, 0xF8, 0x68, 0x13, + 0x01, 0x61, 0x70, 0x47, 0x4F, 0xF0, 0x80, 0x42, 0xD2, 0xF8, 0x10, 0x02, 0x40, 0xF4, 0x80, 0x30, 0xC2, 0xF8, 0x10, 0x02, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF4, 0x40, 0x40, 0xC2, 0xF8, 0x30, 0x02, 0xD4, 0x48, 0x01, 0x6E, 0xC2, 0xF8, 0x5C, 0x13, + 0x41, 0x6E, 0xC2, 0xF8, 0x60, 0x13, 0xD0, 0x49, 0x03, 0x68, 0x41, 0xF8, 0x50, 0x3B, 0x43, 0x68, 0x41, 0xF8, 0x48, 0x3C, 0x83, 0x68, 0x0B, 0x66, 0xC3, 0x68, 0x41, 0xF8, 0x3C, 0x3C, 0x03, 0x69, 0x41, 0xF8, 0x34, 0x3C, 0x43, 0x69, 0x4B, 0x66, + 0x83, 0x69, 0x41, 0xF8, 0x28, 0x3C, 0xC3, 0x69, 0x41, 0xF8, 0x20, 0x3C, 0x03, 0x6A, 0x8B, 0x66, 0x43, 0x6A, 0x41, 0xF8, 0x14, 0x3C, 0x83, 0x6A, 0x41, 0xF8, 0x0C, 0x3C, 0xC3, 0x6A, 0xCB, 0x66, 0x03, 0x6B, 0x0B, 0x60, 0x43, 0x6B, 0x8B, 0x60, + 0x83, 0x6B, 0x0B, 0x67, 0xC3, 0x6B, 0x4B, 0x61, 0x03, 0x6C, 0xCB, 0x61, 0x43, 0x6C, 0x4B, 0x67, 0x83, 0x6C, 0x8B, 0x62, 0xC3, 0x6C, 0x0B, 0x63, 0x03, 0x6D, 0x8B, 0x67, 0x43, 0x6D, 0xCB, 0x63, 0x83, 0x6D, 0x4B, 0x64, 0xC0, 0x6D, 0xC8, 0x67, + 0xB4, 0x48, 0xF8, 0x38, 0xC1, 0x68, 0xC2, 0xF8, 0x64, 0x13, 0x00, 0x69, 0xC2, 0xF8, 0x68, 0x03, 0x70, 0x47, 0x10, 0xB5, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, + 0x41, 0xF0, 0x80, 0x51, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x1C, 0x12, 0x41, 0xF0, 0x01, 0x01, 0xC0, 0xF8, 0x1C, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x40, 0x71, 0xC0, 0xF8, 0x38, 0x12, 0xA3, 0x48, 0xC1, 0x68, 0x21, 0xF0, 0x1F, 0x01, + 0xC1, 0x60, 0xA0, 0x49, 0x68, 0x31, 0xCA, 0x6A, 0x02, 0x65, 0x82, 0x68, 0x6F, 0xF3, 0x0F, 0x02, 0x82, 0x60, 0xCA, 0x68, 0x02, 0x61, 0x0A, + 0x69, 0x42, 0x61, 0x4A, 0x69, 0x82, 0x61, 0x8A, 0x69, 0xC2, 0x61, 0xCA, 0x69, 0x02, 0x62, 0x0A, + 0x6A, 0x42, 0x62, 0x4A, 0x6A, 0x82, 0x62, 0x8A, 0x6A, 0xC2, 0x62, 0x4A, 0x68, 0x82, 0x60, 0x0A, + 0x68, 0x22, 0xF0, 0x03, 0x02, 0x42, 0x60, 0x0A, + 0x6B, 0x42, 0x65, 0x4A, 0x6B, 0x82, 0x65, 0x42, 0x68, 0x42, 0xF0, 0x80, 0x62, 0x42, 0x60, 0xC2, 0x68, 0x42, 0xF4, 0xF8, 0x52, 0xC2, 0x60, 0x89, 0x68, 0xC1, 0x60, 0x4F, 0xF4, 0x88, 0x74, 0x20, 0x46, 0x36, 0xF6, 0x6C, 0xFF, 0x40, 0xF0, 0x04, + 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x36, 0xF6, 0x75, 0xBF, 0x7C, 0xB5, 0x00, 0x24, 0x4F, 0xF0, 0xE0, 0x20, 0x01, 0x21, 0xC0, 0xF8, 0x80, 0x11, 0xD0, 0xF8, 0x00, 0x21, 0x7F, 0x49, 0xE4, 0x39, 0x0A, + 0x60, 0xD0, 0xF8, 0x00, 0x22, 0x4A, 0x60, 0xD0, 0xF8, 0x00, 0x03, 0x88, 0x60, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x92, 0xF8, 0x00, 0x24, 0x41, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0x20, 0x28, 0xF6, 0xD3, 0x78, 0x48, 0x00, 0x68, 0xC1, 0xF8, 0x80, + 0x00, 0x77, 0x48, 0xC0, 0x68, 0x73, 0x4D, 0xF8, 0x3D, 0x05, 0xF1, 0x98, 0x02, 0x28, 0x60, 0x00, 0x20, 0x81, 0x00, 0x01, 0xF1, 0x80, 0x41, 0xD1, 0xF8, 0x80, 0x12, 0x42, 0xF8, 0x20, 0x10, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x04, 0xF0, 0xE5, 0xFD, 0xA8, 0x68, 0x00, 0xB1, 0x80, 0x47, 0xFF, 0xF7, 0xC1, 0xFE, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x00, + 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x18, 0x12, 0x41, 0xF4, 0x80, 0x21, 0xC0, 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x30, 0x01, 0xC0, 0xF8, 0x38, 0x12, 0x4F, 0xF0, 0x40, 0x21, 0x0B, 0x68, 0x58, 0x4A, 0x14, 0x3A, 0x13, + 0x60, 0x4B, 0x68, 0x53, 0x60, 0xCB, 0x68, 0x93, 0x60, 0x4B, 0x69, 0xD3, 0x60, 0xC9, 0x69, 0x11, 0x61, 0xD0, 0xF8, 0x18, 0x12, 0x41, 0xF4, 0x80, 0x61, 0xC0, 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x34, 0x12, 0x41, 0xF4, 0x40, 0x11, 0xC0, 0xF8, 0x34, + 0x12, 0x51, 0x49, 0x0B, 0x68, 0xB4, 0x32, 0x13, 0x60, 0x4B, 0x68, 0x53, 0x60, 0x8B, 0x69, 0x93, 0x60, 0x49, 0x6A, 0xD1, 0x60, 0xD0, 0xF8, 0x1C, 0x12, 0x41, 0xF4, 0x80, 0x71, 0xC0, 0xF8, 0x1C, 0x12, 0xD0, 0xF8, 0x30, 0x12, 0x41, 0xF0, 0x40, + 0x71, 0xC0, 0xF8, 0x30, 0x12, 0x47, 0x4A, 0x13, 0x68, 0x41, 0x49, 0x38, 0x39, 0x0B, 0x60, 0x53, 0x68, 0x4B, 0x60, 0x93, 0x68, 0x8B, 0x60, 0x13, 0x6B, 0xCB, 0x60, 0x53, 0x6B, 0x0B, 0x61, 0x93, 0x6B, 0x4B, 0x61, 0xD3, 0x6B, 0x8B, 0x61, 0x92, + 0x6C, 0xCA, 0x61, 0xD0, 0xF8, 0x44, 0x03, 0x08, 0x62, 0x00, 0xF0, 0x08, 0xF9, 0x4F, 0xF4, 0x00, 0x15, 0x95, 0xF8, 0x34, 0x03, 0xC0, 0x07, 0x0F, 0xD0, 0x00, 0x94, 0x02, 0x23, 0x01, 0x22, 0x00, 0x21, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xA7, + 0xF9, 0x00, 0x94, 0x02, 0x23, 0x01, 0x22, 0x00, 0x21, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0x9F, 0xF9, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x23, 0x00, 0xF0, 0x3F, 0x00, 0x1A, 0x46, 0x00, 0x21, 0x09, 0xF6, 0x94, 0xF9, 0x7C, + 0xBD, 0x30, 0xB5, 0x24, 0x49, 0x00, 0x20, 0x85, 0xB0, 0x60, 0x39, 0x82, 0x00, 0x02, 0xF1, 0x80, 0x42, 0x51, 0xF8, 0x20, 0x30, 0xC2, 0xF8, 0x80, 0x32, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x00, 0x24, 0x4F, 0xF4, 0x00, 0x15, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x22, 0x00, 0xF0, 0x3F, 0x00, 0x23, 0x46, 0x11, 0x46, 0x05, 0xF5, 0x66, 0x75, 0x09, 0xF6, 0x73, 0xF9, 0x15, 0xF8, 0x64, 0x0C, 0xC0, + 0x07, 0x0F, 0xD0, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0x67, 0xF9, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0x5F, 0xF9, 0x04, 0xF0, 0x3E, 0xFD, 0xFF, + 0xF7, 0x5B, 0xFE, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x00, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x18, 0x12, 0x0D, 0xE0, 0x00, 0x20, 0x00, + 0x40, 0xA4, 0xE8, 0x20, 0x00, 0x00, 0x00, 0x01, 0x40, 0x08, 0xED, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x40, 0x00, 0x30, 0x00, 0x40, 0x00, 0x10, 0x00, 0x40, 0x41, 0xF4, 0x80, 0x21, 0xC0, 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x30, + 0x01, 0xC0, 0xF8, 0x38, 0x12, 0x65, 0x49, 0x4F, 0xF0, 0x40, 0x22, 0x0B, 0x68, 0x13, 0x60, 0x4B, 0x68, 0x53, 0x60, 0x8B, 0x68, 0xD3, 0x60, 0xCB, 0x68, 0x53, 0x61, 0x09, 0x69, 0xD1, 0x61, 0xD0, 0xF8, 0x18, 0x12, 0x41, 0xF4, 0x80, 0x61, 0xC0, + 0xF8, 0x18, 0x12, 0xD0, 0xF8, 0x34, 0x12, 0x41, 0xF4, 0x40, 0x11, 0xC0, 0xF8, 0x34, 0x12, 0x59, 0x4A, 0x59, 0x49, 0xB4, 0x32, 0x10, 0x68, 0x08, 0x60, 0x50, 0x68, 0x48, 0x60, 0x00, 0x28, 0x04, 0xDA, 0x90, 0x68, 0x88, 0x61, 0xD0, 0x68, 0x48, + 0x62, 0x00, 0xE0, 0x4C, 0x61, 0x00, 0xF0, 0x33, 0xF8, 0xFF, 0xF7, 0x5D, 0xFE, 0x4F, 0x4D, 0xE4, 0x3D, 0x68, 0x68, 0x00, 0xB1, 0x80, 0x47, 0x01, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x03, 0x20, 0x03, 0x90, 0x8D, 0xF8, 0x08, 0x40, 0x02, 0xA8, 0x09, + 0xF6, 0x69, 0xF8, 0x48, 0x4C, 0xD0, 0x3C, 0x63, 0x68, 0x58, 0x08, 0x04, 0xD0, 0x01, 0x22, 0x47, 0x49, 0x47, 0x48, 0xFF, 0xF5, 0x2E, 0xFC, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x14, 0xF8, 0x20, 0x10, 0x82, 0xF8, 0x00, 0x14, 0x40, 0x1C, 0x20, + 0x28, 0xF6, 0xD3, 0x42, 0x49, 0xD4, 0xF8, 0x80, 0x00, 0x08, 0x60, 0x41, 0x49, 0x28, 0x68, 0xC8, 0x60, 0x4F, 0xF0, 0xE0, 0x21, 0x20, 0x68, 0xC1, 0xF8, 0x00, 0x01, 0x05, 0xB0, 0x30, 0xBD, 0x10, 0xB5, 0x4F, 0xF0, 0x80, 0x42, 0xD2, 0xF8, 0x1C, + 0x02, 0x40, 0xF4, 0x80, 0x70, 0xC2, 0xF8, 0x1C, 0x02, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF0, 0x40, 0x70, 0xC2, 0xF8, 0x30, 0x02, 0x2F, 0x48, 0x35, 0x49, 0x24, 0x38, 0x43, 0x68, 0x4B, 0x60, 0x84, 0x68, 0x8C, 0x60, 0x04, 0x69, 0x4C, 0x63, 0x44, + 0x69, 0x8C, 0x63, 0x84, 0x69, 0xCC, 0x63, 0xC4, 0x69, 0x8C, 0x64, 0x04, 0x68, 0x0C, 0x60, 0xDB, 0x43, 0xCB, 0x64, 0xC3, 0x68, 0x0B, 0x63, 0x00, 0x6A, 0xC2, 0xF8, 0x44, 0x03, 0x10, 0xBD, 0x10, 0xB5, 0x4F, 0xF0, 0x80, 0x40, 0xD0, 0xF8, 0x0C, + 0x12, 0x41, 0xF0, 0x80, 0x61, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x0C, 0x12, 0x41, 0xF0, 0x80, 0x51, 0xC0, 0xF8, 0x0C, 0x12, 0xD0, 0xF8, 0x1C, 0x12, 0x41, 0xF0, 0x01, 0x01, 0xC0, 0xF8, 0x1C, 0x12, 0xD0, 0xF8, 0x38, 0x12, 0x41, 0xF0, 0x40, + 0x71, 0xC0, 0xF8, 0x38, 0x12, 0x1C, 0x48, 0x42, 0x68, 0x14, 0x49, 0x7C, 0x31, 0x0A, + 0x60, 0x82, 0x68, 0x4A, 0x60, 0xC2, 0x68, 0x8A, 0x60, 0x02, 0x69, 0xCA, 0x60, 0x42, 0x69, 0x0A, + 0x61, 0x82, 0x69, 0x4A, 0x61, 0xC2, 0x69, 0x8A, 0x61, 0x02, 0x6A, 0xCA, 0x61, 0x42, 0x6A, 0x0A, + 0x62, 0x82, 0x6A, 0x4A, 0x62, 0x82, 0x6A, 0x8A, 0x62, 0x02, 0x6D, 0xCA, 0x62, 0x42, 0x6D, 0x0A, + 0x63, 0x80, 0x6D, 0x4F, 0xF4, 0x88, 0x74, 0x48, 0x63, 0x20, 0x46, 0x36, 0xF6, 0x82, 0xFD, 0x20, 0xF0, 0x04, 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x36, 0xF6, 0x8B, 0xBD, 0x00, 0x00, 0x90, 0xE8, 0x20, 0x00, 0x00, 0x30, 0x00, 0x40, 0xE8, + 0x00, 0x80, 0x08, 0x01, 0x04, 0x10, 0x21, 0x08, 0xED, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x40, 0x00, 0x10, 0x00, 0x40, 0x00, 0x00, 0x01, 0x40, 0x26, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0x03, 0xF0, 0x7D, 0xBE, 0x70, + 0x47, 0x22, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0x03, 0xF0, 0x91, 0xBE, 0x70, 0x47, 0x1E, 0x48, 0x10, 0xB5, 0x40, 0x78, 0x38, 0xB1, 0x1D, 0x48, 0x00, 0x78, 0x20, 0xB1, 0x15, 0xF0, 0x21, 0xF9, 0x08, 0xB1, 0x01, + 0x20, 0x10, 0xBD, 0x00, 0x20, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x00, 0x22, 0x18, 0x49, 0x18, 0x48, 0xFF, 0xF5, 0x70, 0xFB, 0x00, 0x26, 0x4F, 0xF0, 0xE0, 0x25, 0x01, 0x24, 0xC5, 0xF8, 0x80, 0x41, 0x2B, 0x20, 0x36, 0xF6, 0x3A, 0xFD, 0x01, + 0x06, 0x17, 0xD5, 0x40, 0xF0, 0x80, 0x01, 0x2B, 0x20, 0x36, 0xF6, 0x54, 0xFD, 0x00, 0x20, 0x03, 0xF0, 0xAE, 0xFD, 0x0A, + 0x4F, 0x32, 0x21, 0x0D, 0x48, 0x7E, 0x70, 0xBC, 0x70, 0x1E, 0xF6, 0x46, 0xFC, 0x38, 0xB9, 0x08, 0x49, 0x09, 0x48, 0x00, 0x22, 0x38, 0x31, 0x80, 0x1E, 0xFF, 0xF5, 0x4E, 0xFB, 0x7C, 0x70, 0xC5, 0xF8, 0x80, 0x42, 0xBD, 0xE8, 0xF0, 0x81, 0x70, + 0xF2, 0x20, 0x00, 0xCC, 0xF2, 0x20, 0x00, 0x08, 0xF3, 0x20, 0x00, 0xF0, 0x10, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0xC8, 0xF2, 0x20, 0x00, 0x2B, 0x48, 0x10, 0xB5, 0x81, 0x7C, 0x01, 0x29, 0x0B, 0xD1, 0x40, 0x7D, 0x01, 0x28, 0x08, 0xD0, 0x02, + 0x20, 0x03, 0xF0, 0x6E, 0xF8, 0x05, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x26, 0x20, 0x04, 0xF0, 0xEE, 0xBA, 0x10, 0xBD, 0x22, 0x48, 0x10, 0xB5, 0x80, 0x7C, 0x03, 0x28, 0x09, 0xD1, 0x00, 0x22, 0x20, 0x49, 0x21, 0x48, 0xFF, 0xF5, 0x21, 0xFB, 0xBD, + 0xE8, 0x10, 0x40, 0x04, 0x20, 0x03, 0xF0, 0x7C, 0xB8, 0x10, 0xBD, 0x1A, 0x48, 0x10, 0xB5, 0x83, 0x7C, 0x04, 0x2B, 0x08, 0xD0, 0x19, 0x49, 0x19, 0x48, 0x01, 0x22, 0x30, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x40, 0x1E, 0xFF, 0xF5, 0x0D, 0xBB, 0x16, + 0x48, 0x40, 0x78, 0x01, 0x28, 0x0B, 0xD0, 0x4F, 0xF4, 0xFA, 0x62, 0x0E, 0x21, 0x0C, 0x20, 0x03, 0xF0, 0x8A, 0xF8, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x02, 0xF0, 0x4D, 0xB8, 0xBD, 0xE8, 0x10, 0x40, 0x41, 0xF2, 0x88, 0x31, 0x0D, + 0x48, 0x1E, 0xF6, 0xE6, 0xBB, 0x08, 0x48, 0x10, 0xB5, 0x80, 0x7C, 0x04, 0x28, 0x0A, + 0xD1, 0x06, 0x49, 0x00, 0x22, 0x68, 0x31, 0x06, 0x48, 0xFF, 0xF5, 0xEB, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0x20, 0x03, 0xF0, 0x46, 0xB8, 0x10, 0xBD, 0x70, 0xF2, 0x20, 0x00, 0xFC, 0x26, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x08, 0xF3, 0x20, + 0x00, 0xA8, 0xF2, 0x20, 0x00, 0x1C, 0xB5, 0x0D, 0x4C, 0x20, 0x46, 0xE1, 0x68, 0x00, 0x21, 0x14, 0xF0, 0x92, 0xFB, 0x00, 0x20, 0x00, 0x90, 0x01, 0x90, 0x1A, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x68, 0x46, 0x03, 0xF0, 0x20, 0xF9, 0x20, 0xB9, 0x00, + 0x22, 0x05, 0x49, 0x06, 0x48, 0xFF, 0xF5, 0xC5, 0xFA, 0x01, 0x21, 0x20, 0x46, 0x14, 0xF0, 0x7F, 0xFB, 0x1C, 0xBD, 0x00, 0x00, 0x78, 0x20, 0x00, 0x40, 0x9C, 0x28, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x2D, 0xE9, 0xFF, 0x41, 0x47, 0x4E, 0x30, + 0x6A, 0x4F, 0xF0, 0x00, 0x48, 0x10, 0xF4, 0x00, 0x3F, 0x59, 0xD0, 0x45, 0x4C, 0x01, 0x25, 0x2A, 0x46, 0x65, 0x70, 0x04, 0x21, 0x30, 0x46, 0x13, 0xF0, 0x1C, 0xFE, 0x30, 0x6A, 0x41, 0x4F, 0xC0, 0xF3, 0x05, 0x12, 0xA2, 0x61, 0xCA, 0xB3, 0x04, + 0xF1, 0x1C, 0x01, 0x30, 0x46, 0x13, 0xF0, 0x19, 0xFE, 0xA5, 0x70, 0x00, 0x20, 0xE0, 0x70, 0x32, 0x21, 0x20, 0x1F, 0x1E, 0xF6, 0x86, 0xFB, 0x10, 0xB1, 0x20, 0x78, 0x18, 0xB1, 0x10, 0xE0, 0x00, 0x22, 0x37, 0x49, 0x35, 0xE0, 0x34, 0x48, 0x14, + 0x22, 0x18, 0x30, 0x21, 0x1D, 0x06, 0x46, 0x51, 0xF6, 0x5B, 0xFC, 0x00, 0x28, 0x34, 0xD0, 0x14, 0x22, 0x31, 0x46, 0x20, 0x1D, 0x51, 0xF6, 0x26, 0xFD, 0x2D, 0x48, 0xAD, 0xF8, 0x00, 0x50, 0x00, 0x1D, 0x01, 0x90, 0xAD, 0xF8, 0x02, 0x50, 0x68, + 0x46, 0x03, 0xF0, 0xCC, 0xF8, 0x00, 0x28, 0x23, 0xD1, 0x29, 0x49, 0x00, 0x22, 0x40, 0x31, 0x38, 0x46, 0xFF, 0xF5, 0x6F, 0xFA, 0x03, 0xF0, 0xB4, 0xFC, 0x23, 0x48, 0x00, 0x1F, 0x1E, 0xF6, 0x6C, 0xFB, 0x13, 0xE0, 0xFF, 0xE7, 0xE0, 0x78, 0x70, + 0xB9, 0xAD, 0xF8, 0x08, 0x50, 0x03, 0x20, 0xAD, 0xF8, 0x0A, + 0x00, 0x02, 0xA8, 0x03, 0xF0, 0xB2, 0xF8, 0x28, 0xB9, 0x1D, 0x49, 0x00, 0x22, 0x8C, 0x31, 0x38, 0x46, 0xFF, 0xF5, 0x56, 0xFA, 0x03, 0xF0, 0x9B, 0xFC, 0x40, 0x46, 0x03, 0xF0, 0xA2, 0xFC, 0xBD, 0xE8, 0xFF, 0x81, 0x01, 0xB5, 0x14, 0x48, 0x82, + 0xB0, 0x81, 0x78, 0x01, 0x29, 0x0A, + 0xD0, 0x01, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x03, 0x20, 0xAD, 0xF8, 0x02, 0x00, 0x68, 0x46, 0x03, 0xF0, 0x95, 0xF8, 0x58, 0xB1, 0x0F, 0xE0, 0x00, 0x21, 0x81, 0x70, 0x41, 0x70, 0x08, 0x46, 0x03, 0xF0, 0x89, 0xFC, 0x0A, + 0x21, 0x02, 0xA8, 0x1E, 0xF6, 0x24, 0xFB, 0x0E, 0xBD, 0x00, 0x22, 0x09, 0x49, 0x06, 0x48, 0xFF, 0xF5, 0x2E, 0xFA, 0x03, 0xF0, 0x73, 0xFC, 0x4F, 0xF0, 0x00, 0x40, 0x03, 0xF0, 0x79, 0xFC, 0x0E, 0xBD, 0x00, 0x50, 0x00, 0x40, 0xCC, 0xF2, 0x20, + 0x00, 0x00, 0x30, 0x10, 0x21, 0xDC, 0x31, 0x80, 0x08, 0xDC, 0x32, 0x80, 0x08, 0x70, 0xB5, 0x37, 0x4C, 0x01, 0x22, 0x37, 0x49, 0x37, 0x48, 0x63, 0x68, 0xFF, 0xF5, 0x15, 0xFA, 0x60, 0x68, 0x01, 0x28, 0x2B, 0xD1, 0x35, 0x4C, 0x00, 0x25, 0x20, + 0x78, 0x10, 0xB1, 0x25, 0x70, 0x43, 0xF6, 0x84, 0xFD, 0x65, 0x72, 0xA0, 0x7C, 0x40, 0xB1, 0x01, 0x28, 0x0B, 0xD0, 0x04, 0x28, 0x1D, 0xD1, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0x02, 0xF0, 0x5F, 0xBF, 0xBD, 0xE8, 0x70, 0x40, 0x03, 0x20, 0x02, + 0xF0, 0x6D, 0xBD, 0x60, 0x7D, 0x03, 0x28, 0x09, 0xD0, 0x01, 0x28, 0x02, 0xD0, 0x27, 0x48, 0x1E, 0xF6, 0xF5, 0xFA, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x20, 0x02, 0xF0, 0x29, 0xBF, 0xBD, 0xE8, 0x70, 0x40, 0x44, 0xF6, 0x20, 0x61, 0x21, 0x48, 0x1E, + 0xF6, 0xD6, 0xBA, 0x70, 0xBD, 0x7C, 0xB5, 0x1B, 0x4C, 0x1D, 0x4E, 0x1C, 0x4D, 0x61, 0x78, 0x20, 0x78, 0xCD, 0xE9, 0x00, 0x01, 0x18, 0x49, 0xB3, 0x7C, 0x03, 0x22, 0x44, 0x31, 0x28, 0x46, 0xFF, 0xF5, 0xD6, 0xF9, 0xB0, 0x7C, 0x04, 0x28, 0x11, + 0xD1, 0x21, 0x78, 0x00, 0x29, 0x0E, 0xD0, 0x60, 0x78, 0x68, 0xB1, 0x06, 0x29, 0x1A, 0xD0, 0x10, 0x49, 0x00, 0x22, 0xEC, 0x31, 0x28, 0x46, 0xFF, 0xF5, 0xC6, 0xF9, 0x20, 0x78, 0x03, 0xF0, 0x14, 0xFD, 0x00, 0x20, 0x20, 0x70, 0x7C, 0xBD, 0x06, + 0x29, 0xFA, 0xD0, 0x09, 0x49, 0x00, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFF, 0xF5, 0xB8, 0xF9, 0x20, 0x78, 0x03, 0xF0, 0x06, 0xFD, 0x20, 0x78, 0x60, 0x70, 0x00, 0x20, 0xEB, 0xE7, 0x03, 0xF0, 0x96, 0xFF, 0xEA, 0xE7, 0x00, 0x00, 0x00, 0xF3, 0x20, + 0x00, 0xE4, 0x33, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x70, 0xF2, 0x20, 0x00, 0xA0, 0xF2, 0x20, 0x00, 0x7C, 0xB5, 0x01, 0x21, 0x08, 0x46, 0x00, 0xF0, 0x63, 0xFB, 0x17, 0x4D, 0x68, 0x78, 0x01, 0x28, 0x20, 0xD1, 0x00, 0x22, 0x15, 0x49, 0x16, + 0x48, 0xFF, 0xF5, 0x95, 0xF9, 0x06, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x00, 0x26, 0xAD, 0xF8, 0x02, 0x60, 0xA8, 0x78, 0x05, 0xF2, 0xE3, 0x14, 0x90, 0xB1, 0x01, 0x94, 0x68, 0x46, 0x02, 0xF0, 0xDC, 0xFF, 0x0F, 0x48, 0x0E, 0x49, 0x01, 0x60, 0xA9, + 0x78, 0x69, 0xB1, 0xAE, 0x70, 0xED, 0x1C, 0x85, 0x60, 0x78, 0x21, 0xC1, 0x61, 0x01, 0x21, 0x08, 0x46, 0x00, 0xF0, 0xE8, 0xFA, 0x7C, 0xBD, 0x04, 0x48, 0xC0, 0x1C, 0x01, 0x90, 0xE9, 0xE7, 0x01, 0x21, 0xA9, 0x70, 0x84, 0x60, 0xF0, 0xE7, 0x00, + 0x00, 0x08, 0xF3, 0x20, 0x00, 0x88, 0x38, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x10, 0x00, 0x02, 0x40, 0x58, 0x70, 0x02, 0x40, 0x2D, 0xE9, 0xFC, 0x5F, 0x32, 0x21, 0x26, 0x48, 0x1E, 0xF6, 0x4F, 0xFA, 0xDF, 0xF8, 0x90, 0x90, 0xDF, 0xF8, 0x90, + 0xA0, 0xA9, 0xF1, 0x04, 0x09, 0x4F, 0xF0, 0x01, 0x0B, 0xD9, 0xF8, 0x00, 0x10, 0x49, 0x1C, 0x00, 0x27, 0x3C, 0x46, 0xC9, 0xF8, 0x00, 0x10, 0x1D, 0x48, 0x00, 0x26, 0x04, 0xEB, 0x44, 0x01, 0x00, 0x1D, 0x00, 0xEB, 0xC1, 0x05, 0x68, 0x69, 0x20, + 0xB3, 0x04, 0xF0, 0xA2, 0xF8, 0x0A, + 0xEB, 0xC0, 0x01, 0xD9, 0xF8, 0x00, 0x30, 0x4A, 0x78, 0x1A, 0xF8, 0x30, 0xC0, 0xB3, 0xFB, 0xF2, 0xF8, 0x02, 0xFB, 0x18, 0x33, 0x01, 0x27, 0x0B, 0xFA, 0x03, 0xF3, 0x5A, 0x46, 0x84, 0x45, 0x00, 0xD1, 0x4E, 0x68, 0x33, 0x42, 0x02, 0xD0, 0x00, + 0x92, 0x01, 0x92, 0x02, 0xE0, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0xB0, 0x00, 0x23, 0x68, 0x78, 0x01, 0x22, 0x19, 0x46, 0x08, 0xF6, 0xE4, 0xFD, 0x20, 0x46, 0x04, 0xF0, 0x45, 0xF8, 0x64, 0x1C, 0x14, 0xF0, 0xFF, 0x04, 0xCD, 0xD0, 0x00, 0x2F, 0x04, + 0xD1, 0xBD, 0xE8, 0xFC, 0x5F, 0x02, 0x48, 0x1E, 0xF6, 0x1A, 0xBA, 0xBD, 0xE8, 0xFC, 0x9F, 0x30, 0x13, 0x21, 0x00, 0xEC, 0xE1, 0x20, 0x00, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0x49, 0xEF, 0xF3, 0x05, 0x82, 0x10, 0x4B, 0x98, 0x47, 0xFE, 0xE7, 0x70, + 0x47, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x20, 0x49, 0x53, 0x52, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, + 0x72, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64, 0x21, 0x0A, + 0x00, 0x4E, 0x88, 0x20, 0x00, 0xB1, 0x79, 0x00, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x94, 0xF8, 0x9B, 0x03, 0x40, 0xF0, 0x80, 0x00, 0x84, 0xF8, 0x9B, 0x03, 0x94, 0xF8, 0xDC, 0x02, 0xC1, 0x07, 0x4F, 0xF0, 0x04, 0x50, 0x03, 0xD0, 0x6C, + 0xA1, 0xFF, 0xF5, 0x80, 0xF8, 0x06, 0xE0, 0x6D, 0xA1, 0xFF, 0xF5, 0x7C, 0xF8, 0x09, 0xF6, 0x43, 0xF8, 0x1D, 0xF6, 0x81, 0xFF, 0x94, 0xF8, 0x9A, 0x03, 0xC0, 0x07, 0x02, 0xD0, 0x00, 0x20, 0xFF, 0xF5, 0x83, 0xFC, 0xBD, 0xE8, 0x10, 0x40, 0x05, + 0xF2, 0x99, 0xB5, 0x40, 0xEA, 0x01, 0x21, 0x01, 0x20, 0xFE, 0xF5, 0xE0, 0xBC, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x00, 0x22, 0x94, 0xF8, 0x4C, 0x13, 0x60, 0xF3, 0x01, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x11, 0x46, 0x45, 0xF2, 0x02, 0x00, 0x03, + 0xF6, 0xBA, 0xFB, 0x00, 0x28, 0x05, 0xD1, 0x94, 0xF8, 0x4C, 0x13, 0x21, 0xF0, 0x03, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x10, 0xBD, 0x01, 0x46, 0x40, 0xF2, 0x5D, 0x43, 0x5F, 0x4A, 0x00, 0x20, 0x1D, 0xF6, 0x21, 0xBA, 0x5D, 0x4A, 0x41, 0x43, 0xD2, + 0x1D, 0x40, 0xF2, 0x62, 0x43, 0x00, 0x20, 0x1D, 0xF6, 0x45, 0xBA, 0x10, 0xB5, 0x0C, 0x46, 0x08, 0xB1, 0x1D, 0xF6, 0x9F, 0xFA, 0x56, 0x4A, 0x21, 0x46, 0x0E, 0x32, 0xBD, 0xE8, 0x10, 0x40, 0x40, 0xF2, 0x6C, 0x43, 0x00, 0x20, 0x1D, 0xF6, 0x0A, + 0xBA, 0x1D, 0xF6, 0x93, 0xBA, 0x51, 0x4A, 0xD1, 0x70, 0x51, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x4F, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x4D, 0x48, 0x00, 0x68, 0x70, 0x47, 0x4A, + 0x48, 0x10, 0xB5, 0x0E, 0x22, 0x4B, 0x49, 0x10, 0x30, 0x51, 0xF6, 0x8D, 0xFA, 0x46, 0x48, 0x10, 0x30, 0x10, 0xBD, 0x48, 0x48, 0x80, 0x1E, 0x00, 0x78, 0x70, 0x47, 0x00, 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, + 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x3A, 0x49, 0xBE, 0xB0, 0x40, 0x22, 0x18, 0x31, 0x2D, 0xA8, 0x51, 0xF6, 0xF9, 0xFA, 0x37, 0x49, 0xB4, 0x22, 0x58, 0x31, 0x68, 0x46, 0x51, 0xF6, 0xF3, 0xFA, 0x3C, + 0x49, 0x4F, 0xF4, 0x00, 0x10, 0x38, 0x4E, 0x39, 0x4F, 0x09, 0x68, 0x05, 0x46, 0x00, 0x24, 0xA9, 0x42, 0x01, 0xD0, 0xFC, 0xF5, 0x67, 0xF9, 0xDF, 0xF8, 0xDC, 0x80, 0x4F, 0xF0, 0x05, 0x59, 0xDF, 0xF8, 0xD8, 0xA0, 0x2F, 0xE0, 0x6C, 0xB3, 0x01, + 0x2C, 0x2B, 0xD0, 0x56, 0xF8, 0x24, 0x00, 0x40, 0x45, 0x00, 0xD0, 0x38, 0xB9, 0x40, 0x45, 0x24, 0xD1, 0x55, 0xF8, 0x24, 0x00, 0xA0, 0xF5, 0x80, 0x71, 0x55, 0x39, 0x1E, 0xD1, 0x10, 0x2C, 0x09, 0xD2, 0x2D, 0xA8, 0x50, 0xF8, 0x24, 0x10, 0x48, + 0x46, 0xFF, 0xF5, 0x29, 0xFA, 0x03, 0x46, 0x01, 0x22, 0x28, 0x49, 0x0B, 0xE0, 0x68, 0x46, 0x00, 0xEB, 0x84, 0x00, 0x50, 0xF8, 0x40, 0x1C, 0x48, 0x46, 0xFF, 0xF5, 0x1D, 0xFA, 0x23, 0x49, 0x01, 0x22, 0x03, 0x46, 0x24, 0x31, 0x50, 0x46, 0xFF, + 0xF5, 0x10, 0xF8, 0x56, 0xF8, 0x24, 0x00, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0xB4, 0xEB, 0x97, 0x0F, 0xCC, 0xD3, 0xBF, 0xF3, 0x5F, 0x8F, 0xBF, 0xF3, 0x4F, 0x8F, 0x3E, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x49, 0x6E, 0x20, 0x53, 0x6F, 0x43, 0x20, + 0x4D, 0x6F, 0x64, 0x65, 0x00, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x3A, 0x20, 0x49, 0x6E, 0x20, 0x48, 0x43, 0x49, 0x20, 0x4D, 0x6F, 0x64, 0x65, 0x2C, 0x20, 0x77, 0x69, 0x6C, 0x6C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, + 0x41, 0x50, 0x50, 0x20, 0x54, 0x61, 0x73, 0x6B, 0x00, 0x80, 0xE2, 0x21, 0x00, 0xE0, 0xE5, 0x20, 0x00, 0x8C, 0xE7, 0x20, 0x00, 0x90, 0xE7, 0x20, 0x00, 0xF4, 0x00, 0x20, 0x00, 0xF5, 0x28, 0x20, 0x00, 0x9C, 0xE6, 0x80, 0x00, 0xF4, 0x00, 0x00, + 0x00, 0x08, 0xED, 0x00, 0xE0, 0x3D, 0x88, 0x20, 0x00, 0x01, 0x01, 0x10, 0x21, 0x9C, 0x00, 0x80, 0x08, 0x10, 0xB5, 0x00, 0x21, 0x04, 0x48, 0xFF, 0xF5, 0x10, 0xFE, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x02, 0x48, 0xFF, 0xF5, 0x0A, + 0xBE, 0x00, 0x00, 0x3B, 0x7F, 0x20, 0x00, 0xB7, 0x80, 0x20, 0x00, 0x00, 0x22, 0xCC, 0x49, 0x4F, 0xF4, 0x00, 0x50, 0x13, 0xF0, 0x66, 0xBB, 0xF0, 0xB5, 0xCA, 0x69, 0x02, 0x60, 0x0A, + 0x6A, 0x82, 0x60, 0xC8, 0x4A, 0x01, 0x25, 0xC2, 0xF8, 0x98, 0x53, 0xD2, 0xF8, 0xA0, 0x33, 0x0C, 0x78, 0x05, 0xFA, 0x04, 0xF3, 0xD2, 0xF8, 0x38, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x38, 0x43, 0xD2, 0xF8, 0x40, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x40, + 0x43, 0xD2, 0xF8, 0x50, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x50, 0x43, 0xD2, 0xF8, 0x48, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x48, 0x43, 0xD2, 0xF8, 0x58, 0x43, 0x1C, 0x43, 0xC2, 0xF8, 0x58, 0x43, 0x0B, 0x78, 0x08, 0x33, 0x05, 0xFA, 0x03, 0xF4, 0xC2, + 0xF8, 0x10, 0x43, 0xC2, 0xF8, 0x18, 0x43, 0xC2, 0xF8, 0x28, 0x43, 0xC2, 0xF8, 0x20, 0x43, 0xC2, 0xF8, 0x30, 0x43, 0x0B, 0x69, 0xCC, 0x68, 0x05, 0xEB, 0x43, 0x03, 0x43, 0xEA, 0x04, 0x13, 0x4C, 0x7A, 0x43, 0xEA, 0xC4, 0x13, 0x0C, 0x7A, 0x43, + 0xEA, 0x44, 0x23, 0x8C, 0x69, 0x43, 0xEA, 0xC4, 0x23, 0x4C, 0x69, 0x43, 0xEA, 0x84, 0x33, 0x4C, 0x78, 0x43, 0xEA, 0x04, 0x53, 0x83, 0x61, 0x4B, 0x68, 0xC3, 0x61, 0x4B, 0x78, 0x33, 0xB1, 0x01, 0x2B, 0x07, 0xD0, 0x02, 0x2B, 0x10, 0xD0, 0x00, + 0x24, 0x04, 0x64, 0x05, 0xE0, 0x4F, 0xF4, 0x40, 0x63, 0x01, 0xE0, 0x4F, 0xF4, 0x00, 0x63, 0x03, 0x64, 0x9C, 0x4F, 0x91, 0xF8, 0x2E, 0x30, 0x58, 0x37, 0x9B, 0x4E, 0x01, 0x2B, 0x03, 0xD0, 0x17, 0xE0, 0x4F, 0xF4, 0x80, 0x63, 0xF3, 0xE7, 0xB8, + 0x42, 0x01, 0xD1, 0x01, 0x23, 0x00, 0xE0, 0x00, 0x23, 0xB0, 0x42, 0x01, 0xD1, 0x01, 0x24, 0x00, 0xE0, 0x00, 0x24, 0x23, 0x43, 0x08, 0xD0, 0x83, 0x69, 0x43, 0xF4, 0x00, 0x33, 0x83, 0x61, 0x0C, 0x8E, 0x4B, 0x6B, 0x43, 0xEA, 0x04, 0x53, 0x83, + 0x64, 0x91, 0xF8, 0x2D, 0x30, 0x01, 0x2B, 0x13, 0xD1, 0xB8, 0x42, 0x00, 0xD1, 0x00, 0xE0, 0x00, 0x23, 0xB0, 0x42, 0x01, 0xD1, 0x01, 0x24, 0x00, 0xE0, 0x00, 0x24, 0x23, 0x43, 0x08, 0xD0, 0x83, 0x69, 0x43, 0xF4, 0x80, 0x23, 0x83, 0x61, 0x0C, + 0x8F, 0xCB, 0x6B, 0x43, 0xEA, 0x04, 0x53, 0x03, 0x65, 0x91, 0xF8, 0x2C, 0x30, 0x01, 0x2B, 0x22, 0xD1, 0x90, 0x42, 0x00, 0xD1, 0x00, 0xE0, 0x00, 0x23, 0x7D, 0x4C, 0x58, 0x3C, 0xA0, 0x42, 0x01, 0xD1, 0x01, 0x24, 0x00, 0xE0, 0x00, 0x24, 0x23, + 0x43, 0x15, 0xD0, 0x03, 0x6C, 0x23, 0xF0, 0x40, 0x43, 0x03, 0x64, 0x83, 0x69, 0x23, 0xF0, 0xC0, 0x53, 0x83, 0x61, 0x0B, 0x6C, 0x03, 0xF0, 0x40, 0x44, 0x13, 0xF0, 0xC0, 0x53, 0x04, 0xD0, 0x8E, 0x6A, 0x06, 0x61, 0x86, 0x69, 0x1E, 0x43, 0x86, + 0x61, 0x03, 0x6C, 0x23, 0x43, 0x03, 0x64, 0x43, 0x6C, 0x6E, 0x4C, 0x23, 0x40, 0x43, 0x64, 0x91, 0xF8, 0x44, 0x30, 0x03, 0xF0, 0x10, 0x04, 0x64, 0xF3, 0x1F, 0x13, 0x44, 0x6C, 0x44, 0xEA, 0xC3, 0x13, 0x43, 0x64, 0x91, 0xF8, 0x45, 0x30, 0x03, + 0xF0, 0x0F, 0x04, 0x03, 0xF0, 0x10, 0x03, 0x44, 0xEA, 0x43, 0x03, 0x44, 0x6C, 0x44, 0xEA, 0xC3, 0x23, 0x43, 0x64, 0x91, 0xF8, 0x45, 0x30, 0x18, 0x2B, 0x06, 0xD3, 0x61, 0x4E, 0x74, 0x6A, 0x08, 0x3B, 0x05, 0xFA, 0x03, 0xF3, 0x1C, 0x43, 0x74, + 0x62, 0x43, 0x6C, 0x23, 0xF0, 0x03, 0x03, 0x43, 0x64, 0x43, 0x6C, 0x43, 0xF0, 0x02, 0x03, 0x43, 0x64, 0x08, 0x78, 0x85, 0x40, 0xD2, 0xF8, 0x38, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x38, 0x03, 0xD2, 0xF8, 0x40, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x40, + 0x03, 0xD2, 0xF8, 0x50, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x50, 0x03, 0xD2, 0xF8, 0x48, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x48, 0x03, 0xD2, 0xF8, 0x58, 0x03, 0x28, 0x43, 0xC2, 0xF8, 0x58, 0x03, 0xF0, 0xBD, 0x00, 0x21, 0x02, 0x22, 0x01, 0x70, 0x42, + 0x70, 0xC8, 0x23, 0x43, 0x60, 0x02, 0x72, 0x41, 0x72, 0xC1, 0x60, 0x01, 0x61, 0x41, 0x61, 0x81, 0x61, 0xC1, 0x61, 0x01, 0x62, 0x4F, 0xF0, 0xC0, 0x52, 0x02, 0x64, 0x41, 0x62, 0x80, 0xF8, 0x44, 0x10, 0x80, 0xF8, 0x45, 0x10, 0x80, 0xF8, 0x2C, + 0x10, 0x80, 0xF8, 0x2D, 0x10, 0x80, 0xF8, 0x2E, 0x10, 0x81, 0x62, 0x81, 0x63, 0xC1, 0x63, 0x01, 0x63, 0x41, 0x63, 0x70, 0x47, 0x10, 0xB5, 0x01, 0x24, 0x00, 0xF1, 0x08, 0x03, 0x04, 0xFA, 0x03, 0xF2, 0x34, 0x4B, 0x39, 0xB1, 0x84, 0x40, 0xD3, + 0xF8, 0xA0, 0x03, 0x14, 0x43, 0x04, 0x43, 0xC3, 0xF8, 0xA0, 0x43, 0x10, 0xBD, 0xC3, 0xF8, 0xA0, 0x23, 0x10, 0xBD, 0x30, 0xB5, 0x01, 0x23, 0x00, 0xF1, 0x08, 0x05, 0x03, 0xFA, 0x05, 0xF4, 0x2B, 0x4D, 0x2A, 0xB3, 0x83, 0x40, 0x23, 0x43, 0xC8, + 0x07, 0x04, 0xD0, 0xD5, 0xF8, 0x10, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x10, 0x03, 0x88, 0x07, 0x04, 0xD5, 0xD5, 0xF8, 0x18, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x18, 0x03, 0x48, 0x07, 0x04, 0xD5, 0xD5, 0xF8, 0x20, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x20, + 0x03, 0x08, 0x07, 0x04, 0xD5, 0xD5, 0xF8, 0x28, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x28, 0x03, 0xC8, 0x06, 0x04, 0xD5, 0xD5, 0xF8, 0x30, 0x03, 0x18, 0x43, 0xC5, 0xF8, 0x30, 0x03, 0x30, 0xBD, 0xC8, 0x07, 0x01, 0xD0, 0xC5, 0xF8, 0x10, 0x43, 0x88, + 0x07, 0x01, 0xD5, 0xC5, 0xF8, 0x18, 0x43, 0x48, 0x07, 0x01, 0xD5, 0xC5, 0xF8, 0x20, 0x43, 0x08, 0x07, 0x01, 0xD5, 0xC5, 0xF8, 0x28, 0x43, 0xC8, 0x06, 0xEC, 0xD5, 0xC5, 0xF8, 0x30, 0x43, 0x30, 0xBD, 0x01, 0x22, 0x82, 0x40, 0x0B, 0x48, 0xCB, + 0x07, 0x01, 0xD0, 0xC0, 0xF8, 0x38, 0x23, 0x8B, 0x07, 0x01, 0xD5, 0xC0, 0xF8, 0x40, 0x23, 0x4B, 0x07, 0x01, 0xD5, 0xC0, 0xF8, 0x48, 0x23, 0x0B, 0x07, 0x01, 0xD5, 0xC0, 0xF8, 0x50, 0x23, 0xC9, 0x06, 0x01, 0xD5, 0xC0, 0xF8, 0x58, 0x23, 0x70, + 0x47, 0x00, 0x00, 0x01, 0x20, 0x00, 0x70, 0x02, 0x40, 0x08, 0x71, 0x02, 0x40, 0x7F, 0x00, 0xFE, 0xFF, 0x00, 0x60, 0x00, 0x40, 0x00, 0x22, 0x4F, 0xF0, 0x04, 0x51, 0x5D, 0x48, 0x13, 0xF0, 0xC2, 0xB9, 0x03, 0x79, 0x5C, 0x49, 0x01, 0x2B, 0x02, + 0x68, 0x4B, 0x68, 0x30, 0xD0, 0x93, 0x43, 0x4B, 0x60, 0x42, 0x79, 0x01, 0x2A, 0x2A, 0xD1, 0x00, 0x22, 0x4A, 0x63, 0x82, 0x79, 0x8A, 0xB3, 0x01, 0x2A, 0x3D, 0xD0, 0x8A, 0x6E, 0x03, 0x68, 0x1A, 0x43, 0x8A, 0x66, 0xC2, 0x79, 0x52, 0xB3, 0xCB, + 0x6B, 0x02, 0x68, 0x93, 0x43, 0x13, 0x43, 0xCB, 0x63, 0x02, 0x7A, 0x7A, 0xB3, 0x8B, 0x6C, 0x02, 0x68, 0x93, 0x43, 0x13, 0x43, 0x8B, 0x64, 0x4F, 0xF0, 0x80, 0x41, 0x4F, 0xF4, 0xE0, 0x52, 0xC1, 0xF8, 0x44, 0x23, 0xD1, 0xF8, 0x44, 0x23, 0xC0, + 0x68, 0x44, 0xF6, 0x20, 0x63, 0x58, 0x43, 0xFF, 0x23, 0x03, 0xEB, 0x50, 0x30, 0xC0, 0xB2, 0x02, 0x43, 0xC1, 0xF8, 0x44, 0x23, 0x70, 0x47, 0x13, 0x43, 0x4B, 0x60, 0x42, 0x7A, 0x00, 0x2A, 0x8A, 0x68, 0x00, 0x68, 0x04, 0xD0, 0x02, 0x43, 0x8A, + 0x60, 0x70, 0x47, 0x02, 0xE0, 0x11, 0xE0, 0x82, 0x43, 0xF9, 0xE7, 0x8A, 0x6B, 0x03, 0x68, 0x9A, 0x43, 0x8A, 0x63, 0x0A, + 0x6E, 0x03, 0x68, 0x1A, 0x43, 0x0A, + 0x66, 0xC6, 0xE7, 0x0A, + 0xE0, 0x8B, 0x6B, 0x02, 0x68, 0x93, 0x43, 0x13, 0x43, 0x8B, 0x63, 0xBF, 0xE7, 0xCA, 0x6B, 0x03, 0x68, 0x9A, 0x43, 0xCA, 0x63, 0xC1, 0xE7, 0x8A, 0x6C, 0x00, 0x68, 0x82, 0x43, 0x8A, 0x64, 0xE0, 0xE7, 0x4F, 0xF0, 0xFF, 0x31, 0x01, 0x60, 0x00, + 0x21, 0x01, 0x71, 0x41, 0x71, 0x81, 0x71, 0xC1, 0x71, 0x01, 0x72, 0x41, 0x72, 0x14, 0x21, 0xC1, 0x60, 0xD3, 0xE7, 0x26, 0x4A, 0x00, 0x29, 0x11, 0x6B, 0x01, 0xD0, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x11, 0x63, 0xCA, 0xE7, 0x22, 0x49, 0xC8, + 0x64, 0xC7, 0xE7, 0x20, 0x4A, 0x00, 0x29, 0x51, 0x6B, 0x01, 0xD0, 0x01, 0x43, 0x00, 0xE0, 0x81, 0x43, 0x51, 0x63, 0xBE, 0xE7, 0x01, 0x21, 0x1E, 0x28, 0x0E, 0xD9, 0xA0, 0xF1, 0x20, 0x02, 0x03, 0x2A, 0x01, 0xD8, 0x00, 0x1F, 0x08, 0xE0, 0x24, + 0x28, 0x05, 0xD0, 0x25, 0x28, 0x03, 0xD0, 0x26, 0x28, 0x01, 0xD0, 0xFF, 0x20, 0xAD, 0xE7, 0x0B, 0x38, 0x01, 0xFA, 0x00, 0xF0, 0xA9, 0xE7, 0x1E, 0x28, 0xA7, 0xD9, 0xA0, 0xF1, 0x20, 0x01, 0x03, 0x29, 0x01, 0xD8, 0x00, 0x1F, 0x08, 0xE0, 0x24, + 0x28, 0x05, 0xD0, 0x25, 0x28, 0x03, 0xD0, 0x26, 0x28, 0x01, 0xD0, 0xFF, 0x20, 0x99, 0xE7, 0x0B, 0x38, 0xC0, 0xB2, 0x96, 0xE7, 0x4F, 0xF0, 0x80, 0x41, 0x00, 0x28, 0xD1, 0xF8, 0x44, 0x03, 0x02, 0xD0, 0x40, 0xF4, 0x80, 0x50, 0x01, 0xE0, 0x20, + 0xF4, 0x80, 0x50, 0xC1, 0xF8, 0x44, 0x03, 0x88, 0xE7, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x00, 0x10, 0x00, 0x40, 0x10, 0xB5, 0x4A, 0x88, 0x0B, 0x88, 0x42, 0xEA, 0x03, 0x12, 0x02, 0x60, 0x0A, + 0x79, 0x01, 0x2A, 0x0A, + 0xD1, 0xCA, 0x89, 0x8B, 0x89, 0x4C, 0x89, 0x42, 0xEA, 0x03, 0x12, 0x0B, 0x89, 0x5B, 0x03, 0x43, 0xEA, 0x04, 0x33, 0x1A, 0x43, 0x42, 0x60, 0x4A, 0x79, 0x01, 0x2A, 0x0A, + 0xD1, 0xCA, 0x8A, 0x8B, 0x8A, 0x4C, 0x8A, 0x42, 0xEA, 0x03, 0x12, 0x0B, 0x8A, 0x5B, 0x03, 0x43, 0xEA, 0x04, 0x33, 0x1A, 0x43, 0xC2, 0x60, 0x8A, 0x79, 0x01, 0x2A, 0x0A, + 0xD1, 0xCA, 0x8B, 0x8B, 0x8B, 0x42, 0xEA, 0x03, 0x12, 0x0B, 0x8B, 0x49, 0x8B, 0x5B, 0x03, 0x43, 0xEA, 0x01, 0x31, 0x0A, + 0x43, 0x42, 0x61, 0x10, 0xBD, 0x00, 0x22, 0x53, 0x49, 0x54, 0x48, 0x13, 0xF0, 0xD0, 0xB8, 0x27, 0x21, 0x01, 0x80, 0x00, 0x21, 0x41, 0x80, 0x01, 0x71, 0x40, 0xF2, 0x71, 0x22, 0x82, 0x81, 0x01, 0x81, 0x41, 0x81, 0xC1, 0x81, 0x41, 0x71, 0x82, + 0x82, 0x01, 0x82, 0x41, 0x82, 0xC1, 0x82, 0x81, 0x71, 0x82, 0x83, 0x01, 0x83, 0x41, 0x83, 0xC1, 0x83, 0x70, 0x47, 0x01, 0x2A, 0x4F, 0xEA, 0xC1, 0x72, 0x23, 0xD0, 0x1A, 0xB1, 0x42, 0x68, 0x22, 0xF4, 0x00, 0x42, 0x42, 0x60, 0x4A, 0x07, 0x03, + 0xD5, 0xC2, 0x68, 0x22, 0xF4, 0x00, 0x42, 0xC2, 0x60, 0xCA, 0x06, 0x03, 0xD5, 0x42, 0x69, 0x22, 0xF4, 0x00, 0x42, 0x42, 0x61, 0x8A, 0x07, 0x03, 0xD5, 0x42, 0x68, 0x22, 0xF4, 0x80, 0x42, 0x42, 0x60, 0x0A, + 0x07, 0x03, 0xD5, 0x42, 0x68, 0x22, 0xF4, 0x80, 0x42, 0x42, 0x60, 0x89, 0x06, 0x03, 0xD5, 0x41, 0x68, 0x21, 0xF4, 0x80, 0x41, 0x41, 0x60, 0x70, 0x47, 0x1A, 0xB1, 0x42, 0x68, 0x42, 0xF4, 0x00, 0x42, 0x42, 0x60, 0x4A, 0x07, 0x03, 0xD5, 0xC2, + 0x68, 0x42, 0xF4, 0x00, 0x42, 0xC2, 0x60, 0xCA, 0x06, 0x03, 0xD5, 0x42, 0x69, 0x42, 0xF4, 0x00, 0x42, 0x42, 0x61, 0x8A, 0x07, 0x03, 0xD5, 0x42, 0x68, 0x42, 0xF4, 0x80, 0x42, 0x42, 0x60, 0x0A, + 0x07, 0x03, 0xD5, 0xC2, 0x68, 0x42, 0xF4, 0x80, 0x42, 0xC2, 0x60, 0x89, 0x06, 0xDF, 0xD5, 0x41, 0x69, 0x41, 0xF4, 0x80, 0x41, 0x41, 0x61, 0x70, 0x47, 0x02, 0x46, 0x00, 0x20, 0x47, 0xF2, 0x07, 0x03, 0x19, 0x42, 0x04, 0xD0, 0x12, 0x6A, 0x0A, + 0x42, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x08, 0x29, 0x0C, 0xD0, 0x10, 0x29, 0x0C, 0xD0, 0x20, 0x29, 0x0D, 0xD0, 0x40, 0x29, 0x0D, 0xD0, 0x80, 0x29, 0x0D, 0xD0, 0xB1, 0xF5, 0x80, 0x7F, 0xF1, 0xD1, 0x91, 0x69, 0x09, 0xE0, 0x91, 0x68, 0x00, + 0xE0, 0x11, 0x69, 0x49, 0x03, 0x05, 0xE0, 0x91, 0x69, 0xFB, 0xE7, 0x91, 0x68, 0x00, 0xE0, 0x11, 0x69, 0x09, 0x03, 0x00, 0x29, 0xE1, 0xDB, 0x70, 0x47, 0x01, 0x2A, 0x05, 0xD0, 0x4F, 0xF0, 0x40, 0x22, 0xD0, 0x69, 0x88, 0x43, 0xD0, 0x61, 0x70, + 0x47, 0xC2, 0x69, 0x0A, + 0x43, 0xC2, 0x61, 0x70, 0x47, 0x49, 0x08, 0x00, 0xEB, 0x81, 0x00, 0x01, 0x2A, 0x41, 0x68, 0x03, 0xD0, 0x21, 0xF0, 0x40, 0x41, 0x41, 0x60, 0x70, 0x47, 0x41, 0xF0, 0x40, 0x41, 0xFA, 0xE7, 0x00, 0x00, 0x10, 0x00, 0x00, 0x60, 0x00, 0x00, 0x04, + 0x08, 0x70, 0xB5, 0x13, 0x46, 0x01, 0x24, 0x9A, 0x4A, 0x09, 0x28, 0x06, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x0C, 0x15, 0x21, 0x2A, 0x33, 0x3C, 0x45, 0x4C, 0x56, 0x00, 0x00, 0x24, 0x22, 0x46, 0x95, 0x49, 0x95, 0x48, 0xFE, 0xF5, 0x66, 0xFC, 0x12, + 0xE0, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x11, 0x70, 0x8F, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x0C, 0x30, 0x07, 0xE0, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x51, 0x70, 0x8B, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x20, 0x30, 0x50, 0xF6, 0x70, 0xFE, 0x20, 0x46, 0x70, 0xBD, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x91, 0x70, 0x85, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x34, 0x30, 0xF2, 0xE7, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0xD1, 0x70, 0x80, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x48, 0x30, 0xE9, 0xE7, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x11, 0x71, 0x7C, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x5C, 0x30, 0xE0, 0xE7, 0x14, 0x29, 0x00, 0xD9, 0x14, 0x21, 0x51, 0x71, 0x77, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x70, 0x30, 0xD7, 0xE7, 0x08, 0x29, 0x00, 0xD9, 0x08, 0x21, 0x0A, + 0x46, 0x19, 0x46, 0x75, 0x48, 0xD0, 0xE7, 0x1E, 0x29, 0x00, 0xD9, 0x1E, 0x21, 0x73, 0x48, 0x0A, + 0x46, 0x08, 0x38, 0x01, 0x70, 0x19, 0x46, 0x10, 0x30, 0xC6, 0xE7, 0x07, 0x29, 0x00, 0xD9, 0x07, 0x21, 0x6E, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0xC0, 0x1F, 0xBE, 0xE7, 0x2D, 0xE9, 0xFC, 0x47, 0x92, 0x46, 0xDD, 0xE9, 0x0A, + 0x45, 0x0A, + 0x46, 0x00, 0x26, 0x26, 0x80, 0x02, 0x21, 0x8D, 0xF8, 0x04, 0x10, 0x8D, 0xF8, 0x05, 0x00, 0xAA, 0xF1, 0x02, 0x00, 0x08, 0x27, 0xDF, 0xF8, 0x80, 0x81, 0x4F, 0xF0, 0x07, 0x09, 0x11, 0x28, 0x0A, + 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x1E, 0x09, 0x8C, 0x09, 0x2C, 0x09, 0x49, 0x09, 0x3B, 0x09, 0x57, 0x09, 0x13, 0x09, 0x65, 0x09, 0x72, 0x00, 0x59, 0x49, 0x53, 0x46, 0x01, 0x22, 0x1C, 0x31, 0x58, 0x48, 0xFE, 0xF5, 0xEB, 0xFB, 0x40, 0xF2, 0x0A, + 0x46, 0x6B, 0xE0, 0x8D, 0xF8, 0x06, 0x90, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x52, 0x48, 0x28, 0x60, 0x27, 0x80, 0x60, 0xE0, 0x01, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, + 0x47, 0x49, 0x48, 0x0C, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x00, 0x00, 0x0C, 0xE0, 0x03, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x42, 0x48, 0x34, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x02, 0x00, 0x20, + 0x80, 0x43, 0xE0, 0x05, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x3B, 0x48, 0x5C, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x04, 0x00, 0xEF, 0xE7, 0x04, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, + 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x34, 0x48, 0x48, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x03, 0x00, 0xE1, 0xE7, 0x06, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x2D, 0x48, 0x70, 0x30, 0x28, + 0x60, 0x98, 0xF8, 0x05, 0x00, 0xD3, 0xE7, 0x8D, 0xF8, 0x06, 0x70, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x29, 0x48, 0x08, 0x30, 0x28, 0x60, 0x10, 0x38, 0x00, 0x78, 0xC6, 0xE7, 0x09, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x10, + 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x22, 0x48, 0xC0, 0x1F, 0x28, 0x60, 0xA4, 0xF8, 0x00, 0x90, 0x20, 0x88, 0x00, 0x90, 0x1D, 0x49, 0x1D, 0x48, 0x53, 0x46, 0x02, 0x22, 0x44, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0x72, 0xFB, 0x30, + 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x8D, 0xF8, 0x06, 0x10, 0x10, 0x46, 0xD8, 0xF8, 0x08, 0x20, 0x01, 0xA9, 0x90, 0x47, 0x13, 0x48, 0x20, 0x30, 0x28, 0x60, 0x98, 0xF8, 0x01, 0x00, 0x9F, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x13, 0x48, 0xD0, 0xE9, 0x06, + 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF5, 0x00, 0x71, 0x43, 0x69, 0x4F, 0xF4, 0x05, 0x72, 0x02, 0xA8, 0x46, 0xF6, 0x5B, 0xF9, 0x50, 0xB9, 0x09, 0x49, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x7C, 0x31, 0x07, 0x48, 0xFE, 0xF5, 0x4A, 0xFB, 0xFF, + 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x02, 0x48, 0x84, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x00, 0x00, 0x60, 0xE9, 0x20, 0x00, 0x14, 0x01, 0x80, 0x08, 0x00, 0x33, 0x10, 0x21, 0xEC, 0xE5, 0x20, 0x00, 0x2C, 0xDE, 0x20, 0x00, 0x10, 0xB5, 0x01, + 0x24, 0x01, 0x28, 0x06, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x53, 0x49, 0x54, 0x48, 0xFE, 0xF5, 0x2D, 0xFB, 0x06, 0xE0, 0x01, 0x29, 0x01, 0xD0, 0x00, 0x24, 0x02, 0xE0, 0x51, 0x49, 0x10, 0x78, 0x08, 0x70, 0x20, 0x46, 0x10, 0xBD, 0x07, 0xB5, 0x82, + 0xB0, 0x00, 0x23, 0x01, 0x22, 0xCD, 0xE9, 0x00, 0x23, 0x04, 0xAB, 0x02, 0x22, 0x46, 0xF6, 0xBC, 0xF9, 0x05, 0xB0, 0x00, 0xBD, 0x07, 0xB5, 0x48, 0x4B, 0x82, 0xB0, 0x5A, 0x78, 0x4A, 0xB1, 0x00, 0x22, 0x5A, 0x70, 0x01, 0x23, 0xCD, 0xE9, 0x00, + 0x32, 0x04, 0xAB, 0x02, 0x22, 0x46, 0xF6, 0x23, 0xF9, 0xEE, 0xE7, 0x00, 0x20, 0xEC, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0xDD, 0xE9, 0x08, 0x67, 0x00, 0x20, 0x30, 0x80, 0x88, 0x46, 0x00, 0x93, 0x39, 0x49, 0x3A, 0x48, 0x14, 0x46, 0x13, + 0x46, 0x02, 0x22, 0x1C, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0xF4, 0xFA, 0x02, 0x2C, 0x0A, + 0xD0, 0x34, 0x49, 0x23, 0x46, 0x01, 0x22, 0x4C, 0x31, 0x33, 0x48, 0xFE, 0xF5, 0xEB, 0xFA, 0x40, 0xF2, 0x0A, + 0x40, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x8D, 0xF8, 0x00, 0x50, 0x2E, 0x4D, 0x01, 0x24, 0x8D, 0xF8, 0x02, 0x40, 0x6A, 0x68, 0x69, 0x46, 0x40, 0x46, 0x90, 0x47, 0xA0, 0xF5, 0x50, 0x61, 0x01, 0x39, 0x00, 0xD1, 0x6C, + 0x70, 0x3D, 0x60, 0x34, 0x80, 0xE8, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x26, 0x8D, 0xF8, 0x05, 0x60, 0x88, 0x46, 0x8D, 0xF8, 0x04, 0x00, 0x1D, 0x46, 0x00, 0x93, 0x1F, 0x49, 0x1F, 0x48, 0x17, 0x46, 0x13, 0x46, 0x34, 0x46, 0x02, 0x22, 0x7C, + 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0xBE, 0xFA, 0x03, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x1A, 0x48, 0x42, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xE8, 0x07, 0x02, 0xD0, 0x8D, + 0xF8, 0x06, 0x60, 0xEF, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xEB, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x10, 0x48, 0xD0, 0xE9, 0x1D, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0x01, 0x46, 0x03, 0x6F, 0x70, 0x22, 0x02, 0xA8, 0x46, 0xF6, 0xA2, 0xF8, 0x50, + 0xB9, 0x07, 0x49, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x06, 0x48, 0xFE, 0xF5, 0x91, 0xFA, 0xFF, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x04, 0x48, 0x44, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0xB4, 0x01, 0x80, 0x08, 0x00, 0x33, 0x10, + 0x21, 0xE4, 0xE9, 0x20, 0x00, 0x8C, 0xE3, 0x21, 0x00, 0x2D, 0xE9, 0xFF, 0x47, 0x17, 0x46, 0xDD, 0xE9, 0x0C, 0x86, 0x89, 0x46, 0x01, 0x24, 0x13, 0x46, 0x00, 0x25, 0x22, 0x46, 0x3D, 0x49, 0x3E, 0x48, 0xFE, 0xF5, 0x73, 0xFA, 0x03, 0x20, 0x02, + 0x2F, 0x0F, 0xD0, 0x05, 0x2F, 0x1E, 0xD0, 0x00, 0x24, 0x40, 0xF2, 0x0A, + 0x45, 0x39, 0x48, 0x02, 0x68, 0x1A, 0xB1, 0x14, 0xB1, 0x69, 0x46, 0x48, 0x46, 0x90, 0x47, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xB8, 0xF1, 0x10, 0x0F, 0x09, 0xD1, 0x46, 0xB1, 0x8D, 0xF8, 0x00, 0x00, 0x01, 0x20, 0x8D, 0xF8, 0x04, + 0x00, 0x10, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x0A, + 0xE0, 0x00, 0x24, 0x4F, 0xF4, 0x90, 0x65, 0xE3, 0xE7, 0x8D, 0xF8, 0x00, 0x00, 0x02, 0x20, 0x8D, 0xF8, 0x04, 0x00, 0x8D, 0xF8, 0x08, 0x80, 0x03, 0x96, 0xDA, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x86, 0xB0, 0x88, 0x46, 0x1E, 0x46, 0x01, 0x24, 0x00, + 0x93, 0x21, 0x49, 0x17, 0x46, 0x13, 0x46, 0x25, 0x46, 0x8D, 0xF8, 0x04, 0x40, 0x02, 0x22, 0x34, 0x31, 0x1E, 0x48, 0xFE, 0xF5, 0x34, 0xFA, 0x03, 0x2F, 0x0C, 0xD0, 0x00, 0x24, 0x1C, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, + 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0xF0, 0x07, 0x8D, 0xF8, 0x04, 0x50, 0x02, 0xD0, 0x8D, 0xF8, 0x08, 0x50, 0xEC, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xE8, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x11, + 0x48, 0xD0, 0xE9, 0x0B, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF1, 0x80, 0x01, 0x83, 0x6A, 0xA8, 0x22, 0x02, 0xA8, 0x46, 0xF6, 0x14, 0xF8, 0x20, 0xB1, 0x09, 0x48, 0x04, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x05, 0x49, 0x9D, 0xF8, 0x08, + 0x30, 0x01, 0x22, 0x6C, 0x31, 0x03, 0x48, 0xFE, 0xF5, 0xFE, 0xF9, 0xFF, 0x20, 0x3E, 0xBD, 0x00, 0x00, 0xB8, 0x03, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0xF8, 0xE9, 0x20, 0x00, 0x88, 0xE4, 0x21, 0x00, 0x2D, 0xE9, 0xF7, 0x4F, 0x86, 0xB0, 0x00, + 0x24, 0x03, 0x94, 0x10, 0x20, 0x8D, 0xF8, 0x0C, 0x00, 0xDF, 0xF8, 0x24, 0x94, 0x0A, + 0x20, 0x96, 0x46, 0x04, 0x94, 0x8D, 0xF8, 0x0D, 0x00, 0x4F, 0xF4, 0x00, 0x62, 0x01, 0x26, 0x07, 0x27, 0xDF, 0xF8, 0x0C, 0xB4, 0xD9, 0xF8, 0x14, 0x00, 0x25, 0x46, 0xA9, 0xF6, 0x14, 0x0A, + 0x91, 0x42, 0x20, 0xD9, 0xCD, 0xE9, 0x00, 0x20, 0x0B, 0x46, 0x4C, 0x46, 0x03, 0x22, 0xFE, 0x49, 0x58, 0x46, 0xFE, 0xF5, 0xCE, 0xF9, 0xAA, 0xF8, 0x02, 0x50, 0x02, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x9A, 0xF8, 0x01, 0x10, 0x32, 0xE0, 0xBA, 0xF8, 0x02, 0x30, 0x8B, 0x42, 0x06, 0xD0, 0xD9, 0xF8, + 0x0C, 0x20, 0x00, 0xEB, 0x03, 0x0C, 0xC8, 0x46, 0x94, 0x45, 0x75, 0xD1, 0x72, 0x46, 0xD0, 0x46, 0x19, 0x46, 0xDA, 0xF8, 0x10, 0x00, 0x3E, 0xF6, 0x2A, 0xF8, 0x28, 0xB3, 0xE6, 0x49, 0x4C, 0x46, 0x01, 0x22, 0x48, 0x31, 0x58, 0x46, 0xD9, 0xF8, + 0x14, 0x30, 0xFE, 0xF5, 0x9A, 0xF9, 0xA8, 0xF8, 0x02, 0x50, 0x05, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x98, 0xF8, 0x01, 0x10, 0x03, 0xAB, 0x04, 0x22, 0x06, 0x98, 0x46, 0xF6, 0x23, 0xF8, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0x82, 0x46, 0xB8, 0xF8, 0x02, 0x00, 0x00, 0x1B, 0x10, 0x28, 0x11, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0xCB, 0x48, 0x07, 0xF6, + 0x49, 0xFA, 0xD8, 0xF8, 0x10, 0x00, 0x20, 0x44, 0x01, 0x46, 0xFF, 0xF5, 0x3B, 0xFB, 0x10, 0x34, 0xA4, 0xB2, 0xE8, 0xE7, 0x02, 0xF0, 0xA2, 0xF8, 0xB9, 0xF8, 0x04, 0x00, 0x44, 0x46, 0xD9, 0xF8, 0x14, 0x10, 0xB8, 0xF8, 0x02, 0x20, 0xD8, 0xF8, + 0x10, 0x30, 0x02, 0xF0, 0xF6, 0xF9, 0x03, 0x00, 0x4F, 0xF4, 0x80, 0x5A, 0x19, 0xD0, 0xBC, 0x49, 0x01, 0x22, 0x7C, 0x31, 0x58, 0x46, 0xFE, 0xF5, 0x48, 0xF9, 0xC8, 0x46, 0xB9, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x61, 0x68, 0x02, 0xF0, 0x2B, 0xF9, + 0x4F, 0xF0, 0x08, 0x09, 0xD0, 0xB1, 0x65, 0x80, 0xB3, 0x49, 0x63, 0x68, 0x01, 0x22, 0x45, 0x46, 0xB4, 0x31, 0xC8, 0xF8, 0x14, 0x30, 0x2E, 0xE0, 0x58, 0xE0, 0x62, 0x88, 0xD9, 0xF8, 0x14, 0x00, 0x10, 0x44, 0xC9, 0xF8, 0x14, 0x00, 0x61, 0x68, + 0x42, 0x1A, 0x52, 0x45, 0x02, 0xD3, 0x01, 0xF5, 0x80, 0x51, 0x61, 0x60, 0x65, 0x80, 0x8D, 0xF8, 0x0E, 0x60, 0x22, 0xE0, 0xD8, 0xF8, 0x14, 0x00, 0x61, 0x68, 0x40, 0x1A, 0x50, 0x45, 0x32, 0xD9, 0xA3, 0x49, 0xA1, 0x48, 0x00, 0x22, 0xF4, 0x31, + 0x80, 0x1C, 0xFE, 0xF5, 0x16, 0xF9, 0x61, 0x68, 0xB8, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x01, 0xF5, 0x80, 0x51, 0x02, 0xF0, 0xF8, 0xF8, 0x10, 0xB3, 0x65, 0x80, 0x63, 0x68, 0x9C, 0x49, 0x45, 0x46, 0x01, 0x22, 0xC8, 0xF8, 0x14, 0x30, 0x58, 0x46, + 0xFE, 0xF5, 0x03, 0xF9, 0x8D, 0xF8, 0x0E, 0x90, 0x68, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x06, 0x98, 0x45, 0xF6, 0x90, 0xFF, 0x02, 0xF0, 0x48, 0xF8, 0x69, 0xE7, 0x65, 0x80, + 0x8B, 0x49, 0x87, 0x48, 0x63, 0x68, 0x45, 0x46, 0x01, 0x22, 0x40, 0x31, 0x80, 0x1C, 0xC8, 0xF8, 0x14, 0x30, 0xFE, 0xF5, 0xDE, 0xF8, 0x8D, 0xF8, 0x0E, 0x70, 0xD9, 0xE7, 0xCD, 0xE9, 0x00, 0x30, 0x0B, 0x46, 0x83, 0x49, 0x02, 0x92, 0x54, 0x46, + 0x04, 0x22, 0x70, 0x31, 0x58, 0x46, 0xFE, 0xF5, 0xD0, 0xF8, 0x65, 0x80, 0x06, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0xD8, 0xF8, 0x14, 0x00, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x35, 0xE7, 0x3E, 0xB5, 0x70, 0x4B, 0x04, 0x46, 0x58, 0x7E, 0x01, 0x28, 0x1D, 0xD1, + 0x00, 0x22, 0x5A, 0x76, 0x02, 0x92, 0x10, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x07, 0x20, 0x8D, 0xF8, 0x09, 0x00, 0x8D, 0xF8, 0x0A, + 0x10, 0x0B, 0x46, 0x6A, 0x49, 0x66, 0x48, 0x01, 0x22, 0xD8, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0xA0, 0xF8, 0x01, 0x21, 0x03, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x66, 0x48, 0x02, 0xAB, 0x04, 0x22, 0x41, 0x78, 0x20, 0x46, 0x45, 0xF6, 0x38, 0xFF, 0x3E, + 0xBD, 0x3E, 0xB5, 0x05, 0x46, 0x00, 0x20, 0x02, 0x90, 0x5C, 0x48, 0x80, 0x88, 0x02, 0xF0, 0xD7, 0xF9, 0x04, 0x46, 0x03, 0x46, 0x58, 0x48, 0x01, 0x22, 0x5D, 0x49, 0x80, 0x1C, 0xFE, 0xF5, 0x84, 0xF8, 0x01, 0x20, 0x14, 0xB1, 0x8D, 0xF8, 0x0A, + 0x00, 0x02, 0xE0, 0x05, 0x21, 0x8D, 0xF8, 0x0A, + 0x10, 0x10, 0x21, 0x8D, 0xF8, 0x08, 0x10, 0x03, 0x21, 0xCD, 0xE9, 0x00, 0x10, 0x53, 0x48, 0x8D, 0xF8, 0x09, 0x10, 0x02, 0xAB, 0x41, 0x78, 0x04, 0x22, 0x28, 0x46, 0x45, 0xF6, 0x10, 0xFF, 0x3E, 0xBD, 0x2D, 0xE9, 0xF7, 0x4F, 0x8C, 0xB0, 0x00, + 0x20, 0x05, 0x90, 0x06, 0x90, 0x07, 0x90, 0x92, 0xF8, 0x00, 0x80, 0x0E, 0x46, 0x00, 0x91, 0x49, 0x49, 0x43, 0x48, 0x15, 0x46, 0x57, 0x1C, 0x43, 0x46, 0x02, 0x22, 0xCD, 0xF8, 0x20, 0x80, 0x40, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0x55, 0xF8, 0xDF, + 0xF8, 0x08, 0x91, 0x01, 0x24, 0x4F, 0xF0, 0x10, 0x0A, + 0x4F, 0xF0, 0x03, 0x0B, 0xB8, 0xF1, 0x0D, 0x0F, 0x0D, 0xD2, 0x08, 0x98, 0x58, 0xB1, 0xDF, 0xF8, 0xE0, 0x80, 0x0C, 0x28, 0x6A, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x69, 0x0D, 0xDD, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0x69, 0xF8, 0xF7, 0xF6, 0x8D, 0xF8, + 0x14, 0xA0, 0x08, 0x98, 0x8D, 0xF8, 0x15, 0x00, 0xFF, 0x20, 0x96, 0xE0, 0x11, 0x2E, 0x6A, 0xD1, 0x4F, 0xF4, 0x00, 0x16, 0x96, 0xF8, 0x14, 0x03, 0x80, 0x06, 0x26, 0xD5, 0x3A, 0x46, 0x10, 0x21, 0x30, 0x48, 0xFE, 0xF5, 0x7F, 0xFA, 0x27, 0x4D, + 0x2D, 0x49, 0x03, 0x46, 0xED, 0x1C, 0x01, 0x22, 0x84, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0x20, 0xF8, 0x96, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x23, 0x48, 0x07, 0xF6, 0xF8, 0xF8, 0x39, 0x46, 0x08, 0x46, 0xFF, 0xF5, + 0xEC, 0xF9, 0x3A, 0x46, 0x10, 0x21, 0x22, 0x48, 0xFE, 0xF5, 0x64, 0xFA, 0x20, 0x49, 0x03, 0x46, 0x01, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0x07, 0xF8, 0x3B, 0x78, 0x0A, + 0x93, 0xB8, 0x78, 0xFA, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x02, 0x20, 0x86, 0xB2, 0x38, 0x79, 0x7A, 0x79, 0x0D, 0xF1, 0x08, 0x0C, 0x00, 0xEB, 0x02, 0x20, 0x80, 0xB2, 0x09, 0x90, 0xB8, 0x79, 0xFA, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x85, 0xB2, 0x38, + 0x7A, 0x7A, 0x7A, 0x00, 0xEB, 0x02, 0x20, 0xBA, 0x7A, 0xFF, 0x7A, 0x12, 0x04, 0x02, 0xEB, 0x07, 0x62, 0xCD, 0xE9, 0x00, 0x16, 0x87, 0x18, 0x09, 0x98, 0x0B, 0x49, 0x8C, 0xE8, 0xA1, 0x00, 0x04, 0x48, 0x06, 0x22, 0xD4, 0x31, 0xC0, 0x1C, 0xFD, + 0xF5, 0xDC, 0xFF, 0x0A, + 0x9B, 0x11, 0xE0, 0x4B, 0xE2, 0x00, 0x31, 0x10, 0x21, 0x54, 0xF2, 0x20, 0x00, 0xFC, 0x06, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x20, 0x08, 0x80, 0x08, 0x40, 0xEA, 0x20, 0x00, 0x30, 0x09, 0x80, 0x08, 0x00, 0x00, 0x50, 0x21, 0xEE, 0xE1, 0x88, + 0xF8, 0x00, 0x30, 0xA8, 0xF8, 0x02, 0x60, 0x09, 0x98, 0xA8, 0xF8, 0x04, 0x00, 0xA8, 0xF8, 0x06, 0x50, 0xC8, 0xF8, 0x08, 0x70, 0x07, 0xF5, 0x80, 0x67, 0xC8, 0xF8, 0x0C, 0x70, 0x05, 0x2B, 0x02, 0xD0, 0x01, 0x22, 0xFB, 0x49, 0x0C, 0xE0, 0xA0, + 0xF5, 0x1C, 0x51, 0x90, 0x39, 0x0A, + 0x29, 0x1C, 0xD3, 0xA0, 0xF5, 0x7F, 0x41, 0xFE, 0x39, 0x18, 0xD0, 0xF5, 0x49, 0x01, 0x22, 0x03, 0x46, 0x30, 0x39, 0xF4, 0x48, 0xFD, 0xF5, 0xA4, 0xFF, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, + 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x45, 0xF6, 0x37, 0xFE, 0x0F, 0xB0, 0x12, 0xE6, 0x01, 0xF0, 0xD5, 0xFE, 0xB8, 0xF8, 0x04, 0x00, 0xE9, 0x4B, 0x0C, 0x22, 0x00, 0x21, 0x02, 0xF0, 0x2D, 0xF8, 0x05, + 0x46, 0x01, 0xF0, 0xE3, 0xFE, 0xC5, 0xB1, 0x2A, 0x46, 0xE5, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFD, 0xF5, 0x28, 0xFF, 0xB8, 0xF8, 0x04, 0x00, 0x02, 0xF0, 0xAA, 0xF8, 0x3D, 0xF6, 0xD3, 0xFD, 0xDC, 0x49, 0x00, 0x22, 0x54, 0x39, 0xEA, 0x48, 0xFD, + 0xF5, 0x73, 0xFF, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x8D, 0xF8, 0x16, 0x40, 0x01, 0xE1, 0xD8, 0xF8, 0x14, 0x00, 0x0C, 0x30, 0xC8, 0xF8, 0x14, 0x00, 0xEC, 0xE7, 0x07, 0x2E, 0x04, 0xD0, 0xD2, 0x49, 0x01, 0x22, 0x33, 0x46, 0x70, + 0x31, 0x92, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xA8, 0xF8, 0x04, 0x30, 0xB8, 0x78, 0xFA, 0x78, 0x7C, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x3A, 0x79, 0x12, 0x04, 0x02, 0xEB, 0x04, 0x62, 0x80, 0x18, 0x07, 0xE0, 0x7B, + 0xE1, 0x59, 0xE1, 0x2E, 0xE1, 0xCE, 0xE0, 0x75, 0xE0, 0x53, 0xE0, 0x4A, 0xE0, 0x12, 0xE0, 0xC8, 0xF8, 0x14, 0x00, 0x01, 0xD0, 0x0C, 0x28, 0x04, 0xD1, 0x00, 0x22, 0xA9, 0xF8, 0x02, 0x20, 0xC9, 0xF8, 0x04, 0x20, 0x00, 0x90, 0xBD, 0x49, 0xBD, + 0x48, 0x02, 0x22, 0x30, 0x31, 0xC0, 0x1C, 0xFD, 0xF5, 0x33, 0xFF, 0x58, 0xE1, 0x03, 0x2E, 0x03, 0xD0, 0x33, 0x46, 0x01, 0x22, 0xC7, 0x49, 0x5F, 0xE0, 0x38, 0x78, 0x79, 0x78, 0xB6, 0x4D, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xC3, 0x49, 0xED, + 0x1C, 0x44, 0x46, 0xA8, 0xF8, 0x04, 0x30, 0x01, 0x22, 0x64, 0x39, 0x28, 0x46, 0xFD, 0xF5, 0x1C, 0xFF, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x7A, 0x03, 0xC0, 0x06, 0xE2, 0xD5, 0xE0, 0x68, 0xB0, 0xF5, 0x80, 0x1F, 0xDE, 0xD9, 0x6F, 0xF0, 0x7F, + 0x61, 0x08, 0x44, 0xC0, 0xF3, 0x07, 0x50, 0x09, 0x17, 0x01, 0xEB, 0x40, 0x11, 0x8C, 0xB2, 0xB4, 0x49, 0x83, 0x00, 0x02, 0x22, 0x40, 0x39, 0x28, 0x46, 0x00, 0x94, 0xFD, 0xF5, 0x01, 0xFF, 0x03, 0x22, 0x0F, 0x21, 0x20, 0x46, 0x07, 0xF6, 0x4E, + 0xFE, 0x21, 0xE1, 0xAD, 0x49, 0x9E, 0x48, 0x00, 0x22, 0x2C, 0x31, 0xC0, 0x1C, 0xFD, 0xF5, 0xF4, 0xFE, 0x19, 0xE1, 0xA9, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x99, 0x48, 0xFD, 0xF5, 0xED, 0xFE, 0xB8, 0xF8, 0x04, 0x00, 0xA0, 0xF5, 0x1C, 0x51, 0x90, + 0x39, 0x0A, + 0x29, 0x0A, + 0xD2, 0x02, 0xF6, 0xF5, 0xFD, 0x38, 0xB1, 0x81, 0x78, 0x09, 0x06, 0x04, 0xD4, 0x20, 0xF0, 0x7F, 0x41, 0x02, 0x20, 0x02, 0xF6, 0xBF, 0xF9, 0x4F, 0xF4, 0xFA, 0x60, 0x1C, 0xF6, 0x60, 0xFD, 0xD4, 0x21, 0x03, 0x20, 0xFE, 0xF7, 0x0F, 0xFE, 0xF8, + 0xE0, 0x03, 0x2E, 0x07, 0xD0, 0x98, 0x49, 0x01, 0x22, 0x33, 0x46, 0xE4, 0x31, 0x87, 0x48, 0xFD, 0xF5, 0xC9, 0xFE, 0xEE, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x92, 0x4F, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0x91, 0x49, 0x45, 0x46, 0xA8, 0xF8, 0x04, + 0x30, 0x01, 0x22, 0x68, 0x31, 0x38, 0x46, 0xFD, 0xF5, 0xB9, 0xFE, 0xA8, 0x88, 0x7E, 0x4E, 0xA0, 0xF5, 0x7F, 0x41, 0x10, 0x36, 0xFE, 0x39, 0x2E, 0xD0, 0x32, 0x1D, 0x31, 0x46, 0x3D, 0xF6, 0xF9, 0xFB, 0x00, 0x20, 0x68, 0x61, 0x00, 0x90, 0x85, + 0x49, 0x02, 0x22, 0x9C, 0x31, 0x38, 0x46, 0x2B, 0x69, 0xFD, 0xF5, 0xA4, 0xFE, 0x8D, 0xF8, 0x14, 0xA0, 0x06, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x28, 0x69, 0x8D, 0xF8, 0x17, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x18, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x19, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1A, 0x00, 0x68, 0x69, 0x8D, 0xF8, 0x1B, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x1C, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x1D, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1E, 0x00, 0x0B, 0x20, 0xF0, 0xE0, 0x05, 0x20, 0x02, 0xF6, 0xF1, 0xF8, 0x32, 0x46, 0x04, 0x21, 0x60, 0x30, 0x02, 0xF6, 0xC9, 0xFB, 0xCB, 0xE7, 0x07, 0x20, + 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x00, 0x09, 0x2E, 0x0D, 0xD0, 0x33, 0x46, 0x01, 0x22, 0x69, 0x49, 0x59, 0x48, 0xFD, 0xF5, 0x6D, 0xFE, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x43, 0xE0, + 0x98, 0xF8, 0x19, 0x00, 0xC2, 0x46, 0x30, 0xB1, 0x61, 0x49, 0x00, 0x22, 0xA0, 0x39, 0x50, 0x48, 0xFD, 0xF5, 0x5B, 0xFE, 0x26, 0xE0, 0x68, 0x78, 0xA9, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x87, 0xB2, 0xE8, 0x78, 0x29, 0x79, 0x00, 0xEB, 0x01, 0x20, + 0x86, 0xB2, 0x68, 0x79, 0xA9, 0x79, 0x32, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x1F, 0xFA, 0x80, 0xF8, 0xE8, 0x79, 0x29, 0x7A, 0x43, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x85, 0xB2, 0x6F, 0xF0, 0x01, 0x00, 0x00, 0xEB, 0x46, 0x01, 0x00, 0xEB, 0x47, 0x00, + 0x89, 0xB2, 0x80, 0xB2, 0x00, 0x95, 0xCD, 0xE9, 0x01, 0x01, 0x39, 0x46, 0x00, 0x20, 0x43, 0xF6, 0x4A, 0xFF, 0x18, 0xB1, 0x58, 0x46, 0x8D, 0xF8, 0x16, 0xB0, 0x9C, 0xE0, 0x8A, 0xF8, 0x19, 0x40, 0x00, 0x96, 0x47, 0x49, 0x36, 0x48, 0xCD, 0xE9, + 0x01, 0x85, 0x3B, 0x46, 0x04, 0x22, 0x5C, 0x39, 0x80, 0x1C, 0xFD, 0xF5, 0x22, 0xFE, 0x47, 0xE0, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x45, 0xF6, 0xBF, 0xFC, 0x41, 0xE0, 0x2F, 0x49, 0x40, 0xF2, 0x75, 0x20, 0x18, 0x31, 0x0C, 0x9A, 0x43, 0xF6, + 0x24, 0xFE, 0x4F, 0xF4, 0x00, 0x60, 0x00, 0x90, 0x39, 0x49, 0x29, 0x48, 0x45, 0x46, 0x98, 0xF8, 0x18, 0x30, 0x02, 0x22, 0x3C, 0x31, 0xC0, 0x1C, 0xFD, 0xF5, 0x07, 0xFE, 0x00, 0x20, 0x89, 0xF8, 0x00, 0x00, 0x8D, 0xF8, 0x14, 0xA0, 0x09, 0x22, + 0x8D, 0xF8, 0x15, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0x08, 0x22, 0x8D, 0xF8, 0x17, 0x00, 0x8D, 0xF8, 0x18, 0x20, 0x2A, 0x7E, 0x8D, 0xF8, 0x19, 0x20, 0x8D, 0xF8, 0x1A, 0x00, 0x07, 0x20, 0x5E, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x02, 0x22, 0x00, 0xEB, + 0x01, 0x20, 0x85, 0xB2, 0xB8, 0x78, 0xF9, 0x78, 0x2B, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x84, 0xB2, 0x23, 0x49, 0x13, 0x48, 0x7C, 0x31, 0xC0, 0x1C, 0x00, 0x94, 0xFD, 0xF5, 0xDE, 0xFD, 0x22, 0x46, 0x29, 0x46, 0x0C, 0x98, 0xFF, 0xF7, 0xE6, 0xFB, + 0x1E, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x40, 0xAE, 0x08, 0x99, 0x0C, 0x98, 0x90, 0x47, 0x3B, 0xE6, 0x8D, 0xF8, 0x14, 0xA0, 0x0B, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x02, 0xA9, 0x42, 0xF2, 0x90, 0x70, 0x3D, 0xF6, 0xEC, 0xFA, 0x20, 0xB1, + 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xFF, 0x20, 0x2A, 0xE0, 0x25, 0xE0, 0xD0, 0x0A, + 0x80, 0x08, 0x00, 0x31, 0x10, 0x21, 0x54, 0xF2, 0x20, 0x00, 0x44, 0x46, 0x55, 0x5F, 0x4F, 0x50, 0x43, 0x4F, 0x44, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5F, 0x44, 0x46, 0x55, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x00, 0x02, 0x33, 0x10, 0x21, 0xDC, 0x0B, 0x80, 0x08, 0x94, 0x0D, 0x80, 0x08, 0x4C, 0xEA, 0x20, 0x00, 0x9D, 0xF8, 0x08, 0x00, 0x8D, 0xF8, + 0x16, 0x40, 0x8D, 0xF8, 0x17, 0x00, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x04, 0x05, 0xAB, 0x04, 0x22, 0x6B, 0xE7, 0x03, 0x46, 0x01, 0x22, 0x88, 0x49, 0x89, 0x48, 0xBC, 0xE6, 0x2D, 0xE9, 0xFE, 0x4F, 0x88, 0x4F, 0x05, 0x46, 0xA7, 0xF6, 0x14, 0x04, + 0x88, 0x46, 0x78, 0x69, 0x61, 0x88, 0xFA, 0x68, 0x8D, 0xE8, 0x07, 0x00, 0x81, 0x49, 0x2B, 0x46, 0x04, 0x22, 0x3C, 0x31, 0x80, 0x48, 0xFD, 0xF5, 0x75, 0xFD, 0xDF, 0xF8, 0xF8, 0xA1, 0x20, 0x78, 0xAA, 0xF1, 0x03, 0x0A, + 0xC0, 0xB1, 0x60, 0x88, 0x43, 0x19, 0x4F, 0xF4, 0x00, 0x60, 0x83, 0x42, 0x08, 0xD9, 0x77, 0x49, 0x00, 0x90, 0x02, 0x22, 0xAC, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0x62, 0xFD, 0x3D, 0xF6, 0xBA, 0xFB, 0x61, 0x88, 0x20, 0x69, 0x2A, 0x46, 0x08, 0x44, + 0x41, 0x46, 0x4F, 0xF6, 0x77, 0xFF, 0x60, 0x88, 0x28, 0x44, 0x70, 0xE0, 0x60, 0x88, 0x4F, 0xF4, 0xFF, 0x66, 0x43, 0x19, 0xB3, 0x42, 0x07, 0xD9, 0x02, 0x22, 0x6D, 0x49, 0x50, 0x46, 0x00, 0x96, 0xFD, 0xF5, 0x4A, 0xFD, 0x3D, 0xF6, 0xA2, 0xFB, + 0x60, 0x88, 0x79, 0x69, 0x28, 0x44, 0xFB, 0x68, 0x08, 0x44, 0xA1, 0x46, 0x98, 0x42, 0x07, 0xD9, 0x66, 0x49, 0x01, 0x22, 0x68, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0x3A, 0xFD, 0x3D, 0xF6, 0x92, 0xFB, 0x10, 0x2D, 0x1D, 0xD3, 0x4F, 0xF4, 0x00, 0x10, + 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0xDF, 0xF8, 0x7C, 0xB1, 0x00, 0x24, 0x82, 0x46, 0x28, 0x1B, 0x10, 0x28, 0x10, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x58, 0x46, 0x06, 0xF6, 0x01, 0xFE, + 0x08, 0xEB, 0x04, 0x00, 0x01, 0x46, 0xFE, 0xF5, 0xF4, 0xFE, 0x10, 0x34, 0xA4, 0xB2, 0xEB, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xD9, 0xF8, 0x10, 0x00, 0x4C, 0x46, 0x08, 0x44, 0x2A, 0x46, 0x41, 0x46, 0x4F, 0xF6, 0x2C, 0xFF, 0x60, 0x88, 0x28, 0x44, + 0x80, 0xB2, 0x60, 0x80, 0xB0, 0x42, 0x04, 0xD0, 0x79, 0x69, 0x01, 0x44, 0xF8, 0x68, 0x81, 0x42, 0x1E, 0xD1, 0x01, 0xF0, 0x46, 0xFC, 0xB8, 0x88, 0x79, 0x69, 0x62, 0x88, 0x23, 0x69, 0x01, 0xF0, 0x9F, 0xFD, 0x05, 0x46, 0x01, 0xF0, 0x55, 0xFC, + 0x65, 0xB1, 0x2A, 0x46, 0x43, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFD, 0xF5, 0x9A, 0xFC, 0xB8, 0x88, 0x01, 0xF0, 0x1D, 0xFE, 0xBD, 0xE8, 0xFE, 0x4F, 0x3D, 0xF6, 0x44, 0xBB, 0x61, 0x88, 0x78, 0x69, 0x08, 0x44, 0x78, 0x61, 0x00, 0x20, 0x60, 0x80, + 0xBD, 0xE8, 0xFE, 0x8F, 0x10, 0xB5, 0x03, 0x46, 0xDD, 0xE9, 0x02, 0x01, 0x00, 0x24, 0x04, 0x2A, 0x0B, 0xD0, 0x02, 0x2A, 0x0F, 0xD0, 0x32, 0x49, 0x13, 0x46, 0x01, 0x22, 0xD0, 0x31, 0x40, 0x48, 0xFD, 0xF5, 0xD2, 0xFC, 0x40, 0xF2, 0x0A, + 0x40, 0x10, 0xBD, 0x0A, + 0x46, 0x01, 0x46, 0x18, 0x46, 0xFF, 0xF7, 0x5E, 0xFC, 0x01, 0xE0, 0xFF, 0xF7, 0x3F, 0xFF, 0x20, 0x46, 0x10, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x25, 0x88, 0x46, 0x1E, 0x46, 0x8D, 0xF8, 0x05, 0x50, 0x00, 0x93, 0x24, 0x49, 0x17, 0x46, 0x8D, + 0xF8, 0x04, 0x00, 0x13, 0x46, 0x2C, 0x46, 0x02, 0x22, 0xFC, 0x31, 0x30, 0x48, 0xFD, 0xF5, 0xB2, 0xFC, 0x05, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x2E, 0x48, 0x82, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, + 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xF0, 0x07, 0x8D, 0xF8, 0x05, 0x50, 0x02, 0xD0, 0x8D, 0xF8, 0x06, 0x50, 0xED, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xE9, 0xE7, 0x7C, 0xB5, 0x24, 0x49, 0x05, 0x46, 0xD1, 0xE9, 0x01, 0x02, 0xCD, 0xE9, 0x00, + 0x02, 0x20, 0x48, 0x0B, 0x68, 0xA8, 0x22, 0x20, 0x49, 0x40, 0x1C, 0x45, 0xF6, 0x93, 0xFA, 0x1C, 0x4C, 0x28, 0xB1, 0x04, 0xF1, 0x14, 0x00, 0xA5, 0x60, 0x20, 0x61, 0x60, 0x78, 0x7C, 0xBD, 0x17, 0x48, 0x63, 0x78, 0x01, 0x22, 0x1A, 0x49, 0x80, + 0x1E, 0xFD, 0xF5, 0x7C, 0xFC, 0xFF, 0x20, 0x60, 0x70, 0x7C, 0xBD, 0x4C, 0x0E, 0x80, 0x08, 0x03, 0x31, 0x10, 0x21, 0x54, 0xF2, 0x20, 0x00, 0x60, 0x0F, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x64, 0x66, 0x75, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x70, 0x61, 0x63, 0x6B, 0x65, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, + 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x02, 0x33, 0x10, 0x21, 0x40, 0xEA, 0x20, 0x00, 0xEC, 0xE6, 0x21, 0x00, 0x1C, 0xE6, 0x20, 0x00, 0x8C, 0x10, 0x80, 0x08, 0x2D, 0xE9, 0xF0, 0x41, 0x01, 0x46, 0xFE, 0x48, 0xFE, 0x4E, 0x00, 0x25, 0xFE, + 0x4C, 0x07, 0x29, 0x4D, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x26, 0x09, 0x11, 0x04, 0x4C, 0x15, 0x1F, 0x00, 0x00, 0x22, 0xFA, 0x49, 0xFD, 0xF5, 0x36, 0xFC, 0x3C, 0xE0, 0xF8, 0x49, 0x00, 0x22, 0x20, 0x31, 0xFD, 0xF5, 0x30, 0xFC, 0x25, 0x70, 0x03, + 0x20, 0x36, 0xE0, 0xF4, 0x49, 0x00, 0x22, 0x3C, 0x31, 0x0C, 0xE0, 0xF2, 0x49, 0x00, 0x22, 0x58, 0x31, 0xFD, 0xF5, 0x24, 0xFC, 0x25, 0x70, 0x06, 0x20, 0xB0, 0x74, 0xBD, 0xE8, 0xF0, 0x81, 0xED, 0x49, 0x00, 0x22, 0x78, 0x31, 0xFD, 0xF5, 0x1A, + 0xFC, 0x25, 0x70, 0xF6, 0xE7, 0xEA, 0x49, 0x00, 0x22, 0x98, 0x31, 0x07, 0x46, 0xFD, 0xF5, 0x12, 0xFC, 0x70, 0x7D, 0x01, 0x28, 0xED, 0xD1, 0xE5, 0x49, 0xB3, 0x79, 0x01, 0x22, 0xB4, 0x31, 0x38, 0x46, 0xFD, 0xF5, 0x08, 0xFC, 0xB0, 0x79, 0x03, + 0x28, 0x06, 0xD2, 0x01, 0x20, 0x00, 0xF0, 0x75, 0xFF, 0xB0, 0x79, 0x40, 0x1C, 0xB0, 0x71, 0xDC, 0xE7, 0xB5, 0x71, 0x20, 0x78, 0x00, 0x28, 0xD8, 0xD0, 0x01, 0x28, 0xDD, 0xD1, 0x25, 0x70, 0x05, 0x20, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0xF0, 0x65, + 0xBF, 0xD7, 0x49, 0xD3, 0x48, 0xB3, 0x7D, 0x01, 0x22, 0xE0, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0xEA, 0xFB, 0xCE, 0xE7, 0x10, 0xB5, 0x01, 0x46, 0xCE, 0x48, 0xCF, 0x4C, 0x08, 0x29, 0x39, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x38, 0x04, 0x09, 0x0D, 0x1A, + 0x2A, 0x32, 0x14, 0x00, 0x22, 0xCD, 0x49, 0xFD, 0xF5, 0xD9, 0xFB, 0x1B, 0xE0, 0xCB, 0x49, 0x00, 0x22, 0x38, 0x31, 0x26, 0xE0, 0xC9, 0x49, 0x00, 0x22, 0x70, 0x31, 0xFD, 0xF5, 0xCF, 0xFB, 0x3D, 0xF6, 0x09, 0xFC, 0xD2, 0x21, 0xBD, 0xE8, 0x10, + 0x40, 0x01, 0x20, 0xFE, 0xF7, 0x03, 0xBB, 0xC2, 0x49, 0x63, 0x7A, 0x01, 0x22, 0xA4, 0x31, 0xFD, 0xF5, 0xC1, 0xFB, 0x60, 0x7A, 0x03, 0x28, 0x0D, 0xD2, 0x40, 0x1C, 0x60, 0x72, 0xBD, 0xE8, 0x10, 0x40, 0x03, 0x20, 0x00, 0xF0, 0x2A, 0xBF, 0xBA, + 0x49, 0x00, 0x22, 0xF4, 0x31, 0xFD, 0xF5, 0xB2, 0xFB, 0x06, 0x20, 0xA0, 0x74, 0x10, 0xBD, 0xB7, 0x49, 0x00, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0xFD, 0xF5, 0xA9, 0xBB, 0xB4, 0x49, 0xE3, 0x7D, 0xAE, 0x48, 0x01, 0x22, 0x3C, 0x31, 0xBD, 0xE8, 0x10, + 0x40, 0x40, 0x1E, 0xFD, 0xF5, 0x9F, 0xBB, 0x10, 0xB5, 0x01, 0x78, 0x00, 0x24, 0x86, 0xB0, 0x02, 0x29, 0x68, 0xD1, 0x81, 0x78, 0x01, 0x29, 0x10, 0xD0, 0x02, 0x29, 0x16, 0xD0, 0x03, 0x29, 0x1C, 0xD0, 0x04, 0x29, 0x22, 0xD0, 0x05, 0x29, 0x29, + 0xD0, 0x06, 0x29, 0x30, 0xD0, 0x07, 0x29, 0x37, 0xD0, 0x08, 0x29, 0x3E, 0xD0, 0x09, 0x29, 0x45, 0xD0, 0x54, 0xE0, 0xA3, 0xA0, 0x07, 0xC8, 0x8D, 0xE8, 0x07, 0x00, 0x0A, + 0x21, 0x6A, 0x46, 0x00, 0x20, 0x4A, 0xE0, 0xA2, 0xA1, 0x0F, 0xC9, 0x8D, 0xE8, 0x0F, 0x00, 0x0D, 0x21, 0x6A, 0x46, 0x01, 0x20, 0x42, 0xE0, 0xA2, 0xA1, 0x0F, 0xC9, 0x8D, 0xE8, 0x0F, 0x00, 0x0F, 0x21, 0x6A, 0x46, 0x02, 0x20, 0x3A, 0xE0, 0x14, + 0x22, 0xA2, 0xA1, 0x68, 0x46, 0x4F, 0xF6, 0x0D, 0xFE, 0x11, 0x21, 0x6A, 0x46, 0x03, 0x20, 0x31, 0xE0, 0x14, 0x22, 0xA2, 0xA1, 0x68, 0x46, 0x4F, 0xF6, 0x04, 0xFE, 0x11, 0x21, 0x6A, 0x46, 0x04, 0x20, 0x28, 0xE0, 0x14, 0x22, 0xA3, 0xA1, 0x68, + 0x46, 0x4F, 0xF6, 0xFB, 0xFD, 0x11, 0x21, 0x6A, 0x46, 0x05, 0x20, 0x1F, 0xE0, 0xA4, 0xA0, 0x6A, 0x46, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x00, 0x10, 0x08, 0x21, 0x06, 0x20, 0x16, 0xE0, 0x14, 0x22, 0xA1, 0xA1, 0x68, 0x46, 0x4F, 0xF6, 0xE9, + 0xFD, 0x12, 0x21, 0x6A, 0x46, 0x07, 0x20, 0x0D, 0xE0, 0xA2, 0xA0, 0x6A, 0x46, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x00, 0x10, 0x03, 0x20, 0x8D, 0xF8, 0x05, 0x00, 0x00, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0x07, 0x21, 0x08, 0x20, 0xFE, 0xF7, 0xB7, + 0xFE, 0x06, 0xB0, 0x20, 0x46, 0x10, 0xBD, 0x2D, 0xE9, 0xF8, 0x43, 0xDF, 0xF8, 0xC0, 0x81, 0x04, 0x46, 0x03, 0x78, 0x00, 0x25, 0x01, 0x22, 0x96, 0x49, 0x40, 0x46, 0xFD, 0xF5, 0x21, 0xFB, 0x20, 0x78, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x28, 0x4B, + 0xD1, 0x3A, 0xE0, 0x20, 0x79, 0x00, 0x26, 0x01, 0x27, 0x68, 0x4C, 0x07, 0x28, 0x44, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x43, 0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x00, 0x8B, 0x49, 0x00, 0x22, 0x20, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0x09, 0xFB, 0x67, + 0x70, 0x36, 0xE0, 0x87, 0x49, 0x00, 0x22, 0x54, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0x01, 0xFB, 0x66, 0x70, 0x2E, 0xE0, 0x83, 0x49, 0x00, 0x22, 0x88, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xF9, 0xFA, 0xA7, 0x70, 0x26, 0xE0, 0x7F, 0x49, 0x00, 0x22, 0xC0, + 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xF1, 0xFA, 0xA6, 0x70, 0x1E, 0xE0, 0x7B, 0x49, 0x00, 0x22, 0xF8, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xE9, 0xFA, 0x27, 0x71, 0x16, 0xE0, 0x00, 0x22, 0x78, 0x49, 0x40, 0x46, 0xFD, 0xF5, 0xE2, 0xFA, 0x26, 0x71, 0x0F, + 0xE0, 0x75, 0x49, 0x00, 0x22, 0x38, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xDA, 0xFA, 0x20, 0x79, 0x01, 0x28, 0x06, 0xD1, 0x20, 0x7A, 0x8D, 0xF8, 0x00, 0x00, 0x69, 0x46, 0x02, 0x20, 0x02, 0xF0, 0xEF, 0xF8, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x70, + 0xB5, 0x0C, 0x46, 0x05, 0x46, 0x03, 0x46, 0x01, 0x22, 0x6A, 0x49, 0x3E, 0x48, 0xFD, 0xF5, 0xC4, 0xFA, 0x04, 0xF1, 0x08, 0x01, 0x4D, 0xB1, 0x01, 0x2D, 0x0A, + 0xD0, 0x02, 0x2D, 0x0B, 0xD1, 0xA2, 0x7B, 0x00, 0x20, 0xBD, 0xE8, 0x70, 0x40, 0x42, 0xF6, 0xB2, 0xBC, 0xA2, 0x7B, 0x02, 0x20, 0xF8, 0xE7, 0xA2, 0x7B, 0x01, 0x20, 0xF5, 0xE7, 0x70, 0xBD, 0x2D, 0xE9, 0xF8, 0x4F, 0x0D, 0x46, 0x00, 0x91, 0x06, + 0x46, 0x5B, 0x49, 0xDF, 0xF8, 0xC0, 0xB0, 0x00, 0x24, 0x4F, 0xF0, 0x01, 0x08, 0x33, 0x46, 0x02, 0x22, 0x48, 0x31, 0x58, 0x46, 0xFD, 0xF5, 0x9F, 0xFA, 0xAB, 0xF1, 0x01, 0x0A, + 0x2D, 0xB1, 0x01, 0x2D, 0x03, 0xD0, 0x53, 0x49, 0x00, 0x22, 0x88, 0x31, 0x3A, 0xE0, 0x27, 0x4F, 0x4F, 0xF0, 0x01, 0x09, 0x38, 0x7F, 0x01, 0x28, 0x0E, 0xD0, 0x01, 0x20, 0xB0, 0x40, 0xB9, 0x8C, 0x01, 0x2D, 0x15, 0xD0, 0x81, 0x43, 0x08, 0x04, + 0xB9, 0x84, 0x00, 0x0C, 0x97, 0xF8, 0x21, 0x00, 0x10, 0xD0, 0x01, 0x28, 0x16, 0xD0, 0x19, 0xE0, 0x46, 0x49, 0x00, 0x22, 0xBC, 0x31, 0x58, 0x46, 0xFD, 0xF5, 0x7B, 0xFA, 0x07, 0xF8, 0x1D, 0x9F, 0x7D, 0x71, 0xFE, 0x70, 0xBD, 0xE8, 0xF8, 0x8F, + 0x01, 0x43, 0xE8, 0xE7, 0x10, 0xB1, 0x4F, 0xF0, 0x00, 0x08, 0x07, 0xE0, 0x3D, 0x49, 0x00, 0x22, 0xF4, 0x31, 0x01, 0xE0, 0x3C, 0x49, 0x00, 0x22, 0x58, 0x46, 0x0C, 0xE0, 0x41, 0x46, 0x00, 0x20, 0x42, 0xF6, 0x28, 0xFD, 0x58, 0xB1, 0x64, 0x1C, + 0xE4, 0xB2, 0x03, 0x2C, 0xF6, 0xD3, 0x36, 0x49, 0x00, 0x22, 0xA0, 0x31, 0x50, 0x46, 0xBD, 0xE8, 0xF8, 0x4F, 0xFD, 0xF5, 0x56, 0xBA, 0x32, 0x49, 0xBB, 0x8C, 0x01, 0x22, 0x40, 0x31, 0x58, 0x46, 0xFD, 0xF5, 0x4F, 0xFA, 0x00, 0x20, 0x78, 0x77, + 0x87, 0xF8, 0x1C, 0x90, 0x5A, 0xE0, 0x00, 0x00, 0x02, 0x30, 0x10, 0x21, 0x70, 0xF2, 0x20, 0x00, 0x00, 0xF3, 0x20, 0x00, 0x70, 0x11, 0x80, 0x08, 0x70, 0x12, 0x80, 0x08, 0xA0, 0x13, 0x80, 0x08, 0x52, 0x65, 0x61, 0x6C, 0x74, 0x65, 0x6B, 0x20, + 0x42, 0x54, 0x00, 0x00, 0x4D, 0x6F, 0x64, 0x65, 0x6C, 0x20, 0x4E, 0x62, 0x72, 0x20, 0x30, 0x2E, 0x39, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4B, 0x42, 0x65, 0x65, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6C, 0x4E, 0x75, 0x6D, 0x00, 0x52, 0x54, 0x4B, 0x42, + 0x65, 0x65, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x76, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4B, 0x42, 0x65, 0x65, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x76, 0x00, 0x00, 0x00, 0x52, 0x54, 0x4B, 0x42, + 0x65, 0x65, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x52, 0x65, 0x76, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x03, 0x04, 0x05, 0x52, 0x54, 0x4B, 0x42, 0x65, 0x65, 0x49, 0x45, 0x45, 0x45, 0x44, 0x61, 0x74, 0x61, 0x6C, 0x69, + 0x73, 0x74, 0x00, 0x00, 0x01, 0x5D, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xA4, 0x15, 0x80, 0x08, 0xD4, 0x16, 0x80, 0x08, 0x58, 0x18, 0x80, 0x08, 0x8C, 0x19, 0x80, 0x08, 0x87, 0xF8, 0x21, 0x50, 0xFE, 0x77, 0x73, 0xE7, 0x10, 0xB5, 0x2E, 0x21, + 0xF7, 0x48, 0x4F, 0xF6, 0xC5, 0xFC, 0xF6, 0x4C, 0x17, 0x20, 0x20, 0x72, 0x00, 0x20, 0x60, 0x71, 0x13, 0xF0, 0x84, 0xF9, 0x60, 0x71, 0x00, 0x28, 0x06, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0x22, 0xF0, 0x49, 0xF1, 0x48, 0xFD, 0xF5, 0xD5, 0xB9, + 0x10, 0xBD, 0x7C, 0xB5, 0xEE, 0x4D, 0xEC, 0x4C, 0x06, 0x46, 0x6D, 0x1C, 0x39, 0xB1, 0x01, 0x29, 0x27, 0xD0, 0x02, 0x29, 0x24, 0xD1, 0x00, 0x22, 0xEA, 0x49, 0x28, 0x46, 0x3E, 0xE0, 0x00, 0x20, 0xE5, 0x49, 0xE0, 0x71, 0x32, 0x46, 0x28, 0x31, + 0x40, 0xF2, 0x72, 0x20, 0x43, 0xF6, 0xCD, 0xF9, 0xE1, 0x49, 0x32, 0x46, 0x2A, 0x31, 0x40, 0xF2, 0x73, 0x20, 0x43, 0xF6, 0xC6, 0xF9, 0xDE, 0x49, 0x32, 0x46, 0x2C, 0x31, 0x4F, 0xF4, 0x1D, 0x70, 0x43, 0xF6, 0xBF, 0xF9, 0xA1, 0x8D, 0x60, 0x8D, + 0xCD, 0xE9, 0x00, 0x01, 0x23, 0x8D, 0x03, 0x22, 0xDB, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0xA5, 0xF9, 0x7C, 0xBD, 0xD9, 0x49, 0xD6, 0x48, 0x13, 0x46, 0x01, 0x22, 0x7C, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0x9C, 0xF9, 0xE1, 0x79, 0xD2, 0x48, 0x03, 0x29, + 0x0D, 0xD2, 0x49, 0x1C, 0xE1, 0x71, 0xD1, 0x49, 0x00, 0x22, 0x8C, 0x39, 0xFD, 0xF5, 0x91, 0xF9, 0xBD, 0xE8, 0x7C, 0x40, 0x41, 0xF2, 0x88, 0x31, 0xCE, 0x48, 0x1C, 0xF6, 0x7A, 0xBA, 0xCB, 0x49, 0x00, 0x22, 0x48, 0x39, 0x02, 0xB0, 0xBD, 0xE8, + 0x70, 0x40, 0xFD, 0xF5, 0x82, 0xB9, 0x2D, 0xE9, 0xF0, 0x41, 0xC5, 0x4E, 0x15, 0x46, 0x0C, 0x46, 0x03, 0x46, 0x76, 0x1C, 0x01, 0x22, 0xC6, 0x49, 0x30, 0x46, 0xFD, 0xF5, 0x76, 0xF9, 0x54, 0xB1, 0x01, 0x2C, 0x11, 0xD0, 0x23, 0x46, 0x30, 0x46, + 0xBD, 0xE8, 0xF0, 0x41, 0xBE, 0x49, 0x01, 0x22, 0x3C, 0x39, 0xFD, 0xF5, 0x6A, 0xB9, 0xBE, 0x49, 0x00, 0x22, 0x30, 0x31, 0x30, 0x46, 0xFD, 0xF5, 0x64, 0xF9, 0x42, 0xF2, 0x10, 0x71, 0x0E, 0xE0, 0x95, 0xB1, 0xA5, 0xF5, 0xA0, 0x60, 0xEB, 0x38, + 0x01, 0xD1, 0x41, 0xF6, 0xD3, 0xFC, 0xB4, 0x49, 0x00, 0x22, 0x68, 0x39, 0x30, 0x46, 0xFD, 0xF5, 0x54, 0xF9, 0x42, 0xF6, 0xE0, 0x61, 0xB3, 0x48, 0xBD, 0xE8, 0xF0, 0x41, 0x1C, 0xF6, 0x3D, 0xBA, 0xAF, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x30, 0x46, + 0xFD, 0xF5, 0x47, 0xF9, 0xA6, 0x4D, 0x01, 0x20, 0x00, 0x24, 0x28, 0x70, 0x04, 0x20, 0xA8, 0x74, 0x6C, 0x72, 0xAA, 0x48, 0x1C, 0xF6, 0x40, 0xFA, 0xA9, 0x49, 0xAA, 0x48, 0x1C, 0xF6, 0x29, 0xFA, 0x03, 0x22, 0x06, 0x21, 0x26, 0x20, 0x02, 0xF0, + 0xBD, 0xF8, 0x68, 0x7D, 0xA6, 0x4D, 0x41, 0xF2, 0x88, 0x37, 0x01, 0x28, 0x03, 0xD0, 0x02, 0x28, 0x01, 0xD0, 0x2C, 0x70, 0x23, 0xE0, 0x28, 0x78, 0xB0, 0xB1, 0x01, 0x28, 0x4F, 0xF0, 0x00, 0x02, 0x0A, + 0xD0, 0x9B, 0x49, 0x30, 0x46, 0x7C, 0x31, 0xFD, 0xF5, 0x1F, 0xF9, 0x4F, 0xF4, 0x96, 0x71, 0x9C, 0x48, 0x1C, 0xF6, 0x0A, + 0xFA, 0x04, 0xE0, 0x93, 0x49, 0x30, 0x46, 0xA4, 0x39, 0xFD, 0xF5, 0x14, 0xF9, 0x28, 0x78, 0x06, 0x28, 0x0A, + 0xD0, 0x4F, 0xF4, 0xFA, 0x62, 0x0E, 0x21, 0x0C, 0x20, 0x00, 0xF0, 0x92, 0xFE, 0xBD, 0xE8, 0xF0, 0x41, 0x00, 0x21, 0x08, 0x46, 0x55, 0xE6, 0x39, 0x46, 0x8A, 0x48, 0xB1, 0xE7, 0x2D, 0xE9, 0xF0, 0x43, 0x83, 0x4C, 0x81, 0x46, 0x8B, 0xB0, 0x0E, + 0x46, 0x20, 0x7D, 0xDF, 0xF8, 0x0C, 0x82, 0xCD, 0xE9, 0x00, 0x06, 0x17, 0x46, 0x08, 0xF1, 0x01, 0x08, 0x4B, 0x46, 0x03, 0x22, 0x88, 0x49, 0x40, 0x46, 0xFD, 0xF5, 0xEF, 0xF8, 0x00, 0x25, 0x16, 0xB1, 0x02, 0x2E, 0x75, 0xD1, 0x34, 0xE0, 0xA5, + 0x74, 0x80, 0x48, 0x1C, 0xF6, 0xE9, 0xF9, 0x7D, 0x48, 0x1C, 0xF6, 0xE6, 0xF9, 0x81, 0x48, 0x40, 0x78, 0x01, 0x28, 0x03, 0xD1, 0x80, 0x48, 0x05, 0x70, 0x01, 0xF0, 0xA5, 0xFE, 0xA7, 0xF5, 0x80, 0x70, 0x13, 0x38, 0x0B, 0xD0, 0xB7, 0xF5, 0x8B, + 0x7F, 0x1A, 0xD0, 0x79, 0x49, 0x3B, 0x46, 0x01, 0x22, 0x84, 0x31, 0x6D, 0x48, 0xFD, 0xF5, 0xCD, 0xF8, 0xE5, 0x75, 0x55, 0xE0, 0x74, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x40, 0x46, 0xFD, 0xF5, 0xC5, 0xF8, 0x20, 0x78, 0x00, 0x28, 0xF4, 0xD1, 0x60, + 0x7A, 0x03, 0x28, 0xF1, 0xD2, 0x40, 0x1C, 0x60, 0x72, 0x03, 0x20, 0x00, 0xF0, 0x2D, 0xFC, 0xEB, 0xE7, 0xE0, 0x7D, 0xFF, 0xF7, 0xCD, 0xFC, 0xE7, 0xE7, 0x03, 0x20, 0xA0, 0x74, 0x42, 0xF2, 0x10, 0x71, 0x62, 0x48, 0x1C, 0xF6, 0x9E, 0xF9, 0xE5, + 0x61, 0x25, 0x62, 0xA5, 0x84, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0xF7, 0xFD, 0xFB, 0x21, 0x40, 0xF6, 0x48, 0x02, 0x48, 0x46, 0x42, 0xF6, 0x33, 0xFB, 0x4A, 0x46, 0x06, 0xA9, 0x40, 0xF2, 0x72, 0x20, 0x43, 0xF6, 0xAB, 0xF8, 0x4A, 0x46, 0x08, + 0xA9, 0x40, 0xF2, 0x73, 0x20, 0x43, 0xF6, 0xA5, 0xF8, 0x4A, 0x46, 0x09, 0xA9, 0x4F, 0xF4, 0x1D, 0x70, 0x43, 0xF6, 0x9F, 0xF8, 0x07, 0xAA, 0x04, 0xA9, 0x48, 0x46, 0x43, 0xF6, 0x52, 0xF9, 0x04, 0xA9, 0x56, 0x48, 0xFD, 0xF5, 0x43, 0xFA, 0x03, + 0x46, 0x9D, 0xF8, 0x1C, 0x00, 0xBD, 0xF8, 0x24, 0x50, 0xBD, 0xF8, 0x20, 0x20, 0xBD, 0xF8, 0x18, 0x10, 0x8D, 0xE8, 0x27, 0x00, 0x46, 0x49, 0x05, 0x22, 0x84, 0x39, 0x40, 0x46, 0xFD, 0xF5, 0x75, 0xF8, 0x26, 0x75, 0x0B, 0xB0, 0xBD, 0xE8, 0xF0, + 0x83, 0x2D, 0xE9, 0xFE, 0x4F, 0xC4, 0xB2, 0xC4, 0xF3, 0x81, 0x05, 0xA7, 0x09, 0x00, 0x95, 0xCD, 0xE9, 0x01, 0x71, 0x04, 0xF0, 0x01, 0x00, 0xDF, 0xF8, 0xE0, 0xA0, 0x36, 0x49, 0x80, 0x46, 0x03, 0x46, 0x0A, + 0xF1, 0x01, 0x0A, + 0x04, 0x22, 0x60, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0x5A, 0xF8, 0x30, 0x4E, 0x4F, 0xF0, 0x01, 0x09, 0xF0, 0x7C, 0x00, 0xF0, 0x01, 0x01, 0x40, 0x46, 0x4F, 0xF0, 0x00, 0x08, 0x81, 0x42, 0x29, 0xD0, 0xE0, 0x07, 0x27, 0xD0, 0x35, 0x49, 0x00, 0x22, + 0xA4, 0x39, 0x50, 0x46, 0xFD, 0xF5, 0x47, 0xF8, 0x0C, 0x21, 0xC8, 0x23, 0x0E, 0x22, 0x08, 0x46, 0x46, 0xF6, 0xB0, 0xFF, 0x86, 0xF8, 0x12, 0x80, 0x16, 0x20, 0x12, 0xF0, 0x18, 0xFF, 0x45, 0xF6, 0xAB, 0xFC, 0x78, 0xB1, 0x01, 0x78, 0x69, 0xB1, + 0x86, 0xF8, 0x00, 0x90, 0x82, 0x7B, 0x00, 0xF1, 0x08, 0x01, 0x01, 0x20, 0x42, 0xF6, 0x2A, 0xFA, 0x03, 0x20, 0xB0, 0x71, 0x01, 0x20, 0x00, 0xF0, 0x9D, 0xFB, 0x01, 0xE0, 0x86, 0xF8, 0x00, 0x80, 0x12, 0xF0, 0x0F, 0xFC, 0xF0, 0x7C, 0xC0, 0xF3, + 0x81, 0x00, 0xA8, 0x42, 0x4F, 0xD0, 0x14, 0xF0, 0x0C, 0x0F, 0x02, 0xD0, 0x02, 0x2D, 0x43, 0xD0, 0x49, 0xE0, 0x05, 0x21, 0x26, 0x20, 0x01, 0xF0, 0xD8, 0xFF, 0x86, 0xF8, 0x12, 0x80, 0x70, 0x7D, 0x45, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x1B, 0x48, + 0x1C, 0xF6, 0x10, 0xF9, 0xA0, 0x07, 0x4F, 0xF0, 0x00, 0x02, 0x09, 0xD4, 0x13, 0x49, 0x50, 0x46, 0x90, 0x39, 0xFD, 0xF5, 0x04, 0xF8, 0xB0, 0x7D, 0xFF, 0xF7, 0xB8, 0xFB, 0xB5, 0x75, 0x2E, 0xE0, 0x0E, 0x49, 0x50, 0x46, 0x5C, 0x39, 0xFC, 0xF5, + 0xFA, 0xFF, 0x28, 0xE0, 0x70, 0xF2, 0x20, 0x00, 0x5C, 0x1A, 0x80, 0x08, 0x01, 0x30, 0x10, 0x21, 0xA0, 0x1F, 0x80, 0x08, 0x64, 0x1E, 0x80, 0x08, 0xA8, 0xF2, 0x20, 0x00, 0x00, 0x1D, 0x80, 0x08, 0xAC, 0xF2, 0x20, 0x00, 0xE0, 0x93, 0x04, 0x00, + 0xA4, 0xF2, 0x20, 0x00, 0x00, 0xF3, 0x20, 0x00, 0xFC, 0xF2, 0x20, 0x00, 0xB8, 0x1B, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0xF4, 0xF6, 0x20, 0x00, 0x00, 0x00, 0x30, 0x21, 0xA0, 0xF2, 0x20, 0x00, 0x00, 0x22, 0xF6, 0x49, 0x50, 0x46, 0xFC, 0xF5, + 0xD2, 0xFF, 0x86, 0xF8, 0x12, 0x90, 0xF0, 0x7C, 0x83, 0x09, 0xB3, 0xEB, 0x94, 0x1F, 0x06, 0xD0, 0xF0, 0x49, 0x02, 0x22, 0x14, 0x31, 0x50, 0x46, 0x00, 0x97, 0xFC, 0xF5, 0xC4, 0xFF, 0xF4, 0x74, 0xBD, 0xE8, 0xFE, 0x8F, 0x7F, 0xB5, 0x05, 0x46, + 0x43, 0x88, 0x44, 0x68, 0x01, 0x22, 0xEA, 0x49, 0xEA, 0x48, 0xFC, 0xF5, 0xB8, 0xFF, 0x6B, 0x88, 0xE8, 0x4D, 0x00, 0x20, 0x6D, 0x1E, 0x0B, 0x2B, 0x75, 0xD2, 0xDF, 0xE8, 0x03, 0xF0, 0x8A, 0x06, 0x0C, 0x6C, 0x75, 0x14, 0x29, 0x45, 0x56, 0x33, + 0x1C, 0x00, 0x04, 0xB0, 0x20, 0x46, 0x21, 0x0C, 0xBD, 0xE8, 0x70, 0x40, 0x32, 0xE7, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x98, 0xE6, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, + 0xBD, 0xE8, 0x70, 0x40, 0x11, 0xE6, 0xE0, 0xB2, 0x01, 0x21, 0x02, 0xF0, 0x4C, 0xF9, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xD2, 0x49, 0x00, 0x22, 0x24, 0x31, 0xFC, 0xF5, 0x87, 0xBF, 0x00, 0x90, 0xE0, 0xB2, 0x69, 0x46, 0x41, 0xF6, + 0x48, 0xFC, 0xCD, 0x49, 0x01, 0x22, 0x44, 0x31, 0x00, 0x9B, 0x52, 0xE0, 0xE4, 0xB2, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, 0x41, 0xF6, 0x3D, 0xFC, 0xC7, 0x49, 0x01, 0x22, 0x74, 0x31, 0x28, 0x46, 0x00, 0x9B, 0xFC, 0xF5, 0x70, 0xFF, 0x01, 0x21, + 0x20, 0x46, 0x41, 0xF6, 0x47, 0xFC, 0x7F, 0xBD, 0xC1, 0x49, 0xE4, 0xB2, 0xC2, 0x4E, 0x23, 0x46, 0x01, 0x22, 0xA8, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x62, 0xFF, 0x04, 0xB0, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x22, 0x41, 0xF6, + 0xEC, 0xBB, 0xB9, 0x49, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0xE4, 0xB2, 0x00, 0x22, 0xD8, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x4F, 0xFF, 0x6A, 0x46, 0x10, 0x21, 0x4F, 0xF4, 0x04, 0x70, 0x41, 0xF6, 0x11, 0xFB, 0x01, 0x21, 0x20, 0x46, + 0x41, 0xF6, 0xF1, 0xFB, 0x7F, 0xBD, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x67, 0xE5, 0x14, 0xE0, 0x8D, 0xF8, 0x00, 0x00, 0xE2, 0xB2, 0x69, 0x46, 0x40, 0xF2, 0x75, 0x20, 0x42, 0xF6, 0x43, 0xFF, + 0x9D, 0xF8, 0x00, 0x30, 0x17, 0x2B, 0xE9, 0xD3, 0xA6, 0x48, 0xA3, 0x49, 0x01, 0x22, 0x03, 0x72, 0xF8, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x27, 0xFF, 0x7F, 0xBD, 0x04, 0xB0, 0x9F, 0x48, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x22, 0xA0, 0x49, 0xC0, 0x1E, + 0xFC, 0xF5, 0x1D, 0xBF, 0x13, 0xB5, 0x9B, 0x4B, 0xBD, 0xF8, 0x00, 0x00, 0x5B, 0x1E, 0x06, 0x28, 0x2D, 0xD0, 0x18, 0xDC, 0x20, 0xB3, 0x01, 0x28, 0x14, 0xD1, 0x9A, 0x49, 0x9A, 0x48, 0x1B, 0xF6, 0xFE, 0xFF, 0x9A, 0x48, 0x41, 0x68, 0x21, 0xB1, + 0x00, 0x21, 0x41, 0x60, 0x98, 0x48, 0x1C, 0xF6, 0x09, 0xF8, 0xBD, 0xF8, 0x02, 0x00, 0x03, 0x28, 0x16, 0xD0, 0x01, 0x28, 0x02, 0xD1, 0x01, 0x98, 0x01, 0xF0, 0x6A, 0xFB, 0x1C, 0xBD, 0x17, 0x28, 0x21, 0xD0, 0x1A, 0x28, 0xFA, 0xD1, 0x87, 0x49, + 0x00, 0x22, 0xF0, 0x39, 0x18, 0x46, 0xFC, 0xF5, 0xF2, 0xFE, 0x06, 0xF6, 0x6B, 0xFE, 0x1C, 0xBD, 0x68, 0x46, 0xFF, 0xF7, 0x2B, 0xFF, 0x1C, 0xBD, 0x01, 0xF0, 0x36, 0xFB, 0x1C, 0xBD, 0x00, 0x22, 0x88, 0x49, 0x18, 0x46, 0xFC, 0xF5, 0xE3, 0xFE, + 0x87, 0x49, 0x48, 0x68, 0x40, 0x1C, 0x48, 0x60, 0x07, 0x28, 0xF3, 0xD3, 0x69, 0x46, 0x03, 0x20, 0x01, 0xF0, 0xF8, 0xFC, 0x1C, 0xBD, 0x12, 0xF0, 0xB2, 0xFD, 0x1C, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x76, 0x4D, 0x00, 0x26, 0x6D, 0x1E, 0x0C, 0x46, + 0x01, 0x28, 0x29, 0xD0, 0x12, 0x28, 0x32, 0xD0, 0x14, 0x28, 0x0A, + 0xD0, 0x20, 0x28, 0x15, 0xD0, 0x03, 0x46, 0x01, 0x22, 0x79, 0x49, 0x28, 0x46, 0xFC, 0xF5, 0xC1, 0xFE, 0x30, 0x46, 0xBD, 0xE8, 0xFC, 0x81, 0x08, 0x68, 0x82, 0x88, 0x41, 0x88, 0xCD, 0xE9, 0x00, 0x12, 0x6C, 0x49, 0x03, 0x78, 0x03, 0x22, 0x30, + 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xB2, 0xFE, 0xEF, 0xE7, 0x20, 0x68, 0x68, 0x49, 0x01, 0x22, 0x03, 0x78, 0x84, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xA9, 0xFE, 0x20, 0x68, 0x41, 0x68, 0x00, 0x78, 0xFF, 0xF7, 0xD7, 0xFB, 0xE1, 0xE7, 0x08, 0x68, 0x02, + 0x22, 0x41, 0x88, 0x00, 0x91, 0x5F, 0x49, 0x03, 0x78, 0xB0, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x99, 0xFE, 0xD6, 0xE7, 0x20, 0x68, 0x62, 0x49, 0x01, 0x22, 0x03, 0x88, 0xC4, 0x39, 0x2F, 0x46, 0x28, 0x46, 0xFC, 0xF5, 0x8F, 0xFE, 0x56, 0x4D, 0x00, + 0x20, 0x28, 0x77, 0x21, 0x68, 0x09, 0x88, 0x99, 0xB1, 0xA8, 0x7F, 0x4F, 0xF0, 0x00, 0x02, 0x05, 0x28, 0x1D, 0xD2, 0x59, 0x49, 0x4E, 0x48, 0x58, 0x39, 0x80, 0x1E, 0xFC, 0xF5, 0x7E, 0xFE, 0xA8, 0x7F, 0x40, 0x1C, 0xA8, 0x77, 0x95, 0xF8, 0x21, + 0x10, 0xE8, 0x7F, 0xFF, 0xF7, 0xC6, 0xFB, 0xB3, 0xE7, 0xA8, 0x77, 0x68, 0x7F, 0x01, 0x28, 0xAF, 0xD1, 0x4F, 0x49, 0x00, 0x22, 0x94, 0x39, 0x38, 0x46, 0xFC, 0xF5, 0x6B, 0xFE, 0x95, 0xF8, 0x22, 0x10, 0x95, 0xF8, 0x20, 0x00, 0xED, 0xE7, 0x4A, + 0x49, 0x3F, 0x48, 0x2C, 0x39, 0xC0, 0x1E, 0xFC, 0xF5, 0x60, 0xFE, 0x9D, 0xE7, 0x10, 0xB5, 0x00, 0x24, 0xFF, 0x28, 0x07, 0xD0, 0x3C, 0x4A, 0x93, 0x7A, 0x83, 0x42, 0x07, 0xD1, 0x08, 0x46, 0x00, 0xF0, 0x8B, 0xF8, 0x17, 0xE0, 0x08, 0x46, 0x00, + 0xF0, 0x2E, 0xF8, 0x2A, 0xE0, 0xD3, 0x7A, 0x83, 0x42, 0x03, 0xD1, 0x08, 0x46, 0xFF, 0xF7, 0xAA, 0xFA, 0x0C, 0xE0, 0x13, 0x7B, 0x83, 0x42, 0x03, 0xD1, 0x08, 0x46, 0xFF, 0xF7, 0x15, 0xFB, 0x05, 0xE0, 0x53, 0x7B, 0x83, 0x42, 0x04, 0xD1, 0x08, + 0x46, 0x00, 0xF0, 0xA4, 0xF8, 0x04, 0x46, 0x14, 0xE0, 0x92, 0x7B, 0x82, 0x42, 0x11, 0xD1, 0x08, 0x78, 0x03, 0x28, 0x0E, 0xD1, 0x88, 0x78, 0x01, 0x28, 0x0B, 0xD1, 0x08, 0x79, 0x01, 0x28, 0x08, 0xD1, 0x23, 0x48, 0x00, 0x22, 0x2D, 0x49, 0x40, + 0x1E, 0xFC, 0xF5, 0x27, 0xFE, 0x03, 0x20, 0x00, 0xF0, 0x84, 0xFB, 0x20, 0x46, 0x10, 0xBD, 0x7F, 0xB5, 0x04, 0x46, 0x1D, 0x4E, 0x00, 0x25, 0x00, 0x78, 0x76, 0x1E, 0x10, 0xB1, 0x01, 0x28, 0x1E, 0xD1, 0x06, 0xE0, 0xA3, 0x78, 0x01, 0x22, 0x24, + 0x49, 0x30, 0x46, 0xFC, 0xF5, 0x12, 0xFE, 0x16, 0xE0, 0x20, 0x89, 0x63, 0x88, 0xE2, 0x88, 0x61, 0x79, 0x8D, 0xE8, 0x0F, 0x00, 0x1E, 0x49, 0x23, 0x79, 0x05, 0x22, 0x2C, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x04, 0xFE, 0x20, 0x89, 0x4F, 0xF0, 0x00, + 0x02, 0x40, 0xB1, 0x19, 0x49, 0x0C, 0x48, 0xC0, 0x31, 0xC0, 0x1E, 0xFC, 0xF5, 0xFA, 0xFD, 0x04, 0xB0, 0x28, 0x46, 0x70, 0xBD, 0x14, 0x49, 0x30, 0x46, 0x94, 0x31, 0xFC, 0xF5, 0xF2, 0xFD, 0x13, 0x48, 0x40, 0x78, 0x00, 0x28, 0xF3, 0xD0, 0x00, + 0x21, 0x01, 0x20, 0x01, 0xF0, 0x09, 0xFC, 0xEE, 0xE7, 0x8C, 0x1B, 0x80, 0x08, 0xC8, 0x1F, 0x80, 0x08, 0x03, 0x30, 0x10, 0x21, 0x38, 0x90, 0x0D, 0x00, 0x70, 0xF2, 0x20, 0x00, 0xF4, 0x20, 0x80, 0x08, 0xE0, 0x93, 0x04, 0x00, 0xA4, 0xF2, 0x20, + 0x00, 0x00, 0xF3, 0x20, 0x00, 0xF8, 0xF2, 0x20, 0x00, 0x7C, 0x1A, 0x80, 0x08, 0xF4, 0xF6, 0x20, 0x00, 0xA4, 0x22, 0x80, 0x08, 0x34, 0x18, 0x80, 0x08, 0x10, 0x14, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0x7C, 0xB5, 0x41, 0x78, 0x00, 0x25, 0x3F, + 0x4C, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x27, 0xD1, 0x0F, 0xE0, 0x81, 0x78, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x03, 0xD0, 0x20, 0xE0, 0x00, 0x22, 0x39, 0x49, 0x02, 0xE0, 0x38, 0x49, 0x00, 0x22, 0x38, 0x31, 0x20, 0x46, 0xFC, 0xF5, 0xB1, + 0xFD, 0x16, 0xE0, 0x36, 0x49, 0x88, 0x1C, 0x12, 0xF0, 0x29, 0xFC, 0x34, 0x4E, 0x32, 0x49, 0x18, 0x3E, 0x02, 0x22, 0x70, 0x8B, 0x00, 0x90, 0x33, 0x8B, 0x70, 0x31, 0x20, 0x46, 0xFC, 0xF5, 0xA1, 0xFD, 0xB0, 0x7E, 0x8D, 0xF8, 0x04, 0x00, 0x01, + 0x21, 0x01, 0xAA, 0x08, 0x46, 0xFE, 0xF7, 0x62, 0xFA, 0x28, 0x46, 0x7C, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x26, 0x4E, 0x04, 0x46, 0x03, 0x78, 0x00, 0x25, 0x01, 0x22, 0x27, 0x49, 0x30, 0x46, 0xFC, 0xF5, 0x8C, 0xFD, 0x20, 0x78, 0x01, 0x28, 0x02, + 0xD0, 0x03, 0x28, 0x3D, 0xD1, 0x1F, 0xE0, 0x20, 0x79, 0x01, 0x28, 0x02, 0xD0, 0x02, 0x28, 0x13, 0xD0, 0x36, 0xE0, 0x1F, 0x49, 0x00, 0x22, 0x24, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x7A, 0xFD, 0x01, 0x21, 0x10, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x19, + 0x48, 0x1A, 0x4B, 0x18, 0x38, 0x02, 0x22, 0x41, 0x7B, 0x00, 0x20, 0x44, 0xF6, 0x11, 0xFC, 0x23, 0xE0, 0x15, 0x49, 0x00, 0x22, 0x50, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x67, 0xFD, 0x1C, 0xE0, 0x20, 0x79, 0x4F, 0xF4, 0x90, 0x67, 0x01, 0x28, 0x16, + 0xD1, 0x0F, 0x49, 0x00, 0x22, 0x80, 0x31, 0x30, 0x46, 0xFC, 0xF5, 0x5B, 0xFD, 0x10, 0x22, 0x0D, 0x48, 0xE1, 0x68, 0x4E, 0xF6, 0x74, 0xFF, 0x10, 0x21, 0x0A, + 0x48, 0xFD, 0xF5, 0xD5, 0xFF, 0x38, 0xB9, 0x07, 0x49, 0x04, 0x48, 0x00, 0x22, 0xC0, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x4A, 0xFD, 0x3D, 0x46, 0x28, 0x46, 0x86, 0xE6, 0x02, 0x30, 0x10, 0x21, 0xFC, 0x14, 0x80, 0x08, 0x88, 0xF2, 0x20, 0x00, 0x38, + 0x17, 0x80, 0x08, 0xFC, 0xE9, 0x20, 0x00, 0x00, 0xB5, 0x9D, 0xB0, 0x1C, 0x21, 0x03, 0xA8, 0x4F, 0xF6, 0x38, 0xF8, 0xF8, 0x48, 0x07, 0xC8, 0x8D, 0xE8, 0x07, 0x00, 0x4F, 0xF4, 0xC0, 0x70, 0xAD, 0xF8, 0x6C, 0x00, 0x00, 0x20, 0x07, 0x21, 0x8D, + 0xF8, 0x34, 0x10, 0x4F, 0xF4, 0xA0, 0x71, 0xAD, 0xF8, 0x44, 0x10, 0xAD, 0xF8, 0x30, 0x10, 0x01, 0x21, 0x8D, 0xF8, 0x3C, 0x00, 0x8D, 0xF8, 0x40, 0x00, 0x0A, + 0x90, 0x0B, 0x90, 0x8D, 0xF8, 0x38, 0x00, 0x03, 0x22, 0x8D, 0xF8, 0x48, 0x10, 0xAD, 0xF8, 0x4C, 0x10, 0x8D, 0xF8, 0x50, 0x20, 0x8D, 0xF8, 0x54, 0x00, 0x8D, 0xF8, 0x58, 0x00, 0x17, 0x90, 0x8D, 0xF8, 0x60, 0x00, 0xAD, 0xF8, 0x64, 0x10, 0x8D, + 0xF8, 0x68, 0x10, 0x1A, 0xAA, 0x40, 0xF2, 0x23, 0x20, 0x41, 0xF6, 0xFA, 0xFD, 0xE0, 0x48, 0x41, 0xF6, 0xF4, 0xFD, 0x6A, 0x46, 0x28, 0x21, 0x40, 0xF2, 0x22, 0x20, 0x41, 0xF6, 0xF1, 0xFD, 0x1B, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x21, 0x20, 0x41, + 0xF6, 0xEB, 0xFD, 0x0F, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, 0x09, 0xFF, 0x10, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x19, 0x70, 0x46, 0xF6, 0x03, 0xFF, 0x0A, + 0xAA, 0x06, 0x21, 0x40, 0xF2, 0x65, 0x20, 0x46, 0xF6, 0xFD, 0xFE, 0x0D, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0xF7, 0xFE, 0x0E, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0xF1, 0xFE, 0x11, 0xAA, 0x02, 0x21, 0x4F, + 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0xEB, 0xFE, 0x0C, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0xE5, 0xFE, 0xC5, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0xDF, 0xFE, 0xC2, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, + 0x20, 0x46, 0xF6, 0xD8, 0xFE, 0x12, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x02, 0x20, 0x40, 0xF6, 0x5F, 0xFF, 0x13, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x03, 0x20, 0x40, 0xF6, 0x59, 0xFF, 0x14, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x01, 0x70, 0x40, 0xF6, 0x53, + 0xFF, 0x15, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x05, 0x20, 0x40, 0xF6, 0x4D, 0xFF, 0x17, 0xAA, 0x04, 0x21, 0x40, 0xF2, 0x11, 0x20, 0x41, 0xF6, 0x69, 0xF8, 0x16, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x12, 0x20, 0x41, 0xF6, 0x63, 0xF8, 0x18, 0xAA, 0x01, + 0x21, 0x40, 0xF2, 0x13, 0x20, 0x41, 0xF6, 0x5D, 0xF8, 0x19, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0x41, 0xF6, 0x57, 0xF8, 0x1D, 0xB0, 0x00, 0xBD, 0x2D, 0xE9, 0xF1, 0x4F, 0x86, 0xB0, 0x00, 0x24, 0x45, 0xF6, 0xF8, 0xF8, 0xA3, 0x4E, 0x05, + 0x46, 0xB3, 0x7C, 0x43, 0xB1, 0x01, 0x22, 0xA2, 0x49, 0xA2, 0x48, 0xFC, 0xF5, 0x7E, 0xFC, 0x00, 0x20, 0x07, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, 0x06, 0x99, 0x9F, 0x48, 0x01, 0x27, 0x4F, 0xF0, 0x00, 0x09, 0x4F, 0xF0, 0x03, 0x0A, + 0x4F, 0xF0, 0x07, 0x08, 0x4F, 0xF0, 0x20, 0x0B, 0x06, 0x29, 0x78, 0xD2, 0xDF, 0xE8, 0x01, 0xF0, 0x77, 0x03, 0x3A, 0xE0, 0xFE, 0x84, 0x8D, 0xF8, 0x10, 0x70, 0x8D, 0xF8, 0x04, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, + 0x63, 0x20, 0x46, 0xF6, 0x75, 0xFE, 0x05, 0xF1, 0x0E, 0x02, 0x01, 0x21, 0x4F, 0xF4, 0x19, 0x70, 0x46, 0xF6, 0x6E, 0xFE, 0x05, 0xF1, 0x08, 0x02, 0x06, 0x21, 0x40, 0xF2, 0x65, 0x20, 0x46, 0xF6, 0x67, 0xFE, 0x01, 0xAA, 0x01, 0x21, 0x40, 0xF2, + 0x67, 0x20, 0x46, 0xF6, 0x61, 0xFE, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x5B, 0xFE, 0x46, 0xF6, 0x74, 0xFF, 0x4F, 0xF0, 0x00, 0x02, 0x10, 0xB1, 0x7F, 0x49, 0x5C, 0x31, 0x5B, 0xE1, 0x7E, 0x49, 0x7E, 0x48, 0x34, 0x31, + 0x40, 0x1C, 0xFC, 0xF5, 0x34, 0xFC, 0xB7, 0x74, 0x77, 0x75, 0x0E, 0xE1, 0x8D, 0xF8, 0x10, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0xA0, 0xAD, 0xF8, 0x08, 0xB0, 0xAD, 0xF8, 0x0C, 0xB0, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, + 0x46, 0xF6, 0x3A, 0xFE, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x34, 0xFE, 0x01, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0x2E, 0xFE, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0x28, 0xFE, + 0x03, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0x22, 0xFE, 0x63, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0x1C, 0xFE, 0x60, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0x15, 0xFE, 0x46, 0xF6, + 0x2E, 0xFF, 0x4F, 0xF0, 0x00, 0x02, 0x18, 0xB1, 0x5C, 0x49, 0xB0, 0x31, 0x15, 0xE1, 0x24, 0xE1, 0x5A, 0x49, 0x5B, 0x48, 0x80, 0x31, 0x40, 0x1C, 0xFC, 0xF5, 0xED, 0xFB, 0xB7, 0x74, 0x02, 0x20, 0x70, 0x75, 0x40, 0xF6, 0xB8, 0x31, 0x57, 0xE0, + 0x54, 0x49, 0x00, 0x22, 0xDC, 0x31, 0xFC, 0xF5, 0xE2, 0xFB, 0x30, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x4E, 0x49, 0x00, 0x20, 0x8D, 0xF8, 0x10, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0xA0, 0xAD, 0xF8, 0x08, 0xB0, 0x3A, 0x31, 0x2A, 0x18, + 0x0B, 0x18, 0x12, 0x7A, 0x40, 0x1C, 0xDA, 0x74, 0x06, 0x28, 0xF8, 0xDB, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, 0xE0, 0xFD, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0xDA, 0xFD, 0x01, 0xAA, 0x01, 0x21, + 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0xD4, 0xFD, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0xCE, 0xFD, 0x03, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0xC8, 0xFD, 0x36, 0x4A, 0x19, 0x21, 0x3A, 0x32, 0x40, 0xF2, + 0x61, 0x20, 0x46, 0xF6, 0xC1, 0xFD, 0x33, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0xBA, 0xFD, 0x46, 0xF6, 0xD3, 0xFE, 0x4F, 0xF0, 0x00, 0x02, 0x08, 0xB1, 0x32, 0x49, 0xBB, 0xE0, 0x31, 0x49, 0x2E, 0x48, 0x2C, 0x39, + 0x40, 0x1C, 0xFC, 0xF5, 0x94, 0xFB, 0xB7, 0x74, 0x05, 0x20, 0x70, 0x75, 0x42, 0xF6, 0xE0, 0x61, 0x2C, 0x48, 0x1B, 0xF6, 0x7C, 0xFC, 0x68, 0xE0, 0x29, 0x49, 0x00, 0x22, 0x28, 0x31, 0xFC, 0xF5, 0x86, 0xFB, 0x30, 0x20, 0xAD, 0xF8, 0x0C, 0x00, + 0x8D, 0xF8, 0x10, 0x90, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0x90, 0xAD, 0xF8, 0x08, 0xB0, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, 0x8E, 0xFD, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x88, 0xFD, + 0x01, 0xAA, 0x00, 0xE0, 0x4B, 0xE0, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0x80, 0xFD, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0x7A, 0xFD, 0x03, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0x74, 0xFD, + 0x0C, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0x6E, 0xFD, 0x09, 0x4A, 0x04, 0x21, 0x12, 0x1F, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0x67, 0xFD, 0x46, 0xF6, 0x80, 0xFE, 0x4F, 0xF0, 0x00, 0x02, 0xA8, 0xB1, 0x08, 0x49, 0x7C, 0x31, + 0x67, 0xE0, 0x00, 0x00, 0xF8, 0xE6, 0x21, 0x00, 0xB5, 0xAC, 0x20, 0x00, 0xC8, 0xE6, 0x20, 0x00, 0x70, 0xF2, 0x20, 0x00, 0xD0, 0x22, 0x80, 0x08, 0x01, 0x30, 0x10, 0x21, 0x02, 0x33, 0x10, 0x21, 0x04, 0x24, 0x80, 0x08, 0xA0, 0xF2, 0x20, 0x00, + 0x76, 0x49, 0x77, 0x48, 0xFC, 0xF5, 0x2F, 0xFB, 0xB7, 0x74, 0x86, 0xF8, 0x15, 0xA0, 0x44, 0xF6, 0x20, 0x61, 0x74, 0x48, 0x1B, 0xF6, 0x17, 0xFC, 0x00, 0x22, 0x05, 0x21, 0x26, 0x20, 0x01, 0xF0, 0xAB, 0xFA, 0x01, 0x24, 0x59, 0xE0, 0x6D, 0x49, + 0x00, 0x22, 0x54, 0x31, 0xFC, 0xF5, 0x1B, 0xFB, 0x30, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x8D, 0xF8, 0x10, 0xA0, 0x8D, 0xF8, 0x00, 0x80, 0x8D, 0xF8, 0x04, 0xA0, 0xAD, 0xF8, 0x08, 0xB0, 0x04, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x63, 0x20, 0x46, 0xF6, + 0x23, 0xFD, 0x6A, 0x46, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x46, 0xF6, 0x1D, 0xFD, 0x01, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x46, 0xF6, 0x17, 0xFD, 0x02, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x1A, 0x70, 0x46, 0xF6, 0x11, 0xFD, 0x03, 0xAA, + 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x46, 0xF6, 0x0B, 0xFD, 0x59, 0x4A, 0x1D, 0x21, 0x40, 0xF2, 0x61, 0x20, 0x46, 0xF6, 0x05, 0xFD, 0x56, 0x4A, 0x04, 0x21, 0x21, 0x3A, 0x40, 0xF2, 0x62, 0x20, 0x46, 0xF6, 0xFE, 0xFC, 0x46, 0xF6, 0x17, 0xFE, + 0x4F, 0xF0, 0x00, 0x02, 0x30, 0xB1, 0x4D, 0x49, 0xA4, 0x31, 0x4D, 0x48, 0x40, 0x1E, 0xFC, 0xF5, 0xDA, 0xFA, 0x12, 0xE0, 0x49, 0x49, 0x4A, 0x48, 0x78, 0x31, 0xFC, 0xF5, 0xD4, 0xFA, 0xB7, 0x74, 0x04, 0x20, 0x70, 0x75, 0x41, 0xF2, 0x88, 0x31, + 0x3E, 0xE7, 0x0B, 0x46, 0x43, 0x49, 0x44, 0x48, 0x01, 0x22, 0xCC, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0xC6, 0xFA, 0x20, 0x46, 0x46, 0xE6, 0x70, 0xB5, 0x42, 0x4D, 0x3F, 0x4E, 0x00, 0x24, 0xA8, 0x75, 0xAB, 0x7C, 0x76, 0x1E, 0x01, 0x2B, 0x06, 0xD0, + 0x01, 0x22, 0x3F, 0x49, 0x30, 0x46, 0xFC, 0xF5, 0xB6, 0xFA, 0x20, 0x46, 0x70, 0xBD, 0x46, 0xF6, 0x48, 0xFE, 0x4F, 0xF0, 0x00, 0x02, 0x28, 0xB1, 0x39, 0x49, 0x30, 0x46, 0x30, 0x39, 0xFC, 0xF5, 0xAA, 0xFA, 0xF2, 0xE7, 0x36, 0x49, 0x32, 0x48, + 0x68, 0x39, 0xFC, 0xF5, 0xA4, 0xFA, 0x02, 0x20, 0xA8, 0x74, 0x01, 0x24, 0xE9, 0xE7, 0x70, 0xB5, 0x01, 0x46, 0x30, 0x48, 0x2C, 0x4D, 0x00, 0x24, 0xC1, 0x75, 0x83, 0x7C, 0x6D, 0x1E, 0x03, 0x2B, 0x09, 0xD0, 0x04, 0x2B, 0x07, 0xD0, 0x2C, 0x49, + 0x01, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x8E, 0xFA, 0x20, 0x46, 0x70, 0xBD, 0x00, 0x20, 0x42, 0xF6, 0x6C, 0xFB, 0x4F, 0xF0, 0x00, 0x02, 0x28, 0xB1, 0x25, 0x49, 0x28, 0x46, 0x70, 0x31, 0xFC, 0xF5, 0x81, 0xFA, 0xF1, 0xE7, 0x22, 0x49, + 0x1D, 0x48, 0x2C, 0x31, 0xFC, 0xF5, 0x7B, 0xFA, 0x01, 0x24, 0xEA, 0xE7, 0x3E, 0xB5, 0x1D, 0x4C, 0x0B, 0x46, 0x00, 0x21, 0xE1, 0x71, 0x0A, + 0x21, 0xB2, 0xFB, 0xF1, 0xF2, 0x6F, 0xF0, 0x01, 0x01, 0x01, 0xEB, 0x40, 0x01, 0x89, 0xB2, 0xCD, 0xE9, 0x00, 0x21, 0x02, 0x46, 0x02, 0x91, 0x11, 0x46, 0x00, 0x20, 0x42, 0xF6, 0x7A, 0xFB, 0x00, 0x28, 0x1A, 0xD0, 0x0F, 0x48, 0xE1, 0x79, 0x40, + 0x1E, 0x03, 0x29, 0x0E, 0xD2, 0x49, 0x1C, 0xE1, 0x71, 0x0F, 0x49, 0x00, 0x22, 0xE4, 0x31, 0xFC, 0xF5, 0x56, 0xFA, 0x03, 0xB0, 0x41, 0xF2, 0x88, 0x31, 0xBD, 0xE8, 0x30, 0x40, 0x0B, 0x48, 0x1B, 0xF6, 0x3E, 0xBB, 0x03, 0xB0, 0x00, 0x22, 0xBD, + 0xE8, 0x30, 0x40, 0x09, 0x49, 0xFC, 0xF5, 0x47, 0xBA, 0x3E, 0xBD, 0x00, 0x00, 0x54, 0x24, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0xA0, 0xF2, 0x20, 0x00, 0xE5, 0xE6, 0x20, 0x00, 0x70, 0xF2, 0x20, 0x00, 0xB0, 0x25, 0x80, 0x08, 0xA8, 0xF2, 0x20, + 0x00, 0xC8, 0x26, 0x80, 0x08, 0x7C, 0xB5, 0x26, 0x48, 0x00, 0x24, 0xCD, 0xE9, 0x00, 0x40, 0x44, 0xF6, 0x20, 0x63, 0x01, 0x22, 0x23, 0xA1, 0x26, 0x48, 0x1B, 0xF6, 0xE5, 0xFA, 0x25, 0x4D, 0x20, 0xB9, 0x00, 0x22, 0x25, 0x49, 0x28, 0x46, 0xFC, + 0xF5, 0x22, 0xFA, 0x24, 0x48, 0x42, 0xF6, 0xE0, 0x63, 0xCD, 0xE9, 0x00, 0x40, 0x1E, 0x48, 0x01, 0x22, 0x21, 0xA1, 0x0C, 0x30, 0x1B, 0xF6, 0xD3, 0xFA, 0x28, 0xB9, 0x1D, 0x49, 0x00, 0x22, 0x2C, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x10, 0xFA, 0x22, + 0x48, 0x22, 0x4B, 0xCD, 0xE9, 0x00, 0x40, 0x16, 0x48, 0x01, 0x22, 0x21, 0xA1, 0x00, 0x1D, 0x1B, 0xF6, 0xC2, 0xFA, 0x28, 0xB9, 0x14, 0x49, 0x00, 0x22, 0x64, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xFF, 0xF9, 0x21, 0x48, 0x41, 0xF2, 0x88, 0x33, 0xCD, + 0xE9, 0x00, 0x40, 0x0D, 0x48, 0x01, 0x22, 0x1F, 0xA1, 0x08, 0x30, 0x1B, 0xF6, 0xB0, 0xFA, 0x28, 0xB9, 0x0B, 0x49, 0x00, 0x22, 0x98, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0xED, 0xF9, 0x00, 0xF0, 0x0F, 0xFD, 0xBD, 0xE8, 0x7C, 0x40, 0x00, 0xF0, 0x01, + 0xBE, 0xE5, 0x83, 0x20, 0x00, 0x61, 0x64, 0x76, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0xA0, 0xF2, 0x20, 0x00, 0x02, 0x30, 0x10, 0x21, 0x94, 0x27, 0x80, 0x08, 0x09, 0x84, 0x20, 0x00, 0x70, 0x61, 0x69, 0x72, 0x5F, 0x66, 0x61, + 0x69, 0x6C, 0x5F, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x73, 0x84, 0x20, 0x00, 0xE0, 0x93, 0x04, 0x00, 0x6E, 0x6F, 0x5F, 0x61, 0x63, 0x74, 0x5F, 0x64, 0x69, 0x73, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, + 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00, 0x29, 0x84, 0x20, 0x00, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5F, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0xB5, 0x02, 0x22, 0x8D, 0xF8, 0x04, 0x20, 0x3D, 0x22, 0x38, 0x4C, 0x00, 0x92, 0x01, 0x46, 0x35, 0x4B, 0x00, 0x22, 0xA0, 0x68, 0x1A, 0xF6, 0x61, 0xFC, 0x35, 0x4D, 0x50, 0xB1, 0x42, 0x20, 0x00, 0x90, 0x31, 0x4B, 0x00, 0x22, 0x01, + 0xA9, 0x60, 0x68, 0x1A, 0xF6, 0x57, 0xFC, 0x20, 0xB1, 0x01, 0x20, 0x7C, 0xBD, 0x00, 0x22, 0x2F, 0x49, 0x02, 0xE0, 0x2E, 0x49, 0x00, 0x22, 0x1C, 0x31, 0x28, 0x46, 0xFC, 0xF5, 0x88, 0xF9, 0x00, 0x20, 0x7C, 0xBD, 0x1F, 0xB5, 0x5B, 0x20, 0x00, + 0x90, 0x25, 0x4B, 0x26, 0x48, 0x18, 0x33, 0x08, 0x22, 0x20, 0x21, 0x08, 0x30, 0x1A, 0xF6, 0xC6, 0xFB, 0x5C, 0x20, 0x00, 0x90, 0x20, 0x4B, 0x21, 0x48, 0x18, 0x33, 0x01, 0x22, 0x40, 0x21, 0x00, 0x1D, 0x1A, 0xF6, 0xBC, 0xFB, 0x1D, 0x4C, 0x20, + 0x22, 0xD4, 0xE9, 0x01, 0x01, 0x40, 0xF6, 0x71, 0xFB, 0x00, 0xF0, 0xA6, 0xF8, 0x67, 0x25, 0x4F, 0xF0, 0xFF, 0x37, 0x6D, 0x26, 0x16, 0x4B, 0x00, 0x95, 0x18, 0x33, 0x3A, 0x46, 0x03, 0xA9, 0x60, 0x68, 0x1A, 0xF6, 0x50, 0xFC, 0x00, 0x28, 0xF5, + 0xD0, 0x9D, 0xF8, 0x0C, 0x00, 0x02, 0x28, 0x02, 0xD0, 0x40, 0xF6, 0xC8, 0xFB, 0xEE, 0xE7, 0x0E, 0x4B, 0x00, 0x96, 0x18, 0x33, 0x00, 0x22, 0x01, 0xA9, 0xA0, 0x68, 0x1A, 0xF6, 0x3F, 0xFC, 0x00, 0x28, 0xE4, 0xD0, 0xDD, 0xE9, 0x01, 0x01, 0xFF, + 0xF7, 0x29, 0xFA, 0xDF, 0xE7, 0x1C, 0xB5, 0x01, 0x21, 0xC8, 0x02, 0x00, 0x23, 0xAF, 0xF2, 0x8D, 0x02, 0xCD, 0xE9, 0x00, 0x01, 0x06, 0xA1, 0x03, 0x48, 0x1B, 0xF6, 0xF2, 0xF8, 0x1C, 0xBD, 0x00, 0x00, 0x04, 0xE7, 0x21, 0x00, 0xB0, 0xF2, 0x20, + 0x00, 0x00, 0x30, 0x10, 0x21, 0x64, 0x28, 0x80, 0x08, 0x61, 0x70, 0x70, 0x00, 0x10, 0xB5, 0x03, 0x28, 0x01, 0xD3, 0x00, 0x20, 0x10, 0xBD, 0x1A, 0x49, 0x00, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x80, 0x04, 0x08, 0x22, 0x18, 0x49, 0x20, 0x68, 0x4E, + 0xF6, 0xF1, 0xFA, 0x98, 0xB1, 0xA2, 0x69, 0x61, 0x68, 0xE0, 0x68, 0x4E, 0xF6, 0x36, 0xFB, 0xE2, 0x69, 0xA1, 0x68, 0x20, 0x69, 0x4E, 0xF6, 0x31, 0xFB, 0x21, 0x6A, 0x60, 0x69, 0x4E, 0xF6, 0xEE, 0xFB, 0x20, 0x68, 0x0E, 0x49, 0x02, 0x68, 0x0A, + 0x60, 0x40, 0x68, 0x48, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x09, 0x4D, 0x00, 0x24, 0x04, 0xEB, 0xC4, 0x00, 0x08, 0x22, 0x55, 0xF8, 0x20, 0x00, 0x06, 0x49, 0x4E, 0xF6, 0xCF, 0xFA, 0x20, 0xB1, 0x64, 0x1C, 0x03, 0x2C, 0xF3, 0xDB, 0x03, + 0x20, 0x70, 0xBD, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0x00, 0x1C, 0xE7, 0x20, 0x00, 0xBC, 0xF2, 0x20, 0x00, 0x30, 0xB5, 0x01, 0x22, 0x91, 0xB0, 0x15, 0x49, 0x10, 0x04, 0x10, 0xF0, 0x97, 0xFC, 0x68, 0x46, 0x11, 0xF0, 0x95, 0xF9, 0x00, 0x20, 0xAD, + 0xF8, 0x0A, + 0x00, 0x11, 0x48, 0x11, 0x4C, 0x01, 0x25, 0x03, 0x90, 0xAD, 0xF8, 0x08, 0x50, 0x69, 0x46, 0x20, 0x46, 0x11, 0xF0, 0xF5, 0xF8, 0x03, 0x20, 0x08, 0x21, 0x0E, 0x90, 0x8D, 0xF8, 0x34, 0x10, 0x8D, 0xF8, 0x3C, 0x50, 0x0D, 0xA8, 0x05, 0xF6, 0xFF, + 0xFC, 0xE0, 0x68, 0x01, 0x21, 0x20, 0x46, 0x11, 0xF0, 0x93, 0xF9, 0x01, 0x21, 0x20, 0x46, 0x11, 0xF0, 0x83, 0xF9, 0x11, 0xB0, 0x30, 0xBD, 0xD2, 0xE7, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0xFF, 0xB3, 0xC4, 0x04, 0x78, 0x20, 0x00, 0x40, 0x10, + 0xB5, 0xFC, 0x4C, 0x00, 0x22, 0xFA, 0x49, 0x20, 0x46, 0xFC, 0xF5, 0xB4, 0xF8, 0xFA, 0x49, 0x4F, 0xF4, 0x00, 0x00, 0x01, 0xF0, 0x4C, 0xFD, 0x00, 0x28, 0x08, 0xD0, 0xF6, 0x48, 0xF4, 0x49, 0x01, 0x22, 0x03, 0x78, 0x30, 0x31, 0x20, 0x46, 0xFC, + 0xF5, 0xA5, 0xF8, 0x01, 0x20, 0x10, 0xBD, 0xF1, 0x48, 0x00, 0x78, 0xFF, 0x28, 0x01, 0xD0, 0x12, 0xF0, 0x90, 0xB9, 0x70, 0x47, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x02, 0x20, 0x00, 0xF6, 0x7A, 0xFB, 0x04, 0x46, 0x00, 0x90, 0xE8, 0x49, 0xE8, + 0x48, 0x2B, 0x46, 0x02, 0x22, 0x70, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x8C, 0xF8, 0x20, 0x46, 0x38, 0xBD, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x04, 0x20, 0x00, 0xF6, 0x68, 0xFB, 0x04, 0x46, 0x00, 0x90, 0xDF, 0x49, 0xDF, 0x48, 0x2B, 0x46, 0x02, + 0x22, 0xAC, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x7A, 0xF8, 0x20, 0x46, 0x38, 0xBD, 0x70, 0xB5, 0x0D, 0x46, 0x00, 0x24, 0x00, 0xF6, 0x84, 0xFF, 0x20, 0xB1, 0x28, 0x44, 0xFF, 0xF7, 0xD3, 0xFF, 0x10, 0xB1, 0x02, 0xE0, 0x66, 0x24, 0x00, 0xE0, 0x6C, + 0x24, 0xD3, 0x49, 0xD3, 0x48, 0x23, 0x46, 0x01, 0x22, 0xE8, 0x31, 0x40, 0x1E, 0xFC, 0xF5, 0x62, 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x2D, 0xE9, 0xFC, 0x47, 0x16, 0x46, 0x0D, 0x46, 0xDF, 0xF8, 0x34, 0x93, 0xCD, 0xE9, 0x00, 0x56, 0x04, 0x46, 0x03, + 0x46, 0xA9, 0xF1, 0x01, 0x09, 0x00, 0x27, 0x03, 0x22, 0xCA, 0x49, 0x48, 0x46, 0xFC, 0xF5, 0x4E, 0xF8, 0xA4, 0xF5, 0x7F, 0x40, 0xFE, 0x38, 0x15, 0xD0, 0x1A, 0xF6, 0x41, 0xFF, 0x80, 0x46, 0x32, 0x46, 0x29, 0x46, 0x20, 0x46, 0x3B, 0xF6, 0xF8, + 0xFE, 0x07, 0x46, 0x40, 0x46, 0x1A, 0xF6, 0x44, 0xFF, 0xC0, 0x49, 0x3B, 0x46, 0x01, 0x22, 0x70, 0x31, 0x48, 0x46, 0xFC, 0xF5, 0x37, 0xF8, 0x38, 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x00, 0x24, 0x05, 0x20, 0x00, 0xF6, 0xA1, 0xFA, 0x05, 0x44, 0x13, + 0xE0, 0x6A, 0x46, 0x04, 0x21, 0x28, 0x46, 0x00, 0xF6, 0x77, 0xFD, 0x00, 0x98, 0x40, 0x1C, 0x09, 0xD0, 0xB4, 0x49, 0xB1, 0x48, 0x23, 0x46, 0x01, 0x22, 0x44, 0x31, 0xC0, 0x1E, 0xFC, 0xF5, 0x1E, 0xF8, 0x85, 0x27, 0xDD, 0xE7, 0x64, 0x1C, 0x2D, + 0x1D, 0xB4, 0xEB, 0x96, 0x0F, 0xE8, 0xD3, 0xD7, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x0E, 0x46, 0x00, 0x24, 0xA0, 0xF5, 0x7F, 0x41, 0x91, 0x46, 0x80, 0x46, 0xFE, 0x39, 0x1B, 0xD0, 0x00, 0xF6, 0x1B, 0xFF, 0xE0, 0xB1, 0x87, 0x19, 0x38, 0x46, 0xFF, + 0xF7, 0x69, 0xFF, 0x4A, 0x46, 0x31, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xA0, 0xFF, 0x05, 0x00, 0x02, 0xD0, 0x64, 0x1C, 0x03, 0x2C, 0xF2, 0xD3, 0x9E, 0x49, 0x23, 0x46, 0x02, 0x22, 0x98, 0x31, 0x9A, 0x48, 0x00, 0x95, 0xFB, 0xF5, 0xF3, 0xFF, 0x28, + 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x20, 0x00, 0xF6, 0x5E, 0xFA, 0xE1, 0xE7, 0xB1, 0x25, 0xEE, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, 0x04, 0x46, 0x00, 0x25, 0x00, 0xF6, 0xD6, 0xFE, 0x90, 0xF0, 0x01, 0x0F, 0x42, 0xF2, 0x91, 0x77, 0x42, 0xF2, 0x92, + 0x78, 0x42, 0xF2, 0x93, 0x79, 0x42, 0xF2, 0x94, 0x7A, 0x42, 0xF2, 0x95, 0x7B, 0x0E, 0xD0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x2E, 0xD1, 0x04, 0x20, 0x00, 0xF6, 0x77, + 0xFA, 0x05, 0x46, 0x29, 0xE0, 0x02, 0x20, 0x00, 0xF6, 0x36, 0xFA, 0x06, 0x46, 0xF5, 0xF5, 0x79, 0xFB, 0xB0, 0x42, 0x03, 0xD1, 0x03, 0x20, 0x00, 0xF6, 0x2E, 0xFA, 0x06, 0x46, 0x42, 0xF2, 0x90, 0x71, 0x8C, 0x42, 0x02, 0xD1, 0x4F, 0xF4, 0x80, + 0x55, 0x16, 0xE0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x0C, 0xD1, 0x30, 0x46, 0x00, 0xF6, 0x4D, 0xFE, 0x40, 0xB1, 0x06, 0xEB, 0xC4, 0x00, 0xA0, 0xF5, 0xA0, 0x30, 0xD0, + 0xF8, 0x14, 0x55, 0x68, 0x1C, 0x00, 0xD1, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFC, 0x41, 0x0E, 0x46, 0x08, 0x9C, 0x4F, 0xF0, 0x00, 0x01, 0x1D, 0x00, 0x17, 0x46, 0x21, 0x60, 0x0F, 0xD0, 0xA0, 0xF5, 0x7F, 0x41, 0xFE, + 0x39, 0x07, 0xD0, 0xFF, 0xF7, 0xA1, 0xFF, 0xDF, 0xF8, 0x90, 0xC1, 0xAC, 0xF1, 0x03, 0x0C, 0x3E, 0xB1, 0x15, 0xE0, 0x05, 0x20, 0x00, 0xF6, 0x2F, 0xFA, 0xF5, 0xE7, 0x4F, 0xF4, 0xE3, 0x70, 0x1B, 0xE0, 0xAB, 0x68, 0x03, 0xF5, 0x80, 0x63, 0x83, + 0x42, 0x09, 0xD9, 0x5D, 0x49, 0x00, 0x90, 0x02, 0x22, 0xC4, 0x31, 0x60, 0x46, 0xFB, 0xF5, 0x72, 0xFF, 0x40, 0xF2, 0xDD, 0x10, 0x0C, 0xE0, 0xF1, 0x19, 0x81, 0x42, 0x0D, 0xD9, 0xCD, 0xE9, 0x00, 0x70, 0x33, 0x46, 0x03, 0x22, 0x56, 0x49, 0x60, + 0x46, 0xFB, 0xF5, 0x64, 0xFF, 0x4F, 0xF4, 0xF3, 0x70, 0x20, 0x60, 0x00, 0x20, 0xBD, 0xE8, 0xFC, 0x81, 0x01, 0x20, 0xFB, 0xE7, 0x2D, 0xE9, 0xFF, 0x47, 0x80, 0x46, 0x00, 0x91, 0x16, 0x46, 0x00, 0x20, 0x0D, 0x46, 0xDF, 0xF8, 0x24, 0xA1, 0xCD, + 0xE9, 0x01, 0x60, 0x4A, 0x49, 0x1C, 0x46, 0xAA, 0xF1, 0x01, 0x0A, + 0x43, 0x46, 0x03, 0x22, 0x54, 0x31, 0x50, 0x46, 0xFB, 0xF5, 0x47, 0xFF, 0xB0, 0x07, 0x02, 0xD0, 0x40, 0xF2, 0x4F, 0x20, 0x60, 0xE0, 0x3C, 0xB1, 0xA8, 0xF5, 0x7F, 0x41, 0x40, 0x46, 0xFE, 0x39, 0x05, 0xD0, 0x00, 0xF6, 0x4B, 0xFE, 0x05, 0xE0, + 0x40, 0xF2, 0x55, 0x20, 0x54, 0xE0, 0x05, 0x20, 0x00, 0xF6, 0xA4, 0xF9, 0x07, 0x00, 0x0C, 0xD0, 0x02, 0xA8, 0x00, 0x90, 0x23, 0x46, 0x32, 0x46, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x8E, 0xFF, 0xF0, 0xB3, 0xDF, 0xF8, 0xCC, 0x90, 0x1D, 0xB1, + 0x0E, 0xE0, 0x4F, 0xF4, 0x1C, 0x70, 0x3F, 0xE0, 0x60, 0x88, 0x32, 0x49, 0x40, 0xF0, 0x80, 0x00, 0x60, 0x80, 0x43, 0x46, 0x02, 0x22, 0x90, 0x31, 0x48, 0x46, 0x00, 0x97, 0xFB, 0xF5, 0x15, 0xFF, 0x78, 0x19, 0x07, 0x46, 0x29, 0x05, 0x0B, 0xD0, + 0xC5, 0xF3, 0x0B, 0x01, 0x31, 0x44, 0x4F, 0xF4, 0x80, 0x52, 0x91, 0x42, 0x07, 0xD9, 0x96, 0x42, 0x05, 0xD8, 0xB8, 0x19, 0x6F, 0xF3, 0x0B, 0x00, 0xFF, 0xF7, 0x67, 0xFE, 0x08, 0xB1, 0x00, 0x25, 0x22, 0xE0, 0x40, 0xF2, 0xF6, 0x20, 0x1B, 0xE0, + 0x78, 0x19, 0x80, 0x46, 0x21, 0x68, 0x00, 0xF6, 0x22, 0xFC, 0x48, 0xF0, 0x80, 0x70, 0x03, 0xA9, 0x00, 0xF6, 0x55, 0xFC, 0x20, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0F, 0xD0, 0x78, 0x19, 0xCD, 0xE9, 0x00, 0x10, 0x03, 0x22, 0x17, 0x49, 0x00, 0xE0, + 0x0C, 0xE0, 0xD8, 0x31, 0x48, 0x46, 0x23, 0x68, 0xFB, 0xF5, 0xE3, 0xFE, 0x40, 0xF2, 0x07, 0x30, 0x02, 0x90, 0x03, 0xE0, 0x24, 0x1D, 0x2D, 0x1D, 0xB5, 0x42, 0xDD, 0xD3, 0x01, 0x22, 0x10, 0x49, 0x50, 0x46, 0x02, 0x9B, 0xFB, 0xF5, 0xD5, 0xFE, + 0x02, 0x98, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x46, 0x01, 0x20, 0xA1, 0xF5, 0x7F, 0x42, 0xFE, 0x3A, 0x02, 0xD0, 0x08, 0x46, 0x3B, 0xF6, 0x13, 0xBD, 0x08, 0x4A, 0x00, 0x21, 0x11, 0x60, 0x70, 0x47, 0x00, 0x00, 0x88, 0x2E, 0x80, 0x08, + 0x03, 0x31, 0x10, 0x21, 0x88, 0xE7, 0x20, 0x00, 0xA4, 0x2F, 0x80, 0x08, 0xA8, 0x30, 0x80, 0x08, 0xBC, 0x31, 0x80, 0x08, 0xC4, 0xF2, 0x20, 0x00, 0xF8, 0xB5, 0x04, 0x46, 0xA0, 0xF5, 0x7F, 0x40, 0x4F, 0xF4, 0x00, 0x15, 0xFE, 0x38, 0x17, 0xD0, + 0xFF, 0xF7, 0xF0, 0xFD, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0xF6, 0xF9, 0x20, 0x46, 0x3B, 0xF6, 0x8B, 0xFD, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0x3F, 0xFA, + 0xFF, 0xF7, 0xF4, 0xFD, 0x30, 0x46, 0xF8, 0xBD, 0x20, 0x46, 0xFF, 0xF7, 0xC1, 0xFF, 0x05, 0x20, 0x00, 0xF6, 0x00, 0xF9, 0x40, 0xF0, 0x80, 0x74, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0xD8, 0xF9, 0x20, 0x46, + 0x00, 0xF6, 0x22, 0xFD, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFE, 0xF5, 0x21, 0xFA, 0x6A, 0x46, 0x04, 0x21, 0x20, 0x46, 0x00, 0xF6, 0xC4, 0xFB, 0x00, 0x98, 0x6A, 0x46, 0x20, 0xF4, 0x00, 0x00, 0x00, 0x90, + 0x04, 0x21, 0x20, 0x46, 0x00, 0xF6, 0x83, 0xFB, 0xD4, 0xE7, 0x00, 0x00, 0x2D, 0xE9, 0xFC, 0x41, 0x1C, 0x46, 0x16, 0x46, 0x13, 0x46, 0x0F, 0x46, 0x0A, + 0x46, 0x08, 0x9D, 0x80, 0x46, 0x01, 0x46, 0x14, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x1B, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x13, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x13, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x12, + 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x0B, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x11, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0x03, 0xFB, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x10, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xFB, + 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x23, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xF3, 0xFA, 0xBD, 0xE8, 0xFC, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0x1C, 0x46, 0x16, 0x46, 0x13, 0x46, 0x0F, 0x46, 0x0A, + 0x46, 0x08, 0x9D, 0x80, 0x46, 0x01, 0x46, 0x22, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xE2, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x21, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xDA, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x20, + 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xD2, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x07, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xCA, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x06, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xC2, + 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x05, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xBA, 0xFA, 0x33, 0x46, 0x3A, 0x46, 0x41, 0x46, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x45, 0x05, 0xF6, 0xB2, 0xFA, 0xBD, 0xE7, 0x10, 0xB5, 0x08, 0x20, 0x05, + 0xF6, 0xF4, 0xFA, 0x01, 0x22, 0x11, 0x46, 0x14, 0x20, 0x05, 0xF6, 0x39, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x13, 0x20, 0x05, 0xF6, 0x34, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x12, 0x20, 0x05, 0xF6, 0x2F, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x11, 0x20, 0x05, + 0xF6, 0x2A, 0xFB, 0x01, 0x22, 0x11, 0x46, 0x10, 0x20, 0x05, 0xF6, 0x25, 0xFB, 0x01, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x11, 0x46, 0x23, 0x20, 0x05, 0xF6, 0x1E, 0xBB, 0x10, 0xB5, 0x14, 0x20, 0x05, 0xF6, 0x33, 0xFB, 0x13, 0x20, 0x05, 0xF6, 0x30, + 0xFB, 0x12, 0x20, 0x05, 0xF6, 0x2D, 0xFB, 0x11, 0x20, 0x05, 0xF6, 0x2A, 0xFB, 0x10, 0x20, 0x05, 0xF6, 0x27, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x23, 0x20, 0x05, 0xF6, 0x22, 0xBB, 0x10, 0xB5, 0x2C, 0x21, 0x78, 0x48, 0x4E, 0xF6, 0xB5, 0xF8, 0x77, + 0x48, 0x01, 0x21, 0x41, 0x70, 0xC1, 0x70, 0x10, 0xBD, 0x70, 0xB5, 0x75, 0x4C, 0x75, 0x4E, 0x05, 0x46, 0x8E, 0xB0, 0x00, 0x22, 0x21, 0x46, 0x30, 0x46, 0x10, 0xF0, 0x54, 0xF9, 0x01, 0x22, 0x21, 0x46, 0x30, 0x46, 0x10, 0xF0, 0x4F, 0xF9, 0x6D, + 0x48, 0x00, 0x24, 0x04, 0x70, 0x68, 0x46, 0x10, 0xF0, 0xE7, 0xF8, 0x07, 0x20, 0xAD, 0xF8, 0x02, 0x00, 0x06, 0x20, 0xAD, 0xF8, 0x00, 0x00, 0x26, 0x20, 0xAD, 0xF8, 0x2C, 0x00, 0x0F, 0x20, 0x8D, 0xF8, 0x2E, 0x00, 0x0A, + 0x94, 0xCD, 0xE9, 0x03, 0x54, 0x4F, 0xF4, 0xC8, 0x70, 0xAD, 0xF8, 0x0A, + 0x00, 0x40, 0x20, 0x05, 0x94, 0x8D, 0xF8, 0x32, 0x00, 0x01, 0x20, 0x61, 0x4C, 0x8D, 0xF8, 0x33, 0x00, 0x69, 0x46, 0x20, 0x46, 0x10, 0xF0, 0x70, 0xF8, 0x01, 0x22, 0x04, 0x21, 0x20, 0x46, 0x10, 0xF0, 0xE2, 0xF8, 0xE0, 0x69, 0x40, 0xF0, 0x04, + 0x00, 0xE0, 0x61, 0x00, 0x22, 0x04, 0x21, 0x20, 0x46, 0x10, 0xF0, 0xE1, 0xF8, 0x01, 0x21, 0x20, 0x46, 0x10, 0xF0, 0xF0, 0xF8, 0x0E, 0xB0, 0x70, 0xBD, 0x0E, 0xB5, 0x36, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x03, 0x20, 0x01, 0x90, 0x01, 0x20, 0x8D, + 0xF8, 0x08, 0x00, 0x68, 0x46, 0x05, 0xF6, 0x8C, 0xF9, 0x0E, 0xBD, 0x10, 0xB5, 0x4E, 0x21, 0x14, 0x20, 0x05, 0xF6, 0xE0, 0xF9, 0x4F, 0x21, 0x13, 0x20, 0x05, 0xF6, 0xDC, 0xF9, 0x50, 0x21, 0x12, 0x20, 0x05, 0xF6, 0xD8, 0xF9, 0x51, 0x21, 0x11, + 0x20, 0x05, 0xF6, 0xD4, 0xF9, 0x52, 0x21, 0x10, 0x20, 0x05, 0xF6, 0xD0, 0xF9, 0x53, 0x21, 0x23, 0x20, 0x05, 0xF6, 0xCC, 0xF9, 0x3A, 0x21, 0x22, 0x20, 0x05, 0xF6, 0xC8, 0xF9, 0x3B, 0x21, 0x21, 0x20, 0x05, 0xF6, 0xC4, 0xF9, 0x3C, 0x21, 0x20, + 0x20, 0x05, 0xF6, 0xC0, 0xF9, 0x3D, 0x21, 0x07, 0x20, 0x05, 0xF6, 0xBC, 0xF9, 0x3E, 0x21, 0x06, 0x20, 0x05, 0xF6, 0xB8, 0xF9, 0x3F, 0x21, 0x05, 0x20, 0x05, 0xF6, 0xB4, 0xF9, 0x40, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x20, 0x05, 0xF6, 0xAE, + 0xB9, 0x38, 0xB5, 0x00, 0x24, 0x01, 0x22, 0x23, 0x46, 0x11, 0x46, 0x10, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0xAF, 0xFE, 0x01, 0x23, 0x00, 0x22, 0x19, 0x46, 0x18, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0xE1, 0xFE, 0x38, 0xBD, 0x38, 0xB5, 0x00, 0x24, 0x01, + 0x23, 0x22, 0x46, 0x19, 0x46, 0x20, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0xD7, 0xFE, 0x21, 0x48, 0xC0, 0x78, 0x01, 0x28, 0x09, 0xD0, 0xFF, 0xF7, 0x35, 0xFF, 0x00, 0x23, 0x02, 0x22, 0x00, 0x94, 0x01, 0x21, 0x00, 0x20, 0xFF, 0xF7, 0x91, 0xFE, 0x38, + 0xBD, 0xFF, 0xF7, 0x07, 0xFF, 0x00, 0x23, 0x01, 0x22, 0x00, 0x94, 0xF4, 0xE7, 0x38, 0xB5, 0x00, 0x24, 0x01, 0x22, 0x23, 0x46, 0x11, 0x46, 0x10, 0x46, 0x00, 0x94, 0xFF, 0xF7, 0x81, 0xFE, 0x01, 0x23, 0x00, 0x22, 0x19, 0x46, 0x18, 0x46, 0x00, + 0x94, 0xFF, 0xF7, 0xB3, 0xFE, 0x0F, 0x48, 0xC0, 0x78, 0x01, 0x28, 0x03, 0xD1, 0xBD, 0xE8, 0x38, 0x40, 0xC0, 0x07, 0x2D, 0xE7, 0x38, 0xBD, 0x1C, 0xB5, 0x0E, 0x49, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x08, 0x48, 0x32, 0x23, 0x01, 0x22, 0x0C, + 0xA1, 0x00, 0x1F, 0x1A, 0xF6, 0x8C, 0xFD, 0x00, 0x28, 0x07, 0xD1, 0x02, 0xB0, 0x00, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x0B, 0x49, 0x0B, 0x48, 0xFB, 0xF5, 0xC6, 0xBC, 0x1C, 0xBD, 0xCC, 0xF2, 0x20, 0x00, 0x40, 0x00, 0x00, 0x60, 0x00, 0x00, 0x08, + 0x08, 0x00, 0x50, 0x00, 0x40, 0xC1, 0x85, 0x20, 0x00, 0x6B, 0x65, 0x79, 0x73, 0x63, 0x61, 0x6E, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x00, 0xB0, 0x32, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x2D, 0xE9, 0xFF, 0x47, 0x06, 0x46, 0xD0, + 0x48, 0xDF, 0xF8, 0x48, 0x83, 0x00, 0x25, 0x30, 0xF8, 0x16, 0x40, 0xCE, 0x48, 0x33, 0x46, 0x03, 0x22, 0x47, 0x78, 0xCD, 0x49, 0xCD, 0xE9, 0x00, 0x47, 0x40, 0x46, 0xFB, 0xF5, 0x9C, 0xFC, 0x00, 0x20, 0xCB, 0x49, 0x01, 0x22, 0xA8, 0xF1, 0x01, + 0x09, 0x16, 0xB1, 0x14, 0x2E, 0x02, 0xD3, 0x1A, 0xE0, 0x14, 0x2F, 0x18, 0xD2, 0x4B, 0x78, 0x93, 0xB1, 0x02, 0x90, 0x03, 0x90, 0x08, 0x20, 0xCD, 0xE9, 0x00, 0x02, 0x8D, 0xF8, 0x0A, + 0x40, 0x09, 0x7B, 0x02, 0xAB, 0x0A, + 0x22, 0x00, 0x20, 0x43, 0xF6, 0x25, 0xFB, 0x05, 0x00, 0x20, 0xD1, 0xBC, 0x49, 0x00, 0x22, 0x50, 0x31, 0x22, 0xE0, 0xBA, 0x49, 0x00, 0x22, 0x8C, 0x31, 0x1E, 0xE0, 0x0B, 0x79, 0xD3, 0xB1, 0x02, 0x90, 0x8D, 0xF8, 0x08, 0x40, 0x20, 0x0A, + 0x8D, 0xF8, 0x09, 0x00, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x02, 0x09, 0x7B, 0x02, 0xAB, 0x15, 0x22, 0x00, 0x20, 0x43, 0xF6, 0x0A, + 0xFB, 0x05, 0x00, 0x05, 0xD1, 0xAE, 0x49, 0x00, 0x22, 0xD0, 0x31, 0x40, 0x46, 0xFB, 0xF5, 0x5F, 0xFC, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0xAC, 0x49, 0x00, 0x22, 0x48, 0x46, 0xF5, 0xE7, 0xF8, 0xB5, 0xA9, 0x4C, 0xA7, 0x4E, 0x05, + 0x46, 0xA3, 0x7C, 0x01, 0x22, 0xA8, 0x49, 0x30, 0x46, 0xFB, 0xF5, 0x4D, 0xFC, 0xA1, 0x7C, 0xA1, 0x4A, 0x49, 0xB1, 0x01, 0x29, 0x1B, 0xD0, 0x04, 0x29, 0x0F, 0xD1, 0x06, 0x2D, 0x31, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0x90, 0xE7, 0x20, + 0x78, 0x50, 0xB1, 0x15, 0x70, 0x01, 0x2D, 0x05, 0xD0, 0x01, 0x20, 0xFE, 0xF7, 0xAB, 0xFF, 0x01, 0x20, 0xA0, 0x71, 0xF8, 0xBD, 0x05, 0x20, 0x02, 0xE0, 0x00, 0x20, 0x60, 0x72, 0x03, 0x20, 0xBD, 0xE8, 0xF8, 0x40, 0xFE, 0xF7, 0x9F, 0xBF, 0x60, + 0x7D, 0x01, 0x2D, 0x05, 0xD0, 0x01, 0x28, 0x01, 0xD0, 0x02, 0x28, 0xEE, 0xD1, 0x15, 0x70, 0xF8, 0xBD, 0x01, 0x28, 0x0B, 0xD0, 0x02, 0x28, 0x01, 0xD0, 0x04, 0x28, 0xF8, 0xD1, 0x8F, 0x48, 0x1A, 0xF6, 0x1D, 0xFD, 0xBD, 0xE8, 0xF8, 0x40, 0x03, + 0x20, 0xFF, 0xF7, 0x51, 0xB9, 0x03, 0x20, 0xA0, 0x75, 0xF8, 0xBD, 0x63, 0x78, 0x2B, 0xB1, 0xA0, 0x78, 0x18, 0xB1, 0xBD, 0xE8, 0xF8, 0x40, 0x00, 0xF0, 0xF1, 0xB9, 0xA0, 0x78, 0x84, 0x49, 0x00, 0x90, 0x02, 0x22, 0x34, 0x31, 0x30, 0x46, 0xFB, + 0xF5, 0x02, 0xFC, 0xF8, 0xBD, 0x7E, 0x48, 0x10, 0xB5, 0x01, 0x78, 0x19, 0xB1, 0x00, 0x21, 0x01, 0x70, 0x3F, 0xF6, 0x72, 0xFF, 0xD9, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0xFC, 0xF7, 0x2F, 0xBB, 0x75, 0x49, 0x10, 0xB5, 0x00, 0x22, 0xE0, + 0x39, 0x74, 0x48, 0xFB, 0xF5, 0xEC, 0xFB, 0x71, 0x48, 0x08, 0x38, 0x00, 0x21, 0x81, 0x60, 0xC1, 0x60, 0x10, 0xBD, 0x7C, 0xB5, 0x6E, 0x49, 0x00, 0x22, 0xBC, 0x39, 0x6E, 0x48, 0xFB, 0xF5, 0xDF, 0xFB, 0x71, 0x48, 0x00, 0x24, 0xCD, 0xE9, 0x00, + 0x40, 0x68, 0x48, 0x4F, 0xF4, 0xFA, 0x63, 0x01, 0x22, 0x6E, 0xA1, 0x08, 0x38, 0x1A, 0xF6, 0x8F, 0xFC, 0x66, 0x4D, 0xAD, 0x1E, 0x28, 0xB9, 0x64, 0x49, 0x00, 0x22, 0x94, 0x39, 0x28, 0x46, 0xFB, 0xF5, 0xCA, 0xFB, 0x70, 0x48, 0x4F, 0xF4, 0x96, + 0x73, 0xCD, 0xE9, 0x00, 0x40, 0x5D, 0x48, 0x01, 0x22, 0x6D, 0xA1, 0x00, 0x1F, 0x1A, 0xF6, 0x7B, 0xFC, 0x00, 0x28, 0x08, 0xD1, 0x02, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x58, 0x49, 0x00, 0x22, 0x4C, 0x39, 0xFB, 0xF5, 0xB4, 0xBB, 0x7C, + 0xBD, 0x10, 0xB5, 0x07, 0x21, 0x26, 0x20, 0x00, 0xF0, 0x70, 0xFB, 0x52, 0x4C, 0x60, 0x78, 0x00, 0x28, 0x15, 0xD0, 0x00, 0x22, 0x69, 0x49, 0x51, 0x48, 0xFB, 0xF5, 0xA5, 0xFB, 0x68, 0x48, 0x40, 0x78, 0x01, 0x28, 0x04, 0xD0, 0x4E, 0x48, 0x80, + 0x7C, 0x04, 0x28, 0x03, 0xD0, 0x05, 0xE0, 0x00, 0xF0, 0x96, 0xF9, 0x02, 0xE0, 0x00, 0x20, 0xFF, 0xF7, 0xE7, 0xFE, 0x00, 0x20, 0x60, 0x70, 0x10, 0xBD, 0x2D, 0xE9, 0xFE, 0x43, 0x47, 0x49, 0x45, 0x4F, 0x04, 0x46, 0x03, 0x68, 0x01, 0x22, 0x48, + 0x31, 0x38, 0x46, 0xFB, 0xF5, 0x88, 0xFB, 0x00, 0x22, 0x07, 0x21, 0x26, 0x20, 0x00, 0xF0, 0x0C, 0xFB, 0x3B, 0x4E, 0x00, 0x25, 0x2A, 0x3E, 0xB8, 0x46, 0x15, 0xE0, 0x04, 0xEB, 0x45, 0x00, 0x2B, 0x46, 0x81, 0x88, 0xC1, 0xF3, 0x43, 0x10, 0xC0, + 0xEB, 0xC0, 0x02, 0x32, 0x44, 0x01, 0xF0, 0x1F, 0x01, 0x52, 0x5C, 0x8D, 0xE8, 0x07, 0x00, 0x37, 0x49, 0x04, 0x22, 0x80, 0x31, 0x40, 0x46, 0xFB, 0xF5, 0x6A, 0xFB, 0x6D, 0x1C, 0xED, 0xB2, 0x20, 0x68, 0xA8, 0x42, 0xE6, 0xD8, 0xA0, 0x88, 0xC0, + 0xF3, 0x43, 0x11, 0xC1, 0xEB, 0xC1, 0x01, 0x31, 0x44, 0x00, 0xF0, 0x1F, 0x00, 0x0D, 0x5C, 0xE0, 0x88, 0xC0, 0xF3, 0x43, 0x11, 0xC1, 0xEB, 0xC1, 0x01, 0x31, 0x44, 0x00, 0xF0, 0x1F, 0x00, 0x25, 0x4E, 0x0F, 0x5C, 0x70, 0x78, 0x30, 0xB1, 0x21, + 0x68, 0x01, 0x29, 0x01, 0xD1, 0xA8, 0x42, 0x01, 0xD0, 0xFF, 0xF7, 0x96, 0xFF, 0x18, 0x20, 0x11, 0xF0, 0x22, 0xFA, 0x21, 0x48, 0x80, 0x7C, 0x06, 0x28, 0x33, 0xD0, 0x20, 0x68, 0x40, 0xB1, 0x01, 0x28, 0x10, 0xD0, 0x02, 0x28, 0x2D, 0xD1, 0x4F, + 0xF4, 0xFA, 0x64, 0x07, 0x2D, 0x0F, 0xD0, 0x10, 0xE0, 0x03, 0xB0, 0x30, 0x49, 0xBD, 0xE8, 0xF0, 0x43, 0x16, 0x48, 0x00, 0x22, 0x30, 0x39, 0x40, 0x1E, 0xFB, 0xF5, 0x2D, 0xBB, 0x75, 0x70, 0x28, 0x46, 0xBD, 0xE8, 0xFE, 0x43, 0xD0, 0xE6, 0x0F, + 0x2F, 0x03, 0xD0, 0x07, 0x2F, 0x03, 0xD1, 0x0F, 0x2D, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x60, 0x10, 0x49, 0x01, 0x22, 0x80, 0x31, 0x40, 0x46, 0x73, 0x68, 0xFB, 0xF5, 0x19, 0xFB, 0x70, 0x68, 0x00, 0x28, 0x07, 0xD0, 0x03, 0xB0, 0x21, 0x46, 0xBD, + 0xE8, 0xF0, 0x43, 0x04, 0x48, 0x08, 0x38, 0x1A, 0xF6, 0xFE, 0xBB, 0xBD, 0xE8, 0xFE, 0x83, 0x00, 0x00, 0x92, 0xE1, 0x20, 0x00, 0x00, 0xF3, 0x20, 0x00, 0xE4, 0x35, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x70, 0xF2, 0x20, 0x00, 0xF0, 0x36, 0x80, + 0x08, 0x24, 0x33, 0x80, 0x08, 0xA0, 0xF2, 0x20, 0x00, 0x25, 0x86, 0x20, 0x00, 0x63, 0x6F, 0x6D, 0x62, 0x69, 0x6E, 0x65, 0x5F, 0x6B, 0x65, 0x79, 0x73, 0x5F, 0x64, 0x65, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x5F, 0x74, 0x69, 0x6D, 0x65, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x95, 0x86, 0x20, 0x00, 0x6E, 0x6F, 0x74, 0x69, 0x66, 0x79, 0x5F, 0x6B, 0x65, 0x79, 0x5F, 0x64, 0x61, 0x74, 0x61, 0x5F, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5F, 0x72, 0x65, 0x63, 0x6F, 0x6E, 0x6E, 0x5F, 0x74, 0x69, + 0x6D, 0x65, 0x72, 0x00, 0x00, 0xF4, 0x37, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0x2D, 0xE9, 0xFE, 0x4F, 0x00, 0x25, 0x8D, 0xF8, 0x08, 0x50, 0x02, 0xA9, 0x40, 0xF2, 0x33, 0x20, 0x40, 0xF6, 0x60, 0xFC, 0x00, 0xF0, 0x2F, 0xF9, 0xDF, 0xF8, 0xA8, + 0xC3, 0x18, 0xB1, 0x00, 0x22, 0xE9, 0x49, 0x60, 0x46, 0x55, 0xE0, 0xE9, 0x4F, 0xDF, 0xF8, 0x98, 0xA3, 0x3B, 0x7A, 0xAA, 0xF1, 0x01, 0x0A, + 0xD8, 0x1E, 0x78, 0x28, 0x03, 0xDA, 0xE3, 0x49, 0x01, 0x22, 0x34, 0x31, 0x06, 0xE0, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x2B, 0x06, 0xD8, 0xDF, 0x49, 0x01, 0x22, 0x6C, 0x31, 0x50, 0x46, 0xFB, 0xF5, 0xA7, 0xFA, 0x37, 0xE0, 0xDE, 0x4E, 0xD6, 0xE9, + 0x01, 0x01, 0x81, 0x42, 0x01, 0xD2, 0x32, 0x68, 0x11, 0x44, 0x08, 0x1A, 0x59, 0x1E, 0x88, 0x42, 0x01, 0xD8, 0x04, 0x46, 0x00, 0xE0, 0x0C, 0x46, 0xCD, 0xE9, 0x00, 0x04, 0xD4, 0x49, 0x03, 0x22, 0xAC, 0x31, 0x60, 0x46, 0xFB, 0xF5, 0x90, 0xFA, + 0x4F, 0xF0, 0x01, 0x09, 0x4F, 0xF0, 0x78, 0x08, 0x17, 0xE0, 0xCD, 0xE9, 0x00, 0x89, 0x70, 0x68, 0xF1, 0x68, 0xC0, 0xEB, 0x00, 0x10, 0x01, 0xEB, 0xC0, 0x03, 0x39, 0x7B, 0x0E, 0x22, 0x00, 0x20, 0x64, 0x1E, 0x43, 0xF6, 0x20, 0xF9, 0x05, 0x00, + 0x0F, 0xD0, 0xD6, 0xE9, 0x00, 0x10, 0x40, 0x1C, 0xB0, 0xFB, 0xF1, 0xF2, 0x01, 0xFB, 0x12, 0x00, 0x70, 0x60, 0x1C, 0xB1, 0x00, 0xF0, 0xDA, 0xF8, 0x00, 0x28, 0xE2, 0xD0, 0x28, 0x46, 0xBD, 0xE8, 0xFE, 0x8F, 0x00, 0x22, 0xC1, 0x49, 0x50, 0x46, + 0xFB, 0xF5, 0x66, 0xFA, 0xF6, 0xE7, 0xBF, 0x48, 0x10, 0xB5, 0x41, 0x78, 0xB9, 0x48, 0x01, 0x29, 0x4F, 0xF0, 0x00, 0x02, 0x20, 0xD0, 0xBA, 0x49, 0x04, 0x46, 0x78, 0x31, 0xFB, 0xF5, 0x58, 0xFA, 0xB5, 0x49, 0x00, 0x22, 0x64, 0x39, 0x20, 0x46, + 0xFB, 0xF5, 0x52, 0xFA, 0xB7, 0x49, 0x00, 0x20, 0x3C, 0x22, 0x48, 0x60, 0x88, 0x60, 0xB1, 0x49, 0xC1, 0xE9, 0x00, 0x20, 0x88, 0x60, 0xA1, 0xF5, 0xE1, 0x50, 0xC8, 0x60, 0x11, 0xF0, 0xA1, 0xFB, 0x01, 0x21, 0x02, 0x20, 0xFD, 0xF7, 0x90, 0xFF, + 0x10, 0xF0, 0xF9, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0xAA, 0x49, 0x34, 0x31, 0xFB, 0xF5, 0x38, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x10, 0xB5, 0xA6, 0x49, 0xA2, 0x4C, 0x00, 0x22, 0xA8, 0x31, 0x20, 0x46, 0xFB, 0xF5, 0x2E, 0xFA, 0x00, 0x21, 0x02, 0x20, + 0xFD, 0xF7, 0x7A, 0xFF, 0xA2, 0x49, 0x49, 0x78, 0x29, 0xB1, 0x10, 0xF0, 0x08, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0x5A, 0xBF, 0x9C, 0x49, 0x20, 0x46, 0x00, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0xD4, 0x31, 0xFB, 0xF5, 0x19, 0xBA, 0x99, 0x48, + 0x10, 0xB5, 0x40, 0x78, 0x01, 0x24, 0x01, 0x28, 0x06, 0xD0, 0xFF, 0xF7, 0xAC, 0xFF, 0x06, 0x20, 0xFF, 0xF7, 0x5F, 0xFD, 0x20, 0x46, 0x10, 0xBD, 0x8E, 0x48, 0x00, 0x22, 0x94, 0x49, 0x40, 0x1E, 0xFB, 0xF5, 0x06, 0xFA, 0x00, 0x20, 0x10, 0xBD, + 0x8F, 0x48, 0x10, 0xB5, 0x40, 0x78, 0x18, 0xB1, 0x00, 0xF0, 0x68, 0xF8, 0x90, 0xB9, 0x08, 0xE0, 0x8D, 0x49, 0x85, 0x48, 0x00, 0x22, 0x54, 0x31, 0xBD, 0xE8, 0x10, 0x40, 0x40, 0x1E, 0xFB, 0xF5, 0xF3, 0xB9, 0x87, 0x48, 0x00, 0x1D, 0x01, 0x78, + 0x21, 0xB1, 0x81, 0x49, 0x09, 0x7A, 0xC9, 0x1E, 0x78, 0x29, 0x05, 0xDA, 0x00, 0x20, 0xFF, 0xF7, 0x38, 0xFD, 0xBD, 0xE8, 0x10, 0x40, 0xAD, 0xE7, 0x01, 0x21, 0x41, 0x70, 0x10, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0x0E, 0x46, 0x7E, 0x49, 0x76, 0x4F, + 0x04, 0x46, 0x01, 0x25, 0x03, 0x46, 0x2A, 0x46, 0x94, 0x31, 0x38, 0x46, 0xFB, 0xF5, 0xD4, 0xF9, 0x20, 0x46, 0x77, 0x4C, 0x24, 0x1D, 0x01, 0x28, 0x11, 0xD0, 0x02, 0x28, 0x15, 0xD0, 0x03, 0x28, 0x08, 0xD0, 0x00, 0x22, 0x75, 0x49, 0x38, 0x46, + 0xFB, 0xF5, 0xC6, 0xF9, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0xD6, 0xE9, 0x00, 0x01, 0x00, 0xF0, 0x31, 0xF8, 0xF7, 0xE7, 0x20, 0x78, 0x00, 0x28, 0xF4, 0xD0, 0xFF, 0xF7, 0xE7, 0xFE, 0xF1, 0xE7, 0x33, 0x78, 0x01, 0x2B, 0x08, 0xD0, + 0x4F, 0xF0, 0x01, 0x02, 0x83, 0xB1, 0x68, 0x49, 0x38, 0x46, 0x40, 0x39, 0xFB, 0xF5, 0xAC, 0xF9, 0xE5, 0xE7, 0x65, 0x49, 0x01, 0x22, 0xB8, 0x39, 0x38, 0x46, 0xFB, 0xF5, 0xA5, 0xF9, 0xFF, 0xF7, 0x3E, 0xFF, 0x01, 0x20, 0x20, 0x70, 0xDA, 0xE7, + 0x60, 0x49, 0x38, 0x46, 0x7C, 0x39, 0xFB, 0xF5, 0x9B, 0xF9, 0x00, 0x20, 0x20, 0x70, 0xFF, 0xF7, 0x61, 0xFF, 0xD0, 0xE7, 0x56, 0x48, 0x81, 0x68, 0x40, 0x68, 0x81, 0x42, 0x01, 0xD1, 0x01, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x10, 0xB5, + 0x54, 0x4C, 0xA0, 0xB0, 0x00, 0x22, 0x24, 0x1D, 0x1E, 0x92, 0x62, 0x78, 0x08, 0x46, 0x01, 0x2A, 0x11, 0xD0, 0x1E, 0xAB, 0x6A, 0x46, 0x4F, 0xF4, 0xF0, 0x71, 0x00, 0xF0, 0x56, 0xF8, 0x1E, 0x9B, 0x78, 0x2B, 0x16, 0xD0, 0x4C, 0x49, 0x44, 0x48, + 0x01, 0x22, 0x40, 0x39, 0x40, 0x1E, 0xFB, 0xF5, 0x73, 0xF9, 0x20, 0xB0, 0x10, 0xBD, 0xFF, 0xF7, 0xD9, 0xFF, 0x08, 0xB9, 0x20, 0x78, 0x28, 0xB9, 0x00, 0x20, 0xFF, 0xF7, 0xBA, 0xFC, 0xFF, 0xF7, 0x31, 0xFF, 0xF2, 0xE7, 0xFF, 0xF7, 0x93, 0xFE, + 0xEF, 0xE7, 0x68, 0x46, 0x00, 0xF0, 0x0A, + 0xF8, 0x20, 0x78, 0x01, 0x28, 0xF6, 0xD0, 0x3D, 0x49, 0x00, 0x22, 0x80, 0x39, 0x35, 0x48, 0xFB, 0xF5, 0x57, 0xF9, 0xE2, 0xE7, 0x70, 0xB5, 0x35, 0x4C, 0x05, 0x46, 0xA2, 0x68, 0x20, 0x68, 0x52, 0x1C, 0xB2, 0xFB, 0xF0, 0xF1, 0x00, 0xFB, 0x11, + 0x20, 0x61, 0x68, 0x88, 0x42, 0x0D, 0xD1, 0x2D, 0x49, 0x00, 0x22, 0x3C, 0x39, 0x2B, 0x48, 0xFB, 0xF5, 0x43, 0xF9, 0xD4, 0xE9, 0x00, 0x02, 0x52, 0x1C, 0xB2, 0xFB, 0xF0, 0xF1, 0x00, 0xFB, 0x11, 0x20, 0x60, 0x60, 0xD4, 0xE9, 0x02, 0x01, 0xC0, + 0xEB, 0x00, 0x10, 0x01, 0xEB, 0xC0, 0x00, 0x78, 0x22, 0x29, 0x46, 0x4D, 0xF6, 0x4F, 0xFB, 0xA0, 0x68, 0x21, 0x68, 0x40, 0x1C, 0xB0, 0xFB, 0xF1, 0xF2, 0x01, 0xFB, 0x12, 0x00, 0xA0, 0x60, 0x01, 0x20, 0x70, 0xBD, 0x2D, 0xE9, 0xFC, 0x47, 0x00, + 0x26, 0x01, 0xAF, 0xCD, 0xE9, 0x00, 0x76, 0x9A, 0x46, 0x14, 0x46, 0x81, 0x46, 0x39, 0x23, 0x92, 0x1C, 0xF0, 0x21, 0x11, 0xF0, 0x3C, 0xFA, 0x4F, 0xF0, 0x01, 0x08, 0x19, 0x4D, 0x84, 0xF8, 0x00, 0x80, 0x84, 0xF8, 0x3B, 0x60, 0x28, 0x78, 0xC0, + 0x07, 0x1B, 0xD0, 0xC8, 0x20, 0x60, 0x70, 0x39, 0x23, 0x04, 0xF1, 0x3E, 0x02, 0xF0, 0x21, 0x09, 0xF1, 0xF0, 0x00, 0x00, 0x97, 0x11, 0xF0, 0x27, 0xFA, 0x84, 0xF8, 0x3C, 0x80, 0x84, 0xF8, 0x77, 0x60, 0x28, 0x78, 0xC1, 0x07, 0x0B, 0xD0, 0xF8, + 0x21, 0x78, 0x22, 0x84, 0xF8, 0x3D, 0x10, 0x40, 0x1C, 0xCA, 0xF8, 0x00, 0x20, 0x28, 0x70, 0xBD, 0xE8, 0xFC, 0x87, 0x08, 0x20, 0xE2, 0xE7, 0x38, 0x21, 0xF2, 0xE7, 0x02, 0x30, 0x10, 0x21, 0x1C, 0x39, 0x80, 0x08, 0x70, 0xF2, 0x20, 0x00, 0x1C, + 0x13, 0x21, 0x00, 0x24, 0x3A, 0x80, 0x08, 0x08, 0xF3, 0x20, 0x00, 0xF0, 0xF6, 0x20, 0x00, 0xC0, 0x3B, 0x80, 0x08, 0x38, 0x3D, 0x80, 0x08, 0x2D, 0xE9, 0xFC, 0x41, 0x00, 0xEB, 0x40, 0x01, 0x5E, 0x48, 0x00, 0x24, 0x00, 0xEB, 0xC1, 0x05, 0x68, + 0x69, 0x00, 0x28, 0x2C, 0xD0, 0x01, 0x26, 0x69, 0x69, 0x06, 0xFA, 0x04, 0xF3, 0x19, 0x42, 0x22, 0xD0, 0x05, 0xEB, 0x44, 0x00, 0x81, 0x78, 0xF1, 0xB1, 0x57, 0x4A, 0x55, 0x4F, 0x02, 0xEB, 0xC4, 0x02, 0x08, 0x3F, 0x52, 0x78, 0x3F, 0x68, 0xB7, + 0xFB, 0xF2, 0xFC, 0x02, 0xFB, 0x1C, 0x72, 0xC7, 0x78, 0xBA, 0x42, 0x10, 0xD1, 0x49, 0x1E, 0x11, 0xF0, 0xFF, 0x01, 0x81, 0x70, 0x0B, 0xD1, 0x68, 0x69, 0x01, 0x22, 0x98, 0x43, 0x68, 0x61, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x60, 0x00, 0x23, 0x68, + 0x78, 0x19, 0x46, 0x04, 0xF6, 0x68, 0xFD, 0x64, 0x1C, 0xE4, 0xB2, 0x08, 0x2C, 0xD3, 0xD3, 0xBD, 0xE8, 0xFC, 0x81, 0x02, 0x46, 0x00, 0x20, 0x01, 0x23, 0x03, 0xFA, 0x00, 0xF1, 0x11, 0x42, 0x03, 0xD1, 0x40, 0x1C, 0x08, 0x28, 0xF8, 0xD3, 0x00, + 0x20, 0x70, 0x47, 0x1C, 0xB5, 0x00, 0x24, 0x01, 0x20, 0xCD, 0xE9, 0x00, 0x04, 0x02, 0x46, 0x23, 0x46, 0x21, 0x46, 0x26, 0x20, 0x04, 0xF6, 0x4B, 0xFD, 0x3A, 0x48, 0x32, 0x23, 0xCD, 0xE9, 0x00, 0x40, 0x36, 0x48, 0x01, 0x22, 0x38, 0xA1, 0x00, + 0x1F, 0x1A, 0xF6, 0x3E, 0xF9, 0x03, 0x00, 0x07, 0xD1, 0x02, 0xB0, 0x01, 0x22, 0xBD, 0xE8, 0x10, 0x40, 0x37, 0x49, 0x37, 0x48, 0xFB, 0xF5, 0x78, 0xB8, 0x1C, 0xBD, 0xF8, 0xB5, 0x00, 0x24, 0x00, 0x94, 0x09, 0xB1, 0x08, 0x29, 0x01, 0xD3, 0x01, + 0x20, 0xF8, 0xBD, 0x03, 0x0A, + 0x01, 0xD0, 0x02, 0x20, 0xF8, 0xBD, 0x03, 0x0A, + 0x03, 0xEB, 0x43, 0x05, 0x26, 0x4B, 0x01, 0x26, 0x03, 0xEB, 0xC5, 0x03, 0x8E, 0x40, 0x5D, 0x69, 0x35, 0x43, 0x5D, 0x61, 0x58, 0x70, 0x03, 0xEB, 0x41, 0x00, 0x6A, 0xB1, 0x82, 0x70, 0x20, 0x4A, 0x02, 0xEB, 0xC1, 0x01, 0x1E, 0x4A, 0x49, 0x78, + 0x08, 0x3A, 0x12, 0x68, 0xB2, 0xFB, 0xF1, 0xF3, 0x01, 0xFB, 0x13, 0x21, 0xC1, 0x70, 0x01, 0xE0, 0x84, 0x70, 0xC4, 0x70, 0x18, 0x48, 0x69, 0x46, 0x00, 0x1F, 0x1A, 0xF6, 0x7A, 0xF9, 0x00, 0x98, 0x20, 0xB9, 0x14, 0x48, 0x32, 0x21, 0x00, 0x1F, + 0x1A, 0xF6, 0x30, 0xF9, 0x00, 0x20, 0xF8, 0xBD, 0x7C, 0xB5, 0x09, 0xB1, 0x08, 0x29, 0x01, 0xD3, 0x01, 0x20, 0x7C, 0xBD, 0x02, 0x0A, + 0x01, 0xD0, 0x02, 0x20, 0x7C, 0xBD, 0x00, 0x0A, + 0x00, 0xEB, 0x40, 0x02, 0x0A, + 0x48, 0x00, 0xEB, 0xC2, 0x04, 0x01, 0x20, 0x62, 0x69, 0x00, 0xFA, 0x01, 0xF5, 0x2A, 0x42, 0x0A, + 0xD0, 0x00, 0x21, 0xCD, 0xE9, 0x00, 0x01, 0x60, 0x78, 0x0B, 0x46, 0x01, 0x22, 0x04, 0xF6, 0xDF, 0xFC, 0x60, 0x69, 0xA8, 0x43, 0x60, 0x61, 0x00, 0x20, 0x7C, 0xBD, 0x34, 0x13, 0x21, 0x00, 0xEC, 0xE1, 0x20, 0x00, 0x95, 0x87, 0x20, 0x00, 0x6C, + 0x65, 0x64, 0x5F, 0x63, 0x74, 0x72, 0x6C, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x72, 0x00, 0x00, 0x68, 0x3D, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x1C, 0xB5, 0x01, 0x23, 0x00, 0x24, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x18, 0x46, 0x01, 0x94, 0x04, + 0xF6, 0xBE, 0xFC, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x02, 0x20, 0x01, 0x94, 0x04, 0xF6, 0xB6, 0xFC, 0x17, 0x21, 0x01, 0x20, 0x04, 0xF6, 0x7E, 0xFC, 0xBD, 0xE8, 0x1C, 0x40, 0x18, 0x21, 0x02, 0x20, 0x04, 0xF6, 0x78, 0xBC, 0x30, + 0xB5, 0x4F, 0xF0, 0x40, 0x25, 0x8B, 0xB0, 0x28, 0x46, 0xFC, 0xF7, 0xC0, 0xFA, 0x01, 0x22, 0x7A, 0x49, 0x7B, 0x48, 0x0F, 0xF0, 0x90, 0xFB, 0x68, 0x46, 0xFC, 0xF7, 0xBD, 0xFA, 0x01, 0x24, 0x46, 0xF2, 0xA8, 0x10, 0xAD, 0xF8, 0x1C, 0x00, 0x8D, + 0xF8, 0x05, 0x40, 0xAD, 0xF8, 0x12, 0x40, 0x69, 0x46, 0x28, 0x46, 0xFC, 0xF7, 0x7A, 0xFA, 0x01, 0x22, 0x04, 0x21, 0x28, 0x46, 0xFC, 0xF7, 0xC1, 0xFA, 0x01, 0x22, 0x04, 0x21, 0x28, 0x46, 0xFC, 0xF7, 0x3C, 0xFB, 0x35, 0x20, 0x8D, 0xF8, 0x20, + 0x00, 0x03, 0x20, 0x09, 0x90, 0x8D, 0xF8, 0x28, 0x40, 0x08, 0xA8, 0x04, 0xF6, 0xEE, 0xFB, 0x0B, 0xB0, 0x30, 0xBD, 0x67, 0x48, 0x00, 0x78, 0x70, 0x47, 0x30, 0xB5, 0x87, 0xB0, 0x5A, 0x21, 0x01, 0x20, 0x04, 0xF6, 0x3D, 0xFC, 0x5A, 0x21, 0x02, + 0x20, 0x04, 0xF6, 0x39, 0xFC, 0x01, 0x23, 0x00, 0x24, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x18, 0x46, 0x01, 0x94, 0x04, 0xF6, 0x64, 0xFC, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x02, 0x20, 0x01, 0x94, 0x04, 0xF6, 0x5C, 0xFC, 0x01, + 0x22, 0x4F, 0xF0, 0x04, 0x51, 0x58, 0x48, 0x0F, 0xF0, 0x46, 0xFB, 0x01, 0x20, 0xFC, 0xF7, 0x02, 0xFA, 0x05, 0x46, 0x02, 0x20, 0xFC, 0xF7, 0xFE, 0xF9, 0x05, 0x43, 0x8D, 0xF8, 0x0C, 0x40, 0x02, 0x95, 0x8D, 0xF8, 0x0D, 0x40, 0x02, 0xA8, 0xFC, + 0xF7, 0x74, 0xF9, 0x01, 0x20, 0xFC, 0xF7, 0xF2, 0xF9, 0x00, 0xF0, 0x8B, 0xF8, 0x4B, 0x4C, 0x60, 0x70, 0x02, 0x20, 0xFC, 0xF7, 0xEB, 0xF9, 0x00, 0xF0, 0x84, 0xF8, 0xA0, 0x70, 0x07, 0xB0, 0x30, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xBD, 0xFF, 0x00, + 0x21, 0x01, 0x20, 0x04, 0xF6, 0x88, 0xFD, 0x00, 0x21, 0x02, 0x20, 0x04, 0xF6, 0x84, 0xFD, 0x40, 0x48, 0x4F, 0xF0, 0x00, 0x02, 0x40, 0x78, 0x08, 0xB1, 0x01, 0x21, 0x00, 0xE0, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0x04, 0xF6, 0xB0, + 0xBC, 0x10, 0xB5, 0x17, 0x21, 0x01, 0x20, 0x04, 0xF6, 0xE6, 0xFB, 0x18, 0x21, 0x02, 0x20, 0x04, 0xF6, 0xE2, 0xFB, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0xF6, 0xEF, 0xBC, 0x10, 0xB5, 0x35, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFA, 0xF5, 0xF6, 0xFE, 0xAF, + 0xF2, 0xDF, 0x00, 0xFB, 0xF5, 0x19, 0xFD, 0x20, 0xB9, 0x00, 0x22, 0x33, 0x49, 0x34, 0x48, 0xFA, 0xF5, 0x43, 0xFF, 0xAF, 0xF2, 0x6D, 0x00, 0x32, 0x49, 0x08, 0x60, 0xAF, 0xF2, 0x45, 0x00, 0x31, 0x49, 0x08, 0x60, 0xFB, 0xF7, 0x6C, 0xFF, 0x02, + 0x20, 0xFB, 0xF5, 0x36, 0xFE, 0x00, 0x22, 0x01, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x08, 0x46, 0x04, 0xF6, 0x7F, 0xBC, 0x10, 0xB5, 0xFF, 0xF7, 0x23, 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0x3B, 0xE7, 0x70, 0xB5, 0x4F, 0xF0, 0x40, 0x24, 0x02, 0x21, 0x20, + 0x46, 0xFC, 0xF7, 0x63, 0xFA, 0x1B, 0x4D, 0x4F, 0xF0, 0x04, 0x56, 0x01, 0x28, 0x1C, 0xD1, 0x22, 0xA1, 0x30, 0x46, 0xFA, 0xF5, 0xC2, 0xFE, 0x24, 0xA1, 0x30, 0x46, 0xFA, 0xF5, 0xBE, 0xFE, 0x01, 0x22, 0x02, 0x21, 0x20, 0x46, 0xFC, 0xF7, 0x79, + 0xFA, 0x27, 0x48, 0x81, 0x68, 0xC1, 0xF3, 0x00, 0x41, 0xE9, 0x80, 0x80, 0x68, 0xA8, 0x80, 0x60, 0x6A, 0x40, 0xF0, 0x02, 0x00, 0x60, 0x62, 0x00, 0x22, 0x02, 0x21, 0x20, 0x46, 0xFC, 0xF7, 0x69, 0xFA, 0xB5, 0xF9, 0x04, 0x30, 0xEA, 0x88, 0x30, + 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x1D, 0xA1, 0xFA, 0xF5, 0xA0, 0xBE, 0x23, 0x4A, 0x01, 0x46, 0x00, 0x20, 0x12, 0x6D, 0x0A, + 0x42, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0x10, 0x00, 0x00, 0x60, 0x00, 0x00, 0x04, 0x08, 0x5C, 0x13, 0x21, 0x00, 0x00, 0x01, 0x00, 0x0C, 0x71, 0x64, 0x65, 0x63, 0x5F, 0x64, 0x6C, 0x70, 0x73, 0x5F, 0x69, 0x6E, 0x69, 0x74, 0x00, 0x00, 0x04, + 0x3F, 0x80, 0x08, 0x00, 0x04, 0x10, 0x21, 0xB4, 0xE7, 0x20, 0x00, 0xB0, 0xE7, 0x20, 0x00, 0x51, 0x64, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x5F, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x00, 0x51, 0x44, 0x45, 0x43, 0x5F, 0x46, 0x4C, 0x41, 0x47, + 0x5F, 0x4E, 0x45, 0x57, 0x5F, 0x43, 0x54, 0x5F, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5F, 0x59, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x40, 0x51, 0x44, 0x45, 0x43, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x25, 0x64, + 0x2C, 0x20, 0x20, 0x63, 0x6F, 0x75, 0x6E, 0x74, 0x20, 0x25, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x40, 0x70, 0xB5, 0x02, 0x24, 0x05, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x40, 0xF6, 0x2C, 0xFF, 0x00, + 0x28, 0xF9, 0xD1, 0xFB, 0x48, 0x01, 0x78, 0xC8, 0x07, 0xF5, 0xD0, 0x11, 0xF0, 0x0C, 0x0F, 0xF2, 0xD0, 0x11, 0xF0, 0x30, 0x0F, 0xEF, 0xD1, 0x88, 0x09, 0xED, 0xD1, 0x28, 0x46, 0x14, 0xF6, 0xD4, 0xFC, 0x00, 0x28, 0xE8, 0xD0, 0x00, 0x24, 0xE6, + 0xE7, 0x38, 0xB5, 0x04, 0x00, 0x07, 0xD1, 0xF0, 0x49, 0x08, 0x78, 0x20, 0xF0, 0x0E, 0x00, 0x08, 0x70, 0xFC, 0x20, 0x40, 0xF6, 0xB5, 0xF8, 0xED, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0xAD, 0xF8, 0x00, 0x40, 0x69, 0x46, 0xA5, 0x20, 0x90, + 0x47, 0x38, 0xBD, 0x30, 0xB5, 0x8B, 0xB0, 0x4F, 0xF0, 0x00, 0x01, 0xE7, 0x4D, 0x04, 0x00, 0x06, 0x91, 0x07, 0x91, 0x08, 0x91, 0x09, 0x91, 0x02, 0xD0, 0x20, 0x78, 0x01, 0x28, 0x08, 0xD0, 0x01, 0x23, 0x01, 0x22, 0xE2, 0x49, 0x28, 0x46, 0xFA, + 0xF5, 0x65, 0xFE, 0x00, 0x20, 0x0B, 0xB0, 0x30, 0xBD, 0xA0, 0x78, 0x00, 0x07, 0x18, 0xD5, 0x6A, 0x46, 0x14, 0x21, 0x20, 0x46, 0x43, 0xF6, 0xDD, 0xFA, 0x80, 0xB1, 0x10, 0x22, 0x06, 0xA9, 0x68, 0x46, 0x4D, 0xF6, 0x27, 0xF8, 0x40, 0xB1, 0xD7, + 0x49, 0x63, 0x78, 0x01, 0x22, 0x30, 0x39, 0x28, 0x46, 0xFA, 0xF5, 0x4C, 0xFE, 0x01, 0x20, 0xE5, 0xE7, 0x05, 0x23, 0xDD, 0xE7, 0x04, 0x23, 0xDB, 0xE7, 0x02, 0x23, 0xD9, 0xE7, 0x0A, + 0x46, 0x00, 0xEB, 0x40, 0x01, 0xCF, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x00, 0xEB, 0x01, 0x10, 0x01, 0x78, 0x29, 0xB1, 0x81, 0x79, 0xC0, 0x1D, 0x14, 0xF6, 0x34, 0xFC, 0x00, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0xF0, 0xB5, 0x85, 0xB0, 0x0C, + 0x46, 0x06, 0x00, 0x05, 0xD0, 0x15, 0xF6, 0x75, 0xF9, 0x78, 0xB3, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0x27, 0x44, 0xB3, 0x0F, 0xF0, 0xFE, 0xF8, 0x20, 0x70, 0x01, 0x0A, + 0x61, 0x70, 0x01, 0x0C, 0xA1, 0x70, 0x00, 0x0E, 0x65, 0x1C, 0xE0, 0x70, 0x0F, 0xF0, 0xF4, 0xF8, 0xE8, 0x70, 0x00, 0x0A, + 0x28, 0x71, 0x40, 0xF0, 0xC0, 0x00, 0x60, 0x71, 0xB9, 0xA0, 0x06, 0x22, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x01, 0x10, 0xB8, 0xA0, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x03, 0x10, 0x01, 0xA9, 0x20, 0x46, 0x4C, 0xF6, 0xD7, 0xFF, 0x48, 0xB1, + 0x06, 0x22, 0x03, 0xA9, 0x20, 0x46, 0x4C, 0xF6, 0xD1, 0xFF, 0x18, 0xB1, 0x04, 0xE0, 0x03, 0x20, 0xD0, 0xE7, 0x0F, 0xE0, 0x66, 0x20, 0x20, 0x70, 0x21, 0x46, 0xAF, 0x48, 0xFA, 0xF5, 0xB0, 0xFF, 0xA7, 0x49, 0x03, 0x46, 0x02, 0x22, 0x38, 0x31, + 0xA4, 0x48, 0x00, 0x96, 0xFA, 0xF5, 0xEB, 0xFD, 0x38, 0x46, 0xBF, 0xE7, 0x07, 0x20, 0xBD, 0xE7, 0x70, 0xB5, 0x0D, 0x46, 0x40, 0xF6, 0x2E, 0xFD, 0x04, 0x00, 0x2A, 0xD0, 0xA5, 0x48, 0x9E, 0x49, 0x01, 0x22, 0x03, 0x78, 0x9B, 0x48, 0x74, 0x31, + 0x40, 0x1C, 0xFA, 0xF5, 0xD8, 0xFD, 0x97, 0x49, 0x01, 0x22, 0x08, 0x78, 0xB2, 0xEB, 0x90, 0x1F, 0x0A, + 0xD1, 0x62, 0x78, 0x03, 0x2A, 0x07, 0xD1, 0xA2, 0x78, 0x01, 0x2A, 0x04, 0xD1, 0x22, 0x8A, 0x12, 0xB9, 0x20, 0xF0, 0xC0, 0x00, 0x08, 0x70, 0xE0, 0x78, 0x2A, 0x46, 0x00, 0x21, 0x45, 0xF6, 0xE0, 0xFB, 0x00, 0x20, 0x3F, 0xF6, 0xF1, 0xFF, 0xE0, + 0x6A, 0x08, 0xB1, 0x18, 0xF6, 0xC7, 0xFF, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x40, 0xF6, 0xF0, 0xBC, 0x89, 0x49, 0xBD, 0xE8, 0x70, 0x40, 0x86, 0x48, 0x00, 0x22, 0xA4, 0x31, 0x80, 0x1E, 0xFA, 0xF5, 0xAD, 0xBD, 0x43, 0x88, 0x33, 0xB1, 0x83, + 0x49, 0x82, 0x48, 0x01, 0x22, 0xD4, 0x31, 0x80, 0x1E, 0xFA, 0xF5, 0xA4, 0xBD, 0x81, 0x88, 0x00, 0x88, 0xB9, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x41, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xB4, 0xFF, 0x20, 0x88, 0xBD, 0xE8, 0x10, 0x40, 0x14, 0xF6, 0x6F, + 0xBC, 0x10, 0xB5, 0x8A, 0xB0, 0x0C, 0x46, 0x00, 0x21, 0x21, 0x70, 0x09, 0xAA, 0x07, 0xA9, 0x40, 0xF6, 0x55, 0xFE, 0xB8, 0xB1, 0x9D, 0xF8, 0x24, 0x10, 0x07, 0xA8, 0x43, 0xF6, 0x1F, 0xF9, 0x88, 0xB1, 0x6A, 0x46, 0x11, 0x21, 0x43, 0xF6, 0x05, + 0xFA, 0x60, 0xB1, 0x9D, 0xF8, 0x1B, 0x30, 0x01, 0x22, 0x75, 0x49, 0x6B, 0x48, 0xFA, 0xF5, 0x7A, 0xFD, 0x9D, 0xF8, 0x1B, 0x00, 0x20, 0x70, 0x00, 0x20, 0x0A, + 0xB0, 0x10, 0xBD, 0x03, 0x20, 0xFB, 0xE7, 0x70, 0x48, 0x00, 0x88, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, 0x0F, 0x46, 0x05, 0x00, 0x08, 0xD0, 0x62, 0x4B, 0x28, 0x78, 0x9B, 0x1E, 0x01, 0x28, 0x06, 0xD0, 0x68, 0x49, 0x00, 0x22, 0x48, 0x31, 0x0B, + 0xE0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x67, 0x48, 0x69, 0x78, 0x00, 0x78, 0x40, 0x1E, 0x81, 0x42, 0x06, 0xDD, 0x62, 0x49, 0x00, 0x22, 0x20, 0x31, 0x18, 0x46, 0xFA, 0xF5, 0x52, 0xFD, 0xEF, 0xE7, 0xDF, 0xF8, 0x7C, 0x81, 0x38, 0x46, 0xB8, + 0xF8, 0x00, 0x10, 0x8E, 0x08, 0x4D, 0xF6, 0x28, 0xF8, 0x00, 0x24, 0xDF, 0xF8, 0x74, 0x91, 0xDF, 0xF8, 0x74, 0xA1, 0x11, 0xE0, 0x68, 0x78, 0x00, 0x90, 0xB9, 0xF8, 0x00, 0x10, 0xBA, 0xF8, 0x00, 0x00, 0x04, 0x23, 0x08, 0x44, 0x00, 0xEB, 0x84, + 0x00, 0x81, 0xB2, 0x07, 0xEB, 0x84, 0x00, 0xB8, 0xF8, 0x00, 0x20, 0x44, 0xF6, 0x17, 0xF8, 0x64, 0x1C, 0xB4, 0x42, 0xEB, 0xDB, 0x01, 0x20, 0xCC, 0xE7, 0x30, 0xB5, 0xA7, 0xB0, 0x04, 0x00, 0x07, 0xD0, 0x04, 0xF1, 0x08, 0x00, 0x61, 0x78, 0x05, + 0x46, 0x44, 0xF6, 0xDC, 0xF8, 0x18, 0xB1, 0x14, 0xE0, 0x00, 0x20, 0x27, 0xB0, 0x30, 0xBD, 0xE0, 0x7B, 0xC1, 0x07, 0x0E, 0xD0, 0x01, 0x21, 0x21, 0x70, 0x62, 0x88, 0x83, 0x07, 0x42, 0xF0, 0x01, 0x02, 0x62, 0x80, 0x02, 0xD5, 0x42, 0xF0, 0x80, + 0x02, 0x62, 0x80, 0x40, 0x07, 0x04, 0xD5, 0x21, 0x71, 0x02, 0xE0, 0x20, 0x78, 0x01, 0x28, 0x5D, 0xD1, 0x61, 0x78, 0x0A, + 0xA8, 0x44, 0xF6, 0x00, 0xF9, 0x30, 0xB9, 0x9D, 0xF8, 0x28, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x02, 0x00, 0x60, 0x80, 0x61, 0x78, 0x12, 0xA8, 0x44, 0xF6, 0x3D, 0xF9, 0x30, 0xB9, 0x9D, 0xF8, 0x48, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, + 0xF0, 0x04, 0x00, 0x60, 0x80, 0x61, 0x78, 0x04, 0xA8, 0x44, 0xF6, 0x9F, 0xF9, 0x70, 0xB9, 0x9D, 0xF8, 0x27, 0x00, 0x58, 0xB1, 0x08, 0x98, 0x20, 0x61, 0xBD, 0xF8, 0x24, 0x00, 0xA0, 0x82, 0x9D, 0xF8, 0x26, 0x00, 0xA0, 0x75, 0x60, 0x88, 0x40, + 0xF0, 0x08, 0x00, 0x60, 0x80, 0x61, 0x78, 0x1A, 0xA8, 0x44, 0xF6, 0x54, 0xFA, 0x30, 0xB9, 0x9D, 0xF8, 0x7D, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x10, 0x00, 0x60, 0x80, 0x61, 0x78, 0x20, 0xA8, 0x44, 0xF6, 0xB5, 0xFA, 0x30, 0xB9, 0x9D, + 0xF8, 0x95, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x20, 0x00, 0x60, 0x80, 0x60, 0x78, 0x44, 0xF6, 0x1F, 0xFB, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x40, 0x00, 0x60, 0x80, 0x29, 0x46, 0x12, 0x48, 0xFA, 0xF5, 0x76, 0xFE, 0x22, 0x79, 0x61, + 0x88, 0xA3, 0x7B, 0xCD, 0xE9, 0x02, 0x12, 0xCD, 0xE9, 0x00, 0x03, 0x0F, 0x49, 0x63, 0x78, 0x05, 0x22, 0x7C, 0x31, 0x04, 0x48, 0xFA, 0xF5, 0xAB, 0xFC, 0x01, 0x20, 0x88, 0xE7, 0x38, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0x02, 0x35, 0x10, + 0x21, 0x60, 0x3F, 0x80, 0x08, 0x64, 0x2E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x30, 0x21, 0x60, 0x2E, 0x20, 0x00, 0x68, 0x40, 0x80, 0x08, 0xEE, 0x2E, 0x20, + 0x00, 0xBC, 0x2E, 0x20, 0x00, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x2D, 0xE9, 0xFE, 0x43, 0x88, 0x46, 0x89, 0x4D, 0x00, 0x21, 0x11, 0x70, 0x29, 0x88, 0x88, 0x4E, 0x17, 0x46, 0x88, 0x42, 0x02, 0xD0, 0x00, 0x22, 0x86, 0x49, 0x49, + 0xE0, 0xD8, 0xF8, 0x00, 0x10, 0x01, 0x91, 0xD8, 0xF8, 0x04, 0x00, 0x02, 0x90, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x43, 0xF6, 0x08, 0xF8, 0x04, 0x00, 0x06, 0xD1, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x43, 0xF6, 0x61, 0xFB, 0x04, 0x00, 0x08, 0xD0, 0x01, 0x20, 0x7B, 0x49, 0x38, 0x70, 0x00, 0x22, 0x34, 0x31, 0x30, 0x46, 0xFA, 0xF5, 0x5F, 0xFC, 0x39, 0xE0, 0x9D, 0xF8, 0x0B, 0x00, 0x00, 0x27, 0x40, 0x07, 0x00, 0xD5, 0x01, + 0x27, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x43, 0xF6, 0x83, 0xF8, 0x04, 0x00, 0x0D, 0xD1, 0x43, 0xF6, 0xEF, 0xFA, 0x50, 0xB3, 0x40, 0x78, 0x3E, 0xF6, 0xD1, 0xFF, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x43, 0xF6, 0x75, 0xF8, 0x04, 0x00, 0x1F, 0xD0, 0x60, 0x78, 0x00, 0x90, 0x69, 0x48, 0x69, 0x49, 0x2A, 0x88, 0x00, 0x88, 0x09, 0x88, 0xD3, 0xB2, 0x08, 0x44, 0x81, 0xB2, 0x40, 0x46, 0x43, 0xF6, 0xFA, 0xFE, 0x40, + 0xB1, 0x62, 0x49, 0x00, 0x22, 0x64, 0x31, 0x30, 0x46, 0xFA, 0xF5, 0x2E, 0xFC, 0x00, 0x20, 0xBD, 0xE8, 0xFE, 0x83, 0x61, 0x78, 0x01, 0x20, 0x43, 0xF6, 0x05, 0xFE, 0x20, 0x46, 0xFF, 0xF7, 0xF7, 0xFE, 0x20, 0x46, 0xF4, 0xE7, 0x59, 0x49, 0x00, + 0x22, 0xA4, 0x31, 0xEC, 0xE7, 0x00, 0xB5, 0x91, 0xB0, 0x4F, 0xF4, 0xE8, 0x71, 0xAD, 0xF8, 0x00, 0x10, 0xAD, 0xF8, 0x04, 0x00, 0x01, 0x21, 0x68, 0x46, 0x14, 0xF6, 0xDC, 0xF8, 0x11, 0xB0, 0x00, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x01, 0x46, 0x51, + 0x48, 0x40, 0xF6, 0xE7, 0xFB, 0x68, 0xB1, 0x50, 0x49, 0x04, 0xEB, 0x44, 0x00, 0x09, 0x68, 0x01, 0xEB, 0x00, 0x10, 0x00, 0x8A, 0xFF, 0xF7, 0xE2, 0xFF, 0x08, 0xB1, 0x00, 0x20, 0x10, 0xBD, 0x07, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0x7F, + 0xB5, 0x49, 0x4D, 0x04, 0x46, 0x28, 0x68, 0x00, 0x28, 0x19, 0xD0, 0x60, 0x88, 0x40, 0xF6, 0x3B, 0xFB, 0x00, 0x28, 0x14, 0xD0, 0xC0, 0x78, 0x8D, 0xF8, 0x00, 0x00, 0x20, 0x88, 0xAD, 0xF8, 0x02, 0x00, 0x20, 0x79, 0x8D, 0xF8, 0x04, 0x00, 0xE0, + 0x88, 0xAD, 0xF8, 0x06, 0x00, 0x20, 0x89, 0xAD, 0xF8, 0x08, 0x00, 0xCD, 0xF8, 0x0C, 0xD0, 0x2A, 0x68, 0x03, 0xA9, 0x1B, 0x20, 0x90, 0x47, 0x7F, 0xBD, 0x10, 0xB5, 0x41, 0x88, 0x01, 0x24, 0xA1, 0xF5, 0x80, 0x71, 0xD1, 0x39, 0x02, 0xD0, 0x00, + 0x24, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x1D, 0xFF, 0xF7, 0xD2, 0xFF, 0xF9, 0xE7, 0x70, 0xB5, 0x0C, 0x46, 0x05, 0x46, 0x01, 0x46, 0x2E, 0x48, 0x86, 0xB0, 0x17, 0x30, 0x40, 0xF6, 0x9E, 0xFB, 0x90, 0xB3, 0x61, 0x1E, 0x4F, 0xF6, 0xFF, 0x72, 0x2A, + 0x4B, 0x05, 0xEB, 0x45, 0x00, 0x91, 0x42, 0x0E, 0xD2, 0x19, 0x68, 0x01, 0xEB, 0x00, 0x11, 0x8A, 0x8A, 0x02, 0xEB, 0x82, 0x02, 0x96, 0x08, 0xCA, 0x8A, 0x52, 0x1C, 0x56, 0x43, 0x04, 0xEB, 0x84, 0x02, 0xB6, 0xEB, 0x42, 0x0F, 0x1C, 0xDD, 0x19, + 0x68, 0x01, 0xEB, 0x00, 0x10, 0x81, 0x8A, 0xC0, 0x8A, 0x01, 0xEB, 0x81, 0x02, 0x92, 0x08, 0x43, 0x1C, 0x5A, 0x43, 0x04, 0xEB, 0x84, 0x03, 0x5B, 0x00, 0xCD, 0xE9, 0x00, 0x41, 0xCD, 0xE9, 0x02, 0x03, 0x14, 0x49, 0x04, 0x92, 0x2B, 0x46, 0x06, + 0x22, 0xC4, 0x31, 0x10, 0x48, 0xFA, 0xF5, 0x90, 0xFB, 0x03, 0x20, 0x06, 0xB0, 0x70, 0xBD, 0x15, 0xE0, 0x08, 0x8A, 0x8D, 0xF8, 0x14, 0x00, 0x00, 0x0A, + 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x20, 0x0A, + 0x8D, 0xF8, 0x17, 0x00, 0x05, 0xAA, 0x04, 0x21, 0x40, 0xF6, 0x7C, 0x40, 0x14, 0xF6, 0xC2, 0xF8, 0x08, 0xB1, 0x00, 0x20, 0xE8, 0xE7, 0x07, 0x20, 0xE6, 0xE7, 0x04, 0x20, 0xE4, 0xE7, 0x00, 0x00, 0xEE, 0x2E, 0x20, 0x00, 0x00, 0x35, 0x10, 0x21, + 0x40, 0x41, 0x80, 0x08, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x2C, 0xE2, 0x20, 0x00, 0x64, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0x70, 0xB5, 0x06, 0x46, 0x0D, 0x46, 0x00, 0x24, 0x07, 0x20, 0x10, 0xF0, 0x29, 0xFC, 0x00, 0x28, + 0x0A, + 0xD0, 0x29, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x09, 0xF8, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x10, 0xF0, 0x57, 0xFC, 0x20, 0x46, 0x70, 0xBD, 0x00, 0x00, 0x2D, 0xE9, 0xF0, 0x5F, 0x8B, 0x46, 0x80, 0x46, 0x29, 0x4C, 0xFE, 0xF5, 0xB4, + 0xFD, 0x04, 0x28, 0x02, 0xD2, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x9F, 0x25, 0x7A, 0x94, 0xF8, 0x00, 0x90, 0x66, 0x68, 0x28, 0xF0, 0x80, 0x74, 0x00, 0x27, 0x4F, 0xF4, 0x00, 0x0A, + 0x06, 0xF5, 0x00, 0x08, 0x54, 0x45, 0x01, 0xD3, 0x44, 0x45, 0x02, 0xD9, 0x6F, 0xF0, 0x02, 0x00, 0xEB, 0xE7, 0x58, 0x46, 0xFD, 0xF5, 0x9A, 0xF8, 0x01, 0x28, 0xE6, 0xD1, 0x9B, 0xF8, 0x00, 0x00, 0x78, 0xB3, 0xB9, 0xF1, 0xFF, 0x0F, 0x06, 0xD0, + 0xB9, 0xF1, 0x7F, 0x0F, 0x06, 0xD0, 0x44, 0x45, 0x0B, 0xD1, 0x2F, 0x46, 0x22, 0xE0, 0x44, 0x45, 0xFB, 0xD0, 0x1F, 0xE0, 0x0A, + 0xEB, 0x56, 0x00, 0xA0, 0x42, 0x1B, 0xD8, 0x6D, 0x1E, 0xEF, 0xB2, 0x18, 0xE0, 0x01, 0x20, 0x6A, 0x1E, 0x00, 0xFA, 0x02, 0xF1, 0x11, 0xE0, 0xB6, 0xFB, 0xF1, 0xF3, 0x42, 0x1E, 0x93, 0x40, 0xB6, 0xFB, 0xF1, 0xF2, 0x82, 0x40, 0x03, 0xF5, 0x00, + 0x03, 0x02, 0xF5, 0x00, 0x02, 0x9C, 0x42, 0x03, 0xD3, 0x94, 0x42, 0x01, 0xD2, 0xC7, 0xB2, 0x02, 0xE0, 0x40, 0x1C, 0xA8, 0x42, 0xEB, 0xDB, 0x38, 0x46, 0xFD, 0xF5, 0x8F, 0xF8, 0x01, 0x20, 0xB1, 0xE7, 0xDC, 0x0C, 0x20, 0x00, 0x30, 0xB5, 0x14, + 0x4C, 0x00, 0x22, 0x4F, 0xF4, 0x00, 0x45, 0x28, 0x46, 0x00, 0x21, 0x04, 0xEB, 0x41, 0x13, 0x03, 0xEB, 0x82, 0x03, 0xD3, 0xF8, 0xBC, 0x32, 0x00, 0x2B, 0x00, 0xDA, 0x5B, 0x42, 0x0B, 0xB1, 0x5B, 0x1E, 0x18, 0x43, 0x49, 0x1C, 0xC9, 0xB2, 0x0F, + 0x29, 0xEF, 0xD3, 0x00, 0x21, 0x01, 0xE0, 0x40, 0x08, 0x49, 0x1C, 0x00, 0x28, 0xFB, 0xD1, 0xC1, 0xF1, 0x20, 0x00, 0x04, 0xEB, 0x82, 0x01, 0x52, 0x1C, 0xC0, 0xF1, 0x10, 0x00, 0xD2, 0xB2, 0xC1, 0xF8, 0x9C, 0x02, 0x08, 0x2A, 0xDB, 0xD3, 0x30, + 0xBD, 0x64, 0x13, 0x21, 0x00, 0x01, 0x49, 0x00, 0x20, 0x08, 0x70, 0x70, 0x47, 0x64, 0x13, 0x21, 0x00, 0x70, 0xB5, 0x64, 0x4E, 0x78, 0x25, 0x04, 0x46, 0xB1, 0x68, 0x78, 0x29, 0x09, 0xDA, 0x06, 0xEB, 0x41, 0x01, 0x90, 0x22, 0x06, 0xF5, 0x03, + 0x70, 0x0C, 0x31, 0x4C, 0xF6, 0xD0, 0xFC, 0x4F, 0xF4, 0x80, 0x71, 0x5D, 0x48, 0x08, 0x40, 0x08, 0x28, 0x2C, 0xD1, 0x08, 0x39, 0xA2, 0x7B, 0xE3, 0x7B, 0x06, 0xEB, 0x41, 0x00, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x81, 0x22, 0x7B, 0x63, 0x7B, 0x70, + 0x25, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x82, 0x22, 0x78, 0x63, 0x78, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x82, 0xA2, 0x7A, 0xE3, 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x82, 0xA2, 0x78, 0xE3, 0x78, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x82, 0x22, 0x7A, 0x63, + 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x83, 0x22, 0x79, 0x63, 0x79, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x83, 0xA2, 0x79, 0xE3, 0x79, 0x10, 0x34, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x83, 0x10, 0x39, 0xA2, 0x7F, 0xE3, 0x7F, 0x06, 0xEB, 0x41, 0x00, 0x02, + 0xEB, 0x03, 0x22, 0x82, 0x81, 0xA2, 0x7B, 0xE3, 0x7B, 0x10, 0x3D, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x81, 0x22, 0x7F, 0x63, 0x7F, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x82, 0x22, 0x7C, 0x63, 0x7C, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x82, 0xA2, 0x7E, 0xE3, + 0x7E, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x82, 0xA2, 0x7C, 0xE3, 0x7C, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x82, 0x22, 0x7E, 0x63, 0x7E, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x83, 0x22, 0x7D, 0x63, 0x7D, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x83, 0xA2, 0x7D, 0xE3, + 0x7D, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x83, 0xA2, 0x79, 0xE3, 0x79, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x83, 0x22, 0x7B, 0x63, 0x7B, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x84, 0x22, 0x78, 0x63, 0x78, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x84, 0xA2, 0x7A, 0xE3, + 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x84, 0xA2, 0x78, 0xE3, 0x78, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x84, 0x22, 0x7A, 0x63, 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x02, 0x85, 0x22, 0x79, 0x63, 0x79, 0x20, 0x34, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x85, 0x10, + 0x2D, 0xA8, 0xDA, 0x08, 0x2D, 0x2B, 0xD1, 0x08, 0x39, 0xA2, 0x7B, 0xE3, 0x7B, 0x06, 0xEB, 0x41, 0x00, 0x02, 0xEB, 0x03, 0x22, 0x20, 0xF8, 0x02, 0x2C, 0xA2, 0x79, 0xE3, 0x79, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x81, 0x22, 0x7B, 0x63, 0x7B, 0x02, + 0xEB, 0x03, 0x22, 0x02, 0x82, 0x22, 0x78, 0x63, 0x78, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x82, 0xA2, 0x7A, 0xE3, 0x7A, 0x02, 0xEB, 0x03, 0x22, 0x82, 0x82, 0xA2, 0x78, 0xE3, 0x78, 0x02, 0xEB, 0x03, 0x22, 0xC2, 0x82, 0x22, 0x7A, 0x63, 0x7A, 0x02, + 0xEB, 0x03, 0x22, 0x02, 0x83, 0x22, 0x79, 0x63, 0x79, 0x02, 0xEB, 0x03, 0x22, 0x42, 0x83, 0x08, 0x46, 0x70, 0xBD, 0x00, 0x00, 0x64, 0x13, 0x21, 0x00, 0x0F, 0x00, 0x00, 0x80, 0xF0, 0xB5, 0x86, 0x4B, 0x8C, 0xB0, 0x5A, 0x68, 0xD4, 0x07, 0x7D, + 0xD0, 0x84, 0x4D, 0x52, 0x1C, 0x5A, 0x60, 0x4F, 0xF4, 0x00, 0x42, 0x07, 0x92, 0x06, 0x92, 0x05, 0x92, 0x04, 0x92, 0x03, 0x92, 0x02, 0x92, 0x01, 0x92, 0x00, 0x24, 0x00, 0x92, 0x30, 0xF8, 0x14, 0x30, 0x35, 0xF8, 0x14, 0x60, 0x00, 0x9A, 0x13, + 0xFB, 0x06, 0x26, 0x00, 0xEB, 0x44, 0x03, 0x05, 0xEB, 0x44, 0x02, 0x5F, 0x88, 0xB2, 0xF8, 0x02, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x00, 0x96, 0x9F, 0x88, 0xB2, 0xF8, 0x04, 0xC0, 0x01, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDF, 0x88, 0xB2, 0xF8, 0x06, + 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x01, 0x96, 0x1F, 0x89, 0xB2, 0xF8, 0x08, 0xC0, 0x02, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0x5F, 0x89, 0xB2, 0xF8, 0x0A, + 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x02, 0x96, 0x9F, 0x89, 0xB2, 0xF8, 0x0C, 0xC0, 0x03, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDF, 0x89, 0xB2, 0xF8, 0x0E, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x03, 0x96, 0x1F, 0x8A, 0xB2, 0xF8, 0x10, 0xC0, 0x04, 0x9E, 0x17, + 0xFB, 0x0C, 0x66, 0x5F, 0x8A, 0xB2, 0xF8, 0x12, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x04, 0x96, 0x9F, 0x8A, 0xB2, 0xF8, 0x14, 0xC0, 0x05, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDF, 0x8A, 0xB2, 0xF8, 0x16, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x05, 0x96, 0x1F, + 0x8B, 0xB2, 0xF8, 0x18, 0xC0, 0x06, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0x5F, 0x8B, 0xB2, 0xF8, 0x1A, 0xC0, 0x17, 0xFB, 0x0C, 0x66, 0x06, 0x96, 0x9F, 0x8B, 0xB2, 0xF8, 0x1C, 0xC0, 0x07, 0x9E, 0x17, 0xFB, 0x0C, 0x66, 0xDB, 0x8B, 0xD2, 0x8B, 0x13, + 0xFB, 0x02, 0x62, 0x10, 0x34, 0x07, 0x92, 0x50, 0x2C, 0x98, 0xDB, 0x00, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x20, 0x00, 0x01, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x22, 0x00, 0x00, 0xE0, 0x85, 0xE0, 0x02, 0x98, 0x08, 0xAE, 0x00, 0x14, 0xAD, 0xF8, 0x24, + 0x00, 0x03, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x26, 0x00, 0x04, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x28, 0x00, 0x05, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x2A, 0x00, 0x06, 0x98, 0x00, 0x14, 0xAD, 0xF8, 0x2C, 0x00, 0x10, 0x14, 0xAD, 0xF8, 0x2E, 0x00, 0x00, + 0x20, 0x07, 0x90, 0x06, 0x90, 0x05, 0x90, 0x04, 0x90, 0x03, 0x90, 0x02, 0x90, 0x01, 0x90, 0x04, 0x46, 0x00, 0x90, 0x05, 0xEB, 0x44, 0x10, 0x36, 0xF8, 0x24, 0x30, 0x00, 0x9A, 0x30, 0xF8, 0xA0, 0x7F, 0x13, 0xFB, 0x07, 0x27, 0x06, 0xEB, 0x84, + 0x02, 0xB0, 0xF8, 0x02, 0xC0, 0x52, 0x88, 0x12, 0xFB, 0x0C, 0x77, 0x00, 0x97, 0xB0, 0xF8, 0x04, 0xC0, 0x01, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x06, 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x01, 0x97, 0xB0, 0xF8, 0x08, 0xC0, 0x02, 0x9F, 0x13, + 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x0A, + 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x02, 0x97, 0xB0, 0xF8, 0x0C, 0xC0, 0x03, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x0E, 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x03, 0x97, 0xB0, 0xF8, 0x10, 0xC0, 0x04, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x12, + 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x04, 0x97, 0xB0, 0xF8, 0x14, 0xC0, 0x05, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x16, 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x05, 0x97, 0xB0, 0xF8, 0x18, 0xC0, 0x06, 0x9F, 0x13, 0xFB, 0x0C, 0x77, 0xB0, 0xF8, 0x1A, + 0xC0, 0x12, 0xFB, 0x0C, 0x77, 0x06, 0x97, 0xB0, 0xF8, 0x1C, 0xC0, 0x07, 0x9F, 0x13, 0xFB, 0x0C, 0x73, 0xC0, 0x8B, 0x12, 0xFB, 0x00, 0x30, 0x64, 0x1C, 0x07, 0x90, 0x04, 0x2C, 0xA6, 0xDB, 0x00, 0x20, 0x6A, 0x46, 0x52, 0xF8, 0x20, 0x30, 0x41, + 0xF8, 0x20, 0x30, 0x40, 0x1C, 0x08, 0x28, 0xF8, 0xDB, 0x0C, 0xB0, 0xF0, 0xBD, 0x03, 0x4D, 0xF9, 0xE6, 0x00, 0x00, 0x64, 0x13, 0x21, 0x00, 0x64, 0xE2, 0x20, 0x00, 0x84, 0xE3, 0x20, 0x00, 0x10, 0xB5, 0x91, 0xEA, 0x03, 0x0F, 0x48, 0xBF, 0x83, + 0xF0, 0x00, 0x43, 0x00, 0xF1, 0xD2, 0x80, 0x84, 0x1A, 0x71, 0xEB, 0x03, 0x0C, 0x05, 0xD2, 0x12, 0x19, 0x43, 0xEB, 0x0C, 0x03, 0x00, 0x1B, 0x61, 0xEB, 0x0C, 0x01, 0xDF, 0xF8, 0x24, 0xE1, 0x4F, 0xEA, 0x11, 0x54, 0xA4, 0xEB, 0x13, 0x5C, 0x1E, + 0xEA, 0x43, 0x0F, 0x18, 0xBF, 0x9E, 0xEA, 0x44, 0x5F, 0x73, 0xD0, 0x23, 0xEA, 0x0E, 0x03, 0xDC, 0xF1, 0x20, 0x0E, 0x21, 0xEA, 0x04, 0x51, 0x43, 0xF4, 0x80, 0x13, 0x32, 0xD3, 0x22, 0xFA, 0x0C, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x23, 0xFA, 0x0C, + 0xFE, 0x41, 0xEB, 0x0E, 0x01, 0xCC, 0xF1, 0x20, 0x0E, 0x03, 0xFA, 0x0E, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x51, 0xF1, 0x00, 0x01, 0xB1, 0xF5, 0x80, 0x1F, 0xCC, 0xF1, 0x20, 0x0E, 0x32, 0xD2, 0x01, 0xEB, 0x04, 0x51, 0x12, 0xFA, 0x0E, 0xF2, 0xBD, + 0xE8, 0x10, 0x40, 0x58, 0xBF, 0x70, 0x47, 0x40, 0x1C, 0x38, 0xBF, 0x5F, 0xEA, 0x42, 0x02, 0x18, 0xBF, 0x70, 0x47, 0x00, 0x28, 0x14, 0xBF, 0x20, 0xF0, 0x01, 0x00, 0x41, 0xF1, 0x00, 0x01, 0x4F, 0xEA, 0x41, 0x03, 0x13, 0xF5, 0x00, 0x1F, 0x38, + 0xBF, 0x70, 0x47, 0xA1, 0xF1, 0xC0, 0x41, 0x10, 0xF0, 0x80, 0xBC, 0x01, 0x2A, 0x43, 0xEB, 0x03, 0x02, 0xAC, 0xF1, 0x20, 0x0C, 0xDC, 0xF1, 0x1F, 0x0E, 0x32, 0xBF, 0x4F, 0xF0, 0x00, 0x0E, 0x23, 0xFA, 0x0C, 0xF3, 0x10, 0xEB, 0x03, 0x00, 0x41, + 0xEB, 0x04, 0x51, 0xB4, 0xEB, 0x11, 0x5F, 0xD0, 0xD0, 0xA1, 0xEB, 0x04, 0x51, 0x01, 0xF5, 0x80, 0x11, 0x49, 0x08, 0x5F, 0xEA, 0x30, 0x00, 0x01, 0xEB, 0x04, 0x51, 0x0E, 0xD3, 0x50, 0xF1, 0x00, 0x00, 0x38, 0xBF, 0x12, 0xFA, 0x0E, 0xFE, 0x08, + 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0xC9, 0xE7, 0x40, 0x1C, 0x38, 0xBF, 0x5F, 0xEA, 0x42, 0x02, 0xCA, 0xD1, 0xC3, 0xE7, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xEA, 0x41, 0x03, 0x13, 0xF5, 0x00, 0x1F, 0x38, 0xBF, 0x70, 0x47, 0xA1, 0xF1, 0xC0, 0x41, 0x10, + 0xF0, 0x48, 0xBC, 0x9E, 0xEA, 0x44, 0x5F, 0x08, 0xD0, 0x11, 0xEA, 0x5E, 0x0F, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0xBF, 0x01, 0xF0, 0x00, 0x41, 0x00, 0x20, 0x70, 0x47, 0xBD, 0xE8, 0x10, 0x40, 0x70, 0xB5, 0x10, 0xF0, 0xE9, 0xFB, 0x00, 0xBF, 0x64, + 0xFB, 0xBE, 0x3E, 0x00, 0x00, 0xE0, 0xFF, 0x10, 0xF0, 0x00, 0x42, 0x48, 0xBF, 0x40, 0x42, 0xB0, 0xFA, 0x80, 0xF3, 0x10, 0xFA, 0x03, 0xF1, 0x0A, + 0xD0, 0xC3, 0xF1, 0x1D, 0x03, 0x03, 0xF5, 0x80, 0x63, 0x4F, 0xEA, 0x41, 0x50, 0x02, 0xEB, 0x03, 0x52, 0x02, 0xEB, 0xD1, 0x21, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0xB0, 0xFA, 0x80, 0xF3, 0x10, 0xFA, 0x03, 0xF1, 0x0A, + 0xD0, 0xC3, 0xF1, 0x1D, 0x03, 0x03, 0xF5, 0x80, 0x63, 0x4F, 0xEA, 0x41, 0x50, 0x4F, 0xEA, 0x03, 0x52, 0x02, 0xEB, 0xD1, 0x21, 0x70, 0x47, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0x10, 0xB5, 0x91, 0xEA, 0x03, 0x0F, 0x48, 0xBF, 0x83, 0xF0, 0x00, + 0x43, 0x3F, 0xF5, 0x2E, 0xAF, 0x84, 0x1A, 0x71, 0xEB, 0x03, 0x0C, 0x07, 0xD2, 0x12, 0x19, 0x8C, 0xF0, 0x00, 0x4C, 0x43, 0xEB, 0x0C, 0x03, 0x00, 0x1B, 0x61, 0xEB, 0x0C, 0x01, 0xDF, 0xF8, 0xA4, 0xE1, 0x4F, 0xEA, 0x11, 0x54, 0xA4, 0xEB, 0x13, + 0x5C, 0x1E, 0xEA, 0x43, 0x0F, 0x18, 0xBF, 0x9E, 0xEA, 0x44, 0x5F, 0x00, 0xF0, 0xB0, 0x80, 0x23, 0xEA, 0x6E, 0x03, 0x52, 0x42, 0x21, 0xEA, 0x04, 0x51, 0xC3, 0xEB, 0x6E, 0x03, 0x38, 0xBF, 0x5B, 0x1E, 0xDC, 0xF1, 0x20, 0x0E, 0x25, 0xD3, 0x22, + 0xFA, 0x0C, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x43, 0xFA, 0x0C, 0xFE, 0x41, 0xEB, 0x0E, 0x01, 0xCC, 0xF1, 0x20, 0x0E, 0x03, 0xFA, 0x0E, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x51, 0xF1, 0x00, 0x01, 0xCC, 0xF1, 0x20, 0x0E, 0x29, 0xD4, 0x12, 0xFA, 0x0E, + 0xF2, 0x01, 0xEB, 0x04, 0x51, 0xBD, 0xE8, 0x10, 0x40, 0x58, 0xBF, 0x70, 0x47, 0x40, 0x1C, 0x1C, 0xBF, 0xB2, 0xF1, 0x00, 0x4F, 0x70, 0x47, 0x00, 0x28, 0x0C, 0xBF, 0x49, 0x1C, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x12, 0xEB, 0x02, 0x0E, 0x43, + 0xEB, 0x03, 0x02, 0x18, 0xBF, 0x4F, 0xF0, 0x01, 0x0E, 0x4E, 0xEA, 0x42, 0x02, 0xAC, 0xF1, 0x20, 0x0C, 0xDC, 0xF1, 0x1E, 0x0E, 0x54, 0xD9, 0x43, 0xFA, 0x0C, 0xFE, 0x10, 0xEB, 0x0E, 0x00, 0x51, 0xF1, 0xFF, 0x31, 0xCC, 0xF1, 0x1E, 0x0E, 0xD5, + 0xD5, 0x0E, 0xF1, 0x01, 0x0E, 0x12, 0xFA, 0x0E, 0xFE, 0x40, 0x41, 0x41, 0xEB, 0x01, 0x01, 0x01, 0xEB, 0x44, 0x5C, 0x5F, 0xEA, 0x5C, 0x5C, 0x10, 0xD9, 0x10, 0xEB, 0xDE, 0x70, 0x01, 0xEB, 0x04, 0x51, 0x38, 0xBF, 0xBE, 0xF1, 0x00, 0x4F, 0xBD, + 0xE8, 0x10, 0x40, 0x18, 0xBF, 0x70, 0x47, 0x00, 0x28, 0x0C, 0xBF, 0x49, 0x1C, 0x20, 0xF0, 0x01, 0x00, 0x70, 0x47, 0x30, 0xD2, 0x4F, 0xEA, 0xD4, 0x2C, 0x11, 0xF5, 0x00, 0x11, 0x24, 0xF4, 0x00, 0x64, 0x1B, 0xD0, 0xB1, 0xFA, 0x81, 0xF2, 0x0B, + 0x3A, 0xA4, 0x1A, 0xA4, 0x1E, 0xD2, 0xF1, 0x20, 0x03, 0x91, 0x40, 0x30, 0xFA, 0x03, 0xF3, 0x19, 0x43, 0x90, 0x40, 0x01, 0xEB, 0xCC, 0x71, 0x00, 0x2C, 0x01, 0xEB, 0x04, 0x51, 0xBD, 0xE8, 0x10, 0x40, 0xA8, 0xBF, 0x70, 0x47, 0x01, 0xF1, 0xC0, + 0x41, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x41, 0x70, 0x47, 0xB0, 0xFA, 0x80, 0xF3, 0x10, 0xFA, 0x03, 0xF1, 0x00, 0xD1, 0x10, 0xBD, 0xE4, 0x1A, 0x17, 0x3C, 0x48, 0x05, 0xC9, 0x0A, + 0xE4, 0xE7, 0x01, 0xEB, 0x04, 0x51, 0x10, 0xBD, 0x49, 0x10, 0x01, 0xEB, 0x04, 0x51, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xEA, 0x30, 0x00, 0x02, 0xE0, 0x4F, 0xF0, 0x00, 0x01, 0x70, 0x47, 0x4A, 0x00, 0x08, 0xBF, 0x00, 0x42, 0xF8, 0xD0, 0xB2, 0xF5, + 0x00, 0x1F, 0x28, 0xBF, 0x70, 0x47, 0x01, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, 0x70, 0x47, 0x9E, 0xEA, 0x44, 0x5F, 0x07, 0xD0, 0x11, 0xEA, 0x5E, 0x0F, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0xBF, 0x00, 0x21, 0x00, 0x20, 0x70, 0x47, 0xBD, 0xE8, + 0x10, 0x40, 0x70, 0xB5, 0x10, 0xF0, 0xD9, 0xFA, 0x00, 0xBF, 0x40, 0xDF, 0xF6, 0x3E, 0x83, 0xF0, 0x00, 0x41, 0x10, 0x46, 0x70, 0x47, 0x00, 0x00, 0xE0, 0xFF, 0x4F, 0xF0, 0x40, 0x70, 0xE1, 0xEE, 0x10, 0x0A, + 0x70, 0x47, 0xFF, 0x21, 0x41, 0xEA, 0xD0, 0x50, 0xC0, 0x05, 0x70, 0x47, 0x02, 0x08, 0x00, 0x28, 0x0A, + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x29, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x24, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x25, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x27, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x26, 0x2A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x28, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x23, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x2A, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x50, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x39, 0x92, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, 0x05, 0x07, 0x09, 0x06, 0xA1, 0x01, 0x85, 0x01, 0x95, 0x08, 0x75, 0x08, 0x15, 0x00, 0x25, + 0xFF, 0x19, 0x00, 0x29, 0xFF, 0x81, 0x00, 0xC0, 0x05, 0x0C, 0x09, 0x01, 0xA1, 0x01, 0x85, 0x02, 0x95, 0x02, 0x75, 0x10, 0x15, 0x00, 0x26, 0x9C, 0x02, 0x19, 0x00, 0x2A, 0x9C, 0x02, 0x81, 0x00, 0xC0, 0x06, 0x00, 0xFF, 0x09, 0x00, 0xA1, 0x01, + 0x85, 0x5A, 0x95, 0xFF, 0x75, 0x08, 0x15, 0x00, 0x25, 0xFF, 0x19, 0x00, 0x29, 0xFF, 0x81, 0x00, 0xC0, 0xC0, 0x00, 0x02, 0x08, 0x00, 0x28, 0x12, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4A, 0x2A, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4C, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4E, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x4B, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x1A, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x01, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, + 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x5A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x5A, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x4D, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x29, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x69, 0xCC, 0x21, 0x00, 0x4D, 0xCD, 0x21, 0x00, 0x1B, 0xCE, 0x21, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xD1, 0x00, 0x00, 0x12, + 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x62, 0x00, 0x00, 0x12, 0x08, 0x07, 0x0D, 0x0A, + 0x0C, 0x0C, 0x01, 0x0F, 0x0C, 0x0A, + 0x0A, + 0x0C, 0x0C, 0x13, 0x10, 0x06, 0x04, 0x0A, + 0x0C, 0x0C, 0x0B, 0x03, 0x05, 0x02, 0x0A, + 0x0C, 0x0C, 0x09, 0x00, 0x00, 0x00, 0x0A, + 0x0C, 0x0C, 0x09, 0x00, 0x00, 0x00, 0x0A, + 0x0C, 0x0C, 0x00, 0x00, 0x66, 0x00, 0x4B, 0x00, 0x4E, 0x00, 0x76, 0x00, 0x4A, 0x00, 0x3E, 0x00, 0x28, 0x00, 0x29, 0x00, 0x50, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x51, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x80, 0x00, 0x81, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, 0xCD, 0x00, 0xE2, 0x00, 0xE5, 0x00, 0xE7, 0x00, 0xE9, 0x00, 0xEA, 0x00, 0x52, 0x01, 0x53, 0x01, 0x54, 0x01, 0x55, 0x01, 0x83, 0x01, 0x8A, 0x01, 0x92, 0x01, 0x94, 0x01, 0x21, 0x02, 0x23, 0x02, + 0x24, 0x02, 0x25, 0x02, 0x26, 0x02, 0x27, 0x02, 0x2A, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x03, 0x20, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x04, 0x20, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x05, 0x20, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x20, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x07, 0x20, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x65, 0x5F, 0x72, + 0x65, 0x61, 0x64, 0x5F, 0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x6C, 0x65, 0x5F, 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x5F, 0x70, 0x61, 0x79, 0x6C, 0x6F, + 0x61, 0x64, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x00, 0x00, 0x00, 0x00, 0x70, 0x01, 0x19, 0x00, 0x1C, 0x01, 0x3F, 0x00, 0x0F, 0x01, 0x73, 0x00, 0xED, 0x00, 0x77, 0xFF, 0x00, 0x00, 0x4F, 0x01, 0x2C, 0x02, 0x6E, 0x01, 0x2F, 0x01, + 0x50, 0x01, 0x25, 0x00, 0x0B, 0x04, 0x3E, 0x09, 0xFD, 0x04, 0x84, 0x09, 0x80, 0x07, 0xA2, 0x0B, 0x59, 0x0A, + 0xE9, 0x0C, 0x7B, 0xF6, 0x00, 0x00, 0x81, 0x05, 0x0C, 0x21, 0x19, 0x02, 0x06, 0x1C, 0x02, 0xFC, 0x32, 0x15, 0x94, 0x30, 0xFC, 0x68, 0x8F, 0x33, 0x55, 0x5A, 0xFB, 0x45, 0xF3, 0x64, 0x45, 0x5A, 0x2F, 0x6C, 0xEB, 0xAF, 0x00, 0x00, 0x55, 0x5A, + 0x71, 0xCC, 0xF3, 0x64, 0x05, 0xBA, 0x2F, 0x6C, 0xBB, 0xA5, 0x6C, 0xCF, 0x3E, 0x09, 0xF4, 0xDE, 0x81, 0x05, 0xFA, 0xE3, 0x19, 0x02, 0xCE, 0xEA, 0x02, 0xFC, 0x83, 0x09, 0x00, 0x00, 0x84, 0x09, 0x03, 0xFB, 0xA2, 0x0B, 0x80, 0xF8, 0xE9, 0x0C, + 0xA7, 0xF5, 0xF5, 0xFB, 0x70, 0x01, 0xD4, 0xFD, 0x4F, 0x01, 0xD1, 0xFE, 0x6E, 0x01, 0xDB, 0xFF, 0x50, 0x01, 0x6A, 0xFF, 0x00, 0x00, 0x1C, 0x01, 0xE7, 0xFF, 0x0F, 0x01, 0xC1, 0xFF, 0xED, 0x00, 0x8D, 0xFF, 0x6F, 0x20, 0xDA, 0x2B, 0x91, 0xDF, + 0xB6, 0xF5, 0x91, 0xDF, 0x46, 0xCC, 0x6F, 0x20, 0xB3, 0xE2, 0x6F, 0x20, 0x4D, 0x1D, 0x91, 0xDF, 0xBA, 0x33, 0x91, 0xDF, 0x4A, 0x0A, + 0x6F, 0x20, 0x26, 0xD4, 0x36, 0x2A, 0x97, 0x27, 0x7C, 0x11, 0x90, 0x21, 0x84, 0xEE, 0x6D, 0x16, 0xCA, 0xD5, 0xE0, 0x07, 0xCA, 0xD5, 0x20, 0xF8, 0x84, 0xEE, 0x93, 0xE9, 0x7C, 0x11, 0x70, 0xDE, 0x36, 0x2A, 0x69, 0xD8, 0x90, 0xCD, 0x4D, 0x1D, + 0x90, 0xCD, 0x46, 0xCC, 0x90, 0xCD, 0x4A, 0x0A, + 0x90, 0xCD, 0xDA, 0x2B, 0x90, 0xCD, 0x26, 0xD4, 0x90, 0xCD, 0xB6, 0xF5, 0x90, 0xCD, 0xBA, 0x33, 0x90, 0xCD, 0xB3, 0xE2, 0x7C, 0x11, 0xE0, 0x07, 0xCA, 0xD5, 0x93, 0xE9, 0x36, 0x2A, 0x90, 0x21, 0x84, 0xEE, 0x69, 0xD8, 0x84, 0xEE, 0x97, 0x27, + 0x36, 0x2A, 0x70, 0xDE, 0xCA, 0xD5, 0x6D, 0x16, 0x7C, 0x11, 0x20, 0xF8, 0x00, 0x00, 0x77, 0xFF, 0x19, 0x00, 0x1C, 0x01, 0x3F, 0x00, 0x0F, 0x01, 0x73, 0x00, 0xED, 0x00, 0x70, 0x01, 0x0B, 0x04, 0x4F, 0x01, 0x2C, 0x02, 0x6E, 0x01, 0x2F, 0x01, + 0x50, 0x01, 0x25, 0x00, 0x00, 0x00, 0x7B, 0xF6, 0xFD, 0x04, 0x84, 0x09, 0x80, 0x07, 0xA2, 0x0B, 0x59, 0x0A, + 0xE9, 0x0C, 0x3E, 0x09, 0x94, 0x30, 0x81, 0x05, 0x0C, 0x21, 0x19, 0x02, 0x06, 0x1C, 0x02, 0xFC, 0x32, 0x15, 0x00, 0x00, 0xEB, 0xAF, 0x8F, 0x33, 0x55, 0x5A, 0xFB, 0x45, 0xF3, 0x64, 0x45, 0x5A, 0x2F, 0x6C, 0xFC, 0x68, 0x6C, 0xCF, 0x55, 0x5A, + 0x71, 0xCC, 0xF3, 0x64, 0x05, 0xBA, 0x2F, 0x6C, 0xBB, 0xA5, 0x00, 0x00, 0x83, 0x09, 0xF4, 0xDE, 0x81, 0x05, 0xFA, 0xE3, 0x19, 0x02, 0xCE, 0xEA, 0x02, 0xFC, 0x3E, 0x09, 0xF5, 0xFB, 0x84, 0x09, 0x03, 0xFB, 0xA2, 0x0B, 0x80, 0xF8, 0xE9, 0x0C, + 0xA7, 0xF5, 0x00, 0x00, 0x6A, 0xFF, 0xD4, 0xFD, 0x4F, 0x01, 0xD1, 0xFE, 0x6E, 0x01, 0xDB, 0xFF, 0x50, 0x01, 0x70, 0x01, 0x00, 0x00, 0x1C, 0x01, 0xE7, 0xFF, 0x0F, 0x01, 0xC1, 0xFF, 0xED, 0x00, 0x8D, 0xFF, 0x90, 0xCD, 0xDA, 0x2B, 0x90, 0xCD, + 0xB6, 0xF5, 0x90, 0xCD, 0x46, 0xCC, 0x90, 0xCD, 0xB3, 0xE2, 0x90, 0xCD, 0x4D, 0x1D, 0x90, 0xCD, 0xBA, 0x33, 0x90, 0xCD, 0x4A, 0x0A, + 0x90, 0xCD, 0x26, 0xD4, 0x36, 0x2A, 0x97, 0x27, 0x7C, 0x11, 0x90, 0x21, 0x84, 0xEE, 0x6D, 0x16, 0xCA, 0xD5, 0xE0, 0x07, 0xCA, 0xD5, 0x20, 0xF8, 0x84, 0xEE, 0x93, 0xE9, 0x7C, 0x11, 0x70, 0xDE, 0x36, 0x2A, 0x69, 0xD8, 0x6F, 0x20, 0x4D, 0x1D, + 0x91, 0xDF, 0x46, 0xCC, 0x91, 0xDF, 0x4A, 0x0A, + 0x6F, 0x20, 0xDA, 0x2B, 0x6F, 0x20, 0x26, 0xD4, 0x91, 0xDF, 0xB6, 0xF5, 0x91, 0xDF, 0xBA, 0x33, 0x6F, 0x20, 0xB3, 0xE2, 0x7C, 0x11, 0xE0, 0x07, 0xCA, 0xD5, 0x93, 0xE9, 0x36, 0x2A, 0x90, 0x21, 0x84, 0xEE, 0x69, 0xD8, 0x84, 0xEE, 0x97, 0x27, + 0x36, 0x2A, 0x70, 0xDE, 0xCA, 0xD5, 0x6D, 0x16, 0x7C, 0x11, 0x20, 0xF8, 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, 0x25, 0x38, 0x1F, 0x02, + 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, + 0x67, 0x7A, 0x5D, 0x40, 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, + 0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, + 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, + 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, + 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, + 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4, 0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x42, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x43, 0x00, 0x42, 0x6F, 0x6F, 0x74, 0x4F, 0x6E, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x72, 0x01, + 0x0E, 0x01, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00, 0x03, 0x04, 0x05, 0xFE, 0x00, 0x65, 0x78, 0x70, 0x65, 0x72, 0x69, 0x6D, 0x65, 0x6E, 0x74, 0x61, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x58, 0xE1, 0x20, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, + 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x03, 0x19, 0x80, 0x01, 0x02, 0x01, 0x05, 0x03, 0x03, 0x12, 0x18, 0x03, 0x19, 0x80, 0x01, 0x0B, + 0x09, 0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, 0x05, 0xFF, 0x5D, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x03, 0x03, 0x12, 0x18, 0x03, 0x19, 0x80, 0x01, 0x0B, 0x09, 0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, + 0x05, 0xFF, 0x5D, 0x00, 0x04, 0x00, 0x02, 0x01, 0x04, 0x03, 0x03, 0x12, 0x18, 0x03, 0x19, 0x80, 0x01, 0x0D, 0xFF, 0x5D, 0x00, 0x03, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0xE5, 0x20, 0x00, 0x1C, 0x53, 0x81, 0x00, + 0x1C, 0x53, 0x81, 0x00, 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC4, 0xE5, 0x20, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x1C, 0x53, 0x81, 0x00, + 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xE5, 0x20, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x1C, 0x53, 0x81, 0x00, 0x58, 0x19, 0x21, 0x00, + 0x58, 0x19, 0x21, 0x00, 0x58, 0x19, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x5A, 0x00, 0x00, 0xEC, 0xF7, 0x24, 0xFC, 0x11, 0x46, 0xEB, 0xF7, 0xFB, 0xFD, 0x01, 0xF0, 0x7D, 0xF9, 0x3E, 0xF6, + 0x09, 0xFF, 0x00, 0x00, 0x0B, 0x49, 0xD1, 0xF8, 0x00, 0xC0, 0x4A, 0x68, 0x5C, 0xF8, 0x04, 0x3B, 0x10, 0x68, 0x18, 0x44, 0x42, 0xF8, 0x04, 0x0B, 0x8C, 0x45, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x0C, 0x8A, 0x42, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x02, + 0xC1, 0xF8, 0x00, 0xC0, 0x4A, 0x60, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0x50, 0x19, 0x21, 0x00, 0x30, 0xB5, 0x82, 0x68, 0x22, 0xF0, 0x00, 0x42, 0x82, 0x60, 0x82, 0x69, 0x42, 0xF0, 0x1F, 0x02, 0x82, 0x61, 0x02, 0x68, 0x53, 0x4B, 0x1A, 0x40, + 0x02, 0x60, 0x02, 0x68, 0x91, 0xF8, 0x2E, 0x30, 0x1A, 0x43, 0x8B, 0x8D, 0x42, 0xEA, 0x03, 0x22, 0x02, 0x60, 0xCB, 0x69, 0x8A, 0x6A, 0x1A, 0x43, 0x0B, 0x6A, 0x1A, 0x43, 0x82, 0x60, 0x82, 0x68, 0x0B, 0x8E, 0x42, 0xEA, 0x43, 0x12, 0x82, 0x60, + 0x82, 0x68, 0x91, 0xF8, 0x34, 0x30, 0x42, 0xEA, 0xC3, 0x52, 0x82, 0x60, 0x4B, 0x69, 0xCA, 0x68, 0x1A, 0x43, 0x0B, 0x69, 0x1A, 0x43, 0x42, 0x60, 0x42, 0x68, 0x91, 0xF8, 0x33, 0x30, 0x4C, 0x89, 0x1A, 0x43, 0x91, 0xF8, 0x32, 0x30, 0x9B, 0x04, + 0x43, 0xEA, 0x44, 0x23, 0x1A, 0x43, 0x42, 0x60, 0x4A, 0x88, 0x01, 0x25, 0x05, 0xFA, 0x02, 0xF3, 0x1C, 0x02, 0x52, 0x1E, 0xA4, 0xF5, 0x80, 0x74, 0x14, 0x43, 0xC4, 0x60, 0x09, 0x88, 0x05, 0xFA, 0x01, 0xF3, 0x49, 0x1E, 0x5B, 0x1E, 0x43, 0xEA, + 0x01, 0x41, 0x01, 0x61, 0xC1, 0x69, 0x41, 0xF0, 0xFF, 0x01, 0xC1, 0x61, 0x81, 0x69, 0x21, 0xF0, 0x1F, 0x01, 0x81, 0x61, 0x30, 0xBD, 0x00, 0x22, 0x2F, 0x49, 0x30, 0x48, 0x00, 0xF0, 0x62, 0xB8, 0x02, 0x21, 0x10, 0xB5, 0x41, 0x80, 0x01, 0x80, + 0x0B, 0x07, 0x4A, 0x07, 0xC3, 0x61, 0x4F, 0xF4, 0xFC, 0x71, 0x82, 0x62, 0x81, 0x85, 0x01, 0x21, 0x80, 0xF8, 0x2E, 0x10, 0x01, 0x86, 0x0C, 0x07, 0x04, 0x62, 0xCC, 0x07, 0xC4, 0x60, 0xC0, 0xE9, 0x04, 0x23, 0x10, 0x22, 0x42, 0x81, 0x80, 0xF8, + 0x32, 0x20, 0x80, 0xF8, 0x33, 0x10, 0x03, 0x21, 0x80, 0xF8, 0x34, 0x10, 0x10, 0xBD, 0x01, 0x2A, 0x82, 0x68, 0x02, 0xD0, 0x8A, 0x43, 0x82, 0x60, 0x70, 0x47, 0x0A, + 0x43, 0xFB, 0xE7, 0x01, 0x2A, 0x82, 0x69, 0x02, 0xD0, 0x8A, 0x43, 0x82, 0x61, 0x70, 0x47, 0x0A, + 0x43, 0xFB, 0xE7, 0x10, 0xB5, 0x00, 0x23, 0x04, 0xE0, 0x44, 0x69, 0x5B, 0x1C, 0x21, 0xF8, 0x02, 0x4B, 0x9B, 0xB2, 0x93, 0x42, 0xF8, 0xD3, 0x10, 0xBD, 0x00, 0x29, 0x81, 0x68, 0x02, 0xD0, 0x41, 0xF0, 0x00, 0x41, 0x01, 0xE0, 0x21, 0xF0, 0x00, + 0x41, 0x81, 0x60, 0x70, 0x47, 0x01, 0x2A, 0x0D, 0x4B, 0x82, 0x68, 0xC1, 0xF3, 0x08, 0x01, 0x22, 0xF4, 0x00, 0x12, 0x82, 0x60, 0x82, 0x68, 0x02, 0xEA, 0x03, 0x02, 0x82, 0x60, 0x82, 0x68, 0x42, 0xEA, 0x01, 0x31, 0x03, 0xD1, 0x81, 0x60, 0x81, + 0x68, 0x41, 0xF4, 0x00, 0x11, 0x81, 0x60, 0x70, 0x47, 0xE0, 0x00, 0xFC, 0xFF, 0x40, 0x00, 0x00, 0x60, 0x00, 0x00, 0x08, 0x08, 0xFF, 0x0F, 0xE0, 0xFF, 0xF0, 0xB5, 0x4F, 0xF4, 0x90, 0x77, 0x7B, 0x06, 0xC0, 0xF3, 0x81, 0x66, 0xC1, 0xF3, 0x41, + 0x75, 0x4F, 0xF4, 0xA0, 0x7E, 0x40, 0xEA, 0x01, 0x04, 0x01, 0x2A, 0x06, 0xD0, 0xB9, 0x42, 0x6C, 0xD0, 0x71, 0x45, 0x6A, 0xD0, 0x10, 0x29, 0x68, 0xD0, 0x49, 0xE0, 0xA1, 0xF1, 0xC0, 0x4C, 0xBC, 0xF1, 0x40, 0x0C, 0x16, 0xD0, 0xB1, 0xF1, 0xC2, + 0x4F, 0x1E, 0xD0, 0x1C, 0xF1, 0x30, 0x0C, 0x03, 0xD0, 0xDF, 0xF8, 0xF0, 0xC2, 0x61, 0x45, 0x24, 0xD1, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x80, 0x6C, 0xC3, 0xF8, 0x0C, 0xC2, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x00, 0x6C, 0xC3, 0xF8, 0x0C, + 0xC2, 0x27, 0xE0, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x80, 0x6C, 0xC3, 0xF8, 0x0C, 0xC2, 0xD3, 0xF8, 0x0C, 0xC2, 0x4C, 0xF0, 0x00, 0x5C, 0xF1, 0xE7, 0xD3, 0xF8, 0x0C, 0x42, 0x44, 0xF0, 0x80, 0x64, 0xC3, 0xF8, 0x0C, 0x42, 0xD3, 0xF8, 0x0C, + 0x42, 0x44, 0xF0, 0x80, 0x54, 0xC3, 0xF8, 0x0C, 0x42, 0x15, 0xE0, 0xDF, 0xF8, 0xA4, 0xC2, 0x61, 0x45, 0x0B, 0xD1, 0xD3, 0xF8, 0x60, 0xC3, 0x4C, 0xF4, 0x00, 0x7C, 0xC3, 0xF8, 0x60, 0xC3, 0xD3, 0xF8, 0x48, 0xC3, 0x4C, 0xF0, 0x10, 0x0C, 0xC3, + 0xF8, 0x48, 0xC3, 0xB9, 0x42, 0x1D, 0xD0, 0x71, 0x45, 0x1B, 0xD0, 0x10, 0x29, 0x19, 0xD0, 0x20, 0xF0, 0x40, 0x63, 0x21, 0xF0, 0xC0, 0x40, 0x4F, 0xEA, 0x86, 0x01, 0x01, 0xF1, 0x80, 0x41, 0x01, 0x2A, 0xD1, 0xF8, 0x10, 0x22, 0x17, 0xD0, 0x9A, + 0x43, 0xC1, 0xF8, 0x10, 0x22, 0xA9, 0x00, 0x01, 0xF1, 0x80, 0x41, 0xD1, 0xF8, 0x2C, 0x22, 0x82, 0x43, 0x22, 0xEA, 0x40, 0x00, 0xC1, 0xF8, 0x2C, 0x02, 0xF0, 0xBD, 0xD3, 0xF8, 0x20, 0x02, 0x20, 0x43, 0x02, 0xE0, 0xD3, 0xF8, 0x20, 0x02, 0xA0, + 0x43, 0xC3, 0xF8, 0x20, 0x02, 0xF0, 0xBD, 0x1A, 0x43, 0xC1, 0xF8, 0x10, 0x22, 0xA9, 0x00, 0x01, 0xF1, 0x80, 0x41, 0xD1, 0xF8, 0x2C, 0x22, 0x02, 0x43, 0x42, 0xEA, 0x40, 0x00, 0xE6, 0xE7, 0x87, 0x4B, 0x4F, 0xF0, 0x80, 0x42, 0x98, 0x42, 0x16, + 0xD1, 0xD2, 0xF8, 0x34, 0x02, 0x20, 0xF4, 0x80, 0x30, 0xC2, 0xF8, 0x34, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x10, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0xC1, 0x40, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x34, + 0x02, 0x40, 0xF4, 0x80, 0x30, 0x18, 0xE0, 0x7A, 0x4B, 0x98, 0x42, 0x17, 0xD1, 0xD2, 0xF8, 0x34, 0x02, 0x20, 0xF4, 0x80, 0x20, 0xC2, 0xF8, 0x34, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x00, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, + 0x03, 0x40, 0xEA, 0x41, 0x50, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x34, 0x02, 0x40, 0xF4, 0x80, 0x20, 0xC2, 0xF8, 0x34, 0x02, 0x70, 0x47, 0x6D, 0x4B, 0x9A, 0x04, 0x98, 0x42, 0x16, 0xD1, 0xD2, 0xF8, 0x38, 0x02, 0x20, 0xF0, 0x01, 0x00, 0xC2, + 0xF8, 0x38, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x30, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0xC1, 0x30, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x38, 0x02, 0x40, 0xF0, 0x01, 0x00, 0x18, 0xE0, 0x60, 0x4B, 0x98, + 0x42, 0x17, 0xD1, 0xD2, 0xF8, 0x38, 0x02, 0x20, 0xF0, 0x04, 0x00, 0xC2, 0xF8, 0x38, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x20, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0x41, 0x40, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, + 0xF8, 0x38, 0x02, 0x40, 0xF0, 0x04, 0x00, 0xC2, 0xF8, 0x38, 0x02, 0x70, 0x47, 0x53, 0x4B, 0x5A, 0x04, 0x98, 0x42, 0x18, 0xD1, 0xD2, 0xF8, 0x34, 0x02, 0x20, 0xF0, 0x01, 0x00, 0xC2, 0xF8, 0x34, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, + 0x60, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0x41, 0x20, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x34, 0x02, 0x40, 0xF0, 0x01, 0x00, 0xC2, 0xF8, 0x34, 0x02, 0x70, 0x47, 0x46, 0x4B, 0x98, 0x42, 0xFB, 0xD1, 0xD2, 0xF8, 0x30, + 0x02, 0x20, 0xF4, 0x80, 0x50, 0xC2, 0xF8, 0x30, 0x02, 0xD2, 0xF8, 0x5C, 0x03, 0x20, 0xF4, 0xC0, 0x50, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x5C, 0x03, 0x40, 0xEA, 0xC1, 0x20, 0xC2, 0xF8, 0x5C, 0x03, 0xD2, 0xF8, 0x30, 0x02, 0x40, 0xF4, 0x80, + 0x50, 0xC2, 0xF8, 0x30, 0x02, 0x70, 0x47, 0x30, 0xB5, 0x4F, 0xF4, 0xA0, 0x74, 0x23, 0x06, 0xC0, 0xF3, 0x41, 0x72, 0x4F, 0xF4, 0x90, 0x75, 0x01, 0x29, 0x06, 0xD0, 0xA8, 0x42, 0x1E, 0xD0, 0xA0, 0x42, 0x1C, 0xD0, 0x10, 0x28, 0x1A, 0xD0, 0x05, + 0xE0, 0xA8, 0x42, 0x13, 0xD0, 0xA0, 0x42, 0x11, 0xD0, 0x10, 0x28, 0x0F, 0xD0, 0x01, 0x29, 0x4F, 0xEA, 0x82, 0x01, 0x01, 0xF1, 0x80, 0x41, 0x20, 0xF0, 0xC0, 0x40, 0xD1, 0xF8, 0x2C, 0x22, 0x0F, 0xD0, 0x82, 0x43, 0x22, 0xEA, 0x40, 0x00, 0xC1, + 0xF8, 0x2C, 0x02, 0x30, 0xBD, 0xD3, 0xF8, 0x20, 0x12, 0x01, 0x43, 0x02, 0xE0, 0xD3, 0xF8, 0x20, 0x12, 0x81, 0x43, 0xC3, 0xF8, 0x20, 0x12, 0x30, 0xBD, 0x02, 0x43, 0x42, 0xEA, 0x40, 0x00, 0xEE, 0xE7, 0xC0, 0xF3, 0x81, 0x62, 0x4F, 0xF0, 0x80, + 0x43, 0x01, 0x29, 0x06, 0xD0, 0x02, 0x28, 0x1C, 0xD0, 0x04, 0x28, 0x1A, 0xD0, 0x01, 0x28, 0x18, 0xD0, 0x05, 0xE0, 0x02, 0x28, 0x11, 0xD0, 0x04, 0x28, 0x0F, 0xD0, 0x01, 0x28, 0x0D, 0xD0, 0x01, 0x29, 0x4F, 0xEA, 0x82, 0x01, 0x01, 0xF1, 0x80, + 0x41, 0x20, 0xF0, 0x40, 0x60, 0xD1, 0xF8, 0x10, 0x22, 0x0D, 0xD0, 0x82, 0x43, 0xC1, 0xF8, 0x10, 0x22, 0x70, 0x47, 0xD3, 0xF8, 0x20, 0x12, 0x01, 0x43, 0x02, 0xE0, 0xD3, 0xF8, 0x20, 0x12, 0x81, 0x43, 0xC3, 0xF8, 0x20, 0x12, 0x70, 0x47, 0x02, + 0x43, 0xF0, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x60, 0x00, 0x40, 0x00, 0x20, 0x00, 0x30, 0x01, 0x40, 0x00, 0x34, 0x01, 0x40, 0x00, 0x50, 0x01, 0x40, 0x00, 0x54, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00, 0x10, 0x01, 0x40, 0x4D, 0x49, 0x88, + 0x42, 0x04, 0xD1, 0x00, 0x22, 0x4F, 0xF4, 0x90, 0x71, 0x02, 0x20, 0x06, 0xE0, 0x4A, 0x49, 0x88, 0x42, 0x05, 0xD1, 0x00, 0x22, 0x4F, 0xF4, 0xA0, 0x71, 0x04, 0x20, 0xFF, 0xF7, 0x45, 0xBE, 0x70, 0x47, 0x10, 0xB5, 0x42, 0x68, 0x42, 0xF0, 0x01, + 0x02, 0x42, 0x60, 0x42, 0x68, 0x22, 0xF0, 0x01, 0x02, 0x42, 0x60, 0x0B, 0x89, 0x4F, 0xF0, 0x00, 0x44, 0x4A, 0x68, 0x44, 0xEA, 0x03, 0x43, 0x1A, 0x43, 0xC2, 0x61, 0x4B, 0x69, 0xCA, 0x6A, 0x1A, 0x43, 0xD1, 0xE9, 0x08, 0x43, 0x23, 0x43, 0x1A, + 0x43, 0x8B, 0x69, 0x1A, 0x43, 0x8B, 0x6A, 0x1A, 0x43, 0x0B, 0x69, 0x1A, 0x43, 0xCB, 0x69, 0x1A, 0x43, 0xCB, 0x68, 0x1A, 0x43, 0x0B, 0x6B, 0x1A, 0x43, 0x34, 0x4B, 0x1A, 0x43, 0x42, 0x60, 0x0A, + 0x68, 0x43, 0xF2, 0x81, 0x03, 0x1A, 0x43, 0x82, 0x60, 0x82, 0x68, 0x22, 0xF4, 0x40, 0x52, 0x82, 0x60, 0xD1, 0xE9, 0x0D, 0x21, 0x42, 0xEA, 0x01, 0x21, 0x01, 0x62, 0x10, 0xBD, 0x4F, 0xF4, 0x80, 0x31, 0x01, 0x60, 0x40, 0xF2, 0x71, 0x21, 0x41, + 0x60, 0x10, 0x21, 0x81, 0x60, 0x00, 0x21, 0x4F, 0xF4, 0x00, 0x62, 0xC0, 0xE9, 0x03, 0x12, 0x41, 0x61, 0x81, 0x61, 0xC1, 0x61, 0x01, 0x62, 0x41, 0x62, 0x81, 0x62, 0xC1, 0x62, 0x01, 0x63, 0x01, 0x21, 0x41, 0x63, 0x81, 0x63, 0x70, 0x47, 0x01, + 0x2A, 0x4F, 0xEA, 0x81, 0x32, 0x0F, 0xD0, 0x00, 0x2A, 0x03, 0xDA, 0x42, 0x68, 0x42, 0xF4, 0x80, 0x32, 0x42, 0x60, 0x8A, 0x01, 0x03, 0xD5, 0x42, 0x68, 0x42, 0xF0, 0x80, 0x72, 0x42, 0x60, 0x42, 0x68, 0x8A, 0x43, 0x42, 0x60, 0x70, 0x47, 0x00, + 0x2A, 0x03, 0xDA, 0x42, 0x68, 0x22, 0xF4, 0x80, 0x32, 0x42, 0x60, 0x8A, 0x01, 0x03, 0xD5, 0x42, 0x68, 0x22, 0xF0, 0x80, 0x72, 0x42, 0x60, 0x42, 0x68, 0x0A, + 0x43, 0xEE, 0xE7, 0x01, 0x2A, 0x82, 0x68, 0x02, 0xD0, 0x8A, 0x43, 0x82, 0x60, 0x70, 0x47, 0x0A, + 0x43, 0xFB, 0xE7, 0x02, 0x46, 0x00, 0x20, 0x52, 0x6A, 0x12, 0xEA, 0x11, 0x6F, 0x00, 0xD0, 0x01, 0x20, 0x70, 0x47, 0xC2, 0x68, 0x0A, + 0x43, 0xC2, 0x60, 0xC2, 0x68, 0x8A, 0x43, 0xC2, 0x60, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x10, 0x02, 0x40, 0x00, 0x00, 0x01, 0x01, 0x6B, 0x48, 0x10, 0xB5, 0x01, 0x78, 0x29, 0xB1, 0x00, 0x21, 0x01, 0x70, 0x41, 0x78, 0x26, + 0x20, 0x22, 0xF6, 0xEF, 0xFB, 0x00, 0x22, 0x10, 0x21, 0x01, 0x20, 0xFF, 0xF7, 0xA5, 0xFD, 0x4F, 0xF4, 0x88, 0x74, 0x20, 0x46, 0x22, 0xF6, 0xC4, 0xFB, 0x20, 0xF0, 0x01, 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x22, 0xF6, 0xCD, 0xBB, 0x2D, + 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x0C, 0x46, 0x26, 0x20, 0x22, 0xF6, 0xB6, 0xFB, 0x5A, 0x49, 0x02, 0x07, 0x4F, 0xF0, 0x01, 0x06, 0x48, 0x70, 0x05, 0xD5, 0x0E, 0x70, 0x20, 0xF0, 0x08, 0x01, 0x26, 0x20, 0x22, 0xF6, 0xCB, 0xFB, 0x20, 0x68, 0xB0, + 0xF5, 0x10, 0x6F, 0x44, 0xD1, 0x4F, 0xF4, 0x88, 0x78, 0x40, 0x46, 0x22, 0xF6, 0xA1, 0xFB, 0x40, 0xF0, 0x01, 0x01, 0x40, 0x46, 0x22, 0xF6, 0xAC, 0xFB, 0x4E, 0x49, 0x0A, + 0x20, 0x09, 0x68, 0x88, 0x47, 0x40, 0xF2, 0x13, 0x17, 0x38, 0x46, 0x22, 0xF6, 0x93, 0xFB, 0x40, 0xF0, 0x01, 0x01, 0x38, 0x46, 0x22, 0xF6, 0x9E, 0xFB, 0x40, 0x46, 0x22, 0xF6, 0x8B, 0xFB, 0x40, 0xF0, 0x04, 0x01, 0x40, 0x46, 0x22, 0xF6, 0x96, + 0xFB, 0x44, 0x49, 0x02, 0x20, 0x09, 0x68, 0x88, 0x47, 0x38, 0x46, 0x22, 0xF6, 0x7F, 0xFB, 0x20, 0xF0, 0x01, 0x01, 0x38, 0x46, 0x22, 0xF6, 0x8A, 0xFB, 0x60, 0x6A, 0x38, 0xB9, 0x38, 0x46, 0x22, 0xF6, 0x75, 0xFB, 0x40, 0xF0, 0x02, 0x01, 0x38, + 0x46, 0x22, 0xF6, 0x80, 0xFB, 0x40, 0xF2, 0x01, 0x60, 0x28, 0x60, 0x61, 0x6A, 0x20, 0x69, 0x38, 0x4A, 0x08, 0x43, 0x21, 0x6A, 0x11, 0x43, 0x08, 0x43, 0x68, 0x60, 0x4F, 0xF4, 0x88, 0x50, 0xA8, 0x60, 0x2E, 0x61, 0x00, 0x20, 0xA8, 0x61, 0xAE, + 0x61, 0xA1, 0x6A, 0x20, 0x68, 0x62, 0x68, 0x08, 0x43, 0x21, 0x6B, 0x11, 0x43, 0x08, 0x43, 0x40, 0xF0, 0x0A, + 0x00, 0xE8, 0x61, 0xD4, 0xE9, 0x02, 0x01, 0x08, 0x43, 0x40, 0xF0, 0xA0, 0x00, 0x68, 0x61, 0xE1, 0x69, 0xE0, 0x6A, 0x08, 0x43, 0xD4, 0xE9, 0x05, 0x21, 0x11, 0x43, 0x08, 0x43, 0x40, 0xF4, 0x40, 0x50, 0x68, 0x62, 0x60, 0x6B, 0xB0, 0xF5, 0x00, + 0x6F, 0x03, 0xD0, 0xE8, 0x69, 0x40, 0xF0, 0x01, 0x00, 0xE8, 0x61, 0xE1, 0x6B, 0x60, 0x6B, 0x08, 0x43, 0xA1, 0x6B, 0x41, 0xF4, 0x80, 0x61, 0x08, 0x43, 0x28, 0x62, 0xBD, 0xE8, 0xF0, 0x81, 0x4F, 0xF4, 0x80, 0x62, 0x00, 0x21, 0xC0, 0xE9, 0x00, + 0x21, 0xC2, 0x61, 0x81, 0x60, 0x4F, 0xF4, 0xC0, 0x52, 0xC0, 0xE9, 0x03, 0x12, 0x4F, 0xF4, 0x80, 0x32, 0xC0, 0xE9, 0x08, 0x21, 0x81, 0x62, 0x2F, 0x22, 0xC1, 0x62, 0xC0, 0xE9, 0x05, 0x21, 0x4F, 0xF4, 0x00, 0x62, 0xC0, 0xE9, 0x0C, 0x12, 0xFF, + 0x22, 0xC0, 0xE9, 0x0E, 0x21, 0x70, 0x47, 0x4A, 0x68, 0x02, 0x60, 0x8A, 0x68, 0x42, 0x60, 0xCA, 0x68, 0x82, 0x60, 0x0A, + 0x69, 0xC2, 0x60, 0x4A, 0x69, 0x09, 0x68, 0x0A, + 0x43, 0x02, 0x61, 0x70, 0x47, 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x81, 0x60, 0xC1, 0x60, 0x01, 0x61, 0x41, 0x61, 0x70, 0x47, 0x00, 0x00, 0x5C, 0xE9, 0x20, 0x00, 0x54, 0x01, 0x20, 0x00, 0x58, 0x01, 0x20, 0x00, 0x00, 0x86, 0x20, 0x0A, + 0x2D, 0xE9, 0xF0, 0x41, 0x05, 0x46, 0x4F, 0xF4, 0x88, 0x77, 0x0C, 0x46, 0x00, 0x26, 0x38, 0x46, 0x22, 0xF6, 0xEE, 0xFA, 0x40, 0xF0, 0x04, 0x01, 0x38, 0x46, 0x22, 0xF6, 0xF9, 0xFA, 0xE8, 0x68, 0x20, 0xF0, 0x1F, 0x00, 0xE8, 0x60, 0x61, 0x6C, + 0xA0, 0x6B, 0xA2, 0x8F, 0x08, 0x43, 0xA1, 0x6C, 0x41, 0xEA, 0x82, 0x11, 0x08, 0x43, 0x28, 0x65, 0xA0, 0x6B, 0x48, 0xB9, 0x28, 0x6D, 0xE1, 0x8F, 0xB4, 0xF8, 0x42, 0x20, 0x08, 0x43, 0xB4, 0xF8, 0x40, 0x10, 0x11, 0x43, 0x08, 0x43, 0x28, 0x65, + 0xA8, 0x68, 0x6F, 0xF3, 0x0F, 0x00, 0xA8, 0x60, 0x04, 0xEB, 0x86, 0x00, 0x05, 0xEB, 0x86, 0x01, 0xD0, 0xF8, 0x0A, + 0x00, 0x08, 0x61, 0x76, 0x1C, 0xF6, 0xB2, 0x08, 0x2E, 0xF4, 0xD3, 0x60, 0x8D, 0xA8, 0x60, 0xE0, 0x88, 0xA1, 0x88, 0xE2, 0x78, 0x08, 0x43, 0xA1, 0x78, 0x09, 0x05, 0x41, 0xEA, 0x82, 0x31, 0x08, 0x43, 0x94, 0xF8, 0x34, 0x10, 0x40, 0xEA, 0xC1, + 0x60, 0x68, 0x60, 0x94, 0xF8, 0x35, 0x00, 0x21, 0x6B, 0x94, 0xF8, 0x36, 0x20, 0x08, 0x43, 0x94, 0xF8, 0x2C, 0x10, 0x49, 0x07, 0x41, 0xEA, 0x02, 0x41, 0x08, 0x43, 0x21, 0x78, 0x40, 0xEA, 0x41, 0x20, 0x61, 0x78, 0x08, 0x43, 0x68, 0x65, 0xA8, + 0x6D, 0x40, 0xF4, 0x40, 0x60, 0xA8, 0x65, 0x68, 0x68, 0x40, 0xF0, 0x80, 0x60, 0x68, 0x60, 0xE8, 0x68, 0x40, 0xF4, 0xF8, 0x50, 0xE8, 0x60, 0xBD, 0xE8, 0xF0, 0x81, 0x00, 0x21, 0x01, 0x70, 0x80, 0x22, 0x42, 0x70, 0xC1, 0x80, 0x92, 0x01, 0x82, + 0x80, 0x80, 0xF8, 0x2C, 0x10, 0x80, 0xF8, 0x34, 0x10, 0x01, 0x63, 0x80, 0xF8, 0x35, 0x10, 0x80, 0xF8, 0x36, 0x10, 0x41, 0x81, 0x81, 0x81, 0xC1, 0x81, 0x01, 0x82, 0x41, 0x82, 0x81, 0x82, 0xC1, 0x82, 0x01, 0x83, 0x41, 0x83, 0x81, 0x83, 0xC1, + 0x83, 0x01, 0x84, 0x41, 0x84, 0x81, 0x84, 0xC1, 0x84, 0x01, 0x85, 0x41, 0x85, 0x06, 0x22, 0x82, 0x70, 0x01, 0x22, 0xC2, 0x70, 0x41, 0x64, 0x81, 0x63, 0x82, 0x87, 0xC1, 0x87, 0xA0, 0xF8, 0x40, 0x10, 0xA0, 0xF8, 0x42, 0x10, 0x81, 0x64, 0x70, + 0x47, 0x00, 0x22, 0x4F, 0xF0, 0xC2, 0x41, 0x4E, 0x48, 0xFF, 0xF7, 0x38, 0xBC, 0x00, 0x2A, 0xC2, 0x68, 0x01, 0xD0, 0x0A, + 0x43, 0x00, 0xE0, 0x8A, 0x43, 0xC2, 0x60, 0x70, 0x47, 0xCA, 0x07, 0x4F, 0xEA, 0x51, 0x01, 0x00, 0xEB, 0x81, 0x00, 0x00, 0x6B, 0x01, 0xD0, 0x00, 0x0C, 0x70, 0x47, 0x80, 0xB2, 0x70, 0x47, 0x70, 0xB5, 0x0E, 0x46, 0x04, 0x46, 0x01, 0x2A, 0x03, + 0xD0, 0x60, 0x68, 0x20, 0xF0, 0x03, 0x00, 0x23, 0xE0, 0x20, 0x6D, 0xC0, 0x02, 0x1A, 0xD5, 0x20, 0x6D, 0x40, 0xF4, 0x70, 0x50, 0x20, 0x65, 0x3C, 0x4D, 0x50, 0x20, 0x29, 0x68, 0x88, 0x47, 0x20, 0x6D, 0x40, 0xF4, 0x40, 0x40, 0x20, 0x65, 0x29, + 0x68, 0x4F, 0xF4, 0xA0, 0x70, 0x88, 0x47, 0x20, 0x6D, 0x40, 0xF4, 0x40, 0x30, 0x20, 0x65, 0x29, 0x68, 0xF0, 0x20, 0x88, 0x47, 0x20, 0x6D, 0x40, 0xF4, 0x80, 0x20, 0x20, 0x65, 0x60, 0x68, 0x20, 0xF0, 0x03, 0x00, 0x60, 0x60, 0x60, 0x68, 0x30, + 0x43, 0x60, 0x60, 0x70, 0xBD, 0xCB, 0x07, 0x4F, 0xEA, 0x51, 0x01, 0x00, 0xEB, 0x81, 0x01, 0x08, 0x69, 0x02, 0xD0, 0x40, 0xEA, 0x02, 0x40, 0x00, 0xE0, 0x10, 0x43, 0x08, 0x61, 0x70, 0x47, 0x02, 0xE0, 0x03, 0x68, 0x21, 0xF8, 0x02, 0x3B, 0x52, + 0x1E, 0x92, 0xB2, 0xF9, 0xD2, 0x70, 0x47, 0x23, 0x4B, 0x01, 0x22, 0x10, 0x30, 0x82, 0x40, 0x98, 0x6D, 0x09, 0xB1, 0x10, 0x43, 0x00, 0xE0, 0x90, 0x43, 0x98, 0x65, 0x70, 0x47, 0x08, 0xB5, 0x0B, 0x46, 0x00, 0x22, 0x8D, 0xF8, 0x00, 0x20, 0x01, + 0x46, 0x6A, 0x46, 0x18, 0x46, 0x01, 0xF0, 0x6A, 0xF8, 0xBD, 0xEE, 0xC0, 0x0A, + 0x10, 0xEE, 0x10, 0x0A, + 0x01, 0xB2, 0x9D, 0xF9, 0x00, 0x00, 0x00, 0x28, 0x00, 0xD1, 0x08, 0x46, 0x08, 0xBD, 0x10, 0xB5, 0x4F, 0xF4, 0x88, 0x74, 0x00, 0x28, 0x20, 0x46, 0x04, 0xD0, 0x22, 0xF6, 0xDD, 0xF9, 0x40, 0xF0, 0x04, 0x01, 0x03, 0xE0, 0x22, 0xF6, 0xD8, 0xF9, + 0x20, 0xF0, 0x04, 0x01, 0x20, 0x46, 0xBD, 0xE8, 0x10, 0x40, 0x22, 0xF6, 0xE1, 0xB9, 0x01, 0x29, 0x01, 0x6D, 0x03, 0xD0, 0x21, 0xF4, 0x00, 0x21, 0x01, 0x65, 0x70, 0x47, 0x41, 0xF4, 0x00, 0x21, 0xFA, 0xE7, 0x80, 0x6D, 0x00, 0xF0, 0x01, 0x00, + 0x70, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x54, 0x01, 0x20, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x22, 0x63, 0x49, 0x4F, 0xF4, 0x80, 0x30, 0xFF, 0xF7, 0x92, 0xBB, 0x61, 0x4A, 0x14, 0x23, 0x02, 0x44, 0xB2, 0xFB, 0xF3, 0xF2, 0xF0, 0xB5, + 0x1B, 0x07, 0xD3, 0xF8, 0x60, 0x43, 0x44, 0xF4, 0x00, 0x74, 0xC3, 0xF8, 0x60, 0x43, 0xD3, 0xF8, 0x60, 0x43, 0x64, 0x05, 0x05, 0xD5, 0xD3, 0xF8, 0x60, 0x43, 0x24, 0xF4, 0x80, 0x64, 0xC3, 0xF8, 0x60, 0x43, 0x07, 0x25, 0x02, 0x2A, 0x04, 0xD2, + 0xD3, 0xF8, 0x60, 0x63, 0x02, 0xEB, 0x42, 0x04, 0x07, 0xE0, 0x94, 0x1E, 0x06, 0x2C, 0x0F, 0xD2, 0xD3, 0xF8, 0x60, 0x63, 0x02, 0xEB, 0x42, 0x04, 0xE4, 0x1D, 0xA5, 0x40, 0xAE, 0x43, 0xC3, 0xF8, 0x60, 0x63, 0x8D, 0x88, 0xA5, 0x40, 0xD3, 0xF8, + 0x60, 0x43, 0x25, 0x43, 0xC3, 0xF8, 0x60, 0x53, 0x03, 0x2A, 0x03, 0xD0, 0x05, 0x2A, 0x01, 0xD0, 0x07, 0x2A, 0x10, 0xD1, 0x91, 0xF8, 0x24, 0x50, 0x01, 0x24, 0xA7, 0x1E, 0x01, 0x2D, 0xD3, 0xF8, 0x5C, 0x53, 0xA2, 0xF1, 0x01, 0x06, 0x07, 0xEB, + 0x56, 0x06, 0x04, 0xFA, 0x06, 0xF4, 0x18, 0xD0, 0xA5, 0x43, 0xC3, 0xF8, 0x5C, 0x53, 0x4C, 0x89, 0x00, 0x2C, 0x0C, 0x89, 0x13, 0xD0, 0x0C, 0x25, 0x45, 0xEA, 0x44, 0x04, 0x84, 0x60, 0x3A, 0x4C, 0x0D, 0x69, 0x44, 0xF8, 0x22, 0x50, 0x4C, 0x69, + 0x04, 0x60, 0x8C, 0x8D, 0x01, 0x2C, 0x0C, 0xD0, 0x02, 0x2A, 0x27, 0xD0, 0x03, 0x2A, 0x2C, 0xD0, 0x31, 0xE0, 0x25, 0x43, 0xE5, 0xE7, 0x04, 0x25, 0x45, 0xEA, 0x44, 0x04, 0x84, 0x60, 0xCC, 0x68, 0xEE, 0xE7, 0x4F, 0xF4, 0x80, 0x54, 0x02, 0x2A, + 0x02, 0xD0, 0x03, 0x2A, 0x0B, 0xD0, 0x22, 0xE0, 0x0D, 0x8E, 0x8A, 0x6A, 0xC9, 0x8D, 0x42, 0xEA, 0x45, 0x22, 0x44, 0xEA, 0x81, 0x21, 0x0A, + 0x43, 0xC3, 0xF8, 0x64, 0x23, 0x17, 0xE0, 0x0D, 0x8E, 0x8A, 0x6A, 0xC9, 0x8D, 0x42, 0xEA, 0x45, 0x22, 0x44, 0xEA, 0x81, 0x21, 0x0A, + 0x43, 0xC3, 0xF8, 0x68, 0x23, 0x0C, 0xE0, 0xD3, 0xF8, 0x64, 0x13, 0x21, 0xF4, 0x80, 0x51, 0xC3, 0xF8, 0x64, 0x13, 0x05, 0xE0, 0xD3, 0xF8, 0x68, 0x13, 0x21, 0xF4, 0x80, 0x51, 0xC3, 0xF8, 0x68, 0x13, 0xC0, 0x68, 0xF0, 0xBD, 0x01, 0x22, 0x02, + 0x81, 0x40, 0xF6, 0xFF, 0x71, 0xC1, 0x60, 0x00, 0x21, 0x81, 0x80, 0x80, 0xF8, 0x24, 0x10, 0x02, 0x86, 0xC1, 0x85, 0x41, 0x81, 0x81, 0x85, 0x70, 0x47, 0x00, 0x29, 0x81, 0x68, 0x02, 0xD0, 0x41, 0xF0, 0x01, 0x01, 0x01, 0xE0, 0x21, 0xF0, 0x01, + 0x01, 0x81, 0x60, 0x70, 0x47, 0x01, 0x60, 0x70, 0x47, 0x00, 0x29, 0x81, 0x68, 0x02, 0xD0, 0x21, 0xF0, 0x04, 0x01, 0x01, 0xE0, 0x41, 0xF0, 0x04, 0x01, 0x81, 0x60, 0x70, 0x47, 0x10, 0xB5, 0x05, 0x4B, 0x14, 0x24, 0x03, 0x44, 0xB3, 0xFB, 0xF4, + 0xF3, 0x02, 0x60, 0x03, 0x48, 0x40, 0xF8, 0x23, 0x10, 0x10, 0xBD, 0x00, 0x40, 0x00, 0x20, 0x00, 0xE0, 0xFF, 0xBF, 0xB0, 0x20, 0x00, 0x40, 0x10, 0xB5, 0x01, 0x24, 0x13, 0x46, 0x01, 0x28, 0x09, 0xD0, 0xA6, 0x4A, 0x02, 0x28, 0x0A, + 0xD0, 0x03, 0x28, 0x0B, 0xD0, 0x04, 0x28, 0x10, 0xD0, 0x00, 0x24, 0x20, 0x46, 0x10, 0xBD, 0xA2, 0x49, 0x10, 0x78, 0x08, 0x70, 0xF9, 0xE7, 0x18, 0x78, 0x10, 0x70, 0xF6, 0xE7, 0x9E, 0x48, 0x0A, + 0x46, 0x19, 0x46, 0x00, 0x1D, 0x3D, 0xF6, 0x1D, 0xF9, 0xEF, 0xE7, 0x51, 0x80, 0x93, 0x60, 0xEC, 0xE7, 0x2D, 0xE9, 0xF0, 0x47, 0x86, 0xB0, 0x00, 0x26, 0xDD, 0xE9, 0x0E, 0x45, 0x90, 0x46, 0x26, 0x80, 0x00, 0x93, 0x8A, 0x46, 0x13, 0x46, 0x02, + 0x22, 0x94, 0x49, 0x95, 0x48, 0xEA, 0xF5, 0xEB, 0xFE, 0x02, 0x20, 0x04, 0x27, 0xDF, 0xF8, 0x3C, 0x92, 0x8D, 0xF8, 0x04, 0x00, 0xB8, 0xF1, 0x0A, + 0x0F, 0x1A, 0xD0, 0x0D, 0xDC, 0xB8, 0xF1, 0x02, 0x0F, 0x29, 0xD0, 0x01, 0x27, 0xB8, 0xF1, 0x04, 0x0F, 0x31, 0xD0, 0xB8, 0xF1, 0x06, 0x0F, 0x3A, 0xD0, 0xB8, 0xF1, 0x08, 0x0F, 0x09, 0xD1, 0x41, 0xE0, 0xB8, 0xF1, 0x0E, 0x0F, 0x08, 0xD0, 0xB8, + 0xF1, 0x12, 0x0F, 0x05, 0xD0, 0xB8, 0xF1, 0x15, 0x0F, 0x02, 0xD0, 0x40, 0xF2, 0x0A, + 0x46, 0x39, 0xE0, 0x8D, 0xF8, 0x08, 0x70, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, 0x47, 0xD9, 0xF8, 0x08, 0x00, 0x28, 0x60, 0xB9, 0xF8, 0x02, 0x10, 0x21, 0x80, 0x01, 0xB1, 0x48, 0xBB, 0x4F, 0xF4, 0x90, 0x66, 0x26, + 0xE0, 0x03, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, 0x47, 0x71, 0x48, 0x00, 0x1D, 0x14, 0xE0, 0x8D, 0xF8, 0x08, 0x00, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, + 0x47, 0xC5, 0xF8, 0x00, 0x90, 0x27, 0x80, 0x0E, 0xE0, 0x8D, 0xF8, 0x08, 0x70, 0xD9, 0xF8, 0x04, 0x20, 0x12, 0xB1, 0x01, 0xA9, 0x50, 0x46, 0x90, 0x47, 0x66, 0x48, 0x28, 0x60, 0xF2, 0xE7, 0x67, 0x48, 0x28, 0x60, 0x4F, 0x20, 0x20, 0x80, 0x06, + 0xB0, 0x30, 0x46, 0xBD, 0xE8, 0xF0, 0x87, 0x2D, 0xE9, 0xF0, 0x41, 0x86, 0xB0, 0x88, 0x46, 0xDD, 0xE9, 0x0C, 0x14, 0x00, 0x25, 0x64, 0xB1, 0x60, 0x48, 0x03, 0x26, 0x5A, 0x4F, 0x0E, 0x2A, 0x49, 0xD0, 0x14, 0xDC, 0x04, 0x2A, 0x37, 0xD0, 0x06, + 0x2A, 0x26, 0xD0, 0x0A, + 0x2A, 0x12, 0xD1, 0x41, 0xE0, 0x00, 0x91, 0x56, 0x49, 0x57, 0x48, 0x23, 0x46, 0x02, 0x22, 0x34, 0x31, 0x80, 0x1E, 0xEA, 0xF5, 0x6B, 0xFE, 0x40, 0xF2, 0x04, 0x40, 0x06, 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x12, 0x2A, 0x04, 0xD0, 0x15, 0x2A, 0x2F, + 0xD0, 0x40, 0xF2, 0x0A, + 0x45, 0x34, 0xE0, 0x4C, 0x49, 0x23, 0x78, 0x01, 0x22, 0x64, 0x31, 0xEA, 0xF5, 0x59, 0xFE, 0x01, 0x20, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x00, 0x20, 0x78, 0x8D, 0xF8, 0x0C, 0x00, 0x25, 0xE0, 0x44, 0x49, 0x23, 0x78, 0x01, 0x22, 0x0B, + 0x70, 0x02, 0x21, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x10, 0x21, 0x78, 0x8D, 0xF8, 0x0C, 0x10, 0x3F, 0x49, 0x8C, 0x31, 0x0B, 0xE0, 0x23, 0x78, 0x3B, 0x70, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x60, 0x21, 0x78, 0x8D, 0xF8, 0x0C, + 0x10, 0x39, 0x49, 0x01, 0x22, 0xB8, 0x31, 0xEA, 0xF5, 0x33, 0xFE, 0x07, 0xE0, 0x05, 0x20, 0x8D, 0xF8, 0x04, 0x60, 0x8D, 0xF8, 0x08, 0x00, 0x8D, 0xF8, 0x0C, 0x10, 0x04, 0x94, 0x7A, 0x68, 0x1A, 0xB1, 0x15, 0xB9, 0x01, 0xA9, 0x40, 0x46, 0x90, + 0x47, 0x28, 0x46, 0xB8, 0xE7, 0x2D, 0xE9, 0xF0, 0x41, 0x86, 0xB0, 0x88, 0x46, 0x1C, 0x46, 0x01, 0x27, 0x00, 0x93, 0x2A, 0x49, 0x15, 0x46, 0x13, 0x46, 0x8D, 0xF8, 0x04, 0x70, 0x3E, 0x46, 0x02, 0x22, 0xE0, 0x31, 0x27, 0x48, 0xEA, 0xF5, 0x10, + 0xFE, 0x0B, 0x2D, 0x0E, 0xD0, 0x0F, 0x2D, 0x13, 0xD0, 0x16, 0x2D, 0x17, 0xD0, 0x00, 0x26, 0x1F, 0x48, 0x42, 0x68, 0x00, 0x2A, 0x9B, 0xD0, 0x00, 0x2E, 0x99, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0x95, 0xE7, 0xE0, 0x07, 0x02, 0xD0, 0x8D, + 0xF8, 0x08, 0x70, 0xF0, 0xE7, 0x02, 0x20, 0x0A, + 0xE0, 0xE0, 0x07, 0x01, 0xD0, 0x03, 0x20, 0x06, 0xE0, 0x04, 0x20, 0x04, 0xE0, 0xE0, 0x07, 0x01, 0xD0, 0x05, 0x20, 0x00, 0xE0, 0x06, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xE0, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x15, 0x48, 0xD0, 0xE9, 0x1D, 0x12, 0xCD, + 0xE9, 0x00, 0x12, 0x03, 0x6F, 0x0D, 0x48, 0x0F, 0x49, 0x42, 0x88, 0x50, 0x31, 0x02, 0xA8, 0x32, 0xF6, 0xE3, 0xFB, 0x50, 0xB9, 0x0D, 0x48, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x0D, 0x49, 0x80, 0x1E, 0xEA, 0xF5, 0xD2, 0xFD, 0xFF, 0x20, 0x8D, + 0xF8, 0x08, 0x00, 0x02, 0x48, 0x44, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x00, 0x00, 0xEC, 0xE9, 0x20, 0x00, 0x12, 0xE6, 0x20, 0x00, 0x84, 0x02, 0x80, 0x08, 0x02, 0x33, 0x10, 0x21, 0x4C, 0xDE, 0x20, 0x00, 0x02, 0x30, 0x10, 0x21, 0xCC, + 0xE0, 0x20, 0x00, 0x94, 0x03, 0x80, 0x08, 0x2D, 0xE9, 0xFF, 0x41, 0xB9, 0x4C, 0xDD, 0xE9, 0x0A, + 0x30, 0x0E, 0x46, 0x00, 0x25, 0x03, 0x27, 0x24, 0x68, 0x40, 0xF2, 0x0D, 0x41, 0x02, 0x2A, 0x12, 0xD0, 0x4F, 0xF0, 0x02, 0x0C, 0x10, 0x2A, 0x17, 0xD0, 0x0C, 0x2A, 0x2C, 0xD0, 0x00, 0x93, 0x13, 0x46, 0x02, 0x22, 0xB0, 0x49, 0xB1, 0x48, 0xEA, + 0xF5, 0x9F, 0xFD, 0x40, 0xF2, 0x0A, + 0x45, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x01, 0x2B, 0x2D, 0xD1, 0x60, 0xB3, 0x8D, 0xF8, 0x04, 0x70, 0x01, 0x21, 0x8D, 0xF8, 0x06, 0x10, 0x1D, 0xE0, 0x05, 0x2B, 0x24, 0xD1, 0x18, 0xB3, 0x8D, 0xF8, 0x04, 0x70, 0x8D, 0xF8, 0x06, + 0xC0, 0x01, 0x78, 0x8D, 0xF8, 0x08, 0x10, 0x41, 0x78, 0x82, 0x78, 0x01, 0xEB, 0x02, 0x21, 0xAD, 0xF8, 0x0A, + 0x10, 0xC1, 0x78, 0x00, 0x79, 0x01, 0xEB, 0x00, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x09, 0xE0, 0x01, 0x2B, 0x0D, 0xD1, 0x60, 0xB1, 0x8D, 0xF8, 0x04, 0x70, 0x8D, 0xF8, 0x06, 0xC0, 0x00, 0x78, 0x8D, 0xF8, 0x08, 0x00, 0x00, 0x2C, 0xCF, 0xD0, 0x01, + 0xA9, 0x30, 0x46, 0xA0, 0x47, 0xCB, 0xE7, 0x0D, 0x46, 0xC9, 0xE7, 0x2D, 0xE9, 0xFE, 0x4F, 0x92, 0x4F, 0xDD, 0xE9, 0x0C, 0x54, 0x4F, 0xF0, 0x00, 0x09, 0x0A, + 0x2A, 0x19, 0xD0, 0x09, 0xDC, 0x8C, 0x4E, 0x04, 0x2A, 0x16, 0xD0, 0x4F, 0xF0, 0x04, 0x08, 0x06, 0x2A, 0x2B, 0xD0, 0x08, 0x2A, 0x06, 0xD1, 0x40, 0xE0, 0x42, 0xF2, 0x90, 0x78, 0x0E, 0x2A, 0x57, 0xD0, 0x12, 0x2A, 0x7D, 0xD0, 0x85, 0x49, 0x13, + 0x46, 0x01, 0x22, 0x3C, 0x31, 0x38, 0x46, 0xEA, 0xF5, 0x46, 0xFD, 0x40, 0xF2, 0x0A, + 0x49, 0xDC, 0xE0, 0x7F, 0x49, 0x4F, 0xF4, 0x00, 0x70, 0x0C, 0x31, 0x2F, 0xF6, 0x29, 0xF8, 0x7C, 0x4A, 0x00, 0x20, 0x69, 0x46, 0x0C, 0x32, 0xC0, 0xF1, 0x05, 0x03, 0xD3, 0x5C, 0x0B, 0x54, 0x40, 0x1C, 0x06, 0x28, 0xF8, 0xDB, 0x00, 0x98, 0xF0, + 0x60, 0xBD, 0xF8, 0x04, 0x00, 0x30, 0x82, 0x06, 0x20, 0x22, 0x60, 0x6F, 0xE0, 0x42, 0xF2, 0x92, 0x70, 0xEF, 0xF5, 0xE9, 0xFB, 0x72, 0x49, 0x82, 0x46, 0x03, 0x46, 0x01, 0x22, 0x6C, 0x31, 0x38, 0x46, 0xEA, 0xF5, 0x1E, 0xFD, 0x6E, 0x49, 0xDA, + 0xF8, 0x60, 0x30, 0x01, 0x22, 0x80, 0x31, 0x38, 0x46, 0x73, 0x60, 0xEA, 0xF5, 0x15, 0xFD, 0x68, 0x48, 0x00, 0x1D, 0x16, 0xE0, 0x42, 0xF2, 0x93, 0x70, 0xEF, 0xF5, 0xD1, 0xFB, 0x66, 0x49, 0x82, 0x46, 0x03, 0x46, 0x01, 0x22, 0x98, 0x31, 0x38, + 0x46, 0xEA, 0xF5, 0x06, 0xFD, 0x62, 0x49, 0xDA, 0xF8, 0x60, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x38, 0x46, 0xB3, 0x60, 0xEA, 0xF5, 0xFD, 0xFC, 0x5C, 0x48, 0x08, 0x30, 0x20, 0x60, 0xA5, 0xF8, 0x00, 0x80, 0x90, 0xE0, 0x40, 0x46, 0xEF, 0xF5, 0xB7, + 0xFB, 0x58, 0x4E, 0x41, 0x78, 0x14, 0x36, 0x80, 0x46, 0xB1, 0x70, 0x05, 0x21, 0x31, 0x70, 0x01, 0x21, 0x71, 0x70, 0x40, 0x78, 0xB0, 0x70, 0x49, 0x05, 0xF0, 0x78, 0x91, 0xF8, 0x14, 0x13, 0x40, 0xF0, 0x01, 0x00, 0x49, 0x09, 0x61, 0xF3, 0x41, + 0x00, 0x20, 0xF0, 0x08, 0x00, 0x40, 0xF0, 0x04, 0x00, 0xF0, 0x70, 0xEF, 0xF5, 0xCB, 0xFB, 0xF1, 0x78, 0x43, 0x46, 0x60, 0xF3, 0x04, 0x11, 0xF1, 0x70, 0x4F, 0xF4, 0x00, 0x60, 0xB0, 0x80, 0x01, 0x22, 0x00, 0xE0, 0x18, 0xE0, 0x46, 0x49, 0x38, + 0x46, 0xC0, 0x31, 0xEA, 0xF5, 0xC9, 0xFC, 0xEF, 0xF5, 0xB9, 0xFB, 0x68, 0xB1, 0x44, 0x49, 0xB1, 0xEB, 0x08, 0x2F, 0x02, 0xD1, 0x4F, 0xF4, 0xAA, 0x60, 0x01, 0xE0, 0x4F, 0xF4, 0x2A, 0x60, 0xB0, 0x60, 0x0C, 0x20, 0x26, 0x60, 0x28, 0x80, 0x51, + 0xE0, 0x4F, 0xF4, 0x7F, 0x60, 0xF7, 0xE7, 0xEF, 0xF5, 0xA5, 0xFB, 0x37, 0x4E, 0x10, 0x27, 0x20, 0x36, 0xDF, 0xF8, 0xE8, 0xB0, 0x00, 0x28, 0x42, 0xF2, 0x91, 0x7A, 0x40, 0x46, 0x1F, 0xD0, 0xEF, 0xF5, 0x6A, 0xFB, 0xD0, 0xF8, 0x94, 0x01, 0x30, + 0x60, 0x50, 0x46, 0xEF, 0xF5, 0x64, 0xFB, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x92, 0x70, 0xEF, 0xF5, 0x5E, 0xFB, 0x00, 0x6E, 0xB0, 0x60, 0x42, 0xF2, 0x93, 0x70, 0xEF, 0xF5, 0x58, 0xFB, 0x00, 0x6E, 0xF0, 0x60, 0xD6, 0xE9, 0x01, 0x12, 0x00, + 0x91, 0xCD, 0xE9, 0x01, 0x20, 0x26, 0x49, 0x04, 0x22, 0xD8, 0x31, 0x33, 0x68, 0x1D, 0xE0, 0xEF, 0xF5, 0x4A, 0xFB, 0xD0, 0xF8, 0x94, 0x01, 0x30, 0x60, 0x50, 0x46, 0xEF, 0xF5, 0x44, 0xFB, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x92, 0x70, 0xEF, + 0xF5, 0x3E, 0xFB, 0x00, 0x6E, 0xB0, 0x60, 0x42, 0xF2, 0x93, 0x70, 0xEF, 0xF5, 0x38, 0xFB, 0x00, 0x6E, 0xF0, 0x60, 0xD6, 0xE9, 0x01, 0x12, 0x00, 0x91, 0xCD, 0xE9, 0x01, 0x20, 0x1A, 0x49, 0x33, 0x68, 0x04, 0x22, 0x58, 0x46, 0xEA, 0xF5, 0x68, + 0xFC, 0x26, 0x60, 0x2F, 0x80, 0x48, 0x46, 0xBD, 0xE8, 0xFE, 0x8F, 0x3E, 0xB5, 0x04, 0x46, 0x14, 0x48, 0xD0, 0xE9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF5, 0x00, 0x71, 0x43, 0x69, 0x4F, 0xF4, 0x05, 0x72, 0x02, 0xA8, 0x32, 0xF6, 0x5C, + 0xFA, 0x20, 0xB1, 0x07, 0x48, 0x04, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x0A, + 0x49, 0x06, 0x48, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x40, 0x31, 0x80, 0x1E, 0xEA, 0xF5, 0x45, 0xFC, 0xFF, 0x20, 0x3E, 0xBD, 0x0C, 0xEA, 0x20, 0x00, 0x50, 0x04, 0x80, 0x08, 0x02, 0x33, 0x10, 0x21, 0x00, 0x00, 0x20, 0x80, 0x02, 0x30, 0x10, + 0x21, 0x68, 0x05, 0x80, 0x08, 0xCC, 0xE6, 0x21, 0x00, 0x10, 0xB5, 0xED, 0xF7, 0x47, 0xFA, 0xEE, 0xF7, 0x77, 0xFE, 0xEF, 0xF7, 0x3B, 0xF8, 0x00, 0xF0, 0xBB, 0xF8, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xC6, 0xB8, 0x51, 0x48, 0x90, 0xF8, 0x26, + 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0xEE, 0xF7, 0xC6, 0xBE, 0x70, 0x47, 0x4C, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x01, 0xD1, 0xEE, 0xF7, 0xF4, 0xBE, 0x70, 0x47, 0xEE, 0xF7, 0xAD, 0xBE, 0x10, 0xB5, 0xFF, 0xF7, 0xE9, + 0xFF, 0xBD, 0xE8, 0x10, 0x40, 0xEE, 0xE7, 0x10, 0xB5, 0x00, 0xF0, 0xE1, 0xF9, 0xEF, 0xF7, 0x72, 0xFB, 0x41, 0x48, 0x90, 0xF8, 0x26, 0x00, 0x08, 0xB1, 0x03, 0x28, 0x05, 0xD1, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF0, 0x00, 0x40, 0xEE, 0xF7, 0x4E, + 0xBE, 0x10, 0xBD, 0x10, 0xB5, 0x3B, 0x48, 0xEB, 0xF5, 0xC8, 0xF9, 0x20, 0xB9, 0x00, 0x22, 0x3A, 0x49, 0x3A, 0x48, 0xEA, 0xF5, 0xF2, 0xFB, 0x3B, 0x49, 0x39, 0x48, 0x08, 0x60, 0x3B, 0x49, 0x3A, 0x48, 0x08, 0x60, 0xEB, 0xF7, 0x1D, 0xFC, 0xBD, + 0xE8, 0x10, 0x40, 0x02, 0x20, 0xEB, 0xF5, 0xE5, 0xBA, 0x10, 0xB5, 0x06, 0x20, 0x32, 0xF6, 0x34, 0xF9, 0x35, 0x48, 0xEC, 0xF7, 0x37, 0xF9, 0x2C, 0x4C, 0xA0, 0x72, 0x33, 0x48, 0xEC, 0xF7, 0x77, 0xF8, 0xE0, 0x72, 0x31, 0x48, 0xFF, 0xF7, 0xEB, + 0xFD, 0x20, 0x73, 0x2F, 0x48, 0xEC, 0xF7, 0xB7, 0xF9, 0x60, 0x73, 0x2D, 0x48, 0xFF, 0xF7, 0x6A, 0xFF, 0xA0, 0x73, 0x2B, 0x48, 0xEC, 0xF7, 0x30, 0xFF, 0xE0, 0x73, 0xBD, 0xE8, 0x10, 0x40, 0x28, 0x48, 0x32, 0xF6, 0x2F, 0xB9, 0xEE, 0xF7, 0x7C, + 0xBA, 0x10, 0xB5, 0xFF, 0xF7, 0xAA, 0xFF, 0xFF, 0xF7, 0xAE, 0xFF, 0x01, 0x20, 0x2F, 0xF6, 0x68, 0xFC, 0xED, 0xF7, 0x7A, 0xFE, 0xFF, 0xF7, 0xD0, 0xFF, 0xFF, 0xF7, 0xB7, 0xFF, 0xEE, 0xF7, 0x7C, 0xF9, 0xEE, 0xF7, 0x6A, 0xFA, 0xBD, 0xE8, 0x10, + 0x40, 0xEF, 0xF7, 0x7C, 0xBC, 0x1B, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x00, 0xF0, 0x55, 0xFC, 0xFF, 0xF7, 0x6F, 0xFF, 0x16, 0x20, 0x21, 0xF6, 0x74, 0xFD, 0x0D, 0x4C, 0x40, 0x09, 0x04, 0xF8, 0x26, 0x0F, 0x16, 0x20, 0x21, 0xF6, 0x6D, 0xFD, 0x20, + 0xF0, 0xE0, 0x01, 0x16, 0x20, 0x21, 0xF6, 0x89, 0xFD, 0x09, 0x49, 0x0A, + 0x48, 0x23, 0x78, 0x01, 0x22, 0xA4, 0x31, 0x80, 0x1C, 0xEA, 0xF5, 0x8D, 0xFB, 0x20, 0x78, 0x08, 0xB9, 0xFF, 0xF7, 0xC8, 0xFF, 0x09, 0xF6, 0x39, 0xFA, 0x00, 0x20, 0x10, 0xBD, 0x70, 0xF2, 0x20, 0x00, 0x55, 0x83, 0x20, 0x00, 0xB8, 0x10, 0x80, + 0x08, 0x00, 0x30, 0x10, 0x21, 0x31, 0x83, 0x20, 0x00, 0xB4, 0xE7, 0x20, 0x00, 0x43, 0x83, 0x20, 0x00, 0xB0, 0xE7, 0x20, 0x00, 0xA1, 0xAD, 0x20, 0x00, 0x98, 0xE7, 0x20, 0x00, 0x10, 0xB5, 0x00, 0x22, 0x80, 0x49, 0x81, 0x48, 0xEA, 0xF5, 0x6B, + 0xFB, 0x40, 0xF2, 0xC3, 0x31, 0x7F, 0x48, 0x3C, 0xF6, 0x67, 0xFE, 0x7E, 0x49, 0x01, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x7A, 0x49, 0x10, 0xB5, 0x00, 0x22, 0x28, 0x31, 0x79, 0x48, 0xEA, 0xF5, 0x5B, 0xFB, 0x24, 0x21, 0x79, 0x48, 0x3C, 0xF6, 0x58, + 0xFE, 0x77, 0x48, 0x00, 0x21, 0x41, 0x60, 0x4F, 0xF4, 0x10, 0x61, 0x01, 0x60, 0x4F, 0xF4, 0x80, 0x41, 0x81, 0x60, 0x4F, 0xF4, 0xC0, 0x51, 0xC1, 0x60, 0x4F, 0xF4, 0x00, 0x31, 0x01, 0x61, 0x2F, 0x21, 0x41, 0x61, 0x10, 0xBD, 0x7C, 0xB5, 0xFF, + 0xF7, 0xD1, 0xFF, 0x00, 0x24, 0x6B, 0x48, 0x01, 0x25, 0x23, 0x46, 0x04, 0x70, 0x45, 0x70, 0x00, 0x95, 0x22, 0x46, 0x21, 0x46, 0x24, 0x20, 0x01, 0x95, 0xF3, 0xF5, 0xF4, 0xFF, 0x00, 0x23, 0x1A, 0x46, 0x19, 0x46, 0x16, 0x20, 0xCD, 0xE9, 0x00, + 0x45, 0xF3, 0xF5, 0xEC, 0xFF, 0x00, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x17, 0x20, 0x01, 0x94, 0xF3, 0xF5, 0xE4, 0xFF, 0x00, 0xF0, 0x18, 0xF8, 0x00, 0xF0, 0x48, 0xF8, 0xBD, 0xE8, 0x7C, 0x40, 0x00, 0xF0, 0x72, 0xB8, 0x59, 0x48, 0x10, + 0xB5, 0x01, 0x21, 0x01, 0x70, 0x00, 0x21, 0x41, 0x70, 0x58, 0x48, 0xFF, 0xF7, 0x6D, 0xF8, 0x58, 0x48, 0xFF, 0xF7, 0x0C, 0xF9, 0x00, 0x21, 0xBD, 0xE8, 0x10, 0x40, 0x01, 0x20, 0xEB, 0xF7, 0x7A, 0xBC, 0x10, 0xB5, 0x90, 0xB0, 0x01, 0x22, 0x4F, + 0xF4, 0x90, 0x71, 0x02, 0x20, 0xFE, 0xF7, 0xB2, 0xFE, 0x68, 0x46, 0xFF, 0xF7, 0xA1, 0xF8, 0x4F, 0xF4, 0x80, 0x30, 0x00, 0x90, 0x4A, 0x48, 0x08, 0x21, 0x40, 0xF2, 0x71, 0x22, 0x40, 0x68, 0x04, 0x28, 0x01, 0xD0, 0x18, 0xB1, 0x05, 0xE0, 0xCD, + 0xE9, 0x01, 0x21, 0x02, 0xE0, 0x10, 0x20, 0xCD, 0xE9, 0x01, 0x20, 0x00, 0x20, 0x4F, 0xF4, 0x00, 0x62, 0xCD, 0xE9, 0x03, 0x02, 0x07, 0x90, 0x04, 0x20, 0xCD, 0xE9, 0x0D, 0x10, 0x3F, 0x4C, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x4B, 0xF8, 0x01, + 0x22, 0x3E, 0x49, 0x20, 0x46, 0xFF, 0xF7, 0x95, 0xF8, 0x10, 0xB0, 0x10, 0xBD, 0x00, 0xB5, 0x01, 0x22, 0x91, 0xB0, 0x10, 0x21, 0x10, 0x46, 0xFE, 0xF7, 0x81, 0xFE, 0x68, 0x46, 0xFF, 0xF7, 0x70, 0xF9, 0x33, 0x49, 0x48, 0x68, 0x01, 0x90, 0x08, + 0x68, 0x00, 0x90, 0xB0, 0xF5, 0x10, 0x6F, 0x03, 0xD0, 0xB0, 0xF5, 0x80, 0x6F, 0x09, 0xD0, 0x0E, 0xE0, 0xC8, 0x68, 0x04, 0x90, 0x88, 0x68, 0x09, 0x90, 0x08, 0x69, 0x08, 0x90, 0x48, 0x69, 0x05, 0x90, 0x05, 0xE0, 0x88, 0x69, 0x0A, + 0x90, 0xC8, 0x69, 0x0B, 0x90, 0x08, 0x6A, 0x06, 0x90, 0x00, 0x20, 0x02, 0x90, 0x03, 0x90, 0x69, 0x46, 0x26, 0x48, 0xFF, 0xF7, 0xC3, 0xF8, 0x11, 0xB0, 0x00, 0xBD, 0x70, 0xB5, 0x01, 0x22, 0x96, 0xB0, 0x24, 0x49, 0x50, 0x03, 0xFE, 0xF7, 0x53, + 0xFE, 0x68, 0x46, 0xEB, 0xF7, 0xEE, 0xFB, 0x02, 0x20, 0x78, 0x21, 0x01, 0x24, 0x01, 0x91, 0x8D, 0xF8, 0x00, 0x40, 0x8D, 0xF8, 0x08, 0x00, 0x00, 0x21, 0x03, 0xAA, 0x8D, 0xF8, 0x01, 0x00, 0x8D, 0xF8, 0x09, 0x10, 0x03, 0x26, 0x82, 0xE8, 0x53, + 0x00, 0x15, 0x48, 0x15, 0x25, 0x10, 0x30, 0x07, 0x90, 0x11, 0x48, 0x69, 0x46, 0xC0, 0x1C, 0x08, 0x90, 0x11, 0x20, 0x8D, 0xF8, 0x44, 0x00, 0x8D, 0xF8, 0x45, 0x50, 0x12, 0x48, 0xEB, 0xF7, 0xC9, 0xFA, 0x01, 0x22, 0x11, 0x46, 0x10, 0x46, 0xEB, + 0xF7, 0xFD, 0xFB, 0x8D, 0xF8, 0x48, 0x50, 0x13, 0x96, 0x8D, 0xF8, 0x50, 0x40, 0x12, 0xA8, 0xF3, 0xF5, 0xA4, 0xFE, 0x01, 0x21, 0x08, 0x46, 0xEB, 0xF7, 0xDE, 0xFB, 0x16, 0xB0, 0x70, 0xBD, 0x24, 0x38, 0x80, 0x08, 0x02, 0x30, 0x10, 0x21, 0x08, + 0xF3, 0x20, 0x00, 0xCC, 0xF6, 0x20, 0x00, 0x00, 0x00, 0x02, 0x40, 0x00, 0x20, 0x02, 0x40, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x20, 0x58, 0x70, 0x02, 0x40, 0x01, 0x20, 0x70, 0x47, 0x9F, 0xED, 0xCC, 0x0A, + 0xCC, 0x48, 0x80, 0xED, 0x00, 0x0A, + 0x9F, 0xED, 0xCC, 0x0A, + 0x80, 0xED, 0x01, 0x0A, + 0x01, 0x20, 0x70, 0x47, 0x10, 0xB5, 0xC9, 0x4C, 0x94, 0xB0, 0x20, 0x46, 0xFF, 0xF7, 0xB9, 0xF9, 0x01, 0x22, 0x4F, 0xF0, 0xC2, 0x41, 0xC6, 0x48, 0xFE, 0xF7, 0xF1, 0xFD, 0x68, 0x46, 0xFF, 0xF7, 0x81, 0xF9, 0x10, 0x21, 0x0F, 0x20, 0xAD, 0xF8, + 0x2A, 0x00, 0xAD, 0xF8, 0x0C, 0x10, 0x80, 0x20, 0xAD, 0xF8, 0x0A, + 0x10, 0xAD, 0xF8, 0x0E, 0x10, 0xAD, 0xF8, 0x10, 0x10, 0x8D, 0xF8, 0x01, 0x00, 0x69, 0x46, 0x20, 0x46, 0xFF, 0xF7, 0x07, 0xF9, 0x14, 0xB0, 0x10, 0xBD, 0x10, 0xB5, 0xFF, 0xF7, 0xD9, 0xFF, 0xFF, 0xF7, 0xCC, 0xFF, 0xB3, 0x48, 0x4F, 0xF4, 0xFA, + 0x61, 0x08, 0x30, 0xC1, 0x80, 0x00, 0x21, 0x41, 0x70, 0x10, 0xBD, 0xAF, 0x48, 0x08, 0x30, 0x40, 0x78, 0x70, 0x47, 0x70, 0xB5, 0x06, 0x46, 0x2D, 0xED, 0x04, 0x8B, 0x82, 0xB0, 0x00, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0xAD, 0x48, 0x41, 0x79, 0x9F, + 0xED, 0xAD, 0x8B, 0x06, 0xFB, 0x06, 0xF5, 0xA5, 0xEB, 0x45, 0x10, 0x00, 0xEB, 0x80, 0x00, 0x84, 0x00, 0xAB, 0x4D, 0x9F, 0xED, 0xAB, 0x9B, 0x01, 0x29, 0x0D, 0xD1, 0x6A, 0x46, 0x31, 0x46, 0x01, 0x20, 0x00, 0xF0, 0x49, 0xFA, 0x9D, 0xF9, 0x00, + 0x30, 0x00, 0x2B, 0x1D, 0xDA, 0x01, 0x22, 0xA6, 0x49, 0xA7, 0x48, 0xEA, 0xF5, 0xF3, 0xF9, 0x30, 0x46, 0xF0, 0xF7, 0xD0, 0xF9, 0x53, 0xEC, 0x18, 0x2B, 0x00, 0xF0, 0xEF, 0xFC, 0x41, 0xEC, 0x18, 0x0B, 0x94, 0xFB, 0xF5, 0xF0, 0xF0, 0xF7, 0xAF, + 0xF9, 0x53, 0xEC, 0x18, 0x2B, 0xF0, 0xF7, 0x03, 0xF9, 0x53, 0xEC, 0x19, 0x2B, 0xF0, 0xF7, 0xD1, 0xF9, 0x00, 0xF0, 0xAD, 0xFC, 0x00, 0xEE, 0x10, 0x0A, + 0x02, 0xB0, 0xBC, 0xEE, 0xC0, 0x0A, + 0xBD, 0xEC, 0x04, 0x8B, 0x10, 0xEE, 0x10, 0x0A, + 0x80, 0xB2, 0x70, 0xBD, 0x38, 0xB5, 0xFF, 0xF7, 0xB5, 0xFF, 0x88, 0x4C, 0x40, 0xF6, 0x1C, 0x42, 0x08, 0x34, 0x64, 0x21, 0xA0, 0x80, 0x03, 0x46, 0x90, 0x42, 0x01, 0xD3, 0xA1, 0x70, 0x2D, 0xE0, 0x40, 0xF6, 0xB8, 0x30, 0x83, 0x42, 0x08, 0xD3, + 0xA3, 0xF6, 0xB8, 0x30, 0x00, 0xEB, 0x80, 0x00, 0x80, 0x00, 0x90, 0xFB, 0xF1, 0xF0, 0x50, 0x30, 0x1F, 0xE0, 0x40, 0xF6, 0xC4, 0x10, 0x83, 0x42, 0x09, 0xD3, 0x32, 0x21, 0xA3, 0xF6, 0xC4, 0x10, 0x48, 0x43, 0x4F, 0xF4, 0xFA, 0x71, 0x90, 0xFB, + 0xF1, 0xF0, 0x1E, 0x30, 0x11, 0xE0, 0x40, 0xF6, 0x98, 0x00, 0x83, 0x42, 0x09, 0xD3, 0xA3, 0xF6, 0x98, 0x00, 0xC0, 0xEB, 0x00, 0x10, 0x4F, 0xF4, 0x96, 0x71, 0x90, 0xFB, 0xF1, 0xF0, 0x0F, 0x30, 0x03, 0xE0, 0xC3, 0xEB, 0x03, 0x11, 0xB1, 0xFB, + 0xF0, 0xF0, 0xA0, 0x70, 0xA0, 0x78, 0x00, 0x90, 0x74, 0x49, 0x75, 0x48, 0x02, 0x22, 0x60, 0x39, 0x40, 0x1E, 0xEA, 0xF5, 0x8C, 0xF9, 0xA0, 0x88, 0xE1, 0x88, 0x88, 0x42, 0x01, 0xD2, 0x01, 0x20, 0x00, 0xE0, 0x00, 0x20, 0x60, 0x70, 0x38, 0xBD, + 0x2D, 0xE9, 0xFC, 0x5F, 0x00, 0x27, 0xDF, 0xF8, 0x8C, 0x81, 0x89, 0x46, 0x82, 0x46, 0x00, 0x97, 0x4F, 0xF6, 0xFF, 0x76, 0x3D, 0x46, 0x01, 0x22, 0x10, 0x21, 0x40, 0x46, 0x01, 0x97, 0xFF, 0xF7, 0xE9, 0xF8, 0x01, 0x22, 0x02, 0x21, 0x40, 0x46, + 0xFF, 0xF7, 0xF7, 0xF8, 0x00, 0x20, 0x41, 0xF2, 0x88, 0x32, 0xD8, 0xF8, 0x0C, 0x10, 0x11, 0xF4, 0x80, 0x1F, 0x03, 0xD1, 0x01, 0x46, 0x40, 0x1C, 0x91, 0x42, 0xF6, 0xD3, 0xD8, 0xF8, 0x0C, 0x00, 0x40, 0xF4, 0x80, 0x50, 0xC8, 0xF8, 0x0C, 0x00, + 0xC3, 0x46, 0x00, 0x24, 0xE8, 0x46, 0x21, 0x46, 0x58, 0x46, 0xFF, 0xF7, 0xD3, 0xF8, 0x28, 0xF8, 0x14, 0x00, 0x07, 0x44, 0xB0, 0x42, 0x00, 0xD2, 0x06, 0x46, 0xA8, 0x42, 0x00, 0xD9, 0x05, 0x46, 0x64, 0x1C, 0xE4, 0xB2, 0x04, 0x2C, 0xEE, 0xD3, + 0xB8, 0x1B, 0x40, 0x1B, 0xC0, 0xF3, 0x4F, 0x00, 0xFF, 0xF7, 0x70, 0xFF, 0x41, 0x49, 0x08, 0x31, 0xB9, 0xF1, 0x00, 0x0F, 0x08, 0xD0, 0xBA, 0xF1, 0x00, 0x0F, 0x05, 0xD0, 0x8A, 0x88, 0xA9, 0xF8, 0x00, 0x20, 0x8A, 0x78, 0xAA, 0xF8, 0x00, 0x20, + 0x8B, 0x88, 0x44, 0x49, 0x44, 0x48, 0x01, 0x22, 0x2C, 0x39, 0x40, 0x1E, 0xEA, 0xF5, 0x2B, 0xF9, 0xBD, 0xE8, 0xFC, 0x9F, 0x05, 0x22, 0x01, 0x21, 0x26, 0x20, 0xEF, 0xF7, 0xAD, 0xB8, 0x2D, 0xE9, 0xFC, 0x47, 0x80, 0x46, 0x03, 0x46, 0x3B, 0x49, + 0x3B, 0x48, 0x01, 0x22, 0x2C, 0x31, 0x40, 0x1E, 0xEA, 0xF5, 0x19, 0xF9, 0x2D, 0x4D, 0x01, 0x26, 0x06, 0x27, 0x00, 0x20, 0x08, 0x35, 0x2F, 0x4C, 0x4F, 0xF4, 0xFA, 0x69, 0xB8, 0xF1, 0x16, 0x0F, 0x29, 0xD0, 0xB8, 0xF1, 0x17, 0x0F, 0x26, 0xD0, + 0xB8, 0xF1, 0x18, 0x0F, 0x21, 0xD1, 0x80, 0x46, 0xAD, 0xF8, 0x04, 0x00, 0xA0, 0x7C, 0x06, 0x28, 0x28, 0xD0, 0xE8, 0x78, 0x0A, + 0x21, 0x40, 0x1C, 0xC0, 0xB2, 0xB0, 0xFB, 0xF1, 0xF2, 0xE8, 0x70, 0x01, 0xFB, 0x12, 0x00, 0x00, 0x28, 0x10, 0xD1, 0x69, 0x46, 0x01, 0xA8, 0xFF, 0xF7, 0x70, 0xFF, 0xBD, 0xF8, 0x00, 0x00, 0x48, 0x45, 0x08, 0xD2, 0x6E, 0x70, 0xA0, 0x7C, 0x01, + 0x28, 0x09, 0xD0, 0x03, 0x28, 0x0B, 0xD0, 0x04, 0x28, 0x09, 0xD0, 0xA7, 0x74, 0xBD, 0xE8, 0xFC, 0x87, 0xAD, 0xF8, 0x04, 0x00, 0xE9, 0xE7, 0x05, 0x20, 0xED, 0xF7, 0x1A, 0xFE, 0xF6, 0xE7, 0x05, 0x20, 0xED, 0xF7, 0x3A, 0xFE, 0xF2, 0xE7, 0xFF, + 0xF7, 0xAE, 0xFF, 0x69, 0x46, 0x01, 0xA8, 0xFF, 0xF7, 0x50, 0xFF, 0x15, 0x48, 0xBD, 0xF8, 0x00, 0x10, 0x40, 0xF6, 0x98, 0x02, 0x40, 0x1C, 0x91, 0x42, 0x05, 0xD3, 0x10, 0x49, 0x00, 0x22, 0x84, 0xF8, 0x12, 0x80, 0x54, 0x31, 0x02, 0xE0, 0x0D, + 0x49, 0x00, 0x22, 0x74, 0x31, 0xEA, 0xF5, 0xC0, 0xF8, 0xD8, 0xE7, 0x48, 0xBF, 0x4D, 0x3F, 0x4C, 0x13, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x40, 0x01, 0x00, 0x00, 0x0C, 0x70, 0xF2, 0x20, 0x00, 0xCD, 0xE9, 0xB2, 0x98, 0xD8, + 0x7C, 0xEF, 0x3F, 0x00, 0xE1, 0xF5, 0x05, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x5F, 0x40, 0xEC, 0x3D, 0x80, 0x08, 0x01, 0x30, 0x10, 0x21, 0x10, 0xB5, 0x4A, 0x78, 0x02, 0x80, 0x0B, 0x78, 0x03, 0xEB, 0x02, 0x22, 0x02, 0x80, 0x0A, + 0x79, 0xD4, 0x09, 0x84, 0x72, 0x0A, + 0x79, 0x42, 0x60, 0xCB, 0x78, 0x03, 0xEB, 0x02, 0x22, 0x42, 0x60, 0x8B, 0x78, 0x03, 0xEB, 0x02, 0x23, 0x43, 0x60, 0x8A, 0x79, 0x02, 0x81, 0x49, 0x79, 0x01, 0xEB, 0x02, 0x21, 0x01, 0x81, 0x02, 0xD0, 0x43, 0xF0, 0x7F, 0x41, 0x41, 0x60, 0x10, + 0xBD, 0x01, 0xFB, 0x01, 0xF2, 0x00, 0xEE, 0x10, 0x2A, 0xB8, 0xEE, 0xC0, 0x0A, + 0x9F, 0xED, 0x91, 0x1A, 0xB0, 0xF9, 0x00, 0x20, 0xC0, 0xEE, 0x01, 0x0A, + 0x00, 0xEE, 0x10, 0x2A, 0x42, 0x68, 0xB8, 0xEE, 0xC0, 0x0A, + 0x4A, 0x43, 0x20, 0xEE, 0x80, 0x0A, + 0x00, 0xEE, 0x90, 0x2A, 0xB8, 0xEE, 0xE0, 0x1A, 0xDF, 0xED, 0x89, 0x1A, 0xB0, 0xF9, 0x08, 0x00, 0xC1, 0xEE, 0x21, 0x0A, + 0xF2, 0xEE, 0x04, 0x1A, 0x30, 0xEE, 0x80, 0x0A, + 0x00, 0xEE, 0x90, 0x0A, + 0xB8, 0xEE, 0xE0, 0x1A, 0xC1, 0xEE, 0x21, 0x0A, + 0x30, 0xEE, 0x80, 0x0A, + 0x70, 0x47, 0x70, 0xB5, 0x00, 0x24, 0x7F, 0x49, 0x80, 0x4D, 0x22, 0x46, 0x50, 0x18, 0xD0, 0xF8, 0x91, 0x08, 0xAB, 0x18, 0x52, 0x1C, 0xD2, 0xB2, 0x58, 0x70, 0x1F, 0x2A, 0xF6, 0xD3, 0x55, 0x20, 0x28, 0x70, 0xAA, 0x20, 0x85, 0xF8, 0x20, 0x00, + 0x68, 0x7F, 0x6F, 0xF0, 0x01, 0x02, 0x51, 0x10, 0xFF, 0x28, 0x0A, + 0xD1, 0xA8, 0x7F, 0xFF, 0x28, 0x02, 0xD0, 0x80, 0xB1, 0x03, 0xD0, 0x04, 0xE0, 0xE8, 0x7F, 0xFF, 0x28, 0x08, 0xD0, 0xE8, 0x7F, 0x70, 0xB1, 0xE8, 0x7F, 0xFF, 0x28, 0x35, 0xD0, 0x68, 0x78, 0xFF, 0x28, 0x1F, 0xD1, 0x15, 0xE0, 0x6F, 0xF0, 0x02, + 0x00, 0x1F, 0xE0, 0xE8, 0x7F, 0xFF, 0x28, 0xF5, 0xD1, 0x10, 0x46, 0x1A, 0xE0, 0xE8, 0x7D, 0xFF, 0x28, 0xF0, 0xD1, 0x28, 0x7E, 0xFF, 0x28, 0xED, 0xD1, 0x68, 0x7E, 0xFF, 0x28, 0xEA, 0xD1, 0xA8, 0x7E, 0xFF, 0x28, 0xE7, 0xD1, 0x08, 0x46, 0x0C, + 0xE0, 0x28, 0x7A, 0xFF, 0x28, 0x05, 0xD1, 0xE8, 0x7B, 0xFF, 0x28, 0x02, 0xD1, 0xA8, 0x7D, 0xFF, 0x28, 0x12, 0xD0, 0x95, 0xF9, 0x1F, 0x00, 0x5A, 0x28, 0x0E, 0xD0, 0x5B, 0x4B, 0x01, 0x24, 0x90, 0x42, 0x18, 0x70, 0x0B, 0xD0, 0x58, 0x4E, 0x08, + 0x36, 0x88, 0x42, 0x2B, 0xD0, 0x80, 0xB3, 0x01, 0x28, 0x2F, 0xD0, 0x5A, 0x20, 0x18, 0x70, 0x00, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x52, 0x49, 0x51, 0x4A, 0x2E, 0x31, 0x50, 0x7A, 0x08, 0x80, 0x93, 0x7A, 0x03, 0xEB, 0x00, 0x20, 0x08, 0x80, 0xD0, + 0x7A, 0xC0, 0x09, 0x88, 0x72, 0xD0, 0x7A, 0x48, 0x60, 0x13, 0x7B, 0x03, 0xEB, 0x00, 0x20, 0x48, 0x60, 0x53, 0x7B, 0x03, 0xEB, 0x00, 0x20, 0x48, 0x60, 0x90, 0x7B, 0x08, 0x81, 0xD2, 0x7B, 0x02, 0xEB, 0x00, 0x20, 0x08, 0x81, 0x88, 0x7A, 0x01, + 0x28, 0xDE, 0xD1, 0x48, 0x68, 0x40, 0xF0, 0x7F, 0x40, 0x48, 0x60, 0xD9, 0xE7, 0x40, 0x48, 0x31, 0x46, 0x2E, 0x30, 0xFF, 0xF7, 0x2E, 0xFF, 0xD3, 0xE7, 0xFF, 0xE7, 0x3C, 0x48, 0x69, 0x1C, 0x22, 0x30, 0xFF, 0xF7, 0x27, 0xFF, 0x3A, 0x48, 0x31, + 0x46, 0x2E, 0x30, 0xFF, 0xF7, 0x22, 0xFF, 0x37, 0x49, 0x0F, 0x31, 0x01, 0xF1, 0x2B, 0x00, 0xFF, 0xF7, 0x1C, 0xFF, 0x34, 0x49, 0x16, 0x31, 0x01, 0xF1, 0x30, 0x00, 0xFF, 0xF7, 0x16, 0xFF, 0x31, 0x49, 0xA8, 0x7F, 0x6A, 0x7F, 0x89, 0x1E, 0x02, + 0xEB, 0x00, 0x20, 0x08, 0x80, 0xB4, 0xE7, 0x70, 0xB5, 0x00, 0x23, 0x2D, 0xED, 0x02, 0x8B, 0x4F, 0xF0, 0xFF, 0x34, 0x9F, 0xED, 0x2C, 0x8A, 0x13, 0x70, 0x43, 0x1E, 0xB0, 0xEE, 0x48, 0x0A, + 0x04, 0x2B, 0x21, 0xD2, 0x00, 0x29, 0x1F, 0xDB, 0xB1, 0xF5, 0x80, 0x5F, 0x1C, 0xDA, 0x24, 0x4B, 0x1D, 0x78, 0x55, 0x2D, 0x05, 0xD0, 0x93, 0xF8, 0x20, 0x30, 0xAA, 0x2B, 0x01, 0xD0, 0xFE, 0x20, 0x04, 0xE0, 0x20, 0x4B, 0x1B, 0x78, 0x01, 0x2B, + 0x04, 0xD0, 0xFC, 0x20, 0x10, 0x70, 0xBD, 0xEC, 0x02, 0x8B, 0x70, 0xBD, 0x01, 0x28, 0x09, 0xD0, 0x02, 0x28, 0x0A, + 0xD0, 0xA1, 0xF5, 0x00, 0x61, 0x03, 0x28, 0x12, 0xD0, 0x04, 0x28, 0x13, 0xD0, 0x14, 0x70, 0xF0, 0xE7, 0x14, 0x48, 0x22, 0x30, 0x01, 0xE0, 0x13, 0x48, 0x2E, 0x30, 0xFF, 0xF7, 0xF4, 0xFE, 0xB5, 0xEE, 0xC0, 0x0A, + 0xF1, 0xEE, 0x10, 0xFA, 0xE4, 0xD2, 0xB0, 0xEE, 0x48, 0x0A, + 0xE1, 0xE7, 0x0D, 0x48, 0x3A, 0x30, 0x01, 0xE0, 0x0B, 0x48, 0x46, 0x30, 0xBD, 0xEC, 0x02, 0x8B, 0xBD, 0xE8, 0x70, 0x40, 0xE1, 0xE6, 0x09, 0x48, 0x00, 0x78, 0x01, 0x28, 0x01, 0xD0, 0x00, 0x20, 0x70, 0x47, 0x05, 0x48, 0x80, 0x1E, 0x00, 0x88, + 0x70, 0x47, 0x00, 0x00, 0x20, 0xBC, 0xBE, 0x4C, 0x00, 0x50, 0xC3, 0x47, 0x00, 0x20, 0x20, 0x00, 0x22, 0x18, 0x21, 0x00, 0x89, 0xE7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x49, 0x10, 0xB5, 0xA1, 0xF1, 0x7C, 0x02, 0x0A, + 0x4C, 0xC2, 0xE9, 0x37, 0x12, 0x37, 0x21, 0x06, 0xE0, 0x00, 0xEB, 0x10, 0x43, 0x42, 0xF8, 0x21, 0x30, 0x07, 0x4B, 0x00, 0xFB, 0x03, 0x40, 0x0B, 0x1E, 0xA1, 0xF1, 0x01, 0x01, 0xF4, 0xDC, 0x10, 0xBD, 0x01, 0x20, 0xE8, 0xE7, 0x00, 0x00, 0xF0, + 0x18, 0x21, 0x00, 0xE1, 0x19, 0xD6, 0x66, 0xCD, 0x0D, 0x01, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x0E, 0x48, 0x00, 0x68, 0x28, 0xB1, 0x4F, 0xF0, 0xFF, 0x31, 0x08, 0xF6, 0x65, 0xFE, 0x00, 0x28, 0x10, 0xD0, 0x0B, 0x48, 0x04, 0x70, 0x4F, 0xF4, 0x00, + 0x10, 0x90, 0xF8, 0x50, 0x03, 0x41, 0x07, 0x09, 0xD0, 0xEF, 0xF3, 0x11, 0x81, 0x07, 0x4A, 0x40, 0x07, 0x00, 0x0E, 0x80, 0xF3, 0x11, 0x88, 0x11, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x72, 0xB6, 0xFB, 0xE7, 0x00, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, + 0x04, 0x20, 0x00, 0xAC, 0x0C, 0x20, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x00, 0x24, 0x07, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x00, 0x28, 0x09, 0xD0, 0x28, 0x46, 0xEC, 0xF5, 0x9A, 0xFC, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x00, 0xF0, 0x03, + 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x00, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x50, 0x03, 0x40, 0x07, 0x0C, 0xD0, 0x07, 0x48, 0x00, 0x78, 0x80, 0xF3, 0x11, 0x88, 0x06, 0x48, 0x00, 0x68, 0x08, 0xB1, 0x08, 0xF6, 0x37, 0xFE, 0x04, + 0x49, 0xFF, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x62, 0xB6, 0xF4, 0xE7, 0xAC, 0x0C, 0x20, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, 0x04, 0x20, 0x00, 0x2D, 0xE9, 0xF0, 0x47, 0x1A, 0x4F, 0x91, 0x46, 0x08, 0x9E, 0x3A, 0x78, 0x98, 0x46, 0x01, 0x2A, 0x03, + 0xD0, 0x4F, 0xF0, 0xFF, 0x30, 0xBD, 0xE8, 0xF0, 0x87, 0x38, 0xB1, 0xF0, 0x29, 0x05, 0xDB, 0xB9, 0xF1, 0x00, 0x0F, 0x02, 0xD0, 0xB8, 0xF1, 0x39, 0x0F, 0x02, 0xDA, 0x6F, 0xF0, 0x01, 0x00, 0xF1, 0xE7, 0x0F, 0x49, 0x0C, 0x31, 0xEF, 0xF7, 0xFF, + 0xFB, 0x07, 0xEB, 0x40, 0x05, 0x00, 0x24, 0xEC, 0x35, 0xB8, 0x60, 0x07, 0xEB, 0x44, 0x11, 0x28, 0x46, 0x01, 0xF5, 0x2F, 0x71, 0xEF, 0xF7, 0xC1, 0xFC, 0x64, 0x1C, 0xE4, 0xB2, 0x10, 0x3D, 0x0F, 0x2C, 0xF3, 0xD3, 0xEF, 0xF7, 0xBA, 0xFB, 0x41, + 0x46, 0x48, 0x46, 0x00, 0xF0, 0x16, 0xF8, 0x06, 0xB1, 0x30, 0x60, 0xF0, 0x20, 0xD2, 0xE7, 0x64, 0x13, 0x21, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x24, 0x71, 0x05, 0x48, 0x3C, 0xF6, 0x9E, 0xF9, 0x03, 0x48, 0x4F, 0xF4, 0x80, 0x71, 0x0C, 0x38, 0x81, + 0x60, 0x01, 0x21, 0x01, 0x70, 0x10, 0xBD, 0x70, 0x13, 0x21, 0x00, 0x2D, 0xE9, 0xF0, 0x4F, 0x07, 0x46, 0x9B, 0xB0, 0xAD, 0x20, 0x38, 0x70, 0x00, 0x20, 0x78, 0x70, 0xB8, 0x70, 0x00, 0x90, 0x01, 0x90, 0x06, 0x46, 0x04, 0x46, 0x02, 0x90, 0x78, + 0x78, 0x8D, 0xF8, 0x00, 0x00, 0xB8, 0x78, 0x8D, 0xF8, 0x01, 0x00, 0x10, 0x20, 0x3D, 0x1D, 0xDF, 0xF8, 0x78, 0x81, 0x00, 0x21, 0xEA, 0x46, 0x08, 0xEB, 0x81, 0x0C, 0x24, 0x1D, 0xDC, 0xF8, 0x9C, 0x22, 0x10, 0x2C, 0x66, 0xF3, 0x1F, 0x12, 0x16, + 0x46, 0x0A, + 0xD3, 0xA4, 0xF1, 0x08, 0x02, 0x26, 0xFA, 0x02, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x10, 0x3C, 0x26, 0xFA, 0x04, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x0A, + 0xEB, 0xD0, 0x02, 0x00, 0x1D, 0x13, 0x78, 0x49, 0x1C, 0x1B, 0x01, 0x13, 0x70, 0x9C, 0xF8, 0x9C, 0xC2, 0xC9, 0xB2, 0x0C, 0xF0, 0x0F, 0x0C, 0x43, 0xEA, 0x0C, 0x03, 0xC1, 0x46, 0x13, 0x70, 0xC0, 0xB2, 0x08, 0x29, 0xD7, 0xD3, 0x41, 0x07, 0x08, + 0xD0, 0x0A, + 0xEB, 0xD0, 0x01, 0x00, 0xF0, 0x07, 0x03, 0x0A, + 0x78, 0xC3, 0xF1, 0x08, 0x03, 0x9A, 0x40, 0x0A, + 0x70, 0x52, 0x46, 0x0F, 0x21, 0xC3, 0x08, 0x00, 0xF0, 0x07, 0x0C, 0x00, 0x20, 0xDF, 0xF8, 0x04, 0xA1, 0x06, 0xE0, 0x12, 0xF8, 0x00, 0x80, 0x40, 0x1C, 0x88, 0xEA, 0x01, 0x08, 0x1A, 0xF8, 0x08, 0x10, 0x98, 0x42, 0xF6, 0xD3, 0x10, 0x5C, 0x00, + 0x22, 0x0B, 0xE0, 0x80, 0xEA, 0x01, 0x03, 0xDB, 0x09, 0x00, 0xD0, 0x1D, 0x23, 0x40, 0x06, 0x01, 0xF0, 0x7F, 0x01, 0x00, 0x0E, 0x83, 0xEA, 0x41, 0x01, 0x52, 0x1C, 0x62, 0x45, 0xF1, 0xD3, 0xF9, 0x70, 0x08, 0x21, 0x03, 0xA8, 0x00, 0xF0, 0x63, + 0xF8, 0x00, 0x20, 0x4F, 0xF0, 0x01, 0x0E, 0x0D, 0xF1, 0x0C, 0x0C, 0x0D, 0xF1, 0x2C, 0x0A, + 0x0D, 0xF1, 0x4C, 0x0B, 0x1C, 0xF8, 0x20, 0x10, 0x0E, 0xFA, 0x01, 0xF2, 0x09, 0xEB, 0x80, 0x01, 0x52, 0x1E, 0xD1, 0xF8, 0x9C, 0x12, 0xC1, 0xF1, 0x0F, 0x08, 0x02, 0xFA, 0x08, 0xF2, 0x10, 0x31, 0x4A, 0xF8, 0x20, 0x20, 0x0E, 0xFA, 0x01, 0xF3, + 0x4B, 0xF8, 0x20, 0x30, 0x40, 0x1C, 0xC0, 0xB2, 0x08, 0x28, 0xE7, 0xD3, 0x00, 0x21, 0xE6, 0x46, 0x00, 0x20, 0x5E, 0xF8, 0x20, 0x20, 0xE2, 0xB1, 0x09, 0xEB, 0x41, 0x13, 0x03, 0xEB, 0x80, 0x03, 0x5A, 0xF8, 0x20, 0xC0, 0xD3, 0xF8, 0xBC, 0x82, + 0x5B, 0xF8, 0x20, 0x30, 0x96, 0x40, 0x43, 0x44, 0xAC, 0xFB, 0x03, 0xC3, 0x1E, 0x43, 0x14, 0x44, 0x10, 0x2C, 0x0A, + 0xD3, 0xA4, 0xF1, 0x08, 0x02, 0x26, 0xFA, 0x02, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x10, 0x3C, 0x26, 0xFA, 0x04, 0xF2, 0x05, 0xF8, 0x01, 0x2B, 0x40, 0x1C, 0xC0, 0xB2, 0x08, 0x28, 0xDB, 0xD3, 0x49, 0x1C, 0xC9, 0xB2, 0x0F, 0x29, 0xD6, 0xD3, 0x04, + 0xE0, 0x08, 0x3C, 0x26, 0xFA, 0x04, 0xF0, 0x05, 0xF8, 0x01, 0x0B, 0x08, 0x2C, 0xF8, 0xD2, 0x24, 0xB1, 0xC4, 0xF1, 0x08, 0x00, 0x86, 0x40, 0x05, 0xF8, 0x01, 0x6B, 0x1B, 0xB0, 0xE8, 0x1B, 0xBD, 0xE8, 0xF0, 0x8F, 0x00, 0x00, 0x64, 0x13, 0x21, + 0x00, 0xA4, 0xE4, 0x20, 0x00, 0xF0, 0xB5, 0x00, 0x23, 0x88, 0xB0, 0x42, 0x4C, 0x42, 0x4E, 0x19, 0x46, 0x5D, 0x1F, 0xEC, 0x46, 0x04, 0xEB, 0x81, 0x02, 0xD2, 0xF8, 0x9C, 0x22, 0x02, 0xB3, 0x56, 0xF8, 0x21, 0x70, 0xD2, 0x1B, 0x00, 0x2A, 0x00, + 0xDD, 0x52, 0x10, 0x4C, 0xF8, 0x21, 0x20, 0x9A, 0x42, 0x00, 0xDD, 0x13, 0x46, 0x49, 0x1C, 0xC9, 0xB2, 0x08, 0x29, 0xEB, 0xD3, 0x00, 0x21, 0x0A, + 0x46, 0x5B, 0x1C, 0x11, 0x44, 0x00, 0x22, 0x03, 0xF1, 0x0F, 0x07, 0x1E, 0x46, 0x14, 0x46, 0x5B, 0x1E, 0x5C, 0xF8, 0x24, 0x50, 0xB5, 0x42, 0x08, 0xDD, 0xBD, 0x42, 0x06, 0xDA, 0x52, 0x1C, 0x07, 0xE0, 0x4C, 0xF8, 0x21, 0x50, 0x5C, 0xF8, 0x21, + 0x20, 0xE1, 0xE7, 0xB5, 0x42, 0x00, 0xD1, 0x92, 0x1C, 0x64, 0x1C, 0xE4, 0xB2, 0x08, 0x2C, 0xEB, 0xD3, 0x8C, 0x18, 0x1A, 0x2C, 0xE1, 0xDB, 0x0A, + 0x44, 0x1A, 0x2A, 0x01, 0xD1, 0x11, 0x46, 0x5B, 0x1E, 0x00, 0x22, 0x9E, 0x1C, 0x17, 0x46, 0x10, 0x25, 0x5C, 0xF8, 0x22, 0x40, 0xB4, 0x42, 0x02, 0xDA, 0x40, 0xF8, 0x22, 0x70, 0x06, 0xE0, 0xE4, 0x1A, 0x40, 0xF8, 0x22, 0x40, 0x10, 0x2C, 0x01, + 0xDD, 0x40, 0xF8, 0x22, 0x50, 0x52, 0x1C, 0xD2, 0xB2, 0x08, 0x2A, 0xED, 0xD3, 0x00, 0x22, 0x02, 0x25, 0x5B, 0x1C, 0x15, 0xE0, 0x50, 0xF8, 0x22, 0x40, 0xA6, 0x1E, 0x0E, 0x2E, 0x04, 0xD2, 0x64, 0x1C, 0x40, 0xF8, 0x22, 0x40, 0x49, 0x1C, 0x09, + 0xE0, 0x5C, 0xF8, 0x22, 0x40, 0x9C, 0x42, 0x05, 0xD1, 0x4C, 0x1C, 0x1A, 0x2C, 0x02, 0xDA, 0x40, 0xF8, 0x22, 0x50, 0x89, 0x1C, 0x52, 0x1C, 0xD2, 0xB2, 0x1A, 0x29, 0x01, 0xDA, 0x08, 0x2A, 0xE5, 0xD3, 0x00, 0x22, 0x09, 0xE0, 0x50, 0xF8, 0x22, + 0x30, 0x10, 0x2B, 0x03, 0xDA, 0x5B, 0x1C, 0x40, 0xF8, 0x22, 0x30, 0x49, 0x1C, 0x52, 0x1C, 0xD2, 0xB2, 0x1A, 0x29, 0x01, 0xDA, 0x08, 0x2A, 0xF1, 0xD3, 0x08, 0xB0, 0xF0, 0xBD, 0x64, 0x13, 0x21, 0x00, 0xA4, 0xE5, 0x20, 0x00, 0x21, 0xF0, 0x00, + 0x42, 0xA2, 0xF1, 0x60, 0x52, 0xB2, 0xF5, 0x80, 0x1F, 0x01, 0xF0, 0x00, 0x43, 0x28, 0xBF, 0xD2, 0xF1, 0x7F, 0x6C, 0x0B, 0xD9, 0x5F, 0xEA, 0x00, 0x1C, 0x43, 0xEA, 0xC2, 0x02, 0x42, 0xEB, 0x50, 0x70, 0x18, 0xBF, 0x70, 0x47, 0x28, 0xBF, 0x20, + 0xF0, 0x01, 0x00, 0x70, 0x47, 0xB2, 0xF5, 0x80, 0x1F, 0xBC, 0xBF, 0x18, 0x46, 0x70, 0x47, 0x4F, 0xEA, 0x41, 0x0C, 0x1C, 0xF5, 0x00, 0x1F, 0x02, 0xD2, 0x08, 0x46, 0xEF, 0xF7, 0xEC, 0xBD, 0x70, 0xB5, 0x00, 0xF0, 0xB4, 0xF8, 0x00, 0x00, 0x00, + 0x89, 0xFF, 0xF7, 0xF6, 0xBF, 0x4F, 0xF0, 0x00, 0x40, 0xA0, 0xF5, 0x80, 0x00, 0x70, 0x47, 0x00, 0x00, 0xDF, 0xF8, 0x48, 0xC1, 0x70, 0xB5, 0x1C, 0xEA, 0x11, 0x1E, 0x1E, 0xBF, 0x1C, 0xEA, 0x13, 0x15, 0x9E, 0xEA, 0x0C, 0x0F, 0x95, 0xEA, 0x0C, + 0x0F, 0x00, 0xF0, 0x6F, 0x80, 0x81, 0xEA, 0x03, 0x04, 0x23, 0xEA, 0x4C, 0x13, 0x4E, 0xEA, 0xD4, 0x7E, 0x21, 0xEA, 0x4C, 0x11, 0x41, 0xF4, 0x80, 0x11, 0x43, 0xF4, 0x80, 0x13, 0xAE, 0x44, 0xA1, 0xFB, 0x02, 0x4C, 0xA0, 0xFB, 0x03, 0x65, 0xAE, + 0xF1, 0x7F, 0x7E, 0x36, 0x19, 0x55, 0xEB, 0x0C, 0x05, 0xA1, 0xFB, 0x03, 0x4C, 0x4C, 0xF1, 0x00, 0x03, 0xA0, 0xFB, 0x02, 0x1C, 0x16, 0xEB, 0x0C, 0x06, 0x65, 0x41, 0x53, 0xF1, 0x00, 0x03, 0x09, 0x42, 0x18, 0xBF, 0x46, 0xF0, 0x01, 0x06, 0x13, + 0xF4, 0x00, 0x7F, 0x0B, 0xD1, 0x4F, 0xEA, 0x03, 0x31, 0x4F, 0xEA, 0x05, 0x30, 0x34, 0x03, 0x41, 0xEA, 0x15, 0x51, 0x40, 0xEA, 0x16, 0x50, 0x6F, 0xF0, 0x03, 0x02, 0x0A, + 0xE0, 0x4F, 0xEA, 0xC3, 0x21, 0x4F, 0xEA, 0xC5, 0x20, 0xF4, 0x02, 0x41, 0xEA, 0x55, 0x51, 0x40, 0xEA, 0x56, 0x50, 0x6F, 0xF0, 0x02, 0x02, 0x02, 0xEB, 0x2E, 0x42, 0x01, 0xEB, 0x02, 0x55, 0x85, 0xEA, 0xCE, 0x71, 0x0A, + 0xD0, 0x5F, 0xEA, 0x44, 0x0C, 0x18, 0xBF, 0x24, 0xF0, 0x00, 0x44, 0x50, 0xF1, 0x00, 0x00, 0x41, 0xF1, 0x00, 0x01, 0x20, 0xEA, 0xD4, 0x70, 0x40, 0xF2, 0xFE, 0x7C, 0x62, 0x45, 0x00, 0xD2, 0x70, 0xBD, 0xA8, 0x42, 0x14, 0xBF, 0x4F, 0xF0, 0x80, + 0x44, 0x4F, 0xF0, 0x40, 0x44, 0x00, 0x2E, 0x08, 0xBF, 0x00, 0x24, 0xBE, 0xF1, 0x80, 0x6F, 0xA8, 0xBF, 0xA1, 0xF1, 0xC0, 0x41, 0xBD, 0xE8, 0x70, 0x40, 0x80, 0xF2, 0x82, 0x80, 0x4F, 0xF0, 0x00, 0x00, 0x01, 0xF1, 0xC0, 0x41, 0x01, 0xF0, 0x00, + 0x41, 0x70, 0x47, 0x9E, 0xEA, 0x0C, 0x0F, 0x0C, 0xEA, 0x13, 0x15, 0x18, 0xBF, 0x95, 0xEA, 0x0C, 0x0F, 0x06, 0xD0, 0x4F, 0xF0, 0x00, 0x00, 0x81, 0xEA, 0x03, 0x0E, 0x0E, 0xF0, 0x00, 0x41, 0x70, 0xBD, 0x00, 0xF0, 0x1C, 0xF8, 0x89, 0x00, 0x01, + 0x3E, 0x00, 0xF0, 0x07, 0xB8, 0x00, 0xF0, 0x09, 0xB8, 0x4F, 0xEA, 0x43, 0x0C, 0x5F, 0xEA, 0x5C, 0x5C, 0x08, 0xD0, 0x81, 0xEA, 0x03, 0x01, 0x00, 0xF0, 0x5B, 0xB8, 0x4F, 0xEA, 0x41, 0x0C, 0x5F, 0xEA, 0x5C, 0x5C, 0xF6, 0xD1, 0x4F, 0xF0, 0x00, + 0x00, 0x01, 0x49, 0x70, 0x47, 0x00, 0x00, 0xFF, 0x07, 0x00, 0x00, 0xF8, 0x7F, 0x0E, 0xF1, 0x02, 0x0E, 0x2E, 0xF0, 0x03, 0x0E, 0x5E, 0xF8, 0x04, 0x6B, 0x36, 0x42, 0x05, 0xD4, 0x01, 0x2A, 0x43, 0xEB, 0x03, 0x05, 0x15, 0xF5, 0x00, 0x1F, 0x12, + 0xD8, 0x01, 0x28, 0x41, 0xEB, 0x01, 0x0C, 0x1C, 0xF5, 0x00, 0x1F, 0x0C, 0xD8, 0x0E, 0xD1, 0x4F, 0xEA, 0xD1, 0x7C, 0x15, 0xF5, 0x00, 0x1F, 0x0C, 0xEB, 0x4C, 0x0C, 0x0C, 0xF1, 0x02, 0x0C, 0x08, 0xBF, 0x4C, 0xEB, 0xD3, 0x7C, 0x04, 0xE0, 0x4F, + 0xF0, 0x08, 0x0C, 0x01, 0xE0, 0x4F, 0xEA, 0xD3, 0x7C, 0x0C, 0xEB, 0x4C, 0x05, 0x26, 0xFA, 0x05, 0xF6, 0x06, 0xF0, 0x07, 0x06, 0xB6, 0xF1, 0x04, 0x0C, 0x06, 0xD2, 0x0E, 0xEB, 0x86, 0x0C, 0xBD, 0xE8, 0x70, 0x40, 0x4C, 0xF0, 0x01, 0x0C, 0x60, + 0x47, 0xDF, 0xE8, 0x0C, 0xF0, 0x09, 0x0B, 0x02, 0x02, 0x4F, 0xF0, 0x00, 0x41, 0x4F, 0xF0, 0x00, 0x00, 0xA1, 0xF5, 0x00, 0x21, 0x70, 0xBD, 0x19, 0x46, 0x10, 0x46, 0x01, 0x28, 0x51, 0xEB, 0x01, 0x04, 0x18, 0xBF, 0xD4, 0xF5, 0x00, 0x14, 0x84, + 0xBF, 0x00, 0x20, 0x01, 0xF0, 0x00, 0x41, 0x70, 0xBD, 0x08, 0x08, 0xA0, 0xF5, 0x00, 0x11, 0x4F, 0xEA, 0x31, 0x01, 0x70, 0x47, 0x01, 0xD1, 0x85, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x51, 0x89, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x89, 0x20, 0x00, 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x72, 0x65, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x00, 0x68, 0xE8, 0x21, + 0x00, 0x14, 0xE9, 0x21, 0x00, 0x5C, 0xE8, 0x21, 0x00, 0x1C, 0xE9, 0x21, 0x00, 0xC0, 0xE8, 0x21, 0x00, 0x34, 0xE9, 0x21, 0x00, 0x28, 0xE9, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0xB0, 0xE8, 0x21, + 0x00, 0x50, 0xE8, 0x21, 0x00, 0x08, 0xE9, 0x21, 0x00, 0xB0, 0xE8, 0x21, 0x00, 0x78, 0xE8, 0x21, 0x00, 0xD8, 0xE8, 0x21, 0x00, 0xEC, 0xE8, 0x21, 0x00, 0x58, 0xE8, 0x21, 0x00, 0x40, 0xE8, 0x21, 0x00, 0xC0, 0xE7, 0x21, 0x00, 0x94, 0xE7, 0x21, + 0x00, 0xF4, 0xE8, 0x21, 0x00, 0xA8, 0xE8, 0x21, 0x00, 0x94, 0xE8, 0x21, 0x00, 0x2C, 0xE8, 0x21, 0x00, 0xEC, 0xE7, 0x21, 0x00, 0x0C, 0xE8, 0x21, 0x00, 0x70, 0xE7, 0x21, 0x00, 0x3C, 0xE7, 0x21, 0x00, 0x4C, 0xE8, 0x21, 0x00, 0x34, 0xE7, 0x21, + 0x00, 0x68, 0xE7, 0x21, 0x00, 0x2C, 0xE7, 0x21, 0x00, 0x60, 0xE7, 0x21, 0x00, 0x48, 0xE8, 0x21, 0x00, 0xE0, 0xE8, 0x21, 0x00, 0x44, 0xE7, 0x21, 0x00, 0x78, 0xE7, 0x21, 0x00, 0xA4, 0xE7, 0x21, 0x00, 0xC8, 0xE7, 0x21, 0x00, 0xF4, 0xE7, 0x21, + 0x00, 0x14, 0xE8, 0x21, 0x00, 0xD8, 0xE7, 0x21, 0x00, 0xB4, 0xE7, 0x21, 0x00, 0x74, 0xE8, 0x21, 0x00, 0x88, 0xE7, 0x21, 0x00, 0x54, 0xE7, 0x21, 0x00, 0x9C, 0xE7, 0x21, 0x00, 0xE4, 0xE7, 0x21, 0x00, 0x04, 0xE8, 0x21, 0x00, 0x24, 0xE8, 0x21, + 0x00, 0x38, 0xE8, 0x21, 0x00, 0xCC, 0xE8, 0x21, 0x00, 0xB8, 0xE8, 0x21, 0x00, 0x00, 0xE9, 0x21, 0x00, 0x80, 0xE8, 0x21, 0x00, 0x60, 0xE8, 0x21, 0x00, 0x40, 0xE9, 0x21, 0x00, 0x9C, 0xE8, 0x21, 0x00, 0x88, 0xE8, 0x21, 0x00, 0x54, 0xE8, 0x21, + 0x00, 0x02, 0x08, 0x00, 0x28, 0x0F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x19, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x53, 0x94, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xBB, 0x94, 0x20, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x48, 0xE1, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0x28, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x95, 0x20, 0x00, 0xD3, 0x95, 0x20, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xD0, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xBC, 0xE4, 0x21, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD2, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x04, 0x00, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF1, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x91, 0xCF, 0x21, 0x00, 0xED, 0xCE, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B, 0xA0, 0x20, 0x00, 0xD5, 0xA0, 0x20, 0x00, 0x52, 0x65, 0x61, + 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, 0x00, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x6D, 0x73, 0x67, 0x5F, 0x74, 0x6F, 0x5F, 0x61, 0x70, 0x70, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x6D, 0x61, 0x69, + 0x6E, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x00, 0x00, 0x49, 0x32, 0x43, 0x30, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x30, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x30, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, + 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x30, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x30, 0x00, 0x49, 0x32, 0x43, 0x31, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x31, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, + 0x54, 0x31, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x31, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x31, 0x00, 0x54, 0x49, 0x4D, 0x32, 0x00, 0x00, 0x00, + 0x00, 0x55, 0x41, 0x52, 0x54, 0x32, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x32, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x32, 0x00, 0x54, 0x49, 0x4D, + 0x33, 0x00, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x33, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x33, 0x00, 0x54, 0x49, 0x4D, 0x34, 0x00, 0x00, 0x00, + 0x00, 0x47, 0x50, 0x49, 0x4F, 0x34, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x34, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x35, 0x00, 0x00, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x35, 0x00, 0x00, + 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x35, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x36, 0x00, 0x00, 0x00, 0x00, 0x54, 0x69, 0x6D, 0x65, 0x72, 0x34, 0x2D, 0x37, 0x00, 0x00, 0x00, 0x00, 0x54, 0x49, 0x4D, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x4D, 0x41, 0x43, 0x00, 0x00, 0x00, 0x41, 0x44, 0x43, 0x00, 0x52, 0x54, 0x43, 0x00, 0x53, 0x56, 0x43, 0x00, 0x4C, 0x43, 0x44, 0x00, 0x57, 0x44, 0x47, 0x00, 0x4E, 0x4D, 0x49, 0x00, 0x4C, 0x50, 0x43, + 0x4F, 0x4D, 0x50, 0x00, 0x00, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x53, 0x50, 0x00, 0x00, 0x00, 0x49, 0x52, 0x00, 0x00, 0x50, 0x65, 0x6E, 0x64, 0x53, 0x56, 0x00, 0x00, 0x53, 0x50, 0x49, 0x32, 0x57, 0x00, 0x00, 0x00, 0x53, 0x50, 0x4F, + 0x52, 0x54, 0x31, 0x20, 0x52, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, 0x53, 0x30, 0x5F, 0x52, 0x58, 0x00, 0x53, 0x50, 0x4F, 0x52, 0x54, 0x31, 0x20, 0x54, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, 0x53, 0x30, 0x5F, 0x54, 0x58, 0x00, 0x52, 0x73, 0x76, + 0x64, 0x00, 0x00, 0x00, 0x00, 0x51, 0x64, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x5F, 0x46, 0x6C, 0x61, 0x73, 0x68, 0x00, 0x00, 0x00, 0x53, 0x79, 0x73, + 0x54, 0x69, 0x63, 0x6B, 0x00, 0x50, 0x65, 0x72, 0x69, 0x70, 0x68, 0x65, 0x72, 0x61, 0x6C, 0x00, 0x00, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x00, 0x00, 0x50, 0x6C, 0x61, 0x74, 0x66, 0x6F, 0x72, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, + 0x73, 0x63, 0x61, 0x6E, 0x00, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4D, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x48, 0x61, 0x72, 0x64, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, + 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x50, 0x54, 0x41, 0x5F, 0x4D, 0x61, 0x69, 0x6C, 0x62, 0x6F, 0x78, 0x00, 0x00 +}; + +#else // default silent ota test image +{ + 0x05, 0x00, 0x01, 0x01, 0x93, 0x27, 0x00, 0x00, 0xF0, 0x40, 0x00, 0x00, 0x6D, 0x67, 0xDE, 0xF1, 0x3E, 0x33, 0xE8, 0x11, 0xB1, 0x02, 0x4D, 0x2D, 0xF4, 0x0C, 0xDE, 0x01, 0x00, 0xE4, 0x80, 0x00, 0x00, 0xE4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x20, 0x00, 0x08, 0x50, 0x43, 0x46, 0x1E, 0x73, 0x64, 0x6B, 0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x72, 0xCA, 0xB4, 0x1E, 0xC9, 0x4B, 0xE5, 0xD1, 0xCD, 0x6C, 0xEE, 0x4F, 0xBA, 0xE2, 0x43, 0x96, 0x88, 0x91, 0x44, 0x53, 0x6B, 0x91, 0x3F, 0x7B, 0xEA, 0xEF, 0xB7, + 0xFD, 0x95, 0x03, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xD1, 0x85, 0x0E, 0xE0, 0xAF, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x48, 0x00, 0x47, 0x5F, 0xE5, 0x80, 0x00, 0xAF, 0xF3, 0x00, 0x80, 0xF9, 0xF5, 0xFE, 0xF3, + 0x10, 0xB5, 0x7B, 0x4A, 0x7B, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0x3F, 0xF5, 0x7B, 0x4A, 0x7C, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0x3A, 0xF5, 0x7C, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0xF7, 0xF5, 0x7C, 0x4A, 0x7C, 0x49, 0x7D, 0x48, 0x4B, 0xF4, 0x31, 0xF5, + 0x7C, 0x4A, 0x7D, 0x49, 0x7D, 0x48, 0x4B, 0xF4, 0x2C, 0xF5, 0xBD, 0xE8, 0x10, 0x40, 0x7C, 0x49, 0x7C, 0x48, 0x4B, 0xF4, 0xE7, 0xB5, 0x7F, 0xB5, 0x4F, 0xF4, 0x00, 0x10, 0xF0, 0xE9, 0xE0, 0x12, 0x11, 0x44, 0x80, 0x68, 0x10, 0x22, 0x0D, 0x18, + 0x29, 0x46, 0x68, 0x46, 0x4B, 0xF4, 0x19, 0xF5, 0x10, 0x22, 0x69, 0x46, 0x00, 0x20, 0xF8, 0xF7, 0xB1, 0xDF, 0x73, 0x49, 0xD1, 0xF8, 0x7C, 0x11, 0x72, 0x4E, 0x60, 0xF3, 0x1F, 0x41, 0x4F, 0xF0, 0xFF, 0x30, 0x31, 0x61, 0xF9, 0xF7, 0x95, 0xD9, + 0x31, 0x69, 0x48, 0x43, 0x30, 0x61, 0xFC, 0xF5, 0xBF, 0xF4, 0x00, 0x24, 0xF9, 0xF5, 0xC4, 0xF3, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0x04, 0x2C, 0xF8, 0xDB, 0xF9, 0xF5, 0xBD, 0xF3, 0x30, 0x61, 0x7F, 0xBD, 0x70, 0xB5, 0x66, 0x4D, 0x67, 0x49, + 0x67, 0x4C, 0x28, 0x68, 0x4F, 0xF0, 0x00, 0x02, 0xB1, 0xEB, 0x00, 0x2F, 0x05, 0xD0, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x63, 0x49, 0xF9, 0xF7, 0xCA, 0x9A, 0x00, 0x21, 0x45, 0xF2, 0x06, 0x00, 0xFD, 0xF7, 0xCF, 0xDD, 0x10, 0xF0, 0xFF, 0x03, + 0x03, 0xD0, 0x5E, 0x49, 0x01, 0x22, 0x1C, 0x31, 0x04, 0xE0, 0x28, 0x68, 0x5B, 0x49, 0x03, 0x0E, 0x01, 0x22, 0x50, 0x31, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0xF9, 0xF7, 0xB4, 0x9A, 0x38, 0xB5, 0x72, 0xB6, 0xFF, 0xF7, 0xD6, 0xFF, 0xFF, 0xF7, + 0x87, 0xFF, 0xFF, 0xF7, 0xA4, 0xFF, 0x00, 0x20, 0xFB, 0xF5, 0x08, 0xF1, 0x16, 0x20, 0xF9, 0xF5, 0xA8, 0xF5, 0x17, 0x20, 0xF9, 0xF5, 0xA5, 0xF5, 0x4F, 0xA1, 0x1F, 0x20, 0x4B, 0xF4, 0x6A, 0xF4, 0x4F, 0xF0, 0x05, 0x55, 0x4D, 0xA1, 0x28, 0x46, + 0xF9, 0xF7, 0x9F, 0xDC, 0x04, 0x46, 0x52, 0xA1, 0x28, 0x46, 0xF9, 0xF7, 0x9A, 0xDC, 0x03, 0x46, 0x46, 0x49, 0x45, 0x48, 0x02, 0x22, 0x7C, 0x31, 0x80, 0x1E, 0x00, 0x94, 0xF9, 0xF7, 0x8B, 0xDA, 0xF9, 0xF5, 0x96, 0xF5, 0x4C, 0x48, 0x00, 0x68, + 0x00, 0x28, 0x03, 0xD0, 0x01, 0xB0, 0xBD, 0xE8, 0x30, 0x40, 0x00, 0x47, 0x38, 0xBD, 0x10, 0xB5, 0xFE, 0xF7, 0xFE, 0xD8, 0x00, 0x28, 0x4A, 0xD1, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0xDC, 0x12, 0xC9, 0x07, 0x44, 0xD0, 0xAF, 0xF2, 0x81, 0x01, + 0x42, 0x4A, 0x11, 0x60, 0x43, 0x4A, 0x42, 0x49, 0x11, 0x60, 0x4F, 0xF4, 0x0C, 0x41, 0xC0, 0xF8, 0x84, 0x13, 0x47, 0xF2, 0xF0, 0x71, 0xC0, 0xF8, 0x88, 0x13, 0x3F, 0x49, 0xC0, 0xF8, 0xCC, 0x13, 0x90, 0xF8, 0x4D, 0x13, 0x41, 0xF0, 0x08, 0x01, + 0x80, 0xF8, 0x4D, 0x13, 0x06, 0x21, 0x80, 0xF8, 0x4F, 0x13, 0x90, 0xF8, 0x78, 0x23, 0x90, 0xF8, 0x9A, 0x13, 0x42, 0xF0, 0x26, 0x02, 0x80, 0xF8, 0x78, 0x23, 0x21, 0xF0, 0x21, 0x01, 0x80, 0xF8, 0x9A, 0x13, 0x90, 0xF8, 0x34, 0x13, 0x41, 0xF0, + 0x01, 0x01, 0x80, 0xF8, 0x34, 0x13, 0x90, 0xF8, 0x7A, 0x13, 0x21, 0xF0, 0x10, 0x01, 0x80, 0xF8, 0x7A, 0x13, 0x90, 0xF8, 0xC3, 0x13, 0x21, 0xF0, 0xC0, 0x01, 0x80, 0xF8, 0xC3, 0x13, 0xF0, 0x21, 0x80, 0xF8, 0x20, 0x13, 0x3C, 0x21, 0x80, 0xF8, + 0x21, 0x13, 0xC8, 0x21, 0x80, 0xF8, 0x22, 0x13, 0xFF, 0x21, 0x80, 0xF8, 0x23, 0x13, 0x10, 0xBD, 0x2C, 0x3C, 0x00, 0x00, 0x88, 0xE7, 0x80, 0x00, 0x00, 0x7C, 0x20, 0x00, 0x3C, 0x01, 0x00, 0x00, 0xB4, 0x23, 0x81, 0x00, 0x2C, 0xB8, 0x20, 0x00, + 0x84, 0x0B, 0x00, 0x00, 0x68, 0xB9, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x81, 0x00, 0x00, 0xC0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x24, 0x81, 0x00, 0x00, 0xC0, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x21, 0x00, + 0x00, 0x80, 0x05, 0x40, 0x68, 0xB9, 0x20, 0x00, 0x2C, 0xB8, 0x20, 0x00, 0x00, 0x74, 0x65, 0x72, 0x02, 0x03, 0x10, 0x21, 0x00, 0x00, 0x80, 0x08, 0x43, 0x00, 0x00, 0x00, 0x54, 0x68, 0x75, 0x20, 0x4D, 0x61, 0x79, 0x20, 0x20, 0x37, 0x20, 0x31, + 0x37, 0x3A, 0x31, 0x37, 0x3A, 0x31, 0x33, 0x20, 0x32, 0x30, 0x32, 0x30, 0x00, 0x00, 0x00, 0x00, 0x31, 0x2E, 0x32, 0x2E, 0x32, 0x2E, 0x31, 0x00, 0x74, 0xB9, 0x20, 0x00, 0x38, 0x0C, 0x20, 0x00, 0x55, 0x7F, 0x20, 0x00, 0x3C, 0x0C, 0x20, 0x00, + 0x03, 0x00, 0xAA, 0xA2, 0x00, 0x38, 0x20, 0x00, 0x01, 0xE4, 0x80, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x55, 0x7C, 0x20, 0x00, 0xA1, 0x7C, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0xED, 0x7C, 0x20, 0x00, 0x31, 0x7D, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, + 0x05, 0x7F, 0x20, 0x00, 0x05, 0x7F, 0x20, 0x00, 0x1F, 0xB5, 0x03, 0xF0, 0xE7, 0xF9, 0x03, 0xF0, 0x18, 0xF9, 0x1F, 0xBD, 0x00, 0xF0, 0x82, 0xF9, 0x11, 0x46, 0xFF, 0xF7, 0xF5, 0xFF, 0x01, 0xF0, 0x45, 0xFD, 0x53, 0xF6, 0x03, 0xF9, 0x00, 0x00, + 0x0B, 0x49, 0xD1, 0xF8, 0x00, 0xC0, 0x4A, 0x68, 0x5C, 0xF8, 0x04, 0x3B, 0x10, 0x68, 0x18, 0x44, 0x42, 0xF8, 0x04, 0x0B, 0x8C, 0x45, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x0C, 0x8A, 0x42, 0x28, 0xBF, 0xA1, 0xF1, 0xDC, 0x02, 0xC1, 0xF8, 0x00, 0xC0, + 0x4A, 0x60, 0x20, 0xF0, 0x00, 0x40, 0x70, 0x47, 0xE4, 0xC4, 0x20, 0x00, 0x47, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x20, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x51, 0xF9, 0x20, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0x4D, 0xF9, 0x20, 0x05, 0x01, 0xD5, 0x00, 0xF0, + 0x49, 0xF9, 0x20, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0x45, 0xF9, 0x20, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x41, 0xF9, 0x20, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0x3D, 0xF9, 0x20, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0x39, 0xF9, 0x00, 0x2C, 0x03, 0xDA, 0xBD, 0xE8, + 0x10, 0x40, 0x00, 0xF0, 0x33, 0xB9, 0x10, 0xBD, 0x34, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0x60, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x2B, 0xF9, 0x60, 0x06, 0x01, 0xD5, 0x00, 0xF0, 0x27, 0xF9, 0x60, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x23, 0xF9, 0x60, 0x04, + 0x01, 0xD5, 0x00, 0xF0, 0x1F, 0xF9, 0x60, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0x1B, 0xF9, 0x60, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0x17, 0xF9, 0x60, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0x13, 0xF9, 0x60, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, + 0x0D, 0xB9, 0x10, 0xBD, 0x21, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xA0, 0x07, 0x01, 0xD5, 0x00, 0xF0, 0x05, 0xF9, 0xA0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0x01, 0xF9, 0xA0, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0xFD, 0xF8, 0xA0, 0x03, 0x01, 0xD5, 0x00, 0xF0, + 0xF9, 0xF8, 0xA0, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xF5, 0xF8, 0xA0, 0x01, 0x01, 0xD5, 0x00, 0xF0, 0xF1, 0xF8, 0xA0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xEB, 0xB8, 0x10, 0xBD, 0x10, 0x48, 0x10, 0xB5, 0x04, 0x6C, 0xE0, 0x07, + 0x01, 0xD0, 0x00, 0xF0, 0xE3, 0xF8, 0xE0, 0x05, 0x01, 0xD5, 0x00, 0xF0, 0xDF, 0xF8, 0xE0, 0x04, 0x01, 0xD5, 0x00, 0xF0, 0xDB, 0xF8, 0xE0, 0x03, 0x01, 0xD5, 0x00, 0xF0, 0xD7, 0xF8, 0xE0, 0x02, 0x01, 0xD5, 0x00, 0xF0, 0xD3, 0xF8, 0xE0, 0x01, + 0x01, 0xD5, 0x00, 0xF0, 0xCF, 0xF8, 0xE0, 0x00, 0x03, 0xD5, 0xBD, 0xE8, 0x10, 0x40, 0x00, 0xF0, 0xC9, 0xB8, 0x10, 0xBD, 0x00, 0x10, 0x00, 0x40, 0x7C, 0xB5, 0x00, 0x24, 0x4F, 0xF0, 0xE0, 0x20, 0x01, 0x21, 0xC0, 0xF8, 0x80, 0x11, 0xD0, 0xF8, + 0x00, 0x21, 0x59, 0x49, 0x0A, + 0x60, 0xD0, 0xF8, 0x00, 0x22, 0x4A, 0x60, 0xD0, 0xF8, 0x00, 0x03, 0x88, 0x60, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x92, 0xF8, 0x00, 0x24, 0x41, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0x20, 0x28, 0xF6, 0xD3, 0x51, 0x48, 0x00, 0x68, 0xC1, 0xF8, 0x80, + 0x00, 0x50, 0x48, 0xC0, 0x68, 0x4D, 0x4B, 0x0C, 0x3B, 0x03, 0xF1, 0x90, 0x01, 0x18, 0x60, 0x00, 0x20, 0x82, 0x00, 0x02, 0xF1, 0x80, 0x42, 0xD2, 0xF8, 0x80, 0x22, 0x41, 0xF8, 0x20, 0x20, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x98, 0x68, 0x00, 0xB1, 0x80, 0x47, 0x4F, 0xF4, 0x00, 0x15, 0x95, 0xF8, 0x34, 0x03, 0xC0, 0x07, 0x0F, 0xD0, 0x00, 0x94, 0x02, 0x23, 0x01, 0x22, 0x00, 0x21, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xEF, 0xFA, 0x00, 0x94, 0x02, + 0x23, 0x01, 0x22, 0x00, 0x21, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xE7, 0xFA, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x23, 0x00, 0xF0, 0x3F, 0x00, 0x1A, 0x46, 0x00, 0x21, 0x09, 0xF6, 0xDC, 0xFA, 0x7C, 0xBD, 0x30, 0xB5, 0x31, + 0x49, 0x00, 0x20, 0x85, 0xB0, 0x84, 0x31, 0x82, 0x00, 0x02, 0xF1, 0x80, 0x42, 0x51, 0xF8, 0x20, 0x30, 0xC2, 0xF8, 0x80, 0x32, 0x40, 0x1C, 0xC0, 0xB2, 0x0A, + 0x28, 0xF4, 0xD3, 0x00, 0x24, 0x4F, 0xF4, 0x00, 0x15, 0x00, 0x94, 0x01, 0x94, 0x95, 0xF8, 0x98, 0x03, 0x01, 0x22, 0x00, 0xF0, 0x3F, 0x00, 0x23, 0x46, 0x11, 0x46, 0x05, 0xF5, 0x66, 0x75, 0x09, 0xF6, 0xBB, 0xFA, 0x15, 0xF8, 0x64, 0x0C, 0xC0, + 0x07, 0x0F, 0xD0, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x08, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xAF, 0xFA, 0x01, 0x23, 0x00, 0x94, 0x1A, 0x46, 0x19, 0x46, 0x09, 0x20, 0x01, 0x94, 0x09, 0xF6, 0xA7, 0xFA, 0x18, 0x4D, 0x0C, 0x3D, 0x68, + 0x68, 0x00, 0xB1, 0x80, 0x47, 0x01, 0x20, 0x8D, 0xF8, 0x10, 0x00, 0x03, 0x20, 0x03, 0x90, 0x8D, 0xF8, 0x08, 0x40, 0x02, 0xA8, 0x09, 0xF6, 0x0A, + 0xFA, 0x10, 0x4C, 0x63, 0x68, 0x58, 0x08, 0x04, 0xD0, 0x01, 0x22, 0x11, 0x49, 0x11, 0x48, 0xFF, 0xF5, 0xD0, 0xFD, 0x03, 0x20, 0x00, 0xF1, 0xE0, 0x22, 0x14, 0xF8, 0x20, 0x10, 0x82, 0xF8, 0x00, 0x14, 0x40, 0x1C, 0x20, 0x28, 0xF6, 0xD3, 0x08, + 0x49, 0xD4, 0xF8, 0x80, 0x00, 0x08, 0x60, 0x07, 0x49, 0x28, 0x68, 0xC8, 0x60, 0x4F, 0xF0, 0xE0, 0x21, 0x20, 0x68, 0xC1, 0xF8, 0x00, 0x01, 0x05, 0xB0, 0x30, 0xBD, 0x00, 0x00, 0x98, 0xB9, 0x20, 0x00, 0x08, 0xED, 0x00, 0xE0, 0x00, 0x60, 0x00, + 0x40, 0xE8, 0x00, 0x80, 0x08, 0x01, 0x04, 0x10, 0x21, 0x4F, 0xF0, 0x00, 0x50, 0x10, 0x49, 0xEF, 0xF3, 0x05, 0x82, 0x10, 0x4B, 0x98, 0x47, 0xFE, 0xE7, 0x70, 0x47, 0x45, 0x72, 0x72, 0x6F, 0x72, 0x21, 0x20, 0x50, 0x6C, 0x65, 0x61, 0x73, 0x65, + 0x20, 0x69, 0x6D, 0x70, 0x6C, 0x65, 0x6D, 0x65, 0x6E, 0x74, 0x20, 0x79, 0x6F, 0x75, 0x72, 0x20, 0x49, 0x53, 0x52, 0x20, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, 0x20, 0x66, 0x6F, 0x72, 0x20, 0x49, 0x52, 0x51, 0x20, 0x25, 0x64, 0x21, 0x0A, + 0x00, 0x16, 0x7F, 0x20, 0x00, 0xB1, 0x79, 0x00, 0x00, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x94, 0xF8, 0x9B, 0x03, 0x40, 0xF0, 0x80, 0x00, 0x84, 0xF8, 0x9B, 0x03, 0x94, 0xF8, 0xDC, 0x02, 0xC1, 0x07, 0x4F, 0xF0, 0x04, 0x50, 0x03, 0xD0, 0x6F, + 0xA1, 0xFF, 0xF5, 0x1C, 0xFD, 0x06, 0xE0, 0x70, 0xA1, 0xFF, 0xF5, 0x18, 0xFD, 0x09, 0xF6, 0xDF, 0xFC, 0x1E, 0xF6, 0x1D, 0xFC, 0x94, 0xF8, 0x9A, 0x03, 0xC0, 0x07, 0x02, 0xD0, 0x00, 0x20, 0x00, 0xF6, 0x1F, 0xF9, 0xBD, 0xE8, 0x10, 0x40, 0x06, + 0xF2, 0x35, 0xB2, 0x40, 0xEA, 0x01, 0x21, 0x01, 0x20, 0xFF, 0xF5, 0x7C, 0xB9, 0x10, 0xB5, 0x4F, 0xF4, 0x00, 0x14, 0x00, 0x22, 0x94, 0xF8, 0x4C, 0x13, 0x60, 0xF3, 0x01, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x11, 0x46, 0x45, 0xF2, 0x02, 0x00, 0x04, + 0xF6, 0x56, 0xF8, 0x00, 0x28, 0x05, 0xD1, 0x94, 0xF8, 0x4C, 0x13, 0x21, 0xF0, 0x03, 0x01, 0x84, 0xF8, 0x4C, 0x13, 0x10, 0xBD, 0x01, 0x46, 0x40, 0xF2, 0x71, 0x43, 0x62, 0x4A, 0x00, 0x20, 0x1D, 0xF6, 0xBD, 0xBE, 0x60, 0x4A, 0x41, 0x43, 0xD2, + 0x1D, 0x40, 0xF2, 0x76, 0x43, 0x00, 0x20, 0x1D, 0xF6, 0xE1, 0xBE, 0x10, 0xB5, 0x0C, 0x46, 0x08, 0xB1, 0x1D, 0xF6, 0x3B, 0xFF, 0x59, 0x4A, 0x21, 0x46, 0x0E, 0x32, 0xBD, 0xE8, 0x10, 0x40, 0x4F, 0xF4, 0x90, 0x63, 0x00, 0x20, 0x1D, 0xF6, 0xA6, + 0xBE, 0x1D, 0xF6, 0x2F, 0xBF, 0x54, 0x4A, 0xD1, 0x70, 0x54, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x52, 0x4A, 0x12, 0x68, 0x00, 0x2A, 0x00, 0xD0, 0x10, 0x47, 0x70, 0x47, 0x50, 0x48, 0x00, 0x68, 0x00, 0x28, 0x00, + 0xD0, 0x00, 0x47, 0x70, 0x47, 0x4E, 0x48, 0x00, 0x68, 0x70, 0x47, 0x4A, 0x48, 0x10, 0xB5, 0x0E, 0x22, 0x4C, 0x49, 0x14, 0x30, 0x51, 0xF6, 0x23, 0xFF, 0x46, 0x48, 0x14, 0x30, 0x10, 0xBD, 0x49, 0x48, 0x80, 0x1E, 0x00, 0x78, 0x70, 0x47, 0x00, + 0xF0, 0x1F, 0x02, 0x01, 0x21, 0x91, 0x40, 0x40, 0x09, 0x80, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0xC0, 0xF8, 0x80, 0x11, 0x70, 0x47, 0x2D, 0xE9, 0xF0, 0x47, 0x3A, 0x49, 0xBE, 0xB0, 0x40, 0x22, 0x18, 0x31, 0x2D, 0xA8, 0x51, 0xF6, 0x8F, 0xFF, 0x37, + 0x49, 0xB4, 0x22, 0x58, 0x31, 0x68, 0x46, 0x51, 0xF6, 0x89, 0xFF, 0x3D, 0x49, 0x4F, 0xF4, 0x00, 0x10, 0x39, 0x4E, 0x3A, 0x4F, 0x09, 0x68, 0x05, 0x46, 0x00, 0x24, 0xA9, 0x42, 0x01, 0xD0, 0xFC, 0xF5, 0xFD, 0xFD, 0xDF, 0xF8, 0xE0, 0x80, 0x4F, + 0xF0, 0x05, 0x59, 0xDF, 0xF8, 0xDC, 0xA0, 0x2F, 0xE0, 0x6C, 0xB3, 0x01, 0x2C, 0x2B, 0xD0, 0x56, 0xF8, 0x24, 0x00, 0x40, 0x45, 0x00, 0xD0, 0x38, 0xB9, 0x40, 0x45, 0x24, 0xD1, 0x55, 0xF8, 0x24, 0x00, 0xA0, 0xF5, 0x80, 0x71, 0x55, 0x39, 0x1E, + 0xD1, 0x10, 0x2C, 0x09, 0xD2, 0x2D, 0xA8, 0x50, 0xF8, 0x24, 0x10, 0x48, 0x46, 0xFF, 0xF5, 0xBF, 0xFE, 0x03, 0x46, 0x01, 0x22, 0x29, 0x49, 0x0B, 0xE0, 0x68, 0x46, 0x00, 0xEB, 0x84, 0x00, 0x50, 0xF8, 0x40, 0x1C, 0x48, 0x46, 0xFF, 0xF5, 0xB3, + 0xFE, 0x24, 0x49, 0x01, 0x22, 0x03, 0x46, 0x24, 0x31, 0x50, 0x46, 0xFF, 0xF5, 0xA6, 0xFC, 0x56, 0xF8, 0x24, 0x00, 0x45, 0xF8, 0x24, 0x00, 0x64, 0x1C, 0xB4, 0xEB, 0x97, 0x0F, 0xCC, 0xD3, 0xBF, 0xF3, 0x5F, 0x8F, 0xBF, 0xF3, 0x4F, 0x8F, 0x3E, + 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x49, 0x6E, 0x20, 0x53, 0x6F, 0x43, 0x20, 0x4D, 0x6F, 0x64, 0x65, 0x00, 0x57, 0x41, 0x52, 0x4E, 0x49, 0x4E, 0x47, 0x3A, 0x20, 0x49, 0x6E, 0x20, 0x48, 0x43, 0x49, 0x20, 0x4D, 0x6F, 0x64, 0x65, 0x2C, 0x20, 0x77, + 0x69, 0x6C, 0x6C, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x41, 0x50, 0x50, 0x20, 0x54, 0x61, 0x73, 0x6B, 0x00, 0x04, 0xB0, 0x20, 0x00, 0x2C, 0xB8, 0x20, 0x00, 0x68, 0xB9, 0x20, 0x00, 0x6C, 0xB9, 0x20, 0x00, 0x70, 0xB9, 0x20, + 0x00, 0xF4, 0x00, 0x20, 0x00, 0xF5, 0x28, 0x20, 0x00, 0x94, 0xE6, 0x80, 0x00, 0xF4, 0x00, 0x00, 0x00, 0x08, 0xED, 0x00, 0xE0, 0x05, 0x7F, 0x20, 0x00, 0x01, 0x01, 0x10, 0x21, 0x9C, 0x00, 0x80, 0x08, 0x10, 0xB5, 0x00, 0x21, 0x04, 0x48, 0x00, + 0xF6, 0xA4, 0xFA, 0xBD, 0xE8, 0x10, 0x40, 0x04, 0x21, 0x02, 0x48, 0x00, 0xF6, 0x9E, 0xBA, 0x00, 0x00, 0x79, 0x7D, 0x20, 0x00, 0x27, 0x7E, 0x20, 0x00, 0x70, 0xB5, 0x01, 0x24, 0x13, 0x46, 0x0D, 0x46, 0x01, 0x28, 0x06, 0xD0, 0x00, 0x24, 0x22, + 0x46, 0x82, 0x49, 0x83, 0x48, 0xFF, 0xF5, 0x45, 0xFC, 0x09, 0xE0, 0xB5, 0xF5, 0x96, 0x7F, 0xF5, 0xD8, 0x0A, + 0x46, 0x19, 0x46, 0x7F, 0x48, 0x51, 0xF6, 0x5A, 0xFE, 0x7F, 0x48, 0x05, 0x80, 0x20, 0x46, 0x70, 0xBD, 0xFE, 0xB5, 0x00, 0x24, 0xDD, 0xE9, 0x08, 0x65, 0x0B, 0x46, 0x02, 0x2A, 0x09, 0xD0, 0x76, 0x49, 0x13, 0x46, 0x01, 0x22, 0x2C, 0x31, 0x75, + 0x48, 0xFF, 0xF5, 0x2A, 0xFC, 0x40, 0xF2, 0x0A, + 0x44, 0x13, 0xE0, 0x02, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x8D, 0xF8, 0x00, 0x00, 0x71, 0x48, 0x01, 0x21, 0x08, 0x38, 0x8D, 0xF8, 0x04, 0x10, 0x42, 0x68, 0x12, 0xB1, 0x69, 0x46, 0x18, 0x46, 0x90, 0x47, 0x6C, 0x48, 0x28, 0x60, 0x6C, 0x48, 0x00, + 0x88, 0x30, 0x80, 0x20, 0x46, 0xFE, 0xBD, 0x0E, 0xB5, 0x8D, 0xE8, 0x0E, 0x00, 0x03, 0x46, 0x64, 0x49, 0x65, 0x48, 0x04, 0x22, 0x68, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0x06, 0xFC, 0x0E, 0xBD, 0x2D, 0xE9, 0xFF, 0x5F, 0x8B, 0x46, 0x80, 0x46, 0xDD, + 0xE9, 0x0E, 0x65, 0x5D, 0x49, 0x5E, 0x48, 0x17, 0x46, 0x99, 0x46, 0x00, 0x24, 0x01, 0x22, 0xC0, 0x31, 0x80, 0x1C, 0xDD, 0xF8, 0x40, 0xA0, 0xFF, 0xF5, 0xF3, 0xFB, 0xAF, 0xF2, 0x3F, 0x01, 0xCA, 0xF8, 0x00, 0x10, 0x05, 0x2F, 0x0D, 0xD0, 0x54, + 0x49, 0x3B, 0x46, 0x02, 0x22, 0xF4, 0x31, 0x53, 0x48, 0x00, 0x96, 0xFF, 0xF5, 0xE5, 0xFB, 0x40, 0xF2, 0x0A, + 0x44, 0x04, 0xB0, 0x20, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0xAD, 0xB1, 0x03, 0x20, 0x8D, 0xF8, 0x05, 0x00, 0x01, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x4C, 0x48, 0x8D, 0xF8, 0x09, 0x90, 0x08, 0x38, 0x8D, 0xF8, 0x04, 0x80, 0xAD, 0xF8, 0x0A, + 0x60, 0x03, 0x95, 0x42, 0x68, 0x00, 0x2A, 0xE8, 0xD0, 0x01, 0xA9, 0x58, 0x46, 0x90, 0x47, 0xE4, 0xE7, 0x40, 0xF2, 0x0D, 0x44, 0xE1, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x07, 0x46, 0x40, 0x48, 0x15, 0x46, 0x0E, 0x46, 0x1C, 0x46, 0x00, 0x22, 0x40, + 0x49, 0x80, 0x1C, 0xFF, 0xF5, 0xB9, 0xFB, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x40, 0x2B, 0x46, 0x07, 0x22, 0x31, 0x46, 0x38, 0x46, 0x47, 0xF6, 0x53, 0xFA, 0xBD, 0xE8, 0xFC, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0x0E, 0x46, 0x07, 0x46, 0x37, 0x49, 0x33, + 0x48, 0x15, 0x46, 0x1C, 0x46, 0x00, 0x22, 0x24, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0xA1, 0xFB, 0x00, 0x20, 0xCD, 0xE9, 0x00, 0x40, 0x2B, 0x46, 0x0A, + 0x22, 0x31, 0x46, 0x38, 0x46, 0x47, 0xF6, 0x3B, 0xFA, 0xE6, 0xE7, 0x2D, 0xE9, 0xFF, 0x41, 0x88, 0x46, 0x8D, 0xF8, 0x04, 0x00, 0x1D, 0x46, 0x00, 0x93, 0x2A, 0x49, 0x26, 0x48, 0x16, 0x46, 0x01, 0x27, 0x13, 0x46, 0x00, 0x24, 0x8D, 0xF8, 0x05, + 0x70, 0x02, 0x22, 0x4C, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0x83, 0xFB, 0x08, 0x2E, 0x02, 0xD0, 0x0B, 0x2E, 0x08, 0xD1, 0x13, 0xE0, 0xE8, 0x07, 0x02, 0xD0, 0x8D, 0xF8, 0x08, 0x70, 0x01, 0xE0, 0x02, 0x20, 0x11, 0xE0, 0x01, 0x24, 0x1B, 0x48, 0x08, + 0x38, 0x42, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xFF, 0x81, 0xA8, 0x07, 0x01, 0xD5, 0x03, 0x20, 0x00, 0xE0, 0x04, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0xEA, 0xE7, 0x7C, 0xB5, 0x13, + 0x49, 0x05, 0x46, 0xD1, 0xE9, 0x15, 0x02, 0xCD, 0xE9, 0x00, 0x02, 0x0D, 0x48, 0x0B, 0x6D, 0x4F, 0xF4, 0xA8, 0x72, 0xA1, 0xF5, 0x80, 0x71, 0x08, 0x38, 0x47, 0xF6, 0x5A, 0xF9, 0x09, 0x4C, 0x08, 0x3C, 0x10, 0xB1, 0x65, 0x60, 0x20, 0x78, 0x7C, + 0xBD, 0x08, 0x49, 0x00, 0x22, 0x8C, 0x31, 0x03, 0x48, 0xFF, 0xF5, 0x46, 0xFB, 0xFF, 0x20, 0x20, 0x70, 0x7C, 0xBD, 0x14, 0x01, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x4C, 0xBA, 0x20, 0x00, 0x30, 0xB8, 0x20, 0x00, 0x50, 0x02, 0x80, 0x08, 0x10, + 0xB2, 0x20, 0x00, 0x10, 0xB5, 0x01, 0x24, 0x01, 0x28, 0x06, 0xD0, 0x00, 0x24, 0x22, 0x46, 0x53, 0x49, 0x54, 0x48, 0xFF, 0xF5, 0x2D, 0xFB, 0x06, 0xE0, 0x01, 0x29, 0x01, 0xD0, 0x00, 0x24, 0x02, 0xE0, 0x51, 0x49, 0x10, 0x78, 0x08, 0x70, 0x20, + 0x46, 0x10, 0xBD, 0x07, 0xB5, 0x82, 0xB0, 0x00, 0x23, 0x01, 0x22, 0xCD, 0xE9, 0x00, 0x23, 0x04, 0xAB, 0x02, 0x22, 0x47, 0xF6, 0xBC, 0xF9, 0x05, 0xB0, 0x00, 0xBD, 0x07, 0xB5, 0x48, 0x4B, 0x82, 0xB0, 0x5A, 0x78, 0x4A, 0xB1, 0x00, 0x22, 0x5A, + 0x70, 0x01, 0x23, 0xCD, 0xE9, 0x00, 0x32, 0x04, 0xAB, 0x02, 0x22, 0x47, 0xF6, 0x23, 0xF9, 0xEE, 0xE7, 0x00, 0x20, 0xEC, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x05, 0x46, 0xDD, 0xE9, 0x08, 0x67, 0x00, 0x20, 0x30, 0x80, 0x88, 0x46, 0x00, 0x93, 0x39, + 0x49, 0x3A, 0x48, 0x14, 0x46, 0x13, 0x46, 0x02, 0x22, 0x1C, 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0xF4, 0xFA, 0x02, 0x2C, 0x0A, + 0xD0, 0x34, 0x49, 0x23, 0x46, 0x01, 0x22, 0x4C, 0x31, 0x33, 0x48, 0xFF, 0xF5, 0xEB, 0xFA, 0x40, 0xF2, 0x0A, + 0x40, 0xBD, 0xE8, 0xF8, 0x83, 0x02, 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x8D, 0xF8, 0x00, 0x50, 0x2E, 0x4D, 0x01, 0x24, 0x8D, 0xF8, 0x02, 0x40, 0x6A, 0x68, 0x69, 0x46, 0x40, 0x46, 0x90, 0x47, 0xA0, 0xF5, 0x50, 0x61, 0x01, 0x39, 0x00, 0xD1, 0x6C, + 0x70, 0x3D, 0x60, 0x34, 0x80, 0xE8, 0xE7, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x26, 0x8D, 0xF8, 0x05, 0x60, 0x88, 0x46, 0x8D, 0xF8, 0x04, 0x00, 0x1D, 0x46, 0x00, 0x93, 0x1F, 0x49, 0x1F, 0x48, 0x17, 0x46, 0x13, 0x46, 0x34, 0x46, 0x02, 0x22, 0x7C, + 0x31, 0x80, 0x1C, 0xFF, 0xF5, 0xBE, 0xFA, 0x03, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x1A, 0x48, 0x42, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xE8, 0x07, 0x02, 0xD0, 0x8D, + 0xF8, 0x06, 0x60, 0xEF, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xEB, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x10, 0x48, 0xD0, 0xE9, 0x1D, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0x01, 0x46, 0x03, 0x6F, 0x70, 0x22, 0x02, 0xA8, 0x47, 0xF6, 0xA2, 0xF8, 0x50, + 0xB9, 0x07, 0x49, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x06, 0x48, 0xFF, 0xF5, 0x91, 0xFA, 0xFF, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x04, 0x48, 0x44, 0x60, 0x9D, 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x04, 0x03, 0x80, 0x08, 0x00, 0x33, 0x10, + 0x21, 0x78, 0xBB, 0x20, 0x00, 0x6C, 0xB2, 0x20, 0x00, 0x2D, 0xE9, 0xFF, 0x41, 0xC3, 0x4C, 0x0E, 0x46, 0xDD, 0xE9, 0x0A, + 0x30, 0x00, 0x25, 0x03, 0x21, 0x24, 0x68, 0x40, 0xF2, 0x0D, 0x47, 0x02, 0x2A, 0x0F, 0xD0, 0x10, 0x2A, 0x14, 0xD0, 0x0C, 0x2A, 0x29, 0xD0, 0x00, 0x93, 0x13, 0x46, 0x02, 0x22, 0xBB, 0x49, 0xBC, 0x48, 0xFF, 0xF5, 0x69, 0xFA, 0xFD, 0x1E, 0x04, + 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x81, 0x01, 0x2B, 0x2C, 0xD1, 0x58, 0xB3, 0x8D, 0xF8, 0x04, 0x10, 0x01, 0x21, 0x1C, 0xE0, 0x05, 0x2B, 0x25, 0xD1, 0x20, 0xB3, 0x8D, 0xF8, 0x04, 0x10, 0x8D, 0xF8, 0x06, 0x10, 0x01, 0x78, 0x8D, 0xF8, 0x08, + 0x10, 0x41, 0x78, 0x82, 0x78, 0x01, 0xEB, 0x02, 0x21, 0xAD, 0xF8, 0x0A, + 0x10, 0xC1, 0x78, 0x00, 0x79, 0x01, 0xEB, 0x00, 0x20, 0xAD, 0xF8, 0x0C, 0x00, 0x0A, + 0xE0, 0x01, 0x2B, 0x0E, 0xD1, 0x68, 0xB1, 0x8D, 0xF8, 0x04, 0x10, 0x02, 0x21, 0x8D, 0xF8, 0x06, 0x10, 0x00, 0x78, 0x8D, 0xF8, 0x08, 0x00, 0x00, 0x2C, 0xD0, 0xD0, 0x01, 0xA9, 0x30, 0x46, 0xA0, 0x47, 0xCC, 0xE7, 0x3D, 0x46, 0xCA, 0xE7, 0x2D, + 0xE9, 0xFF, 0x4F, 0x87, 0xB0, 0x4F, 0xF0, 0x00, 0x0A, + 0xDD, 0xE9, 0x14, 0x54, 0x9C, 0x4E, 0xDF, 0xF8, 0x64, 0x82, 0x57, 0x46, 0x4F, 0xF0, 0x06, 0x09, 0x0A, + 0x2A, 0x1A, 0xD0, 0x08, 0xDC, 0x04, 0x2A, 0x18, 0xD0, 0x4F, 0xF0, 0x04, 0x09, 0x06, 0x2A, 0x30, 0xD0, 0x08, 0x2A, 0x08, 0xD1, 0x46, 0xE0, 0x42, 0xF2, 0x90, 0x70, 0x4F, 0xF0, 0x0C, 0x0B, 0x0E, 0x2A, 0x5A, 0xD0, 0x12, 0x2A, 0x7D, 0xD0, 0x8E, + 0x49, 0x13, 0x46, 0x01, 0x22, 0x3C, 0x31, 0x30, 0x46, 0xFF, 0xF5, 0x0B, 0xFA, 0x40, 0xF2, 0x0A, + 0x4A, 0xE2, 0xE0, 0x88, 0x49, 0x4F, 0xF4, 0x00, 0x70, 0x0C, 0x31, 0x43, 0xF6, 0xEE, 0xFC, 0x85, 0x4A, 0x00, 0x20, 0x69, 0x46, 0x0C, 0x32, 0xC0, 0xF1, 0x05, 0x03, 0xD3, 0x5C, 0x0B, 0x54, 0x40, 0x1C, 0x06, 0x28, 0xF8, 0xDB, 0x00, 0x99, 0xC8, + 0xF8, 0x0C, 0x10, 0xBD, 0xF8, 0x04, 0x10, 0xA8, 0xF8, 0x10, 0x10, 0x22, 0x60, 0xA5, 0xF8, 0x00, 0x90, 0xC6, 0xE0, 0x42, 0xF2, 0x92, 0x70, 0x04, 0xF6, 0xAB, 0xF8, 0x79, 0x49, 0x83, 0x46, 0x03, 0x46, 0x01, 0x22, 0x6C, 0x31, 0x30, 0x46, 0xFF, + 0xF5, 0xE0, 0xF9, 0x75, 0x49, 0xDB, 0xF8, 0x60, 0x30, 0x01, 0x22, 0x80, 0x31, 0x30, 0x46, 0xC8, 0xF8, 0x04, 0x30, 0xFF, 0xF5, 0xD6, 0xF9, 0x6F, 0x48, 0x00, 0x1D, 0x17, 0xE0, 0x42, 0xF2, 0x93, 0x70, 0x04, 0xF6, 0x92, 0xF8, 0x6C, 0x49, 0x83, + 0x46, 0x03, 0x46, 0x01, 0x22, 0x98, 0x31, 0x30, 0x46, 0xFF, 0xF5, 0xC7, 0xF9, 0x68, 0x49, 0xDB, 0xF8, 0x60, 0x30, 0x01, 0x22, 0xAC, 0x31, 0x30, 0x46, 0xC8, 0xF8, 0x08, 0x30, 0xFF, 0xF5, 0xBD, 0xF9, 0x62, 0x48, 0x08, 0x30, 0x20, 0x60, 0xC9, + 0xE7, 0x04, 0xF6, 0x7A, 0xF8, 0x5F, 0x4E, 0x41, 0x78, 0x14, 0x36, 0x81, 0x46, 0xB1, 0x70, 0x05, 0x21, 0x31, 0x70, 0x01, 0x21, 0x71, 0x70, 0x40, 0x78, 0xB0, 0x70, 0x49, 0x05, 0xF0, 0x78, 0x91, 0xF8, 0x14, 0x13, 0x40, 0xF0, 0x01, 0x00, 0x49, + 0x09, 0x61, 0xF3, 0x41, 0x00, 0x20, 0xF0, 0x08, 0x00, 0x40, 0xF0, 0x04, 0x00, 0xF0, 0x70, 0x04, 0xF6, 0x8E, 0xF8, 0xF1, 0x78, 0x60, 0xF3, 0x04, 0x11, 0xF1, 0x70, 0x4F, 0xF4, 0x00, 0x60, 0xB0, 0x80, 0x00, 0xE0, 0x13, 0xE0, 0x04, 0xF6, 0x83, + 0xF8, 0x68, 0xB1, 0x4F, 0x49, 0xB1, 0xEB, 0x09, 0x2F, 0x02, 0xD1, 0x4F, 0xF4, 0xA2, 0x60, 0x01, 0xE0, 0x4F, 0xF4, 0x22, 0x60, 0xB0, 0x60, 0x26, 0x60, 0xA5, 0xF8, 0x00, 0xB0, 0x5C, 0xE0, 0x4F, 0xF4, 0x7F, 0x60, 0xF7, 0xE7, 0x04, 0xF6, 0x40, + 0xF8, 0x43, 0x49, 0x07, 0x46, 0x03, 0x46, 0x01, 0x22, 0xC0, 0x31, 0x42, 0x48, 0xFF, 0xF5, 0x75, 0xF9, 0x3E, 0x4E, 0x20, 0x36, 0x17, 0xB1, 0xD7, 0xF8, 0x94, 0x01, 0x30, 0x60, 0x04, 0xF6, 0x5F, 0xF8, 0xE8, 0xB1, 0x42, 0xF2, 0x92, 0x70, 0x04, + 0xF6, 0x2B, 0xF8, 0x08, 0xB1, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x93, 0x70, 0x04, 0xF6, 0x24, 0xF8, 0x78, 0xB1, 0x00, 0x6E, 0xB0, 0x60, 0x71, 0x68, 0xCD, 0xE9, 0x00, 0x10, 0x32, 0x49, 0x03, 0x22, 0xD8, 0x31, 0x32, 0x48, 0x33, 0x68, 0xFF, + 0xF5, 0x54, 0xF9, 0x26, 0x60, 0xA5, 0xF8, 0x00, 0xB0, 0x24, 0xE0, 0xB0, 0x68, 0xEF, 0xE7, 0x42, 0xF2, 0x91, 0x70, 0x04, 0xF6, 0x0D, 0xF8, 0x08, 0xB1, 0x00, 0x6E, 0x70, 0x60, 0x42, 0xF2, 0x92, 0x70, 0x04, 0xF6, 0x06, 0xF8, 0x08, 0xB1, 0x00, + 0x6E, 0xB0, 0x60, 0x42, 0xF2, 0x93, 0x70, 0x03, 0xF6, 0xFF, 0xFF, 0x00, 0xB3, 0x00, 0x6E, 0xF0, 0x60, 0xD6, 0xE9, 0x01, 0x12, 0x00, 0x91, 0xCD, 0xE9, 0x01, 0x20, 0x04, 0x22, 0x21, 0x49, 0x1F, 0x48, 0x33, 0x68, 0xFF, 0xF5, 0x2E, 0xF9, 0x10, + 0x20, 0x26, 0x60, 0x28, 0x80, 0x02, 0x20, 0x8D, 0xF8, 0x0C, 0x00, 0x8D, 0xF8, 0x0E, 0x90, 0x01, 0x27, 0xD8, 0xF8, 0x00, 0x20, 0x1A, 0xB1, 0x17, 0xB1, 0x03, 0xA9, 0x08, 0x98, 0x90, 0x47, 0x0B, 0xB0, 0x50, 0x46, 0xBD, 0xE8, 0xF0, 0x8F, 0xF0, + 0x68, 0xDE, 0xE7, 0x3E, 0xB5, 0x04, 0x46, 0x14, 0x48, 0xD0, 0xE9, 0x06, 0x12, 0xCD, 0xE9, 0x00, 0x12, 0xA0, 0xF5, 0x00, 0x71, 0x43, 0x69, 0x4F, 0xF4, 0x05, 0x72, 0x02, 0xA8, 0x46, 0xF6, 0x11, 0xFF, 0x20, 0xB1, 0x08, 0x48, 0x04, 0x60, 0x9D, + 0xF8, 0x08, 0x00, 0x3E, 0xBD, 0x09, 0x49, 0x07, 0x48, 0x9D, 0xF8, 0x08, 0x30, 0x01, 0x22, 0x44, 0x31, 0x80, 0x1E, 0xFF, 0xF5, 0xFA, 0xF8, 0xFF, 0x20, 0x3E, 0xBD, 0x00, 0x00, 0x80, 0xBB, 0x20, 0x00, 0xFC, 0x07, 0x80, 0x08, 0x02, 0x33, 0x10, + 0x21, 0x00, 0x00, 0x20, 0x80, 0x04, 0x09, 0x80, 0x08, 0xF8, 0xB4, 0x20, 0x00, 0x2D, 0xE9, 0xF7, 0x4F, 0x86, 0xB0, 0x00, 0x24, 0x03, 0x94, 0x10, 0x20, 0x8D, 0xF8, 0x0C, 0x00, 0xDF, 0xF8, 0x24, 0x94, 0x0A, + 0x20, 0x96, 0x46, 0x04, 0x94, 0x8D, 0xF8, 0x0D, 0x00, 0x4F, 0xF4, 0x00, 0x62, 0x01, 0x26, 0x07, 0x27, 0xDF, 0xF8, 0x0C, 0xB4, 0xD9, 0xF8, 0x14, 0x00, 0x25, 0x46, 0xA9, 0xF6, 0x14, 0x0A, + 0x91, 0x42, 0x20, 0xD9, 0xCD, 0xE9, 0x00, 0x20, 0x0B, 0x46, 0x4C, 0x46, 0x03, 0x22, 0xFE, 0x49, 0x58, 0x46, 0xFF, 0xF5, 0xC6, 0xF8, 0xAA, 0xF8, 0x02, 0x50, 0x02, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x9A, 0xF8, 0x01, 0x10, 0x32, 0xE0, 0xBA, 0xF8, 0x02, 0x30, 0x8B, 0x42, 0x06, 0xD0, 0xD9, 0xF8, + 0x0C, 0x20, 0x00, 0xEB, 0x03, 0x0C, 0xC8, 0x46, 0x94, 0x45, 0x75, 0xD1, 0x72, 0x46, 0xD0, 0x46, 0x19, 0x46, 0xDA, 0xF8, 0x10, 0x00, 0x3E, 0xF6, 0x22, 0xFF, 0x28, 0xB3, 0xE6, 0x49, 0x4C, 0x46, 0x01, 0x22, 0x48, 0x31, 0x58, 0x46, 0xD9, 0xF8, + 0x14, 0x30, 0xFF, 0xF5, 0x92, 0xF8, 0xA8, 0xF8, 0x02, 0x50, 0x05, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0x60, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x10, 0x20, 0x02, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x20, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x98, 0xF8, 0x01, 0x10, 0x03, 0xAB, 0x04, 0x22, 0x06, 0x98, 0x46, 0xF6, 0x1B, 0xFF, 0x09, 0xB0, 0xBD, 0xE8, 0xF0, 0x8F, + 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0x82, 0x46, 0xB8, 0xF8, 0x02, 0x00, 0x00, 0x1B, 0x10, 0x28, 0x11, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0xCB, 0x48, 0x08, 0xF6, + 0x41, 0xF9, 0xD8, 0xF8, 0x10, 0x00, 0x20, 0x44, 0x01, 0x46, 0x00, 0xF6, 0x33, 0xFA, 0x10, 0x34, 0xA4, 0xB2, 0xE8, 0xE7, 0x01, 0xF0, 0x00, 0xFA, 0xB9, 0xF8, 0x04, 0x00, 0x44, 0x46, 0xD9, 0xF8, 0x14, 0x10, 0xB8, 0xF8, 0x02, 0x20, 0xD8, 0xF8, + 0x10, 0x30, 0x01, 0xF0, 0x54, 0xFB, 0x03, 0x00, 0x4F, 0xF4, 0x80, 0x5A, 0x19, 0xD0, 0xBC, 0x49, 0x01, 0x22, 0x7C, 0x31, 0x58, 0x46, 0xFF, 0xF5, 0x40, 0xF8, 0xC8, 0x46, 0xB9, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x61, 0x68, 0x01, 0xF0, 0x89, 0xFA, + 0x4F, 0xF0, 0x08, 0x09, 0xD0, 0xB1, 0x65, 0x80, 0xB3, 0x49, 0x63, 0x68, 0x01, 0x22, 0x45, 0x46, 0xB4, 0x31, 0xC8, 0xF8, 0x14, 0x30, 0x2E, 0xE0, 0x58, 0xE0, 0x62, 0x88, 0xD9, 0xF8, 0x14, 0x00, 0x10, 0x44, 0xC9, 0xF8, 0x14, 0x00, 0x61, 0x68, + 0x42, 0x1A, 0x52, 0x45, 0x02, 0xD3, 0x01, 0xF5, 0x80, 0x51, 0x61, 0x60, 0x65, 0x80, 0x8D, 0xF8, 0x0E, 0x60, 0x22, 0xE0, 0xD8, 0xF8, 0x14, 0x00, 0x61, 0x68, 0x40, 0x1A, 0x50, 0x45, 0x32, 0xD9, 0xA3, 0x49, 0xA1, 0x48, 0x00, 0x22, 0xF4, 0x31, + 0x80, 0x1C, 0xFF, 0xF5, 0x0E, 0xF8, 0x61, 0x68, 0xB8, 0xF8, 0x04, 0x00, 0x52, 0x46, 0x01, 0xF5, 0x80, 0x51, 0x01, 0xF0, 0x56, 0xFA, 0x10, 0xB3, 0x65, 0x80, 0x63, 0x68, 0x9C, 0x49, 0x45, 0x46, 0x01, 0x22, 0xC8, 0xF8, 0x14, 0x30, 0x58, 0x46, + 0xFE, 0xF5, 0xFB, 0xFF, 0x8D, 0xF8, 0x0E, 0x90, 0x68, 0x69, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x06, 0x98, 0x46, 0xF6, 0x88, 0xFE, 0x01, 0xF0, 0xA6, 0xF9, 0x69, 0xE7, 0x65, 0x80, + 0x8B, 0x49, 0x87, 0x48, 0x63, 0x68, 0x45, 0x46, 0x01, 0x22, 0x40, 0x31, 0x80, 0x1C, 0xC8, 0xF8, 0x14, 0x30, 0xFE, 0xF5, 0xD6, 0xFF, 0x8D, 0xF8, 0x0E, 0x70, 0xD9, 0xE7, 0xCD, 0xE9, 0x00, 0x30, 0x0B, 0x46, 0x83, 0x49, 0x02, 0x92, 0x54, 0x46, + 0x04, 0x22, 0x70, 0x31, 0x58, 0x46, 0xFE, 0xF5, 0xC8, 0xFF, 0x65, 0x80, 0x06, 0x20, 0x8D, 0xF8, 0x0E, 0x00, 0xD8, 0xF8, 0x14, 0x00, 0x8D, 0xF8, 0x0F, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x10, 0x10, 0x01, 0x0C, 0x00, 0x0E, 0xCD, 0xE9, 0x00, 0x76, 0x8D, 0xF8, 0x11, 0x10, 0x8D, 0xF8, 0x12, 0x00, 0x03, 0xAB, 0x04, 0x22, 0x61, 0x78, 0x35, 0xE7, 0x3E, 0xB5, 0x70, 0x4B, 0x04, 0x46, 0x58, 0x7E, 0x01, 0x28, 0x1D, 0xD1, + 0x00, 0x22, 0x5A, 0x76, 0x02, 0x92, 0x10, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x07, 0x20, 0x8D, 0xF8, 0x09, 0x00, 0x8D, 0xF8, 0x0A, + 0x10, 0x0B, 0x46, 0x6A, 0x49, 0x66, 0x48, 0x01, 0x22, 0xD8, 0x31, 0x80, 0x1C, 0xFE, 0xF5, 0x98, 0xFF, 0x01, 0x21, 0x03, 0x20, 0xCD, 0xE9, 0x00, 0x01, 0x66, 0x48, 0x02, 0xAB, 0x04, 0x22, 0x41, 0x78, 0x20, 0x46, 0x46, 0xF6, 0x30, 0xFE, 0x3E, + 0xBD, 0x3E, 0xB5, 0x05, 0x46, 0x00, 0x20, 0x02, 0x90, 0x5C, 0x48, 0x80, 0x88, 0x01, 0xF0, 0x35, 0xFB, 0x04, 0x46, 0x03, 0x46, 0x58, 0x48, 0x01, 0x22, 0x5D, 0x49, 0x80, 0x1C, 0xFE, 0xF5, 0x7C, 0xFF, 0x01, 0x20, 0x14, 0xB1, 0x8D, 0xF8, 0x0A, + 0x00, 0x02, 0xE0, 0x05, 0x21, 0x8D, 0xF8, 0x0A, + 0x10, 0x10, 0x21, 0x8D, 0xF8, 0x08, 0x10, 0x03, 0x21, 0xCD, 0xE9, 0x00, 0x10, 0x53, 0x48, 0x8D, 0xF8, 0x09, 0x10, 0x02, 0xAB, 0x41, 0x78, 0x04, 0x22, 0x28, 0x46, 0x46, 0xF6, 0x08, 0xFE, 0x3E, 0xBD, 0x2D, 0xE9, 0xF7, 0x4F, 0x8C, 0xB0, 0x00, + 0x20, 0x05, 0x90, 0x06, 0x90, 0x07, 0x90, 0x92, 0xF8, 0x00, 0x80, 0x0E, 0x46, 0x00, 0x91, 0x49, 0x49, 0x43, 0x48, 0x15, 0x46, 0x57, 0x1C, 0x43, 0x46, 0x02, 0x22, 0xCD, 0xF8, 0x20, 0x80, 0x40, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0x4D, 0xFF, 0xDF, + 0xF8, 0x08, 0x91, 0x01, 0x24, 0x4F, 0xF0, 0x10, 0x0A, + 0x4F, 0xF0, 0x03, 0x0B, 0xB8, 0xF1, 0x0D, 0x0F, 0x0D, 0xD2, 0x08, 0x98, 0x58, 0xB1, 0xDF, 0xF8, 0xE0, 0x80, 0x0C, 0x28, 0x6A, 0xD2, 0xDF, 0xE8, 0x00, 0xF0, 0x69, 0x0D, 0xDD, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0x69, 0xF8, 0xF7, 0xF6, 0x8D, 0xF8, + 0x14, 0xA0, 0x08, 0x98, 0x8D, 0xF8, 0x15, 0x00, 0xFF, 0x20, 0x96, 0xE0, 0x11, 0x2E, 0x6A, 0xD1, 0x4F, 0xF4, 0x00, 0x16, 0x96, 0xF8, 0x14, 0x03, 0x80, 0x06, 0x26, 0xD5, 0x3A, 0x46, 0x10, 0x21, 0x30, 0x48, 0xFF, 0xF5, 0x77, 0xF9, 0x27, 0x4D, + 0x2D, 0x49, 0x03, 0x46, 0xED, 0x1C, 0x01, 0x22, 0x84, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0x18, 0xFF, 0x96, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x23, 0x48, 0x07, 0xF6, 0xF0, 0xFF, 0x39, 0x46, 0x08, 0x46, 0x00, 0xF6, + 0xE4, 0xF8, 0x3A, 0x46, 0x10, 0x21, 0x22, 0x48, 0xFF, 0xF5, 0x5C, 0xF9, 0x20, 0x49, 0x03, 0x46, 0x01, 0x22, 0xAC, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0xFF, 0xFE, 0x3B, 0x78, 0x0A, + 0x93, 0xB8, 0x78, 0xFA, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x02, 0x20, 0x86, 0xB2, 0x38, 0x79, 0x7A, 0x79, 0x0D, 0xF1, 0x08, 0x0C, 0x00, 0xEB, 0x02, 0x20, 0x80, 0xB2, 0x09, 0x90, 0xB8, 0x79, 0xFA, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x85, 0xB2, 0x38, + 0x7A, 0x7A, 0x7A, 0x00, 0xEB, 0x02, 0x20, 0xBA, 0x7A, 0xFF, 0x7A, 0x12, 0x04, 0x02, 0xEB, 0x07, 0x62, 0xCD, 0xE9, 0x00, 0x16, 0x87, 0x18, 0x09, 0x98, 0x0B, 0x49, 0x8C, 0xE8, 0xA1, 0x00, 0x04, 0x48, 0x06, 0x22, 0xD4, 0x31, 0xC0, 0x1C, 0xFE, + 0xF5, 0xD4, 0xFE, 0x0A, + 0x9B, 0x11, 0xE0, 0x4F, 0xE2, 0x00, 0x31, 0x10, 0x21, 0xC8, 0xC3, 0x20, 0x00, 0x70, 0x09, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x94, 0x0A, + 0x80, 0x08, 0xB4, 0xBB, 0x20, 0x00, 0xA4, 0x0B, 0x80, 0x08, 0x00, 0x00, 0x50, 0x21, 0xF2, 0xE1, 0x88, 0xF8, 0x00, 0x30, 0xA8, 0xF8, 0x02, 0x60, 0x09, 0x98, 0xA8, 0xF8, 0x04, 0x00, 0xA8, 0xF8, 0x06, 0x50, 0xC8, 0xF8, 0x08, 0x70, 0x07, 0xF5, + 0x80, 0x67, 0xC8, 0xF8, 0x0C, 0x70, 0x05, 0x2B, 0x02, 0xD0, 0x01, 0x22, 0xFD, 0x49, 0x0C, 0xE0, 0xA0, 0xF5, 0x1C, 0x51, 0x90, 0x39, 0x0A, + 0x29, 0x1C, 0xD3, 0xA0, 0xF5, 0x7F, 0x41, 0xFE, 0x39, 0x18, 0xD0, 0xF7, 0x49, 0x01, 0x22, 0x03, 0x46, 0x30, 0x39, 0xF6, 0x48, 0xFE, 0xF5, 0x9C, 0xFE, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, + 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x46, 0xF6, 0x2F, 0xFD, 0x0F, 0xB0, 0x12, 0xE6, 0x01, 0xF0, 0x33, 0xF8, 0xB8, 0xF8, 0x04, 0x00, 0xEB, 0x4B, 0x0C, 0x22, 0x00, 0x21, 0x01, 0xF0, 0x8B, 0xF9, 0x05, + 0x46, 0x01, 0xF0, 0x41, 0xF8, 0xC5, 0xB1, 0x2A, 0x46, 0xE7, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFE, 0xF5, 0x20, 0xFE, 0xB8, 0xF8, 0x04, 0x00, 0x01, 0xF0, 0x08, 0xFA, 0x3E, 0xF6, 0xCB, 0xFC, 0xDE, 0x49, 0x00, 0x22, 0x54, 0x39, 0xEC, 0x48, 0xFE, + 0xF5, 0x6B, 0xFE, 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x40, 0x8D, 0xF8, 0x16, 0x40, 0x01, 0xE1, 0xD8, 0xF8, 0x14, 0x00, 0x0C, 0x30, 0xC8, 0xF8, 0x14, 0x00, 0xEC, 0xE7, 0x07, 0x2E, 0x04, 0xD0, 0xD4, 0x49, 0x01, 0x22, 0x33, 0x46, 0x70, + 0x31, 0x92, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xA8, 0xF8, 0x04, 0x30, 0xB8, 0x78, 0xFA, 0x78, 0x7C, 0x79, 0x00, 0xEB, 0x02, 0x20, 0x3A, 0x79, 0x12, 0x04, 0x02, 0xEB, 0x04, 0x62, 0x80, 0x18, 0x07, 0xE0, 0x7F, + 0xE1, 0x5D, 0xE1, 0x2E, 0xE1, 0xCE, 0xE0, 0x75, 0xE0, 0x53, 0xE0, 0x4A, 0xE0, 0x12, 0xE0, 0xC8, 0xF8, 0x14, 0x00, 0x01, 0xD0, 0x0C, 0x28, 0x04, 0xD1, 0x00, 0x21, 0xA9, 0xF8, 0x02, 0x10, 0xC9, 0xF8, 0x04, 0x10, 0x00, 0x90, 0xBF, 0x49, 0xBF, + 0x48, 0x02, 0x22, 0x30, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0x2B, 0xFE, 0x5C, 0xE1, 0x03, 0x2E, 0x03, 0xD0, 0x33, 0x46, 0x01, 0x22, 0xC9, 0x49, 0x5F, 0xE0, 0x38, 0x78, 0x79, 0x78, 0xB8, 0x4D, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0xC5, 0x49, 0xED, + 0x1C, 0x44, 0x46, 0xA8, 0xF8, 0x04, 0x30, 0x01, 0x22, 0x64, 0x39, 0x28, 0x46, 0xFE, 0xF5, 0x14, 0xFE, 0x4F, 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x7A, 0x03, 0xC0, 0x06, 0xE2, 0xD5, 0xE0, 0x68, 0xB0, 0xF5, 0x80, 0x1F, 0xDE, 0xD9, 0x6F, 0xF0, 0x7F, + 0x61, 0x08, 0x44, 0xC0, 0xF3, 0x07, 0x50, 0x09, 0x17, 0x01, 0xEB, 0x40, 0x11, 0x8C, 0xB2, 0xB6, 0x49, 0x83, 0x00, 0x02, 0x22, 0x40, 0x39, 0x28, 0x46, 0x00, 0x94, 0xFE, 0xF5, 0xF9, 0xFD, 0x03, 0x22, 0x0F, 0x21, 0x20, 0x46, 0x08, 0xF6, 0x46, + 0xFD, 0x25, 0xE1, 0xAF, 0x49, 0xA0, 0x48, 0x00, 0x22, 0x2C, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0xEC, 0xFD, 0x1D, 0xE1, 0xAB, 0x49, 0x00, 0x22, 0x4C, 0x31, 0x9B, 0x48, 0xFE, 0xF5, 0xE5, 0xFD, 0xB8, 0xF8, 0x04, 0x00, 0xA0, 0xF5, 0x1C, 0x51, 0x90, + 0x39, 0x0A, + 0x29, 0x0A, + 0xD2, 0x03, 0xF6, 0xED, 0xFC, 0x38, 0xB1, 0x81, 0x78, 0x09, 0x06, 0x04, 0xD4, 0x20, 0xF0, 0x7F, 0x41, 0x02, 0x20, 0x03, 0xF6, 0xB7, 0xF8, 0x4F, 0xF4, 0xFA, 0x60, 0x1D, 0xF6, 0x58, 0xFC, 0xD4, 0x21, 0x03, 0x20, 0xFF, 0xF7, 0x6B, 0xF8, 0xFC, + 0xE0, 0x03, 0x2E, 0x07, 0xD0, 0x9A, 0x49, 0x01, 0x22, 0x33, 0x46, 0xE4, 0x31, 0x89, 0x48, 0xFE, 0xF5, 0xC1, 0xFD, 0xF2, 0xE0, 0x38, 0x78, 0x79, 0x78, 0x94, 0x4F, 0x00, 0xEB, 0x01, 0x20, 0x83, 0xB2, 0x93, 0x49, 0x45, 0x46, 0xA8, 0xF8, 0x04, + 0x30, 0x01, 0x22, 0x68, 0x31, 0x38, 0x46, 0xFE, 0xF5, 0xB1, 0xFD, 0xA8, 0x88, 0x80, 0x4E, 0xA0, 0xF5, 0x7F, 0x41, 0x10, 0x36, 0xFE, 0x39, 0x2E, 0xD0, 0x32, 0x1D, 0x31, 0x46, 0x3E, 0xF6, 0xF1, 0xFA, 0x00, 0x20, 0x68, 0x61, 0x00, 0x90, 0x87, + 0x49, 0x02, 0x22, 0x9C, 0x31, 0x38, 0x46, 0x2B, 0x69, 0xFE, 0xF5, 0x9C, 0xFD, 0x8D, 0xF8, 0x14, 0xA0, 0x06, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x28, 0x69, 0x8D, 0xF8, 0x17, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x18, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x19, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1A, 0x00, 0x68, 0x69, 0x8D, 0xF8, 0x1B, 0x00, 0x01, 0x0A, + 0x8D, 0xF8, 0x1C, 0x10, 0x01, 0x0C, 0x8D, 0xF8, 0x1D, 0x10, 0x00, 0x0E, 0x8D, 0xF8, 0x1E, 0x00, 0x0B, 0x20, 0xF4, 0xE0, 0x05, 0x20, 0x02, 0xF6, 0xE9, 0xFF, 0x32, 0x46, 0x04, 0x21, 0x60, 0x30, 0x03, 0xF6, 0xC1, 0xFA, 0xCB, 0xE7, 0x07, 0x20, + 0x8D, 0xF8, 0x14, 0xA0, 0x8D, 0xF8, 0x15, 0x00, 0x09, 0x2E, 0x0D, 0xD0, 0x33, 0x46, 0x01, 0x22, 0x6B, 0x49, 0x5B, 0x48, 0xFE, 0xF5, 0x65, 0xFD, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xCD, 0xE9, 0x00, 0xB4, 0x05, 0xAB, 0x04, 0x22, 0x43, 0xE0, + 0x98, 0xF8, 0x19, 0x00, 0xC2, 0x46, 0x30, 0xB1, 0x63, 0x49, 0x00, 0x22, 0xA0, 0x39, 0x52, 0x48, 0xFE, 0xF5, 0x53, 0xFD, 0x26, 0xE0, 0x68, 0x78, 0xA9, 0x78, 0x00, 0xEB, 0x01, 0x20, 0x87, 0xB2, 0xE8, 0x78, 0x29, 0x79, 0x00, 0xEB, 0x01, 0x20, + 0x86, 0xB2, 0x68, 0x79, 0xA9, 0x79, 0x32, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x1F, 0xFA, 0x80, 0xF8, 0xE8, 0x79, 0x29, 0x7A, 0x43, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x85, 0xB2, 0x6F, 0xF0, 0x01, 0x00, 0x00, 0xEB, 0x46, 0x01, 0x00, 0xEB, 0x47, 0x00, + 0x89, 0xB2, 0x80, 0xB2, 0x00, 0x95, 0xCD, 0xE9, 0x01, 0x01, 0x39, 0x46, 0x00, 0x20, 0x44, 0xF6, 0x42, 0xFE, 0x18, 0xB1, 0x58, 0x46, 0x8D, 0xF8, 0x16, 0xB0, 0xA0, 0xE0, 0x8A, 0xF8, 0x19, 0x40, 0x00, 0x96, 0x49, 0x49, 0x38, 0x48, 0xCD, 0xE9, + 0x01, 0x85, 0x3B, 0x46, 0x04, 0x22, 0x5C, 0x39, 0x80, 0x1C, 0xFE, 0xF5, 0x1A, 0xFD, 0x4B, 0xE0, 0x99, 0xF8, 0x01, 0x10, 0x0C, 0x98, 0x46, 0xF6, 0xB7, 0xFB, 0x45, 0xE0, 0x31, 0x49, 0x40, 0xF2, 0x75, 0x20, 0x18, 0x31, 0x0C, 0x9A, 0x44, 0xF6, + 0x1C, 0xFD, 0x4F, 0xF4, 0x00, 0x60, 0x00, 0x90, 0x3B, 0x49, 0x2B, 0x48, 0x45, 0x46, 0x98, 0xF8, 0x18, 0x30, 0x02, 0x22, 0x3C, 0x31, 0xC0, 0x1C, 0xFE, 0xF5, 0xFF, 0xFC, 0x89, 0xF8, 0x00, 0x40, 0x8D, 0xF8, 0x14, 0xA0, 0x09, 0x21, 0x8D, 0xF8, + 0x15, 0x10, 0x8D, 0xF8, 0x16, 0x40, 0x00, 0x21, 0x08, 0x22, 0x8D, 0xF8, 0x17, 0x10, 0x8D, 0xF8, 0x18, 0x20, 0x2A, 0x7E, 0x8D, 0xF8, 0x19, 0x20, 0x8D, 0xF8, 0x1A, 0x10, 0x07, 0x21, 0xCD, 0xE9, 0x00, 0x14, 0x05, 0xAB, 0x04, 0x22, 0xCB, 0xE7, + 0x38, 0x78, 0x79, 0x78, 0x02, 0x22, 0x00, 0xEB, 0x01, 0x20, 0x85, 0xB2, 0xB8, 0x78, 0xF9, 0x78, 0x2B, 0x46, 0x00, 0xEB, 0x01, 0x20, 0x84, 0xB2, 0x23, 0x49, 0x13, 0x48, 0x7C, 0x31, 0xC0, 0x1C, 0x00, 0x94, 0xFE, 0xF5, 0xD2, 0xFC, 0x22, 0x46, + 0x29, 0x46, 0x0C, 0x98, 0xFF, 0xF7, 0xE2, 0xFB, 0x1E, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x3F, 0xF4, 0x3C, 0xAE, 0x08, 0x99, 0x0C, 0x98, 0x90, 0x47, 0x37, 0xE6, 0x8D, 0xF8, 0x14, 0xA0, 0x0B, 0x20, 0x8D, 0xF8, 0x15, 0x00, 0x02, 0xA9, 0x42, 0xF2, + 0x90, 0x70, 0x3E, 0xF6, 0xE0, 0xF9, 0x20, 0xB1, 0x02, 0x20, 0x8D, 0xF8, 0x16, 0x00, 0xFF, 0x20, 0x2A, 0xE0, 0x25, 0xE0, 0x44, 0x0D, 0x80, 0x08, 0x00, 0x31, 0x10, 0x21, 0xC8, 0xC3, 0x20, 0x00, 0x44, 0x46, 0x55, 0x5F, 0x4F, 0x50, 0x43, 0x4F, + 0x44, 0x45, 0x5F, 0x53, 0x54, 0x41, 0x52, 0x54, 0x5F, 0x44, 0x46, 0x55, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x00, + 0x02, 0x33, 0x10, 0x21, 0x50, 0x0E, 0x80, 0x08, 0x08, 0x10, 0x80, 0x08, 0x60, 0xB9, 0x20, 0x00, 0x9D, 0xF8, 0x08, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x8D, 0xF8, 0x17, 0x00, 0x04, 0x20, 0xCD, 0xE9, 0x00, 0x04, 0x05, 0xAB, 0x04, 0x22, 0x67, 0xE7, + 0x03, 0x46, 0x01, 0x22, 0x88, 0x49, 0x89, 0x48, 0xB8, 0xE6, 0x2D, 0xE9, 0xFE, 0x4F, 0x88, 0x4F, 0x05, 0x46, 0xA7, 0xF6, 0x14, 0x04, 0x88, 0x46, 0x78, 0x69, 0x61, 0x88, 0xFA, 0x68, 0x8D, 0xE8, 0x07, 0x00, 0x81, 0x49, 0x2B, 0x46, 0x04, 0x22, + 0x3C, 0x31, 0x80, 0x48, 0xFE, 0xF5, 0x69, 0xFC, 0xDF, 0xF8, 0xF8, 0xA1, 0x20, 0x78, 0xAA, 0xF1, 0x03, 0x0A, + 0xC0, 0xB1, 0x60, 0x88, 0x43, 0x19, 0x4F, 0xF4, 0x00, 0x60, 0x83, 0x42, 0x08, 0xD9, 0x77, 0x49, 0x00, 0x90, 0x02, 0x22, 0xAC, 0x31, 0x50, 0x46, 0xFE, 0xF5, 0x56, 0xFC, 0x3E, 0xF6, 0xAE, 0xFA, 0x61, 0x88, 0x20, 0x69, 0x2A, 0x46, 0x08, 0x44, + 0x41, 0x46, 0x50, 0xF6, 0x6B, 0xFE, 0x60, 0x88, 0x28, 0x44, 0x70, 0xE0, 0x60, 0x88, 0x4F, 0xF4, 0xFF, 0x66, 0x43, 0x19, 0xB3, 0x42, 0x07, 0xD9, 0x02, 0x22, 0x6D, 0x49, 0x50, 0x46, 0x00, 0x96, 0xFE, 0xF5, 0x3E, 0xFC, 0x3E, 0xF6, 0x96, 0xFA, + 0x60, 0x88, 0x79, 0x69, 0x28, 0x44, 0xFB, 0x68, 0x08, 0x44, 0xA1, 0x46, 0x98, 0x42, 0x07, 0xD9, 0x66, 0x49, 0x01, 0x22, 0x68, 0x31, 0x50, 0x46, 0xFE, 0xF5, 0x2E, 0xFC, 0x3E, 0xF6, 0x86, 0xFA, 0x10, 0x2D, 0x1D, 0xD3, 0x4F, 0xF4, 0x00, 0x10, + 0x90, 0xF8, 0x14, 0x13, 0x89, 0x06, 0x17, 0xD5, 0xDF, 0xF8, 0x7C, 0xB1, 0x00, 0x24, 0x82, 0x46, 0x28, 0x1B, 0x10, 0x28, 0x10, 0xDB, 0x9A, 0xF8, 0x14, 0x03, 0x02, 0x22, 0xC0, 0xF3, 0x80, 0x13, 0x00, 0x21, 0x58, 0x46, 0x07, 0xF6, 0xF5, 0xFC, + 0x08, 0xEB, 0x04, 0x00, 0x01, 0x46, 0xFF, 0xF5, 0xE8, 0xFD, 0x10, 0x34, 0xA4, 0xB2, 0xEB, 0xE7, 0xB9, 0xF8, 0x02, 0x10, 0xD9, 0xF8, 0x10, 0x00, 0x4C, 0x46, 0x08, 0x44, 0x2A, 0x46, 0x41, 0x46, 0x50, 0xF6, 0x20, 0xFE, 0x60, 0x88, 0x28, 0x44, + 0x80, 0xB2, 0x60, 0x80, 0xB0, 0x42, 0x04, 0xD0, 0x79, 0x69, 0x01, 0x44, 0xF8, 0x68, 0x81, 0x42, 0x1E, 0xD1, 0x00, 0xF0, 0xA0, 0xFD, 0xB8, 0x88, 0x79, 0x69, 0x62, 0x88, 0x23, 0x69, 0x00, 0xF0, 0xF9, 0xFE, 0x05, 0x46, 0x00, 0xF0, 0xAF, 0xFD, + 0x65, 0xB1, 0x2A, 0x46, 0x43, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFE, 0xF5, 0x8E, 0xFB, 0xB8, 0x88, 0x00, 0xF0, 0x77, 0xFF, 0xBD, 0xE8, 0xFE, 0x4F, 0x3E, 0xF6, 0x38, 0xBA, 0x61, 0x88, 0x78, 0x69, 0x08, 0x44, 0x78, 0x61, 0x00, 0x20, 0x60, 0x80, + 0xBD, 0xE8, 0xFE, 0x8F, 0x10, 0xB5, 0x03, 0x46, 0xDD, 0xE9, 0x02, 0x01, 0x00, 0x24, 0x04, 0x2A, 0x0B, 0xD0, 0x02, 0x2A, 0x0F, 0xD0, 0x32, 0x49, 0x13, 0x46, 0x01, 0x22, 0xD0, 0x31, 0x40, 0x48, 0xFE, 0xF5, 0xC6, 0xFB, 0x40, 0xF2, 0x0A, + 0x40, 0x10, 0xBD, 0x0A, + 0x46, 0x01, 0x46, 0x18, 0x46, 0xFF, 0xF7, 0x5A, 0xFC, 0x01, 0xE0, 0xFF, 0xF7, 0x3F, 0xFF, 0x20, 0x46, 0x10, 0xBD, 0x2D, 0xE9, 0xFC, 0x41, 0x01, 0x25, 0x88, 0x46, 0x1E, 0x46, 0x8D, 0xF8, 0x05, 0x50, 0x00, 0x93, 0x24, 0x49, 0x17, 0x46, 0x8D, + 0xF8, 0x04, 0x00, 0x13, 0x46, 0x2C, 0x46, 0x02, 0x22, 0xFC, 0x31, 0x30, 0x48, 0xFE, 0xF5, 0xA6, 0xFB, 0x05, 0x2F, 0x0B, 0xD0, 0x00, 0x24, 0x2E, 0x48, 0x82, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0x00, 0x2C, 0x02, 0xD0, 0x01, 0xA9, 0x40, 0x46, 0x90, + 0x47, 0xBD, 0xE8, 0xFC, 0x81, 0xF0, 0x07, 0x8D, 0xF8, 0x05, 0x50, 0x02, 0xD0, 0x8D, 0xF8, 0x06, 0x50, 0xED, 0xE7, 0x02, 0x20, 0x8D, 0xF8, 0x06, 0x00, 0xE9, 0xE7, 0x7C, 0xB5, 0x24, 0x49, 0x05, 0x46, 0xD1, 0xE9, 0x01, 0x02, 0xCD, 0xE9, 0x00, + 0x02, 0x20, 0x48, 0x0B, 0x68, 0xA8, 0x22, 0x20, 0x49, 0x40, 0x1C, 0x46, 0xF6, 0x87, 0xF9, 0x1C, 0x4C, 0x28, 0xB1, 0x04, 0xF1, 0x14, 0x00, 0xA5, 0x60, 0x20, 0x61, 0x60, 0x78, 0x7C, 0xBD, 0x17, 0x48, 0x63, 0x78, 0x01, 0x22, 0x1A, 0x49, 0x80, + 0x1E, 0xFE, 0xF5, 0x70, 0xFB, 0xFF, 0x20, 0x60, 0x70, 0x7C, 0xBD, 0xC0, 0x10, 0x80, 0x08, 0x03, 0x31, 0x10, 0x21, 0xC8, 0xC3, 0x20, 0x00, 0xD4, 0x11, 0x80, 0x08, 0x9C, 0x03, 0x20, 0x00, 0x64, 0x66, 0x75, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x5F, 0x70, 0x61, 0x63, 0x6B, 0x65, 0x74, 0x5F, 0x72, 0x65, 0x71, 0x3A, 0x20, 0x73, 0x69, 0x6C, 0x5F, 0x64, 0x66, 0x75, 0x5F, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x65, 0x72, 0x72, + 0x6F, 0x72, 0x3D, 0x25, 0x64, 0x00, 0x00, 0x02, 0x33, 0x10, 0x21, 0xB4, 0xBB, 0x20, 0x00, 0x28, 0xB5, 0x20, 0x00, 0x4C, 0xB8, 0x20, 0x00, 0x00, 0x13, 0x80, 0x08, 0x1F, 0xB5, 0x4A, 0x20, 0x00, 0x90, 0x38, 0x4B, 0x08, 0x22, 0x20, 0x21, 0x37, + 0x48, 0x1C, 0xF6, 0x7F, 0xFD, 0x4B, 0x20, 0x00, 0x90, 0x35, 0x48, 0x33, 0x4B, 0x01, 0x22, 0x40, 0x21, 0x00, 0x1F, 0x1C, 0xF6, 0x76, 0xFD, 0x31, 0x4C, 0x20, 0x22, 0x08, 0x3C, 0xD4, 0xE9, 0x01, 0x01, 0x42, 0xF6, 0x2A, 0xFD, 0x00, 0xF0, 0x30, + 0xF9, 0x52, 0x25, 0x4F, 0xF0, 0xFF, 0x37, 0x57, 0x26, 0x00, 0x95, 0x29, 0x4B, 0x3A, 0x46, 0x03, 0xA9, 0x60, 0x68, 0x1C, 0xF6, 0x0A, + 0xFE, 0x00, 0x28, 0xF6, 0xD0, 0x9D, 0xF8, 0x0C, 0x00, 0x02, 0x28, 0x02, 0xD0, 0x42, 0xF6, 0x82, 0xFD, 0xEF, 0xE7, 0x00, 0x96, 0x21, 0x4B, 0x00, 0x22, 0x01, 0xA9, 0xA0, 0x68, 0x1C, 0xF6, 0xFA, 0xFD, 0x00, 0x28, 0xE6, 0xD0, 0xDD, 0xE9, 0x01, + 0x01, 0x00, 0xF0, 0x52, 0xFB, 0xE1, 0xE7, 0x1C, 0xB5, 0x01, 0x21, 0x88, 0x02, 0x00, 0x23, 0xAF, 0xF2, 0x83, 0x02, 0xCD, 0xE9, 0x00, 0x01, 0x18, 0x48, 0x18, 0xA1, 0x08, 0x38, 0x1D, 0xF6, 0xAC, 0xFA, 0x1C, 0xBD, 0x7C, 0xB5, 0x02, 0x22, 0x8D, + 0xF8, 0x04, 0x20, 0x13, 0x4C, 0x68, 0x22, 0x11, 0x4B, 0x00, 0x92, 0x08, 0x3C, 0x01, 0x46, 0x0E, 0x33, 0x00, 0x22, 0xA0, 0x68, 0x1C, 0xF6, 0xA6, 0xFD, 0x0F, 0x4D, 0x58, 0xB1, 0x6D, 0x20, 0x0B, 0x4B, 0x00, 0x90, 0x0E, 0x33, 0x00, 0x22, 0x01, + 0xA9, 0x60, 0x68, 0x1C, 0xF6, 0x9B, 0xFD, 0x20, 0xB1, 0x01, 0x20, 0x7C, 0xBD, 0x00, 0x22, 0x09, 0x49, 0x02, 0xE0, 0x08, 0x49, 0x00, 0x22, 0x1C, 0x31, 0x28, 0x46, 0xFE, 0xF5, 0xCC, 0xFA, 0x00, 0x20, 0x7C, 0xBD, 0x00, 0x00, 0x34, 0xB5, 0x20, + 0x00, 0xEC, 0xC3, 0x20, 0x00, 0x61, 0x70, 0x70, 0x00, 0x00, 0x30, 0x10, 0x21, 0x2C, 0x13, 0x80, 0x08, 0x00, 0xB5, 0x9D, 0xB0, 0x28, 0x22, 0x7D, 0x49, 0x68, 0x46, 0x50, 0xF6, 0x5D, 0xFD, 0x00, 0x20, 0x8D, 0xF8, 0x44, 0x00, 0x07, 0x21, 0x8D, + 0xF8, 0x40, 0x00, 0x8D, 0xF8, 0x30, 0x10, 0x0B, 0x90, 0x4F, 0xF4, 0xB0, 0x71, 0xAD, 0xF8, 0x68, 0x10, 0x4F, 0xF4, 0xC0, 0x71, 0xAD, 0xF8, 0x6C, 0x10, 0x01, 0x21, 0x8D, 0xF8, 0x3C, 0x00, 0x0A, + 0x90, 0xAD, 0xF8, 0x38, 0x00, 0x8D, 0xF8, 0x34, 0x00, 0x03, 0x22, 0x8D, 0xF8, 0x48, 0x10, 0xAD, 0xF8, 0x4C, 0x10, 0x8D, 0xF8, 0x50, 0x20, 0x8D, 0xF8, 0x54, 0x00, 0x8D, 0xF8, 0x58, 0x00, 0x17, 0x90, 0x8D, 0xF8, 0x60, 0x00, 0xAD, 0xF8, 0x64, + 0x10, 0x6A, 0x46, 0x28, 0x21, 0x40, 0xF2, 0x22, 0x20, 0x43, 0xF6, 0x7E, 0xFB, 0x0E, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x21, 0x20, 0x43, 0xF6, 0x78, 0xFB, 0x0F, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x23, 0x20, 0x43, 0xF6, 0x72, 0xFB, 0x10, 0xAA, 0x01, + 0x21, 0x40, 0xF2, 0x63, 0x20, 0x48, 0xF6, 0x90, 0xFC, 0x11, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x19, 0x70, 0x48, 0xF6, 0x8A, 0xFC, 0x0A, + 0xAA, 0x06, 0x21, 0x40, 0xF2, 0x65, 0x20, 0x48, 0xF6, 0x84, 0xFC, 0x0C, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x66, 0x20, 0x48, 0xF6, 0x7E, 0xFC, 0x0D, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x67, 0x20, 0x48, 0xF6, 0x78, 0xFC, 0x1A, 0xAA, 0x02, 0x21, 0x4F, + 0xF4, 0x1A, 0x70, 0x48, 0xF6, 0x72, 0xFC, 0x1B, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x69, 0x20, 0x48, 0xF6, 0x6C, 0xFC, 0x48, 0x4A, 0x13, 0x21, 0x14, 0x3A, 0x40, 0xF2, 0x61, 0x20, 0x48, 0xF6, 0x65, 0xFC, 0x45, 0x4A, 0x04, 0x21, 0x18, 0x3A, 0x40, + 0xF2, 0x62, 0x20, 0x48, 0xF6, 0x5E, 0xFC, 0x12, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x02, 0x20, 0x42, 0xF6, 0xE5, 0xFC, 0x13, 0xAA, 0x02, 0x21, 0x40, 0xF2, 0x03, 0x20, 0x42, 0xF6, 0xDF, 0xFC, 0x14, 0xAA, 0x01, 0x21, 0x4F, 0xF4, 0x01, 0x70, 0x42, + 0xF6, 0xD9, 0xFC, 0x15, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x05, 0x20, 0x42, 0xF6, 0xD3, 0xFC, 0x17, 0xAA, 0x04, 0x21, 0x40, 0xF2, 0x11, 0x20, 0x42, 0xF6, 0xEF, 0xFD, 0x16, 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x12, 0x20, 0x42, 0xF6, 0xE9, 0xFD, 0x18, + 0xAA, 0x01, 0x21, 0x40, 0xF2, 0x13, 0x20, 0x42, 0xF6, 0xE3, 0xFD, 0x19, 0xAA, 0x02, 0x21, 0x4F, 0xF4, 0x05, 0x70, 0x42, 0xF6, 0xDD, 0xFD, 0x2A, 0x48, 0x43, 0xF6, 0x04, 0xFB, 0x1D, 0xB0, 0x00, 0xBD, 0x10, 0xB5, 0x04, 0x20, 0x45, 0xF6, 0x5F, + 0xFF, 0x27, 0x48, 0xFE, 0xF7, 0xA7, 0xFE, 0x26, 0x49, 0x08, 0x70, 0x24, 0x48, 0xFE, 0xF7, 0x5D, 0xFF, 0x25, 0x49, 0x08, 0x70, 0x22, 0x48, 0xFF, 0xF7, 0xE7, 0xF8, 0x23, 0x49, 0x08, 0x70, 0x1F, 0x48, 0xFF, 0xF7, 0x6D, 0xFE, 0x22, 0x49, 0x08, + 0x70, 0xBD, 0xE8, 0x10, 0x40, 0x1C, 0x48, 0x45, 0xF6, 0x5F, 0xBF, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x10, 0xB5, 0xAF, 0xF2, 0x07, 0x00, 0x1C, 0x49, 0x08, 0x60, 0xAF, 0xF2, 0x0D, 0x00, 0x1B, 0x49, 0x08, 0x60, 0xFE, 0xF7, 0x83, + 0xFD, 0xBD, 0xE8, 0x10, 0x40, 0x02, 0x20, 0xFF, 0xF5, 0xDF, 0xB8, 0xFF, 0xF7, 0xDD, 0xBE, 0x16, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x01, 0xF0, 0xB1, 0xFB, 0x01, 0x20, 0x43, 0xF6, 0x84, 0xFA, 0x00, 0xF0, 0x07, 0xFE, 0xFF, 0xF7, 0x12, 0xFF, 0xFF, + 0xF7, 0xBF, 0xFF, 0xFF, 0xF7, 0xDE, 0xFF, 0xFF, 0xF7, 0xCB, 0xFE, 0x0E, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFE, 0xF5, 0x6F, 0xF9, 0x1D, 0xF6, 0x76, 0xF8, 0x00, 0x20, 0x10, 0xBD, 0x00, 0x00, 0x74, 0xB5, 0x20, 0x00, 0x2B, 0x9B, 0x20, 0x00, 0x7B, + 0x9B, 0x20, 0x00, 0xFC, 0xC3, 0x20, 0x00, 0xFD, 0xC3, 0x20, 0x00, 0xFE, 0xC3, 0x20, 0x00, 0xFF, 0xC3, 0x20, 0x00, 0x94, 0xB9, 0x20, 0x00, 0x90, 0xB9, 0x20, 0x00, 0x78, 0xB9, 0x20, 0x00, 0x43, 0x6F, 0x6D, 0x70, 0x6C, 0x65, 0x74, 0x65, 0x64, + 0x20, 0x4F, 0x54, 0x41, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x21, 0x00, 0x00, 0x00, 0x10, 0xB5, 0x03, 0x28, 0x01, 0xD3, 0x00, 0x20, 0x10, 0xBD, 0x1A, 0x49, 0x00, 0xEB, 0xC0, 0x00, 0x01, 0xEB, 0x80, 0x04, 0x08, 0x22, 0x18, 0x49, 0x20, + 0x68, 0x50, 0xF6, 0x65, 0xFB, 0x98, 0xB1, 0xA2, 0x69, 0x61, 0x68, 0xE0, 0x68, 0x50, 0xF6, 0xAA, 0xFB, 0xE2, 0x69, 0xA1, 0x68, 0x20, 0x69, 0x50, 0xF6, 0xA5, 0xFB, 0x21, 0x6A, 0x60, 0x69, 0x50, 0xF6, 0x62, 0xFC, 0x20, 0x68, 0x0E, 0x49, 0x02, + 0x68, 0x0A, + 0x60, 0x40, 0x68, 0x48, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x70, 0xB5, 0x09, 0x4D, 0x00, 0x24, 0x04, 0xEB, 0xC4, 0x00, 0x08, 0x22, 0x55, 0xF8, 0x20, 0x00, 0x06, 0x49, 0x50, 0xF6, 0x43, 0xFB, 0x20, 0xB1, 0x64, 0x1C, 0x03, 0x2C, 0xF3, 0xDB, 0x03, + 0x20, 0x70, 0xBD, 0xE0, 0xB2, 0x70, 0xBD, 0x00, 0x00, 0xF4, 0xB8, 0x20, 0x00, 0xF0, 0xC3, 0x20, 0x00, 0xF8, 0xB5, 0x0C, 0x46, 0x15, 0x46, 0x00, 0x92, 0xFE, 0x49, 0x03, 0x46, 0x02, 0x22, 0xFE, 0x4E, 0x30, 0x46, 0xFE, 0xF5, 0x58, 0xF9, 0x54, + 0xB1, 0x01, 0x2C, 0x0C, 0xD0, 0x01, 0x22, 0x01, 0xB0, 0x23, 0x46, 0xB0, 0x1E, 0xBD, 0xE8, 0xF0, 0x40, 0xF8, 0x49, 0xFE, 0xF5, 0x4C, 0xB9, 0xF5, 0x49, 0x00, 0x22, 0x38, 0x31, 0x04, 0xE0, 0x4F, 0xF0, 0x00, 0x02, 0x35, 0xB1, 0xF3, 0x49, 0x48, + 0x39, 0x30, 0x46, 0xBD, 0xE8, 0xF8, 0x40, 0xFE, 0xF5, 0x3E, 0xB9, 0xEE, 0x49, 0x74, 0x31, 0xF7, 0xE7, 0x30, 0xB5, 0xED, 0x4C, 0x85, 0xB0, 0x05, 0x46, 0x59, 0xB1, 0x01, 0x29, 0x2B, 0xD0, 0x02, 0x29, 0x27, 0xD1, 0x05, 0xB0, 0x20, 0x46, 0xBD, + 0xE8, 0x30, 0x40, 0x00, 0x22, 0xE8, 0x49, 0xFE, 0xF5, 0x2A, 0xB9, 0x02, 0x46, 0x04, 0xA9, 0x40, 0xF2, 0x72, 0x20, 0x44, 0xF6, 0x34, 0xF9, 0x2A, 0x46, 0x03, 0xA9, 0x40, 0xF2, 0x73, 0x20, 0x44, 0xF6, 0x2E, 0xF9, 0x2A, 0x46, 0x02, 0xA9, 0x4F, + 0xF4, 0x1D, 0x70, 0x44, 0xF6, 0x28, 0xF9, 0xBD, 0xF8, 0x08, 0x10, 0xBD, 0xF8, 0x0C, 0x00, 0xCD, 0xE9, 0x00, 0x01, 0xDA, 0x49, 0xBD, 0xF8, 0x10, 0x30, 0x03, 0x22, 0x70, 0x31, 0x20, 0x46, 0xFE, 0xF5, 0x0A, + 0xF9, 0x05, 0xB0, 0x30, 0xBD, 0x05, 0xB0, 0xD5, 0x49, 0x13, 0x46, 0xD2, 0x48, 0xBD, 0xE8, 0x30, 0x40, 0x01, 0x22, 0x40, 0x39, 0x80, 0x1E, 0xFE, 0xF5, 0xFD, 0xB8, 0x08, 0xB5, 0x03, 0x46, 0x00, 0x91, 0xCE, 0x49, 0x02, 0x22, 0x34, 0x31, 0xCB, + 0x48, 0xFE, 0xF5, 0xF4, 0xF8, 0x08, 0xBD, 0x2D, 0xE9, 0xF0, 0x41, 0xCB, 0x4E, 0x80, 0x46, 0x8A, 0xB0, 0x0D, 0x46, 0xF0, 0x78, 0xCD, 0xE9, 0x00, 0x05, 0xC4, 0x49, 0xC4, 0x4F, 0x14, 0x46, 0x02, 0x92, 0x43, 0x46, 0x04, 0x22, 0xF8, 0x39, 0x38, + 0x46, 0xFE, 0xF5, 0xE0, 0xF8, 0x15, 0xB1, 0x02, 0x2D, 0x49, 0xD1, 0x1C, 0xE0, 0xA4, 0xF5, 0x80, 0x70, 0x13, 0x38, 0x0A, + 0xD0, 0xB4, 0xF5, 0x8B, 0x7F, 0x07, 0xD0, 0xB9, 0x49, 0xBA, 0x48, 0x23, 0x46, 0x01, 0x22, 0xA4, 0x39, 0x80, 0x1E, 0xFE, 0xF5, 0xCD, 0xF8, 0x30, 0x78, 0x40, 0xB1, 0x00, 0x20, 0x30, 0x70, 0x3E, 0xF6, 0x03, 0xF9, 0xD2, 0x21, 0x01, 0x20, 0xFE, + 0xF7, 0x63, 0xFB, 0x2E, 0xE0, 0x48, 0xF6, 0xF4, 0xFB, 0x2B, 0xE0, 0x42, 0x46, 0x06, 0xA9, 0x40, 0xF2, 0x72, 0x20, 0x44, 0xF6, 0xC9, 0xF8, 0x42, 0x46, 0x08, 0xA9, 0x40, 0xF2, 0x73, 0x20, 0x44, 0xF6, 0xC3, 0xF8, 0x42, 0x46, 0x09, 0xA9, 0x4F, + 0xF4, 0x1D, 0x70, 0x44, 0xF6, 0xBD, 0xF8, 0x07, 0xAA, 0x04, 0xA9, 0x40, 0x46, 0x44, 0xF6, 0x70, 0xF9, 0x04, 0xA9, 0xA7, 0x48, 0xFE, 0xF5, 0x61, 0xFA, 0x03, 0x46, 0x9D, 0xF8, 0x1C, 0x00, 0xBD, 0xF8, 0x24, 0x40, 0xBD, 0xF8, 0x20, 0x20, 0xBD, + 0xF8, 0x18, 0x10, 0x8D, 0xE8, 0x17, 0x00, 0x9B, 0x49, 0x05, 0x22, 0x84, 0x39, 0x38, 0x46, 0xFE, 0xF5, 0x93, 0xF8, 0xF5, 0x70, 0x0A, + 0xB0, 0xBD, 0xE8, 0xF0, 0x81, 0x2D, 0xE9, 0xFC, 0x41, 0xC4, 0xB2, 0xC4, 0xF3, 0x81, 0x05, 0xCD, 0xE9, 0x00, 0x51, 0xDF, 0xF8, 0x50, 0x82, 0x04, 0xF0, 0x01, 0x06, 0x33, 0x46, 0x03, 0x22, 0x96, 0x49, 0x40, 0x46, 0xFE, 0xF5, 0x7E, 0xF8, 0x92, + 0x4F, 0xBF, 0x1C, 0x38, 0x78, 0x00, 0xF0, 0x01, 0x00, 0xB0, 0x42, 0x09, 0xD0, 0xE0, 0x07, 0x07, 0xD0, 0x8F, 0x49, 0x00, 0x22, 0x48, 0x31, 0x40, 0x46, 0xFE, 0xF5, 0x6F, 0xF8, 0x48, 0xF6, 0xA1, 0xFB, 0x38, 0x78, 0xC0, 0xF3, 0x81, 0x00, 0xA8, + 0x42, 0x15, 0xD0, 0x14, 0xF0, 0x0C, 0x0F, 0x02, 0xD0, 0x02, 0x2D, 0x0A, + 0xD0, 0x0F, 0xE0, 0xA0, 0x07, 0x4F, 0xF0, 0x00, 0x02, 0x02, 0xD5, 0x84, 0x49, 0x5C, 0x31, 0x05, 0xE0, 0x82, 0x49, 0x8C, 0x31, 0x02, 0xE0, 0x81, 0x49, 0x00, 0x22, 0xA0, 0x31, 0x40, 0x46, 0xFE, 0xF5, 0x52, 0xF8, 0x7C, 0x48, 0x84, 0x70, 0xBD, + 0xE8, 0xFC, 0x81, 0x7F, 0xB5, 0x05, 0x46, 0x43, 0x88, 0x44, 0x68, 0x77, 0x49, 0x74, 0x48, 0x01, 0x22, 0x34, 0x31, 0x40, 0x1C, 0xFE, 0xF5, 0x43, 0xF8, 0x6B, 0x88, 0x00, 0x20, 0x70, 0x4D, 0x0B, 0x2B, 0x7E, 0xD2, 0xDF, 0xE8, 0x03, 0xF0, 0x83, + 0x06, 0x0C, 0x1A, 0x14, 0x22, 0x37, 0x5B, 0x6C, 0x49, 0x2A, 0x00, 0x04, 0xB0, 0x20, 0x46, 0x21, 0x0C, 0xBD, 0xE8, 0x70, 0x40, 0xA0, 0xE7, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x34, 0xE7, 0x04, + 0xB0, 0x21, 0x0C, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0x24, 0xE7, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, 0x40, 0xDE, 0xE6, 0x04, 0xB0, 0x22, 0x0C, 0xC4, 0xF3, 0x07, 0x21, 0xE0, 0xB2, 0xBD, 0xE8, 0x70, + 0x40, 0xAE, 0xE6, 0xE0, 0xB2, 0x01, 0x21, 0x00, 0xF0, 0xD6, 0xFC, 0x04, 0xB0, 0x28, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x57, 0x49, 0x00, 0x22, 0x54, 0x31, 0xFE, 0xF5, 0x05, 0xB8, 0xE4, 0xB2, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, 0x42, 0xF6, 0xC5, + 0xFC, 0x51, 0x49, 0x01, 0x22, 0x74, 0x31, 0x28, 0x46, 0x00, 0x9B, 0xFD, 0xF5, 0xF8, 0xFF, 0x01, 0x21, 0x20, 0x46, 0x42, 0xF6, 0xFF, 0xFC, 0x7F, 0xBD, 0xE4, 0xB2, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, 0x42, 0xF6, 0xB3, 0xFC, 0x48, 0x49, 0x01, + 0x22, 0xA4, 0x31, 0x28, 0x46, 0x00, 0x9B, 0xFD, 0xF5, 0xE6, 0xFF, 0x01, 0x21, 0x20, 0x46, 0x42, 0xF6, 0xBD, 0xFC, 0x7F, 0xBD, 0x42, 0x49, 0xE4, 0xB2, 0x45, 0x4E, 0x23, 0x46, 0x01, 0x22, 0xD8, 0x31, 0x28, 0x46, 0xFD, 0xF5, 0xD8, 0xFF, 0x04, + 0xB0, 0x31, 0x46, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x01, 0x22, 0x42, 0xF6, 0x62, 0xBC, 0x00, 0x90, 0x01, 0x90, 0x02, 0x90, 0x03, 0x90, 0xE4, 0xB2, 0x00, 0x22, 0x3C, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0xC6, 0xFF, 0x6A, 0x46, 0x10, 0x21, 0x4F, + 0xF4, 0x04, 0x70, 0x42, 0xF6, 0x88, 0xFB, 0x00, 0xE0, 0x04, 0xE0, 0x01, 0x21, 0x20, 0x46, 0x42, 0xF6, 0x66, 0xFC, 0x7F, 0xBD, 0x04, 0xB0, 0x33, 0x49, 0xBD, 0xE8, 0x70, 0x40, 0x2A, 0x48, 0x01, 0x22, 0x20, 0x31, 0x80, 0x1E, 0xFD, 0xF5, 0xAF, + 0xBF, 0x13, 0xB5, 0xBD, 0xF8, 0x00, 0x00, 0x60, 0xB1, 0x21, 0x28, 0x09, 0xD1, 0x29, 0x49, 0x00, 0x22, 0x1C, 0x39, 0x23, 0x48, 0xFD, 0xF5, 0xA3, 0xFF, 0x01, 0x98, 0xC0, 0xB2, 0xFF, 0xF7, 0x13, 0xF8, 0x1C, 0xBD, 0x68, 0x46, 0xFF, 0xF7, 0x4D, + 0xFF, 0x1C, 0xBD, 0x7C, 0xB5, 0x00, 0x24, 0x1C, 0x4D, 0x01, 0x28, 0x17, 0xD0, 0x14, 0x28, 0x08, 0xD0, 0x20, 0x49, 0x03, 0x46, 0x01, 0x22, 0xDC, 0x31, 0xA8, 0x1E, 0xFD, 0xF5, 0x8C, 0xFF, 0x20, 0x46, 0x7C, 0xBD, 0x08, 0x68, 0x82, 0x88, 0x41, + 0x88, 0xCD, 0xE9, 0x00, 0x12, 0x19, 0x49, 0x03, 0x78, 0x03, 0x22, 0x4C, 0x31, 0x28, 0x46, 0xFD, 0xF5, 0x7E, 0xFF, 0xF0, 0xE7, 0x08, 0x68, 0x02, 0x22, 0x41, 0x88, 0x00, 0x91, 0x13, 0x49, 0x03, 0x78, 0xA0, 0x31, 0x28, 0x46, 0xFD, 0xF5, 0x73, + 0xFF, 0xE5, 0xE7, 0x7F, 0xB5, 0x02, 0x46, 0x00, 0x25, 0x07, 0x48, 0x0C, 0x46, 0xFF, 0x2A, 0x1E, 0xD0, 0x08, 0x49, 0x0B, 0x79, 0x9A, 0x42, 0x73, 0xD1, 0x61, 0x78, 0x01, 0x29, 0x3B, 0xD0, 0x02, 0x29, 0x52, 0xD0, 0x11, 0xE0, 0x2C, 0x15, 0x80, + 0x08, 0x02, 0x30, 0x10, 0x21, 0x30, 0x16, 0x80, 0x08, 0x60, 0x17, 0x80, 0x08, 0xF8, 0xC3, 0x20, 0x00, 0x00, 0x00, 0x30, 0x21, 0x80, 0x13, 0x80, 0x08, 0x38, 0x90, 0x0D, 0x00, 0x68, 0x18, 0x80, 0x08, 0x03, 0x29, 0x0A, + 0xD1, 0x4D, 0xE0, 0x21, 0x78, 0x11, 0xB1, 0x01, 0x29, 0x05, 0xD1, 0x05, 0xE0, 0xA3, 0x78, 0x01, 0x22, 0x6A, 0x49, 0xFD, 0xF5, 0x42, 0xFF, 0xAE, 0xE0, 0x21, 0x89, 0x66, 0x88, 0xE3, 0x88, 0x62, 0x79, 0x8D, 0xE8, 0x4E, 0x00, 0x65, 0x49, 0x23, + 0x79, 0x05, 0x22, 0x2C, 0x31, 0x06, 0x46, 0xFD, 0xF5, 0x34, 0xFF, 0x20, 0x89, 0x4F, 0xF0, 0x00, 0x02, 0x18, 0xB1, 0x60, 0x49, 0x60, 0x48, 0xC0, 0x31, 0x4E, 0xE0, 0x5E, 0x49, 0x30, 0x46, 0x94, 0x31, 0x4A, 0xE0, 0x21, 0x79, 0x01, 0x29, 0x06, + 0xD0, 0x02, 0x29, 0x08, 0xD0, 0x03, 0x29, 0x09, 0xD0, 0x04, 0x29, 0x1F, 0xD1, 0x0A, + 0xE0, 0x57, 0x49, 0x00, 0x22, 0xEC, 0x31, 0x3C, 0xE0, 0x00, 0x22, 0x56, 0x49, 0x39, 0xE0, 0x55, 0x49, 0x00, 0x22, 0x24, 0x31, 0x35, 0xE0, 0x53, 0x49, 0x00, 0x22, 0x48, 0x31, 0x31, 0xE0, 0x21, 0x79, 0x01, 0x29, 0x79, 0xD1, 0x51, 0xA1, 0x00, + 0x22, 0x09, 0x68, 0x00, 0x91, 0x4E, 0x49, 0x6C, 0x31, 0xFD, 0xF5, 0x04, 0xFF, 0x6A, 0x46, 0x02, 0x21, 0x01, 0x20, 0xFE, 0xF7, 0xAE, 0xFA, 0x6B, 0xE0, 0x21, 0x79, 0x01, 0x29, 0x68, 0xD1, 0xE1, 0x88, 0x00, 0x91, 0x46, 0x49, 0x02, 0x22, 0x63, + 0x79, 0x7C, 0x31, 0x57, 0xE0, 0xFF, 0xE7, 0x4B, 0x79, 0x9A, 0x42, 0x26, 0xD1, 0x61, 0x78, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x58, 0xD1, 0x0F, 0xE0, 0xA1, 0x78, 0x01, 0x29, 0x02, 0xD0, 0x02, 0x29, 0x52, 0xD1, 0x03, 0xE0, 0x3C, 0x49, 0x00, + 0x22, 0xA4, 0x31, 0x02, 0xE0, 0x3A, 0x49, 0x00, 0x22, 0xC8, 0x31, 0xFD, 0xF5, 0xDB, 0xFE, 0x47, 0xE0, 0xA1, 0x78, 0x01, 0x29, 0x44, 0xD1, 0x35, 0x49, 0x5A, 0x23, 0x8D, 0xF8, 0x00, 0x30, 0x01, 0x22, 0xEC, 0x31, 0xFD, 0xF5, 0xCF, 0xFE, 0x01, + 0x21, 0x6A, 0x46, 0x08, 0x46, 0xFE, 0xF7, 0x93, 0xFB, 0x36, 0xE0, 0x8B, 0x79, 0x9A, 0x42, 0x2C, 0xD1, 0x00, 0x22, 0x2E, 0x49, 0x06, 0x46, 0xFD, 0xF5, 0xC1, 0xFE, 0x20, 0x78, 0x02, 0x28, 0x2B, 0xD0, 0x03, 0x28, 0x29, 0xD1, 0xA3, 0x78, 0x01, + 0x2B, 0x04, 0xD0, 0x02, 0x2B, 0x14, 0xD0, 0x03, 0x2B, 0x22, 0xD1, 0x05, 0xE0, 0x26, 0x49, 0x20, 0x79, 0x02, 0x22, 0x18, 0x31, 0x00, 0x90, 0x10, 0xE0, 0x21, 0x89, 0xE0, 0x88, 0xCD, 0xE9, 0x00, 0x01, 0x21, 0x49, 0x23, 0x79, 0x03, 0x22, 0x50, + 0x31, 0x30, 0x46, 0xFD, 0xF5, 0xA3, 0xFE, 0x0F, 0xE0, 0x1D, 0x49, 0x20, 0x79, 0x02, 0x22, 0xB0, 0x31, 0x00, 0x90, 0x30, 0x46, 0xFD, 0xF5, 0x9A, 0xFE, 0x06, 0xE0, 0xC9, 0x79, 0x8A, 0x42, 0x03, 0xD1, 0x17, 0x49, 0x00, 0x22, 0xF4, 0x31, 0xB4, + 0xE7, 0x04, 0xB0, 0x28, 0x46, 0x70, 0xBD, 0x1C, 0xB5, 0x03, 0x29, 0x0C, 0xD0, 0x04, 0x29, 0x09, 0xD1, 0x4F, 0xF4, 0x7A, 0x70, 0x1C, 0xF6, 0x0F, 0xFD, 0x00, 0x20, 0x43, 0xF6, 0x66, 0xFF, 0x0E, 0x49, 0x01, 0x20, 0x48, 0x70, 0x1C, 0xBD, 0x21, + 0x21, 0x01, 0x90, 0xAD, 0xF8, 0x00, 0x10, 0x68, 0x46, 0xFF, 0xF7, 0x86, 0xFB, 0x00, 0x28, 0xF5, 0xD1, 0x09, 0xA1, 0x4F, 0xF0, 0x04, 0x50, 0xFD, 0xF5, 0x1A, 0xFE, 0x1C, 0xBD, 0x00, 0x00, 0x70, 0x19, 0x80, 0x08, 0x00, 0x30, 0x10, 0x21, 0x80, + 0x1A, 0x80, 0x08, 0x01, 0x02, 0x00, 0x00, 0x98, 0x1B, 0x80, 0x08, 0xF8, 0xC3, 0x20, 0x00, 0x44, 0x46, 0x55, 0x20, 0x73, 0x65, 0x6E, 0x64, 0x20, 0x76, 0x61, 0x6C, 0x69, 0x64, 0x20, 0x66, 0x77, 0x20, 0x6D, 0x73, 0x67, 0x20, 0x66, 0x61, 0x69, + 0x6C, 0x21, 0x00, 0x10, 0xB5, 0xFC, 0x4C, 0x00, 0x22, 0xFA, 0x49, 0x20, 0x46, 0xFD, 0xF5, 0x4E, 0xFE, 0xFA, 0x49, 0x4F, 0xF4, 0x00, 0x00, 0x01, 0xF0, 0x79, 0xF8, 0x00, 0x28, 0x08, 0xD0, 0xF6, 0x48, 0xF4, 0x49, 0x01, 0x22, 0x03, 0x78, 0x30, + 0x31, 0x20, 0x46, 0xFD, 0xF5, 0x3F, 0xFE, 0x01, 0x20, 0x10, 0xBD, 0xF1, 0x48, 0x00, 0x78, 0xFF, 0x28, 0x01, 0xD0, 0x01, 0xF0, 0x54, 0xB8, 0x70, 0x47, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x02, 0x20, 0x02, 0xF6, 0x14, 0xF9, 0x04, 0x46, 0x00, + 0x90, 0xE8, 0x49, 0xE8, 0x48, 0x2B, 0x46, 0x02, 0x22, 0x70, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0x26, 0xFE, 0x20, 0x46, 0x38, 0xBD, 0x38, 0xB5, 0x05, 0x46, 0x01, 0x46, 0x04, 0x20, 0x02, 0xF6, 0x02, 0xF9, 0x04, 0x46, 0x00, 0x90, 0xDF, 0x49, 0xDF, + 0x48, 0x2B, 0x46, 0x02, 0x22, 0xAC, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0x14, 0xFE, 0x20, 0x46, 0x38, 0xBD, 0x70, 0xB5, 0x0D, 0x46, 0x00, 0x24, 0x02, 0xF6, 0x1E, 0xFD, 0x20, 0xB1, 0x28, 0x44, 0xFF, 0xF7, 0xD3, 0xFF, 0x10, 0xB1, 0x02, 0xE0, 0x66, + 0x24, 0x00, 0xE0, 0x6C, 0x24, 0xD3, 0x49, 0xD3, 0x48, 0x23, 0x46, 0x01, 0x22, 0xE8, 0x31, 0x40, 0x1E, 0xFD, 0xF5, 0xFC, 0xFD, 0x20, 0x46, 0x70, 0xBD, 0x2D, 0xE9, 0xFC, 0x47, 0x16, 0x46, 0x0D, 0x46, 0xDF, 0xF8, 0x34, 0x93, 0xCD, 0xE9, 0x00, + 0x56, 0x04, 0x46, 0x03, 0x46, 0xA9, 0xF1, 0x01, 0x09, 0x00, 0x27, 0x03, 0x22, 0xCA, 0x49, 0x48, 0x46, 0xFD, 0xF5, 0xE8, 0xFD, 0xA4, 0xF5, 0x7F, 0x40, 0xFE, 0x38, 0x15, 0xD0, 0x1C, 0xF6, 0xDB, 0xFC, 0x80, 0x46, 0x32, 0x46, 0x29, 0x46, 0x20, + 0x46, 0x3D, 0xF6, 0x92, 0xFC, 0x07, 0x46, 0x40, 0x46, 0x1C, 0xF6, 0xDE, 0xFC, 0xC0, 0x49, 0x3B, 0x46, 0x01, 0x22, 0x70, 0x31, 0x48, 0x46, 0xFD, 0xF5, 0xD1, 0xFD, 0x38, 0x46, 0xBD, 0xE8, 0xFC, 0x87, 0x00, 0x24, 0x05, 0x20, 0x02, 0xF6, 0x3B, + 0xF8, 0x05, 0x44, 0x13, 0xE0, 0x6A, 0x46, 0x04, 0x21, 0x28, 0x46, 0x02, 0xF6, 0x11, 0xFB, 0x00, 0x98, 0x40, 0x1C, 0x09, 0xD0, 0xB4, 0x49, 0xB1, 0x48, 0x23, 0x46, 0x01, 0x22, 0x44, 0x31, 0xC0, 0x1E, 0xFD, 0xF5, 0xB8, 0xFD, 0x85, 0x27, 0xDD, + 0xE7, 0x64, 0x1C, 0x2D, 0x1D, 0xB4, 0xEB, 0x96, 0x0F, 0xE8, 0xD3, 0xD7, 0xE7, 0x2D, 0xE9, 0xF8, 0x43, 0x0E, 0x46, 0x00, 0x24, 0xA0, 0xF5, 0x7F, 0x41, 0x91, 0x46, 0x80, 0x46, 0xFE, 0x39, 0x1B, 0xD0, 0x02, 0xF6, 0xB5, 0xFC, 0xE0, 0xB1, 0x87, + 0x19, 0x38, 0x46, 0xFF, 0xF7, 0x69, 0xFF, 0x4A, 0x46, 0x31, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0xA0, 0xFF, 0x05, 0x00, 0x02, 0xD0, 0x64, 0x1C, 0x03, 0x2C, 0xF2, 0xD3, 0x9E, 0x49, 0x23, 0x46, 0x02, 0x22, 0x98, 0x31, 0x9A, 0x48, 0x00, 0x95, 0xFD, + 0xF5, 0x8D, 0xFD, 0x28, 0x46, 0xBD, 0xE8, 0xF8, 0x83, 0x05, 0x20, 0x01, 0xF6, 0xF8, 0xFF, 0xE1, 0xE7, 0xB1, 0x25, 0xEE, 0xE7, 0x2D, 0xE9, 0xF0, 0x5F, 0x04, 0x46, 0x00, 0x25, 0x02, 0xF6, 0x70, 0xFC, 0x90, 0xF0, 0x01, 0x0F, 0x42, 0xF2, 0x91, + 0x77, 0x42, 0xF2, 0x92, 0x78, 0x42, 0xF2, 0x93, 0x79, 0x42, 0xF2, 0x94, 0x7A, 0x42, 0xF2, 0x95, 0x7B, 0x0E, 0xD0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x2E, 0xD1, 0x04, + 0x20, 0x02, 0xF6, 0x11, 0xF8, 0x05, 0x46, 0x29, 0xE0, 0x02, 0x20, 0x01, 0xF6, 0xD0, 0xFF, 0x06, 0x46, 0xF7, 0xF5, 0x13, 0xF9, 0xB0, 0x42, 0x03, 0xD1, 0x03, 0x20, 0x01, 0xF6, 0xC8, 0xFF, 0x06, 0x46, 0x42, 0xF2, 0x90, 0x71, 0x8C, 0x42, 0x02, + 0xD1, 0x4F, 0xF4, 0x80, 0x55, 0x16, 0xE0, 0xBC, 0x42, 0x07, 0xD0, 0x44, 0x45, 0x05, 0xD0, 0x4C, 0x45, 0x03, 0xD0, 0x54, 0x45, 0x01, 0xD0, 0x5C, 0x45, 0x0C, 0xD1, 0x30, 0x46, 0x02, 0xF6, 0xE7, 0xFB, 0x40, 0xB1, 0x06, 0xEB, 0xC4, 0x00, 0xA0, + 0xF5, 0xA0, 0x30, 0xD0, 0xF8, 0x14, 0x55, 0x68, 0x1C, 0x00, 0xD1, 0x00, 0x25, 0x28, 0x46, 0xBD, 0xE8, 0xF0, 0x9F, 0x2D, 0xE9, 0xFC, 0x41, 0x0E, 0x46, 0x08, 0x9C, 0x4F, 0xF0, 0x00, 0x01, 0x1D, 0x00, 0x17, 0x46, 0x21, 0x60, 0x0F, 0xD0, 0xA0, + 0xF5, 0x7F, 0x41, 0xFE, 0x39, 0x07, 0xD0, 0xFF, 0xF7, 0xA1, 0xFF, 0xDF, 0xF8, 0x90, 0xC1, 0xAC, 0xF1, 0x03, 0x0C, 0x3E, 0xB1, 0x15, 0xE0, 0x05, 0x20, 0x01, 0xF6, 0xC9, 0xFF, 0xF5, 0xE7, 0x4F, 0xF4, 0xE3, 0x70, 0x1B, 0xE0, 0xAB, 0x68, 0x03, + 0xF5, 0x80, 0x63, 0x83, 0x42, 0x09, 0xD9, 0x5D, 0x49, 0x00, 0x90, 0x02, 0x22, 0xC4, 0x31, 0x60, 0x46, 0xFD, 0xF5, 0x0C, 0xFD, 0x40, 0xF2, 0xDD, 0x10, 0x0C, 0xE0, 0xF1, 0x19, 0x81, 0x42, 0x0D, 0xD9, 0xCD, 0xE9, 0x00, 0x70, 0x33, 0x46, 0x03, + 0x22, 0x56, 0x49, 0x60, 0x46, 0xFD, 0xF5, 0xFE, 0xFC, 0x4F, 0xF4, 0xF3, 0x70, 0x20, 0x60, 0x00, 0x20, 0xBD, 0xE8, 0xFC, 0x81, 0x01, 0x20, 0xFB, 0xE7, 0x2D, 0xE9, 0xFF, 0x47, 0x80, 0x46, 0x00, 0x91, 0x16, 0x46, 0x00, 0x20, 0x0D, 0x46, 0xDF, + 0xF8, 0x24, 0xA1, 0xCD, 0xE9, 0x01, 0x60, 0x4A, 0x49, 0x1C, 0x46, 0xAA, 0xF1, 0x01, 0x0A, + 0x43, 0x46, 0x03, 0x22, 0x54, 0x31, 0x50, 0x46, 0xFD, 0xF5, 0xE1, 0xFC, 0xB0, 0x07, 0x02, 0xD0, 0x40, 0xF2, 0x4F, 0x20, 0x60, 0xE0, 0x3C, 0xB1, 0xA8, 0xF5, 0x7F, 0x41, 0x40, 0x46, 0xFE, 0x39, 0x05, 0xD0, 0x02, 0xF6, 0xE5, 0xFB, 0x05, 0xE0, + 0x40, 0xF2, 0x55, 0x20, 0x54, 0xE0, 0x05, 0x20, 0x01, 0xF6, 0x3E, 0xFF, 0x07, 0x00, 0x0C, 0xD0, 0x02, 0xA8, 0x00, 0x90, 0x23, 0x46, 0x32, 0x46, 0x29, 0x46, 0x40, 0x46, 0xFF, 0xF7, 0x8E, 0xFF, 0xF0, 0xB3, 0xDF, 0xF8, 0xCC, 0x90, 0x1D, 0xB1, + 0x0E, 0xE0, 0x4F, 0xF4, 0x1C, 0x70, 0x3F, 0xE0, 0x60, 0x88, 0x32, 0x49, 0x40, 0xF0, 0x80, 0x00, 0x60, 0x80, 0x43, 0x46, 0x02, 0x22, 0x90, 0x31, 0x48, 0x46, 0x00, 0x97, 0xFD, 0xF5, 0xAF, 0xFC, 0x78, 0x19, 0x07, 0x46, 0x29, 0x05, 0x0B, 0xD0, + 0xC5, 0xF3, 0x0B, 0x01, 0x31, 0x44, 0x4F, 0xF4, 0x80, 0x52, 0x91, 0x42, 0x07, 0xD9, 0x96, 0x42, 0x05, 0xD8, 0xB8, 0x19, 0x6F, 0xF3, 0x0B, 0x00, 0xFF, 0xF7, 0x67, 0xFE, 0x08, 0xB1, 0x00, 0x25, 0x22, 0xE0, 0x40, 0xF2, 0xF6, 0x20, 0x1B, 0xE0, + 0x78, 0x19, 0x80, 0x46, 0x21, 0x68, 0x02, 0xF6, 0xBC, 0xF9, 0x48, 0xF0, 0x80, 0x70, 0x03, 0xA9, 0x02, 0xF6, 0xEF, 0xF9, 0x20, 0x68, 0x03, 0x99, 0x88, 0x42, 0x0F, 0xD0, 0x78, 0x19, 0xCD, 0xE9, 0x00, 0x10, 0x03, 0x22, 0x17, 0x49, 0x00, 0xE0, + 0x0C, 0xE0, 0xD8, 0x31, 0x48, 0x46, 0x23, 0x68, 0xFD, 0xF5, 0x7D, 0xFC, 0x40, 0xF2, 0x07, 0x30, 0x02, 0x90, 0x03, 0xE0, 0x24, 0x1D, 0x2D, 0x1D, 0xB5, 0x42, 0xDD, 0xD3, 0x01, 0x22, 0x10, 0x49, 0x50, 0x46, 0x02, 0x9B, 0xFD, 0xF5, 0x6F, 0xFC, + 0x02, 0x98, 0x04, 0xB0, 0xBD, 0xE8, 0xF0, 0x87, 0x01, 0x46, 0x01, 0x20, 0xA1, 0xF5, 0x7F, 0x42, 0xFE, 0x3A, 0x02, 0xD0, 0x08, 0x46, 0x3D, 0xF6, 0xAD, 0xBA, 0x08, 0x4A, 0x00, 0x21, 0x11, 0x60, 0x70, 0x47, 0x00, 0x00, 0xA4, 0x1C, 0x80, 0x08, + 0x03, 0x31, 0x10, 0x21, 0x64, 0xB9, 0x20, 0x00, 0xC0, 0x1D, 0x80, 0x08, 0xC4, 0x1E, 0x80, 0x08, 0xD8, 0x1F, 0x80, 0x08, 0x00, 0xC4, 0x20, 0x00, 0xF8, 0xB5, 0x04, 0x46, 0xA0, 0xF5, 0x7F, 0x40, 0x4F, 0xF4, 0x00, 0x15, 0xFE, 0x38, 0x17, 0xD0, + 0xFF, 0xF7, 0xF0, 0xFD, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0x90, 0xFF, 0x20, 0x46, 0x3D, 0xF6, 0x25, 0xFB, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0xD9, 0xFF, + 0xFF, 0xF7, 0xF4, 0xFD, 0x30, 0x46, 0xF8, 0xBD, 0x20, 0x46, 0xFF, 0xF7, 0xC1, 0xFF, 0x05, 0x20, 0x01, 0xF6, 0x9A, 0xFE, 0x40, 0xF0, 0x80, 0x74, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0x72, 0xFF, 0x20, 0x46, + 0x02, 0xF6, 0xBC, 0xFA, 0x06, 0x46, 0x95, 0xF8, 0x9A, 0x03, 0x80, 0x06, 0x02, 0xD5, 0x01, 0x20, 0xFF, 0xF5, 0xBB, 0xFF, 0x6A, 0x46, 0x04, 0x21, 0x20, 0x46, 0x02, 0xF6, 0x5E, 0xF9, 0x00, 0x98, 0x6A, 0x46, 0x20, 0xF4, 0x00, 0x00, 0x00, 0x90, + 0x04, 0x21, 0x20, 0x46, 0x02, 0xF6, 0x1D, 0xF9, 0xD4, 0xE7, 0x00, 0x00, 0x70, 0xB5, 0x04, 0x46, 0x01, 0x20, 0x08, 0x70, 0x60, 0x88, 0x00, 0x25, 0xB0, 0xF5, 0x97, 0x7F, 0x1A, 0xD0, 0x06, 0xDC, 0x0E, 0x28, 0x0B, 0xD0, 0x0F, 0x28, 0x11, 0xD0, + 0x22, 0x28, 0x26, 0xD1, 0x0A, + 0xE0, 0xA0, 0xF5, 0x80, 0x70, 0x2F, 0x38, 0x16, 0xD0, 0xA2, 0x28, 0x1F, 0xD1, 0x1A, 0xE0, 0x20, 0x1D, 0x00, 0xF0, 0xE8, 0xFB, 0x1A, 0xE0, 0xA0, 0x88, 0x00, 0xF0, 0x64, 0xF8, 0x09, 0xE0, 0x20, 0x1D, 0x00, 0xF0, 0x65, 0xFC, 0x12, 0xE0, 0x20, + 0x46, 0x45, 0xF6, 0xD1, 0xF8, 0x20, 0x1D, 0x00, 0xF0, 0x3A, 0xF9, 0x01, 0x25, 0x0A, + 0xE0, 0x20, 0x46, 0x45, 0xF6, 0xC9, 0xF8, 0x20, 0x1D, 0x00, 0xF0, 0x3E, 0xF9, 0xF6, 0xE7, 0x20, 0x46, 0x00, 0xF0, 0x03, 0xFB, 0x05, 0x46, 0x28, 0x46, 0x70, 0xBD, 0x30, 0xB5, 0x87, 0xB0, 0x00, 0x20, 0x05, 0x90, 0x01, 0x24, 0x06, 0x90, 0xCD, + 0xE9, 0x00, 0x40, 0x10, 0x4D, 0x03, 0x90, 0x04, 0x90, 0x02, 0x90, 0x1C, 0x23, 0x08, 0x22, 0x0C, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0xBA, 0xFB, 0x0A, + 0x49, 0x05, 0x94, 0x06, 0x94, 0x03, 0x94, 0x04, 0x94, 0x00, 0x94, 0x01, 0x94, 0x00, 0x23, 0x08, 0x22, 0xF0, 0x31, 0x28, 0x46, 0x02, 0x94, 0xFD, 0xF5, 0xAC, 0xFB, 0xAF, 0xF2, 0xB3, 0x00, 0x07, 0xB0, 0xBD, 0xE8, 0x30, 0x40, 0x41, 0xF6, 0x7E, + 0xBD, 0xF8, 0x1F, 0x80, 0x08, 0x00, 0x35, 0x10, 0x21, 0x70, 0xB5, 0x02, 0x24, 0x05, 0x46, 0x01, 0x28, 0x02, 0xD0, 0x03, 0x24, 0x20, 0x46, 0x70, 0xBD, 0x43, 0xF6, 0x20, 0xFC, 0x00, 0x28, 0xF9, 0xD1, 0xFB, 0x48, 0x01, 0x78, 0xC8, 0x07, 0xF5, + 0xD0, 0x11, 0xF0, 0x0C, 0x0F, 0xF2, 0xD0, 0x11, 0xF0, 0x30, 0x0F, 0xEF, 0xD1, 0x88, 0x09, 0xED, 0xD1, 0x28, 0x46, 0x17, 0xF6, 0xC8, 0xF9, 0x00, 0x28, 0xE8, 0xD0, 0x00, 0x24, 0xE6, 0xE7, 0x38, 0xB5, 0x04, 0x00, 0x07, 0xD1, 0xF0, 0x49, 0x08, + 0x78, 0x20, 0xF0, 0x0E, 0x00, 0x08, 0x70, 0xFC, 0x20, 0x42, 0xF6, 0xA9, 0xFD, 0xED, 0x48, 0x02, 0x68, 0x00, 0x2A, 0x04, 0xD0, 0xAD, 0xF8, 0x00, 0x40, 0x69, 0x46, 0xA5, 0x20, 0x90, 0x47, 0x38, 0xBD, 0x30, 0xB5, 0x8B, 0xB0, 0x4F, 0xF0, 0x00, + 0x01, 0xE7, 0x4D, 0x04, 0x00, 0x06, 0x91, 0x07, 0x91, 0x08, 0x91, 0x09, 0x91, 0x02, 0xD0, 0x20, 0x78, 0x01, 0x28, 0x08, 0xD0, 0x01, 0x23, 0x01, 0x22, 0xE2, 0x49, 0x28, 0x46, 0xFD, 0xF5, 0x59, 0xFB, 0x00, 0x20, 0x0B, 0xB0, 0x30, 0xBD, 0xA0, + 0x78, 0x00, 0x07, 0x18, 0xD5, 0x6A, 0x46, 0x14, 0x21, 0x20, 0x46, 0x45, 0xF6, 0xD1, 0xFF, 0x80, 0xB1, 0x10, 0x22, 0x06, 0xA9, 0x68, 0x46, 0x4F, 0xF6, 0x1B, 0xFD, 0x40, 0xB1, 0xD7, 0x49, 0x63, 0x78, 0x01, 0x22, 0x30, 0x39, 0x28, 0x46, 0xFD, + 0xF5, 0x40, 0xFB, 0x01, 0x20, 0xE5, 0xE7, 0x05, 0x23, 0xDD, 0xE7, 0x04, 0x23, 0xDB, 0xE7, 0x02, 0x23, 0xD9, 0xE7, 0x0A, + 0x46, 0x00, 0xEB, 0x40, 0x01, 0xCF, 0x48, 0x10, 0xB5, 0x00, 0x68, 0x00, 0xEB, 0x01, 0x10, 0x01, 0x78, 0x29, 0xB1, 0x81, 0x79, 0xC0, 0x1D, 0x17, 0xF6, 0x28, 0xF9, 0x00, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0xF0, 0xB5, 0x85, 0xB0, 0x0C, + 0x46, 0x06, 0x00, 0x05, 0xD0, 0x17, 0xF6, 0x69, 0xFE, 0x78, 0xB3, 0x00, 0x20, 0x05, 0xB0, 0xF0, 0xBD, 0x00, 0x27, 0x44, 0xB3, 0xFD, 0xF7, 0xF8, 0xFB, 0x20, 0x70, 0x01, 0x0A, + 0x61, 0x70, 0x01, 0x0C, 0xA1, 0x70, 0x00, 0x0E, 0x65, 0x1C, 0xE0, 0x70, 0xFD, 0xF7, 0xEE, 0xFB, 0xE8, 0x70, 0x00, 0x0A, + 0x28, 0x71, 0x40, 0xF0, 0xC0, 0x00, 0x60, 0x71, 0xB9, 0xA0, 0x06, 0x22, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x01, 0x10, 0xB8, 0xA0, 0xD0, 0xE9, 0x00, 0x10, 0xCD, 0xE9, 0x03, 0x10, 0x01, 0xA9, 0x20, 0x46, 0x4F, 0xF6, 0xCB, 0xFC, 0x48, 0xB1, + 0x06, 0x22, 0x03, 0xA9, 0x20, 0x46, 0x4F, 0xF6, 0xC5, 0xFC, 0x18, 0xB1, 0x04, 0xE0, 0x03, 0x20, 0xD0, 0xE7, 0x0F, 0xE0, 0x66, 0x20, 0x20, 0x70, 0x21, 0x46, 0xAF, 0x48, 0xFD, 0xF5, 0xA4, 0xFC, 0xA7, 0x49, 0x03, 0x46, 0x02, 0x22, 0x38, 0x31, + 0xA4, 0x48, 0x00, 0x96, 0xFD, 0xF5, 0xDF, 0xFA, 0x38, 0x46, 0xBF, 0xE7, 0x07, 0x20, 0xBD, 0xE7, 0x70, 0xB5, 0x0D, 0x46, 0x43, 0xF6, 0x22, 0xFA, 0x04, 0x00, 0x2A, 0xD0, 0xA5, 0x48, 0x9E, 0x49, 0x01, 0x22, 0x03, 0x78, 0x9B, 0x48, 0x74, 0x31, + 0x40, 0x1C, 0xFD, 0xF5, 0xCC, 0xFA, 0x97, 0x49, 0x01, 0x22, 0x08, 0x78, 0xB2, 0xEB, 0x90, 0x1F, 0x0A, + 0xD1, 0x62, 0x78, 0x03, 0x2A, 0x07, 0xD1, 0xA2, 0x78, 0x01, 0x2A, 0x04, 0xD1, 0x22, 0x8A, 0x12, 0xB9, 0x20, 0xF0, 0xC0, 0x00, 0x08, 0x70, 0xE0, 0x78, 0x2A, 0x46, 0x00, 0x21, 0x48, 0xF6, 0xD4, 0xF8, 0x00, 0x20, 0x42, 0xF6, 0xE5, 0xFC, 0xE0, + 0x6A, 0x08, 0xB1, 0x1B, 0xF6, 0xBB, 0xFC, 0x20, 0x46, 0xBD, 0xE8, 0x70, 0x40, 0x43, 0xF6, 0xE4, 0xB9, 0x89, 0x49, 0xBD, 0xE8, 0x70, 0x40, 0x86, 0x48, 0x00, 0x22, 0xA4, 0x31, 0x80, 0x1E, 0xFD, 0xF5, 0xA1, 0xBA, 0x43, 0x88, 0x33, 0xB1, 0x83, + 0x49, 0x82, 0x48, 0x01, 0x22, 0xD4, 0x31, 0x80, 0x1E, 0xFD, 0xF5, 0x98, 0xBA, 0x81, 0x88, 0x00, 0x88, 0xB9, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x41, 0x88, 0x00, 0x88, 0xFF, 0xF7, 0xB4, 0xFF, 0x20, 0x88, 0xBD, 0xE8, 0x10, 0x40, 0x17, 0xF6, 0x63, + 0xB9, 0x10, 0xB5, 0x8A, 0xB0, 0x0C, 0x46, 0x00, 0x21, 0x21, 0x70, 0x09, 0xAA, 0x07, 0xA9, 0x43, 0xF6, 0x49, 0xFB, 0xB8, 0xB1, 0x9D, 0xF8, 0x24, 0x10, 0x07, 0xA8, 0x45, 0xF6, 0x13, 0xFE, 0x88, 0xB1, 0x6A, 0x46, 0x11, 0x21, 0x45, 0xF6, 0xF9, + 0xFE, 0x60, 0xB1, 0x9D, 0xF8, 0x1B, 0x30, 0x01, 0x22, 0x75, 0x49, 0x6B, 0x48, 0xFD, 0xF5, 0x6E, 0xFA, 0x9D, 0xF8, 0x1B, 0x00, 0x20, 0x70, 0x00, 0x20, 0x0A, + 0xB0, 0x10, 0xBD, 0x03, 0x20, 0xFB, 0xE7, 0x70, 0x48, 0x00, 0x88, 0x70, 0x47, 0x2D, 0xE9, 0xF8, 0x4F, 0x0F, 0x46, 0x05, 0x00, 0x08, 0xD0, 0x62, 0x4B, 0x28, 0x78, 0x9B, 0x1E, 0x01, 0x28, 0x06, 0xD0, 0x68, 0x49, 0x00, 0x22, 0x48, 0x31, 0x0B, + 0xE0, 0x00, 0x20, 0xBD, 0xE8, 0xF8, 0x8F, 0x67, 0x48, 0x69, 0x78, 0x00, 0x78, 0x40, 0x1E, 0x81, 0x42, 0x06, 0xDD, 0x62, 0x49, 0x00, 0x22, 0x20, 0x31, 0x18, 0x46, 0xFD, 0xF5, 0x46, 0xFA, 0xEF, 0xE7, 0xDF, 0xF8, 0x7C, 0x81, 0x38, 0x46, 0xB8, + 0xF8, 0x00, 0x10, 0x8E, 0x08, 0x4F, 0xF6, 0x1C, 0xFD, 0x00, 0x24, 0xDF, 0xF8, 0x74, 0x91, 0xDF, 0xF8, 0x74, 0xA1, 0x11, 0xE0, 0x68, 0x78, 0x00, 0x90, 0xB9, 0xF8, 0x00, 0x10, 0xBA, 0xF8, 0x00, 0x00, 0x04, 0x23, 0x08, 0x44, 0x00, 0xEB, 0x84, + 0x00, 0x81, 0xB2, 0x07, 0xEB, 0x84, 0x00, 0xB8, 0xF8, 0x00, 0x20, 0x46, 0xF6, 0x0B, 0xFD, 0x64, 0x1C, 0xB4, 0x42, 0xEB, 0xDB, 0x01, 0x20, 0xCC, 0xE7, 0x30, 0xB5, 0xA7, 0xB0, 0x04, 0x00, 0x07, 0xD0, 0x04, 0xF1, 0x08, 0x00, 0x61, 0x78, 0x05, + 0x46, 0x46, 0xF6, 0xD0, 0xFD, 0x18, 0xB1, 0x14, 0xE0, 0x00, 0x20, 0x27, 0xB0, 0x30, 0xBD, 0xE0, 0x7B, 0xC1, 0x07, 0x0E, 0xD0, 0x01, 0x21, 0x21, 0x70, 0x62, 0x88, 0x83, 0x07, 0x42, 0xF0, 0x01, 0x02, 0x62, 0x80, 0x02, 0xD5, 0x42, 0xF0, 0x80, + 0x02, 0x62, 0x80, 0x40, 0x07, 0x04, 0xD5, 0x21, 0x71, 0x02, 0xE0, 0x20, 0x78, 0x01, 0x28, 0x5D, 0xD1, 0x61, 0x78, 0x0A, + 0xA8, 0x46, 0xF6, 0xF4, 0xFD, 0x30, 0xB9, 0x9D, 0xF8, 0x28, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x02, 0x00, 0x60, 0x80, 0x61, 0x78, 0x12, 0xA8, 0x46, 0xF6, 0x31, 0xFE, 0x30, 0xB9, 0x9D, 0xF8, 0x48, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, + 0xF0, 0x04, 0x00, 0x60, 0x80, 0x61, 0x78, 0x04, 0xA8, 0x46, 0xF6, 0x93, 0xFE, 0x70, 0xB9, 0x9D, 0xF8, 0x27, 0x00, 0x58, 0xB1, 0x08, 0x98, 0x20, 0x61, 0xBD, 0xF8, 0x24, 0x00, 0xA0, 0x82, 0x9D, 0xF8, 0x26, 0x00, 0xA0, 0x75, 0x60, 0x88, 0x40, + 0xF0, 0x08, 0x00, 0x60, 0x80, 0x61, 0x78, 0x1A, 0xA8, 0x46, 0xF6, 0x48, 0xFF, 0x30, 0xB9, 0x9D, 0xF8, 0x7D, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x10, 0x00, 0x60, 0x80, 0x61, 0x78, 0x20, 0xA8, 0x46, 0xF6, 0xA9, 0xFF, 0x30, 0xB9, 0x9D, + 0xF8, 0x95, 0x00, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x20, 0x00, 0x60, 0x80, 0x60, 0x78, 0x47, 0xF6, 0x13, 0xF8, 0x18, 0xB1, 0x60, 0x88, 0x40, 0xF0, 0x40, 0x00, 0x60, 0x80, 0x29, 0x46, 0x12, 0x48, 0xFD, 0xF5, 0x6A, 0xFB, 0x22, 0x79, 0x61, + 0x88, 0xA3, 0x7B, 0xCD, 0xE9, 0x02, 0x12, 0xCD, 0xE9, 0x00, 0x03, 0x0F, 0x49, 0x63, 0x78, 0x05, 0x22, 0x7C, 0x31, 0x04, 0x48, 0xFD, 0xF5, 0x9F, 0xF9, 0x01, 0x20, 0x88, 0xE7, 0x38, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0x02, 0x35, 0x10, + 0x21, 0x00, 0x22, 0x80, 0x08, 0x64, 0x2E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x30, 0x21, 0x60, 0x2E, 0x20, 0x00, 0x08, 0x23, 0x80, 0x08, 0xEE, 0x2E, 0x20, + 0x00, 0xBC, 0x2E, 0x20, 0x00, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x2D, 0xE9, 0xFE, 0x43, 0x88, 0x46, 0x98, 0x4D, 0x00, 0x21, 0x11, 0x70, 0x29, 0x88, 0x97, 0x4E, 0x17, 0x46, 0x88, 0x42, 0x02, 0xD0, 0x00, 0x22, 0x95, 0x49, 0x49, + 0xE0, 0xD8, 0xF8, 0x00, 0x10, 0x01, 0x91, 0xD8, 0xF8, 0x04, 0x00, 0x02, 0x90, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x45, 0xF6, 0xFC, 0xFC, 0x04, 0x00, 0x06, 0xD1, 0x9D, 0xF8, 0x0A, + 0x10, 0x01, 0xA8, 0x46, 0xF6, 0x55, 0xF8, 0x04, 0x00, 0x08, 0xD0, 0x01, 0x20, 0x8A, 0x49, 0x38, 0x70, 0x00, 0x22, 0x34, 0x31, 0x30, 0x46, 0xFD, 0xF5, 0x53, 0xF9, 0x39, 0xE0, 0x9D, 0xF8, 0x0B, 0x00, 0x00, 0x27, 0x40, 0x07, 0x00, 0xD5, 0x01, + 0x27, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x45, 0xF6, 0x77, 0xFD, 0x04, 0x00, 0x0D, 0xD1, 0x45, 0xF6, 0xE3, 0xFF, 0x50, 0xB3, 0x40, 0x78, 0x41, 0xF6, 0xC5, 0xFC, 0x9D, 0xF8, 0x0A, + 0x10, 0x3A, 0x46, 0x01, 0xA8, 0x45, 0xF6, 0x69, 0xFD, 0x04, 0x00, 0x1F, 0xD0, 0x60, 0x78, 0x00, 0x90, 0x78, 0x48, 0x78, 0x49, 0x2A, 0x88, 0x00, 0x88, 0x09, 0x88, 0xD3, 0xB2, 0x08, 0x44, 0x81, 0xB2, 0x40, 0x46, 0x46, 0xF6, 0xEE, 0xFB, 0x40, + 0xB1, 0x71, 0x49, 0x00, 0x22, 0x64, 0x31, 0x30, 0x46, 0xFD, 0xF5, 0x22, 0xF9, 0x00, 0x20, 0xBD, 0xE8, 0xFE, 0x83, 0x61, 0x78, 0x01, 0x20, 0x46, 0xF6, 0xF9, 0xFA, 0x20, 0x46, 0xFF, 0xF7, 0xF7, 0xFE, 0x20, 0x46, 0xF4, 0xE7, 0x68, 0x49, 0x00, + 0x22, 0xA4, 0x31, 0xEC, 0xE7, 0x00, 0xB5, 0x91, 0xB0, 0x4F, 0xF4, 0xE8, 0x71, 0xAD, 0xF8, 0x00, 0x10, 0xAD, 0xF8, 0x04, 0x00, 0x01, 0x21, 0x68, 0x46, 0x16, 0xF6, 0xD0, 0xFD, 0x11, 0xB0, 0x00, 0xBD, 0x10, 0xB5, 0x04, 0x46, 0x01, 0x46, 0x60, + 0x48, 0x43, 0xF6, 0xDB, 0xF8, 0x68, 0xB1, 0x5F, 0x49, 0x04, 0xEB, 0x44, 0x00, 0x09, 0x68, 0x01, 0xEB, 0x00, 0x10, 0x00, 0x8A, 0xFF, 0xF7, 0xE2, 0xFF, 0x08, 0xB1, 0x00, 0x20, 0x10, 0xBD, 0x07, 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0x7F, + 0xB5, 0x58, 0x4D, 0x04, 0x46, 0x28, 0x68, 0x00, 0x28, 0x19, 0xD0, 0x60, 0x88, 0x43, 0xF6, 0x2F, 0xF8, 0x00, 0x28, 0x14, 0xD0, 0xC0, 0x78, 0x8D, 0xF8, 0x00, 0x00, 0x20, 0x88, 0xAD, 0xF8, 0x02, 0x00, 0x20, 0x79, 0x8D, 0xF8, 0x04, 0x00, 0xE0, + 0x88, 0xAD, 0xF8, 0x06, 0x00, 0x20, 0x89, 0xAD, 0xF8, 0x08, 0x00, 0xCD, 0xF8, 0x0C, 0xD0, 0x2A, 0x68, 0x03, 0xA9, 0x1B, 0x20, 0x90, 0x47, 0x7F, 0xBD, 0x10, 0xB5, 0x41, 0x88, 0x01, 0x24, 0xA1, 0xF5, 0x80, 0x71, 0xD1, 0x39, 0x02, 0xD0, 0x00, + 0x24, 0x20, 0x46, 0x10, 0xBD, 0x00, 0x1D, 0xFF, 0xF7, 0xD2, 0xFF, 0xF9, 0xE7, 0x70, 0xB5, 0x0C, 0x46, 0x05, 0x46, 0x01, 0x46, 0x3D, 0x48, 0x86, 0xB0, 0x17, 0x30, 0x43, 0xF6, 0x92, 0xF8, 0x90, 0xB3, 0x61, 0x1E, 0x4F, 0xF6, 0xFF, 0x72, 0x39, + 0x4B, 0x05, 0xEB, 0x45, 0x00, 0x91, 0x42, 0x0E, 0xD2, 0x19, 0x68, 0x01, 0xEB, 0x00, 0x11, 0x8A, 0x8A, 0x02, 0xEB, 0x82, 0x02, 0x96, 0x08, 0xCA, 0x8A, 0x52, 0x1C, 0x56, 0x43, 0x04, 0xEB, 0x84, 0x02, 0xB6, 0xEB, 0x42, 0x0F, 0x1C, 0xDD, 0x19, + 0x68, 0x01, 0xEB, 0x00, 0x10, 0x81, 0x8A, 0xC0, 0x8A, 0x01, 0xEB, 0x81, 0x02, 0x92, 0x08, 0x43, 0x1C, 0x5A, 0x43, 0x04, 0xEB, 0x84, 0x03, 0x5B, 0x00, 0xCD, 0xE9, 0x00, 0x41, 0xCD, 0xE9, 0x02, 0x03, 0x23, 0x49, 0x04, 0x92, 0x2B, 0x46, 0x06, + 0x22, 0xC4, 0x31, 0x1F, 0x48, 0xFD, 0xF5, 0x84, 0xF8, 0x03, 0x20, 0x06, 0xB0, 0x70, 0xBD, 0x15, 0xE0, 0x08, 0x8A, 0x8D, 0xF8, 0x14, 0x00, 0x00, 0x0A, + 0x8D, 0xF8, 0x15, 0x00, 0x8D, 0xF8, 0x16, 0x40, 0x20, 0x0A, + 0x8D, 0xF8, 0x17, 0x00, 0x05, 0xAA, 0x04, 0x21, 0x40, 0xF6, 0x7C, 0x40, 0x16, 0xF6, 0xB6, 0xFD, 0x08, 0xB1, 0x00, 0x20, 0xE8, 0xE7, 0x07, 0x20, 0xE6, 0xE7, 0x04, 0x20, 0xE4, 0xE7, 0x10, 0xB5, 0x04, 0x46, 0x01, 0x46, 0x12, 0x48, 0x37, 0x30, + 0x43, 0xF6, 0x3E, 0xF8, 0xA0, 0xB1, 0x11, 0x49, 0x04, 0xEB, 0x44, 0x00, 0x09, 0x68, 0x01, 0xEB, 0x00, 0x10, 0x00, 0x8A, 0x14, 0xF6, 0x21, 0xFD, 0x40, 0xB1, 0x41, 0x8D, 0x17, 0x29, 0x03, 0xD3, 0x11, 0xF6, 0xF7, 0xFE, 0x00, 0x20, 0x10, 0xBD, + 0x03, 0x20, 0x10, 0xBD, 0x0A, + 0x20, 0x10, 0xBD, 0x04, 0x20, 0x10, 0xBD, 0xEE, 0x2E, 0x20, 0x00, 0x00, 0x35, 0x10, 0x21, 0xE0, 0x23, 0x80, 0x08, 0xF0, 0x2E, 0x20, 0x00, 0xE0, 0x2E, 0x20, 0x00, 0x9C, 0xB5, 0x20, 0x00, 0x64, 0x2E, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0xFD, + 0x49, 0x08, 0x60, 0x70, 0x47, 0x08, 0xB5, 0xC1, 0x1E, 0x40, 0xF2, 0xFE, 0x72, 0x91, 0x42, 0x01, 0xD3, 0x00, 0x20, 0x08, 0xBD, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x8D, 0xF8, 0x01, 0x00, 0x00, 0x0A, + 0x8D, 0xF8, 0x02, 0x00, 0x6A, 0x46, 0x03, 0x21, 0x4F, 0xF6, 0x6E, 0x40, 0x16, 0xF6, 0x67, 0xFD, 0x00, 0x28, 0xEE, 0xD0, 0x01, 0x20, 0x08, 0xBD, 0x30, 0xB5, 0xEF, 0x4B, 0x1D, 0x68, 0x1B, 0x1D, 0x1C, 0x68, 0x1B, 0x1D, 0x1B, 0x68, 0x05, 0x60, + 0x0C, 0x60, 0x13, 0x60, 0x30, 0xBD, 0x08, 0xB5, 0x0F, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x6A, 0x46, 0x01, 0x21, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, 0x4E, 0xFD, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x2D, 0xE9, 0xF8, 0x43, + 0x01, 0x88, 0x4F, 0xF6, 0x80, 0x58, 0xE1, 0x4D, 0x04, 0x46, 0x41, 0x45, 0x21, 0xD1, 0xA0, 0x79, 0x0F, 0x28, 0x04, 0xD0, 0x13, 0x28, 0x07, 0xD0, 0x14, 0x28, 0x1A, 0xD1, 0x09, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAC, 0x20, 0x10, 0xE0, + 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xA8, 0x20, 0x0B, 0xE0, 0xE0, 0x79, 0x21, 0x7A, 0xA2, 0x7A, 0x00, 0xEB, 0x01, 0x20, 0x61, 0x7A, 0x09, 0x04, 0x01, 0xEB, 0x02, 0x61, 0x08, 0x44, 0x00, 0x90, 0xAE, 0x20, 0x2A, 0x68, 0x0A, + 0xB1, 0x69, 0x46, 0x90, 0x47, 0x20, 0x88, 0x4F, 0xF6, 0x6E, 0x46, 0xB0, 0x42, 0x07, 0xD1, 0x60, 0x79, 0x28, 0xB9, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0x2A, 0x68, 0xA6, 0x20, 0x62, 0xBB, 0x20, 0x88, 0x4F, 0xF6, 0x82, 0x57, 0xB8, 0x42, 0x1C, + 0xD1, 0xA0, 0x79, 0x05, 0x28, 0x19, 0xD1, 0xE0, 0x79, 0x09, 0x28, 0x04, 0xD0, 0x1E, 0x28, 0x07, 0xD0, 0x1F, 0x28, 0x12, 0xD1, 0x09, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAB, 0x20, 0x08, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAA, + 0x20, 0x03, 0xE0, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0xAD, 0x20, 0x2A, 0x68, 0x0A, + 0xB1, 0x69, 0x46, 0x90, 0x47, 0x20, 0x88, 0xA0, 0xF5, 0x7D, 0x41, 0x87, 0x39, 0x09, 0xD1, 0x60, 0x88, 0xAD, 0xF8, 0x00, 0x00, 0x2A, 0x68, 0xAF, 0x20, 0x1A, 0xB1, 0x69, 0x46, 0x90, 0x47, 0xBD, 0xE8, 0xF8, 0x83, 0x20, 0x88, 0x40, 0x45, 0xFA, + 0xD0, 0xA0, 0xF5, 0x7D, 0x41, 0x81, 0x39, 0xF6, 0xD0, 0xB8, 0x42, 0xF4, 0xD0, 0xB0, 0x42, 0xF2, 0xD0, 0xAB, 0x48, 0x02, 0x68, 0x00, 0x2A, 0xEE, 0xD0, 0x03, 0x20, 0x69, 0x46, 0x00, 0x94, 0x90, 0x47, 0xE9, 0xE7, 0x10, 0xB5, 0x16, 0xF6, 0xC9, + 0xFC, 0x08, 0xB1, 0x00, 0x20, 0x10, 0xBD, 0x07, 0x20, 0x10, 0xBD, 0x01, 0x46, 0xA2, 0x48, 0x08, 0xB5, 0x02, 0x68, 0x00, 0x2A, 0x03, 0xD0, 0x00, 0x91, 0x04, 0x20, 0x69, 0x46, 0x90, 0x47, 0x08, 0xBD, 0x0E, 0xB5, 0x10, 0x22, 0x8D, 0xF8, 0x00, + 0x20, 0x8D, 0xF8, 0x01, 0x00, 0x02, 0x0A, + 0x8D, 0xF8, 0x02, 0x20, 0x02, 0x0C, 0x00, 0x0E, 0x8D, 0xF8, 0x04, 0x00, 0x8D, 0xF8, 0x05, 0x10, 0x08, 0x0A, + 0x8D, 0xF8, 0x06, 0x00, 0x08, 0x0C, 0x8D, 0xF8, 0x07, 0x00, 0x08, 0x0E, 0x8D, 0xF8, 0x03, 0x20, 0x8D, 0xF8, 0x08, 0x00, 0x6A, 0x46, 0x09, 0x21, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, 0x99, 0xFC, 0x08, 0xB1, 0x00, 0x20, 0x0E, 0xBD, 0x07, 0x20, + 0x0E, 0xBD, 0x0A, + 0x28, 0x01, 0xD9, 0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x70, 0x47, 0x30, 0xB5, 0x8B, 0xB0, 0x04, 0x46, 0x2C, 0x21, 0x68, 0x46, 0x4F, 0xF6, 0x41, 0xFA, 0x13, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x20, 0x78, 0x00, 0x22, 0x01, 0x21, 0x02, 0x28, 0x03, + 0xD0, 0x01, 0x28, 0x07, 0xD0, 0x48, 0xB1, 0x90, 0xE0, 0x8D, 0xF8, 0x01, 0x10, 0x8D, 0xF8, 0x02, 0x20, 0x03, 0x21, 0x82, 0xE0, 0x8D, 0xF8, 0x01, 0x10, 0x01, 0xE0, 0x8D, 0xF8, 0x01, 0x20, 0xE0, 0x79, 0x02, 0x28, 0x0D, 0xD1, 0x20, 0x7A, 0xFF, + 0xF7, 0xD6, 0xFF, 0x00, 0x28, 0x7D, 0xD0, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x01, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0x20, 0x7A, 0x8D, 0xF8, 0x03, 0x00, 0x60, 0x78, 0x01, 0x28, 0x0D, 0xD1, 0xA0, 0x78, 0xFF, 0xF7, 0xC5, 0xFF, 0x00, 0x28, 0x6C, + 0xD0, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x04, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0xA0, 0x78, 0x8D, 0xF8, 0x04, 0x00, 0x60, 0x79, 0x01, 0x28, 0x0C, 0xD1, 0xA0, 0x79, 0xFF, 0xF7, 0xB4, 0xFF, 0xE0, 0xB3, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x08, + 0x00, 0x8D, 0xF8, 0x02, 0x00, 0xA0, 0x79, 0x8D, 0xF8, 0x05, 0x00, 0xE0, 0x78, 0x01, 0x28, 0x0C, 0xD1, 0x20, 0x79, 0xFF, 0xF7, 0xA4, 0xFF, 0x60, 0xB3, 0x9D, 0xF8, 0x02, 0x00, 0x40, 0xF0, 0x10, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0x20, 0x79, 0x8D, + 0xF8, 0x06, 0x00, 0xE0, 0x79, 0x07, 0x21, 0x01, 0x28, 0x37, 0xD1, 0x60, 0x7A, 0x40, 0x1E, 0x0B, 0x28, 0x3B, 0xD2, 0x9D, 0xF8, 0x02, 0x00, 0x00, 0x21, 0x40, 0xF0, 0x02, 0x00, 0x8D, 0xF8, 0x02, 0x00, 0x60, 0x7A, 0x8D, 0xF8, 0x07, 0x00, 0x1F, + 0xE0, 0x04, 0xEB, 0x41, 0x00, 0x82, 0x7A, 0x02, 0xEB, 0x42, 0x03, 0x4C, 0x4A, 0x12, 0x68, 0x02, 0xEB, 0x03, 0x13, 0x1A, 0x8A, 0x5D, 0x78, 0xC3, 0x7A, 0x02, 0x2D, 0x03, 0xD0, 0x02, 0x20, 0x0B, 0xB0, 0x30, 0xBD, 0x1E, 0xE0, 0x18, 0x46, 0xFF, + 0xF7, 0x72, 0xFF, 0xD0, 0xB1, 0x01, 0xEB, 0x41, 0x05, 0x68, 0x46, 0x28, 0x44, 0x02, 0x72, 0x12, 0x0A, + 0x42, 0x72, 0x49, 0x1C, 0x83, 0x72, 0xC9, 0xB2, 0x9D, 0xF8, 0x07, 0x00, 0x88, 0x42, 0xDB, 0xD8, 0xC0, 0xB2, 0x00, 0xEB, 0x40, 0x00, 0x08, 0x30, 0xC1, 0xB2, 0x6A, 0x46, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, 0xED, 0xFB, 0x18, 0xB1, 0x00, 0x20, + 0xDD, 0xE7, 0x03, 0x20, 0xDB, 0xE7, 0x07, 0x20, 0xD9, 0xE7, 0x08, 0xB5, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x09, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x00, 0xB1, 0x01, 0x20, 0x8D, 0xF8, 0x02, 0x00, 0x6A, 0x46, 0x03, 0x21, 0x4F, 0xF6, 0x82, 0x50, + 0x16, 0xF6, 0xD5, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x1E, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x00, 0xB1, 0x01, 0x20, 0x8D, 0xF8, 0x02, 0x00, 0x6A, 0x46, 0x03, 0x21, + 0x4F, 0xF6, 0x82, 0x50, 0x16, 0xF6, 0xBF, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x05, 0x21, 0x8D, 0xF8, 0x00, 0x10, 0x1F, 0x21, 0x8D, 0xF8, 0x01, 0x10, 0x00, 0xB1, 0x01, 0x20, 0x8D, 0xF8, 0x02, 0x00, + 0x6A, 0x46, 0x03, 0x21, 0x4F, 0xF6, 0x82, 0x50, 0x16, 0xF6, 0xA9, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x08, 0xB5, 0x14, 0x20, 0x8D, 0xF8, 0x00, 0x00, 0x6A, 0x46, 0x01, 0x21, 0x4F, 0xF6, 0x80, 0x50, 0x16, 0xF6, + 0x9A, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x08, 0xBD, 0x07, 0x20, 0x08, 0xBD, 0x1C, 0xB5, 0x0A, + 0x00, 0x4F, 0xF0, 0x08, 0x01, 0x8D, 0xF8, 0x00, 0x10, 0x8D, 0xF8, 0x01, 0x00, 0x11, 0xD0, 0x10, 0x68, 0xCD, 0xF8, 0x02, 0x00, 0x10, 0x79, 0x07, 0x21, 0x8D, 0xF8, 0x06, 0x00, 0x0A, + 0xE0, 0x04, 0xC4, 0x20, 0x00, 0x1C, 0x1B, 0x20, 0x00, 0x48, 0x2E, 0x20, 0x00, 0xF4, 0x2D, 0x20, 0x00, 0x64, 0x2E, 0x20, 0x00, 0x02, 0x21, 0x6A, 0x46, 0x4F, 0xF6, 0x87, 0x50, 0x16, 0xF6, 0x74, 0xFB, 0x08, 0xB1, 0x00, 0x20, 0x1C, 0xBD, 0x07, + 0x20, 0x1C, 0xBD, 0x00, 0x00, 0x0B, 0x49, 0x10, 0xB5, 0xA1, 0xF1, 0x7C, 0x02, 0x0A, + 0x4C, 0xC2, 0xE9, 0x37, 0x12, 0x37, 0x21, 0x06, 0xE0, 0x00, 0xEB, 0x10, 0x43, 0x42, 0xF8, 0x21, 0x30, 0x07, 0x4B, 0x00, 0xFB, 0x03, 0x40, 0x0B, 0x1E, 0xA1, 0xF1, 0x01, 0x01, 0xF4, 0xDC, 0x10, 0xBD, 0x01, 0x20, 0xE8, 0xE7, 0x00, 0x00, 0x84, + 0xC4, 0x20, 0x00, 0xE1, 0x19, 0xD6, 0x66, 0xCD, 0x0D, 0x01, 0x00, 0x10, 0xB5, 0x04, 0x46, 0x0E, 0x48, 0x00, 0x68, 0x28, 0xB1, 0x4F, 0xF0, 0xFF, 0x31, 0x1B, 0xF6, 0x3B, 0xFD, 0x00, 0x28, 0x10, 0xD0, 0x0B, 0x48, 0x04, 0x70, 0x4F, 0xF4, 0x00, + 0x10, 0x90, 0xF8, 0x50, 0x03, 0x41, 0x07, 0x09, 0xD0, 0xEF, 0xF3, 0x11, 0x81, 0x07, 0x4A, 0x40, 0x07, 0x00, 0x0E, 0x80, 0xF3, 0x11, 0x88, 0x11, 0x60, 0x01, 0x20, 0x10, 0xBD, 0x72, 0xB6, 0xFB, 0xE7, 0x00, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, + 0x04, 0x20, 0x00, 0xAC, 0x0C, 0x20, 0x00, 0x70, 0xB5, 0x05, 0x46, 0x00, 0x24, 0x07, 0x20, 0xFF, 0xF7, 0xD4, 0xFF, 0x00, 0x28, 0x09, 0xD0, 0x28, 0x46, 0xFF, 0xF5, 0x70, 0xFB, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x00, 0xF0, 0x71, + 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x70, 0xB5, 0x06, 0x46, 0x0D, 0x46, 0x00, 0x24, 0x07, 0x20, 0xFF, 0xF7, 0xC0, 0xFF, 0x00, 0x28, 0x0A, + 0xD0, 0x29, 0x46, 0x30, 0x46, 0x00, 0xF0, 0x08, 0xF8, 0x01, 0x28, 0x00, 0xD1, 0x01, 0x24, 0x07, 0x20, 0x00, 0xF0, 0x5C, 0xF8, 0x20, 0x46, 0x70, 0xBD, 0x2D, 0xE9, 0xF0, 0x5F, 0x8B, 0x46, 0x80, 0x46, 0x29, 0x4C, 0x01, 0xF6, 0x22, 0xF8, 0x04, + 0x28, 0x02, 0xD2, 0x00, 0x20, 0xBD, 0xE8, 0xF0, 0x9F, 0x25, 0x7A, 0x94, 0xF8, 0x00, 0x90, 0x66, 0x68, 0x28, 0xF0, 0x80, 0x74, 0x00, 0x27, 0x4F, 0xF4, 0x00, 0x0A, + 0x06, 0xF5, 0x00, 0x08, 0x54, 0x45, 0x01, 0xD3, 0x44, 0x45, 0x02, 0xD9, 0x6F, 0xF0, 0x02, 0x00, 0xEB, 0xE7, 0x58, 0x46, 0xFF, 0xF5, 0x08, 0xFB, 0x01, 0x28, 0xE6, 0xD1, 0x9B, 0xF8, 0x00, 0x00, 0x78, 0xB3, 0xB9, 0xF1, 0xFF, 0x0F, 0x06, 0xD0, + 0xB9, 0xF1, 0x7F, 0x0F, 0x06, 0xD0, 0x44, 0x45, 0x0B, 0xD1, 0x2F, 0x46, 0x22, 0xE0, 0x44, 0x45, 0xFB, 0xD0, 0x1F, 0xE0, 0x0A, + 0xEB, 0x56, 0x00, 0xA0, 0x42, 0x1B, 0xD8, 0x6D, 0x1E, 0xEF, 0xB2, 0x18, 0xE0, 0x01, 0x20, 0x6A, 0x1E, 0x00, 0xFA, 0x02, 0xF1, 0x11, 0xE0, 0xB6, 0xFB, 0xF1, 0xF3, 0x42, 0x1E, 0x93, 0x40, 0xB6, 0xFB, 0xF1, 0xF2, 0x82, 0x40, 0x03, 0xF5, 0x00, + 0x03, 0x02, 0xF5, 0x00, 0x02, 0x9C, 0x42, 0x03, 0xD3, 0x94, 0x42, 0x01, 0xD2, 0xC7, 0xB2, 0x02, 0xE0, 0x40, 0x1C, 0xA8, 0x42, 0xEB, 0xDB, 0x38, 0x46, 0xFF, 0xF5, 0xFD, 0xFA, 0x01, 0x20, 0xB1, 0xE7, 0xDC, 0x0C, 0x20, 0x00, 0x10, 0xB5, 0x4F, + 0xF4, 0x00, 0x10, 0x90, 0xF8, 0x50, 0x03, 0x40, 0x07, 0x0C, 0xD0, 0x07, 0x48, 0x00, 0x78, 0x80, 0xF3, 0x11, 0x88, 0x06, 0x48, 0x00, 0x68, 0x08, 0xB1, 0x1B, 0xF6, 0x9F, 0xFC, 0x04, 0x49, 0xFF, 0x20, 0x08, 0x70, 0x10, 0xBD, 0x62, 0xB6, 0xF4, + 0xE7, 0xAC, 0x0C, 0x20, 0x00, 0x40, 0x0D, 0x20, 0x00, 0xF9, 0x04, 0x20, 0x00, 0x4F, 0xF0, 0x40, 0x70, 0xE1, 0xEE, 0x10, 0x0A, + 0x70, 0x47, 0x00, 0x00, 0x01, 0xD1, 0x85, 0x0E, 0x07, 0x00, 0x00, 0x00, 0x19, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x80, 0x20, 0x00, 0x35, 0x80, 0x20, 0x00, + 0x6D, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x63, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x72, 0x65, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x00, 0x00, 0x00, 0x2C, 0xB7, 0x20, 0x00, 0xD8, 0xB7, 0x20, 0x00, 0x20, 0xB7, 0x20, 0x00, 0xE0, 0xB7, 0x20, 0x00, + 0x84, 0xB7, 0x20, 0x00, 0xF8, 0xB7, 0x20, 0x00, 0xEC, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, 0x14, 0xB7, 0x20, 0x00, 0xCC, 0xB7, 0x20, 0x00, 0x74, 0xB7, 0x20, 0x00, + 0x3C, 0xB7, 0x20, 0x00, 0x9C, 0xB7, 0x20, 0x00, 0xB0, 0xB7, 0x20, 0x00, 0x1C, 0xB7, 0x20, 0x00, 0x04, 0xB7, 0x20, 0x00, 0x84, 0xB6, 0x20, 0x00, 0x58, 0xB6, 0x20, 0x00, 0xB8, 0xB7, 0x20, 0x00, 0x6C, 0xB7, 0x20, 0x00, 0x58, 0xB7, 0x20, 0x00, + 0xF0, 0xB6, 0x20, 0x00, 0xB0, 0xB6, 0x20, 0x00, 0xD0, 0xB6, 0x20, 0x00, 0x34, 0xB6, 0x20, 0x00, 0x00, 0xB6, 0x20, 0x00, 0x10, 0xB7, 0x20, 0x00, 0xF8, 0xB5, 0x20, 0x00, 0x2C, 0xB6, 0x20, 0x00, 0xF0, 0xB5, 0x20, 0x00, 0x24, 0xB6, 0x20, 0x00, + 0x0C, 0xB7, 0x20, 0x00, 0xA4, 0xB7, 0x20, 0x00, 0x08, 0xB6, 0x20, 0x00, 0x3C, 0xB6, 0x20, 0x00, 0x68, 0xB6, 0x20, 0x00, 0x8C, 0xB6, 0x20, 0x00, 0xB8, 0xB6, 0x20, 0x00, 0xD8, 0xB6, 0x20, 0x00, 0x9C, 0xB6, 0x20, 0x00, 0x78, 0xB6, 0x20, 0x00, + 0x38, 0xB7, 0x20, 0x00, 0x4C, 0xB6, 0x20, 0x00, 0x18, 0xB6, 0x20, 0x00, 0x60, 0xB6, 0x20, 0x00, 0xA8, 0xB6, 0x20, 0x00, 0xC8, 0xB6, 0x20, 0x00, 0xE8, 0xB6, 0x20, 0x00, 0xFC, 0xB6, 0x20, 0x00, 0x90, 0xB7, 0x20, 0x00, 0x7C, 0xB7, 0x20, 0x00, + 0xC4, 0xB7, 0x20, 0x00, 0x44, 0xB7, 0x20, 0x00, 0x24, 0xB7, 0x20, 0x00, 0x04, 0xB8, 0x20, 0x00, 0x60, 0xB7, 0x20, 0x00, 0x4C, 0xB7, 0x20, 0x00, 0x18, 0xB7, 0x20, 0x00, 0x02, 0x08, 0x00, 0x28, 0x0A, + 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x01, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x32, 0xB8, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0xB0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0xEF, 0x81, 0x20, 0x00, 0x55, 0x82, 0x20, 0x00, 0x31, 0x83, 0x20, 0x00, 0x02, 0x08, 0x00, 0x28, 0x0F, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x19, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x53, 0x84, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x84, 0x20, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0xFF, + 0xD0, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xE8, 0xB2, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD2, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD3, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD4, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x04, 0x00, 0xD5, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xD8, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF1, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xF2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x03, 0x28, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xF9, 0x85, 0x20, 0x00, 0x5D, 0x85, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, + 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0x92, 0x20, 0x00, 0xED, 0x92, 0x20, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x6D, 0x61, 0x69, 0x6E, 0x5F, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x61, 0x70, 0x70, 0x5F, 0x73, 0x65, 0x6E, 0x64, 0x5F, 0x6D, 0x73, + 0x67, 0x5F, 0x74, 0x6F, 0x5F, 0x61, 0x70, 0x70, 0x74, 0x61, 0x73, 0x6B, 0x00, 0x00, 0x00, 0x03, 0x19, 0x00, 0x00, 0x02, 0x01, 0x05, 0x03, 0x03, 0x0A, + 0xA0, 0x0B, 0x09, 0x52, 0x65, 0x61, 0x6C, 0x54, 0x65, 0x6B, 0x44, 0x66, 0x75, 0x00, 0x42, 0x4C, 0x45, 0x5F, 0x4F, 0x54, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x65, 0x5F, 0x72, 0x65, 0x61, 0x64, 0x5F, 0x72, 0x65, 0x6D, 0x6F, 0x74, 0x65, 0x5F, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x6C, 0x65, 0x5F, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x5F, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6E, 0x5F, 0x70, 0x61, 0x79, 0x6C, 0x6F, 0x61, 0x64, 0x5F, 0x74, 0x69, 0x6D, 0x65, 0x6F, 0x75, 0x74, 0x00, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x5F, 0x73, 0x65, 0x6E, 0x64, + 0x5F, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6E, 0x67, 0x65, 0x5F, 0x6D, 0x74, 0x75, 0x5F, 0x72, 0x65, 0x71, 0x00, 0x49, 0x32, 0x43, 0x30, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x30, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x30, 0x00, + 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x30, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, 0x30, 0x00, 0x49, 0x32, 0x43, 0x31, 0x00, 0x00, 0x00, 0x00, 0x53, 0x50, + 0x49, 0x31, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x31, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x31, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, + 0x31, 0x00, 0x54, 0x49, 0x4D, 0x32, 0x00, 0x00, 0x00, 0x00, 0x55, 0x41, 0x52, 0x54, 0x32, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x32, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, + 0x72, 0x6F, 0x75, 0x70, 0x32, 0x00, 0x54, 0x49, 0x4D, 0x33, 0x00, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x33, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x5F, 0x47, 0x72, 0x6F, 0x75, 0x70, + 0x33, 0x00, 0x54, 0x49, 0x4D, 0x34, 0x00, 0x00, 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x34, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x34, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x35, 0x00, 0x00, + 0x00, 0x00, 0x47, 0x50, 0x49, 0x4F, 0x35, 0x00, 0x00, 0x00, 0x47, 0x44, 0x4D, 0x41, 0x30, 0x20, 0x43, 0x68, 0x61, 0x6E, 0x6E, 0x65, 0x6C, 0x35, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x36, 0x00, 0x00, 0x00, 0x00, 0x54, 0x69, 0x6D, 0x65, 0x72, 0x34, + 0x2D, 0x37, 0x00, 0x00, 0x00, 0x00, 0x54, 0x49, 0x4D, 0x37, 0x00, 0x00, 0x00, 0x00, 0x42, 0x54, 0x4D, 0x41, 0x43, 0x00, 0x00, 0x00, 0x41, 0x44, 0x43, 0x00, 0x52, 0x54, 0x43, 0x00, 0x53, 0x56, 0x43, 0x00, 0x4C, 0x43, 0x44, 0x00, 0x57, 0x44, + 0x47, 0x00, 0x4E, 0x4D, 0x49, 0x00, 0x4C, 0x50, 0x43, 0x4F, 0x4D, 0x50, 0x00, 0x00, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x53, 0x50, 0x00, 0x00, 0x00, 0x49, 0x52, 0x00, 0x00, 0x50, 0x65, 0x6E, 0x64, 0x53, 0x56, 0x00, 0x00, 0x53, 0x50, + 0x49, 0x32, 0x57, 0x00, 0x00, 0x00, 0x53, 0x50, 0x4F, 0x52, 0x54, 0x31, 0x20, 0x52, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, 0x53, 0x30, 0x5F, 0x52, 0x58, 0x00, 0x53, 0x50, 0x4F, 0x52, 0x54, 0x31, 0x20, 0x54, 0x58, 0x00, 0x00, 0x00, 0x49, 0x32, + 0x53, 0x30, 0x5F, 0x54, 0x58, 0x00, 0x52, 0x73, 0x76, 0x64, 0x00, 0x00, 0x00, 0x00, 0x51, 0x64, 0x65, 0x63, 0x6F, 0x64, 0x65, 0x00, 0x4D, 0x65, 0x6D, 0x4D, 0x61, 0x6E, 0x61, 0x67, 0x65, 0x00, 0x00, 0x00, 0x53, 0x50, 0x49, 0x5F, 0x46, 0x6C, + 0x61, 0x73, 0x68, 0x00, 0x00, 0x00, 0x53, 0x79, 0x73, 0x54, 0x69, 0x63, 0x6B, 0x00, 0x50, 0x65, 0x72, 0x69, 0x70, 0x68, 0x65, 0x72, 0x61, 0x6C, 0x00, 0x00, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6D, 0x00, 0x00, 0x50, 0x6C, 0x61, 0x74, 0x66, 0x6F, + 0x72, 0x6D, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x65, 0x79, 0x73, 0x63, 0x61, 0x6E, 0x00, 0x44, 0x65, 0x62, 0x75, 0x67, 0x4D, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x52, 0x65, 0x73, 0x65, 0x74, 0x00, 0x00, 0x00, 0x48, 0x61, 0x72, 0x64, 0x46, 0x61, + 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x55, 0x73, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x42, 0x75, 0x73, 0x46, 0x61, 0x75, 0x6C, 0x74, 0x00, 0x00, 0x00, 0x00, 0x50, 0x54, 0x41, 0x5F, 0x4D, 0x61, 0x69, 0x6C, 0x62, 0x6F, + 0x78, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x42, 0x00, 0x53, 0x63, 0x65, 0x6E, 0x65, 0x5F, 0x43, 0x00, 0x42, 0x6F, 0x6F, 0x74, 0x4F, 0x6E, 0x63, 0x65, 0x00, 0x00, 0x00, 0x00, 0x74, 0x65, 0x72, 0x01, 0x01, 0x00, 0x56, 0x31, 0x20, 0x72, + 0x65, 0x61, 0x64, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x69, 0x73, 0x74, 0x69, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x18, 0xB5, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, + 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x28, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8E, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x12, 0x00, 0x02, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x20, 0xB8, 0x20, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xF0, 0x24, + 0x81, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xB8, 0x20, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xEC, 0xC4, + 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xB8, 0x20, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xF0, 0x24, 0x81, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0xEC, 0xC4, + 0x20, 0x00, 0xEC, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x9D, 0x20, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/dfu_client.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/dfu_client.c new file mode 100644 index 00000000..00db0bc9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/dfu_client.c @@ -0,0 +1,1315 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file dfu_client.c + * @brief dfu service client source file. + * @details + * @author bill + * @date 2017-8-28 + * @version v1.0 + ****************************************************************************** + * @attention + *

© COPYRIGHT 2015 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include +#include +#include "gap_conn_le.h" +#include "gap_scan.h" +#include "patch_header_check.h" +#include "mem_types.h" +#include "os_mem.h" +#include "trace.h" +#include "trace_app.h" +#include "dfu_client.h" +#include "crypto_api.h" +#include "device_lock.h" +#include "data_uart.h" +#include "platform_stdlib.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include +#endif + +#define DFU_HEADER_SIZE 12 +#define IMG_HEADER_SIZE 1024 + +#define DFU_CLIENT_INVALID_CONN_ID 0xff + +#define GATT_UUID128_DFU_DATA 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x63, 0x00, 0x00 +#define GATT_UUID128_DFU_CONTROL_POINT 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x64, 0x00, 0x00 +#define GATT_UUID128_DFU_SERVICE 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x62, 0x00, 0x00 + + +//convert img version bit map to deirectly copmare version value +#define IMG_VER_TO_LITTLE_ENDIAN(p) (((p & 0xf) << 28 )+ (((p & 0xff0) >> 4) << 20) + (((p & 0x07fff000) >> 12) << 5) + ((p & 0xf8000000) >> 27)) + +#define MAJOR_IMG_VER(p) (p & 0xf) +#define MINOR_IMG_VER(p) ((p & 0xff0) >> 4) +#define REVISION_IMG_VER(p) ((p & 0x07fff000) >> 12) +#define RESERVE_IMG_VER(p) ((p & 0xf8000000) >> 27) + +#undef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +/* PUT external 2 CHARS from local SHORT, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_WORD2EXTRN(p,w) \ + {*((p)+1) = (unsigned char)((w) & 0xff); \ + *(p) = /*lint -e(572,778)*/ (unsigned char)(((w)>>8) & 0xff);} + +/* Get local WORD from external 2 BYTE, Little-Endian format */ +#define LE_EXTRN2WORD(p) (((*(p)) & 0xff) + ((*((p)+1)) << 8)) + +/* Get local DWORD from external 4 BYTE, Little-Endian format */ +#define LE_EXTRN2DWORD(p) (((unsigned long)(*((p)+0)) & 0xff) + ((unsigned long)(*((p)+1)) << 8) \ + + ((unsigned long)(*((p)+2)) << 16) + ((unsigned long)(*((p)+3)) << 24)) + +/* PUT external 2 BYTE from local WORD, Little-Endian Format */ +#define LE_WORD2EXTRN(p,w) \ + {*((unsigned char*)p) = (unsigned char)((unsigned short)(w) & 0xff); \ + *(((unsigned char*)p)+1) = /*lint -e(572,778)*/ (unsigned char)(((unsigned short)(w)>>8) & 0xff);} + + +const uint8_t dfu_data_uuid[16] = {GATT_UUID128_DFU_DATA}; +const uint8_t dfu_control_point_uuid[16] = {GATT_UUID128_DFU_CONTROL_POINT}; +const uint8_t dfu_service_uuid[16] = {GATT_UUID128_DFU_SERVICE}; + +T_DFU_CLIENT_FSM_WRITE g_dfu_fsm_write = DFU_FSM_WRITE_DO_NOT_CARE; + +/*when ota target enable buffer check*/ +uint16_t g_buf_check_pkt_num; +uint16_t g_buf_check_pkt_count; +uint16_t g_buf_check_crc; + +/* for record data that target send by notification*/ +T_DFU_CTX g_dfu_ctx; + +uint8_t g_cp_msg[20]; //for cache control point masg +uint8_t g_cp_msg_len; + +extern uint8_t* bt_ota_central_client_get_image(void); +extern uint8_t* bt_ota_central_client_get_key(void); + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +/** + * @brief dfu client Link control block definition. + */ +typedef struct +{ + T_DFU_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_DFU_CACHE_LEN]; +} T_DFU_LINK, *P_DFU_LINK; + + +static P_DFU_LINK dfu_table; +static uint8_t dfu_link_num; + +/**< Callback used to send data to app from Dfu client layer. */ +static P_FUN_GENERAL_APP_CB pf_dfu_client_cb = NULL; +static P_FUN_GENERAL_APP_CB pf_dfu_client_app_info_cb = NULL; + +/**< Dfu client ID. */ +static T_CLIENT_ID dfu_client = CLIENT_PROFILE_GENERAL_ID; + +/**< Dfu discovery end handle control. */ +static T_DFU_HANDLE_TYPE dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + +/**< Discovery State indicate which CCCD is in discovery. */ +static T_DFU_CCCD_DISC_STATE dfu_cccd_disc_state = DFU_CCCD_DISC_START; + +static void dfu_client_init(void); + +/** + * @brief Used by application, to set the handles in Dfu handle cache. + * @param handle_type: handle types of this specific profile. + * @param handle_value: handle value to set. + * @retval true--set success. + * flase--set failed. + */ +bool dfu_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (dfu_table[conn_id].disc_state != DISC_DFU_IDLE) + { + PROFILE_PRINT_ERROR1("dfu_client_set_hdl_cache: failed invalid state %d", + dfu_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_DFU_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("dfu_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(dfu_table[conn_id].hdl_cache, p_hdl_cache, len); + dfu_table[conn_id].disc_state = DISC_DFU_DONE; + return true; +} + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool dfu_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (dfu_table[conn_id].disc_state != DISC_DFU_DONE) + { + PROFILE_PRINT_ERROR1("dfu_client_get_hdl_cache: failed invalid state %d", + dfu_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_DFU_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("dfu_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, dfu_table[conn_id].hdl_cache, len); + return true; +} + + +/** + * @brief Used by application, to start the discovery procedure of Dfu server. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_start_discovery(uint8_t conn_id) +{ + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + + APP_PRINT_INFO0("dfu_client_start_discovery"); + data_uart_print("dfu_client_start_discovery\n\r"); + /* First clear handle cache. */ + memset(&dfu_table[conn_id], 0, sizeof(T_DFU_LINK)); + dfu_table[conn_id].disc_state = DISC_DFU_START; + if (client_by_uuid128_srv_discovery(conn_id, dfu_client, + (uint8_t *)dfu_service_uuid) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +/** + * @brief Used internal, start the discovery of Dfu characteristics. + * NOTE--user can offer this interface for application if required. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +static bool dfu_client_start_all_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + PROFILE_PRINT_INFO0("dfu_client_start_all_char_discovery"); + start_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_START]; + end_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END]; + return (client_all_char_discovery(conn_id, dfu_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS); +} + +/** + * @brief Used internal, start the discovery of Dfu characteristics descriptor. + * NOTE--user can offer this interface for application if required. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +static bool dfu_client_start_all_char_descriptor_discovery(uint8_t conn_id, uint16_t start_handle, + uint16_t end_handle) +{ + DFU_PRINT_INFO0("dfu_client_start_all_char_descriptor_discovery"); + return (client_all_char_descriptor_discovery(conn_id, dfu_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS); +} + +/** + * @brief Used by application, read data from server by using handles. + * @param readCharType: one of characteristic that has the readable property. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_read_by_handle(uint8_t conn_id, T_DFU_READ_TYPE type) +{ + bool hdl_valid = false; + uint16_t handle = 0; + + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + switch (type) + { + case DFU_READ_CP_CCCD: + if (dfu_table[conn_id].hdl_cache[DFU_READ_CP_CCCD]) + { + handle = dfu_table[conn_id].hdl_cache[DFU_READ_CP_CCCD]; + hdl_valid = true; + } + break; + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, dfu_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + DFU_PRINT_INFO0("dfu_client_read_by_handle: Request fail! Please check!"); + return false; +} + +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param command: 0--disable the notification, 1--enable the notification. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_cp_cccd_set(uint8_t conn_id, bool command) +{ + uint16_t handle; + uint16_t length; + uint8_t *pdata; + uint16_t cccd_value; + handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD]; + if (handle) + { + cccd_value = command ? 1 : 0; + length = sizeof(uint16_t); + pdata = (uint8_t *)&cccd_value; + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_REQ, handle, length, + pdata) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + DFU_PRINT_INFO0("dfu_client_cp_cccd_set: Request fail! Please check!"); + return false; +} + +/** + * @brief Used internal, to send write request to peer server's V5 Control Point Characteristic. + * @param ctl_pnt_ptr: pointer of control point data to write. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_cp_write(uint8_t conn_id, uint8_t *pdata, uint16_t length) +{ + uint16_t handle; + DFU_PRINT_INFO2("==>dfu_client_cp_write: opcode = %d, datalen = %d.", pdata[0], + length); //opcode = pdata[0] + g_dfu_fsm_write = DFU_FSM_WRITE_WAIT_WRITE_RESP; + handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP]; + if (handle) + { +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(if_queue_in(0, conn_id, dfu_client, handle, length, pdata) != 0) + { + printf("(conn_id %d)no dfu write request send\r\n", conn_id); + return false; + } + + request_in_process_flag[conn_id] = 1; + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_REQ, handle, length, pdata) == GAP_CAUSE_SUCCESS) + return true; + else + request_in_process_flag[conn_id] = 0; //if write request fail then reset flag=0 + +#else + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_REQ, handle, length, pdata) == GAP_CAUSE_SUCCESS) + return true; +#endif + } + DFU_PRINT_INFO0("==>dfu_client_cp_write: Request fail! Please check!"); + printf("==>dfu_client_cp_write: Request fail! Please check!\r\n"); + return false; +} + +/** + * @brief Used internal, to send write request to peer server's V5 Control Point Characteristic. + * @param ctl_pnt_ptr: pointer of control point data to write. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_data_write(uint8_t conn_id, uint8_t *pdata, uint16_t length) +{ + uint16_t handle; + g_dfu_fsm_write = DFU_FSM_WRITE_DFU_DATA; + handle = dfu_table[conn_id].hdl_cache[HDL_DFU_DATA]; + DFU_PRINT_INFO2("==>dfu_client_data_write: datalen = %d, conn_id=%d", length, conn_id); + if (handle) + { + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_CMD, handle, length, + pdata) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + DFU_PRINT_INFO0("dfu_client_data_write: command fail! Please check!"); + return false; +} + +/** + * @brief Used internal, switch to the next CCCD handle to be discovered. + * NOTE--this function only used when peer service has more than one CCCD. + * @param pSwitchState: CCCD discovery state. + * @retval none. + */ +static void dfu_client_switch_next_descriptor(uint8_t conn_id, T_DFU_CCCD_DISC_STATE *cccd_state) +{ + T_DFU_CCCD_DISC_STATE new_state; + switch (*cccd_state) + { + case DFU_CCCD_DISC_START: + if (dfu_table[conn_id].hdl_cache[HDL_DFU_CP_END]) + { + new_state = DFU_CCCD_DISC_CP_NOTIFY; + } + else + { + new_state = DFU_CCCD_DISC_END; + } + break; + case DFU_CCCD_DISC_CP_NOTIFY: + new_state = DFU_CCCD_DISC_END; + break; + default: + new_state = DFU_CCCD_DISC_END; + break; + } + + *cccd_state = new_state; +} + +/** + * @brief Called by profile client layer, when discover state of discovery procedure changed. + * @param discoveryState: current service discovery state. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_disc_state_cb(uint8_t conn_id, T_DISCOVERY_STATE disc_state) +{ + bool cb_flag = false; + bool descriptor_disc_flag = false; + + uint16_t start_handle; + uint16_t end_handle; + + T_DFU_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DFU_CLIENT_CB_TYPE_DISC_STATE; + + DFU_PRINT_INFO1("dfu_client_disc_state_cb: disc_state = %d", disc_state); + printf("dfu_client_disc_state_cb: disc_state = %d\n", disc_state); + if (dfu_table[conn_id].disc_state == DISC_DFU_START) + { + switch (disc_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_START] != 0) + || (dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END] != 0)) + { + if (dfu_client_start_all_char_discovery(conn_id) == false) + { + cb_data.cb_content.disc_state = DISC_DFU_FAIL; + cb_flag = true; + } + } + /* No dfu service handle found. Discover procedure complete. */ + else + { + cb_data.cb_content.disc_state = DISC_DFU_FAIL; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + /* We should store the last char end handle if needed. */ + if (dfu_end_hdl_idx < HDL_DFU_CACHE_LEN) + { + dfu_table[conn_id].hdl_cache[dfu_end_hdl_idx] = dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END]; + dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + } + /* Find the first descriptor to be discovered. */ + dfu_cccd_disc_state = DFU_CCCD_DISC_START; + dfu_client_switch_next_descriptor(conn_id, &dfu_cccd_disc_state); + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + /* Find the next descriptor to be discovered. */ + dfu_client_switch_next_descriptor(conn_id, &dfu_cccd_disc_state); + break; + default: + DFU_PRINT_INFO0("dfu_client_disc_state_cb: Invalid Discovery State!"); + break; + } + } + + /* Switch different char descriptor discovery, if has multi char descriptors. */ + switch (dfu_cccd_disc_state) + { + case DFU_CCCD_DISC_CP_NOTIFY: + /* Need to discover notify char descriptor. */ + start_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP] + 1; + end_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP_END]; + descriptor_disc_flag = true; + break; + case DFU_CCCD_DISC_END: + cb_data.cb_content.disc_state = DISC_DFU_DONE; + cb_flag = true; + break; + default: + /* No need to send char descriptor discovery. */ + break; + } + if (descriptor_disc_flag) + { + if (dfu_client_start_all_char_descriptor_discovery(conn_id, start_handle, end_handle) == false) + { + cb_data.cb_content.disc_state = DISC_DFU_FAIL; + cb_flag = true; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } +} + +/** + * @brief Called by profile client layer, when discover result fetched. + * @param resultType: indicate which type of value discovered in service discovery procedure. + * @param resultData: value discovered. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_disc_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: result_type = %d", result_type); + printf("==>dfu_client_disc_result_cb: result_type = %d\n", result_type); + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + /* send service handle range to application. */ + dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_START] = result_data.p_srv_disc_data->att_handle; + dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END] = result_data.p_srv_disc_data->end_group_handle; + break; + case DISC_RESULT_CHAR_UUID128: + /* When use clientAPI_AllCharDiscovery. */ + if (dfu_end_hdl_idx < HDL_DFU_CACHE_LEN) + { + DFU_PRINT_INFO2("==>dfu_client_disc_result_cb: dfu_end_hdl_idx = %d, hnadle=0x%4x", + dfu_end_hdl_idx, result_data.p_char_uuid128_disc_data->decl_handle - 1); + dfu_table[conn_id].hdl_cache[dfu_end_hdl_idx] = result_data.p_char_uuid128_disc_data->decl_handle - + 1; + dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + + } + /* we should inform intrested handles to upper application. */ + if (0 == memcmp(result_data.p_char_uuid128_disc_data->uuid128, dfu_data_uuid, 16)) + { + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: set dfu_data handle=0x%4x", + result_data.p_char_uuid128_disc_data->value_handle); + dfu_table[conn_id].hdl_cache[HDL_DFU_DATA] = result_data.p_char_uuid128_disc_data->value_handle; + } + else if (0 == memcmp(result_data.p_char_uuid128_disc_data->uuid128, dfu_control_point_uuid, 16)) + { + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: set dfu_control_point handle=0x%4x", + result_data.p_char_uuid128_disc_data->value_handle); + dfu_table[conn_id].hdl_cache[HDL_DFU_CP] = result_data.p_char_uuid128_disc_data->value_handle; + dfu_end_hdl_idx = HDL_DFU_CP_END; + } + break; + case DISC_RESULT_CHAR_DESC_UUID16: + /* When use clientAPI_AllCharDescriptorDiscovery. */ + if (result_data.p_char_desc_uuid16_disc_data->uuid16 == + GATT_UUID_CHAR_CLIENT_CONFIG) //GATT Client Characteristic Configuration descriptors uuid + { + uint16_t temp_handle = result_data.p_char_desc_uuid16_disc_data->handle; + if ((temp_handle > dfu_table[conn_id].hdl_cache[HDL_DFU_CP]) + && (temp_handle <= dfu_table[conn_id].hdl_cache[HDL_DFU_CP_END])) + { + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: set dfu_cccd handle=0x%4x", temp_handle); + dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD] = temp_handle; + } + else + { + /* have no intrest in this handle. */ + } + } + break; + default: + DFU_PRINT_INFO0("dfu_client_disc_result_cb: Invalid Discovery Result Type!"); + break; + } +} + +/** + * @brief Called by profile client layer, when read request responsed. + * @param reqResult: read request from peer device success or not. + * @param wHandle: handle of the value in read response. + * @param iValueSize: size of the value in read response. + * @param pValue: pointer to the value in read response. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_read_result_cb(uint8_t conn_id, uint16_t cause, uint16_t handle, + uint16_t len, uint8_t *pvalue) +{ + T_DFU_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DFU_CLIENT_CB_TYPE_READ_RESULT; + cb_data.cb_content.read_result.cause = cause; + DFU_PRINT_INFO3("==>dfu_client_read_result_cb: cause=%d, handle=0x%x, size=%d", cause, + handle, len); + printf("==>dfu_client_read_result_cb: cause=%d, handle=0x%x, size=%d\n", cause, + handle, len); + /* If read req success, branch to fetch value and send to application. */ + if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD]) + { + cb_data.cb_content.read_result.type = DFU_READ_CP_CCCD; + if (cause == GAP_SUCCESS && len == sizeof(uint16_t)) + { + uint16_t cccd_value = LE_EXTRN2WORD(pvalue); + cb_data.cb_content.read_result.data.dfu_cp_cccd = cccd_value & + GATT_CLIENT_CHAR_CONFIG_NOTIFY; + } + } + + /* Inform application the read result. */ + if (pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } +} + +/** + * @brief Called by profile client layer, when write request complete. + * @param reqResult: write request send success or not. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, uint16_t handle, + uint16_t cause, uint8_t credits) +{ + T_DFU_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DFU_CLIENT_CB_TYPE_WRITE_RESULT; + cb_data.cb_content.write_result.cause = cause; + + DFU_PRINT_INFO4("==>dfu_client_write_result_cb: cause=%d, handle=0x%x, type=%d, credits=%d", + cause, handle, type, credits); + printf("==>dfu_client_write_result_cb: cause=%d, handle=0x%x, type=%d, credits=%d\n", + cause, handle, type, credits); + /* If write req success, branch to fetch value and send to application. */ + if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD]) + + { + cb_data.cb_content.write_result.type = DFU_WRITE_CP_CCCD; + } + else if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP]) + { + cb_data.cb_content.write_result.type = DFU_WRITE_CP; + } + else if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_DATA]) + { + cb_data.cb_content.write_result.type = DFU_WRITE_DATA; + } + else + { + return; + } + + /* Inform application the write result. */ + if (pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } +} + +/** + * @brief Called by profile client layer, when notification or indication arrived. + * @param wHandle: handle of the value in received data. + * @param iValueSize: size of the value in received data. + * @param pValue: pointer to the value in received data. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static T_APP_RESULT dfu_client_notify_indicate_cb(uint8_t conn_id, bool notify, + uint16_t handle, uint16_t len, uint8_t *pvalue) +{ + T_APP_RESULT app_result = APP_RESULT_REJECT; + T_DFU_CLIENT_CB_DATA cb_data; + + DFU_PRINT_INFO3("==>dfu_client_notify_indicate_cb: handle=0x%x, len=%d, is notify=%d", + handle, len, notify); + printf("==>dfu_client_notify_indicate_cb: handle=0x%x, len=%d, is notify=%d\n", + handle, len, notify); + if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP]) + { + cb_data.cb_type = DFU_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + cb_data.cb_content.notif_ind_data.type = DFU_NOTIF_RECEIVE_DFU_CP_NOTIFY; + cb_data.cb_content.notif_ind_data.value.len = len; + cb_data.cb_content.notif_ind_data.value.pdata = pvalue; + + /* Inform application the notif/ind result. */ + if (pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } + app_result = APP_RESULT_SUCCESS; + } + + return app_result; +} + +/** + * @brief Called by profile client layer, when link disconnected. + * NOTE--we should reset some state when disconnected. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +void dfu_client_disconnect_cb(uint8_t conn_id) +{ + DFU_PRINT_INFO1("dfu_client_disconnect_cb: conn_id=%d", conn_id); + + dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + dfu_cccd_disc_state = DFU_CCCD_DISC_START; + dfu_client_init(); + + if (g_dfu_ctx.fsm_client == DFU_CB_START) + { + g_dfu_ctx.fsm_client = DFU_CB_NONE; + if (pf_dfu_client_app_info_cb) + { + T_DFU_CB_MSG cb_msg; + cb_msg.type = DFU_CB_FAIL; + pf_dfu_client_app_info_cb(dfu_client, conn_id, &cb_msg); + } + } +} + + +static void swap_buf(uint8_t *dst, const uint8_t *src, uint16_t len) +{ + int i; + if (dst == NULL || src == NULL) + { + return; + } + + for (i = 0; i < len; i++) + { + dst[len - 1 - i] = src[i]; + } +} + +unsigned char bt_ota_central_client_tmp_image[16] __attribute__((aligned(32))) = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char bt_ota_central_client_tmp_encrypted[16] __attribute__((aligned(32))) = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char bt_ota_central_client_tmp_key[32] __attribute__((aligned(32))) = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +bool dfu_encrypt(uint8_t image[16]) +{ + int ret = false; + +#if defined(CONFIG_PLATFORM_8710C) + const u8 *key; + + swap_buf(bt_ota_central_client_tmp_key, bt_ota_central_client_get_key(), 32); + key = bt_ota_central_client_tmp_key; + + memcpy(bt_ota_central_client_tmp_image, image, 16); + + device_mutex_lock(RT_DEV_LOCK_CRYPTO); + ret = crypto_aes_ecb_init(key, 32); + if(ret != 0){ + printf("crypto_aes_ecb_init: ret=%d\n", ret); + return ret; + } + ret = crypto_aes_ecb_encrypt(bt_ota_central_client_tmp_image, 16, NULL, 0, bt_ota_central_client_tmp_encrypted); + if(ret !=0){ + printf("crypto_aes_ecb_encrypt: ret=%d\n", ret); + return ret; + } + device_mutex_unlock(RT_DEV_LOCK_CRYPTO); + + memcpy(image, bt_ota_central_client_tmp_encrypted, 16); +#endif + + return ret; +} + +uint16_t dfu_client_crc_cal(uint8_t *buf, uint32_t length, uint16_t checksum16) +{ + uint32_t i; + uint16_t *p16; + p16 = (uint16_t *)buf; + for (i = 0; i < length / 2; ++i) + { + checksum16 = checksum16 ^ (*p16); + ++p16; + } + return checksum16; +} + +bool dfu_client_push_image(uint8_t conn_id) +{ + uint16_t mtu_size = 0; + uint16_t push_img_size = 0; + uint32_t image_size = 0; + uint8_t *pheader; + uint8_t *pdata; + + DFU_PRINT_INFO0("==>dfu_client_push_image"); + if (g_dfu_fsm_write == DFU_FSM_WRITE_WAIT_WRITE_RESP) + { + // in case that the credit is bigger then the buffer check packet num + DFU_PRINT_INFO0("==>dfu_client_push_image: current waiting cp response"); + return false; + } + +#if 0 + mtu_size = 20; +#else + le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, &mtu_size, 0); + DFU_PRINT_INFO1("==>dfu_client_push_image: mtu_size=%d", mtu_size); + mtu_size -= 3; + mtu_size &= 0xfff0; //mtu size down align 16 bytes +#endif + + image_size = g_dfu_ctx.image_length - g_dfu_ctx.curr_offset; + push_img_size = MIN(image_size, mtu_size); + DFU_PRINT_INFO2("==>dfu_client_push_image: push_img_size=%d, img_size=%d", push_img_size, + image_size); + +#if (SILENT_OTA == 0) + if (!g_dfu_ctx.mode.buffercheck) + { + image_size = NORMAL_OTA_MAX_BUFFER_SIZE - (g_dfu_ctx.curr_offset % NORMAL_OTA_MAX_BUFFER_SIZE); + push_img_size = MIN(image_size, push_img_size); + DFU_PRINT_INFO2("==>dfu_client_push_image: push_img_size=%d, img_size=%d", push_img_size, + image_size); + } + +#endif + + DFU_PRINT_INFO3("==>dfu_client_push_image: image_length=%d, g_dfu_ctx.curr_offset=%d, push_img_size=%d", + g_dfu_ctx.image_length, g_dfu_ctx.curr_offset, push_img_size); + + //pheader = (uint8_t *)TEMP_OTA_IMG_ADDR; + pheader = bt_ota_central_client_get_image(); + pdata = os_mem_alloc(RAM_TYPE_DATA_ON, push_img_size); //send one packet(mtu size) or left img size + if (pdata == NULL) + { + return false; + } + memcpy(pdata, pheader + g_dfu_ctx.curr_offset, push_img_size); + g_dfu_ctx.curr_offset += push_img_size; + + //aes encrypt when ota and all data is encrypted + if (g_dfu_ctx.mode.aesflg && g_dfu_ctx.mode.aesmode) + { + uint8_t *ptmp = pdata; + for (uint16_t loop = 0; loop < push_img_size / 16; loop++) //only encrypt 16 bytes align + { + dfu_encrypt(ptmp); + ptmp += 16; + } + } + dfu_client_data_write(conn_id, pdata, push_img_size); + + //target enable buffer check + if (g_dfu_ctx.mode.buffercheck) + { + if (!g_buf_check_pkt_count) + { + g_buf_check_crc = 0; + } + g_buf_check_pkt_count++; + g_buf_check_crc = dfu_client_crc_cal(pdata, push_img_size, g_buf_check_crc); + if (g_buf_check_pkt_count == g_buf_check_pkt_num || g_dfu_ctx.curr_offset == g_dfu_ctx.image_length) + { + uint8_t data[5]; + data[0] = DFU_OPCODE_REPORT_BUFFER_CRC; + LE_WORD2EXTRN(data + 1, (g_buf_check_pkt_count - 1) * mtu_size + push_img_size); + BE_WORD2EXTRN(data + 3, g_buf_check_crc); + dfu_client_cp_write(conn_id, data, DFU_LENGTH_REPORT_BUFFER_CRC); + g_buf_check_pkt_count = 0; + } + } + + os_mem_free(pdata); + return true; +} + +void dfu_client_handle_cp_msg(uint8_t conn_id, uint8_t *pdata, uint16_t len) +{ + uint8_t opcode = pdata[0]; + uint8_t req_opcode = pdata[1]; + DFU_PRINT_INFO2("==>dfu_client_handle_cp_msg: opcode=%d len=%d.", req_opcode, len); + printf("==>dfu_client_handle_cp_msg: opcode=%d len=%d.\n", req_opcode, len); + if (opcode != DFU_OPCODE_NOTIFICATION) + { + DFU_PRINT_INFO1("==>handle cp msg: invalid notify opcode=%d!", opcode); + return; + } + + if (req_opcode == DFU_OPCODE_REPORT_TARGET_INFO && len == DFU_NOTIFY_LENGTH_REPORT_TARGET_INFO) + { +#if (RCU_SILENT_OTA == 1) + uint16_t target_version = LE_EXTRN2WORD(pdata + 3); //obey git_ver format + uint32_t cur_offset = LE_EXTRN2DWORD(pdata + 5); + printf("handle cp msg: report target info(bee2 rcu)\r\n");//debug +#else + + uint32_t target_version = LE_EXTRN2DWORD(pdata + 3); //obey git_ver format + uint32_t cur_offset = LE_EXTRN2DWORD(pdata + 7); + PROFILE_PRINT_INFO5("handle cp msg: report target info, target_version=%d.%d.%d.%d, cur_offset=0x%x", + MAJOR_IMG_VER(target_version), MINOR_IMG_VER(target_version), + REVISION_IMG_VER(target_version), RESERVE_IMG_VER(target_version), cur_offset); + +#if (ONLY_SUPPORT_UPGRADE == 1) + if (IMG_VER_TO_LITTLE_ENDIAN(LE_EXTRN2DWORD(g_dfu_ctx.dfu_img_version) <= IMG_VER_TO_LITTLE_ENDIAN( + LE_EXTRN2DWORD(pdata + 3))) + { + DBG_DIRECT("handle cp msg: Img no need ota!"); + return; + } +#endif +#endif + + //uint8_t *pheader = (uint8_t *)TEMP_OTA_IMG_ADDR; + uint8_t *pheader = bt_ota_central_client_get_image(); + uint8_t data[DFU_LENGTH_START_DFU]; + data[0] = DFU_OPCODE_START_DFU; + memcpy(data + 1, pheader, DFU_HEADER_SIZE); + memset(data + 1 + DFU_HEADER_SIZE, 0, 4); + + //aes encrypt when ota + if (g_dfu_ctx.mode.aesflg) + { + DFU_PRINT_TRACE1("===>Data before encryped: %b", TRACE_BINARY(16, data + 1)); + dfu_encrypt(data + 1); + DFU_PRINT_TRACE1("===>Data after encryped: %b", TRACE_BINARY(16, data + 1)); + } + + dfu_client_cp_write(conn_id, data, DFU_LENGTH_START_DFU); + g_dfu_ctx.curr_offset = DFU_HEADER_SIZE; + g_dfu_ctx.image_length = ((T_IMG_CTRL_HEADER_FORMAT *)pheader)->payload_len + IMG_HEADER_SIZE; + DFU_PRINT_INFO4("==>handle cp msg: otaing img_id 0x%x, verision 0x%x->0x%x, dfu_img_total_len=%d", + g_dfu_ctx.signature, target_version, g_dfu_ctx.dfu_img_version, g_dfu_ctx.image_length); + + /*notify application*/ + g_dfu_ctx.fsm_client = DFU_CB_START; + if (pf_dfu_client_app_info_cb) + { + T_DFU_CB_MSG cb_msg; + cb_msg.type = DFU_CB_START; + pf_dfu_client_app_info_cb(dfu_client, conn_id, &cb_msg); + } + } + else if (req_opcode == DFU_OPCODE_START_DFU && len == DFU_NOTIFY_LENGTH_ARV) + { + if (g_dfu_ctx.mode.buffercheck) + { + DFU_PRINT_INFO0("==>handle cp msg: Enable buffer check"); + uint8_t data[1]; + data[0] = DFU_OPCODE_BUFFER_CHECK_EN; + dfu_client_cp_write(conn_id, data, DFU_LENGTH_BUFFER_CHECK_EN); + } + else + { + DFU_PRINT_INFO0("==>handle cp msg: Disable buffer check"); + //start push image, make use of credits + for (uint8_t loop = 0; loop < 4; loop++) + { + dfu_client_push_image(conn_id); + } + } + } + else if (req_opcode == DFU_OPCODE_BUFFER_CHECK_EN && len == DFU_NOTIFY_LENGTH_BUFFER_CHECK_EN) + { + uint16_t buffer_check_len = LE_EXTRN2WORD(pdata + 3); + uint16_t mtu_size = LE_EXTRN2WORD(pdata + 5); + + g_buf_check_pkt_num = buffer_check_len / ((mtu_size - 3) & 0xfff0); //buffer check paket num + g_buf_check_pkt_count = 0; + + DFU_PRINT_INFO3("==>handle cp msg: buffer_check_lengeth=%d, mtu_size=%d, g_buf_check_pkt_num=%d", + buffer_check_len, mtu_size, g_buf_check_pkt_num); + + //start push image, make use of credits + for (uint8_t loop = 0; loop < 8; loop++) + { + dfu_client_push_image(conn_id); + } + } + else if (req_opcode == DFU_OPCODE_REPORT_BUFFER_CRC && len == DFU_NOTIFY_LENGTH_REPORT_BUFFER_CRC) + { + uint32_t offset = LE_EXTRN2DWORD(pdata + 3); + DFU_PRINT_INFO2("==>handle cp msg: Target offset=%d,g_dfu_ctx.curr_offset=%d", offset, + g_dfu_ctx.curr_offset); + g_dfu_ctx.curr_offset = offset; + if (g_dfu_ctx.image_length > g_dfu_ctx.curr_offset) + { + dfu_client_push_image(conn_id); + } + else + { + DFU_PRINT_INFO0("==>handle cp msg: Img trans done(BufCheckEn)!"); + uint8_t data[DFU_LENGTH_VALID_FW]; + data[0] = DFU_OPCODE_VALID_FW; + LE_WORD2EXTRN(data + 1, g_dfu_ctx.signature); + dfu_client_cp_write(conn_id, data, DFU_LENGTH_VALID_FW); + } + } + else if (req_opcode == DFU_OPCODE_VALID_FW && len == DFU_NOTIFY_LENGTH_ARV) + { + DFU_PRINT_INFO1("==>handle cp msg: verify image rst=%d(1 success)", pdata[2]); + uint8_t data[DFU_LENGTH_ACTIVE_IMAGE_RESET]; + data[0] = pdata[2] == DFU_ARV_SUCCESS ? DFU_OPCODE_ACTIVE_IMAGE_RESET : DFU_OPCODE_SYSTEM_RESET; + dfu_client_cp_write(conn_id, data, DFU_LENGTH_ACTIVE_IMAGE_RESET); + g_dfu_ctx.fsm_client = DFU_CB_NONE; + if (pf_dfu_client_app_info_cb) + { + T_DFU_CB_MSG cb_msg; + cb_msg.type = pdata[2] == DFU_ARV_SUCCESS ? DFU_CB_END : DFU_CB_FAIL; + pf_dfu_client_app_info_cb(dfu_client, conn_id, &cb_msg); + } + } +} + +/*profile callback to handle msg*/ +T_APP_RESULT dfu_client_handle_msg(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_DFU_CLIENT_CB_DATA *pcb_data = (T_DFU_CLIENT_CB_DATA *)p_data; + DFU_PRINT_INFO2("==>dfu client hdl msg: type=%d, g_dfu_fsm_write=%d.", pcb_data->cb_type, + g_dfu_fsm_write); + printf("==>dfu client hdl msg: client_id=%d, type=%d, g_dfu_fsm_write=%d.\n", client_id, pcb_data->cb_type, + g_dfu_fsm_write); + switch (pcb_data->cb_type) + { + case DFU_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case DISC_DFU_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + DFU_PRINT_INFO0("==>dfu client hdl msg: discover procedure done."); + + if (dfu_client_cp_cccd_set(conn_id, 1)) //enable server notification + { + g_dfu_fsm_write = DFU_FSM_WRITE_CCCD_ENABLE; + DFU_PRINT_INFO0("==>dfu client hdl msg: Enable CCCD."); + } + break; + case DISC_DFU_FAIL: + /* Discovery Request failed. */ + DFU_PRINT_INFO0("==>dfu client hdl msg: discover request failed."); + break; + default: + break; + } + break; + case DFU_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case DFU_READ_CP_CCCD: + DFU_PRINT_INFO1("==>dfu client hdl msg: dfu_cp_cccd=%d.", + pcb_data->cb_content.read_result.data.dfu_cp_cccd); + break; + default: + break; + } + break; + case DFU_CLIENT_CB_TYPE_WRITE_RESULT: + if (pcb_data->cb_content.write_result.cause == 0) + { +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(pcb_data->cb_content.write_result.type == DFU_WRITE_CP_CCCD || pcb_data->cb_content.write_result.type == DFU_WRITE_CP) + { + request_in_process_flag[conn_id] = 0; + if_queue_out_and_send(conn_id); + } +#endif + switch (pcb_data->cb_content.write_result.type) + { + case DFU_WRITE_CP_CCCD: + DFU_PRINT_INFO1("==>dfu client hdl msg: CB Type(DFU_WRITE_CP_CCCD),g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_CCCD_ENABLE) + { + //T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)TEMP_OTA_IMG_ADDR; + uint8_t *ota_app_image = bt_ota_central_client_get_image(); + T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)ota_app_image; + + g_dfu_ctx.signature = p_header->ctrl_header.image_id; + uint8_t data[DFU_LENGTH_REPORT_TARGET_INFO]; + data[0] = DFU_OPCODE_REPORT_TARGET_INFO; + LE_WORD2EXTRN(data + 1, g_dfu_ctx.signature); + + /*after enable CCCD, start handle control point procedure*/ + dfu_client_cp_write(conn_id, data, DFU_LENGTH_REPORT_TARGET_INFO); + } + break; + case DFU_WRITE_DATA: + DFU_PRINT_INFO1("==>dfu client hdl msg: CB Type(DFU_WRITE_DATA),g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_DFU_DATA) + { + if (g_dfu_ctx.image_length > g_dfu_ctx.curr_offset) + { + DFU_PRINT_INFO0("==>dfu client hdl msg: CB Type(DFU_WRITE_DATA)"); + dfu_client_push_image(conn_id); + } + else + { + if (!g_dfu_ctx.mode.buffercheck) + { + /*when not enable buf check, img trans done, verify img*/ + DFU_PRINT_INFO0("==>dfu client hdl msg: Img trans done(BufCheckDisable)"); + uint8_t data[DFU_LENGTH_VALID_FW]; + data[0] = DFU_OPCODE_VALID_FW; + LE_WORD2EXTRN(data + 1, g_dfu_ctx.signature); + dfu_client_cp_write(conn_id, data, DFU_LENGTH_VALID_FW); + } + } + } + break; + case DFU_WRITE_CP: + DFU_PRINT_INFO1("==>dfu client hdl msg: DFU_WRITE_CP, g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_WAIT_WRITE_RESP) + { + g_dfu_fsm_write = DFU_FSM_WRITE_DO_NOT_CARE; + if (g_cp_msg_len) + { + DFU_PRINT_INFO2("==>dfu client hdl msg: DFU_WRITE_CP, g_dfu_fsm_write=%d, g_cp_msg_len=%d", + g_dfu_fsm_write, g_cp_msg_len); + dfu_client_handle_cp_msg(conn_id, g_cp_msg, g_cp_msg_len); + g_cp_msg_len = 0; + } + } + break; + default: + break; + } + } + else + { + DFU_PRINT_INFO3("==>dfu client hdl msg: fail to send msg! type=%d, cause=0x%x g_dfu_fsm_write=%d", + pcb_data->cb_content.write_result.type, pcb_data->cb_content.write_result.cause, g_dfu_fsm_write); + DFU_PRINT_INFO0("==>dfu client hdl msg: le_disconnect"); + le_disconnect(conn_id); + } + break; + case DFU_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (pcb_data->cb_content.notif_ind_data.type) + { + case DFU_NOTIF_RECEIVE_DFU_CP_NOTIFY: + { + DFU_PRINT_INFO1("==>dfu client hdl msg: NOTIF_IND_RESULT, g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_DO_NOT_CARE) + { + DFU_PRINT_INFO1("==>dfu client hdl msg: NOTIF_IND_RESULT, g_dfu_fsm_write=%d(if 0 hdl cp msg)", + g_dfu_fsm_write); + dfu_client_handle_cp_msg(conn_id, pcb_data->cb_content.notif_ind_data.value.pdata, + pcb_data->cb_content.notif_ind_data.value.len); + } + else + { + //cache + g_cp_msg_len = pcb_data->cb_content.notif_ind_data.value.len; + memcpy(g_cp_msg, pcb_data->cb_content.notif_ind_data.value.pdata, + g_cp_msg_len > 20 ? 20 : g_cp_msg_len); + DFU_PRINT_INFO1("==>dfu client hdl msg: Cached Received Notify Data, len=%d", g_cp_msg_len); + + } + } + break; + default: + break; + } + break; + + default: + break; + } + return APP_RESULT_SUCCESS; +} + +/** + * @brief Dfu Client Callbacks. +*/ +const T_FUN_CLIENT_CBS dfu_client_cbs = +{ + dfu_client_disc_state_cb, //!< Discovery State callback function pointer + dfu_client_disc_result_cb, //!< Discovery result callback function pointer + dfu_client_read_result_cb, //!< Read response callback function pointer + dfu_client_write_result_cb, //!< Write result callback function pointer + dfu_client_notify_indicate_cb, //!< Notify Indicate callback function pointer + NULL //dfu_client_disconnect_cb //!< Link disconnection callback function pointer +}; + +static void dfu_client_init(void) +{ + //T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)TEMP_OTA_IMG_ADDR; + uint8_t *ota_app_image = bt_ota_central_client_get_image(); + T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)ota_app_image; + + if (p_header && p_header->ctrl_header.payload_len) + { + T_IMG_ID dfu_img_id = (T_IMG_ID)p_header->ctrl_header.image_id; + if (dfu_img_id < IMAGE_MAX && dfu_img_id >= SecureBoot) + { + DFU_PRINT_INFO5("==>dfu_client_init: will dfu img:0x%x, version:%d.%d.%d.%d", dfu_img_id, + MAJOR_IMG_VER(p_header->git_ver.ver_info.version), + MINOR_IMG_VER(p_header->git_ver.ver_info.version), + REVISION_IMG_VER(p_header->git_ver.ver_info.version), + RESERVE_IMG_VER(p_header->git_ver.ver_info.version)); + + g_dfu_ctx.dfu_img_version = p_header->git_ver.ver_info.version; + } + else + { + DFU_PRINT_ERROR1("==>dfu_client_init: Temp bank img_id:0x%x Invalid!", dfu_img_id); + } + + + } + +#if defined(CONFIG_PLATFORM_8710C) + if(crypto_init()) printf("crypto_init fail!\n"); +#endif +} + +/** + * @brief add Dfu client to application. + * @param appCB: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID dfu_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > DFU_MAX_LINKS) + { + PROFILE_PRINT_ERROR1("dfu_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&dfu_client, &dfu_client_cbs)) + { + dfu_client = CLIENT_PROFILE_GENERAL_ID; + DFU_PRINT_ERROR0("dfu_client_add: fail!"); + return dfu_client; + } + DFU_PRINT_INFO1("dfu_client_add: client ID = %d", dfu_client); + + dfu_link_num = link_num; + size = dfu_link_num * sizeof(T_DFU_LINK); + dfu_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + /* register callback for profile to inform application that some events happened. */ + pf_dfu_client_cb = dfu_client_handle_msg; + pf_dfu_client_app_info_cb = app_cb; + dfu_client_init(); + + return dfu_client; +} + +void dfu_delete_client(void) +{ + if (dfu_table != NULL) { + os_mem_free(dfu_table); + dfu_table = NULL; + } +} + + +/** + * @brief dfu client connect target device. + * @param p_le_scan_info: filtered scan info + */ +void dfu_client_connect_device(T_LE_SCAN_INFO *p_le_scan_info) +{ + PROFILE_PRINT_INFO1("dfu_client_connect_device: p_le_scan_info->adv_type = %d", + p_le_scan_info->adv_type); + + /* corresponding to silent ota or normal ota */ + if (p_le_scan_info->adv_type == GAP_ADV_EVT_TYPE_UNDIRECTED || + p_le_scan_info->adv_type == GAP_ADV_EVT_TYPE_SCAN_RSP) + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 0x80; + conn_req_param.conn_interval_max = 0x80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + T_GAP_CAUSE cause; + if (GAP_CAUSE_SUCCESS == (cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, p_le_scan_info->bd_addr, + p_le_scan_info->remote_addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, 1000))) + { + + PROFILE_PRINT_INFO2("==>dfu_client_connect_device: try connecting %s, remote_addr_type=%d", + TRACE_BDADDR(p_le_scan_info->bd_addr), p_le_scan_info->remote_addr_type); + } + else + { + PROFILE_PRINT_WARN1("==>dfu_client_connect_device: FAIL cause=%d!", cause); + } + } + else + { + PROFILE_PRINT_ERROR1("dfu_client_connect_device: invalid adv type=%d!", p_le_scan_info->adv_type); + } + + return; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/dfu_client.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/dfu_client.h new file mode 100644 index 00000000..1e7fbb09 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/dfu_client.h @@ -0,0 +1,366 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file dfu_client.h + * @brief Head file for using dfu service Client. + * @details Data structs and external functions declaration. + * @author bill + * @date 2018-4-17 + * @version v2.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _DFU_CLIENT_H_ +#define _DFU_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Add Includes here */ +#include "profile_client.h" +#include "bt_ota_central_client.h" + +/** @defgroup DFU_Client + * @{ + */ +/** @brief Define links number. range: 0-4 */ +#define DFU_MAX_LINKS 4 + +#define NORMAL_OTA_MAX_BUFFER_SIZE 2000 + +/*each control point procedure*/ +#define DFU_OPCODE_MIN 0x00 +#define DFU_OPCODE_START_DFU 0x01 +#define DFU_OPCODE_RECEIVE_FW_IMAGE_INFO 0x02 +#define DFU_OPCODE_VALID_FW 0x03 +#define DFU_OPCODE_ACTIVE_IMAGE_RESET 0x04 +#define DFU_OPCODE_SYSTEM_RESET 0x05 +#define DFU_OPCODE_REPORT_TARGET_INFO 0x06 +#define DFU_OPCODE_CONN_PARA_TO_UPDATE_REQ 0x07 + +#define DFU_OPCODE_PKT_RX_NOTIFICATION_VOICE 0x08 +#define DFU_OPCODE_BUFFER_CHECK_EN 0x09 /*report current ota function version information*/ +#define DFU_OPCODE_REPORT_BUFFER_CRC 0x0a /*report current buffer CRC*/ + +#define DFU_OPCODE_RECEIVE_IC_TYPE 0x0b +#define DFU_OPCODE_COPY_IMG 0x0c +#define DFU_OPCODE_MAX 0x0d + +/*length of each control point procedure*/ +#define DFU_LENGTH_START_DFU (1+12+4)/*4 bytes is padding for encrypt*/ +#define DFU_LENGTH_RECEIVE_FW_IMAGE_INFO (1+2+4) //img_id + cur_offset +#define DFU_LENGTH_VALID_FW (1+2) //img_id +#define DFU_LENGTH_ACTIVE_IMAGE_RESET 0x01 +#define DFU_LENGTH_SYSTEM_RESET 0x01 +#define DFU_LENGTH_REPORT_TARGET_INFO (1+2) //img_id +#define DFU_LENGTH_CONN_PARA_TO_UPDATE_REQ (1+2+2+2+2) //conn_interval_min,conn_interval_max,conn_latency,superv_tout +#define DFU_LENGTH_BUFFER_CHECK_EN (1) +#define DFU_LENGTH_REPORT_BUFFER_CRC (1+2+2) //buf_size, buf_crc + +/*notification opcode*/ +#define DFU_OPCODE_NOTIFICATION 0x10 + +/*length of notification*/ +#define DFU_NOTIFY_LENGTH_ARV 3 //others opcode notification length +//#define DFU_NOTIFY_LENGTH_START_DFU (DFU_NOTIFY_LENGTH_ARV) +//#define DFU_NOTIFY_LENGTH_VALID_FW (DFU_NOTIFY_LENGTH_ARV) +#if (RCU_SILENT_OTA == 1) +#define DFU_NOTIFY_LENGTH_REPORT_TARGET_INFO (DFU_NOTIFY_LENGTH_ARV+2+4) //img_ver, cur_offset +#else +#define DFU_NOTIFY_LENGTH_REPORT_TARGET_INFO (DFU_NOTIFY_LENGTH_ARV+4+4) //img_ver, cur_offset +#endif +#define DFU_NOTIFY_LENGTH_BUFFER_CHECK_EN (DFU_NOTIFY_LENGTH_ARV+2+2) //buf_size, mtu_size +#define DFU_NOTIFY_LENGTH_REPORT_BUFFER_CRC (DFU_NOTIFY_LENGTH_ARV+4) //cur_offset + +/*dfu error code*/ +#define DFU_ARV_SUCCESS 0x01 +#define DFU_ARV_FAIL_INVALID_PARAMETER 0x02 +#define DFU_ARV_FAIL_OPERATION 0x03 +#define DFU_ARV_FAIL_DATA_SIZE_EXCEEDS_LIMIT 0x04 +#define DFU_ARV_FAIL_CRC_ERROR 0x05 +#define DFU_ARV_FAIL_LENGTH_ERROR 0x06 +#define DFU_ARV_FAIL_PROG_ERROR 0x07 +#define DFU_ARV_FAIL_ERASE_ERROR 0x08 + +/** @defgroup DFU_Client_Exported_Types Exported Types + * @{ + */ + +/** @brief Handle cache for intrested UUIDs */ +typedef enum +{ + HDL_DFU_SRV_START, // start handle of dfu service + HDL_DFU_SRV_END, // end handle of dfu service + HDL_DFU_DATA, + HDL_DFU_CP, + HDL_DFU_CP_END, + HDL_DFU_CP_CCCD, + HDL_DFU_CACHE_LEN +} T_DFU_HANDLE_TYPE; + +/** @brief used to inform app the discovery procedure is done or pending */ +typedef enum +{ + DISC_DFU_IDLE, + DISC_DFU_START, + DISC_DFU_DONE, + DISC_DFU_FAIL, +} T_DFU_DISC_STATE; + +/** @brief handle information found in discovery procedure */ +typedef struct +{ + T_DFU_HANDLE_TYPE handle_type; + uint16_t handle_value; +} T_DFU_READ_DISC_HDL_INFO; + +/** @brief read request type, used by app to send read request */ +typedef enum +{ + DFU_READ_CP_CCCD +} T_DFU_READ_TYPE; + +/** @brief read content, used to inform app read response data content */ +typedef union +{ + bool dfu_cp_cccd; +} T_DFU_READ_DATA; + +/** @brief read data, used to inform app read response data */ +typedef struct +{ + T_DFU_READ_TYPE type; + T_DFU_READ_DATA data; + uint16_t cause; +} T_DFU_READ_RESULT; + +/** @brief write request result */ +typedef enum +{ + DFU_WRITE_CP, + DFU_WRITE_CP_CCCD, + DFU_WRITE_DATA +} T_DFU_WRITE_TYPE; + +typedef struct +{ + T_DFU_WRITE_TYPE type; + uint16_t cause; +} T_DFU_WRITE_RESULT; + +/** @brief notif/ind receive type */ +typedef enum +{ + DFU_NOTIF_RECEIVE_DFU_CP_NOTIFY, +} T_DFU_NOTIFY_INDICATE_TYPE; + +/** @brief notif/ind receive content */ +typedef struct +{ + uint16_t len; + uint8_t *pdata; +} T_DFU_NOTIFY_INDICATE_VAL; + +/** @brief The notif/ind data received by the client from the server */ +typedef struct +{ + T_DFU_NOTIFY_INDICATE_TYPE type; + T_DFU_NOTIFY_INDICATE_VAL value; +} T_DFU_NOTIFY_INDICATE_DATA; + +/** @brief Event type to inform app */ +typedef enum +{ + DFU_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + DFU_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + DFU_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + DFU_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + DFU_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_DFU_CLIENT_CB_TYPE; + +/** @brief Callback content sent to application from the client */ +typedef union +{ + T_DFU_DISC_STATE disc_state; + T_DFU_READ_DISC_HDL_INFO disc_hdl_info; + T_DFU_READ_RESULT read_result; + T_DFU_WRITE_RESULT write_result; + T_DFU_NOTIFY_INDICATE_DATA notif_ind_data; +} T_DFU_CLIENT_CB_CONTENT; + +/** @brief Callback data sent to application from the client, include type and content */ +typedef struct +{ + T_DFU_CLIENT_CB_TYPE cb_type; + T_DFU_CLIENT_CB_CONTENT cb_content; +} T_DFU_CLIENT_CB_DATA; + +/** @brief Used for CCCD handle discovering in discovery procedure */ +typedef enum +{ + DFU_CCCD_DISC_START, + DFU_CCCD_DISC_CP_NOTIFY, + DFU_CCCD_DISC_END +} T_DFU_CCCD_DISC_STATE; + + +typedef enum +{ + DFU_FSM_WRITE_DO_NOT_CARE, + DFU_FSM_WRITE_CCCD_ENABLE, + DFU_FSM_WRITE_DFU_DATA, + DFU_FSM_WRITE_WAIT_WRITE_RESP +} T_DFU_CLIENT_FSM_WRITE; + + +typedef enum +{ + DFU_CB_NONE, + DFU_CB_START, + DFU_CB_END, + DFU_CB_FAIL +} T_DFU_CB_TYPE; + +typedef union +{ + uint8_t dull; +} T_DFU_CB_DATA; + +/** Dfu service data to inform application */ +typedef struct +{ + uint8_t conn_id; + T_DFU_CB_TYPE type; + T_DFU_CB_DATA data; +} T_DFU_CB_MSG; + +typedef struct +{ + uint8_t ic_type; + uint8_t secure_version; + union + { + uint16_t value; + struct + { + uint16_t xip: 1; // payload is executed on flash + uint16_t enc: 1; // all the payload is encrypted + uint16_t load_when_boot: 1; // load image when boot + uint16_t enc_load: 1; // encrypt load part or not + uint16_t enc_key_select: 3; // referenced to ENC_KEY_SELECT + uint16_t not_ready : 1; //for copy image in ota + uint16_t not_obsolete : 1; //for copy image in ota + uint16_t rsvd: 7; + }; + } ctrl_flag; + uint16_t signature; //!< app then patch + uint16_t crc16; + uint32_t image_length; + + union + { + uint8_t value; + struct + { + uint8_t buffercheck: 1; // 1:support, 0:don't support + uint8_t aesflg: 1; // 1:aes encrypt when ota, 0:not encrypt + uint8_t aesmode: 1; // 1:all data is encrypted, 0:only encrypt 16byte + //uint8_t verify_algo: 1; // 1:sha256, 0:crc + uint8_t copy_img: 1; //1:support ,0:don't support + uint8_t multi_img: 1; //1:support(update multi img at a time) ,0:don't support(one img at a time) + uint8_t rsvd: 3; + }; + } mode; + uint16_t maxbuffersize; + uint32_t origin_image_version; + uint32_t curr_offset; + uint32_t dfu_img_version; + T_DFU_CB_TYPE fsm_client; +} T_DFU_CTX; + +extern T_DFU_CTX g_dfu_ctx; +/** @} */ + +/** @defgroup DFU_Client_Exported_Functions Exported Functions + * @{ + */ +/** + * @brief Used by application, to set the handles in Dfu handle cache. + * @param handle_type: handle types of this specific profile. + * @param handle_value: handle value to set. + * @retval true--set success. + * flase--set failed. + */ +bool dfu_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool dfu_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief add Dfu client to application. + * @param appCB: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID dfu_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num); + +/** + * @brief start the service discovery + * + * contains the service/characteristic/cccd declaration + * @param[in] conn_id: the connection id + * @return the operatino result + */ +bool dfu_client_start_discovery(uint8_t conn_id); + +/** + * @brief handle the adv pkt + * @param[in] p_le_scan_info: the adv pkt pointer + * @return none + */ +void dfu_client_handle_adv_pkt(T_LE_SCAN_INFO *p_le_scan_info); + +/** + * @brief Get the conn id when actively connect. + * @param[in] conn_id: the connection id + * @return none + */ +void dfu_client_handle_connecting(uint8_t conn_id); + +/** + * @brief handle the establish of connection + * + * discovery the dfu server etc. + * @param[in] conn_id: the connection id + * @return none + */ +void dfu_client_handle_connect(uint8_t conn_id); + +/** + * @brief handle the disconnetion + * + * to release the resource and notify the dfu state + * @param[in] conn_id: the connection id + * @return the operatino result + */ +void dfu_client_disconnect_cb(uint8_t conn_id); + +void dfu_client_connect_device(T_LE_SCAN_INFO *p_le_scan_info); + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DFU_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.c new file mode 100644 index 00000000..b5dd6c76 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.c @@ -0,0 +1,178 @@ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include "platform_stdlib.h" +#include +#include +#include +#include + +T_OS_QUEUE write_req_queue[4]; + +uint8_t request_in_process_flag[4] = {0, 0, 0, 0}; //e.g if send request then flag=1, receive response then flag=0 + +extern void bt_ota_central_client_app_discov_services(uint8_t conn_id, bool start); + + +/* if add write request information to queue */ +/* @return 0 -- queue is empty + * 1 -- add write request info to queue + 2 -- add discovery service info to queue + * -1 -- add data to queue fail + */ +int if_queue_in(uint8_t type, uint8_t conn_id, T_CLIENT_ID client_id, uint16_t handle, uint16_t length, uint8_t *p_data) +{ + if(os_queue_peek(&write_req_queue[conn_id]) == NULL && request_in_process_flag[conn_id] == 0) // queue empty, and no requesting + { + return 0; + } + else //if (user_req_flag == 1) //queue empty and exist requesting, or queue not empty and no requesting, or queue not empty and exist requesting + { + if(type == 0) //write request info queue in + { + /* for send data to queue */ + WRITE_REQ_INFO *add_write_data = NULL; + + add_write_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(WRITE_REQ_INFO)); + if(add_write_data == NULL) + { + printf("WRITE_REQ_INFO malloc fail\r\n"); + return -1; + } + memset(add_write_data, 0, sizeof(WRITE_REQ_INFO)); + + add_write_data->conn_id = conn_id; + add_write_data->client_id = client_id; + add_write_data->handle = handle; + add_write_data->length = length; + if(add_write_data->length != 0) + { + add_write_data->p_data = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if(add_write_data->p_data == NULL) + { + printf("malloc fail\r\n"); + os_mem_free(add_write_data); + return -1; + } + memcpy(add_write_data->p_data, p_data, length); + } + + os_queue_in(&write_req_queue[conn_id], (void *) add_write_data); + printf("(conn_id %d, client_id %d)add write request to queue\r\n", conn_id, client_id); + + return 1; + } + + if(type == 1) //discovery service info queue in + { + WRITE_REQ_INFO *add_service_info = NULL; + + add_service_info = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(WRITE_REQ_INFO)); + if(add_service_info == NULL) + { + printf("WRITE_REQ_INFO(of service info) malloc fail\r\n"); + return -1; + } + memset(add_service_info, 0, sizeof(WRITE_REQ_INFO)); + add_service_info->conn_id = conn_id; + add_service_info->status = 1; //flag: exist a write request before discovery service. + + os_queue_in(&write_req_queue[conn_id], (void *) add_service_info); + printf("(conn_id %d) add discovery service info to queue\r\n", conn_id); + + return 2; + } + } + + return -1; +} + + +/* if take out write request(or discovery service) information from queue */ +int if_queue_out_and_send(uint8_t conn_id) +{ + WRITE_REQ_INFO *out_write_data = NULL; + out_write_data = os_queue_out(&write_req_queue[conn_id]); + + if(out_write_data) + { + if(out_write_data->status == 1) + { + printf("exist discovery service info, os_queue_out\r\n"); + + //after user write request send success, then start discovery service + bt_ota_central_client_app_discov_services(conn_id, true); + + os_mem_free(out_write_data); + + return 1; + } + else + { + printf("(conn_id %d, client_id %d) os_queue_out\r\n", conn_id, out_write_data->client_id); + + if(out_write_data->p_data) + { + request_in_process_flag[conn_id] = 1; + if(client_attr_write(out_write_data->conn_id, out_write_data->client_id, GATT_WRITE_TYPE_REQ, out_write_data->handle, + out_write_data->length, out_write_data->p_data) != GAP_CAUSE_SUCCESS) + { + request_in_process_flag[conn_id] = 0; + printf("(conn_id %d, queue out)write request fail, please check!!!\r\n", conn_id); + } + os_mem_free(out_write_data->p_data); + } + + os_mem_free(out_write_data); + + return 2; + } + } + + return 0; +} + +/* if disconnected during ota process, then need queue out and free memory */ +void disconnect_and_queue_out(uint8_t conn_id) +{ + WRITE_REQ_INFO *out_req = NULL; + int i = 0; + + while(true) + { + out_req = os_queue_out(&write_req_queue[conn_id]); + if(out_req) + { + printf("exist items in queue, queue out item %d\r\n", i++); + + if(out_req->p_data) + { + os_mem_free(out_req->p_data); + out_req->p_data = NULL; + } + + os_mem_free(out_req); + out_req = NULL; + } + else + { + /* clear flag and queue */ + request_in_process_flag[conn_id] = 0; + memset(&write_req_queue[conn_id], 0, sizeof(T_OS_QUEUE)); + + break; + } + } + +} + +void connect_and_init(uint8_t conn_id) +{ + /* init flag and queue*/ + request_in_process_flag[conn_id] = 0; + memset(&write_req_queue[conn_id], 0, sizeof(T_OS_QUEUE)); + + os_queue_init(&write_req_queue[conn_id]); +} +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.h new file mode 100644 index 00000000..7a3ddd46 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.h @@ -0,0 +1,47 @@ +#ifndef _INSERT_WRITE_H_ +#define _INSERT_WRITE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +#include +#include + +/* used for storage write request info during ota process */ +typedef struct write_req_info_t +{ + struct write_req_info_t *p_next; // Pointer to the next item, must be the first field. + uint8_t status; //0 -- default, 1 -- mark service discovery process. + T_CLIENT_ID client_id; + uint8_t conn_id; + uint16_t handle; + uint16_t length; + uint8_t *p_data; +} WRITE_REQ_INFO; + +typedef struct +{ + uint8_t conn_id; + uint16_t handle; +} T_OTA_WRITE_MSG; + +extern T_OS_QUEUE write_req_queue[4]; + +extern uint8_t request_in_process_flag[4]; //if send request then flag=1, receive response then flag=0 + +int if_queue_in(uint8_t type, uint8_t conn_id, T_CLIENT_ID client_id, uint16_t handle, uint16_t length, uint8_t *p_data); + +int if_queue_out_and_send(uint8_t conn_id); + +void disconnect_and_queue_out(uint8_t conn_id); + +void connect_and_init(uint8_t conn_id); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/ota_client.c b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/ota_client.c new file mode 100644 index 00000000..7f323c2b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/ota_client.c @@ -0,0 +1,656 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ota_client.c + * @brief ota service client source file. + * @details + * @author + * @date + * @version + ****************************************************************************** + * @attention + *

© COPYRIGHT 2015 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT) && CONFIG_BT_OTA_CENTRAL_CLIENT +#include +#include +#include "trace_app.h" +#include "gap_conn_le.h" +#include "bt_types.h" +#include "mem_types.h" +#include "os_mem.h" +#include "ota_client.h" +/** + * @brief OTA client Link control block definition. + */ +typedef struct +{ + T_OTA_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_OTA_CACHE_LEN]; +} T_OTA_LINK, *P_OTA_LINK; + + +static P_OTA_LINK ota_table; +static uint8_t ota_link_num; + +/**< OTA client ID. */ +static T_CLIENT_ID ota_client = CLIENT_PROFILE_GENERAL_ID; +/**< Callback used to send data to app from OTA client layer. */ +static P_FUN_GENERAL_APP_CB ota_client_cb = NULL; + +const uint8_t ota_service_uuid[16] = {GATT_UUID_OTA_SERVICE}; + +/** + * @brief Used by application, to start the discovery procedure of OTA server. + * @param[in] conn_id connection ID. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool ota_client_start_discovery(uint8_t conn_id) +{ + APP_PRINT_INFO0("ota_client_start_discovery"); + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + /* First clear handle cache. */ + memset(&ota_table[conn_id], 0, sizeof(T_OTA_LINK)); + ota_table[conn_id].disc_state = DISC_OTA_START; + if (client_by_uuid128_srv_discovery(conn_id, ota_client, + (uint8_t *)ota_service_uuid) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + + +static bool ota_client_start_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("ota_client_start_char_discovery"); + start_handle = ota_table[conn_id].hdl_cache[HDL_OTA_SRV_START]; + end_handle = ota_table[conn_id].hdl_cache[HDL_OTA_SRV_END]; + if (client_all_char_discovery(conn_id, ota_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +/** + * @brief Used by application, to read data from server by using handles. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool ota_client_read_by_handle(uint8_t conn_id, T_OTA_READ_TYPE read_type) +{ + bool hdl_valid = false; + uint16_t handle; + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case OTA_READ_DEVICE_MAC: + if (ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_MAC]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_MAC]; + hdl_valid = true; + } + break; + case OTA_READ_PATCH_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_VER]; + hdl_valid = true; + } + break; + case OTA_READ_APP_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_APP_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_APP_VER]; + hdl_valid = true; + } + break; + case OTA_READ_PATCH_EXT_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_EXT_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_EXT_VER]; + hdl_valid = true; + } + break; + case OTA_READ_DEVICE_INFO: + if (ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_INFO]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_INFO]; + hdl_valid = true; + } + break; + case OTA_READ_IMG_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_IMG_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_IMG_VER]; + hdl_valid = true; + } + break; + + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, ota_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("ota_client_read_by_handle: Request fail! Please check!"); + return false; +} + + +/** + * @brief Used by application, to write ota cmd write Characteristic. + * @param[in] conn_id connection ID. + * @param[in] length write data length + * @param[in] p_value point the value to write + * @param[in] type write type. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool ota_client_write_char(uint8_t conn_id, T_OTA_WRTIE_TYPE write_type) +{ + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_write_char: failed invalid conn_id %d", conn_id); + return false; + } + + switch (write_type) + { + case OTA_WRITE_CMD: + { + PROFILE_PRINT_INFO1("write handle 0x%x", ota_table[conn_id].hdl_cache[HDL_OTA_CMD]); + if (ota_table[conn_id].hdl_cache[HDL_OTA_CMD]) + { + uint16_t handle = ota_table[conn_id].hdl_cache[HDL_OTA_CMD]; + uint8_t ota_cmd = OTA_WRITE_OTA_CMD_CHAR_VAL; + if (client_attr_write(conn_id, ota_client, GATT_WRITE_TYPE_CMD, handle, + sizeof(ota_cmd), &ota_cmd) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + break; + } + case OTA_WRITE_TEST_MODE: + { + if (ota_table[conn_id].hdl_cache[HDL_OTA_TEST_MODE]) + { + uint16_t handle = ota_table[conn_id].hdl_cache[HDL_OTA_TEST_MODE]; + uint8_t test_mode = OTA_WRITE_TEST_MODE_CHAR_VAL; + if (client_attr_write(conn_id, ota_client, GATT_WRITE_TYPE_CMD, handle, + sizeof(test_mode), &test_mode) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + break; + } + case OTA_WRITE_IMG_COUNTER: + { + if (ota_table[conn_id].hdl_cache[HDL_OTA_IMG_COUNTER]) + { + uint16_t handle = ota_table[conn_id].hdl_cache[HDL_OTA_IMG_COUNTER]; + uint8_t img_counter = OTA_WRITE_OTA_IMG_COUNTER_CHAR_VAL; + if (client_attr_write(conn_id, ota_client, GATT_WRITE_TYPE_CMD, handle, + sizeof(img_counter), &img_counter) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + break; + } + default: + break; + + } + + PROFILE_PRINT_WARN1("ota_client_write_char fail! write_type: %d!", write_type); + return false; +} + + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool ota_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (ota_table[conn_id].disc_state != DISC_OTA_DONE) + { + PROFILE_PRINT_ERROR1("ota_client_get_hdl_cache: failed invalid state %d", + ota_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_OTA_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("ota_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, ota_table[conn_id].hdl_cache, len); + return true; +} +/** + * @brief Used by application, to set handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool ota_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (ota_table[conn_id].disc_state != DISC_OTA_IDLE) + { + PROFILE_PRINT_ERROR1("ota_client_set_hdl_cache: failed invalid state %d", + ota_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_OTA_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("ota_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(ota_table[conn_id].hdl_cache, p_hdl_cache, len); + ota_table[conn_id].disc_state = DISC_OTA_DONE; + return true; +} + + +static void ota_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + bool cb_flag = false; + T_OTA_CLIENT_CB_DATA cb_data; + cb_data.cb_type = OTA_CLIENT_CB_TYPE_DISC_STATE; + + PROFILE_PRINT_INFO1("ota_client_discover_state_cb: discovery_state = %d", discovery_state); + if (ota_table[conn_id].disc_state == DISC_OTA_START) + { + switch (discovery_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((ota_table[conn_id].hdl_cache[HDL_OTA_SRV_START] != 0) + || (ota_table[conn_id].hdl_cache[HDL_OTA_SRV_END] != 0)) + { + if (ota_client_start_char_discovery(conn_id) == false) + { + ota_table[conn_id].disc_state = DISC_OTA_FAILED; + cb_flag = true; + } + } + /* No ota handle found. Discover procedure complete. */ + else + { + ota_table[conn_id].disc_state = DISC_OTA_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + ota_table[conn_id].disc_state = DISC_OTA_DONE; + cb_flag = true; + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + break; + default: + PROFILE_PRINT_ERROR0("Invalid Discovery State!"); + break; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && ota_client_cb) + { + cb_data.cb_content.disc_state = ota_table[conn_id].disc_state; + (*ota_client_cb)(ota_client, conn_id, &cb_data); + } + return; +} + + +static void ota_client_discover_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + uint16_t handle; + uint16_t *hdl_cache; + hdl_cache = ota_table[conn_id].hdl_cache; + PROFILE_PRINT_INFO1("ota_client_discover_result_cb: result_type = %d", result_type); + if (ota_table[conn_id].disc_state == DISC_OTA_START) + { + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + PROFILE_PRINT_INFO0("DISC_RESULT_SRV_DATA"); + ota_table[conn_id].hdl_cache[HDL_OTA_SRV_START] = + result_data.p_srv_disc_data->att_handle; + ota_table[conn_id].hdl_cache[HDL_OTA_SRV_END] = + result_data.p_srv_disc_data->end_group_handle; + break; + + case DISC_RESULT_CHAR_UUID16: + { + PROFILE_PRINT_INFO2("DISC_RESULT_CHAR_UUID16: handle 0x%x, uuid 0x%x", + result_data.p_char_uuid16_disc_data->value_handle, + result_data.p_char_uuid16_disc_data->uuid16); + handle = result_data.p_char_uuid16_disc_data->value_handle; + switch (result_data.p_char_uuid16_disc_data->uuid16) + { + case GATT_UUID_CHAR_OTA: + hdl_cache[HDL_OTA_CMD] = handle; + break; + case GATT_UUID_CHAR_MAC: + hdl_cache[HDL_OTA_DEVICE_MAC] = handle; + break; + case GATT_UUID_CHAR_PATCH: + hdl_cache[HDL_OTA_PATCH_VER] = handle; + break; + case GATT_UUID_CHAR_APP_VERSION: + hdl_cache[HDL_OTA_APP_VER] = handle; + break; + case GATT_UUID_CHAR_PATCH_EXTENSION: + hdl_cache[HDL_OTA_PATCH_EXT_VER] = handle; + break; + case GATT_UUID_CHAR_TEST_MODE: + hdl_cache[HDL_OTA_TEST_MODE] = handle; + break; + case GATT_UUID_CHAR_DEVICE_INFO: + hdl_cache[HDL_OTA_DEVICE_INFO] = handle; + break; + case GATT_UUID_CHAR_IMAGE_COUNT_TO_UPDATE: + hdl_cache[HDL_OTA_IMG_COUNTER] = handle; + break; + case GATT_UUID_CHAR_IMAGE_VERSION: + hdl_cache[HDL_OTA_IMG_VER] = handle; + break; + default: + /* have no intrest on this handle. */ + break; + } + } + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + + return; +} + +static void ota_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_OTA_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = ota_table[conn_id].hdl_cache; + cb_data.cb_type = OTA_CLIENT_CB_TYPE_READ_RESULT; + + PROFILE_PRINT_INFO2("ota_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + + if (handle == hdl_cache[HDL_OTA_DEVICE_MAC]) + { + cb_data.cb_content.read_result.type = OTA_READ_DEVICE_MAC; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_PATCH_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_PATCH_VER; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_APP_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_APP_VER; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_PATCH_EXT_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_PATCH_EXT_VER; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_DEVICE_INFO]) + { + cb_data.cb_content.read_result.type = OTA_READ_DEVICE_INFO; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_IMG_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_IMG_VER; + if (cause == GAP_SUCCESS) + { + //ota header, secure boot, patch, app version + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else + { + return; + } + + if (ota_client_cb) + { + (*ota_client_cb)(ota_client, conn_id, &cb_data); + } + return; +} + +static void ota_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, + uint16_t cause, + uint8_t credits) +{ + T_OTA_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = ota_table[conn_id].hdl_cache; + cb_data.cb_type = OTA_CLIENT_CB_TYPE_WRITE_RESULT; + + PROFILE_PRINT_INFO2("ota_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.write_result.cause = cause; + + if (handle == hdl_cache[HDL_OTA_CMD]) + { + cb_data.cb_content.write_result.type = OTA_WRITE_CMD; + } + else if (handle == hdl_cache[HDL_OTA_TEST_MODE]) + { + cb_data.cb_content.write_result.type = OTA_WRITE_TEST_MODE; + } + else if (handle == hdl_cache[HDL_OTA_IMG_COUNTER]) + { + cb_data.cb_content.write_result.type = OTA_WRITE_IMG_COUNTER; + } + else + { + return; + } + + /* Inform application the write result. */ + if (ota_client_cb) + { + (*ota_client_cb)(ota_client, conn_id, &cb_data); + } + return; +} + + +/** + * @brief OTA Client Callbacks. +*/ +const T_FUN_CLIENT_CBS ota_client_cbs = +{ + ota_client_discover_state_cb, //!< Discovery State callback function pointer + ota_client_discover_result_cb, //!< Discovery result callback function pointer + ota_client_read_result_cb, //!< Read response callback function pointer + ota_client_write_result_cb, //!< Write result callback function pointer + NULL, //ota_client_notify_ind_cb, //!< Notify Indicate callback function pointer + NULL//ota_client_disc_cb //!< Link disconnection callback function pointer +}; + +/** + * @brief add Dfu client to application. + * @param appCB: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID ota_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > OTA_MAX_LINKS) + { + PROFILE_PRINT_ERROR1("ota_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&ota_client, &ota_client_cbs)) + { + ota_client = CLIENT_PROFILE_GENERAL_ID; + DFU_PRINT_ERROR0("ota_client_add: fail!"); + return ota_client; + } + DFU_PRINT_INFO1("ota_client_add: client ID = %d", ota_client); + ota_link_num = link_num; + size = ota_link_num * sizeof(T_OTA_LINK); + ota_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + /* register callback for profile to inform application that some events happened. */ + ota_client_cb = app_cb; + return ota_client; + +} + +void ota_delete_client(void) +{ + if (ota_table != NULL) { + os_mem_free(ota_table); + ota_table = NULL; + } +} + + +/** + * @brief ota client connect target device. + * @param p_le_scan_info: filtered scan info + */ +void ota_client_connect_device(T_LE_SCAN_INFO *p_le_scan_info) +{ + PROFILE_PRINT_INFO1("ota_client_connect_device: p_le_scan_info->adv_type = %d", + p_le_scan_info->adv_type); + if (p_le_scan_info->adv_type != GAP_ADV_EVT_TYPE_UNDIRECTED) + { + return; + } + + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + conn_req_param.scan_interval = 0xA0; + conn_req_param.scan_window = 0x80; + conn_req_param.conn_interval_min = 0x60; + conn_req_param.conn_interval_max = 0x60; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + T_GAP_CAUSE cause; + if (GAP_CAUSE_SUCCESS == (cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, p_le_scan_info->bd_addr, + p_le_scan_info->remote_addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, 1000))) + { + PROFILE_PRINT_INFO2("ota_client_connect_device: try connecting %s, remote_addr_type=%d", + TRACE_BDADDR(p_le_scan_info->bd_addr), p_le_scan_info->remote_addr_type); + } + else + { + PROFILE_PRINT_WARN1("ota_client_connect_device: FAIL cause=%d!", cause); + } + + + return; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/ota_client.h b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/ota_client.h new file mode 100644 index 00000000..a7767833 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/ota_client.h @@ -0,0 +1,261 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ota_client.h + * @brief Head file for using ota service Client. + * @details Data structs and external functions declaration. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _OTA_CLIENT_H_ +#define _OTA_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Add Includes here */ +#include "profile_client.h" + +#define GATT_UUID_OTA_SERVICE 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xD0, 0x00, 0x00 + +#define GATT_UUID_OTA_PROFILE + +#define GATT_UUID_CHAR_OTA 0xFFD1 //1, write +#define GATT_UUID_CHAR_MAC 0xFFD2 //2 +#define GATT_UUID_CHAR_PATCH 0xFFD3 //3 +#define GATT_UUID_CHAR_APP_VERSION 0xFFD4 //4 +#define GATT_UUID_CHAR_PATCH_EXTENSION 0xFFD5 //5 +#define GATT_UUID_CHAR_TEST_MODE 0xFFD8 //6, write + +#define GATT_UUID_CHAR_DEVICE_INFO 0xFFF1 //7 +#define GATT_UUID_CHAR_IMAGE_COUNT_TO_UPDATE 0xFFF2 //8, write +#define GATT_UUID_CHAR_IMAGE_VERSION 0xFFE0 + + +#define OTA_WRITE_OTA_CMD_CHAR_VAL 0x01 +#define OTA_WRITE_TEST_MODE_CHAR_VAL 0x02 +#define OTA_WRITE_OTA_IMG_COUNTER_CHAR_VAL 0x03 + +/** @defgroup DFU_Client + * @{ + */ +/** @brief Define links number. range: 0-4 */ +#define OTA_MAX_LINKS 4 + +typedef struct _T_OTA_DEVICE_INFO +{ + uint8_t ictype; + uint8_t ota_version; + uint8_t secure_version; + + union + { + uint8_t value; + struct + { + uint8_t buffercheck: 1; // 1:support, 0:don't support + uint8_t aesflg: 1; // 1:aes encrypt when ota, 0:not encrypt + uint8_t aesmode: 1; // 1:all data is encrypted, 0:only encrypt 16byte + //uint8_t verify_algo: 1; // 1:sha256, 0:crc + uint8_t copy_img: 1; //1:support ,0:don't support + uint8_t multi_img: 1; //1:support(update multi img at a time) ,0:don't support(one img at a time) + uint8_t rsvd: 3; + }; + } mode; + + uint16_t maxbuffersize; + uint16_t res; + + uint32_t img_indicator; +} T_OTA_DEVICE_INFO, *P_OTA_DEVICE_INFO; + +/** @defgroup DFU_Client_Exported_Types Exported Types + * @{ + */ +/** @brief OTA client handle type*/ +typedef enum +{ + HDL_OTA_SRV_START, //!< start handle of battery service + HDL_OTA_SRV_END, //!< end handle of battery service + HDL_OTA_CMD, //!< OTA CMD characteristic value handle + HDL_OTA_DEVICE_MAC, + HDL_OTA_PATCH_VER, + HDL_OTA_APP_VER, + HDL_OTA_PATCH_EXT_VER, + HDL_OTA_TEST_MODE, //!< OTA test mode characteristic handle + HDL_OTA_DEVICE_INFO, + HDL_OTA_IMG_COUNTER, //! +#include +//#include "rtl876x.h" +//#include "flash_device.h" + +/** @addtogroup FLASH_DEVICE Flash Device + * @{ + */ +#define OTA_HEADER_SIZE 0x1000 +#define OTA_HEADER_DEFAULT_VALUE 0xFFFFFFFF + +#define AUTO_ENTER_DFU_MODE_PATTERN 0xC58E +#define USE_SINGLE_BANK_OTA_PATTERN 0x7369 + +#define IMG_HEADER_SIZE 1024 + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup FLASH_DEVICE_Exported_Types Flash Device Exported Types + * @brief + * @{ + */ + +typedef enum +{ + SCCD = 0x278D, + OCCD = 0x278E, + FactoryCode = 0x278F, + OTA = 0x2790, /**< OTA header */ + SecureBoot = 0x2791, + RomPatch = 0x2792, + AppPatch = 0x2793, + AppData1 = 0x2794, + AppData2 = 0x2795, + AppData3 = 0x2796, + AppData4 = 0x2797, + AppData5 = 0x2798, + AppData6 = 0x2799, + IMAGE_MAX = 0x279a, + IMAGE_USER_DATA = 0xFFFE, /**= IMAGE_MAX) //not support + { + return image_size; + } + else + { + uint32_t ota_header_addr = get_active_ota_bank_addr(); + + if (!check_header_valid(ota_header_addr, OTA)) + { + return image_size; + } + else + { + if (image_id == OTA) + { + image_size = OTA_HEADER_SIZE; + } + else + { + T_OTA_HEADER_FORMAT *ota_header = (T_OTA_HEADER_FORMAT *)ota_header_addr; + + image_size = HAL_READ32((uint32_t)&ota_header->secure_boot_size, (image_id - SecureBoot) * 8); + + if (OTA_HEADER_DEFAULT_VALUE == image_size) + { + image_size = 0; + } + } + } + } + + return image_size; +} + +/** + * @brief get image version of specified image which located in ota active bank + * @param image_id specify the image which located in ota active bank + * @param p_image_version the T_IMAGE_VERSION pointer which indicate specified image's version and sub verdion + * @note + * 1.If get ota header version, sub version have no meaning. + * 2.If patch not support cmd flash_ioctl_get_image_addr_by_image_id_ext,it will get app data3-6 version fail + * @return true if get specified image version successfully +*/ +static inline bool get_active_bank_image_version(T_IMG_ID image_id, + T_IMAGE_VERSION *p_image_version) +{ + uint32_t image_addr; + uint32_t image_size; + + if ((image_id < OTA) || (image_id >= IMAGE_MAX)) //not support + { + return false; + } + else if (image_id == OTA) + { + image_addr = get_header_addr_by_img_id(image_id); + T_OTA_HEADER_FORMAT *p_header = (T_OTA_HEADER_FORMAT *)image_addr; + if (!p_header) + { + return false; + } + else + { + p_image_version->ver_info.version = p_header->ver_val; + return true; + } + } +#ifdef SDK_8772 + image_addr = get_header_addr_by_img_id(image_id); +#else + else if (image_id <= AppData2) + { + image_addr = get_header_addr_by_img_id(image_id); + } + else + { + //if patch not support cmd flash_ioctl_get_image_addr_by_image_id_ext, will get app data3-6 version fail!!! + image_addr = flash_ioctl(flash_ioctl_get_image_addr_by_image_id_ext, image_id, 0); + } +#endif + image_size = get_active_bank_image_size_by_img_id(image_id); + + //get active bank image version when image id is not less than OTA + T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)image_addr; + if ((!p_header) || (image_size == 0)) + { + return false; + } + else + { + p_image_version->ver_info.version = p_header->git_ver.ver_info.version; + return true; + } +} + + +/** @} */ /* End of group FLASH_DEVICE_Exported_Functions */ +/** @} */ /* End of group FLASH_DEVICE */ +#endif +#endif // _PATCH_HEADER_CHECK_H_ diff --git a/component/common/bluetooth/realtek/sdk/example/customer_example/GEL/mesh_ota/amazon/btmesh_dev.a b/component/common/bluetooth/realtek/sdk/example/customer_example/GEL/mesh_ota/amazon/btmesh_dev.a new file mode 100644 index 00000000..bf58cdf7 Binary files /dev/null and b/component/common/bluetooth/realtek/sdk/example/customer_example/GEL/mesh_ota/amazon/btmesh_dev.a differ diff --git a/component/common/bluetooth/realtek/sdk/example/customer_example/GEL/mesh_ota/amazon/btmesh_prov.a b/component/common/bluetooth/realtek/sdk/example/customer_example/GEL/mesh_ota/amazon/btmesh_prov.a new file mode 100644 index 00000000..9dad8380 Binary files /dev/null and b/component/common/bluetooth/realtek/sdk/example/customer_example/GEL/mesh_ota/amazon/btmesh_prov.a differ diff --git a/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_customer.h b/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_customer.h new file mode 100644 index 00000000..1ef4ea29 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_customer.h @@ -0,0 +1,19 @@ +#ifndef GAP_CUSTOMER_H +#define GAP_CUSTOMER_H + +#include "bt_flags.h" + +typedef struct +{ + //FW version + uint16_t hci_revision; + uint16_t lmp_subversion; + //Upperstack version + uint16_t btgap_revision; + uint16_t btgap_buildnum; +} T_BT_VERSION_INFO; + +bool gap_get_bt_version_info(T_BT_VERSION_INFO *p_info); + + +#endif /* GAP_DTM_H */ diff --git a/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_storage_le.h b/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_storage_le.h index 6fcb7523..b73428de 100644 --- a/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_storage_le.h +++ b/component/common/bluetooth/realtek/sdk/inc/bluetooth/gap/gap_storage_le.h @@ -648,6 +648,19 @@ bool le_get_dev_bond_info(T_LE_KEY_ENTRY *p_entry, uint8_t *p_data); */ T_LE_KEY_ENTRY *le_set_dev_bond_info(uint16_t length, uint8_t *p_data, bool *exist); +/** + * @brief Get device LTK information. + * + * @param[in] p_entry Pointer to the key entry of bonded device. + * @param[in] remote Read the remote LTK or the local LTK. + * @param[out] p_key_len Pointer to LTK key length to read. + * @param[out] p_ltk Pointer to LTK to read. + * @return Operation result. + * @retval true Operation success. + * @retval false Operation failure. + */ +bool le_get_dev_ltk(T_LE_KEY_ENTRY *p_entry, bool remote, uint8_t *p_key_len, uint8_t *p_ltk); + /** @} */ /* End of group GAP_LE_STORAGE_EXPORT_Functions */ /** @} */ /* End of group GAP_LE_STORAGE */ diff --git a/component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client/dfu_client.h b/component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client/dfu_client.h new file mode 100644 index 00000000..1e7fbb09 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client/dfu_client.h @@ -0,0 +1,366 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file dfu_client.h + * @brief Head file for using dfu service Client. + * @details Data structs and external functions declaration. + * @author bill + * @date 2018-4-17 + * @version v2.0 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _DFU_CLIENT_H_ +#define _DFU_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Add Includes here */ +#include "profile_client.h" +#include "bt_ota_central_client.h" + +/** @defgroup DFU_Client + * @{ + */ +/** @brief Define links number. range: 0-4 */ +#define DFU_MAX_LINKS 4 + +#define NORMAL_OTA_MAX_BUFFER_SIZE 2000 + +/*each control point procedure*/ +#define DFU_OPCODE_MIN 0x00 +#define DFU_OPCODE_START_DFU 0x01 +#define DFU_OPCODE_RECEIVE_FW_IMAGE_INFO 0x02 +#define DFU_OPCODE_VALID_FW 0x03 +#define DFU_OPCODE_ACTIVE_IMAGE_RESET 0x04 +#define DFU_OPCODE_SYSTEM_RESET 0x05 +#define DFU_OPCODE_REPORT_TARGET_INFO 0x06 +#define DFU_OPCODE_CONN_PARA_TO_UPDATE_REQ 0x07 + +#define DFU_OPCODE_PKT_RX_NOTIFICATION_VOICE 0x08 +#define DFU_OPCODE_BUFFER_CHECK_EN 0x09 /*report current ota function version information*/ +#define DFU_OPCODE_REPORT_BUFFER_CRC 0x0a /*report current buffer CRC*/ + +#define DFU_OPCODE_RECEIVE_IC_TYPE 0x0b +#define DFU_OPCODE_COPY_IMG 0x0c +#define DFU_OPCODE_MAX 0x0d + +/*length of each control point procedure*/ +#define DFU_LENGTH_START_DFU (1+12+4)/*4 bytes is padding for encrypt*/ +#define DFU_LENGTH_RECEIVE_FW_IMAGE_INFO (1+2+4) //img_id + cur_offset +#define DFU_LENGTH_VALID_FW (1+2) //img_id +#define DFU_LENGTH_ACTIVE_IMAGE_RESET 0x01 +#define DFU_LENGTH_SYSTEM_RESET 0x01 +#define DFU_LENGTH_REPORT_TARGET_INFO (1+2) //img_id +#define DFU_LENGTH_CONN_PARA_TO_UPDATE_REQ (1+2+2+2+2) //conn_interval_min,conn_interval_max,conn_latency,superv_tout +#define DFU_LENGTH_BUFFER_CHECK_EN (1) +#define DFU_LENGTH_REPORT_BUFFER_CRC (1+2+2) //buf_size, buf_crc + +/*notification opcode*/ +#define DFU_OPCODE_NOTIFICATION 0x10 + +/*length of notification*/ +#define DFU_NOTIFY_LENGTH_ARV 3 //others opcode notification length +//#define DFU_NOTIFY_LENGTH_START_DFU (DFU_NOTIFY_LENGTH_ARV) +//#define DFU_NOTIFY_LENGTH_VALID_FW (DFU_NOTIFY_LENGTH_ARV) +#if (RCU_SILENT_OTA == 1) +#define DFU_NOTIFY_LENGTH_REPORT_TARGET_INFO (DFU_NOTIFY_LENGTH_ARV+2+4) //img_ver, cur_offset +#else +#define DFU_NOTIFY_LENGTH_REPORT_TARGET_INFO (DFU_NOTIFY_LENGTH_ARV+4+4) //img_ver, cur_offset +#endif +#define DFU_NOTIFY_LENGTH_BUFFER_CHECK_EN (DFU_NOTIFY_LENGTH_ARV+2+2) //buf_size, mtu_size +#define DFU_NOTIFY_LENGTH_REPORT_BUFFER_CRC (DFU_NOTIFY_LENGTH_ARV+4) //cur_offset + +/*dfu error code*/ +#define DFU_ARV_SUCCESS 0x01 +#define DFU_ARV_FAIL_INVALID_PARAMETER 0x02 +#define DFU_ARV_FAIL_OPERATION 0x03 +#define DFU_ARV_FAIL_DATA_SIZE_EXCEEDS_LIMIT 0x04 +#define DFU_ARV_FAIL_CRC_ERROR 0x05 +#define DFU_ARV_FAIL_LENGTH_ERROR 0x06 +#define DFU_ARV_FAIL_PROG_ERROR 0x07 +#define DFU_ARV_FAIL_ERASE_ERROR 0x08 + +/** @defgroup DFU_Client_Exported_Types Exported Types + * @{ + */ + +/** @brief Handle cache for intrested UUIDs */ +typedef enum +{ + HDL_DFU_SRV_START, // start handle of dfu service + HDL_DFU_SRV_END, // end handle of dfu service + HDL_DFU_DATA, + HDL_DFU_CP, + HDL_DFU_CP_END, + HDL_DFU_CP_CCCD, + HDL_DFU_CACHE_LEN +} T_DFU_HANDLE_TYPE; + +/** @brief used to inform app the discovery procedure is done or pending */ +typedef enum +{ + DISC_DFU_IDLE, + DISC_DFU_START, + DISC_DFU_DONE, + DISC_DFU_FAIL, +} T_DFU_DISC_STATE; + +/** @brief handle information found in discovery procedure */ +typedef struct +{ + T_DFU_HANDLE_TYPE handle_type; + uint16_t handle_value; +} T_DFU_READ_DISC_HDL_INFO; + +/** @brief read request type, used by app to send read request */ +typedef enum +{ + DFU_READ_CP_CCCD +} T_DFU_READ_TYPE; + +/** @brief read content, used to inform app read response data content */ +typedef union +{ + bool dfu_cp_cccd; +} T_DFU_READ_DATA; + +/** @brief read data, used to inform app read response data */ +typedef struct +{ + T_DFU_READ_TYPE type; + T_DFU_READ_DATA data; + uint16_t cause; +} T_DFU_READ_RESULT; + +/** @brief write request result */ +typedef enum +{ + DFU_WRITE_CP, + DFU_WRITE_CP_CCCD, + DFU_WRITE_DATA +} T_DFU_WRITE_TYPE; + +typedef struct +{ + T_DFU_WRITE_TYPE type; + uint16_t cause; +} T_DFU_WRITE_RESULT; + +/** @brief notif/ind receive type */ +typedef enum +{ + DFU_NOTIF_RECEIVE_DFU_CP_NOTIFY, +} T_DFU_NOTIFY_INDICATE_TYPE; + +/** @brief notif/ind receive content */ +typedef struct +{ + uint16_t len; + uint8_t *pdata; +} T_DFU_NOTIFY_INDICATE_VAL; + +/** @brief The notif/ind data received by the client from the server */ +typedef struct +{ + T_DFU_NOTIFY_INDICATE_TYPE type; + T_DFU_NOTIFY_INDICATE_VAL value; +} T_DFU_NOTIFY_INDICATE_DATA; + +/** @brief Event type to inform app */ +typedef enum +{ + DFU_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + DFU_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + DFU_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + DFU_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + DFU_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_DFU_CLIENT_CB_TYPE; + +/** @brief Callback content sent to application from the client */ +typedef union +{ + T_DFU_DISC_STATE disc_state; + T_DFU_READ_DISC_HDL_INFO disc_hdl_info; + T_DFU_READ_RESULT read_result; + T_DFU_WRITE_RESULT write_result; + T_DFU_NOTIFY_INDICATE_DATA notif_ind_data; +} T_DFU_CLIENT_CB_CONTENT; + +/** @brief Callback data sent to application from the client, include type and content */ +typedef struct +{ + T_DFU_CLIENT_CB_TYPE cb_type; + T_DFU_CLIENT_CB_CONTENT cb_content; +} T_DFU_CLIENT_CB_DATA; + +/** @brief Used for CCCD handle discovering in discovery procedure */ +typedef enum +{ + DFU_CCCD_DISC_START, + DFU_CCCD_DISC_CP_NOTIFY, + DFU_CCCD_DISC_END +} T_DFU_CCCD_DISC_STATE; + + +typedef enum +{ + DFU_FSM_WRITE_DO_NOT_CARE, + DFU_FSM_WRITE_CCCD_ENABLE, + DFU_FSM_WRITE_DFU_DATA, + DFU_FSM_WRITE_WAIT_WRITE_RESP +} T_DFU_CLIENT_FSM_WRITE; + + +typedef enum +{ + DFU_CB_NONE, + DFU_CB_START, + DFU_CB_END, + DFU_CB_FAIL +} T_DFU_CB_TYPE; + +typedef union +{ + uint8_t dull; +} T_DFU_CB_DATA; + +/** Dfu service data to inform application */ +typedef struct +{ + uint8_t conn_id; + T_DFU_CB_TYPE type; + T_DFU_CB_DATA data; +} T_DFU_CB_MSG; + +typedef struct +{ + uint8_t ic_type; + uint8_t secure_version; + union + { + uint16_t value; + struct + { + uint16_t xip: 1; // payload is executed on flash + uint16_t enc: 1; // all the payload is encrypted + uint16_t load_when_boot: 1; // load image when boot + uint16_t enc_load: 1; // encrypt load part or not + uint16_t enc_key_select: 3; // referenced to ENC_KEY_SELECT + uint16_t not_ready : 1; //for copy image in ota + uint16_t not_obsolete : 1; //for copy image in ota + uint16_t rsvd: 7; + }; + } ctrl_flag; + uint16_t signature; //!< app then patch + uint16_t crc16; + uint32_t image_length; + + union + { + uint8_t value; + struct + { + uint8_t buffercheck: 1; // 1:support, 0:don't support + uint8_t aesflg: 1; // 1:aes encrypt when ota, 0:not encrypt + uint8_t aesmode: 1; // 1:all data is encrypted, 0:only encrypt 16byte + //uint8_t verify_algo: 1; // 1:sha256, 0:crc + uint8_t copy_img: 1; //1:support ,0:don't support + uint8_t multi_img: 1; //1:support(update multi img at a time) ,0:don't support(one img at a time) + uint8_t rsvd: 3; + }; + } mode; + uint16_t maxbuffersize; + uint32_t origin_image_version; + uint32_t curr_offset; + uint32_t dfu_img_version; + T_DFU_CB_TYPE fsm_client; +} T_DFU_CTX; + +extern T_DFU_CTX g_dfu_ctx; +/** @} */ + +/** @defgroup DFU_Client_Exported_Functions Exported Functions + * @{ + */ +/** + * @brief Used by application, to set the handles in Dfu handle cache. + * @param handle_type: handle types of this specific profile. + * @param handle_value: handle value to set. + * @retval true--set success. + * flase--set failed. + */ +bool dfu_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool dfu_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief add Dfu client to application. + * @param appCB: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID dfu_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num); + +/** + * @brief start the service discovery + * + * contains the service/characteristic/cccd declaration + * @param[in] conn_id: the connection id + * @return the operatino result + */ +bool dfu_client_start_discovery(uint8_t conn_id); + +/** + * @brief handle the adv pkt + * @param[in] p_le_scan_info: the adv pkt pointer + * @return none + */ +void dfu_client_handle_adv_pkt(T_LE_SCAN_INFO *p_le_scan_info); + +/** + * @brief Get the conn id when actively connect. + * @param[in] conn_id: the connection id + * @return none + */ +void dfu_client_handle_connecting(uint8_t conn_id); + +/** + * @brief handle the establish of connection + * + * discovery the dfu server etc. + * @param[in] conn_id: the connection id + * @return none + */ +void dfu_client_handle_connect(uint8_t conn_id); + +/** + * @brief handle the disconnetion + * + * to release the resource and notify the dfu state + * @param[in] conn_id: the connection id + * @return the operatino result + */ +void dfu_client_disconnect_cb(uint8_t conn_id); + +void dfu_client_connect_device(T_LE_SCAN_INFO *p_le_scan_info); + +/** @} */ +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DFU_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client/ota_client.h b/component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client/ota_client.h new file mode 100644 index 00000000..a7767833 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client/ota_client.h @@ -0,0 +1,261 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ota_client.h + * @brief Head file for using ota service Client. + * @details Data structs and external functions declaration. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _OTA_CLIENT_H_ +#define _OTA_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Add Includes here */ +#include "profile_client.h" + +#define GATT_UUID_OTA_SERVICE 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0xFF, 0xD0, 0x00, 0x00 + +#define GATT_UUID_OTA_PROFILE + +#define GATT_UUID_CHAR_OTA 0xFFD1 //1, write +#define GATT_UUID_CHAR_MAC 0xFFD2 //2 +#define GATT_UUID_CHAR_PATCH 0xFFD3 //3 +#define GATT_UUID_CHAR_APP_VERSION 0xFFD4 //4 +#define GATT_UUID_CHAR_PATCH_EXTENSION 0xFFD5 //5 +#define GATT_UUID_CHAR_TEST_MODE 0xFFD8 //6, write + +#define GATT_UUID_CHAR_DEVICE_INFO 0xFFF1 //7 +#define GATT_UUID_CHAR_IMAGE_COUNT_TO_UPDATE 0xFFF2 //8, write +#define GATT_UUID_CHAR_IMAGE_VERSION 0xFFE0 + + +#define OTA_WRITE_OTA_CMD_CHAR_VAL 0x01 +#define OTA_WRITE_TEST_MODE_CHAR_VAL 0x02 +#define OTA_WRITE_OTA_IMG_COUNTER_CHAR_VAL 0x03 + +/** @defgroup DFU_Client + * @{ + */ +/** @brief Define links number. range: 0-4 */ +#define OTA_MAX_LINKS 4 + +typedef struct _T_OTA_DEVICE_INFO +{ + uint8_t ictype; + uint8_t ota_version; + uint8_t secure_version; + + union + { + uint8_t value; + struct + { + uint8_t buffercheck: 1; // 1:support, 0:don't support + uint8_t aesflg: 1; // 1:aes encrypt when ota, 0:not encrypt + uint8_t aesmode: 1; // 1:all data is encrypted, 0:only encrypt 16byte + //uint8_t verify_algo: 1; // 1:sha256, 0:crc + uint8_t copy_img: 1; //1:support ,0:don't support + uint8_t multi_img: 1; //1:support(update multi img at a time) ,0:don't support(one img at a time) + uint8_t rsvd: 3; + }; + } mode; + + uint16_t maxbuffersize; + uint16_t res; + + uint32_t img_indicator; +} T_OTA_DEVICE_INFO, *P_OTA_DEVICE_INFO; + +/** @defgroup DFU_Client_Exported_Types Exported Types + * @{ + */ +/** @brief OTA client handle type*/ +typedef enum +{ + HDL_OTA_SRV_START, //!< start handle of battery service + HDL_OTA_SRV_END, //!< end handle of battery service + HDL_OTA_CMD, //!< OTA CMD characteristic value handle + HDL_OTA_DEVICE_MAC, + HDL_OTA_PATCH_VER, + HDL_OTA_APP_VER, + HDL_OTA_PATCH_EXT_VER, + HDL_OTA_TEST_MODE, //!< OTA test mode characteristic handle + HDL_OTA_DEVICE_INFO, + HDL_OTA_IMG_COUNTER, //!
© COPYRIGHT 2016 Realtek Semiconductor Corporation
+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#include +#include "app_task.h" +#include "app_msg.h" +#include "gap.h" +#include + + +extern void app_handle_io_msg(T_IO_MSG io_msg); +void app_main_task(void *p_param); + +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + + +/**< Handles of app task and queues. */ +void *app_task_handle; +void *evt_queue_handle; +void *io_queue_handle; + +/** + * @brief Create application task. + * @retval none + */ +void app_task_init() +{ + + /* Create APP Task. */ + os_task_create(&app_task_handle, "app", app_main_task, 0, 512 * 4, 1); +} + +/** + * @brief application task. + * @param pvParameters + * @retval none + */ +void app_main_task(void *p_param) +{ + char event; + + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(unsigned char)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + data_uart_init(evt_queue_handle, io_queue_handle); + user_cmd_init(&user_cmd_if, "ble_auto_test"); + + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/app_task.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/app_task.h new file mode 100644 index 00000000..0507cd99 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/app_task.h @@ -0,0 +1,32 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file application.h + * @brief Application task related interfaces. + * @details + * @author ranhui + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion **/ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Add Includes here **/ + +/** Add all public functions here **/ +extern void app_task_init(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/application_ble_auto_test.ewp b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/application_ble_auto_test.ewp new file mode 100644 index 00000000..5b909194 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/application_ble_auto_test.ewp @@ -0,0 +1,3066 @@ + + + 3 + + Debug + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\prebuild.vbs" "$PROJ_DIR$" + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\postbuild_is.vbs" "$TARGET_DIR$" "$PROJ_DIR$" "$CONFIG_NAME$" "$TOOLKIT_DIR$" + + + + ILINK + 0 + + 21 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + @ERAM + + Debug + + ICCARM + + 34 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @SRAM + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\flash_api.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\flash_api_ext.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\flash_fatfs.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_flash.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_spic.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\power_mode_api.c + + + Debug + + ICCARM + + 34 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bluetooth + + board + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\bt_fwconfig.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\cycle_queue.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\data_uart\data_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\ftl.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\hci_board.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\hci_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\os\freertos_v10.0.1_IAR\osif_freertos.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\platform_utils.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\rtk_coex.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\trace_uart.c + + + + common + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\ancs_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\bas.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\bas_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\bt_uart_bridge.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\dis.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\gaps_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\hci_adapter.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\hci_process.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids_kb.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids_rmc.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\simple_ble_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\simple_ble_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\trace_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\cmd\user_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\mcu\module\data_uart_cmd\user_cmd_parse.c + + + + example + + ble_auto_test + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\app_flags.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\app_task.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\ble_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\ble_auto_test_application.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\ble_auto_test_application.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\ble_auto_test_case.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\ble_auto_test_case.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\link_mgr.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\link_mgr.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\privacy_mgnt.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\privacy_mgnt.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_0001.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_0001.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_100.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_100.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1000.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1000.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1100.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1100.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1100_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1100_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1200.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1200.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1200_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_1200_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_200.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_200.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_200_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_200_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_300.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_300.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_300_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_300_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_310.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_310.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_310_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_310_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_400.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_400.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_400_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_400_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_500.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_500.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_500_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_500_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_600.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_600.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_600_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_600_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_700.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_700.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_800.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_800.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_800_sut.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_800_sut.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_900.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_900.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_common.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\tc_common.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_pxpext_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_pxpext_client.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_pxpext_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_pxpext_service.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_tp_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_tp_client.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_tp_config.h + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_tp_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\ble_auto_test\vendor_tp_service.h + + + + ble_peripheral + + Debug + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\ble_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\peripheral_app.c + + + + bt_beacon + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_beacon\bt_beacon_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_beacon\bt_beacon_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_beacon\bt_beacon_app_task.c + + + + bt_config + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_peripheral_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_wifi.c + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\bt_example_entry.c + + + + + cmsis + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram_s\app_start.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\utilities\source\ram\libc_wrap.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram\mpu_config.c + + + + console + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_bt.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_isp.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_lwip.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_media.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_mp.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_mp_ext2.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\app\shell\cmd_shell.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\app\shell\ram_s\consol_cmds.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\low_level_io.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\rtl_console.c + + + + lib + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\lib\btgap.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\lib\lib\hal_pmc.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_dct.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_eap.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_googlenest.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_http.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_p2p.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_soc_is.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_websocket.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_wlan.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_wps.a + + + + network + + api + + wifi + + rtw_wpa_supplicant + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\src\crypto\tls_polarssl.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_eap_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_p2p_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + + + + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + + + + app + + mqtt + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTClient\MQTTClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTConnectClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTConnectServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTDeserializePublish.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTFormat.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTClient\MQTTFreertos.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTPacket.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSerializePublish.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSubscribeClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSubscribeServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTUnsubscribeClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTUnsubscribeServer.c + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\platform\ota_8710c.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client_ext.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + + + + coap + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_ameba_port.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_builder.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_header_check.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_parser.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_protocol.c + + + + googlenest + + $PROJ_DIR$\..\..\..\component\common\application\google\google_tls.c + + + + http + + $PROJ_DIR$\..\..\..\component\common\network\httpc\httpc_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\httpd\httpd_tls.c + + + + lwip + + api + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\api_lib.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\api_msg.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\err.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netdb.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netifapi.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\tcpip.c + + + + core + + ipv4 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\autoip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\dhcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\etharp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\icmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\igmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4_frag.c + + + + ipv6 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\dhcp6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ethip6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\icmp6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\inet6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ip6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ip6_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ip6_frag.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\mld6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\nd6.c + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\def.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\dns.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\inet_chksum.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\init.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\mem.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\memp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\netif.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\pbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\raw.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\stats.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\sys.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp_in.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp_out.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\timeouts.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\udp.c + + + + netif + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\netif\ethernet.c + + + + port + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\port\realtek\freertos\ethernetif.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\port\realtek\freertos\sys_arch.c + + + + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + + + $PROJ_DIR$\..\..\..\component\common\network\sntp\sntp.c + + + + mdns + + $PROJ_DIR$\..\..\..\component\common\network\mDNS\mDNSPlatform.c + + + + ssl + + mbedtls + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\aesni.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\blowfish.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\camellia.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ccm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\certs.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cipher.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cipher_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cmac.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\debug.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\error.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\gcm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\havege.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\memory_buffer_alloc.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\net_sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\padlock.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs11.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs12.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkparse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\platform.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ripemd160.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cache.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_ciphersuites.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cli.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cookie.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_srv.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_ticket.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\threading.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\timing.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\version.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\version_features.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_create.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_crl.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509write_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509write_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\xtea.c + + + + ssl_ram_map + + $PROJ_DIR$\..\..\..\component\common\network\ssl\ssl_ram_map\rom\rom_ssl_ram_map.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\ssl_func_stubs\ssl_func_stubs.c + + + + + websocket + + $PROJ_DIR$\..\..\..\component\common\network\websocket\wsclient_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\websocket\wsserver_tls.c + + + + + os + + freertos + + portable + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\portable\MemMang\heap_5.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\portable\IAR\ARM_RTL8710C\port.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\portable\IAR\ARM_RTL8710C\portasm.s + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\croutine.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\event_groups.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\list.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\queue.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\stream_buffer.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\tasks.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\timers.c + + + + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\device_lock.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_cb.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_service.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_service.c + + + + peripheral + + api + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\crypto_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\dma_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\efuse_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\gpio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\gpio_irq_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\i2c_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pinmap.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pinmap_common.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\port_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pwmout_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\serial_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\spdio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\spi_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\sys_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\timer_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\us_ticker.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\us_ticker_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\wait_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\wdt_api.c + + + + hal + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_s\hal_efuse.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_gdma.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_i2c.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_misc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_s\hal_pinmux_nsc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_sdio_dev.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_uart.c + + + + + user + + $PROJ_DIR$\..\src\main.c + + + + utilities + + example + + $PROJ_DIR$\..\..\..\component\common\example\amazon_awsiot\example_amazon_awsiot.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\example\bcast\example_bcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\cJSON\example_cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\example\coap\example_coap.c + + + $PROJ_DIR$\..\..\..\component\common\example\dct\example_dct.c + + + $PROJ_DIR$\..\..\..\component\common\example\eap\example_eap.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + + + $PROJ_DIR$\..\..\..\component\common\example\get_beacon_frame\example_get_beacon_frame.c + + + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\example\high_load_memory_use\example_high_load_memory_use.c + + + $PROJ_DIR$\..\..\..\component\common\example\http_client\example_http_client.c + + + $PROJ_DIR$\..\..\..\component\common\example\http_download\example_http_download.c + + + $PROJ_DIR$\..\..\..\component\common\example\httpc\example_httpc.c + + + $PROJ_DIR$\..\..\..\component\common\example\httpd\example_httpd.c + + + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\mqtt\example_mqtt.c + + + $PROJ_DIR$\..\..\..\component\common\example\nonblock_connect\example_nonblock_connect.c + + + $PROJ_DIR$\..\..\..\component\common\example\ota_http\example_ota_http.c + + + $PROJ_DIR$\..\..\..\component\common\example\rarp\example_rarp.c + + + $PROJ_DIR$\..\..\..\component\common\example\secure_boot\example_secure_boot.c + + + $PROJ_DIR$\..\..\..\component\common\example\sntp_showtime\example_sntp_showtime.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_select\example_socket_select.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_tcp_trx\example_socket_tcp_trx_1.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_tcp_trx\example_socket_tcp_trx_2.c + + + $PROJ_DIR$\..\..\..\component\common\example\ssl_download\example_ssl_download.c + + + $PROJ_DIR$\..\..\..\component\common\example\ssl_server\example_ssl_server.c + + + $PROJ_DIR$\..\..\..\component\common\example\tcp_keepalive\example_tcp_keepalive.c + + + $PROJ_DIR$\..\..\..\component\common\example\uart_atcmd\example_uart_atcmd.c + + + $PROJ_DIR$\..\..\..\component\common\example\wifi_mac_monitor\example_wifi_mac_monitor.c + + + $PROJ_DIR$\..\..\..\component\common\example\wifi_roaming\example_wifi_roaming.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_scenario\example_wlan_scenario.c + + + $PROJ_DIR$\..\..\..\component\common\example\websocket_client\example_wsclient.c + + + $PROJ_DIR$\..\..\..\component\common\example\xml\example_xml.c + + + + FatFs + + Debug + + + disk_if + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\sdcard.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\sdio\realtek\sdio_host\src\sdio_combine.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\usbdisk.c + + + + fatfs_ext + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\fatfs_ext\src\ff_driver.c + + + + r0.10c + + option + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\option\ccsbcs.c + + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\diskio.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\ff.c + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\http_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\xml.c + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_app_main.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_app_main.c new file mode 100644 index 00000000..d6b40340 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_app_main.c @@ -0,0 +1,336 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief This is the entry of user code which the main function resides in. + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + * @attention + *

© COPYRIGHT 2016 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#include "os_sched.h" +#include "app_task.h" +#include "trace_app.h" +#include "gap.h" +#include "gap_bond_le.h" +#include "gap_scan.h" +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +#include "gap_msg.h" +#include "ble_auto_test_application.h" +#include "user_cmd.h" +#include "data_uart.h" +#if F_BT_LE_4_1_CBC_SUPPORT +#include "gap_credit_based_conn.h" +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include "gap_adv.h" +#endif + +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#include "vendor_tp_service.h" +#include "vendor_pxpext_service.h" +#endif + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include "vendor_pxpext_client.h" +#include "vendor_tp_client.h" +#endif +#if F_BT_LE_PRIVACY_SUPPORT +#include "privacy_mgnt.h" +#include "gap_privacy.h" +#endif + +#if F_BT_DLPS_EN +#include "dlps.h" +#include +#endif +#include "trace_uart.h" + +/**< Default scan interval (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_INTERVAL 0x10 +/**< Default scan window (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_WINDOW 0x10 + +/**< Client ID for Simple BLE Client module, get from lower layer when add Simple BLE Client module. */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_CLIENT_ID SimBleClientID; +T_CLIENT_ID GapClientID; +T_CLIENT_ID vendor_tp_client_id; +T_CLIENT_ID vendor_pxp_client_id; +#endif + +uint8_t gSimpleProfileServiceId; +uint8_t g_vendor_pxpext_service_id; +uint8_t simple_srv_id; +uint8_t g_hid_keyboard_service_id; + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +// What is the advertising interval when device is discoverable (units of 625us, 160=100ms) +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 //0x20 /* 20ms */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 //0x30 /* 30ms */ +#define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL + +// Minimum connection interval (units of 1.25ms, 80=100ms) if automatic parameter update request is enabled +#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 80 +// Maximum connection interval (units of 1.25ms, 800=1000ms) if automatic parameter update request is enabled +#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 800 +// Slave latency to use if automatic parameter update request is enabled +#define DEFAULT_DESIRED_SLAVE_LATENCY 0 +// Supervision timeout value (units of 10ms, 1000=10s) if automatic parameter update request is enabled +#define DEFAULT_DESIRED_CONN_TIMEOUT 1000 + + + +// GAP - SCAN RSP data (max size = 31 bytes) +static uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc1, 0x03, /* Keyboard */ +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +// best kept short to conserve power while advertisting) +static uint8_t adv_data[] = +{ + /* Core spec. Vol. 3, Part C, Chapter 18 */ + /* Flags */ + 0x02, /* length */ + 0x01, 0x05, /* type="flags", data="bit 1: LE General Discoverable Mode" */ + /* Service */ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc1, 0x03, /* Keyboard */ + 0x0D, /* length */ + 0x09, /* type="Complete local name" */ + 'K', 'e', 'y', 'b', 'o', 'a', 'r', 'd', '_', 'Q', 'W', 'E' /* Keyboard Name */ +}; +#endif + +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); +} +/** + * @brief Initiate GAP parameters, these params will affect the local device's behavior. + * @retval none. + */ +void app_le_gap_init() +{ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "Bee_GapTest"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + +#if F_BT_LE_GAP_SCAN_SUPPORT + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; +#endif + + uint8_t pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t oob_enable = false; + uint32_t passkey = 0; /* passkey "000000"*/ + uint8_t fix_passkey_enable = false; + uint8_t secReqEnable = false; + uint16_t secReqRequirement = GAP_AUTHEN_BIT_BONDING_FLAG; +#if F_BT_LE_PRIVACY_SUPPORT + uint16_t privacy_timeout = 0x384; +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + //advertising parameters + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advDirectType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t advIntMax = DEFAULT_ADVERTISING_INTERVAL_MIN; +#endif + + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(uint8_t), &pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(uint16_t), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(uint8_t), &io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + +#if F_BT_LE_GAP_SCAN_SUPPORT + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); +#endif + + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(uint32_t), &passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(uint8_t), &fix_passkey_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &secReqRequirement); +#if F_BT_LE_PRIVACY_SUPPORT + le_privacy_set_param(GAP_PARAM_PRIVACY_TIMEOUT, sizeof(uint16_t), &privacy_timeout); +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + //Set advertising parameters + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectType), &advDirectType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); +#endif +#if F_BT_LE_4_1_CBC_SUPPORT + le_cbc_init(1); + le_cbc_register_app_cb(app_credit_based_conn_callback); +#endif +} + +/** + * @brief Initiate Profile. + * @retval none. + */ +void app_le_profile_init(void) +{ +#if F_BT_LE_GATT_SERVER_SUPPORT + server_init(3); + gSimpleProfileServiceId = vendor_tp_service_add((void *)app_profile_callback); + g_vendor_pxpext_service_id = vendor_pxpext_service_add((void *)app_profile_callback); + + server_register_app_cb(app_profile_callback); +#endif + + /* Register app callback--App_CentralRoleCallback to handle events from GAP Central Role. */ + le_register_app_cb(app_gap_callback); + +#if F_BT_LE_GATT_CLIENT_SUPPORT + client_init(3); + /* Add Simple BLE Client Module, app_simp_client_callback used to handle events from this Module. */ + GapClientID = gaps_add_client(app_gap_client_callback, 4); + vendor_tp_client_id = tp_client_add(test_client_callback); + vendor_pxp_client_id = vendor_pxpext_client_add(test_client_callback); + /* Register this callcack--app_general_client_callback to handle events from Profile Client layer. */ + client_register_general_client_cb(app_general_client_callback); +#endif + +#if F_BT_LE_PRIVACY_SUPPORT + le_privacy_register_cb(App_PrivacyCallback); +#endif +} + +/** + * @brief Board_Init() contains the initialization of pinmux settings and pad settings. + * + * NOTE: All the pinmux settings and pad settings shall be initiated in this function. + * But if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * + * @retval none. + */ +void board_init() +{ + +} + +/** + * @brief Driver_Init() contains the initialization of peripherals. + * @retval none. + */ +void driver_init() +{ + /* Use Data UART to handle user commands. */ + +} + +/** + * @brief PwrMgr_Init() contains the setting about power mode. + * @retval none. + */ +void pwrmgr_init() +{ +#if F_BT_DLPS_EN + data_uart_dlps_init(); + lps_mode_set(LPM_DLPS_MODE); + lps_mode_pause(); +#endif +} + +/** + * @brief Task_Init() contains the initialization of all the tasks. + * + * NOTE: There are four tasks are initiated. + * Lowerstack task and upperstack task are used by bluetooth stack. + * Application task is task which user application code resides in. + * Emergency task is reserved. + * + * @retval none. + */ +void task_init() +{ + app_task_init(); +} + +/** + * @brief main() is the entry of user code. + * @retval none. + */ +int ble_app_main(void) +{ + bt_trace_init(); + bt_stack_config_init(); + bte_init(); + board_init(); + driver_init(); + le_gap_init(APP_MAX_LINKS); + app_le_gap_init(); + app_le_profile_init(); + pwrmgr_init(); + task_init(); + + return 0; +} diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_application.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_application.c new file mode 100644 index 00000000..f21a86a7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_application.c @@ -0,0 +1,3426 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include +#include "gap_scan.h" +#include "gap.h" +#include "gap_adv.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" +#include "link_mgr.h" +#include "user_cmd.h" +#include "user_cmd_parse.h" + +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#include "vendor_tp_service.h" +#endif + +#include + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include "gap_adv.h" +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +#include "privacy_mgnt.h" +#endif + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include +#include +#include +#endif + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +#include "gap_credit_based_conn.h" +#endif + +bool V3NotifyEnable = false; +/* Client ID of Simple BLE Client Module, generated when add this module in main.c. Can't be modified by user. */ +/* Device state maintained in application. */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0, 0}; +extern uint8_t simple_srv_id; +#if F_BT_LE_GATT_CLIENT_SUPPORT +extern T_CLIENT_ID GapClientID; +extern T_CLIENT_ID vendor_tp_client_id; +extern T_CLIENT_ID vendor_pxp_client_id; +#endif +// GAP - SCAN RSP data (max size = 31 bytes) +const uint8_t scan_rsp_data[] = +{ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc2, 0x03, /* Mouse */ +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +// best kept short to conserve power while advertisting) +const uint8_t adv_data[] = +{ + 0x02, /* length */ + //XXXXMJMJ 0x01, 0x06, /* type="flags", data="bit 1: LE General Discoverable Mode", BR/EDR not supp. */ + 0x01, 0x05, /* type="flags", data="bit 1: LE General Discoverable Mode" */ + /* Service */ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc2, 0x03, /* Mouse */ + 0x0C, /* length */ + 0x09, /* type="Complete local name" */ +// 0x42, 0x65, 0x65, 0x5F, 0x6D, 0x6F, 0x75, 0x73, 0x65 /* Bee_perip */ + 'B', 'e', 'e', '_', 'G', 'a', 'p', 'T', 'e', 's', 't' /* Bee_perip */ +}; + + +void app_handle_gap_msg(T_IO_MSG *pBeeIoMsg); + +/** +* @brief All the application events are pre-handled in this function. +* +* All the IO MSGs are sent to this function. +* Then the event handling function shall be called according to the MSG type. +* +* @param io_msg The T_IO_MSG from peripherals or BT stack state machine. +* @return void +*/ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + uint8_t rx_char; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + app_handle_gap_msg(&io_msg); + break; + case IO_MSG_TYPE_UART: + /* We handle user command informations from Data UART in this branch. */ + rx_char = (uint8_t)io_msg.subtype; + user_cmd_collect(&user_cmd_if, &rx_char, sizeof(rx_char), user_cmd_table); + break; + default: + break; + } +} + +/** + * @brief handle messages indicate that GAP device state has changed. + * @param new_state: GAP state. + * @retval none + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO4("app_handle_dev_state_evt: init state %d scan state %d adv state %d conn state %d", + new_state.gap_init_state, + new_state.gap_scan_state, new_state.gap_adv_state, new_state.gap_conn_state); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + uint8_t bt_addr[6]; + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + + /*stack ready*/ + } + } + + if (gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + +#if TC_100_SUPPORT + if (app_get_cur_test_case() == TC_0100_SCAN_PERFORMANCE) + { + tc_0100_scan_state_change_to_idle(); + } + else if (app_get_cur_test_case() == TC_0101_SCAN_STRESS_ENABLE_DISABLE) + { + tc_0101_scan_stress_enable_disable_state_change_to_idle(); + } +#endif + +#if TC_1200_SUPPORT + if (app_get_cur_test_case() == TC_1200_MULTI_LINK_4_MASTER) + { + tc_1200_scan_state_change_to_idle(); + } +#endif + +#if TC_1201_SUPPORT + if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { + tc_1201_scan_state_change_to_idle(); + } +#endif +#if TC_1202_SUPPORT + if (app_get_cur_test_case() == TC_1202_MULTI_LINK_4_MASTER) + { + tc_1202_scan_state_change_to_idle(); + } +#endif +#if TC_1203_SUPPORT + if (app_get_cur_test_case() == TC_1203_MULTI_LINK_4_MASTER) + { + tc_1203_scan_state_change_to_idle(); + } +#endif +#if TC_1204_SUPPORT + if (app_get_cur_test_case() == TC_1204_MULTI_LINK_4_MASTER) + { + tc_1204_scan_state_change_to_idle(); + } +#endif +#if TC_1205_SUPPORT + if (app_get_cur_test_case() == TC_1205_MULTI_LINK_4_MASTER) + { + tc_1205_scan_state_change_to_idle(); + } +#endif +#if TC_1206_SUPPORT + if (app_get_cur_test_case() == TC_1206_MULTI_LINK_4_MASTER) + { + tc_1206_scan_state_change_to_idle(); + } +#endif +#if TC_1207_SUPPORT + if (app_get_cur_test_case() == TC_1207_MULTI_LINK_4_MASTER) + { + tc_1207_scan_state_change_to_idle(); + } +#endif + + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + +#if TC_100_SUPPORT + + if (app_get_cur_test_case() == TC_0100_SCAN_PERFORMANCE) + { + tc_0100_scan_state_change_to_scaning(); + } + else if (app_get_cur_test_case() == TC_0101_SCAN_STRESS_ENABLE_DISABLE) + { + tc_0101_scan_stress_enable_disable_state_change_to_scaning(); + } +#endif + } + } + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (app_get_cur_test_case() == TC_0001_ADV_PERFORMANCE) + { +#if TC_0001_SUPPORT + tc_0001_adv_adv_state_change_to_idle(); +#endif + } + else if (app_get_cur_test_case() == TC_0002_ADV_STRESS_START_STOP) + { +#if TC_0002_SUPPORT + tc_0002_adv_start_stop_adv_state_change_to_idle(); +#endif + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + if (app_get_cur_test_case() == TC_0001_ADV_PERFORMANCE) + { +#if TC_0001_SUPPORT + tc_0001_adv_adv_state_change_to_advertising(); +#endif + } + else if (app_get_cur_test_case() == TC_0002_ADV_STRESS_START_STOP) + { +#if TC_0002_SUPPORT + tc_0002_adv_start_stop_adv_state_change_to_advertising(); +#endif + } + + } + } +#endif + + if (gap_dev_state.gap_conn_state != new_state.gap_conn_state) + { + /* + APP_PRINT_INFO2("Conn state: %d -> %d", + gap_dev_state.gap_conn_state, + new_state.gap_conn_state); + */ + } + +#if TC_900_SUPPORT +#if F_BT_LE_PRIVACY_SUPPORT + if ((app_get_cur_test_case() == TC_0900_PRIVACY_TEST_SLAVE) + || (app_get_cur_test_case() == TC_0901_PRIVACY_TEST_MASTER)) + { + if ((new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + && (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + && (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + && (new_state.gap_conn_state == GAP_CONN_DEV_STATE_IDLE)) + { + privacy_handle_pending_resolving_list(); + } + } +#endif +#endif + + gap_dev_state = new_state; +} + +/** + * @brief handle messages indicate that GAP connection state has changed. + * @param conn_id: connection ID. + * @param new_state: new connection state. + * @param disc_cause: when new_state=GAP_CONN_STATE_DISCONNECTED, this value is valid. + * @retval none + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + APP_PRINT_INFO3("app_handle_conn_state_evt: conn_id %d oldState %d new_state %d", + conn_id, app_link_table[conn_id].conn_state, new_state); + + app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + /*device is disconnected.*/ + case GAP_CONN_STATE_DISCONNECTED: + { + APP_PRINT_INFO2("app_handle_conn_state_evt: conn_id %d disc_cause 0x%04x", + conn_id, disc_cause); + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { + + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { +#if TC_206_SUPPORT + tc_206_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { +#if TC_207_SUPPORT + tc_207_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { +#if TC_208_SUPPORT + tc_208_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0300_ADV_ONLY) + { +#if TC_300_SUPPORT + tc_300_adv_only_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0301_ADV_DISC) + { +#if TC_301_SUPPORT + tc_301_adv_disc_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0400_CONN_PARAM_UPDATE_SLAVE) + { +#if TC_400_SUPPORT + tc_400_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0401_CONN_PARAM_UPDATE_SLAVE_01) + { +#if TC_401_SUPPORT + tc_401_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0500_SLAVE_AUTO_ADV) + { +#if TC_500_SUPPORT + tc_500_salve_auto_adv_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ) + { +#if TC_501_SUPPORT + tc_501_salve_auto_adv_with_sec_req_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV) + { +#if TC_502_SUPPORT + tc_502_salve_auto_adv_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUPPORT + tc_600_iop_android_legacl_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUPPORT + tc_601_iop_android_sc_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUPPORT + tc_700_stable_notification_tx_01_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUPPORT + tc_800_iop_android_legacl_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUPPORT + tc_801_iop_android_sc_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0900_PRIVACY_TEST_SLAVE) + { + le_adv_start(); + } + else if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUPPORT + tc_1100_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUPPORT + tc_1101_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUPPORT + tc_1102_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1200_MULTI_LINK_4_MASTER) + { +#if TC_1200_SUPPORT + tc_1200_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1201_SUPPORT + tc_1201_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1202_MULTI_LINK_4_MASTER) + { +#if TC_1202_SUPPORT + tc_1202_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1203_SUPPORT + tc_1203_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1204_SUPPORT + tc_1204_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1205_SUPPORT + tc_1205_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1206_SUPPORT + tc_1206_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1207_SUPPORT + tc_1207_link_disconnected(conn_id, disc_cause); +#endif + } + else + { + data_uart_print("Disconnect conn_id %d\r\n", conn_id); + } +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { +#if TC_200_SUT_SUPPORT + tc_200_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { +#if TC_206_SUT_SUPPORT + tc_206_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { +#if TC_207_SUT_SUPPORT + tc_207_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { +#if TC_208_SUT_SUPPORT + tc_208_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0300_ADV_ONLY) + { +#if TC_300_SUT_SUPPORT + tc_300_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0301_ADV_DISC) + { +#if TC_301_SUT_SUPPORT + tc_301_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0400_CONN_PARAM_UPDATE_SLAVE) + { +#if TC_400_SUT_SUPPORT + tc_400_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0401_CONN_PARAM_UPDATE_SLAVE_01) + { +#if TC_401_SUT_SUPPORT + tc_401_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0500_SLAVE_AUTO_ADV) + { +#if TC_500_SUT_SUPPORT + tc_500_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ) + { +#if TC_501_SUT_SUPPORT + tc_501_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV) + { +#if TC_502_SUT_SUPPORT + +#endif + } + else if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUT_SUPPORT + tc_600_sut_iop_android_legacl_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUT_SUPPORT + tc_601_sut_iop_android_sc_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUPPORT + +#endif + } +#if F_BT_LE_5_0_SUPPORT + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUT_SUPPORT + tc_800_sut_iop_android_legacl_pair_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUT_SUPPORT + tc_801_sut_iop_android_sc_pair_link_disconnected(conn_id, disc_cause); +#endif + } +#endif + else if (app_get_cur_test_case() == TC_0900_PRIVACY_TEST_SLAVE) + { + + } + else if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUT_SUPPORT + tc_1100_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUT_SUPPORT + tc_1101_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUT_SUPPORT + tc_1102_sut_link_disconnected(conn_id, disc_cause); +#endif + } + else + { + data_uart_print("Disconnect conn_id = %d\r\n", conn_id); + } + } + + + if (disc_cause == (HCI_ERR | HCI_ERR_CONN_TIMEOUT)) + { + APP_PRINT_INFO1("Test_HandleBtConnStateChangeEvt: connection lost", conn_id); + } + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + /*device is disconnected.*/ + case GAP_CONN_STATE_CONNECTING: + { + + } + break; + + /*device is connected*/ + case GAP_CONN_STATE_CONNECTED: + { + uint16_t mtu_size; + le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, &mtu_size, conn_id); + data_uart_print("Connected conn_id = %d, mtu size = %d\r\n", conn_id, mtu_size); + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { +#if TC_200_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); + tc_200_tp_notification_tx_init_default_param(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { +#if TC_206_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); + //tc_206_tp_notification_tx_init_default_param(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { +#if TC_207_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { +#if TC_208_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0300_ADV_ONLY) + { +#if TC_300_SUPPORT + tc_300_adv_only_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0301_ADV_DISC) + { +#if TC_301_SUPPORT + tc_301_adv_disc_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0400_CONN_PARAM_UPDATE_SLAVE) + { +#if TC_400_SUPPORT + tc_400_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0401_CONN_PARAM_UPDATE_SLAVE_01) + { +#if TC_401_SUPPORT + tc_401_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUPPORT + tc_700_stable_notification_tx_01_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0500_SLAVE_AUTO_ADV) + { +#if TC_500_SUPPORT + tc_500_salve_auto_adv_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ) + { +#if TC_501_SUPPORT + tc_501_salve_auto_adv_with_sec_req_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV) + { +#if TC_502_SUPPORT + tc_502_salve_auto_adv_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { + +#if TC_600_SUPPORT + tc_600_iop_android_legacl_pair_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { + +#if TC_601_SUPPORT + tc_601_iop_android_sc_pair_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUPPORT + tc_800_iop_android_legacl_pair_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUPPORT + tc_801_iop_android_sc_pair_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUPPORT + tc_1100_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUPPORT + tc_1101_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1200_MULTI_LINK_4_MASTER) + { +#if TC_1200_SUPPORT + tc_1200_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { +#if TC_1201_SUPPORT + tc_1201_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1202_MULTI_LINK_4_MASTER) + { +#if TC_1202_SUPPORT + tc_1202_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1203_MULTI_LINK_4_MASTER) + { +#if TC_1203_SUPPORT + tc_1203_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1204_MULTI_LINK_4_MASTER) + { +#if TC_1204_SUPPORT + tc_1204_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1205_MULTI_LINK_4_MASTER) + { +#if TC_1205_SUPPORT + tc_1205_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1206_MULTI_LINK_4_MASTER) + { +#if TC_1206_SUPPORT + tc_1206_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1207_MULTI_LINK_4_MASTER) + { +#if TC_1207_SUPPORT + tc_1207_link_connected(conn_id); +#endif + } + else + { + data_uart_print("Conn conn_id = %d\r\n", conn_id); + } +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { +#if TC_200_SUT_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); + tc_200_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { +#if TC_206_SUT_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); + tc_206_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { +#if TC_207_SUT_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); + tc_207_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { +#if TC_208_SUT_SUPPORT + data_uart_print("connected success conn_id %d\r\n", conn_id); + tc_208_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0300_ADV_ONLY) + { +#if TC_300_SUT_SUPPORT + tc_300_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0301_ADV_DISC) + { +#if TC_301_SUT_SUPPORT + tc_301_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0400_CONN_PARAM_UPDATE_SLAVE) + { +#if TC_400_SUT_SUPPORT + tc_400_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0401_CONN_PARAM_UPDATE_SLAVE_01) + { +#if TC_401_SUT_SUPPORT + tc_401_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { + + } + else if (app_get_cur_test_case() == TC_0500_SLAVE_AUTO_ADV) + { +#if TC_500_SUT_SUPPORT + tc_500_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ) + { +#if TC_501_SUT_SUPPORT + tc_501_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV) + { +#if TC_502_SUT_SUPPORT + //tc_502_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUT_SUPPORT + tc_600_sut_iop_android_legacl_pair_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUT_SUPPORT + tc_601_sut_iop_android_sc_pair_link_connected(conn_id); +#endif + } +#if F_BT_LE_5_0_SUPPORT + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUT_SUPPORT + tc_800_sut_iop_android_legacl_pair_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUT_SUPPORT + tc_801_sut_iop_android_sc_pair_link_connected(conn_id); +#endif + } +#endif + else if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUT_SUPPORT + tc_1100_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUT_SUPPORT + tc_1101_sut_link_connected(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUT_SUPPORT + tc_1102_sut_link_connected(conn_id); +#endif + } + else + { + data_uart_print("Conn conn_id %d\r\n", conn_id); + } + } + } + break; + + /*error comes here*/ + default: + { + + } + break; + + } +} + +/** + * @brief handle messages indicate that GAP bond state has changed. + * @param conn_id: connection ID. + * @param new_state: GAP bond state. + * @param status: pairing complete status. + * @arg: 0 - success. + * @arg: other - failed. + * @retval none + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t status) +{ + APP_PRINT_INFO3("app_handle_authen_state_evt: conn_id %d, new_state %d, status 0x%x", conn_id, + new_state, status); + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(GAP_AUTHEN_STATE_STARTED)"); + + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUT_SUPPORT + tc_600_iop_android_legacl_pair_state_to_start(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUT_SUPPORT + tc_601_iop_android_sc_pair_state_to_start(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUPPORT + tc_800_iop_android_legacl_pair_state_to_start(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUPPORT + tc_801_iop_android_sc_pair_state_to_start(conn_id); +#endif + } +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUT_SUPPORT + tc_600_sut_iop_android_legacl_pair_state_to_start(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUT_SUPPORT + tc_601_sut_iop_android_sc_pair_state_to_start(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUT_SUPPORT + tc_800_sut_iop_android_legacl_pair_state_to_start(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUT_SUPPORT + tc_801_sut_iop_android_sc_pair_state_to_start(conn_id); +#endif + } + + } + } + break; + case GAP_AUTHEN_STATE_COMPLETE: + { + APP_PRINT_INFO1("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(GAP_AUTHEN_STATE_COMPLETE) status 0x%x", + status); + if (status == 0) + { + + + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { + if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUPPORT + tc_600_iop_android_legacl_pair_state_to_success(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUPPORT + tc_601_iop_android_sc_pair_state_to_success(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUPPORT + tc_800_iop_android_legacl_pair_state_to_success(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUPPORT + tc_801_iop_android_sc_pair_state_to_success(conn_id); +#endif + } + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUT_SUPPORT + tc_600_sut_iop_android_legacl_pair_state_to_success(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUT_SUPPORT + tc_601_sut_iop_android_sc_pair_state_to_success(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUT_SUPPORT + tc_800_sut_iop_android_legacl_pair_state_to_success(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUT_SUPPORT + tc_801_sut_iop_android_sc_pair_state_to_success(conn_id); +#endif + } + } + + + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair success"); + } + else + { + APP_PRINT_INFO0("GAP_MSG_LE_AUTHEN_STATE_CHANGE pair failed"); + data_uart_print("pair failed conn_id = %d\r\n", conn_id); + + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { + + if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUPPORT + tc_600_iop_android_legacl_pair_state_to_fail(conn_id, status); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUPPORT + tc_601_iop_android_sc_pair_state_to_fail(conn_id); +#endif + } + + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUPPORT + tc_800_iop_android_legacl_pair_state_to_fail(conn_id, status); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUPPORT + tc_801_iop_android_sc_pair_state_to_fail(conn_id); +#endif + } + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_0600_IOP_PAIR_LEGACL) + { +#if TC_600_SUT_SUPPORT + tc_600_sut_iop_android_legacl_pair_state_to_fail(conn_id, status); +#endif + } + else if (app_get_cur_test_case() == TC_0601_IOP_PAIR_SC) + { +#if TC_601_SUT_SUPPORT + tc_601_sut_iop_android_sc_pair_state_to_fail(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_0800_IOP_PAIR_LEGACL) + { +#if TC_800_SUT_SUPPORT + tc_800_sut_iop_android_legacl_pair_state_to_fail(conn_id, status); +#endif + } + else if (app_get_cur_test_case() == TC_0801_IOP_PAIR_SC) + { +#if TC_801_SUT_SUPPORT + tc_801_sut_iop_android_sc_pair_state_to_fail(conn_id); +#endif + } + + } + + } + } + break; + + default: + { + APP_PRINT_INFO1("GAP_MSG_LE_AUTHEN_STATE_CHANGE:(unknown newstate: %d)", new_state); + } + break; + } + +} + +/** + * @brief handle messages indicate that connection parameters has changed. + * @param conn_id: connection ID. + * @param status: change status. + * @retval none + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + if (app_get_cur_test_case() == TC_0400_CONN_PARAM_UPDATE_SLAVE) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_400_SUPPORT + tc_400_conn_param_update_evt(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_400_SUT_SUPPORT + tc_400_sut_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_0400_CONN_PARAM_UPDATE_SLAVE) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_401_SUPPORT + tc_401_conn_param_update_evt(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_401_SUT_SUPPORT + tc_401_sut_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_200_SUPPORT + tc_200_tp_notification_tx_conn_param_update_event(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_200_SUT_SUPPORT + tc_200_sut_conn_param_update_event(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_206_SUPPORT + tc_206_tp_notification_tx_conn_param_update_event(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_206_SUT_SUPPORT + tc_206_sut_conn_param_update_event(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_207_SUPPORT + tc_207_tp_rx_conn_param_update_event(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_207_SUT_SUPPORT + tc_207_sut_conn_param_update_event(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_208_SUPPORT + tc_208_tp_trx_conn_param_update_event(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_208_SUT_SUPPORT + tc_208_sut_conn_param_update_event(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUT_SUPPORT + tc_700_stable_notification_tx_conn_param_update_event(conn_id); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1102_SUPPORT + tc_1102_conn_param_update_event(conn_id); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_1102_SUT_SUPPORT + tc_1102_sut_conn_param_update_event(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1200_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1200_SUPPORT + tc_1200_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1201_SUPPORT + tc_1201_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1202_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1202_SUPPORT + tc_1202_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1203_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1203_SUPPORT + tc_1203_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1204_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1204_SUPPORT + tc_1204_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1205_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1205_SUPPORT + tc_1205_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1206_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1206_SUPPORT + tc_1206_conn_param_update_evt(conn_id); +#endif + } + } + + + } + break; + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_INFO0("GAP_MSG_LE_CONN_PARAM_UPDATE failed."); + data_uart_print("LE_CONN_PARAM_UPDATE failed\r\n"); + if (app_get_cur_test_case() == TC_1200_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1200_SUPPORT + tc_1200_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1201_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1201_SUPPORT + tc_1201_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1202_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1202_SUPPORT + tc_1202_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1203_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1203_SUPPORT + tc_1203_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1204_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1204_SUPPORT + tc_1204_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1205_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1205_SUPPORT + tc_1205_conn_param_update_evt(conn_id); +#endif + } + } + else if (app_get_cur_test_case() == TC_1206_MULTI_LINK_4_MASTER) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1206_SUPPORT + tc_1206_conn_param_update_evt(conn_id); +#endif + } + } + + } + break; + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO0("GAP_MSG_LE_CONN_PARAM_UPDATE param request pending."); + } + break; + default: + break; + } +} + +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); + if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_1102_SUPPORT + tc_1102_mtu_size_info(conn_id); +#endif + } + } +} +/** + * @brief handle messages from GAP layer. + * @param pBeeIoMsg: message from GAP layer. + * @retval none + */ +void app_handle_gap_msg(T_IO_MSG *p_io_msg) +{ + T_LE_GAP_MSG bt_msg; + uint8_t conn_id; + + memcpy(&bt_msg, &p_io_msg->u.param, sizeof(p_io_msg->u.param)); + + switch (p_io_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(bt_msg.msg_data.gap_dev_state_change.new_state, + bt_msg.msg_data.gap_dev_state_change.cause); + } + break; + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(bt_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)bt_msg.msg_data.gap_conn_state_change.new_state, + bt_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(bt_msg.msg_data.gap_conn_mtu_info.conn_id, + bt_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(bt_msg.msg_data.gap_authen_state.conn_id, + bt_msg.msg_data.gap_authen_state.new_state, + bt_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + uint8_t conn_id = bt_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + uint8_t conn_id = bt_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_DISPLAY:passkey %d", display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn id=%d value=%d\r\n", + conn_id, display_value); + } + break; + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t displayValue = 0; + uint8_t conn_id = bt_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &displayValue); + if (app_get_cur_test_case() >= TC_0801_IOP_PAIR_SC) + { + data_uart_print("GAP_MSG_LE_BOND_USER_CONFIRMATION conn id=%d value=%d\r\n", + conn_id, displayValue); + } + else + { + + APP_PRINT_INFO1("GAP_MSG_LE_BOND_USER_CONFIRMATION: %d", displayValue); + le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + } + break; + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + conn_id = bt_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO0("GAP_MSG_LE_BOND_PASSKEY_INPUT"); + if (app_get_cur_test_case() >= TC_0801_IOP_PAIR_SC) + { + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT conn id=%d\r\n", conn_id); + } + else + { + uint32_t passKey = 888888; + le_bond_passkey_input_confirm(conn_id, passKey, GAP_CFM_CAUSE_ACCEPT); + } + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + APP_PRINT_INFO0("GAP_MSG_LE_BOND_OOB_INPUT"); + uint8_t ooBData[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, ooBData); + conn_id = bt_msg.msg_data.gap_bond_oob_input.conn_id; + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(bt_msg.msg_data.gap_conn_param_update.conn_id, + bt_msg.msg_data.gap_conn_param_update.status); + } + break; + default: + APP_PRINT_ERROR1("app_handle_gap_msg unknown subtype", p_io_msg->subtype); + break; + } + +} + +static void app_parse_scan_info(T_LE_SCAN_INFO *pLeScanInfo) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < pLeScanInfo->data_len) + { + /* Length of the AD structure. */ + uint8_t length = pLeScanInfo->data[pos++]; + uint8_t type; + + if (length < 0x02 || (pos + length) > 0x1F) + { + continue; + } + + /* Copy the AD Data to buffer. */ + memcpy(buffer, pLeScanInfo->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = pLeScanInfo->data[pos]; + + //APP_PRINT_INFO2(" AD Structure Info: AD type = 0x%x, AD Data Length = %d", type, length -1); + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = pLeScanInfo->data[pos + 1]; + APP_PRINT_INFO1(" AD Data: Flags = 0x%x", flags); + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *pUUID = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *pUUID++); + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *pUUID = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO2(" AD Data: UUID32 List Item %d = 0x%x", i / 4, *pUUID++); + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *pUUID = (uint32_t *)(buffer); + APP_PRINT_INFO4(" AD Data: UUID128 value: 0x%8.8x%8.8x%8.8x%8.8x", + pUUID[3], pUUID[2], pUUID[1], pUUID[0]); + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1(" AD Data: Local Name (%s)", TRACE_STRING(buffer)); + } + break; + default: + break; + } + + pos += length; + } +} + +/** + * @brief Use 16 bit uuid to filter scan information + * @param[in] uuid 16 bit UUID. + * @param[in] scan_info point to scan information data. + * @return filter result + * @retval true found success + * @retval false not found + */ +bool filter_scan_info_by_uuid(uint16_t uuid, T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *p_uuid); + if (*p_uuid == uuid) + { + return true; + } + p_uuid++; + i -= 2; + } + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} + +/** + * @brief This callback will be called when advertising or scan response data received. + * @param msg_type: type of the message sent from GAP Central Role layer. + * @param cb_data: message sent from GAP Central Role layer. + * @retval None + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_LE_CB_DATA)); + APP_PRINT_INFO1("app_gap_callback: cb_type %d", cb_type); + switch (cb_type) + { +#if F_BT_LE_GAP_SCAN_SUPPORT + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_TRACE5("GAP_MSG_LE_SCAN_INFO: bd_addr %s, bdtype=%d, event=0x%x, rssi=%d, len=%d", + TRACE_BDADDR(cb_data.p_le_scan_info->bd_addr), + cb_data.p_le_scan_info->remote_addr_type, + cb_data.p_le_scan_info->adv_type, + cb_data.p_le_scan_info->rssi, + cb_data.p_le_scan_info->data_len); + app_parse_scan_info(cb_data.p_le_scan_info); + /* User can split interested information by using the function as follow. */ + //if (filter_scan_info_by_uuid(GATT_UUID_SIMPLE_PROFILE, cb_data.p_le_scan_info)) + if (filter_scan_info_by_uuid(0xA00A, cb_data.p_le_scan_info)) + { + //APP_PRINT_INFO0("found simple profile"); + if (dev_list_count < 4) + { + link_mgr_add_device(cb_data.p_le_scan_info->bd_addr, cb_data.p_le_scan_info->remote_addr_type); + } + else + { + le_scan_stop(); + } + } + break; +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO4(" GAP_MSG_LE_CONN_UPDATE_IND: max_interval=0x%x, min_interval=0x%x, Latency=0x%x,timeOut=0x%x", + cb_data.p_le_conn_update_ind->conn_interval_max, + cb_data.p_le_conn_update_ind->conn_interval_min, + cb_data.p_le_conn_update_ind->conn_latency, + cb_data.p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1(" GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause=0x%x", + cb_data.p_le_set_host_chann_classif_rsp->cause); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2(" GAP_MSG_LE_MODIFY_WHITE_LIST: operation = 0x%x cause=0x%x", + cb_data.p_le_modify_white_list_rsp->operation, + cb_data.p_le_modify_white_list_rsp->cause); + break; +#if F_BT_LE_READ_CHANN_MAP + case GAP_MSG_LE_READ_CHANN_MAP: + APP_PRINT_INFO7(" GAP_MSG_LE_READ_CHANN_MAP: conn_id=0x%x, cause=0x%x, map[0x%x:0x%x:0x%x:0x%x:0x%x]", + cb_data.p_le_read_chann_map_rsp->conn_id, + cb_data.p_le_read_chann_map_rsp->cause, + cb_data.p_le_read_chann_map_rsp->channel_map[0], + cb_data.p_le_read_chann_map_rsp->channel_map[1], + cb_data.p_le_read_chann_map_rsp->channel_map[2], + cb_data.p_le_read_chann_map_rsp->channel_map[3], + cb_data.p_le_read_chann_map_rsp->channel_map[4]); + break; +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + case GAP_MSG_LE_ADV_READ_TX_POWER: + APP_PRINT_INFO2(" GAP_MSG_LE_ADV_READ_TX_POWER: cause=0x%x, tx=0x%x", + cb_data.p_le_adv_read_tx_power_rsp->cause, + cb_data.p_le_adv_read_tx_power_rsp->tx_power_level); + break; +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_SET_DATA_LEN: + APP_PRINT_INFO2(" GAP_MSG_LE_SET_DATA_LEN: conn_id=0x%x, cause=0x%x", + cb_data.p_le_set_data_len_rsp->conn_id, + cb_data.p_le_set_data_len_rsp->cause); + break; + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO5(" GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id=0x%x MaxTxOctets=0x%x MaxTxTime=0x%x MaxRxOctets=0x%x MaxRxTime=0x%x", + cb_data.p_le_data_len_change_info->conn_id, + cb_data.p_le_data_len_change_info->max_tx_octets, + cb_data.p_le_data_len_change_info->max_tx_time, + cb_data.p_le_data_len_change_info->max_rx_octets, + cb_data.p_le_data_len_change_info->max_rx_time); + data_uart_print("LE data length: con id %d, tx %d octets, %d ms - rx %d octets, %d ms\r\n", + cb_data.p_le_data_len_change_info->conn_id, + cb_data.p_le_data_len_change_info->max_tx_octets, + cb_data.p_le_data_len_change_info->max_tx_time, + cb_data.p_le_data_len_change_info->max_rx_octets, + cb_data.p_le_data_len_change_info->max_rx_time); + break; +#endif + case GAP_MSG_LE_SET_RAND_ADDR: + APP_PRINT_INFO1(" GAP_MSG_LE_SET_RAND_ADDR: cause=0x%x", + cb_data.p_le_set_rand_addr_rsp->cause); + break; + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3(" GAP_MSG_LE_READ_RSSI:conn_id=0x%x cause=0x%x rssi=%01d", + cb_data.p_le_read_rssi_rsp->conn_id, + cb_data.p_le_read_rssi_rsp->cause, + cb_data.p_le_read_rssi_rsp->rssi); + break; +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1(" GAP_MSG_LE_ADV_UPDATE_PARAM:cause=0x%x", + cb_data.p_le_adv_update_param_rsp->cause); + break; +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1(" GAP_MSG_LE_DISABLE_SLAVE_LATENCY:cause=0x%x", + cb_data.p_le_disable_slave_latency_rsp->cause); + break; +#endif + case GAP_MSG_LE_CREATE_CONN_IND: + APP_PRINT_INFO0(" GAP_MSG_LE_CREATE_CONN_IND"); + result = APP_RESULT_ACCEPT; + break; +#endif +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + case GAP_MSG_LE_KEYPRESS_NOTIFY: + APP_PRINT_INFO2(" GAP_MSG_LE_KEYPRESS_NOTIFY:conn %d, cause 0x%x", + cb_data.p_le_keypress_notify_rsp->conn_id, cb_data.p_le_keypress_notify_rsp->cause); + break; + + case GAP_MSG_LE_KEYPRESS_NOTIFY_INFO: + APP_PRINT_INFO2(" GAP_MSG_LE_KEYPRESS_NOTIFY_INFO:conn %d, type 0x%x", + cb_data.p_le_keypress_notify_info->conn_id, cb_data.p_le_keypress_notify_info->event_type); + break; +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4(" GAP_MSG_LE_PHY_UPDATE_INFO:conn %d, cause 0x%x, rx_phy %d, tx_phy %d", + cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->rx_phy, + cb_data.p_le_phy_update_info->tx_phy); + data_uart_print("LE phy update info: con id %d, cause = 0x%x, rx_phy = %d, tx_phy = %d\r\n", + cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->rx_phy, + cb_data.p_le_phy_update_info->tx_phy); + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_200_SUPPORT + tc_200_tp_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_206_SUPPORT + tc_206_tp_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_206_SUT_SUPPORT + tc_206_sut_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + } + else if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_207_SUPPORT + tc_207_tp_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_207_SUT_SUPPORT + tc_207_sut_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_208_SUPPORT + tc_208_tp_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_208_SUT_SUPPORT + tc_208_sut_notification_phy_update_event(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + } + else if (app_get_cur_test_case() == TC_0310_2M_LONGRANGE_1) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_310_SUPPORT + tc_310_phy_update_evt(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_310_SUT_SUPPORT + tc_310_sut_phy_update_evt(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + } + else if (app_get_cur_test_case() == TC_0311_2M_LONGRANGE_2) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_311_SUPPORT + tc_311_phy_update_evt(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_311_SUT_SUPPORT + tc_311_sut_phy_update_evt(cb_data.p_le_phy_update_info->conn_id, + cb_data.p_le_phy_update_info->cause, + cb_data.p_le_phy_update_info->tx_phy, + cb_data.p_le_phy_update_info->rx_phy); +#endif + } + } + break; +#endif +#if F_BT_LE_READ_REMOTE_FEATS + case GAP_MSG_LE_REMOTE_FEATS_INFO: + APP_PRINT_INFO3(" GAP_MSG_LE_REMOTE_FEATS_INFO:conn id %d, cause 0x%x, remote_feats %b", + cb_data.p_le_remote_feats_info->conn_id, + cb_data.p_le_remote_feats_info->cause, + TRACE_BINARY(8, cb_data.p_le_remote_feats_info->remote_feats)); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1(" GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + cb_data.p_le_update_passed_chann_map_rsp->cause); + break; +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + case GAP_MSG_LE_EXT_ADV_REPORT_INFO: + APP_PRINT_INFO6("GAP_MSG_LE_EXT_ADV_REPORT_INFO:connectable %d, scannable %d, direct %d, scan response %d, legacy %d, data status 0x%x", + cb_data.p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_CONNECTABLE_ADV, + cb_data.p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_SCANNABLE_ADV, + cb_data.p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_DIRECTED_ADV, + cb_data.p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_SCAN_RESPONSE, + cb_data.p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_USE_LEGACY_ADV, + cb_data.p_le_ext_adv_report_info->data_status); + APP_PRINT_INFO5("GAP_MSG_LE_EXT_ADV_REPORT_INFO:event_type 0x%x, bd_addr %s, addr_type %d, rssi %d, data_len %d", + cb_data.p_le_ext_adv_report_info->event_type, + TRACE_BDADDR(cb_data.p_le_ext_adv_report_info->bd_addr), + cb_data.p_le_ext_adv_report_info->addr_type, + cb_data.p_le_ext_adv_report_info->rssi, + cb_data.p_le_ext_adv_report_info->data_len); + APP_PRINT_INFO5("GAP_MSG_LE_EXT_ADV_REPORT_INFO:primary_phy %d, secondary_phy %d, adv_sid %d, tx_power %d, peri_adv_interval %d", + cb_data.p_le_ext_adv_report_info->primary_phy, + cb_data.p_le_ext_adv_report_info->secondary_phy, + cb_data.p_le_ext_adv_report_info->adv_sid, + cb_data.p_le_ext_adv_report_info->tx_power, + cb_data.p_le_ext_adv_report_info->peri_adv_interval); + APP_PRINT_INFO2("GAP_MSG_LE_EXT_ADV_REPORT_INFO:direct_addr_type 0x%x, direct_addr %s", + cb_data.p_le_ext_adv_report_info->direct_addr_type, + TRACE_BDADDR(cb_data.p_le_ext_adv_report_info->direct_addr)); + + if (1) + { + if (dev_list_count < 4) + { + link_mgr_add_device(cb_data.p_le_scan_info->bd_addr, cb_data.p_le_scan_info->remote_addr_type); + } + else + { + le_scan_stop(); + } + } + break; +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case GAP_MSG_LE_EXT_ADV_START_SETTING: + APP_PRINT_INFO3("GAP_MSG_LE_EXT_ADV_START_SETTING:cause 0x%x, flag 0x%x, adv_handle %d", + cb_data.p_le_ext_adv_start_setting_rsp->cause, + cb_data.p_le_ext_adv_start_setting_rsp->flag, + cb_data.p_le_ext_adv_start_setting_rsp->adv_handle); + if (app_get_cur_tc_role() == TC_ROLE_SUT) + { +#if TC_1204_SUPPORT + if (app_get_cur_test_case() == TC_1204_MULTI_LINK_4_MASTER) + { + le_ext_adv_enable(1, &cb_data.p_le_ext_adv_start_setting_rsp->adv_handle); + } +#endif +#if TC_1205_SUPPORT + if (app_get_cur_test_case() == TC_1205_MULTI_LINK_4_MASTER) + { + le_ext_adv_enable(1, &cb_data.p_le_ext_adv_start_setting_rsp->adv_handle); + } +#endif +#if TC_1206_SUPPORT + if (app_get_cur_test_case() == TC_1206_MULTI_LINK_4_MASTER) + { + le_ext_adv_enable(1, &cb_data.p_le_ext_adv_start_setting_rsp->adv_handle); + } +#endif + } + + break; + case GAP_MSG_LE_EXT_ADV_REMOVE_SET: + APP_PRINT_INFO2("GAP_MSG_LE_EXT_ADV_REMOVE_SET:cause 0x%x, adv_handle %d", + cb_data.p_le_ext_adv_remove_set_rsp->cause, + cb_data.p_le_ext_adv_remove_set_rsp->adv_handle); + break; + case GAP_MSG_LE_EXT_ADV_CLEAR_SET: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_CLEAR_SET:cause 0x%x", + cb_data.p_le_ext_adv_clear_set_rsp->cause); + break; + case GAP_MSG_LE_EXT_ADV_ENABLE: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_ENABLE:cause 0x%x", + cb_data.le_cause.cause); + break; + case GAP_MSG_LE_EXT_ADV_DISABLE: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_DISABLE:cause 0x%x", + cb_data.le_cause.cause); + break; + case GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO:adv_handle %d, scanner_addr_type 0x%x, scanner_addr %s", + cb_data.p_le_scan_req_received_info->adv_handle, + cb_data.p_le_scan_req_received_info->scanner_addr_type, + TRACE_BDADDR(cb_data.p_le_scan_req_received_info->scanner_addr)); + break; +#endif +#if F_BT_LE_PRIVACY_SUPPORT + case GAP_MSG_LE_BOND_MODIFY_INFO: + { + APP_PRINT_INFO1(" GAP_MSG_LE_BOND_MODIFY_INFO:type=0x%x", + cb_data.p_le_bond_modify_info->type); + if (cb_data.p_le_bond_modify_info->type == LE_BOND_CLEAR) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_CLEAR, GAP_IDENT_ADDR_PUBLIC, + NULL); + privacy_handle_pending_resolving_list(); + } + else if (cb_data.p_le_bond_modify_info->type == LE_BOND_ADD) + { + T_LE_KEY_ENTRY *p_entry = cb_data.p_le_bond_modify_info->p_entry; + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + else if (p_entry->flags & LE_KEY_STORE_LOCAL_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + else + { + } + privacy_handle_pending_resolving_list(); + } + else if (cb_data.p_le_bond_modify_info->type == LE_BOND_DELETE) + { + T_LE_KEY_ENTRY *p_entry = cb_data.p_le_bond_modify_info->p_entry; + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + else if (p_entry->flags & LE_KEY_STORE_LOCAL_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, + (T_GAP_IDENT_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + else + { + } + privacy_handle_pending_resolving_list(); + } + else + { + } + } + break; +#endif + +#if 0 + case GAP_MSG_LE_VENDOR_DROP_ACL_DATA: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_DROP_ACL_DATA: cause 0x%x", + cb_data.le_cause.cause); + break; +#endif + default: + break; + } + return result; +} + +#if F_BT_LE_GATT_CLIENT_SUPPORT +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id: the ID distinguish which module sent the data. + * @param conn_id: connection ID. + * @param p_data: pointer to data. + * @retval T_APP_RESULT + */ +T_APP_RESULT app_general_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16=0x%x,StartHdl=0x%x,EndHdl=0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + return result; +} + +T_APP_RESULT app_gap_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + + if (client_id == GapClientID) + { + T_GAPS_CLIENT_CB_DATA *pGapCallbackData = (T_GAPS_CLIENT_CB_DATA *)p_data; + APP_PRINT_INFO1("GAp BLE Client CB Type: %d.", pGapCallbackData->cb_type); + switch (pGapCallbackData->cb_type) + { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + switch (pGapCallbackData->cb_content.disc_state) + { + case DISC_GAPS_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("GAP BLE Client CB: discover procedure done."); + break; + case DISC_GAPS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("GAP BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + case GAPS_CLIENT_CB_TYPE_READ_RESULT: + switch (pGapCallbackData->cb_content.read_result.type) + { + case GAPS_READ_DEVICE_NAME: + if (pGapCallbackData->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.", + TRACE_STRING(pGapCallbackData->cb_content.read_result.data.device_name.p_value)); + } + else + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x", + pGapCallbackData->cb_content.read_result.cause); + } + break; + case GAPS_READ_APPEARANCE: + if (pGapCallbackData->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance name %d", + pGapCallbackData->cb_content.read_result.data.appearance); + } + else + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x", + pGapCallbackData->cb_content.read_result.cause); + } + break; + case GAPS_READ_CENTRAL_ADDR_RESOLUTION: + if (pGapCallbackData->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d", + pGapCallbackData->cb_content.read_result.data.central_addr_res); + } + else + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x", + pGapCallbackData->cb_content.read_result.cause); + } + break; + default: + break; + } + break; + + default: + break; + } + } + + return result; +} + + +T_APP_RESULT test_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + + if (client_id == vendor_tp_client_id) + { + T_TP_CB_DATA *p_cb = (T_TP_CB_DATA *)p_data; + tc_20x_sut_client_result_callback(conn_id, p_cb); + } + else if (client_id == vendor_pxp_client_id) + { +#if (TC_500_SUT_SUPPORT||TC_501_SUT_SUPPORT||TC_502_SUT_SUPPORT) + + T_PXP_CB_DATA *p_cb = (T_PXP_CB_DATA *)p_data; + tc_50x_sut_client_result_callback(conn_id, p_cb); +#endif + } + + return result; +} +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +/****************************************************************** + * @fn app_profile_callback + * @brief All the bt profile callbacks are handled in this function. + * Then the event handling function shall be called according to the serviceID + * of T_IO_MSG. + * + * @param serviceID - service id of profile + * @param p_data - pointer to callback data + * @return void + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID serviceID, void *p_data) +{ + T_APP_RESULT appResult = APP_RESULT_SUCCESS; + if (serviceID == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *pPara = (T_SERVER_APP_CB_DATA *)p_data; + switch (pPara->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("profile callback PROFILE_EVT_SRV_REG_COMPLETE result", + pPara->event_data.service_reg_result); + { + //peripheral_Init_StartAdvertising(); + } + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO2("profile callback PROFILE_EVT_SEND_DATA_COMPLETE,result = %d wCredits = %d", + pPara->event_data.send_data_result.cause, + pPara->event_data.send_data_result.credits); + if (pPara->event_data.send_data_result.cause == GAP_SUCCESS) + { + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { +#if TC_200_SUPPORT + tc_200_tp_notification_tx_tx_data_complete(pPara->event_data.send_data_result.credits); +#endif + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { +#if TC_206_SUPPORT + tc_206_tp_notification_tx_tx_data_complete(pPara->event_data.send_data_result.credits); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { +#if TC_208_SUPPORT + tc_208_tp_notification_tx_data_complete(pPara->event_data.send_data_result.credits); +#endif + } + } + else if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUPPORT + tc_700_stable_notification_tx_01_tx_data_complete( + pPara->event_data.send_data_result.credits); +#endif + } + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (serviceID == gSimpleProfileServiceId) + { + TTP_CALLBACK_DATA *pTpCallbackData = (TTP_CALLBACK_DATA *)p_data; + APP_PRINT_INFO1("gSimpleProfileServiceId conn_id = %d", pTpCallbackData->conn_id); + switch (pTpCallbackData->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + APP_PRINT_INFO0("SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION"); + switch (pTpCallbackData->msg_data.notification_indification_index) + { + case VENDOR_TP_SERVICE_V1_INDICATION_ENABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_INDICATION_ENABLE"); + } + break; + + case VENDOR_TP_SERVICE_V1_INDICATION_DISABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_INDICATION_DISABLE"); + } + break; + case VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE"); + if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUPPORT + tc_700_stable_notification_tx_01_cccd_enable(pTpCallbackData->conn_id, true); +#endif + } + } + break; + case VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE: + { + APP_PRINT_INFO0("VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE"); + if (app_get_cur_test_case() == TC_0700_STABLE_NOTIFICATION_TX_01) + { +#if TC_700_SUPPORT + tc_700_stable_notification_tx_01_cccd_enable(pTpCallbackData->conn_id, false); +#endif + } + } + break; + + } + } + break; + + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + APP_PRINT_INFO0("SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE"); + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + APP_PRINT_INFO0("SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE"); + if (pTpCallbackData->msg_data.write.write_type == WRITE_REQUEST) + { + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { +#if TC_200_SUPPORT + tc_200_tp_notification_tx_tx_config(p_data); +#endif + } + else if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { +#if TC_206_SUPPORT + tc_206_tp_notification_tx_tx_config(p_data); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { +#if TC_208_SUPPORT + tc_208_tp_notification_tx_tx_config(p_data); +#endif + } + } + else + { + if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { +#if TC_207_SUPPORT + tc_207_tp_handle_write_data(p_data); +#endif + } + else if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { +#if TC_208_SUPPORT + tc_208_tp_handle_write_data(p_data); +#endif + } + } + } + } + } + + return appResult; +} +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CBC_DATA cb_data; + memcpy(&cb_data, p_cbc_data, sizeof(T_LE_CBC_DATA)); + APP_PRINT_TRACE1("app_credit_based_conn_callback: msgType = %d", cbc_type); + switch (cbc_type) + { + case GAP_CBC_MSG_LE_CHANN_STATE: + APP_PRINT_INFO4("GAP_CBC_MSG_LE_CHANN_STATE: conn_id %d, cid 0x%x, conn_state %d, cause 0x%x", + cb_data.p_le_chann_state->conn_id, + cb_data.p_le_chann_state->cid, + cb_data.p_le_chann_state->conn_state, + cb_data.p_le_chann_state->cause); + if (cb_data.p_le_chann_state->conn_state == GAP_CHANN_STATE_CONNECTED) + { + uint16_t mtu; + uint16_t credit; + le_cbc_get_chann_param(CBC_CHANN_PARAM_CUR_CREDITS, &credit, cb_data.p_le_chann_state->cid); + le_cbc_get_chann_param(CBC_CHANN_PARAM_MTU, &mtu, cb_data.p_le_chann_state->cid); + APP_PRINT_INFO2("GAP_CHANN_STATE_CONNECTED: mtu %d, credit %d", mtu, credit); + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { + if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUPPORT + tc_1100_chann_connected(cb_data.p_le_chann_state->cid); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUPPORT + tc_1101_chann_connected(cb_data.p_le_chann_state->cid, + mtu, + credit); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUPPORT + tc_1102_chann_connected(cb_data.p_le_chann_state->cid, + mtu, + credit); +#endif + } + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUT_SUPPORT + tc_1100_sut_chann_connected(cb_data.p_le_chann_state->cid); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUT_SUPPORT + tc_1101_sut_chann_connected(cb_data.p_le_chann_state->cid, mtu, + credit); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUT_SUPPORT + tc_1102_sut_chann_connected(cb_data.p_le_chann_state->cid, mtu, + credit); +#endif + } + } + } + else if (cb_data.p_le_chann_state->conn_state == GAP_CHANN_STATE_DISCONNECTED) + { + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { + if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUPPORT + tc_1100_chann_disconnected(cb_data.p_le_chann_state->cid, cb_data.p_le_chann_state->cause); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUPPORT + tc_1101_chann_disconnected(cb_data.p_le_chann_state->cid, cb_data.p_le_chann_state->cause); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUPPORT + tc_1102_chann_disconnected(cb_data.p_le_chann_state->cid, cb_data.p_le_chann_state->cause); +#endif + } + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUT_SUPPORT + tc_1100_sut_chann_disconnected(cb_data.p_le_chann_state->cid, cb_data.p_le_chann_state->cause); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUT_SUPPORT + tc_1101_sut_chann_disconnected(cb_data.p_le_chann_state->cid, cb_data.p_le_chann_state->cause); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUT_SUPPORT + tc_1102_sut_chann_disconnected(cb_data.p_le_chann_state->cid, cb_data.p_le_chann_state->cause); +#endif + } + } + } + break; + + case GAP_CBC_MSG_LE_REG_PSM: + APP_PRINT_INFO2("GAP_CBC_MSG_LE_REG_PSM: le_psm 0x%x, cause 0x%x", + cb_data.p_le_reg_psm_rsp->le_psm, + cb_data.p_le_reg_psm_rsp->cause); + break; + + case GAP_CBC_MSG_LE_SET_PSM_SECURITY: + APP_PRINT_INFO1("GAP_CBC_MSG_LE_SET_PSM_SECURITY: cause 0x%x", + cb_data.p_le_set_psm_security_rsp->cause); + break; + + case GAP_CBC_MSG_LE_SEND_DATA: + APP_PRINT_INFO4("GAP_CBC_MSG_LE_SEND_DATA: conn_id %d, cid 0x%x, cause 0x%x, credit %d", + cb_data.p_le_send_data->conn_id, + cb_data.p_le_send_data->cid, + cb_data.p_le_send_data->cause, + cb_data.p_le_send_data->credit); + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { + if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUPPORT + tx_1101_send_data_cmpl(cb_data.p_le_send_data->cause, cb_data.p_le_send_data->credit); +#endif + } + if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUPPORT + tc_1102_send_data_cmpl(cb_data.p_le_send_data->cause, cb_data.p_le_send_data->credit); +#endif + } + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUT_SUPPORT + tc_1100_sut_chann_data_send_cmpl(cb_data.p_le_send_data->cause); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUT_SUPPORT + tc_1101_sut_chann_data_send_cmpl(cb_data.p_le_send_data->cause, cb_data.p_le_send_data->credit); +#endif + } + } + break; + + case GAP_CBC_MSG_LE_RECEIVE_DATA: + APP_PRINT_INFO3("GAP_CBC_MSG_LE_RECEIVE_DATA: conn_id %d, cid 0x%x, value_len %d", + cb_data.p_le_receive_data->conn_id, + cb_data.p_le_receive_data->cid, + cb_data.p_le_receive_data->value_len); + if (app_get_cur_tc_role() == TC_ROLE_DUT) + { + if (app_get_cur_test_case() == TC_1100_BT41_CONN_TEST) + { +#if TC_1100_SUPPORT + tc_1100_receive_data(cb_data.p_le_receive_data->cid); +#endif + } + else if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUPPORT + tc_1101_receive_data(cb_data.p_le_receive_data->cid, cb_data.p_le_receive_data->value_len); +#endif + } + } + else if (app_get_cur_tc_role() == TC_ROLE_SUT) + { + if (app_get_cur_test_case() == TC_1101_BT41_TRX_STRESS_TEST) + { +#if TC_1101_SUT_SUPPORT + tc_1101_sut_receive_data(cb_data.p_le_receive_data->cid, cb_data.p_le_receive_data->value_len); +#endif + } + else if (app_get_cur_test_case() == TC_1102_BT41_TP_TEST) + { +#if TC_1102_SUT_SUPPORT + tc_1102_sut_receive_data(cb_data.p_le_receive_data->cid, cb_data.p_le_receive_data->value_len); +#endif + } + } + break; + + default: + break; + } + return result; +} +#endif +void tc_add_case(uint32_t count) +{ + T_CUR_DEVICE_ROLE role = app_get_cur_tc_role(); + + switch (role) + { + case TC_ROLE_DUT: + { + + +#if TC_0001_SUPPORT +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + tc_0001_add_case(0x80, 0x80); +#endif +#endif + +#if TC_0002_SUPPORT + tc_0002_add_case(0x80, 0x80, 1000); +#endif + /** + format: + tc 101 [scan_mode] [interval] [window] [filter_policy] [filter_dup] [count] + + sample: + tc 101 1 100 100 0 0 1000 + + */ +#if TC_101_SUPPORT + tc_0101_add_case(GAP_SCAN_MODE_ACTIVE, 100, 100, GAP_SCAN_FILTER_ANY, 0, 10); +#endif +#if TC_300_SUPPORT + tc_300_add_case(count); +#endif +#if TC_301_SUPPORT + tc_301_add_case(count); +#endif +#if TC_500_SUPPORT + tc_500_add_case(count); +#endif +#if TC_501_SUPPORT + tc_501_add_case(count); +#endif +#if TC_600_SUPPORT + tc_600_add_case(count); +#endif +#if TC_601_SUPPORT + tc_601_add_case(count); +#endif + + + } + break; + + case TC_ROLE_SUT: + { +#if 1 + /** + format: + tc 101 [scan_mode] [interval] [window] [filter_policy] [filter_dup] [count] + sample: + tc 101 1 100 100 0 0 1000 + */ +#if TC_101_SUPPORT + tc_0101_add_case(GAP_SCAN_MODE_ACTIVE, 100, 100, GAP_SCAN_FILTER_ANY, 0, 10); +#endif + +#if TC_300_SUT_SUPPORT + tc_300_sut_add_case(count, g_cur_rembd); +#endif + +#if TC_301_SUT_SUPPORT + tc_301_sut_add_case(count, g_cur_rembd); +#endif + +#if TC_500_SUT_SUPPORT + tc_500_sut_add_case(count, g_cur_rembd); +#endif + +#if TC_501_SUT_SUPPORT + tc_501_sut_add_case(count, g_cur_rembd); +#endif + +#if TC_600_SUT_SUPPORT + tc_600_sut_add_case(count, g_cur_rembd); +#endif +#if TC_601_SUT_SUPPORT + tc_601_sut_add_case(count, g_cur_rembd); +#endif + +#endif + + } + break; + case TC_ROLE_UNDEFINED: + + break; + default: + break; + } +} + +void tc_result_cb(uint16_t case_id, uint16_t result, void *p_cb_data) +{ + data_uart_print("tc %d, result 0x%04x\r\n", case_id, result); + + tc_dump_disc_reason(); + memset(&g_ble_disconn_reason, 0, sizeof(g_ble_disconn_reason)); + + if (case_id) + { + switch (case_id) + { + case TC_0001_ADV_PERFORMANCE: + break; + + case TC_0002_ADV_STRESS_START_STOP: + + break; + +#if TC_100_SUPPORT + case TC_0100_SCAN_PERFORMANCE: + { + + } + break; + + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + + } + break; +#endif + + case TC_0200_TP_NOTIFICATION_TX_01: + { + } + + break; + case TC_0201_TP_INDICATION_TX_01: + + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + case TC_0300_ADV_ONLY: + { + + } + break; + case TC_0301_ADV_DISC: + { + } + break; + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + break; + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + break; + case TC_0500_SLAVE_AUTO_ADV: + { + } + break; + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + } + break; + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + { + } + break; + case TC_0600_IOP_PAIR_LEGACL: + { + } + break; + case TC_0601_IOP_PAIR_SC: + { + } + break; + case TC_0700_STABLE_NOTIFICATION_TX_01: + break; + + case TC_0800_IOP_PAIR_LEGACL: + break; + case TC_0801_IOP_PAIR_SC: + break; + + case TC_0900_PRIVACY_TEST_SLAVE: + break; + case TC_0901_PRIVACY_TEST_MASTER: + break; + + default: + break; + + } + } + + tc_start_next_case(); +} + + + + +void tc_dut_start_next_case(uint16_t id, T_TC_PARAM_DATA *p_tc_param) +{ + switch (id) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + +#if TC_0001_SUPPORT + case TC_0001_ADV_PERFORMANCE: + { + T_TC_0001_PARAM_DATA *p_tc_0001_param_data; + p_tc_0001_param_data = (T_TC_0001_PARAM_DATA *)p_tc_param; + tc_0001_adv_start(p_tc_0001_param_data->adv_interval_min, p_tc_0001_param_data->adv_interval_max); + } + break; +#endif + +#if TC_0002_SUPPORT + case TC_0002_ADV_STRESS_START_STOP: + { + T_TC_0002_PARAM_DATA *p_tc_0002_param_data; + p_tc_0002_param_data = (T_TC_0002_PARAM_DATA *)p_tc_param; + + tc_0002_adv_start_stop_start(p_tc_0002_param_data->adv_interval_min, + p_tc_0002_param_data->adv_interval_max, + p_tc_0002_param_data->max_count); + } + break; +#endif + +#if TC_100_SUPPORT + + case TC_0100_SCAN_PERFORMANCE: + { + + } + break; +#endif +#endif + +#if TC_100_SUPPORT + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + + T_TC_0101_IN_PARAM_DATA *p_tc_0101_in_param_data; + p_tc_0101_in_param_data = (T_TC_0101_IN_PARAM_DATA *)p_tc_param; + tc_0101_scan_stress_enable_disable_start(p_tc_0101_in_param_data->mode, + p_tc_0101_in_param_data->interval, + p_tc_0101_in_param_data->window, + p_tc_0101_in_param_data->filter_policy, + p_tc_0101_in_param_data->filter_duplicates, + p_tc_0101_in_param_data->max_count); + } + break; +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + +#if TC_200_SUPPORT + case TC_0200_TP_NOTIFICATION_TX_01: + { + uint16_t interval = 0x80; + uint16_t length = 20; + uint8_t tx_octets = 27; + tc_200_tp_notification_tx_init_config(interval, length, tx_octets, false); + tc_200_tp_notification_tx_start(); + } + break; +#endif + case TC_0201_TP_INDICATION_TX_01: + + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUPPORT + case TC_0300_ADV_ONLY: + { + T_TC_300_IN_PARAM_DATA *p_tc_300_in_param_data; + p_tc_300_in_param_data = (T_TC_300_IN_PARAM_DATA *)p_tc_param; + + tc_300_adv_only_start(p_tc_300_in_param_data->total_test_count); + } + break; +#endif + +#if TC_301_SUPPORT + case TC_0301_ADV_DISC: + { + T_TC_301_IN_PARAM_DATA *p_tc_301_in_param_data; + p_tc_301_in_param_data = (T_TC_301_IN_PARAM_DATA *)p_tc_param; + + tc_301_adv_disc_start(p_tc_301_in_param_data->total_test_count); + } + break; +#endif + +#if TC_400_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + { + T_TC_400_IN_PARAM_DATA *p_tc_400_in_param_data; + p_tc_400_in_param_data = (T_TC_400_IN_PARAM_DATA *)p_tc_param; + + tc_400_start(p_tc_400_in_param_data->total_test_count); + } + break; +#endif + +#if TC_401_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + { + T_TC_401_IN_PARAM_DATA *p_tc_401_in_param_data; + p_tc_401_in_param_data = (T_TC_401_IN_PARAM_DATA *)p_tc_param; + + tc_401_start(p_tc_401_in_param_data->total_test_count); + } + break; +#endif + +#if TC_500_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + { + T_TC_500_IN_PARAM_DATA *p_tc_500_in_param_data; + p_tc_500_in_param_data = (T_TC_500_IN_PARAM_DATA *)p_tc_param; + tc_500_salve_auto_adv_start(p_tc_500_in_param_data->total_test_count); + } + break; +#endif + +#if TC_501_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + T_TC_501_IN_PARAM_DATA *p_tc_501_in_param_data; + p_tc_501_in_param_data = (T_TC_501_IN_PARAM_DATA *)p_tc_param; + + tc_501_salve_auto_adv_with_sec_req_start(p_tc_501_in_param_data->total_test_count); + } + break; +#endif + +#if TC_502_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + { + T_TC_502_IN_PARAM_DATA *p_tc_502_in_param_data; + p_tc_502_in_param_data = (T_TC_502_IN_PARAM_DATA *)p_tc_param; + tc_502_salve_auto_adv_start(p_tc_502_in_param_data->total_test_count); + } + break; +#endif + +#if TC_600_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + { + T_TC_600_IN_PARAM_DATA *p_tc_600_in_param_data; + p_tc_600_in_param_data = (T_TC_600_IN_PARAM_DATA *)p_tc_param; + + tc_600_iop_android_legacl_pair_start(p_tc_600_in_param_data->total_test_count); + } + break; +#endif + +#if TC_601_SUPPORT + case TC_0601_IOP_PAIR_SC: + { + T_TC_601_IN_PARAM_DATA *p_tc_601_in_param_data; + p_tc_601_in_param_data = (T_TC_601_IN_PARAM_DATA *)p_tc_param; + tc_601_iop_android_sc_pair_start(p_tc_601_in_param_data->total_test_count); + } + break; +#endif + +#if TC_700_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + tc_700_stable_notification_tx_01_start(); + break; + +#endif + +#if TC_800_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + { + T_TC_800_IN_PARAM_DATA *p_tc_800_in_param_data; + p_tc_800_in_param_data = (T_TC_800_IN_PARAM_DATA *)p_tc_param; + + tc_800_iop_android_legacl_pair_start(p_tc_800_in_param_data->total_test_count); + } + break; +#endif + +#if TC_801_SUPPORT + case TC_0801_IOP_PAIR_SC: + { + T_TC_801_IN_PARAM_DATA *p_tc_801_in_param_data; + p_tc_801_in_param_data = (T_TC_801_IN_PARAM_DATA *)p_tc_param; + tc_801_iop_android_sc_pair_start(p_tc_801_in_param_data->total_test_count); + } + break; +#endif + +#if TC_900_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + tc_900_privacy_slave(); + break; +#endif + +#if TC_901_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + tc_901_privacy_master(); + break; +#endif + +#endif + +#if TC_1000_SUPPORT +#if F_CP_TEST_SUPPORT + case TC_1000_CP_TEST: + tc_1000_hw_init(); + tc_1000_start(); + break; + case TC_1001_CP_TEST: + tc_1001_start(); + break; + case TC_1002_CP_TEST: + tc_1002_start(); + break; +#endif +#endif + default: + return; + } +} + + +void tc_sut_start_next_case(uint16_t id, T_TC_PARAM_DATA *p_tc_param) +{ + switch (id) + { + + +#if TC_0001_SUPPORT + case TC_0001_ADV_PERFORMANCE: + { + T_TC_0001_PARAM_DATA *p_tc_0001_param_data; + p_tc_0001_param_data = (T_TC_0001_PARAM_DATA *)p_tc_param; + tc_0001_adv_start(p_tc_0001_param_data->adv_interval_min, p_tc_0001_param_data->adv_interval_max); + } + break; +#endif + + +#if TC_0002_SUPPORT + case TC_0002_ADV_STRESS_START_STOP: + { + T_TC_0002_PARAM_DATA *p_tc_0002_param_data; + p_tc_0002_param_data = (T_TC_0002_PARAM_DATA *)p_tc_param; + + tc_0002_adv_start_stop_start(p_tc_0002_param_data->adv_interval_min, + p_tc_0002_param_data->adv_interval_max, + p_tc_0002_param_data->max_count); + } + break; +#endif +#if TC_100_SUPPORT + case TC_0100_SCAN_PERFORMANCE: + { + + } + break; +#endif + +#if TC_100_SUPPORT + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + + T_TC_0101_IN_PARAM_DATA *p_tc_0101_in_param_data; + p_tc_0101_in_param_data = (T_TC_0101_IN_PARAM_DATA *)p_tc_param; + tc_0101_scan_stress_enable_disable_start(p_tc_0101_in_param_data->mode, + p_tc_0101_in_param_data->interval, + p_tc_0101_in_param_data->window, + p_tc_0101_in_param_data->filter_policy, + p_tc_0101_in_param_data->filter_duplicates, + p_tc_0101_in_param_data->max_count); + } + break; +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + + + +#if TC_200_SUT_SUPPORT + case TC_0200_TP_NOTIFICATION_TX_01: + { + uint16_t interval = 0x80; + uint16_t length = 20; + uint8_t tx_octets = 27; + tc_200_tp_notification_tx_init_config(interval, length, tx_octets, false); + tc_200_tp_notification_tx_start(); + } + break; +#endif + + case TC_0201_TP_INDICATION_TX_01: + + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUT_SUPPORT + case TC_0300_ADV_ONLY: + { + T_TC_300_SUT_IN_PARAM_DATA *p_tc_300_sut_in_param_data; + p_tc_300_sut_in_param_data = (T_TC_300_SUT_IN_PARAM_DATA *)p_tc_param; + + tc_300_sut_start(p_tc_300_sut_in_param_data->total_test_count, + p_tc_300_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_301_SUT_SUPPORT + case TC_0301_ADV_DISC: + { + T_TC_301_SUT_IN_PARAM_DATA *p_tc_301_sut_in_param_data; + p_tc_301_sut_in_param_data = (T_TC_301_SUT_IN_PARAM_DATA *)p_tc_param; + + tc_301_sut_start(p_tc_301_sut_in_param_data->total_test_count, + p_tc_301_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_400_SUT_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + { + T_TC_400_SUT_IN_PARAM_DATA *p_tc_400_sut_in_param_data; + p_tc_400_sut_in_param_data = (T_TC_400_SUT_IN_PARAM_DATA *)p_tc_param; + + tc_400_sut_start(p_tc_400_sut_in_param_data->total_test_count, + p_tc_400_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_401_SUT_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + { + T_TC_401_SUT_IN_PARAM_DATA *p_tc_401_sut_in_param_data; + p_tc_401_sut_in_param_data = (T_TC_401_SUT_IN_PARAM_DATA *)p_tc_param; + + tc_401_sut_start(p_tc_401_sut_in_param_data->total_test_count, + p_tc_401_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_500_SUT_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + { + T_TC_500_SUT_IN_PARAM_DATA *p_tc_500_sut_in_param_data; + p_tc_500_sut_in_param_data = (T_TC_500_SUT_IN_PARAM_DATA *)p_tc_param; + tc_500_sut_start(p_tc_500_sut_in_param_data->total_test_count, + p_tc_500_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_501_SUT_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + T_TC_501_SUT_IN_PARAM_DATA *p_tc_501_sut_in_param_data; + p_tc_501_sut_in_param_data = (T_TC_501_SUT_IN_PARAM_DATA *)p_tc_param; + tc_501_sut_start(p_tc_501_sut_in_param_data->total_test_count, + p_tc_501_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_502_SUT_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + { + + } + break; +#endif + +#if TC_600_SUT_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + { + T_TC_600_SUT_IN_PARAM_DATA *p_tc_600_sut_in_param_data; + p_tc_600_sut_in_param_data = (T_TC_600_SUT_IN_PARAM_DATA *)p_tc_param; + tc_600_sut_iop_android_legacl_pair_start(p_tc_600_sut_in_param_data->total_test_count, + p_tc_600_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_601_SUT_SUPPORT + case TC_0601_IOP_PAIR_SC: + { + T_TC_601_SUT_IN_PARAM_DATA *p_tc_601_sut_in_param_data; + p_tc_601_sut_in_param_data = (T_TC_601_SUT_IN_PARAM_DATA *)p_tc_param; + tc_601_sut_iop_android_sc_pair_start(p_tc_601_sut_in_param_data->total_test_count, + p_tc_601_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_700_SUT_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + tc_700_stable_notification_tx_01_start(); + break; + + +#endif + +#if TC_800_SUT_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + { + T_TC_800_SUT_IN_PARAM_DATA *p_tc_800_sut_in_param_data; + p_tc_800_sut_in_param_data = (T_TC_800_SUT_IN_PARAM_DATA *)p_tc_param; + tc_800_sut_iop_android_legacl_pair_start(p_tc_800_sut_in_param_data->total_test_count, + p_tc_800_sut_in_param_data->remote_bd); + } + break; +#endif + +#if TC_801_SUT_SUPPORT + case TC_0801_IOP_PAIR_SC: + { + T_TC_801_SUT_IN_PARAM_DATA *p_tc_801_sut_in_param_data; + p_tc_801_sut_in_param_data = (T_TC_801_SUT_IN_PARAM_DATA *)p_tc_param; + tc_801_sut_iop_android_sc_pair_start(p_tc_801_sut_in_param_data->total_test_count, + p_tc_801_sut_in_param_data->remote_bd); + } + break; +#endif + +#endif + +#if TC_900_SUT_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + tc_900_privacy_slave(); + break; + +#endif + +#if TC_901_SUT_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + tc_901_privacy_master(); + break; +#endif + + +#if TC_1000_SUPPORT + + case TC_1000_CP_TEST: + tc_1000_hw_init(); + tc_1000_start(); + break; + case TC_1001_CP_TEST: + tc_1001_start(); + break; + case TC_1002_CP_TEST: + tc_1002_start(); + break; + +#endif + + default: + return; + } +} + + +void tc_start_next_case(void) +{ + T_CUR_DEVICE_ROLE role = app_get_cur_tc_role(); + + tc_reg_result_callback(tc_result_cb); + + //start next case + T_TC_PARAM *p_tc_param = os_queue_out(&tc_q); + T_TC_PARAM_DATA *p_tc_param_data; + + if (p_tc_param == NULL) + { + data_uart_print("queue out failed"); + return; + } + + p_tc_param_data = (T_TC_PARAM_DATA *)(p_tc_param->p_data); + + app_set_cur_case((T_CUR_TEST_CASE)p_tc_param_data->id); + + switch (role) + { + case TC_ROLE_DUT: + tc_dut_start_next_case(p_tc_param_data->id, p_tc_param_data); + break; + + case TC_ROLE_SUT: + tc_sut_start_next_case(p_tc_param_data->id, p_tc_param_data); + break; + + default: + break; + } + + os_mem_free(p_tc_param->p_data); + os_mem_free(p_tc_param); + +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_application.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_application.h new file mode 100644 index 00000000..27c1aee1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_application.h @@ -0,0 +1,59 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ble_auto_test_application.h +* @brief gap roles test app implementation +* @details gap roles test app implementation +* @author jane +* @date 2016-02-18 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _GAP_ROLES_TEST_APP_H_ +#define _GAP_ROLES_TEST_APP_H_ +#include "app_msg.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#include "privacy_mgnt.h" +#endif + + +extern void app_handle_io_msg(T_IO_MSG io_msg); +extern T_APP_RESULT app_gap_callback(uint8_t cb_type, + void *p_cb_data); +#if F_BT_LE_GATT_CLIENT_SUPPORT +extern T_APP_RESULT app_simp_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +extern T_APP_RESULT app_gap_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +extern T_APP_RESULT app_general_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, + void *p_data); +#endif +#if F_BT_LE_GATT_SERVER_SUPPORT +extern T_APP_RESULT app_profile_callback(T_SERVER_ID serviceID, void *p_data); +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data); +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT test_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#endif +void tc_start_next_case(void); +void tc_add_case(uint32_t count); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_case.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_case.c new file mode 100644 index 00000000..fc377175 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_case.c @@ -0,0 +1,2406 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#endif + +#include +#if F_BT_LE_PRIVACY_SUPPORT +#include "privacy_mgnt.h" +#endif + +#if F_BT_DLPS_EN +#include "dlps.h" +#include +#endif + +T_CUR_TEST_CASE g_cur_test_case; + +T_CUR_DEVICE_ROLE g_cur_test_role; + +T_OS_QUEUE tc_q; + + + + +TGATTDBdAddr tc_rembd_list[] = /* first entry is default BD: */ +{ + { 0x66, 0x66, 0xee, 0x22, 0x11, 0x00 }, /* FPGA v6-5 */ + { 0x3d, 0x19, 0x48, 0x25, 0x80, 0x00 }, /* Stollmann Board 1 */ + { 0xe3, 0x18, 0x48, 0x25, 0x80, 0x00 }, /* Stollmann Board 2 */ + { 0x01, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB1*/ + { 0x02, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB2*/ + { 0x03, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB3*/ + { 0x04, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB4*/ + { 0x05, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB5*/ + { 0x06, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB6*/ + { 0x07, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB7*/ + { 0x08, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB8*/ + { 0x09, 0x44, 0x33, 0x22, 0x11, 0x00 }, /* Bee1 EVB9*/ + +}; + +TGATTDBdAddr g_cur_rembd; + +uint32_t os_time_get_elapsed(uint32_t begin, uint32_t end) +{ +#if 1 + if (end > begin) + { + return end - begin; + } + else + { + return ((uint32_t)(2147483647) - begin + end); + } +#else + uint32_t expire_count; + + if (begin <= end) + { + expire_count = end - begin; + } + else + { + expire_count = 0xFFFFFFFF - (begin - end); + } + return expire_count; +#endif +} + +uint32_t amebad_time_get_elapsed(uint32_t begin, uint32_t end) +{ + uint32_t expire_count; + + if (begin <= end) + { + expire_count = end - begin; + } + else + { + expire_count = 0xFFFFFFFF - (begin - end); + } + expire_count = expire_count * 31; + return expire_count; +} + +T_CUR_DEVICE_ROLE app_get_cur_tc_role(void) +{ + return g_cur_test_role; +} + +void app_set_cur_tc_role(T_CUR_DEVICE_ROLE role) +{ + switch (role) + { + case TC_ROLE_UNDEFINED: + data_uart_print("app_set_cur_tc_role: TC_ROLE_UNDEFINED\r\n"); + break; + case TC_ROLE_DUT: + data_uart_print("app_set_cur_tc_role: role TC_ROLE_DUT\r\n"); + break; + case TC_ROLE_SUT: + data_uart_print("app_set_cur_tc_role: TC_ROLE_SUT\r\n"); + break; + default: + role = TC_ROLE_UNDEFINED; + data_uart_print("app_set_cur_tc_role: TC_ROLE_UNDEFINED\r\n"); + break; + } + g_cur_test_role = role; +} + + +T_CUR_TEST_CASE app_get_cur_test_case(void) +{ + return g_cur_test_case; +} + +void app_display_case_details(T_CUR_TEST_CASE test_case_id) +{ + switch (test_case_id) + { + case TC_IDLE: + { + data_uart_print("select one test case:\r\n"); + + data_uart_print("testcase 1 - %s\r\n", "TC_0001_ADV_PERFORMANCE"); + data_uart_print("testcase 2 - %s\r\n", "TC_0200_TP_NOTIFICATION_TX_01"); + data_uart_print("testcase 3 - %s\r\n", "TC_0201_TP_INDICATION_TX_01"); + data_uart_print("testcase 4 - %s\r\n", "TC_0202_TP_WRITE_COMMAND_TX_01"); + data_uart_print("testcase 5 - %s\r\n", "TC_0203_TP_NOTIFICATION_RX_01"); + data_uart_print("testcase 6 - %s\r\n", "TC_0205_TP_WRITE_COMMAND_RX_01"); + data_uart_print("testcase 7 - %s\r\n", "TC_0204_TP_INDICATION_RX_01"); + data_uart_print("testcase 8 - %s\r\n", "TC_0300_ADV_ONLY"); + data_uart_print("testcase 9 - %s\r\n", "TC_0301_ADV_DISC"); + data_uart_print("testcase 10 - %s\r\n", "TC_0400_CONN_PARAM_UPDATE_SLAVE"); + data_uart_print("testcase 11 - %s\r\n", "TC_0401_CONN_PARAM_UPDATE_SLAVE_01"); + data_uart_print("testcase 12 - %s\r\n", "TC_0500_SLAVE_AUTO_ADV"); + } + break; + + case TC_0001_ADV_PERFORMANCE: + data_uart_print("TC_0001_ADV_PERFORMANCE is selected\r\n"); + APP_PRINT_INFO0("TC_0001_ADV_PERFORMANCE Start\r\n"); + break; + case TC_0002_ADV_STRESS_START_STOP: + data_uart_print("TC_0002_ADV_STRESS_START_STOP is selected\r\n"); + APP_PRINT_INFO0("TC_0002_ADV_STRESS_START_STOP Start\r\n"); + break; + + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + data_uart_print("TC_0101_SCAN_STRESS_ENABLE_DISABLE is selected, 7 params\r\n"); + data_uart_print("tc 101 [scan_mode] [interval] [window] [filte_policy] [filter_dup] [coount]\r\n"); + APP_PRINT_INFO0("TC_0101_SCAN_STRESS_ENABLE_DISABLE Start\r\n"); + break; + + case TC_0200_TP_NOTIFICATION_TX_01: + data_uart_print("TC_0200_TP_NOTIFICATION_TX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0200_TP_NOTIFICATION_TX_01 Start\r\n"); + + break; + case TC_0201_TP_INDICATION_TX_01: + data_uart_print("TC_0201_TP_INDICATION_TX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0201_TP_INDICATION_TX_01 Start\r\n"); + + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + data_uart_print("TC_0202_TP_WRITE_COMMAND_TX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0202_TP_WRITE_COMMAND_TX_01 Start\r\n"); + + break; + case TC_0203_TP_NOTIFICATION_RX_01: + data_uart_print("TC_0203_TP_NOTIFICATION_RX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0203_TP_NOTIFICATION_RX_01 Start\r\n"); + + break; + case TC_0204_TP_INDICATION_RX_01: + data_uart_print("TC_0204_TP_INDICATION_RX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0204_TP_INDICATION_RX_01 Start\r\n"); + + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + data_uart_print("TC_0205_TP_WRITE_COMMAND_RX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0205_TP_WRITE_COMMAND_RX_01 Start\r\n"); + + break; + case TC_0206_TP_NOTIFICATION_TX_02: + data_uart_print("TC_0206_TP_NOTIFICATION_TX_02 is selected\r\n"); + APP_PRINT_INFO0("TC_0206_TP_NOTIFICATION_TX_02 Start\r\n"); + break; + + case TC_0207_TP_WRITE_COMMAND_RX_02: + data_uart_print("TC_0207_TP_WRITE_COMMAND_RX_02 is selected\r\n"); + APP_PRINT_INFO0("TC_0207_TP_WRITE_COMMAND_RX_02 Start\r\n"); + break; + + case TC_0208_TP_NOTIF_WRITE_CMD_TRX_02: + data_uart_print("TC_0208_TP_NOTIF_WRITE_CMD_TRX_02 is selected\r\n"); + APP_PRINT_INFO0("TC_0208_TP_NOTIF_WRITE_CMD_TRX_02 Start\r\n"); + break; + + case TC_0300_ADV_ONLY: + data_uart_print("TC_0300_ADV_ONLY is selected\r\n"); + APP_PRINT_INFO0("TC_0300_ADV_ONLY Start\r\n"); + break; + case TC_0301_ADV_DISC: + data_uart_print("TC_0301_ADV_DISC is selected\r\n"); + APP_PRINT_INFO0("TC_0301_ADV_DISC Start\r\n"); + break; + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + data_uart_print("TC_0400_CONN_PARAM_UPDATE_SLAVE is selected\r\n"); + APP_PRINT_INFO0("TC_0400_CONN_PARAM_UPDATE_SLAVE Start\r\n"); + + break; + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + data_uart_print("TC_0401_CONN_PARAM_UPDATE_SLAVE_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0401_CONN_PARAM_UPDATE_SLAVE_01 Start\r\n"); + + break; + case TC_0500_SLAVE_AUTO_ADV: + data_uart_print("TC_0500_SLAVE_AUTO_ADV is selected\r\n"); + APP_PRINT_INFO0("TC_0500_SLAVE_AUTO_ADV Start\r\n"); + + break; + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + data_uart_print("TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ is selected\r\n"); + APP_PRINT_INFO0("TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ Start\r\n"); + + break; + + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + data_uart_print("TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV is selected\r\n"); + APP_PRINT_INFO0("TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV Start\r\n"); + break; + + case TC_0600_IOP_PAIR_LEGACL: + data_uart_print("TC_0600_IOP_PAIR_LEGACL is selected\r\n"); + APP_PRINT_INFO0("TC_0600_IOP_PAIR_LEGACL Start\r\n"); + + break; + case TC_0601_IOP_PAIR_SC: + data_uart_print("TC_0601_IOP_PAIR_SC is selected\r\n"); + APP_PRINT_INFO0("TC_0601_IOP_PAIR_SC Start\r\n"); + + break; + case TC_0700_STABLE_NOTIFICATION_TX_01: + data_uart_print("TC_0700_STABLE_NOTIFICATION_TX_01 is selected\r\n"); + APP_PRINT_INFO0("TC_0700_STABLE_NOTIFICATION_TX_01 Start\r\n"); + + break; + case TC_0800_IOP_PAIR_LEGACL: + data_uart_print("TC_0800_IOP_PAIR_LEGACL is selected\r\n"); + APP_PRINT_INFO0("TC_0800_IOP_PAIR_LEGACL Start\r\n"); + + break; + case TC_0801_IOP_PAIR_SC: + data_uart_print("TC_0801_IOP_PAIR_SC is selected\r\n"); + APP_PRINT_INFO0("TC_0801_IOP_PAIR_SC Start\r\n"); + + break; + case TC_0900_PRIVACY_TEST_SLAVE: + data_uart_print("TC_0900_PRIVACY_TEST_SLAVE is selected\r\n"); + APP_PRINT_INFO0("TC_0900_PRIVACY_TEST_SLAVE Start\r\n"); + break; + + case TC_0901_PRIVACY_TEST_MASTER: + data_uart_print("TC_0901_PRIVACY_TEST_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_0901_PRIVACY_TEST_MASTER Start\r\n"); + + break; + + case TC_1000_CP_TEST: + data_uart_print("TC_1000_CP_TEST is selected\r\n"); + APP_PRINT_INFO0("TC_1000_CP_TEST Start\r\n"); + + break; + + case TC_1100_BT41_CONN_TEST: + data_uart_print("TC_1100_BT41_CONN_TEST is selected\r\n"); + APP_PRINT_INFO0("TC_1100_BT41_CONN_TEST Start\r\n"); + break; + + case TC_1101_BT41_TRX_STRESS_TEST: + data_uart_print("TC_1101_BT41_TRX_STRESS_TEST is selected\r\n"); + APP_PRINT_INFO0("TC_1101_BT41_TRX_STRESS_TEST Start\r\n"); + break; + + case TC_1102_BT41_TP_TEST: + data_uart_print("TC_1102_BT41_TP_TEST is selected\r\n"); + APP_PRINT_INFO0("TC_1102_BT41_TP_TEST Start\r\n"); + break; + case TC_1200_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + case TC_1201_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + case TC_1202_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + case TC_1203_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + case TC_1204_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + case TC_1205_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + case TC_1206_MULTI_LINK_4_MASTER: + data_uart_print("TC_1200_MULTI_LINK_2_MASTER is selected\r\n"); + APP_PRINT_INFO0("TC_1200_MULTI_LINK_2_MASTER Start\r\n"); + break; + + default: + data_uart_print("invlid test case id\r\n"); + return; + } + +} + +void app_dump_tc_status(T_CUR_TEST_CASE test_case_id) +{ + T_CUR_DEVICE_ROLE role; + role = app_get_cur_tc_role(); + switch (role) + { + case TC_ROLE_UNDEFINED: + default: + data_uart_print("app_handle_test_case: TC_ROLE_UNDEFINED\r\n"); + return; + + case TC_ROLE_DUT: + { + + switch (test_case_id) + { + case TC_IDLE: + data_uart_print("select one test case:\r\n"); + break; + + case TC_0001_ADV_PERFORMANCE: + + break; + case TC_0002_ADV_STRESS_START_STOP: + break; + + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + break; + + case TC_0200_TP_NOTIFICATION_TX_01: + break; + case TC_0201_TP_INDICATION_TX_01: + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; +#if TC_206_SUPPORT + case TC_0206_TP_NOTIFICATION_TX_02: + tc_206_dump_result(); + break; +#endif +#if TC_207_SUPPORT + case TC_0207_TP_WRITE_COMMAND_RX_02: + tc_207_dump_result(); + break; +#endif +#if TC_208_SUPPORT + case TC_0208_TP_NOTIF_WRITE_CMD_TRX_02: + tc_208_dump_tx_result(); + tc_208_dump_rx_result(); + break; +#endif +#if TC_300_SUPPORT + case TC_0300_ADV_ONLY: + tc_300_dump_result(); + break; +#endif + +#if TC_301_SUPPORT + case TC_0301_ADV_DISC: + tc_301_dump_result(); + break; +#endif + +#if TC_400_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + tc_400_dump_result(); + break; +#endif + +#if TC_401_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + tc_401_dump_result(); + break; +#endif + +#if TC_500_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + tc_500_dump_result(); + break; +#endif + +#if TC_501_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + tc_501_dump_result(); + break; +#endif + +#if TC_502_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + tc_502_dump_result(); + break; +#endif + +#if TC_600_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + tc_600_dump_result(); + break; +#endif + +#if TC_601_SUPPORT + case TC_0601_IOP_PAIR_SC: + tc_601_dump_result(); + break; +#endif + +#if TC_700_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + break; + +#endif + + +#if TC_800_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + tc_800_dump_result(); + break; +#endif + +#if TC_801_SUPPORT + case TC_0801_IOP_PAIR_SC: + tc_801_dump_result(); + break; +#endif + +#if TC_900_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + break; +#endif + +#if TC_901_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + break; +#endif + +#if TC_1000_SUPPORT + case TC_1000_CP_TEST: + + break; +#endif +#if TC_1100_SUPPORT + case TC_1100_BT41_CONN_TEST: + tc_1100_dump_result(); + break; +#endif +#if TC_1101_SUPPORT + case TC_1101_BT41_TRX_STRESS_TEST: + tc_1101_dump_result(); + break; +#endif + default: + return; + } + } + break; + + case TC_ROLE_SUT: + { + switch (test_case_id) + { + case TC_IDLE: + data_uart_print("select one test case:\r\n"); + break; + + case TC_0001_ADV_PERFORMANCE: + break; + + case TC_0002_ADV_STRESS_START_STOP: + break; + + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + break; + + +#if TC_200_SUT_SUPPORT + case TC_0200_TP_NOTIFICATION_TX_01: + tc_200_sut_dump_result(); + break; +#endif +#if TC_206_SUT_SUPPORT + case TC_0206_TP_NOTIFICATION_TX_02: + tc_206_sut_dump_result(); + break; +#endif +#if TC_207_SUT_SUPPORT + case TC_0207_TP_WRITE_COMMAND_RX_02: + tc_207_sut_dump_result(); + break; +#endif +#if TC_208_SUT_SUPPORT + case TC_0208_TP_NOTIF_WRITE_CMD_TRX_02: + tc_208_sut_dump_tx_result(); + tc_208_sut_dump_rx_result(); + break; +#endif + case TC_0201_TP_INDICATION_TX_01: + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUT_SUPPORT + case TC_0300_ADV_ONLY: + tc_300_sut_dump_result(); + break; +#endif + +#if TC_301_SUT_SUPPORT + case TC_0301_ADV_DISC: + tc_301_sut_dump_result(); + break; +#endif + +#if TC_400_SUT_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + tc_400_sut_dump_result(); + break; +#endif + +#if TC_401_SUT_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + tc_401_sut_dump_result(); + break; +#endif + +#if TC_500_SUT_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + tc_500_sut_dump_result(); + break; +#endif + +#if TC_501_SUT_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + tc_501_sut_dump_result(); + break; +#endif + +#if TC_502_SUT_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + //tc_502_sut_dump_result(); + break; +#endif + +#if TC_600_SUT_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + tc_600_sut_dump_result(); + break; +#endif + +#if TC_601_SUT_SUPPORT + case TC_0601_IOP_PAIR_SC: + tc_601_sut_dump_result(); + break; +#endif + +#if TC_700_SUT_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + //tc_701_sut_dump_result(); + break; +#endif + +#if TC_800_SUT_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + tc_800_sut_dump_result(); + break; +#endif + +#if TC_801_SUT_SUPPORT + case TC_0801_IOP_PAIR_SC: + tc_801_sut_dump_result(); + break; +#endif + +#if TC_900_SUT_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + break; +#endif + +#if TC_901_SUT_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + break; +#endif + +#if TC_1000_SUT_SUPPORT + case TC_1000_CP_TEST: + break; +#endif +#if TC_1100_SUT_SUPPORT + case TC_1100_BT41_CONN_TEST: + tc_1100_sut_dump_result(); + break; +#endif +#if TC_1101_SUT_SUPPORT + case TC_1101_BT41_TRX_STRESS_TEST: + tc_1101_sut_dump_result(); + break; +#endif + default: + return; + } + } + } + + tc_dump_disc_reason(); +} + +void app_dump_cur_test_case(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_CUR_TEST_CASE test_case_id = TC_IDLE; + if (p_parse_value->param_count == 0) + { + test_case_id = app_get_cur_test_case(); + } + else + { + test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + } + app_dump_tc_status(test_case_id); +} + +bool app_set_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool ret = true; + if (p_parse_value->param_count == 1) + { + memcpy(g_cur_rembd, &tc_rembd_list[p_parse_value->dw_param[0]], 6); + } + else if (p_parse_value->param_count == 6) + { + g_cur_rembd[0] = p_parse_value->dw_param[5]; + g_cur_rembd[1] = p_parse_value->dw_param[4]; + g_cur_rembd[2] = p_parse_value->dw_param[3]; + g_cur_rembd[3] = p_parse_value->dw_param[2]; + g_cur_rembd[4] = p_parse_value->dw_param[1]; + g_cur_rembd[5] = p_parse_value->dw_param[0]; + } + else + { + ret = false; + } + + data_uart_print("g_cur_rembd: 0x%02x:%02x:%02x:%02x:%02x:%02x\r\n", + g_cur_rembd[5], g_cur_rembd[4], + g_cur_rembd[3], g_cur_rembd[2], + g_cur_rembd[1], g_cur_rembd[0]); + return ret; +} + +void app_handle_test_case(T_CUR_TEST_CASE test_case_id, T_CUR_DEVICE_ROLE role) +{ + switch (role) + { + case TC_ROLE_UNDEFINED: + data_uart_print("app_handle_test_case: TC_ROLE_UNDEFINED\r\n"); + break; + case TC_ROLE_DUT: + data_uart_print("app_handle_test_case: role TC_ROLE_DUT\r\n"); + break; + case TC_ROLE_SUT: + data_uart_print("app_handle_test_case: TC_ROLE_UNDEFINED\r\n"); + break; + + } +} +#if F_BT_DLPS_EN + +void app_set_dlps_mode(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + + if (p_parse_value->dw_param[0] == 0) + { + lps_mode_pause(); + data_uart_print("app_set_dlps_mode: Active Mode\r\n"); + } + else + { + uint16_t scan_interval = 400; + uint16_t scan_window = 200; + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + lps_mode_resume(); + data_uart_can_enter_dlps(true); + data_uart_print("app_set_dlps_mode: LPS Mode\r\n"); + } +} +#endif + +void app_set_cur_case(T_CUR_TEST_CASE test_case_id) +{ + g_cur_test_case = test_case_id; +} + +void app_select_cur_test_case(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_CUR_TEST_CASE test_case_id; + T_CUR_DEVICE_ROLE role; + + test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + role = app_get_cur_tc_role(); + + switch (role) + { + case TC_ROLE_UNDEFINED: + data_uart_print("app_handle_test_case: TC_ROLE_UNDEFINED\r\n"); + return; + + case TC_ROLE_DUT: + { + data_uart_print("app_handle_test_case: role TC_ROLE_DUT\r\n"); + app_display_case_details(test_case_id); + switch (test_case_id) + { +#if TC_0001_SUPPORT + case TC_0001_ADV_PERFORMANCE: + { + uint16_t advIntMin = 80; + uint16_t advIntMax = 80; + if (p_parse_value->param_count == 3) + { + advIntMin = p_parse_value->dw_param[1]; + advIntMax = p_parse_value->dw_param[2]; + } + tc_0001_adv_start(advIntMin, advIntMax); + } + break; +#endif + +#if TC_0002_SUPPORT + case TC_0002_ADV_STRESS_START_STOP: + { + uint16_t advIntMin = 80; + uint16_t advIntMax = 80; + uint32_t max_count = 1000; + if (p_parse_value->param_count == 4) + { + advIntMin = p_parse_value->dw_param[1]; + advIntMax = p_parse_value->dw_param[2]; + max_count = p_parse_value->dw_param[3]; + } + tc_0002_adv_start_stop_start(advIntMin, advIntMax, max_count); + } + break; +#endif + +#if TC_100_SUPPORT + case TC_0100_SCAN_PERFORMANCE: + { + + } + break; +#endif + +#if TC_101_SUPPORT + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + if (p_parse_value->param_count == 7) + { + + T_GAP_SCAN_MODE mode = (T_GAP_SCAN_MODE)p_parse_value->dw_param[1]; + uint16_t interval = p_parse_value->dw_param[2]; + uint16_t window = p_parse_value->dw_param[3]; + T_GAP_SCAN_FILTER_POLICY filter_policy = (T_GAP_SCAN_FILTER_POLICY) + p_parse_value->dw_param[4]; + uint8_t filter_duplicates = p_parse_value->dw_param[5]; + uint32_t max_count = p_parse_value->dw_param[6]; + tc_0101_scan_stress_enable_disable_start(mode, interval, window, + filter_policy, filter_duplicates, max_count); + + } + else + { + data_uart_print("invlid param count, shall be 7 param count\r\n"); + } + } + break; + +#endif + +#if TC_200_SUPPORT + + case TC_0200_TP_NOTIFICATION_TX_01: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t length = p_parse_value->dw_param[2]; + uint8_t tx_octets = p_parse_value->dw_param[3]; + bool test_drop_acl_data = false; + if (p_parse_value->param_count == 5) + { + test_drop_acl_data = p_parse_value->dw_param[4]; + } + tc_200_tp_notification_tx_init_config(interval, length, tx_octets, test_drop_acl_data); + tc_200_tp_notification_tx_start(); + } + + break; +#endif +#if TC_206_SUPPORT + + case TC_0206_TP_NOTIFICATION_TX_02: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t latency = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t mode = p_parse_value->dw_param[4]; + uint32_t count = p_parse_value->dw_param[5]; + uint8_t data_check = 0; + if (p_parse_value->param_count == 7) + { + data_check = p_parse_value->dw_param[6]; + } + tc_206_tp_notification_tx_init_config(interval, latency, length, mode, count, data_check); + tc_206_tp_notification_tx_start(); + } + + break; +#endif +#if TC_207_SUPPORT + case TC_0207_TP_WRITE_COMMAND_RX_02: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t latency = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t mode = p_parse_value->dw_param[4]; + uint32_t count = p_parse_value->dw_param[5]; + uint8_t data_check = 0; + if (p_parse_value->param_count == 7) + { + data_check = p_parse_value->dw_param[6]; + } + tc_207_tp_rx_init_config(interval, latency, length, mode, count, data_check); + tc_207_tp_rx_start(); + } + + break; +#endif +#if TC_208_SUPPORT + case TC_0208_TP_NOTIF_WRITE_CMD_TRX_02: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t latency = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t mode = p_parse_value->dw_param[4]; + uint32_t count = p_parse_value->dw_param[5]; + uint8_t data_check = 0; + if (p_parse_value->param_count == 7) + { + data_check = p_parse_value->dw_param[6]; + } + tc_208_tp_trx_init_config(interval, latency, length, mode, count, data_check); + tc_208_tp_trx_start(); + } + + break; +#endif + case TC_0201_TP_INDICATION_TX_01: + + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUPPORT + case TC_0300_ADV_ONLY: + { + uint32_t count = 10; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_300_adv_only_start(count); + } + break; +#endif + +#if TC_301_SUPPORT + case TC_0301_ADV_DISC: + { + uint32_t count = 10; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_301_adv_disc_start(count); + } + break; +#endif + +#if TC_400_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + { + uint32_t count = 10; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_400_start(count); + } + break; +#endif + +#if TC_401_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + { + uint32_t count = 10; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_401_start(count); + } + break; +#endif + +#if TC_500_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + + tc_500_salve_auto_adv_start(count); + } + break; +#endif + +#if TC_501_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + + tc_501_salve_auto_adv_with_sec_req_start(count); + } + break; +#endif + +#if TC_502_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + + tc_502_salve_auto_adv_start(count); + } + break; +#endif + +#if TC_600_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + tc_600_iop_android_legacl_pair_start(count); + } + break; +#endif + +#if TC_601_SUPPORT + case TC_0601_IOP_PAIR_SC: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + tc_601_iop_android_sc_pair_start(count); + } + break; +#endif + +#if TC_700_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + tc_700_stable_notification_tx_01_start(); + break; +#endif + +#if TC_800_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + tc_800_iop_android_legacl_pair_start(count); + } + break; +#endif + +#if TC_801_SUPPORT + case TC_0801_IOP_PAIR_SC: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + tc_801_iop_android_sc_pair_start(count); + } + break; +#endif + +#if TC_900_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + tc_900_privacy_slave(); + break; +#endif + +#if TC_901_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + tc_901_privacy_master(); + break; +#endif + +#if TC_1000_SUPPORT + case TC_1000_CP_TEST: + tc_1000_hw_init(); + tc_1000_start(); + break; + case TC_1001_CP_TEST: + tc_1001_start(); + break; + case TC_1002_CP_TEST: + tc_1002_start(); + break; + +#endif +#if TC_1100_SUPPORT + case TC_1100_BT41_CONN_TEST: + { + uint32_t count = 1000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + + tc_1100_start(count); + } + break; +#endif +#if TC_1101_SUPPORT + case TC_1101_BT41_TRX_STRESS_TEST: + { + uint32_t count = 1000; + uint16_t data_length = 0; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count >= 3) + { + data_length = p_parse_value->dw_param[2]; + } + data_uart_print("count %d, len %d\r\n", count, data_length); + + tc_1101_start(count, data_length); + } + break; +#endif +#if TC_1102_SUPPORT + case TC_1102_BT41_TP_TEST: + { + uint16_t data_length = 20; + + if (p_parse_value->param_count >= 2) + { + data_length = p_parse_value->dw_param[1]; + } + data_uart_print("len %d\r\n", data_length); + + tc_1102_start(data_length); + } + break; +#endif + +#if TC_1200_SUPPORT + case TC_1200_MULTI_LINK_4_MASTER: + { + tc_1200_start(1); + } + break; +#endif + +#if TC_1201_SUPPORT + case TC_1201_MULTI_LINK_4_MASTER: + { + tc_1201_start(1); + } + break; +#endif +#if TC_1202_SUPPORT + case TC_1202_MULTI_LINK_4_MASTER: + { + tc_1202_start(1); + } + break; +#endif +#if TC_1203_SUPPORT + case TC_1203_MULTI_LINK_4_MASTER: + { + tc_1203_start(1); + } + break; +#endif +#if TC_1204_SUPPORT + case TC_1204_MULTI_LINK_4_MASTER: + { + tc_1204_start(1); + } + break; +#endif +#if TC_1205_SUPPORT + case TC_1205_MULTI_LINK_4_MASTER: + { + tc_1205_start(1); + } + break; +#endif +#if TC_1206_SUPPORT + case TC_1206_MULTI_LINK_4_MASTER: + { + tc_1206_start(1); + } + break; +#endif +#if TC_1207_SUPPORT + case TC_1207_MULTI_LINK_4_MASTER: + { + tc_1207_start(1); + } + break; +#endif + + + default: + return; + } + } + break; + + case TC_ROLE_SUT: + { + data_uart_print("app_handle_test_case: TC_ROLE_SUT\r\n"); + app_display_case_details(test_case_id); + switch (test_case_id) + { + case TC_0001_ADV_PERFORMANCE: + break; + case TC_0002_ADV_STRESS_START_STOP: + break; +#if TC_100_SUPPORT + case TC_0100_SCAN_PERFORMANCE: + break; +#endif + +#if TC_101_SUPPORT + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + if (p_parse_value->param_count == 7) + { + T_GAP_SCAN_MODE mode = (T_GAP_SCAN_MODE)p_parse_value->dw_param[1]; + uint16_t interval = p_parse_value->dw_param[2]; + uint16_t window = p_parse_value->dw_param[3]; + T_GAP_SCAN_FILTER_POLICY filter_policy = (T_GAP_SCAN_FILTER_POLICY) + p_parse_value->dw_param[4]; + uint8_t filter_duplicates = p_parse_value->dw_param[5]; + uint32_t max_count = p_parse_value->dw_param[6]; + tc_0101_scan_stress_enable_disable_start(mode, interval, window, + filter_policy, filter_duplicates, max_count); + + } + else + { + data_uart_print("invlid param count, shall be 7 param count\r\n"); + } + } + break; +#endif + +#if TC_200_SUT_SUPPORT + case TC_0200_TP_NOTIFICATION_TX_01: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t mode = 0; + uint8_t mode_end = 0; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count >= 3) + { + mode = p_parse_value->dw_param[2]; + } + if (p_parse_value->param_count >= 4) + { + mode_end = p_parse_value->dw_param[3]; + } + + data_uart_print("count %d, mode %d\r\n", count, mode); + tc_200_sut_start(count, mode, mode_end, peer_addr); + } + break; +#endif +#if TC_206_SUT_SUPPORT + case TC_0206_TP_NOTIFICATION_TX_02: + { + uint8_t peer_addr[6] = {0}; + + memcpy(peer_addr, g_cur_rembd, 6); + + tc_206_sut_start(peer_addr); + } + break; +#endif +#if TC_207_SUT_SUPPORT + case TC_0207_TP_WRITE_COMMAND_RX_02: + { + uint8_t peer_addr[6] = {0}; + + memcpy(peer_addr, g_cur_rembd, 6); + + tc_207_sut_start(peer_addr); + } + break; +#endif +#if TC_208_SUT_SUPPORT + case TC_0208_TP_NOTIF_WRITE_CMD_TRX_02: + { + uint8_t peer_addr[6] = {0}; + + memcpy(peer_addr, g_cur_rembd, 6); + + tc_208_sut_start(peer_addr); + } + break; +#endif + case TC_0201_TP_INDICATION_TX_01: + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUT_SUPPORT + case TC_0300_ADV_ONLY: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count); + tc_300_sut_start(count, peer_addr); + } + break; +#endif + +#if TC_301_SUT_SUPPORT + case TC_0301_ADV_DISC: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_301_sut_start(count, peer_addr); + } + break; +#endif + +#if TC_400_SUT_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_400_sut_start(count, peer_addr); + } + break; +#endif + +#if TC_401_SUT_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_401_sut_start(count, peer_addr); + } + + break; +#endif + +#if TC_500_SUT_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_500_sut_start(count, peer_addr); + } + break; +#endif + +#if TC_501_SUT_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_501_sut_start(count, peer_addr); + } + break; +#endif + +#if TC_502_SUT_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + break; +#endif + +#if TC_600_SUT_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count); + tc_600_sut_iop_android_legacl_pair_start(count, peer_addr); + } + break; +#endif + +#if TC_601_SUT_SUPPORT + case TC_0601_IOP_PAIR_SC: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + + data_uart_print("count %d\r\n", count); + + tc_601_sut_iop_android_sc_pair_start(count, peer_addr); + } + break; +#endif + + + case TC_0700_STABLE_NOTIFICATION_TX_01: + //tc_700_stable_notification_tx_01_start(); + break; + + +#if TC_800_SUT_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count); + tc_800_sut_iop_android_legacl_pair_start(count, peer_addr); + } + break; +#endif + +#if TC_801_SUT_SUPPORT + case TC_0801_IOP_PAIR_SC: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + + data_uart_print("count %d\r\n", count); + + tc_801_sut_iop_android_sc_pair_start(count, peer_addr); + } + break; +#endif + +#if TC_900_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + tc_900_privacy_slave(); + break; + case TC_0901_PRIVACY_TEST_MASTER: + tc_901_privacy_master(); + break; +#endif + +#if TC_1000_SUPPORT + case TC_1000_CP_TEST: + tc_1000_hw_init(); + tc_1000_start(); + break; + case TC_1001_CP_TEST: + tc_1001_start(); + break; + case TC_1002_CP_TEST: + tc_1002_start(); + break; +#endif +#if TC_1100_SUT_SUPPORT + case TC_1100_BT41_CONN_TEST: + { + uint32_t count = 1000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count == 8) + { + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + } + + data_uart_print("count %d\r\n", count); + tc_1100_sut_start(count, peer_addr); + } + break; +#endif +#if TC_1101_SUT_SUPPORT + case TC_1101_BT41_TRX_STRESS_TEST: + { + uint32_t count = 1000; + uint8_t peer_addr[6] = {0}; + uint16_t data_len = 0; + + memcpy(peer_addr, g_cur_rembd, 6); + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + if (p_parse_value->param_count >= 3) + { + data_len = p_parse_value->dw_param[2]; + } + + data_uart_print("count %d\r\n", count); + tc_1101_sut_start(count, peer_addr, data_len); + } + break; +#endif +#if TC_1102_SUT_SUPPORT + case TC_1102_BT41_TP_TEST: + { + uint8_t peer_addr[6] = {0}; + memcpy(peer_addr, g_cur_rembd, 6); + + tc_1102_sut_start(peer_addr); + } + break; +#endif + +#if TC_1204_SUT_SUPPORT + case TC_1204_MULTI_LINK_4_MASTER: + { + tc_1204_sut_start(1); + } + break; +#endif + + default: + return; + } + } + break; + } + + + g_cur_test_case = test_case_id; +} + + + + +void app_tc_dut_add(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_CUR_TEST_CASE test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + + data_uart_print("app_tc_add: role TC_ROLE_DUT\r\n"); + + switch (test_case_id) + { +#if TC_0001_SUPPORT + case TC_0001_ADV_PERFORMANCE: + { + uint16_t advIntMin = 80; + uint16_t advIntMax = 80; + if (p_parse_value->param_count == 3) + { + advIntMin = p_parse_value->dw_param[1]; + advIntMax = p_parse_value->dw_param[2]; + } + tc_0001_add_case(advIntMin, advIntMax); + } + break; +#endif + +#if TC_0002_SUPPORT + case TC_0002_ADV_STRESS_START_STOP: + { + uint16_t advIntMin = 80; + uint16_t advIntMax = 80; + uint32_t max_count = 1000; + if (p_parse_value->param_count == 4) + { + advIntMin = p_parse_value->dw_param[1]; + advIntMax = p_parse_value->dw_param[2]; + max_count = p_parse_value->dw_param[3]; + } + tc_0002_add_case(advIntMin, advIntMax, max_count); + } + break; +#endif + +#if TC_100_SUPPORT + case TC_0100_SCAN_PERFORMANCE: + { + + } + break; +#endif + +#if TC_101_SUPPORT + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + if (p_parse_value->param_count == 7) + { + + T_GAP_SCAN_MODE mode = (T_GAP_SCAN_MODE)p_parse_value->dw_param[1]; + uint16_t interval = p_parse_value->dw_param[2]; + uint16_t window = p_parse_value->dw_param[3]; + T_GAP_SCAN_FILTER_POLICY filter_policy = (T_GAP_SCAN_FILTER_POLICY) + p_parse_value->dw_param[4]; + uint8_t filter_duplicates = p_parse_value->dw_param[5]; + uint32_t max_count = p_parse_value->dw_param[6]; + tc_0101_scan_stress_enable_disable_start(mode, interval, window, + filter_policy, filter_duplicates, max_count); + + } + else + { + data_uart_print("invlid param count, shall be 7 param count\r\n"); + } + } + break; +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + +#if TC_200_SUPPORT + case TC_0200_TP_NOTIFICATION_TX_01: + { + uint16_t interval = p_parse_value->dw_param[1]; + uint16_t length = p_parse_value->dw_param[2]; + uint8_t tx_octets = p_parse_value->dw_param[3]; + tc_200_tp_notification_tx_init_config(interval, length, tx_octets, false); + tc_200_tp_notification_tx_start(); + } + break; +#endif +#if TC_200_SUPPORT + case TC_0201_TP_INDICATION_TX_01: + break; +#endif + + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUPPORT + case TC_0300_ADV_ONLY: + { + uint32_t count = 10000; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_300_add_case(count); + } + break; +#endif + +#if TC_301_SUPPORT + case TC_0301_ADV_DISC: + { + uint32_t count = 10000; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_301_add_case(count); + } + break; +#endif + +#if TC_400_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + { + uint32_t count = 10000; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_400_add_case(count); + } + break; +#endif + +#if TC_401_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + { + uint32_t count = 10000; + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_401_add_case(count); + } + break; +#endif + +#if TC_500_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + + tc_500_add_case(count); + } + break; +#endif + +#if TC_501_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + uint32_t count = 10000; + + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + + tc_501_add_case(count); + } + break; +#endif + +#if TC_502_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + { + + } + break; +#endif + +#if TC_600_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + tc_600_add_case(count); + } + break; +#endif + +#if TC_601_SUPPORT + case TC_0601_IOP_PAIR_SC: + { + uint32_t count = 10000; + if (p_parse_value->param_count == 2) + { + count = p_parse_value->dw_param[1]; + } + data_uart_print("count %d\r\n", count); + tc_601_add_case(count); + } + break; +#endif + +#if TC_700_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + tc_700_stable_notification_tx_01_start(); + break; + +#endif + +#if TC_800_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + + data_uart_print("count %d\r\n", count); + tc_800_add_case(count); + } + break; +#endif + +#if TC_801_SUPPORT + case TC_0801_IOP_PAIR_SC: + { + uint32_t count = 10000; + + data_uart_print("count %d\r\n", count); + tc_801_add_case(count); + } + break; +#endif + +#if TC_900_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + tc_900_privacy_slave(); + break; +#endif + +#if TC_901_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + tc_901_privacy_master(); + break; +#endif +#endif + + +#if TC_1000_SUPPORT + +#if F_CP_TEST_SUPPORT + case TC_1000_CP_TEST: + tc_1000_hw_init(); + tc_1000_start(); + break; + case TC_1001_CP_TEST: + tc_1001_start(); + break; + case TC_1002_CP_TEST: + tc_1002_start(); + break; +#endif +#endif + + default: + return; + } +} + + +void app_tc_sut_add(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_CUR_TEST_CASE test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + + data_uart_print("app_handle_test_case: TC_ROLE_SUT\r\n"); + app_display_case_details(test_case_id); + switch (test_case_id) + { +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + +#if TC_0001_SUPPORT + case TC_0001_ADV_PERFORMANCE: + { + uint16_t advIntMin = 80; + uint16_t advIntMax = 80; + if (p_parse_value->param_count == 3) + { + advIntMin = p_parse_value->dw_param[1]; + advIntMax = p_parse_value->dw_param[2]; + } + tc_0001_add_case(advIntMin, advIntMax); + } + break; +#endif + +#if TC_0002_SUPPORT + case TC_0002_ADV_STRESS_START_STOP: + { + uint16_t advIntMin = 80; + uint16_t advIntMax = 80; + uint32_t max_count = 1000; + if (p_parse_value->param_count == 4) + { + advIntMin = p_parse_value->dw_param[1]; + advIntMax = p_parse_value->dw_param[2]; + max_count = p_parse_value->dw_param[3]; + } + tc_0002_add_case(advIntMin, advIntMax, max_count); + } + break; +#endif +#endif + +#if TC_100_SUPPORT + case TC_0100_SCAN_PERFORMANCE: + { + + } + break; +#endif + +#if TC_101_SUPPORT + case TC_0101_SCAN_STRESS_ENABLE_DISABLE: + { + if (p_parse_value->param_count == 7) + { + + T_GAP_SCAN_MODE mode = (T_GAP_SCAN_MODE)p_parse_value->dw_param[1]; + uint16_t interval = p_parse_value->dw_param[2]; + uint16_t window = p_parse_value->dw_param[3]; + T_GAP_SCAN_FILTER_POLICY filter_policy = (T_GAP_SCAN_FILTER_POLICY) + p_parse_value->dw_param[4]; + uint8_t filter_duplicates = p_parse_value->dw_param[5]; + uint32_t max_count = p_parse_value->dw_param[6]; + tc_0101_scan_stress_enable_disable_start(mode, interval, window, + filter_policy, filter_duplicates, max_count); + + } + else + { + data_uart_print("invlid param count, shall be 7 param count\r\n"); + } + } + break; +#endif + + + +#if TC_200_SUT_SUPPORT + case TC_0200_TP_NOTIFICATION_TX_01: + { + uint32_t count = 1; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_200_sut_add_case(count, g_cur_rembd); + } + break; +#endif + + case TC_0201_TP_INDICATION_TX_01: + break; + case TC_0202_TP_WRITE_COMMAND_TX_01: + break; + case TC_0203_TP_NOTIFICATION_RX_01: + break; + case TC_0204_TP_INDICATION_RX_01: + break; + case TC_0205_TP_WRITE_COMMAND_RX_01: + break; + +#if TC_300_SUT_SUPPORT + case TC_0300_ADV_ONLY: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + data_uart_print("count %d\r\n", count); + tc_300_sut_add_case(count, peer_addr); + } + break; +#endif + +#if TC_301_SUT_SUPPORT + case TC_0301_ADV_DISC: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_301_sut_add_case(count, peer_addr); + } + break; +#endif + +#if TC_400_SUT_SUPPORT + case TC_0400_CONN_PARAM_UPDATE_SLAVE: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_400_sut_add_case(count, peer_addr); + } + break; +#endif + +#if TC_401_SUT_SUPPORT + case TC_0401_CONN_PARAM_UPDATE_SLAVE_01: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_401_sut_add_case(count, peer_addr); + } + break; +#endif + +#if TC_500_SUT_SUPPORT + case TC_0500_SLAVE_AUTO_ADV: + { + uint32_t count = 10000; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_500_sut_add_case(count, g_cur_rembd); + } + + break; +#endif + +#if TC_501_SUT_SUPPORT + case TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ: + { + uint32_t count = 10000; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_501_sut_add_case(count, g_cur_rembd); + } + break; +#endif + +#if TC_502_SUT_SUPPORT + case TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV: + break; +#endif + +#if TC_600_SUT_SUPPORT + case TC_0600_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_600_sut_add_case(count, g_cur_rembd); + } + break; +#endif + +#if TC_601_SUT_SUPPORT + case TC_0601_IOP_PAIR_SC: + { + uint32_t count = 10000; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + data_uart_print("count %d\r\n", count); + tc_601_sut_add_case(count, g_cur_rembd); + } + break; +#endif + +#if TC_700_SUPPORT + case TC_0700_STABLE_NOTIFICATION_TX_01: + tc_700_stable_notification_tx_01_start(); + break; +#endif + +#if TC_800_SUT_SUPPORT + case TC_0800_IOP_PAIR_LEGACL: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_800_sut_add_case(count, peer_addr); + } + break; +#endif + +#if TC_801_SUT_SUPPORT + case TC_0801_IOP_PAIR_SC: + { + uint32_t count = 10000; + uint8_t peer_addr[6] = {0}; + uint8_t addr_len; + + if (p_parse_value->param_count >= 2) + { + count = p_parse_value->dw_param[1]; + } + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + peer_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1 + 2]; + } + + data_uart_print("count %d\r\n", count, peer_addr); + tc_801_sut_add_case(count, peer_addr); + } + break; +#endif + +#if TC_900_SUPPORT + case TC_0900_PRIVACY_TEST_SLAVE: + tc_900_privacy_slave(); + break; +#endif + +#if TC_901_SUPPORT + case TC_0901_PRIVACY_TEST_MASTER: + tc_901_privacy_master(); + break; +#endif + +#if TC_1000_SUPPORT +#if F_CP_TEST_SUPPORT + case TC_1000_CP_TEST: + tc_1000_hw_init(); + tc_1000_start(); + break; + case TC_1001_CP_TEST: + tc_1001_start(); + break; + case TC_1002_CP_TEST: + tc_1002_start(); + break; +#endif +#endif + + + + default: + return; + } +} + + +void app_tc_add(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_CUR_TEST_CASE test_case_id; + T_CUR_DEVICE_ROLE role; + + test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + role = app_get_cur_tc_role(); + + memset(&g_ble_disconn_reason, 0, sizeof(g_ble_disconn_reason)); + + switch (role) + { + case TC_ROLE_UNDEFINED: + data_uart_print("app_tc_add: TC_ROLE_UNDEFINED\r\n"); + return; + + case TC_ROLE_DUT: + app_tc_dut_add(p_parse_value); + break; + + case TC_ROLE_SUT: + app_tc_sut_add(p_parse_value); + break; + + default: + break; + } + + g_cur_test_case = test_case_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_case.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_case.h new file mode 100644 index 00000000..71486d7b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/ble_auto_test_case.h @@ -0,0 +1,231 @@ + +#ifndef _BLE_AUTO_TEST_CASE_H_ +#define _BLE_AUTO_TEST_CASE_H_ +#include "app_msg.h" +#include +#include +#include "user_cmd_parse.h" + +#define TC_0001_SUPPORT 0 +#define TC_0002_SUPPORT 0 +#define TC_100_SUPPORT 0 +#define TC_101_SUPPORT 0 +#define TC_200_SUPPORT 1 +#define TC_200_SUT_SUPPORT 1 +#define TC_206_SUPPORT 1 +#define TC_206_SUT_SUPPORT 1 +#define TC_207_SUPPORT 1 +#define TC_207_SUT_SUPPORT 1 +#define TC_208_SUPPORT 1 +#define TC_208_SUT_SUPPORT 1 +#define TC_300_SUPPORT 0 +#define TC_300_SUT_SUPPORT 0 +#define TC_301_SUPPORT 0 +#define TC_301_SUT_SUPPORT 0 +#define TC_310_SUPPORT 0 +#define TC_310_SUT_SUPPORT 0 +#define TC_311_SUPPORT 0 +#define TC_311_SUT_SUPPORT 0 +#define TC_400_SUPPORT 0 +#define TC_400_SUT_SUPPORT 0 +#define TC_401_SUPPORT 0 +#define TC_401_SUT_SUPPORT 0 +#define TC_500_SUPPORT 1 +#define TC_500_SUT_SUPPORT 1 +#define TC_501_SUPPORT 1 +#define TC_501_SUT_SUPPORT 1 +#define TC_502_SUPPORT 1 +#define TC_502_SUT_SUPPORT 0 +#define TC_600_SUPPORT 1 +#define TC_600_SUT_SUPPORT 1 +#define TC_601_SUPPORT 1 +#define TC_601_SUT_SUPPORT 1 +#define TC_700_SUPPORT 0 +#define TC_700_SUT_SUPPORT 0 +#if F_BT_LE_5_0_SUPPORT +#define TC_800_SUPPORT 0 +#define TC_800_SUT_SUPPORT 0 +#define TC_801_SUPPORT 0 +#define TC_801_SUT_SUPPORT 0 +#endif +#if F_BT_LE_PRIVACY_SUPPORT +#define TC_900_SUPPORT 0 +#define TC_900_SUT_SUPPORT 0 +#define TC_901_SUPPORT 0 +#define TC_901_SUT_SUPPORT 0 +#endif +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI +#define TC_1000_SUPPORT 0 +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#define TC_1100_SUPPORT 1 +#define TC_1100_SUT_SUPPORT 1 +#define TC_1101_SUPPORT 1 +#define TC_1101_SUT_SUPPORT 1 +#define TC_1102_SUPPORT 1 +#define TC_1102_SUT_SUPPORT 1 +#endif +#define TC_1200_SUPPORT 0 +#define TC_1201_SUPPORT 0 +#define TC_1202_SUPPORT 0 +#define TC_1203_SUPPORT 0 +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#define TC_1204_SUPPORT 1 +#define TC_1205_SUPPORT 1 +#define TC_1206_SUPPORT 1 +#endif +#define TC_1207_SUPPORT 0 +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#define TC_1204_SUT_SUPPORT 1 +#define TC_1205_SUT_SUPPORT 1 +#define TC_1206_SUT_SUPPORT 1 +#endif + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include +#endif + +#include + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include +#include +#include +#include +#include +#include +#include +#if F_BT_LE_5_0_SUPPORT +#include +#endif +#include +#include +#if F_BT_LE_4_1_CBC_SUPPORT +#include +#endif +#endif + +#if F_BT_LE_GAP_CENTRAL_SUPPORT +#include +#include +#include +#include +#include +#include +#if F_BT_LE_5_0_SUPPORT +#include +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#include +#endif +#endif + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint8_t TGATTDBdAddr[6]; +extern TGATTDBdAddr g_cur_rembd; + + +typedef enum +{ + TC_IDLE = 0x0000, + TC_0001_ADV_PERFORMANCE = 1, + TC_0002_ADV_STRESS_START_STOP, + + TC_0100_SCAN_PERFORMANCE = 100, + TC_0101_SCAN_STRESS_ENABLE_DISABLE, + + TC_0200_TP_NOTIFICATION_TX_01 = 200, + TC_0201_TP_INDICATION_TX_01, + + TC_0202_TP_WRITE_COMMAND_TX_01, + TC_0203_TP_NOTIFICATION_RX_01, + TC_0204_TP_INDICATION_RX_01, + TC_0205_TP_WRITE_COMMAND_RX_01, + + TC_0206_TP_NOTIFICATION_TX_02, + TC_0207_TP_WRITE_COMMAND_RX_02, + TC_0208_TP_NOTIF_WRITE_CMD_TRX_02, + + TC_0300_ADV_ONLY = 300, + TC_0301_ADV_DISC, + + TC_0310_2M_LONGRANGE_1 = 310, + TC_0311_2M_LONGRANGE_2, + + TC_0400_CONN_PARAM_UPDATE_SLAVE = 400,//10 + TC_0401_CONN_PARAM_UPDATE_SLAVE_01, + + TC_0500_SLAVE_AUTO_ADV = 500, + TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ, + TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV, + + TC_0600_IOP_PAIR_LEGACL = 600, + TC_0601_IOP_PAIR_SC, + + TC_0700_STABLE_NOTIFICATION_TX_01 = 700, + + TC_0800_IOP_PAIR_LEGACL = 800, + TC_0801_IOP_PAIR_SC, + + TC_0900_PRIVACY_TEST_SLAVE = 900, + TC_0901_PRIVACY_TEST_MASTER, + + TC_1000_CP_TEST = 1000, + TC_1001_CP_TEST = 1001, + TC_1002_CP_TEST = 1002, + + TC_1100_BT41_CONN_TEST = 1100, + TC_1101_BT41_TRX_STRESS_TEST = 1101, + TC_1102_BT41_TP_TEST = 1102, + + TC_1200_MULTI_LINK_4_MASTER = 1200, + TC_1201_MULTI_LINK_4_MASTER, + TC_1202_MULTI_LINK_4_MASTER, + TC_1203_MULTI_LINK_4_MASTER, + TC_1204_MULTI_LINK_4_MASTER, + TC_1205_MULTI_LINK_4_MASTER, + TC_1206_MULTI_LINK_4_MASTER, + TC_1207_MULTI_LINK_4_MASTER, + + + TC_MAX = 65535 +} T_CUR_TEST_CASE; + + +typedef enum _T_CUR_DEVICE_ROLE +{ + TC_ROLE_UNDEFINED, + TC_ROLE_DUT, + TC_ROLE_SUT +} T_CUR_DEVICE_ROLE; + +T_CUR_DEVICE_ROLE app_get_cur_tc_role(void); +void app_set_cur_tc_role(T_CUR_DEVICE_ROLE role); + +T_CUR_TEST_CASE app_get_cur_test_case(void); +void app_set_dlps_mode(T_USER_CMD_PARSED_VALUE *p_parse_value); +void app_select_cur_test_case(T_USER_CMD_PARSED_VALUE *p_parse_value); +void app_dump_cur_test_case(T_USER_CMD_PARSED_VALUE *p_parse_value); +bool app_set_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value); +void app_set_cur_case(T_CUR_TEST_CASE test_case_id); + + +/** + common api +*/ +uint32_t os_time_get_elapsed(uint32_t begin, uint32_t end); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/cmd/user_cmd.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/cmd/user_cmd.c new file mode 100644 index 00000000..eb22f19b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/cmd/user_cmd.c @@ -0,0 +1,1556 @@ +/** +************************************************************************************************************ +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +************************************************************************************************************ +* @file user_cmd.c +* @brief User defined profile test commands. +* @details User command interfaces. +* @author +* @date 2016-02-18 +* @version v0.1 +************************************************************************************************************* +*/ +#include +#include "trace_app.h" +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#include "vendor_tp_client.h" +#include "vendor_pxpext_client.h" +#include +#endif +#include "gap_bond_le.h" +#include "gap_scan.h" +#include "user_cmd.h" +#include "gap.h" +#include "link_mgr.h" + +#include "ble_auto_test_application.h" +#include "gap_adv.h" +#include "gap_le.h" +#include "gap_conn_le.h" +#include +#include "privacy_mgnt.h" +#include "gap_storage_le.h" + + +T_USER_CMD_IF user_cmd_if; +extern uint8_t gSimpleProfileServiceId; + + +/** + * @brief print project related string. + * + * @param none. + * @return print project related string. +*/ +char *User_CmdProjectInfo(void) +{ + static char *pStr; + pStr = "ble_auto_test"; + return (pStr); +} + +static T_USER_CMD_PARSE_RESULT cmd_reset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if UPPER_STACK_USE_VIRTUAL_HCI + WDG_SystemReset(RESET_ALL); + return (RESULT_SUCESS); +#else + //NVIC_SystemReset(); + return RESULT_CMD_NOT_SUPPORT; +#endif +} + +static T_USER_CMD_PARSE_RESULT cmd_dlps_mode(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_DLPS_EN + app_set_dlps_mode(p_parse_value); + return (RESULT_SUCESS); +#else + return RESULT_ERR; +#endif +} + +static T_USER_CMD_PARSE_RESULT UserCmdSelectTestCase(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + app_select_cur_test_case(p_parse_value); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_dump(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + app_dump_cur_test_case(p_parse_value); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_rembd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_USER_CMD_PARSE_RESULT result = RESULT_SUCESS; + bool ret; + + ret = app_set_rembd(p_parse_value); + if (ret == false) + { + result = RESULT_ERR; + } + return result; +} + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_role(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + + T_CUR_DEVICE_ROLE role; + role = (T_CUR_DEVICE_ROLE)p_parse_value->dw_param[0]; + app_set_cur_tc_role(role); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_add(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint32_t count = 10; + if (p_parse_value->param_count >= 1) + { + count = p_parse_value->dw_param[0]; + } + + tc_add_case(count); + return (RESULT_SUCESS); +} + +extern void app_tc_add(T_USER_CMD_PARSED_VALUE *p_parse_value); +static T_USER_CMD_PARSE_RESULT user_cmd_tc_tcqueue(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + app_tc_add(p_parse_value); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT user_cmd_tc_auto(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + tc_start_next_case(); + return (RESULT_SUCESS); +} + + +static T_USER_CMD_PARSE_RESULT UserCmdLogOn(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 1); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 1); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 1); + data_uart_print("Log On Sucess\r\n"); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdLogOff(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 0); + data_uart_print("Log Off Sucess\r\n"); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_showcon(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = 0; + T_GAP_CONN_INFO conn_info; + for (conn_id = 0; conn_id < 4; conn_id++) + { + if (le_get_conn_info(conn_id, &conn_info)) + { + data_uart_print("ShowCon conn_id = %d state = 0x%x role = %d\r\n", conn_id, + conn_info.conn_state, conn_info.role); + data_uart_print("RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + conn_info.remote_bd[5], conn_info.remote_bd[4], + conn_info.remote_bd[3], conn_info.remote_bd[2], + conn_info.remote_bd[1], conn_info.remote_bd[0], + conn_info.remote_bd_type); + } + } + return (RESULT_SUCESS); +} +#if F_BT_LE_GAP_CENTRAL_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_con(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t DestAddr[6] = {0}; + uint8_t addr_len; + uint8_t DestAddrType = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + data_uart_print("cmd_con\r\n"); + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + DestAddr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + if (p_parse_value->param_count >= 7) + { + DestAddrType = p_parse_value->dw_param[6]; + } + + le_connect(0, DestAddr, (T_GAP_REMOTE_ADDR_TYPE)DestAddrType, GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + + return (RESULT_SUCESS); +} + + + +static T_USER_CMD_PARSE_RESULT cmd_condev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + data_uart_print("UserCmdConnect\r\n"); + if (p_parse_value->dw_param[0] < dev_list_count) + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, dev_list[p_parse_value->dw_param[0]].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[p_parse_value->dw_param[0]].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + } + else + { + return RESULT_ERR; + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_chanclassset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t chanMap[5] = {0}; + uint8_t i; + for (i = 0; i < 5; i++) + { + chanMap[i] = (uint8_t)p_parse_value->dw_param[i]; + } + chanMap[4] = chanMap[4] & 0x1F; + + if (le_set_host_chann_classif(chanMap) == GAP_CAUSE_ERROR_UNKNOWN) + { + data_uart_print("cmd_chanclassset Fail!!!\r\n"); + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_disc(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_disconnect(p_parse_value->dw_param[0]); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_iocapset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t ioCap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + if (p_parse_value->param_count >= 1) + { + switch (p_parse_value->dw_param[0]) + { + case 0: + ioCap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + data_uart_print("GAP_IO_CAP_NO_INPUT_NO_OUTPUT\r\n"); + break; + case 1: + ioCap = GAP_IO_CAP_DISPLAY_ONLY; + data_uart_print("GAP_IO_CAP_DISPLAY_ONLY\r\n"); + break; + case 2: + ioCap = GAP_IO_CAP_KEYBOARD_ONLY; + data_uart_print("GAP_IO_CAP_KEYBOARD_ONLY\r\n"); + break; + case 3: + ioCap = GAP_IO_CAP_DISPLAY_YES_NO; + data_uart_print("GAP_IO_CAP_DISPLAY_YES_NO\r\n"); + break; + case 4: + ioCap = GAP_IO_CAP_KEYBOARD_DISPLAY; + data_uart_print("GAP_IO_CAP_KEYBOARD_DISPLAY\r\n"); + break; + default: + data_uart_print("GAP_IO_CAP parameter error!!!\r\n"); + break; + } + } + else + { + data_uart_print("GAP_IO_CAP_NO_INPUT_NO_OUTPUT\r\n"); + } + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap); + gap_set_pairable_mode(); + + return (RESULT_SUCESS); +} + +#if F_BT_LE_GAP_SCAN_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_scan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t scan_mode = GAP_SCAN_MODE_PASSIVE; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + if (p_parse_value->param_count > 0) + { + scan_mode = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + scan_filter_policy = p_parse_value->dw_param[1]; + } + link_mgr_clear_device_list(); + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_start(); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_stopscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_scan_stop(); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_showdev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + data_uart_print("Advertising and Scan response: filter uuid = 0xA00A dev list\r\n"); + for (i = 0; i < dev_list_count; i++) + { + data_uart_print("RemoteBd[%d] = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", i, + dev_list[i].bd_addr[5], dev_list[i].bd_addr[4], + dev_list[i].bd_addr[3], dev_list[i].bd_addr[2], + dev_list[i].bd_addr[1], dev_list[i].bd_addr[0], + dev_list[i].bd_type); + } + + return (RESULT_SUCESS); +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_sauth(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_bond_pair(p_parse_value->dw_param[0]); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdUpdateConnParam(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint16_t desired_min_interval = p_parse_value->dw_param[1]; + uint16_t desired_max_interval = p_parse_value->dw_param[2]; + uint16_t desired_slave_latency = p_parse_value->dw_param[3]; + uint16_t desired_conn_timeout = p_parse_value->dw_param[4]; + + le_update_conn_param(p_parse_value->dw_param[0], + desired_min_interval, + desired_max_interval, + desired_slave_latency, + desired_conn_timeout, + 2 * (desired_min_interval - 1), + 2 * (desired_min_interval - 1) + ); + return (RESULT_SUCESS); +} +static T_USER_CMD_PARSE_RESULT UserCmdAddToWhitelist(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CONN_INFO conn_info; + if (conn_id >= APP_MAX_LINKS) + { + return RESULT_ERR; + } + le_get_conn_info(conn_id, &conn_info); + le_modify_white_list(GAP_WHITE_LIST_OP_ADD, conn_info.remote_bd, + (T_GAP_REMOTE_ADDR_TYPE)conn_info.remote_bd_type); + return (RESULT_SUCESS); + +} +#if F_BT_LE_GATT_CLIENT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_gapdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + gaps_start_discovery(p_parse_value->dw_param[0]); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_gapread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char to be read. */ + T_GAPS_READ_TYPE read_char_type = (T_GAPS_READ_TYPE)p_parse_value->dw_param[1]; + + + gaps_read(p_parse_value->dw_param[0], read_char_type); + + return (RESULT_SUCESS); +} +#endif +static T_USER_CMD_PARSE_RESULT UserCmdTxPowerSet(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if 0 + uint8_t type = p_parse_value->dw_param[0]; + uint8_t tx_gain = p_parse_value->dw_param[1]; + + + le_adv_set_tx_power((T_LE_ADV_TX_POW_TYPE)type, tx_gain); +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_rssiread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + + le_read_rssi(p_parse_value->dw_param[0]); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdSetLocalType(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_PUBLIC; + if (p_parse_value->dw_param[0] > 3) + { + return RESULT_ERR; + } + local_bd_type = p_parse_value->dw_param[0]; + if (local_bd_type == GAP_LOCAL_ADDR_LE_RANDOM) + { + uint8_t random_addr[6] = {0}; + if (p_parse_value->dw_param[1] == GAP_RAND_ADDR_STATIC) + { + random_addr[0] = 0x4E; + random_addr[1] = 0xEF; + random_addr[2] = 0x3B; + random_addr[3] = 0x58; + random_addr[4] = 0xFA; + random_addr[5] = 0xFF; + } + else + { + le_gen_rand_addr((T_GAP_RAND_ADDR_TYPE)p_parse_value->dw_param[1], random_addr); + } + data_uart_print("set local random addr:0x%02x%02x%02x%02x%02x%02x\r\n", + random_addr[5], + random_addr[4], + random_addr[3], + random_addr[2], + random_addr[1], + random_addr[0]); + le_set_rand_addr(random_addr); + } + + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdSetRandom(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t random_addr[6] = {0}; + if (p_parse_value->dw_param[0] > 2) + { + return RESULT_ERR; + } + le_gen_rand_addr((T_GAP_RAND_ADDR_TYPE)p_parse_value->dw_param[0], random_addr); + le_set_rand_addr(random_addr); + return (RESULT_SUCESS); +} +#if F_BT_LE_READ_CHANN_MAP +static T_USER_CMD_PARSE_RESULT UserCmdReadChanMap(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + + le_read_chann_map(p_parse_value->dw_param[0]); + + return (RESULT_SUCESS); +} +#endif +static T_USER_CMD_PARSE_RESULT UserCmdPatchVerGet(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //uint16_t patch_version = get_image_version(SIGNATURE_PATCH_FLASH); + + //p_user_cmd_if->cPrompt); + + return (RESULT_SUCESS); +} +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT +static T_USER_CMD_PARSE_RESULT UserCmdSetDataLength(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint16_t txOctets = p_parse_value->dw_param[1]; + uint16_t txTime = p_parse_value->dw_param[2]; + + le_set_data_len(p_parse_value->dw_param[0], + txOctets, + txTime); + return (RESULT_SUCESS); +} +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT +static T_USER_CMD_PARSE_RESULT UserCmdReadAdvPower(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + + le_adv_read_tx_power(); + + return (RESULT_SUCESS); +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +static T_USER_CMD_PARSE_RESULT cmd_latency(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_disable_slave_latency(p_parse_value->dw_param[0], p_parse_value->dw_param[1]); + return (RESULT_SUCESS); +} +#endif +static T_USER_CMD_PARSE_RESULT UserCmdLpsCmd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if 0 + bool lpscmd = (bool)p_parse_value->dw_param[0]; + uint8_t *yesStr = "yes"; + uint8_t *noStr = "no"; + + dataUARTCmdPrint(p_user_cmd_if, "UserCmdLpsCmd: enable DLPS? %s\r\n", + (lpscmd == 0) ? noStr : yesStr); + + if (lpscmd) + { + LPS_MODE_Resume(); + } + else + { + LPS_MODE_Pause(); + } +#endif + return (RESULT_SUCESS); +} + + + +static T_USER_CMD_PARSE_RESULT cmd_authmode(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //configure parameter first + uint8_t pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_MITM_FLAG; + uint8_t io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t oob_enable = false; + uint8_t secReqEnable = false; + uint16_t secReqRequirement = GAP_AUTHEN_BIT_MITM_FLAG; + + if (p_parse_value->param_count > 0) + { + auth_flags = p_parse_value->dw_param[0]; + secReqRequirement = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + io_cap = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + secReqEnable = p_parse_value->dw_param[2]; + } + if (p_parse_value->param_count > 3) + { + oob_enable = p_parse_value->dw_param[3]; + } + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(uint8_t), &pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(uint16_t), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(uint8_t), &io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &secReqRequirement); + gap_set_pairable_mode(); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdGetBondDevInfo(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_LE_KEY_ENTRY *p_entry = le_get_high_priority_bond(); + if (p_entry != NULL) + { + data_uart_print("UserCmdGetBondDevInfo: 0x%02x%02x%02x%02x%02x%02x, addr_type:%d\r\n", + p_entry->remote_bd.addr[5], + p_entry->remote_bd.addr[4], + p_entry->remote_bd.addr[3], + p_entry->remote_bd.addr[2], + p_entry->remote_bd.addr[1], + p_entry->remote_bd.addr[0], + p_entry->remote_bd.remote_bd_type); + } + else + { + data_uart_print("UserCmdGetBondDevInfo no exist\r\n"); + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdEraseBondDev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_bond_clear_all_keys(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_userconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CFM_CAUSE cause = GAP_CFM_CAUSE_ACCEPT; + if (p_parse_value->dw_param[1] == 0) + { + cause = GAP_CFM_CAUSE_REJECT; + } + le_bond_user_confirm(p_parse_value->dw_param[0], cause); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_authkey(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_bond_passkey_input_confirm(p_parse_value->dw_param[0], p_parse_value->dw_param[1], + GAP_CFM_CAUSE_ACCEPT); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdInitStartAdv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_adv_start(); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_adv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + T_GAP_CAUSE cause; + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = (uint16_t)p_parse_value->dw_param[0]; + uint16_t advIntMax = (uint16_t)p_parse_value->dw_param[1]; + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + cause = le_adv_start(); + if (cause == GAP_CAUSE_SUCCESS) + { + return (RESULT_SUCESS); + } + else + { + data_uart_print("cause %d\r\n", cause); + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_stopadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_adv_stop(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_advld(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t advEventType = GAP_ADTYPE_ADV_LDC_DIRECT_IND; + uint8_t advDirectAddrType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint16_t advIntMin = 0x80; + uint16_t advIntMax = 0x80; + + + //get connected device address and address type + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR_TYPE, &advDirectAddrType); + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR, &advDirectAddr); + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectAddrType), + &advDirectAddrType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_start(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_advhd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t advEventType = GAP_ADTYPE_ADV_HDC_DIRECT_IND; + uint8_t advDirectAddrType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t addr_len; + + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + advDirectAddr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + + //get connected device address and address type + //le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR_TYPE, &whiteListAddrType); + //le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR, &whiteListAddr); + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectAddrType), + &advDirectAddrType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + + le_adv_start(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_advscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + uint8_t advEventType = GAP_ADTYPE_ADV_SCAN_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = 0x80; + uint16_t advIntMax = 0x80; + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_start(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_advnonconn(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + uint8_t advEventType = GAP_ADTYPE_ADV_NONCONN_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = 0x80; + uint16_t advIntMax = 0x80; + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_start(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdStartAdvWithWL(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_WHITE_LIST_ALL; + uint16_t advIntMin = 0x80; + uint16_t advIntMax = 0x80; + + T_GAP_REMOTE_ADDR_TYPE whiteListAddrType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t whiteListAddr[GAP_BD_ADDR_LEN] = {0}; + + //get connected device address and address type + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR_TYPE, &whiteListAddrType); + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR, &whiteListAddr); + + le_modify_white_list(GAP_WHITE_LIST_OP_ADD, whiteListAddr, whiteListAddrType); + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_start(); + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdStartAdvSet(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = 0x80; + uint16_t advIntMax = 0x80; + + + //get connected device address and address type + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_update_param(); + + return (RESULT_SUCESS); +} +#if F_BT_LE_PRIVACY_SUPPORT +static T_USER_CMD_PARSE_RESULT UserCmdStartAdvRel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t advDirectType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + + if (p_parse_value->param_count > 0) + { + advEventType = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + advFilterPolicy = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + uint8_t idx = p_parse_value->dw_param[2]; + if (privacy_table[idx].is_used == true) + { + advDirectType = privacy_table[idx].remote_bd_type; + memcpy(advDirectAddr, privacy_table[idx].addr, 6); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + + advFilterPolicy = p_parse_value->dw_param[2]; + } + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectType), &advDirectType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + + le_adv_start(); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdReadlra(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + + if (privacy_table[idx].is_used) + { + le_privacy_read_local_resolv_addr((T_GAP_IDENT_ADDR_TYPE)privacy_table[idx].remote_bd_type, + privacy_table[idx].addr); + return (RESULT_SUCESS); + } + return (RESULT_ERR); + +} + +static T_USER_CMD_PARSE_RESULT UserCmdReadpra(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + + if (privacy_table[idx].is_used) + { + le_privacy_read_peer_resolv_addr(privacy_table[idx].remote_bd_type, + privacy_table[idx].addr); + return (RESULT_SUCESS); + } + return (RESULT_ERR); +} + +static T_USER_CMD_PARSE_RESULT UserCmdSetrea(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool enable = true; + if (p_parse_value->dw_param[0] == 0) + { + enable = false; + } + le_privacy_set_addr_resolution(enable); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdShowRel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + data_uart_print("show resolved list\r\n"); + + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used) + { + data_uart_print("rel[%d] RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d is_add_to_list=%d pending=%d\r\n", + i, + privacy_table[i].addr[5], privacy_table[i].addr[4], + privacy_table[i].addr[3], privacy_table[i].addr[2], + privacy_table[i].addr[1], privacy_table[i].addr[0], + privacy_table[i].remote_bd_type, + privacy_table[i].is_add_to_list, + privacy_table[i].pending); + } + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdSetPrivacy(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + uint8_t mode = p_parse_value->dw_param[1]; + data_uart_print("show resolved list\r\n"); + if (privacy_table[idx].is_used) + { + le_privacy_set_mode((T_GAP_IDENT_ADDR_TYPE)privacy_table[idx].remote_bd_type, + privacy_table[idx].addr, + (T_GAP_PRIVACY_MODE)mode); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdAddRelToWhitelist(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t idx = p_parse_value->dw_param[1]; + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + le_modify_white_list(op, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + } + else + { + if (privacy_table[idx].is_used) + { + le_modify_white_list(op, privacy_table[idx].addr, + (T_GAP_REMOTE_ADDR_TYPE)privacy_table[idx].remote_bd_type); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + } + return (RESULT_SUCESS); + +} + +static T_USER_CMD_PARSE_RESULT UserCmdConnectRelDev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + + if (privacy_table[idx].is_used) + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + le_connect(0, privacy_table[idx].addr, + (T_GAP_REMOTE_ADDR_TYPE)privacy_table[idx].remote_bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + } + else + { + return RESULT_ERR; + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdSetLocalIrk(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_LOCAL_IRK irk; + uint8_t type = p_parse_value->dw_param[0]; + + if (type == 0) + + { + memset(irk.local_irk, 0, 16); + } + else if (type == 1) + { + memset(irk.local_irk, 0x02, 16); + } + else + { + uint8_t i = 0; + for (i = 0; i < 16; i++) + { + irk.local_irk[i] = i; + } + } + flash_save_local_irk(&irk); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdSetRemoteIrk(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if 0 + T_LE_KEY_ENTRY *p_entry = NULL; + //uint8_t remote_BD[6] = {0xEF, 0x24, 0x45, 0x67, 0x89, 0xAB}; + uint8_t remote_BD[6] = {0xAB, 0x89, 0x67, 0x45, 0x24, 0xEF}; + T_GAP_REMOTE_ADDR_TYPE remote_BD_Type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_LE_REMOTE_IRK p_irk; + p_entry = le_allocate_key_entry(remote_BD, remote_BD_Type); +#if 0 + p_irk.addr[0] = 0xEF; + p_irk.addr[1] = 0x24; + p_irk.addr[2] = 0x45; + p_irk.addr[3] = 0x67; + p_irk.addr[4] = 0x89; + p_irk.addr[5] = 0xAB; +#endif + p_irk.addr[0] = 0xAB; + p_irk.addr[1] = 0x89; + p_irk.addr[2] = 0x67; + p_irk.addr[3] = 0x45; + p_irk.addr[4] = 0x24; + p_irk.addr[5] = 0xEF; + p_irk.addr_type = 0; + //memset(p_irk.key, 0x2,16); + p_irk.key[0] = 0x00; + p_irk.key[1] = 0x11; + p_irk.key[2] = 0x22; + p_irk.key[3] = 0x33; + p_irk.key[4] = 0x44; + p_irk.key[5] = 0x55; + p_irk.key[6] = 0x66; + p_irk.key[7] = 0x77; + p_irk.key[8] = 0x88; + p_irk.key[9] = 0x99; + p_irk.key[10] = 0xAA; + p_irk.key[11] = 0xBB; + p_irk.key[12] = 0xCC; + p_irk.key[13] = 0xDD; + p_irk.key[14] = 0xEE; + p_irk.key[15] = 0xFF; + + if (p_entry != NULL) + { + le_save_key(p_entry, BTIF_LINK_KEY_LE_REMOTE_IRK, 24, + (uint8_t *)&p_irk); + } + else + { + return RESULT_ERR; + } +#endif + return (RESULT_SUCESS); +} +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +static T_USER_CMD_PARSE_RESULT UserCmdTpDis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + tp_client_start_discovery(conn_id); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdTpWrite(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t data[270]; + uint16_t length = 10; + uint16_t i; + if (p_parse_value->param_count > 1) + { + length = p_parse_value->dw_param[1]; + } + for (i = 0; i < length; i++) + { + data[i] = i; + } + tp_client_write_value(p_parse_value->dw_param[0], length, data); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT UserCmdPxpDis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + vendor_pxpext_start_discovery(conn_id); + return (RESULT_SUCESS); +} +static T_USER_CMD_PARSE_RESULT UserCmdPxpWrite(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t data[270]; + uint16_t length = 10; + uint16_t i; + if (p_parse_value->param_count > 1) + { + length = p_parse_value->dw_param[1]; + } + for (i = 0; i < length; i++) + { + data[i] = i; + } + vendor_pxpext_write_value(p_parse_value->dw_param[0], length, data); + return (RESULT_SUCESS); +} +static T_USER_CMD_PARSE_RESULT UserCmdPxpRead(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + vendor_pxpext_read_value(conn_id); + return (RESULT_SUCESS); +} +#endif +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const T_USER_CMD_TABLE_ENTRY user_cmd_table[] = +{ + /********************************Common*********************************/ + + { + "reset", + "reset\n\r", + "reset\n\r", + cmd_reset + }, + + { + "dlps", + "dlps [mode]\n\r", + "dlps\n\r", + cmd_dlps_mode + }, + + { + "tc", + "testcase [index]\n\r", + "testcase\n\r", + UserCmdSelectTestCase + }, + { + "tcrole", + "tcrole [role]\n\r", + "tcrole\n\r", + user_cmd_tc_role + }, + { + "tcdump", + "tcdump [index]\n\r", + "tcdump\n\r", + user_cmd_tc_dump + }, + + { + "rembd", + "rembd [index]\n\r", + "rembd\n\r", + user_cmd_tc_rembd + }, + + + + { + "tcadd", + "tcadd [index]\n\r", + "tcadd\n\r", + user_cmd_tc_add + }, + { + "tcqueue", + "tcqueue [index]\n\r", + "tcqueue\n\r", + user_cmd_tc_tcqueue + }, + { + "tcauto", + "tcauto [index]\n\r", + "tcauto\n\r", + user_cmd_tc_auto + }, + + { + "logon", + "logon\n\r", + "logon\n\r", + UserCmdLogOn + }, + { + "logoff", + "logoff\n\r", + "logoff\n\r", + UserCmdLogOff + }, + { + "patchver", + "patchver\n\r", + "Get the patch Version\n\r", + UserCmdPatchVerGet + }, + { + "txpwrset", + "txpwrset [txpwridx]\n\r", + "Set the TX Power of BLE RF\n\r", + UserCmdTxPowerSet + }, + { + "rssiread", + "rssiread [conn_id]\n\r", + "Read the RSSI value of this local MDL ID\n\r", + cmd_rssiread + }, + { + "setrandom", + "setrandom [type]\n\r", + "set random address type: 0-static, 1-non-resolved, 2-resolved\n\r", + UserCmdSetRandom + }, + { + "setlocaltype", + "setlocaltype [type]\n\r", + "set local address type: 0-public, 1-random, 2-resolved or public 3- resolved or random\n\r", + UserCmdSetLocalType + }, +#if F_BT_LE_READ_CHANN_MAP + { + "readchanmap", + "readchanmap [conn_id]\n\r", + "read channel map\n\r", + UserCmdReadChanMap + }, +#endif + { + "addwl", + "addwl [conn_id]\n\r", + "add remote BD to whitelist\n\r", + UserCmdAddToWhitelist + }, + { + "dlps", + "dlps [cmd]\n\r", + "Set dlps mode\n\r", + UserCmdLpsCmd + }, + { + "showcon", + "showcon\n\r", + "Show all device connecting status\n\r", + cmd_showcon + }, + { + "disc", + "disc [conn_id]\n\r", + "disconnect to remote device\n\r", + cmd_disc + }, + { + "authmode", + "authmode [auth_flags] [io_cap] [sec enable]\n\r", + "set auth mode\n\r", + cmd_authmode + }, + { + "iocapset", + "iocapset [iocap]\n\r", + "choose io capability.\n\r", + cmd_iocapset + }, + { + "sauth", + "sauth [conn_id]\n\r", + "bond manager authentication request.\n\r", + cmd_sauth + }, + { + "bonddevget", + "bonddevget\n\r", + "Get Bonded device information\n\r", + UserCmdGetBondDevInfo + }, + { + "bonddeverase", + "bonddeverase\n\r", + "Erase Bonded device information\n\r", + UserCmdEraseBondDev + }, + { + "userconf", + "userconf [conn_id] [0/1]\n\r", + "Send user confirmation 0-reject 1-accept\n\r", + cmd_userconf + }, + { + "authkey", + "authkey [conn_id] [key]\n\r", + "input key\n\r", + cmd_authkey + }, + { + "conupdreq", + "conupdreq [conn_id] [Interval_min] [Interval_max] [latency] [suptimeout]\n\r", + "Update connection parameter\n\r", + UserCmdUpdateConnParam + }, + { + "addwl", + "addwl [conn_id]\n\r", + "add remote BD to whitelist\n\r", + UserCmdAddToWhitelist + }, + /********************************Central*********************************/ +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + { + "setdatalength", + "setdatalength [conn_id] [tx octests] [tx time]\n\r", + "set data length\n\r", + UserCmdSetDataLength + }, +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + { + "readadvpwr", + "readadvpwr\n\r", + "Read adv channel tx power\n\r", + UserCmdReadAdvPower + }, +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + { + "latency", + "latency [0/1]\n\r", + "on off latency\n\r", + cmd_latency + }, +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT + { + "con", + "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [bd_addr type]\n\r", + "connect to remote device\n\r", + cmd_con + }, + { + "condev", + "condev [idx]\n\r", + "connect to remote device\n\r", + cmd_condev + }, + { + "chanclassset", + "chanclassset [idx0] [idx1] [idx2] [idx3] [idx4]\n\r", + "Set Host Channel Classification\n\r", + cmd_chanclassset + }, +#endif +#if F_BT_LE_GAP_SCAN_SUPPORT + { + "scan", + "scan [1/2] [filter]\n\r", + "scan remote devices 1-passive 2-active\n\r", + cmd_scan + }, + + { + "stopscan", + "stopscan\n\r", + "stopscan remote device\n\r", + cmd_stopscan + }, + { + "showdev", + "showdev\n\r", + "Show simple dev list\n\r", + cmd_showdev + }, +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT + { + "gapdis", + "gapdis [conn_id]\n\r", + "Start discovery gap service\n\r", + cmd_gapdis + }, + { + "gapread", + "gapread [conn_id] [char]\n\r", + "Read all related chars by user input\n\r", + cmd_gapread + }, +#endif + { + "initadv", + "initadv\n\r", // minInterval: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step) + "Init advertising\n\r", // maxInterval: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step) + UserCmdInitStartAdv + }, + { + "adv", + "adv [min_interval] [max_interval]\n\r", // min_interval: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step) + "Start Undirected advertising\n\r", // max_interval: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step) + cmd_adv + }, + { + "stopadv", + "stopadv\n\r", + "Stop advertising\n\r", + cmd_stopadv + }, + { + "advld", + "advld\n\r", + "Start lower duty directed advertising\n\r", + cmd_advld + }, + { + "advhd", + "advhd [index of BD]\n\r", + "Start high duty directed advertising\n\r", + cmd_advhd + }, + { + "advscan", + "advscan\n\r", + "Start scannable undirected advertising\n\r", + cmd_advscan + }, + { + "advnonconn", + "advnonconn\n\r", + "Start non_connectable undirected advertising\n\r", + cmd_advnonconn + }, + { + "advwl", + "advwl\n\r", + "Start undirected advertising with white list\n\r", + UserCmdStartAdvWithWL + }, + { + "advset", + "advset [flag]\n\r", + "set adv param\n\r", + UserCmdStartAdvSet + }, +#if F_BT_LE_PRIVACY_SUPPORT + { + "advrel", + "advrel\n\r", + "Start undirected advertising with local type = resolved\n\r", + UserCmdStartAdvRel + }, + { + "setrae", + "setrae [enable]\n\r", + "set addr resolution enable.\n\r", + UserCmdSetrea + }, + { + "readlra", + "readlra [conn_id]\n\r", + "read local resolvable address.\n\r", + UserCmdReadlra + }, + { + "readpra", + "readlra [conn_id]\n\r", + "read peer resolvable address..\n\r", + UserCmdReadpra + }, + { + "showrel", + "showrel\n\r", + "show resolved list.\n\r", + UserCmdShowRel + }, + { + "setprivacy", + "setprivacy [rel_idx] [0/1]\n\r", + "set privacy mode.\n\r", + UserCmdSetPrivacy + }, + { + "wlrel", + "wlrel [op] [rel_idx]\n\r", + "whitelist\n\r", + UserCmdAddRelToWhitelist + }, + { + "conrel", + "conrel [idx]\n\r", + "connect to remote device\n\r", + UserCmdConnectRelDev + }, + { + "setlocalirk", + "setlocalirk [0/1/2]\n\r", + "set local irk\n\r", + UserCmdSetLocalIrk + }, + { + "setremoteirk", + "setremoteirk\n\r", + "set remote irk\n\r", + UserCmdSetRemoteIrk + }, +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT + { + "tpdis", + "tpdis [conn_id]\n\r", + "vendor tp service discovery.\n\r", + UserCmdTpDis + }, + { + "tpwrite", + "tpwrite [conn_id]\n\r", + "vendor tp service write char.\n\r", + UserCmdTpWrite + }, + { + "pxpdis", + "pxpdis [conn_id]\n\r", + "vendor pxpext service discovery.\n\r", + UserCmdPxpDis + }, + { + "pxpwrite", + "pxpwrite [conn_id]\n\r", + "vendor pxpext service write char.\n\r", + UserCmdPxpWrite + }, + { + "pxpread", + "pxpread [conn_id]\n\r", + "vendor pxpext service discovery.\n\r", + UserCmdPxpRead + }, +#endif + /********************************Peripheral*********************************/ + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/cmd/user_cmd.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/cmd/user_cmd.h new file mode 100644 index 00000000..c8239cab --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/cmd/user_cmd.h @@ -0,0 +1,31 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file user_cmd.h +* @brief Define user command. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _USER_CMD_H_ +#define _USER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "data_uart.h" +#include "user_cmd_parse.h" + +extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[]; +extern T_USER_CMD_IF user_cmd_if; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/link_mgr.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/link_mgr.c new file mode 100644 index 00000000..1870e6b0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/link_mgr.c @@ -0,0 +1,137 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include + +/*============================================================================* + * Constants + *============================================================================*/ +#if F_BT_LE_USE_STATIC_RANDOM_ADDR +/** @brief Define start offset of the falsh to save static random address. */ +#define APP_STATIC_RANDOM_ADDR_OFFSET 0 +#endif + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup SCATTERNET_GAP_MSG + * @{ + */ +T_APP_LINK app_link_table[APP_MAX_LINKS]; +/** @} */ +/** @addtogroup SCATTERNET_SCAN_MGR + * @{ + */ +T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +uint8_t dev_list_count = 0; +/** @} */ + +/*============================================================================* + * Functions + *============================================================================*/ +/** @addtogroup CENTRAL_SCAN_MGR + * @{ + */ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (dev_list_count < APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < dev_list_count; i++) + { + if (memcmp(bd_addr, dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(dev_list[dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + dev_list[dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void link_mgr_clear_device_list(void) +{ + dev_list_count = 0; +} +/** @} */ +/** @addtogroup SCATTERNET_APP + * @{ + */ +/** @defgroup SCATTERNET_RANDOM Static Random Address Storage + * @brief Use @ref F_BT_LE_USE_STATIC_RANDOM_ADDR to open + * @{ + */ +#if F_BT_LE_USE_STATIC_RANDOM_ADDR +/** + * @brief Save static random address information into flash. + * @param[in] p_info the buffer for saving data + * @retval 0 Save success. + * @retval other Failed. + */ +uint32_t app_save_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr) +{ + APP_PRINT_INFO0("app_save_static_random_address"); + return ftl_save(p_addr, APP_STATIC_RANDOM_ADDR_OFFSET, sizeof(T_APP_STATIC_RANDOM_ADDR)); +} +/** + * @brief load static random address information from storage + * @param[out] p_info the buffer for loading data + * @retval 0 Load success. + * @retval other Failed. + */ +uint32_t app_load_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr) +{ + uint32_t result; + result = ftl_load(p_addr, APP_STATIC_RANDOM_ADDR_OFFSET, + sizeof(T_APP_STATIC_RANDOM_ADDR)); + APP_PRINT_INFO1("app_load_static_random_address: result 0x%x", result); + if (result) + { + memset(p_addr, 0, sizeof(T_APP_STATIC_RANDOM_ADDR)); + } + return result; +} +#endif +/** @} */ +/** @} */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/link_mgr.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/link_mgr.h new file mode 100644 index 00000000..247c71e8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/link_mgr.h @@ -0,0 +1,89 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _LINK_MANAGER_H_ +#define _LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Define device list table size. */ +#define APP_MAX_DEVICE_INFO 6 + +/** @addtogroup SCATTERNET_GAP_MSG + * @{ + */ +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; +/** @} */ /* End of group SCATTERNET_GAP_MSG */ +/** @addtogroup SCATTERNET_SCAN_MGR GATT + * @{ + */ +/** + * @brief Device list block defination. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/** @} */ +/** @addtogroup SCATTERNET_RANDOM + * @{ + */ +#if F_BT_LE_USE_STATIC_RANDOM_ADDR +typedef struct +{ + uint8_t is_exist; + uint8_t reserved; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_STATIC_RANDOM_ADDR; +#endif +/** @} */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK app_link_table[APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void link_mgr_clear_device_list(void); + +#if F_BT_LE_USE_STATIC_RANDOM_ADDR +uint32_t app_save_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr); +uint32_t app_load_static_random_address(T_APP_STATIC_RANDOM_ADDR *p_addr); +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/privacy_mgnt.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/privacy_mgnt.c new file mode 100644 index 00000000..0a0d8bb3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/privacy_mgnt.c @@ -0,0 +1,376 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file privacy_mgnt.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#if F_BT_LE_PRIVACY_SUPPORT +#include "trace_app.h" +#include +#include "gap.h" +#include + +T_LE_PRIVACY_ENTRY privacy_table[PRIVACY_ENTRY_SIZE]; +bool clear_resolving_list_pending = false; +uint8_t modify_resolving_list_waiting_idx = 0xff; +bool wait_modify_resolving_list_rsp = false; +T_PRIVACY_STATE privacy_state = PRIVACY_STATE_INIT; +static P_FUN_PRIVACY_STATE_CB pfnPrivacyCB = NULL; + +void privacy_init_resolving_list(P_FUN_PRIVACY_STATE_CB p_fun) +{ + APP_PRINT_INFO0("privacy_init_resolving_list"); + uint8_t i; + T_LE_KEY_ENTRY *p_entry; + memset(privacy_table, 0, PRIVACY_ENTRY_SIZE * sizeof(T_LE_PRIVACY_ENTRY)); + pfnPrivacyCB = p_fun; + + for (i = 0; i < bond_storage_num; i++) + { + p_entry = le_find_key_entry_by_idx(i); + if (p_entry->is_used) + { + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + APP_PRINT_INFO2("privacy_init_resolving_list: add BD=%s type=%d", + TRACE_BDADDR(p_entry->resolved_remote_bd.addr), + p_entry->resolved_remote_bd.remote_bd_type); + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + } + } +} + +T_PRIVACY_STATE privacy_handle_pending_resolving_list_int(void) +{ + APP_PRINT_INFO0("privacy_handle_pending_resolving_list"); + uint8_t i; + T_PRIVACY_STATE state = PRIVACY_STATE_BUSY; + if (wait_modify_resolving_list_rsp) + { + APP_PRINT_INFO0("wait rsp"); + return state; + } + if (clear_resolving_list_pending) + { + APP_PRINT_INFO0("clear"); + if (le_privacy_modify_resolv_list(GAP_RESOLV_LIST_OP_CLEAR, GAP_IDENT_ADDR_PUBLIC, + NULL) == GAP_CAUSE_SUCCESS) + { + wait_modify_resolving_list_rsp = true; + return state; + } + else + { + return state; + } + } + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used && privacy_table[i].pending != PRIVACY_RESOLVING_LIST_IDLE) + { + T_GAP_CAUSE status; + if (privacy_table[i].pending == PRIVACY_RESOLVING_LIST_ADD_PENDING) + { + + APP_PRINT_INFO3("add i=%d BD=%s type=%d\n", i, + TRACE_BDADDR(privacy_table[i].addr), + privacy_table[i].remote_bd_type); + status = le_privacy_modify_resolv_list(GAP_RESOLV_LIST_OP_ADD, + privacy_table[i].remote_bd_type, + privacy_table[i].addr); + if (status == GAP_CAUSE_SUCCESS) + { + wait_modify_resolving_list_rsp = true; + modify_resolving_list_waiting_idx = i; + return state; + } + else if (status != GAP_CAUSE_INVALID_STATE) + { + APP_PRINT_INFO1("remove i=%d from pend add\n", i); + memset(&privacy_table[i], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + else + { + return state; + } + } + else + { + APP_PRINT_INFO3("remove i=%d BD=%s type=%d", i, + TRACE_BDADDR(privacy_table[i].addr), + privacy_table[i].remote_bd_type); + status = le_privacy_modify_resolv_list(GAP_RESOLV_LIST_OP_REMOVE, + privacy_table[i].remote_bd_type, + privacy_table[i].addr); + if (status == GAP_CAUSE_SUCCESS) + { + wait_modify_resolving_list_rsp = true; + modify_resolving_list_waiting_idx = i; + return state; + } + else if (status != GAP_CAUSE_INVALID_STATE) + { + APP_PRINT_INFO1("remove i=%d from pend remove\n", i); + memset(&privacy_table[i], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + else + { + return state; + } + } + } + } + APP_PRINT_INFO0("privacy_handle_pending_resolving_list: idle"); + state = PRIVACY_STATE_IDLE; + return state; +} + +T_PRIVACY_STATE privacy_handle_pending_resolving_list(void) +{ + T_PRIVACY_STATE state = privacy_handle_pending_resolving_list_int(); + if (privacy_state != state) + { + privacy_state = state; + if (pfnPrivacyCB) + { + pfnPrivacyCB(PRIVACY_STATE_MSGTYPE, privacy_state); + } + } + return state; +} +void privacy_add_pending_resolving_list(T_GAP_RESOLV_LIST_OP op, + T_GAP_IDENT_ADDR_TYPE addr_type, uint8_t *addr) +{ + APP_PRINT_INFO1("privacy_add_pending_resolving_list op = %d", op); + switch (op) + { + case GAP_RESOLV_LIST_OP_CLEAR: + clear_resolving_list_pending = true; + break; + + case GAP_RESOLV_LIST_OP_ADD: + //if((addr_type == BTIF_RemoteBDTypeLEPublic) + //||(addr_type == BTIF_RemoteBDTypeLEPublicIdentityAddress) + //||(addr_type == BTIF_RemoteBDTypeLERandomIdentityAddress) + //||((addr_type == BTIF_RemoteBDTypeLERandom) && (addr[5]&RANDOM_ADDR_MASK == RANDOM_ADDR_MASK_STATIC))) + { + uint8_t i; + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used) + { + if ((privacy_table[i].remote_bd_type == addr_type) + && (memcmp(privacy_table[i].addr, addr, 6) == 0)) + { + if (!privacy_table[i].is_add_to_list) + { + privacy_table[i].pending = PRIVACY_RESOLVING_LIST_ADD_PENDING; + } + break; + } + } + } + if (i != PRIVACY_ENTRY_SIZE) + { + break; + } + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (!privacy_table[i].is_used) + { + privacy_table[i].is_used = true; + privacy_table[i].remote_bd_type = addr_type; + memcpy(privacy_table[i].addr, addr, 6); + privacy_table[i].pending = PRIVACY_RESOLVING_LIST_ADD_PENDING; + break; + } + } + } + break; + + case GAP_RESOLV_LIST_OP_REMOVE: + //if((addr_type == BTIF_RemoteBDTypeLEPublicIdentityAddress) + //||(addr_type == BTIF_RemoteBDTypeLERandomIdentityAddress)) + { + uint8_t i; + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used) + { + if ((privacy_table[i].remote_bd_type == addr_type) + && (memcmp(privacy_table[i].addr, addr, 6) == 0)) + { + if (privacy_table[i].is_add_to_list) + { + privacy_table[i].pending = PRIVACY_RESOLVING_LIST_REMOVE_PENDING; + } + else + { + memset(&privacy_table[i], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + break; + } + } + } + } + break; + default: + break; + } +} + +void privacy_handle_LE_ADDRESS_RESOLUTION_STATUS_INFO_MSGTYPE(T_LE_PRIVACY_RESOLUTION_STATUS_INFO + res_status) +{ + APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_RESOLUTION_STATUS_INFO: status = 0x%x\n", res_status.status); + if (pfnPrivacyCB) + { + pfnPrivacyCB(PRIVACY_RESOLUTION_STATUS_MSGTYPE, res_status.status); + } +} + +void privacy_handle_LE_MODIFY_RESOLVING_LIST_MSGTYPE(T_LE_PRIVACY_MODIFY_RESOLV_LIST_RSP + *pListRsp) +{ + APP_PRINT_INFO2("GAP_MSG_LE_PRIVACY_MODIFY_RESOLV_LIST: operation = 0x%x casue = 0x%x", + pListRsp->operation, pListRsp->cause); + wait_modify_resolving_list_rsp = false; + if (pListRsp->cause != GAP_SUCCESS) + { + if (pListRsp->cause == (HCI_ERR | HCI_ERR_UNKNOWN_CONN_ID) + || pListRsp->cause == (HCI_ERR | HCI_ERR_MEMORY_FULL) + || pListRsp->cause == (HCI_ERR | HCI_ERR_INVALID_PARAM)) + { + memset(&privacy_table[modify_resolving_list_waiting_idx], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + modify_resolving_list_waiting_idx = 0xff; + } + else + { + if (pListRsp->operation == GAP_RESOLV_LIST_OP_CLEAR) + { + clear_resolving_list_pending = false; + memset(privacy_table, 0, PRIVACY_ENTRY_SIZE * sizeof(T_LE_PRIVACY_ENTRY)); + } + else if (pListRsp->operation == GAP_RESOLV_LIST_OP_ADD) + { + if (modify_resolving_list_waiting_idx < PRIVACY_ENTRY_SIZE) + { + privacy_table[modify_resolving_list_waiting_idx].is_add_to_list = true; + privacy_table[modify_resolving_list_waiting_idx].pending = PRIVACY_RESOLVING_LIST_IDLE; + modify_resolving_list_waiting_idx = 0xff; + } + } + else + { + if (modify_resolving_list_waiting_idx < PRIVACY_ENTRY_SIZE) + { + memset(&privacy_table[modify_resolving_list_waiting_idx], 0, sizeof(T_LE_PRIVACY_ENTRY)); + modify_resolving_list_waiting_idx = 0xff; + } + } + privacy_handle_pending_resolving_list(); + } +} + +void privacy_handle_LE_READ_PEER_RESOLVABLE_ADDRESS_MSGTYPE( + T_LE_PRIVACY_READ_PEER_RESOLV_ADDR_RSP *pLEReadPeerResolvableAddressRsp) +{ + APP_PRINT_INFO2("GAP_MSG_LE_PRIVACY_READ_PEER_RESOLV_ADDR: cause = 0x%x BD=%s", + pLEReadPeerResolvableAddressRsp->cause, + TRACE_BDADDR(pLEReadPeerResolvableAddressRsp->peer_resolv_addr)); +} +void privacy_handle_LE_READ_LOCAL_RESOLVABLE_ADDRESS_MSGTYPE( + T_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR_RSP * + pLEReadLocalResolvableAddressRsp) +{ + APP_PRINT_INFO2("GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR: cause = 0x%x BD=%s", + pLEReadLocalResolvableAddressRsp->cause, + TRACE_BDADDR(pLEReadLocalResolvableAddressRsp->local_resolv_addr)); +} + +void privacy_handle_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_MSGTYPE( + T_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT_RSP *pTimeoutRsp) +{ + APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT: cause = 0x%x", + pTimeoutRsp->cause); +} + +#if 0 +void privacy_handle_LE_BOND_MODIFY_MSGTYPE(P_LE_BOND_MODIFY_INFO pDeleteInfo) +{ + APP_PRINT_INFO2("LE_BOND_MODIFY_MSGTYPE: type = 0x%x bd_addr = %s", + pDeleteInfo->remote_bd_type, TRACE_BDADDR(pDeleteInfo->remote_bd)); + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, pDeleteInfo->remote_bd_type, + pDeleteInfo->remote_bd); + privacy_handle_pending_resolving_list(); +} +#endif + +#if 0 +void privacy_handle_LE_REMOTE_IRK_RECEIVE_MSGTYPE(P_LE_REMOTE_IRK_RECEIVE p_irk) +{ + APP_PRINT_INFO2("LE_REMOTE_IRK_RECEIVE_MSGTYPE: type = 0x%x bd_addr = %s", + p_irk->remote_bd_type, TRACE_BDADDR(p_irk->remote_bd)); + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, p_irk->remote_bd_type, + p_irk->remote_bd); + privacy_handle_pending_resolving_list(); +} +#endif +void privacy_handle_LE_SET_PRIVACY_MODE_MSGTYPE(T_LE_PRIVACY_SET_MODE_RSP *p_privacy_mode) +{ + APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_SET_MODE: cause = %d", + p_privacy_mode->cause); +} + +T_APP_RESULT App_PrivacyCallback(uint8_t msg_type, T_LE_PRIVACY_CB_DATA msg_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("App_PrivacyCallback: msgType = %d", msg_type); + switch (msg_type) + { + case GAP_MSG_LE_PRIVACY_RESOLUTION_STATUS_INFO: + privacy_handle_LE_ADDRESS_RESOLUTION_STATUS_INFO_MSGTYPE( + msg_data.le_privacy_resolution_status_info); + break; + case GAP_MSG_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT: + privacy_handle_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_MSGTYPE( + msg_data.p_le_privacy_set_resolv_priv_addr_timeout_rsp); + break; + + case GAP_MSG_LE_PRIVACY_MODIFY_RESOLV_LIST: + privacy_handle_LE_MODIFY_RESOLVING_LIST_MSGTYPE(msg_data.p_le_privacy_modify_resolv_list_rsp); + break; + case GAP_MSG_LE_PRIVACY_READ_PEER_RESOLV_ADDR: + privacy_handle_LE_READ_PEER_RESOLVABLE_ADDRESS_MSGTYPE( + msg_data.p_le_privacy_read_peer_resolv_addr_rsp); + break; + case GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR: + privacy_handle_LE_READ_LOCAL_RESOLVABLE_ADDRESS_MSGTYPE( + msg_data.p_le_privacy_read_local_resolv_addr_rsp); + break; + //case LE_BOND_DELETE_MSGTYPE: + //privacy_handle_LE_BOND_DELETE_MSGTYPE(msg_data.p_le_bond_delete_info); + //break; + + //case LE_REMOTE_IRK_RECEIVE_MSGTYPE: + //privacy_handle_LE_REMOTE_IRK_RECEIVE_MSGTYPE(msg_data.p_remote_irk_rec); + //break; + case GAP_MSG_LE_PRIVACY_SET_MODE: + privacy_handle_LE_SET_PRIVACY_MODE_MSGTYPE(msg_data.p_le_privacy_set_mode_rsp); + break; + default: + break; + } + return result; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/privacy_mgnt.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/privacy_mgnt.h new file mode 100644 index 00000000..b7bc3375 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/privacy_mgnt.h @@ -0,0 +1,66 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file privacy_mgnt.h + * @brief privacy managerment. + * @details privacy managerment. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PRIVACY_MGNT_H_ +#define _PRIVACY_MGNT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#if F_BT_LE_PRIVACY_SUPPORT +#include +#include + +#define PRIVACY_ENTRY_SIZE 4 +#define PRIVACY_RESOLVING_LIST_IDLE 0 +#define PRIVACY_RESOLVING_LIST_ADD_PENDING 1 +#define PRIVACY_RESOLVING_LIST_REMOVE_PENDING 2 +typedef struct +{ + bool is_used; + uint8_t addr[6]; + T_GAP_IDENT_ADDR_TYPE remote_bd_type; + bool is_add_to_list; + uint8_t pending; + +} T_LE_PRIVACY_ENTRY, *P_LE_PRIVACY_ENTRY; + +typedef enum +{ + PRIVACY_STATE_MSGTYPE, + PRIVACY_RESOLUTION_STATUS_MSGTYPE +} T_PRI_CB_TYPE; + +typedef enum +{ + PRIVACY_STATE_INIT, + PRIVACY_STATE_IDLE, //!< Disconnected. + PRIVACY_STATE_BUSY +} T_PRIVACY_STATE; +extern T_LE_PRIVACY_ENTRY privacy_table[PRIVACY_ENTRY_SIZE]; +typedef void(*P_FUN_PRIVACY_STATE_CB)(T_PRI_CB_TYPE type, uint8_t status); + +T_APP_RESULT App_PrivacyCallback(uint8_t msg_type, T_LE_PRIVACY_CB_DATA msg_data); +void privacy_init_resolving_list(P_FUN_PRIVACY_STATE_CB p_fun); +T_PRIVACY_STATE privacy_handle_pending_resolving_list(void); +void privacy_add_pending_resolving_list(T_GAP_RESOLV_LIST_OP op, + T_GAP_IDENT_ADDR_TYPE addr_type, uint8_t *addr); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _PRIVACY_MGNT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_0001.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_0001.c new file mode 100644 index 00000000..66313369 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_0001.c @@ -0,0 +1,449 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include +#include +#include + + + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT +#include "gap_adv.h" +#endif + +#include "gap.h" + + +#include +#include + + +#if TC_0001_SUPPORT +#include "ameba_soc.h" + + +#define ADV_TEST_PARAM_COUNT 8 + +T_ADV_TEST_PARAM g_adv_test_param[ADV_TEST_PARAM_COUNT]; +uint8_t g_adv_cur_test_index = 0; +uint8_t g_adv_total_test_index = ADV_TEST_PARAM_COUNT; + + + +// GAP - SCAN RSP data (max size = 31 bytes) +const uint8_t scan_rsp_data_for_adv_test[] = +{ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc2, 0x03, /* Mouse */ +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +// best kept short to conserve power while advertisting) +const uint8_t adv_data_for_adv_test[] = +{ + /* Core spec. Vol. 3, Part C, Chapter 18 */ + /* Flags */ + 0x02, /* length */ + //XXXXMJMJ 0x01, 0x06, /* type="flags", data="bit 1: LE General Discoverable Mode", BR/EDR not supp. */ + 0x01, 0x05, /* type="flags", data="bit 1: LE General Discoverable Mode" */ + /* Service */ + 0x03, /* length */ + 0x03, /* type="More 16-bit UUIDs available" */ + 0x12, + 0x18, + /* place holder for Local Name, filled by BT stack. if not present */ + /* BT stack appends Local Name. */ + 0x03, /* length */ + 0x19, /* type="Appearance" */ + 0xc2, 0x03, /* Mouse */ + 0x0C, /* length */ + 0x09, /* type="Complete local name" */ +// 0x42, 0x65, 0x65, 0x5F, 0x6D, 0x6F, 0x75, 0x73, 0x65 /* Bee_perip */ + 'B', 'e', 'e', '_', 'G', 'a', 'p', 'T', 'e', 's', 't' /* Bee_perip */ +}; + + +void tc_0001_adv_start(uint16_t advIntMin, uint16_t advIntMax) +{ + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + + g_adv_cur_test_index = 0; + g_adv_total_test_index = ADV_TEST_PARAM_COUNT; + + for (uint8_t i = 0; i < g_adv_total_test_index; i++) + { + g_adv_test_param[i].adv_interval_min = advIntMin; + g_adv_test_param[i].adv_interval_max = advIntMax; + } + if (NULL == g_test_timer_handle) + { + os_timer_create(&g_test_timer_handle, "testTimer", 1, 1000, false, tc_0001_adv_timeout_handler); + } + //start total timer + os_timer_start(&g_test_timer_handle); + //reset_vendor_counter(); + g_test_begin_time = RTIM_GetCount(TIMM00); + + g_adv_test_param[g_adv_cur_test_index].start_adv_begin_time = RTIM_GetCount(TIMM00); + + APP_PRINT_INFO1("cmd_adv begin_time = %d", + g_adv_test_param[g_adv_cur_test_index].start_adv_begin_time); + + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data_for_adv_test), + (void *)adv_data_for_adv_test); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data_for_adv_test), + (void *)scan_rsp_data_for_adv_test); + le_adv_start(); + +} + +static bool flag2 = false; +void tc_0001_adv_timeout_handler(void *pxTimer) +{ + g_test_end_time = RTIM_GetCount(TIMM00); + + APP_PRINT_INFO3("tc_0001_adv_timeout_handler begin time=%d, end time=%d, time elapsed = %dus", + g_test_begin_time, g_test_end_time, + amebad_time_get_elapsed(g_test_begin_time, g_test_end_time)); + if (false == flag2) + { + data_uart_print("begin time, end time, elapase time(us)\r\n"); + flag2 = true; + } + + data_uart_print( + " %d, %d, %d\r\n", + g_test_begin_time, + g_test_end_time, + amebad_time_get_elapsed(g_test_begin_time, g_test_end_time)); + flag2 = false; +} +bool flag1 = false; +void tc_0001_adv_adv_state_change_to_idle(void) +{ + + g_adv_test_param[g_adv_cur_test_index].stop_adv_end_time = RTIM_GetCount(TIMM00); + /* + APP_PRINT_INFO3(" ble stop adv begin_time =%d, end_time =%d, elapsed time = %d", + g_adv_test_param[g_adv_cur_test_index].stop_adv_begin_time, + g_adv_test_param[g_adv_cur_test_index].stop_adv_end_time, + (g_adv_test_param[g_adv_cur_test_index].stop_adv_end_time - g_adv_test_param[g_adv_cur_test_index].stop_adv_begin_time)); + */ + + g_adv_cur_test_index++; + if (g_adv_cur_test_index < g_adv_total_test_index) + { + + g_adv_test_param[g_adv_cur_test_index].start_adv_begin_time = RTIM_GetCount(TIMM00); + + + APP_PRINT_INFO2(" ble start adv index = %d, begin_time=%d", g_adv_cur_test_index, + g_adv_test_param[g_adv_cur_test_index].start_adv_begin_time); + + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advDirectType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + uint16_t advIntMin = (uint16_t)0x100; + uint16_t advIntMax = (uint16_t)0x200; + + //advertising parameters + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectType), &advDirectType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data_for_adv_test), + (void *)adv_data_for_adv_test); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data_for_adv_test), + (void *)scan_rsp_data_for_adv_test); + + le_adv_start(); + } + else + { + for (uint8_t i = 0; i < g_adv_total_test_index; i++) + { + if (false == flag1) + { + data_uart_print(" adv_interval_min , adv_interval_max , start adv elapase time(us)\r\n"); + flag1 = true; + } + data_uart_print(" %d, %d, %d\r\n", + g_adv_test_param[i].adv_interval_min, + g_adv_test_param[i].adv_interval_max, + amebad_time_get_elapsed(g_adv_test_param[i].start_adv_begin_time, + g_adv_test_param[i].start_adv_end_time) + ); + } + flag1 = false; + for (uint8_t i = 0; i < g_adv_total_test_index; i++) + { + if (false == flag1) + { + data_uart_print(" adv_interval_min , adv_interval_max , stop adv elapase time(us)\r\n"); + flag1 = true; + } + data_uart_print(" %d, %d, %d\r\n", + g_adv_test_param[i].adv_interval_min, + g_adv_test_param[i].adv_interval_max, + (g_adv_test_param[i].stop_adv_end_time - g_adv_test_param[i].stop_adv_begin_time) / TEST_CPU_CLOCK); + + + } + flag1 = false; + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0001_ADV_PERFORMANCE, 0, NULL); + } + + + } + +} + +void tc_0001_adv_adv_state_change_to_advertising(void) +{ + //APP_PRINT_INFO0("GAP adv start"); + + + g_adv_test_param[g_adv_cur_test_index].start_adv_end_time = RTIM_GetCount(TIMM00); + /* + APP_PRINT_INFO3(" ble adv g_start_adv_begin_time =%d, end_time =%d, elapsed time = %d", + g_adv_test_param[g_adv_cur_test_index].start_adv_begin_time, + g_adv_test_param[g_adv_cur_test_index].start_adv_end_time, + (g_adv_test_param[g_adv_cur_test_index].start_adv_end_time - g_adv_test_param[g_adv_cur_test_index].start_adv_begin_time)); + + */ + g_adv_test_param[g_adv_cur_test_index].stop_adv_begin_time = RTIM_GetCount(TIMM00); + APP_PRINT_INFO2(" ble stop adv index = %d, begin_time=%d", g_adv_cur_test_index, + g_adv_test_param[g_adv_cur_test_index].stop_adv_begin_time); + le_adv_stop(); + +} + + + +void *g_tc_adv_enable_disable_timer_handle = NULL; +void *g_tc_adv_enable_disable_monitor_timer_handle = NULL; + +uint32_t g_tc_adv_enable_disable_begin_time = 0; +uint32_t g_tc_adv_enable_disable_max_start_adv_ellapsed_time = 0; +uint32_t g_tc_adv_enable_disable_max_stop_adv_ellapsed_time = 0; +uint32_t g_tc_adv_enable_disable_max_count = 65535; +uint32_t g_tc_adv_enable_disable_cur_count = 0; + +void tc_adv_start_stop_TimeoutHandler(void *pxTimer) +{ + data_uart_print( + "tc_adv_start_stop_TimeoutHandler max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + g_tc_adv_enable_disable_max_start_adv_ellapsed_time, + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time, + g_tc_adv_enable_disable_cur_count); + APP_PRINT_ERROR3("tc_adv_start_stop_TimeoutHandler max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + g_tc_adv_enable_disable_max_start_adv_ellapsed_time, + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time, + g_tc_adv_enable_disable_cur_count); + +} + +void tc_adv_start_stop_monitor_TimeoutHandler(void *pxTimer) +{ + /* + data_uart_print( + "tc_adv_start_stop_monitor_TimeoutHandler 10s max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + g_tc_adv_enable_disable_max_start_adv_ellapsed_time, + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time, + g_tc_adv_enable_disable_cur_count); + APP_PRINT_INFO3( "tc_adv_start_stop_monitor_TimeoutHandler 10s max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + g_tc_adv_enable_disable_max_start_adv_ellapsed_time, + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time, + g_tc_adv_enable_disable_cur_count); + */ +} + +void tc_0002_adv_start_stop_start(uint16_t advIntMin, uint16_t advIntMax, uint32_t max_count) +{ + uint8_t advEventType = GAP_ADTYPE_ADV_IND; + uint8_t advChanMap = GAP_ADVCHAN_ALL; + uint8_t advFilterPolicy = GAP_ADV_FILTER_ANY; + + + g_tc_adv_enable_disable_max_count = max_count; + g_tc_adv_enable_disable_cur_count = 0; + + + if (NULL == g_tc_adv_enable_disable_timer_handle) + { + os_timer_create(&g_tc_adv_enable_disable_timer_handle, "g_tc_adv_enable_disable_timer_handle", 1, + 1000, false, tc_adv_start_stop_TimeoutHandler); + } + + if (NULL == g_tc_adv_enable_disable_monitor_timer_handle) + { + os_timer_create(&g_tc_adv_enable_disable_monitor_timer_handle, "adv_monitor_timer", 1, 10000, false, + tc_adv_start_stop_monitor_TimeoutHandler); + } + + //start total timer + os_timer_start(&g_tc_adv_enable_disable_timer_handle); + os_timer_start(&g_tc_adv_enable_disable_monitor_timer_handle); + //reset_vendor_counter(); + g_tc_adv_enable_disable_begin_time = RTIM_GetCount(TIMM00); + + APP_PRINT_INFO1("app_handle_tc_adv_enable_disable_start begin_time = %d", + g_tc_adv_enable_disable_begin_time); + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(advEventType), &advEventType); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(advChanMap), &advChanMap); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(advFilterPolicy), &advFilterPolicy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(advIntMin), &advIntMin); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(advIntMax), &advIntMax); + + le_adv_start(); + +} + +void tc_0002_adv_start_stop_adv_state_change_to_advertising(void) +{ + uint32_t cur_time = RTIM_GetCount(TIMM00); + uint32_t ellapsed_time = amebad_time_get_elapsed(g_tc_adv_enable_disable_begin_time, cur_time); + + if (ellapsed_time > g_tc_adv_enable_disable_max_start_adv_ellapsed_time) + { + g_tc_adv_enable_disable_max_start_adv_ellapsed_time = ellapsed_time; + /* + data_uart_print( + "tc_adv_start_stop start adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + g_tc_adv_enable_disable_cur_count); + */ + APP_PRINT_INFO2( + "tc_adv_start_stop start adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + g_tc_adv_enable_disable_cur_count); + + + } + + os_timer_start(&g_tc_adv_enable_disable_timer_handle); + //reset_vendor_counter(); + g_tc_adv_enable_disable_begin_time = RTIM_GetCount(TIMM00); + le_adv_stop(); +} + +void tc_0002_adv_start_stop_adv_state_change_to_idle(void) +{ + uint32_t cur_time = RTIM_GetCount(TIMM00); + uint32_t ellapsed_time = amebad_time_get_elapsed(g_tc_adv_enable_disable_begin_time, cur_time); + + if (ellapsed_time > g_tc_adv_enable_disable_max_stop_adv_ellapsed_time) + { + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time = ellapsed_time; + /* + data_uart_print( + "tc_adv_start_stop stop adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + g_tc_adv_enable_disable_cur_count); + */ + APP_PRINT_INFO2( + "tc_adv_start_stop stop adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + g_tc_adv_enable_disable_cur_count); + } + + + os_timer_start(&g_tc_adv_enable_disable_timer_handle); + g_tc_adv_enable_disable_cur_count++; + if (g_tc_adv_enable_disable_cur_count != g_tc_adv_enable_disable_max_count) + { + le_adv_start(); + } + else + { + //test case end here + //stop timer + os_timer_stop(&g_tc_adv_enable_disable_timer_handle); + os_timer_stop(&g_tc_adv_enable_disable_monitor_timer_handle); + + //print result + data_uart_print( + "tc_adv_start_stop finish max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + g_tc_adv_enable_disable_max_start_adv_ellapsed_time, + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time, + g_tc_adv_enable_disable_cur_count); + + APP_PRINT_INFO3("tc_adv_start_stop finish max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + g_tc_adv_enable_disable_max_start_adv_ellapsed_time, + g_tc_adv_enable_disable_max_stop_adv_ellapsed_time, + g_tc_adv_enable_disable_cur_count); + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0002_ADV_STRESS_START_STOP, 0, NULL); + } + + } +} + +void tc_0001_add_case(uint16_t adv_interval_min, uint16_t adv_interval_max) +{ + T_TC_0001_PARAM_DATA *p_tc_0001_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_0001_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_0001_PARAM_DATA)); + + p_tc_0001_param_data->id = TC_0001_ADV_PERFORMANCE; + p_tc_0001_param_data->adv_interval_max = adv_interval_max; + p_tc_0001_param_data->adv_interval_min = adv_interval_min; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_0001_param_data; + + + os_queue_in(&tc_q, p_tc_param); + +} + +void tc_0002_add_case(uint16_t adv_interval_min, uint16_t adv_interval_max, uint32_t max_count) +{ + + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + T_TC_0002_PARAM_DATA *p_tc_0002_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, + sizeof(T_TC_0002_PARAM_DATA)); + + p_tc_0002_param_data->id = TC_0002_ADV_STRESS_START_STOP; + p_tc_0002_param_data->adv_interval_max = adv_interval_max; + p_tc_0002_param_data->adv_interval_min = adv_interval_min; + p_tc_0002_param_data->max_count = max_count; + + p_tc_param->p_data = (void *)p_tc_0002_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_0001.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_0001.h new file mode 100644 index 00000000..97e0cea2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_0001.h @@ -0,0 +1,77 @@ + + +#ifndef _BLE_AUTO_TEST_TC_0001_H_ +#define _BLE_AUTO_TEST_TC_0001_H_ + + +#if F_BT_LE_GAP_PERIPHERAL_SUPPORT + +#ifdef __cplusplus +extern "C" { +#endif + + + + +typedef struct t_adv_test_param +{ + uint16_t adv_interval_min; + uint16_t adv_interval_max; + + uint32_t start_adv_begin_time; + uint32_t start_adv_end_time; + uint32_t stop_adv_begin_time; + uint32_t stop_adv_end_time; + +} T_ADV_TEST_PARAM; + + + + +typedef struct _T_TC_0001_PARAM_DATA +{ + uint16_t id; + uint16_t result; + uint16_t adv_interval_min; + uint16_t adv_interval_max; +} T_TC_0001_PARAM_DATA; + +typedef struct _T_TC_0002_PARAM_DATA +{ + uint16_t id; + uint16_t result; + uint16_t adv_interval_min; + uint16_t adv_interval_max; + uint32_t max_count; +} T_TC_0002_PARAM_DATA; + + +/** + for case TC_0001_ADV_PERFORMANCE +*/ +void tc_0001_adv_start(uint16_t advIntMin, uint16_t advIntMax); +void tc_0001_adv_timeout_handler(void *pxTimer); +void tc_0001_adv_adv_state_change_to_idle(void); +void tc_0001_adv_adv_state_change_to_advertising(void); +void tc_0001_add_case(uint16_t adv_interval_min, uint16_t adv_interval_max); + + +/** + for case TC_0002_ADV_PERFORMANCE +*/ +void tc_0002_adv_start_stop_start(uint16_t advIntMin, uint16_t advIntMax, uint32_t max_count); +void tc_0002_adv_start_stop_adv_state_change_to_advertising(void); +void tc_0002_adv_start_stop_adv_state_change_to_idle(void); +void tc_0002_add_case(uint16_t adv_interval_min, uint16_t adv_interval_max, uint32_t max_count); + + + + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_100.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_100.c new file mode 100644 index 00000000..e8d7478d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_100.c @@ -0,0 +1,291 @@ +#include +#include "app_msg.h" +#include "trace_app.h" + + +#include "user_cmd.h" +#include "user_cmd_parse.h" + + +#include +#include + +#include + +#if F_BT_LE_GAP_SCAN_SUPPORT +#include "gap_scan.h" +#endif +#include "gap.h" + + + +#include +#include + +#if TC_100_SUPPORT + +#if F_BT_LE_GAP_SCAN_SUPPORT + +//for case TC_0100_SCAN_PERFORMANCE +#define SCAN_TEST_PARAM_COUNT 8 +T_SCAN_TEST_PARAM g_scan_test_param[SCAN_TEST_PARAM_COUNT]; +uint8_t g_scan_cur_test_index = 0; +uint8_t g_scan_total_test_index = SCAN_TEST_PARAM_COUNT; +bool flag2 = false; +void tc_0100_scan_perf_timeout_handler(void *pxTimer) +{ + g_test_end_time = read_vendor_counter_no_display(); + APP_PRINT_INFO3("tc_0100_scan_perf_timeout_handler begin time=%d, end time=%d, time elapsed = %dus", + g_test_begin_time, g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK); + if (false == flag2) + { + data_uart_print("begin time, end time, elapase time(us)\r\n"); + flag2 = true; + } + data_uart_print( + " %d, %d, %d\r\n", + g_test_begin_time, + g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK); + flag2 = false; +} + +void tc_0100_scan_perf_start(uint16_t scan_interval, uint16_t scan_window) +{ + g_scan_cur_test_index = 0; + g_scan_total_test_index = SCAN_TEST_PARAM_COUNT; + + for (uint8_t i = 0; i < g_scan_total_test_index; i++) + { + g_scan_test_param[i].scan_interval = scan_interval; + g_scan_test_param[i].scan_window = scan_window; + } + if (NULL == g_test_timer_handle) + { + os_timer_create(&g_test_timer_handle, "testTimer", 1, 1000, false, + tc_0100_scan_perf_timeout_handler); + } + //start total timer + os_timer_start(&g_test_timer_handle); + reset_vendor_counter(); + g_test_begin_time = read_vendor_counter_no_display(); + + g_scan_test_param[g_scan_cur_test_index].start_scan_begin_time = read_vendor_counter_no_display(); + + APP_PRINT_INFO1("tc_0100_scan_perf_start begin_time = %d", + g_scan_test_param[g_scan_cur_test_index].start_scan_begin_time); + + le_scan_start(); +} + +void tc_0100_scan_state_change_to_scaning() +{ + le_scan_stop(); +} + +void tc_0100_scan_state_change_to_idle() +{ + le_scan_start(); +} + + +/******************************************************** + + +TC_0101 + + +********************************************************/ + + +T_TC_0101_PARAM *p_tc_0101_param = NULL; +void tc_0101_scan_stress_enable_disable_TimeoutHandler(void *pxTimer) +{ + data_uart_print( + "!!!tc_0101_scan_stress_enable_disable_TimeoutHandler max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + p_tc_0101_param->scan_enable_disable_max_enable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_max_disable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_cur_count); + APP_PRINT_ERROR3("tc_0101_scan_stress_enable_disable_TimeoutHandler max start adv ellapsed time =%dus, max stop adv ellapsed time =%dus cur count = %d \r\n", + p_tc_0101_param->scan_enable_disable_max_enable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_max_disable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_cur_count); + +} +void tc_0101_scan_stress_enable_disable_start(T_GAP_SCAN_MODE mode, + uint16_t interval, + uint16_t window, + T_GAP_SCAN_FILTER_POLICY filter_policy, + uint8_t filter_duplicates, + uint32_t max_count + ) +{ + if (p_tc_0101_param == NULL) + { + p_tc_0101_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_0101_PARAM)); + } + if (p_tc_0101_param != NULL) + { + p_tc_0101_param->mode = mode; + p_tc_0101_param->interval = interval; + p_tc_0101_param->window = window; + p_tc_0101_param->filter_policy = filter_policy; + p_tc_0101_param->filter_duplicates = filter_duplicates; + + p_tc_0101_param->scan_enable_disable_max_count = max_count; + p_tc_0101_param->scan_enable_disable_cur_count = 0; + if (NULL == p_tc_0101_param->scan_enable_disable_timer_handle) + { + os_timer_create(&p_tc_0101_param->scan_enable_disable_timer_handle, + "tc_0101_scan_stress_enable_disable_start", 1, 1000, false, + tc_0101_scan_stress_enable_disable_TimeoutHandler); + } + + //start total timer + os_timer_start(&p_tc_0101_param->scan_enable_disable_timer_handle); + + reset_vendor_counter(); + p_tc_0101_param->scan_enable_disable_begin_time = read_vendor_counter_no_display(); + + APP_PRINT_INFO1("app_handle_tc_adv_enable_disable_start begin_time = %d", + p_tc_0101_param->scan_enable_disable_begin_time); + + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(p_tc_0101_param->mode), &p_tc_0101_param->mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(p_tc_0101_param->interval), + &p_tc_0101_param->interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(p_tc_0101_param->window), + &p_tc_0101_param->window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(p_tc_0101_param->filter_policy), + &p_tc_0101_param->filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(p_tc_0101_param->filter_duplicates), + &p_tc_0101_param->filter_duplicates); + + le_scan_start(); + } + else + { + data_uart_print( + "Fail to run tc_0101_scan_stress_enable_disable_start"); + + } + +} +void tc_0101_scan_stress_enable_disable_state_change_to_scaning(void) +{ + uint32_t cur_time = read_vendor_counter_no_display(); + uint32_t ellapsed_time = (cur_time - p_tc_0101_param->scan_enable_disable_begin_time) / + TEST_CPU_CLOCK; + + if (ellapsed_time > p_tc_0101_param->scan_enable_disable_max_enable_scan_ellapsed_time) + { + p_tc_0101_param->scan_enable_disable_max_enable_scan_ellapsed_time = ellapsed_time; + /* + data_uart_print( + "tc_adv_start_stop start adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + g_tc_adv_enable_disable_cur_count); + */ + APP_PRINT_INFO2( + "tc_adv_start_stop start adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + p_tc_0101_param->scan_enable_disable_cur_count); + + + } + + os_timer_start(&p_tc_0101_param->scan_enable_disable_timer_handle); + reset_vendor_counter(); + p_tc_0101_param->scan_enable_disable_begin_time = read_vendor_counter_no_display(); + le_scan_stop(); +} +void tc_0101_scan_stress_enable_disable_state_change_to_idle(void) +{ + uint32_t cur_time = read_vendor_counter_no_display(); + uint32_t ellapsed_time = (cur_time - p_tc_0101_param->scan_enable_disable_begin_time) / + TEST_CPU_CLOCK; + + if (ellapsed_time > p_tc_0101_param->scan_enable_disable_max_disable_scan_ellapsed_time) + { + p_tc_0101_param->scan_enable_disable_max_disable_scan_ellapsed_time = ellapsed_time; + /* + data_uart_print( + "tc_adv_start_stop stop adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + g_tc_adv_enable_disable_cur_count); + */ + APP_PRINT_INFO2( + "tc_adv_start_stop stop adv ellapsed time =%dus, cur count = %d \r\n", + ellapsed_time, + p_tc_0101_param->scan_enable_disable_cur_count); + } + + + os_timer_start(&p_tc_0101_param->scan_enable_disable_timer_handle); + p_tc_0101_param->scan_enable_disable_cur_count++; + if (p_tc_0101_param->scan_enable_disable_cur_count != + p_tc_0101_param->scan_enable_disable_max_count) + { + le_scan_start(); + } + else + { + //test case end here + //stop timer + os_timer_stop(&p_tc_0101_param->scan_enable_disable_timer_handle); + + //print result + data_uart_print( + "tc_0101 finish max enable scan ellapsed time =%dus, max disable scan ellapsed time =%dus cur count = %d \r\n", + p_tc_0101_param->scan_enable_disable_max_enable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_max_disable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_cur_count); + + APP_PRINT_INFO3("tc_0101 finish max enable scan ellapsed time =%dus, max disable scan ellapsed time =%dus cur count = %d \r\n", + p_tc_0101_param->scan_enable_disable_max_enable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_max_disable_scan_ellapsed_time, + p_tc_0101_param->scan_enable_disable_cur_count); + + os_mem_free(p_tc_0101_param); + p_tc_0101_param = NULL; + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0101_SCAN_STRESS_ENABLE_DISABLE, 0, NULL); + } + + } +} + + + +void tc_0101_add_case(T_GAP_SCAN_MODE mode, + uint16_t interval, + uint16_t window, + T_GAP_SCAN_FILTER_POLICY filter_policy, + uint8_t filter_duplicates, + uint32_t max_count + ) +{ + + T_TC_0101_IN_PARAM_DATA *p_tc_0101_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_0101_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_0101_IN_PARAM_DATA)); + + p_tc_0101_param_data->id = TC_0101_SCAN_STRESS_ENABLE_DISABLE; + p_tc_0101_param_data->mode = mode; + p_tc_0101_param_data->interval = interval; + p_tc_0101_param_data->window = window; + p_tc_0101_param_data->filter_policy = filter_policy; + p_tc_0101_param_data->filter_duplicates = filter_duplicates; + p_tc_0101_param_data->max_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_0101_param_data; + + os_queue_in(&tc_q, p_tc_param); + + +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_100.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_100.h new file mode 100644 index 00000000..0943e2a3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_100.h @@ -0,0 +1,89 @@ + +#ifndef _BLE_AUTO_TEST_TC_100_H_ +#define _BLE_AUTO_TEST_TC_100_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef struct t_scan_test_param +{ + uint16_t scan_interval; + uint16_t scan_window; + + uint32_t start_scan_begin_time; + uint32_t start_scan_end_time; + uint32_t stop_scan_begin_time; + uint32_t stop_scan_end_time; +} T_SCAN_TEST_PARAM; + + + +/** + for case TC_0100_SCAN_PERFORMANCE +*/ +void tc_0100_scan_perf_start(uint16_t scan_interval, uint16_t scan_window); +void tc_0100_scan_state_change_to_scaning(void); +void tc_0100_scan_state_change_to_idle(void); + + +/** + for case TC_0101_SCAN_STRESS_ENABLE_DISABLE +*/ +typedef struct +{ + T_GAP_SCAN_MODE mode; + uint16_t interval; + uint16_t window; + T_GAP_SCAN_FILTER_POLICY filter_policy; + uint8_t filter_duplicates; + + void *scan_enable_disable_timer_handle; + + uint32_t scan_enable_disable_begin_time; + uint32_t scan_enable_disable_max_enable_scan_ellapsed_time; + uint32_t scan_enable_disable_max_disable_scan_ellapsed_time; + uint32_t scan_enable_disable_max_count; + uint32_t scan_enable_disable_cur_count; +} T_TC_0101_PARAM; +typedef T_TC_0101_PARAM *P_TC_0101_PARAM; + + +typedef struct _T_TC_0101_IN_PARAM_DATA +{ + uint16_t id; + T_GAP_SCAN_MODE mode; + uint16_t interval; + uint16_t window; + T_GAP_SCAN_FILTER_POLICY filter_policy; + uint8_t filter_duplicates; + uint32_t max_count; +} T_TC_0101_IN_PARAM_DATA; + +void tc_0101_scan_stress_enable_disable_start(T_GAP_SCAN_MODE mode, + uint16_t interval, + uint16_t window, + T_GAP_SCAN_FILTER_POLICY filter_policy, + uint8_t filter_duplicates, + uint32_t max_count); +void tc_0101_scan_stress_enable_disable_state_change_to_scaning(void); +void tc_0101_scan_stress_enable_disable_state_change_to_idle(void); + + +void tc_0101_add_case(T_GAP_SCAN_MODE mode, + uint16_t interval, + uint16_t window, + T_GAP_SCAN_FILTER_POLICY filter_policy, + uint8_t filter_duplicates, + uint32_t max_count + ); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1000.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1000.c new file mode 100644 index 00000000..d51500de --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1000.c @@ -0,0 +1,236 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "vendor_tp_service.h" +#include +#include +#include "privacy_mgnt.h" +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI +#include "rtl876x_pinmux.h" +#include "rtl876x_rcc.h" + +#include +#include +#endif +#include +#include + +#if TC_1000_SUPPORT +void tc_1000_hw_init(void) +{ +#if 1 + //if reset PIN pull high + uint8_t cp_reset_pinmux = P2_7; + Pad_Config(cp_reset_pinmux, + PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); +#if 0 + //if reset PIN pull low + Pad_Config(cp_reset_pinmux, + PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_LOW); +#endif + Pinmux_Config(cp_reset_pinmux, DWGPIO); + + Pad_Config(ADC_2, + PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW); + Pad_Config(ADC_3, + PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, PAD_OUT_LOW); + + Pinmux_Config(ADC_2, I2C0_DAT); + Pinmux_Config(ADC_3, I2C0_CLK); +#endif + + + //if reset PIN pull high + cp_hw_init(I2C0, cp_reset_pinmux, false); +#if 0 + //if reset PIN pull low + cp_hw_init(I2C0, cp_reset_pinmux, true); +#endif + +} + + + +void tc_1000_start(void) +{ + APP_PRINT_TRACE0("tc_1000_start: ++"); + +#if 1 //test read device verison + uint8_t i = 0; + T_CP_CAUSE cp_cause = CP_CAUSE_SUCCESS; + + T_CP_INFO info = {0}; + + for (i = 1; i <= 1; i++) + { + cp_cause = cp_read_cp_info(&info); + if (cp_cause == CP_CAUSE_SUCCESS) + { + APP_PRINT_TRACE8("dev_ver 0x%02x, fw_ver 0x%02x, aup_mar_ver 0x%02x, aup_mir_ver 0x%02x, " + "dev_id 0x%02x%02x%02x%02x", + info.dev_ver, + info.fw_ver, + info.aup_mar_ver, + info.aup_mir_ver, + info.dev_id[0], + info.dev_id[1], + info.dev_id[2], + info.dev_id[3] + ); + + } + else + { + APP_PRINT_ERROR2("cp_read_cp_info: timeout i %d, cp_cause %d", i, cp_cause); + } + } + + +#endif + +#if 0 //test read all device information + T_CP_INFO info; + uint8_t a[8]; + uint32_t dev_id = 0xFFFFFFFF; + cp_read_cp_info(&info); + //cp_burst_read(0x00, a, 8); + dev_id = (((uint32_t)info.dev_id[0] << 24) | ((uint32_t)info.dev_id[1] << 16)\ + | ((uint32_t)info.dev_id[2] << 8) | ((uint32_t)info.dev_id[3] << 0)); + DBG_BUFFER(MODULE_APP, LEVEL_INFO, + "dev_verison = 0x%x, fw_verison = 0x%x, auth_protocol_mar = 0x%x,\ + auth_protocol_mir = 0x%x, device_id = 0x%x", 5, \ + info.dev_ver, info.fw_ver, info.aup_mar_ver, info.aup_mir_ver, dev_id); +#endif + +#if 0 //test cp_write + uint8_t cmd = 0x01; + cp_write(CP_REG_CS, &cmd, 1); +#endif + +#if 0 //test write challenge data + uint8_t cha_buf[34]; + uint8_t i = 0; + cha_buf[0] = 0; + cha_buf[1] = 32; + for (i = 0; i < 32; i++) + { + cha_buf[i + 2] = i + 1; + } + //cp_write_cha_info(cha_buf, 34); + + //uint8_t cha_buf1[34] = {0}; + //cp_burst_read(CP_REG_CHA_LEN, cha_buf1, 34); + +#endif + +#if 0 + T_CP_PRO_RES cp_res = CP_PRO_RES_NO_VALID; + T_CP_ERROR_CODE cp_err = CP_ERR_NO_ERR; + cp_write_cha_len(20); + cp_write_cha_data(cha_buf, 20); + //start signature + cp_ctrl(CP_CMD_START_SIG_GEN); + cp_res = cp_read_proc_result(); + if (cp_res == CP_PRO_RES_SIG_GEN_OK) + { + + } + else + { + cp_err = cp_read_err_code(); + } + + return; + +#endif + APP_PRINT_TRACE0("tc_1000_start: --"); + +} + +void cp_reset_internal(bool poll_low); + +void tc_1001_start(void) +{ + APP_PRINT_TRACE0("tc_1001_start: ++ poll high"); + + cp_reset_internal(false); + cp_set_slave_address(false); + uint8_t i = 0; + T_CP_CAUSE cp_cause = CP_CAUSE_SUCCESS; + + T_CP_INFO info = {0}; + + for (i = 1; i <= 1; i++) + { + cp_cause = cp_read_cp_info(&info); + if (cp_cause == CP_CAUSE_SUCCESS) + { + APP_PRINT_TRACE8("dev_ver 0x%02x, fw_ver 0x%02x, aup_mar_ver 0x%02x, aup_mir_ver 0x%02x, " + "dev_id 0x%02x%02x%02x%02x", + info.dev_ver, + info.fw_ver, + info.aup_mar_ver, + info.aup_mir_ver, + info.dev_id[0], + info.dev_id[1], + info.dev_id[2], + info.dev_id[3] + ); + + } + else + { + APP_PRINT_ERROR2("cp_read_cp_info: timeout i %d, cp_cause %d", i, cp_cause); + } + } + + APP_PRINT_TRACE0("tc_1001_start: --"); +} + + +void tc_1002_start(void) +{ + APP_PRINT_TRACE0("tc_1002_start: ++ poll low"); + + cp_reset_internal(true); + cp_set_slave_address(true); + uint8_t i = 0; + T_CP_CAUSE cp_cause = CP_CAUSE_SUCCESS; + + T_CP_INFO info = {0}; + + for (i = 1; i <= 1; i++) + { + cp_cause = cp_read_cp_info(&info); + if (cp_cause == CP_CAUSE_SUCCESS) + { + APP_PRINT_TRACE8("dev_ver 0x%02x, fw_ver 0x%02x, aup_mar_ver 0x%02x, aup_mir_ver 0x%02x, " + "dev_id 0x%02x%02x%02x%02x", + info.dev_ver, + info.fw_ver, + info.aup_mar_ver, + info.aup_mir_ver, + info.dev_id[0], + info.dev_id[1], + info.dev_id[2], + info.dev_id[3] + ); + + } + else + { + APP_PRINT_ERROR2("cp_read_cp_info: timeout i %d, cp_cause %d", i, cp_cause); + } + } + APP_PRINT_TRACE0("tc_1002_start: --"); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1000.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1000.h new file mode 100644 index 00000000..ae8eb0ed --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1000.h @@ -0,0 +1,23 @@ + +#ifndef _BLE_AUTO_TEST_TC_1000_H_ +#define _BLE_AUTO_TEST_TC_1000_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if F_CP_TEST_SUPPORT +void tc_1000_hw_init(void); +void tc_1000_start(void); +void tc_1001_start(void); +void tc_1002_start(void); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100.c new file mode 100644 index 00000000..a4c016ea --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100.c @@ -0,0 +1,591 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "gap_adv.h" +#include "os_sched.h" +#include +#include +#include +#include + +#if F_BT_LE_4_1_CBC_SUPPORT +#include "gap_credit_based_conn.h" +#endif + +#if TC_1100_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_disc_count; + uint32_t disc_error_cnt; + uint32_t data_receive_cnt; +} TC_1100_MGR; + +TC_1100_MGR *p_tc_1100_mgr = NULL; + +void tc_1100_start(uint32_t count) +{ + if (NULL == p_tc_1100_mgr) + { + p_tc_1100_mgr = (TC_1100_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_1100_MGR)); + } + else + { + memset(p_tc_1100_mgr, 0, sizeof(TC_1100_MGR)); + } + + p_tc_1100_mgr->total_test_count = count; + le_cbc_reg_psm(0x25, 1); + le_adv_start(); +} + +void tc_1100_dump_result(void) +{ + if (p_tc_1100_mgr != NULL) + { + APP_PRINT_INFO5("tc 1100: end: total_test_count %d total_connect_count %d total_disc_count %d" + "disc_error_cnt %d data_receive_cnt %d\r\n", + p_tc_1100_mgr->total_test_count, p_tc_1100_mgr->total_connect_count, + p_tc_1100_mgr->total_disc_count, p_tc_1100_mgr->disc_error_cnt, + p_tc_1100_mgr->data_receive_cnt); + + data_uart_print("tc 1100: end: total_test_count %d total_connect_count %d total_disc_count %d" + " disc_error_cnt %d data_receive_cnt %d\r\n", + p_tc_1100_mgr->total_test_count, p_tc_1100_mgr->total_connect_count, + p_tc_1100_mgr->total_disc_count, p_tc_1100_mgr->disc_error_cnt, + p_tc_1100_mgr->data_receive_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_1100_link_connected(uint8_t conn_id) +{ + +} + +void tc_1100_receive_data(uint16_t cid) +{ + p_tc_1100_mgr->data_receive_cnt++; +} + +void tc_1100_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1100_BT41_CONN_TEST, reason); + tc_1100_dump_result(); +} + +void tc_1100_chann_connected(uint16_t cid) +{ + p_tc_1100_mgr->total_connect_count++; +} + +void tc_1100_chann_disconnected(uint16_t cid, uint16_t cause) +{ + p_tc_1100_mgr->total_disc_count++; + if (cause == 0 || cause == (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + { + } + else + { + p_tc_1100_mgr->disc_error_cnt++; + APP_PRINT_ERROR1("tc_1100: error disconnect cause 0x%x", cause); + } +} +#endif + +#if TC_1101_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint16_t data_len; + uint16_t mtu; + uint16_t cid; + uint32_t data_rx_cnt; + uint32_t data_tx_cmpl_cnt; + uint32_t data_tx_cnt; +} TC_1101_MGR; + +TC_1101_MGR *p_tc_1101_mgr = NULL; + +void tc_1101_start(uint32_t count, uint16_t data_len) +{ + if (NULL == p_tc_1101_mgr) + { + p_tc_1101_mgr = (TC_1101_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_1101_MGR)); + } + else + { + memset(p_tc_1101_mgr, 0, sizeof(TC_1101_MGR)); + } + + p_tc_1101_mgr->total_test_count = count; + p_tc_1101_mgr->data_len = data_len; + le_cbc_reg_psm(0x25, 1); + le_adv_start(); +} + +void tc_1101_dump_result(void) +{ + if (p_tc_1101_mgr != NULL) + { + APP_PRINT_INFO4("tc 1101: end: total_test_count %d data_rx_cnt %d data_tx_cmpl_cnt %d" + "data_tx_cnt %d\r\n", + p_tc_1101_mgr->total_test_count, p_tc_1101_mgr->data_rx_cnt, + p_tc_1101_mgr->data_tx_cmpl_cnt, p_tc_1101_mgr->data_tx_cnt); + + data_uart_print("tc 1101: end: total_test_count %d data_rx_cnt %d data_tx_cmpl_cnt %d" + " data_tx_cnt %d\r\n", + p_tc_1101_mgr->total_test_count, p_tc_1101_mgr->data_rx_cnt, + p_tc_1101_mgr->data_tx_cmpl_cnt, p_tc_1101_mgr->data_tx_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_1101_link_connected(uint8_t conn_id) +{ +} + +void tc_1101_receive_data(uint16_t cid, uint16_t length) +{ + p_tc_1101_mgr->data_rx_cnt++; +} + +void tx_1101_send_data_cmpl(uint16_t cause, uint16_t credit) +{ + if (cause == 0) + { + p_tc_1101_mgr->data_tx_cmpl_cnt++; + T_GAP_CAUSE cause; + void *p_buffer; + uint8_t i; + uint16_t length = p_tc_1101_mgr->data_len; + + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, 2, length); + } + for (i = 0; i < credit; i++) + { + if (p_tc_1101_mgr->data_tx_cnt == p_tc_1101_mgr->total_test_count) + { + break; + } + cause = le_cbc_send_data(p_tc_1101_mgr->cid, p_buffer, length); + p_tc_1101_mgr->data_tx_cnt++; + if (cause != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("tc_1101: send data failed 0x%x", cause); + break; + } + } + os_mem_free(p_buffer); + } +} + +void tc_1101_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1101_BT41_TRX_STRESS_TEST, reason); + tc_1101_dump_result(); +} + +void tc_1101_chann_connected(uint16_t cid, uint16_t mtu, uint16_t credit) +{ + T_GAP_CAUSE cause; + void *p_buffer; + uint8_t i; + uint16_t length; + p_tc_1101_mgr->mtu = mtu; + p_tc_1101_mgr->cid = cid; + if (p_tc_1101_mgr->data_len == 0 || p_tc_1101_mgr->data_len >= p_tc_1101_mgr->mtu) + { + p_tc_1101_mgr->data_len = p_tc_1101_mgr->mtu; + } + length = p_tc_1101_mgr->data_len; + + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, 2, length); + } + for (i = 0; i < credit; i++) + { + cause = le_cbc_send_data(cid, p_buffer, length); + p_tc_1101_mgr->data_tx_cnt++; + if (cause != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("tc_1101: send data failed 0x%x", cause); + break; + } + } + os_mem_free(p_buffer); +} + +void tc_1101_chann_disconnected(uint16_t cid, uint16_t cause) +{ + if (cause == 0 || cause == (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + { + } + else + { + APP_PRINT_ERROR1("tc_1101: error disconnect cause 0x%x", cause); + } +} +#endif + +#if TC_1102_SUPPORT +typedef struct +{ + uint16_t mtu; + uint16_t cid; +} TC_1102_MGR; + +TC_1102_MGR *p_tc_1102_mgr = NULL; + +typedef struct +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + uint16_t length; + uint32_t count; + uint32_t count_remain; + uint8_t initial_value; + bool is_update; + + uint8_t conn_id; + uint32_t begin_time; + uint32_t end_time; + uint32_t data_rate; +} T_1102_TEST_PARAM; + +#define MAX_TP_TEST_COUNT 1000 +#define TP_TEST_PARAM_COUNT 8 +T_1102_TEST_PARAM g_1102_test_param[TP_TEST_PARAM_COUNT]; +uint8_t g_1102_cur_test_index = 0; +uint8_t g_1102_used_test_index = 0; +uint8_t g_1102_test_start = false; + +void tc_1102_tx_config_with_fixed_length(uint16_t length) +{ + uint8_t i = 0; + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 6; + g_1102_test_param[i].conn_slave_latency = 0; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 6; + g_1102_test_param[i].conn_slave_latency = 50; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 10; + g_1102_test_param[i].conn_slave_latency = 0; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 10; + g_1102_test_param[i].conn_slave_latency = 50; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 15; + g_1102_test_param[i].conn_slave_latency = 0; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 15; + g_1102_test_param[i].conn_slave_latency = 50; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 20; + g_1102_test_param[i].conn_slave_latency = 0; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + i++; + + g_1102_test_param[i].conn_id = 0; + g_1102_test_param[i].con_interval = 20; + g_1102_test_param[i].conn_slave_latency = 50; + g_1102_test_param[i].conn_supervision_timeout = 1000; + g_1102_test_param[i].length = length; + g_1102_test_param[i].count = MAX_TP_TEST_COUNT; + g_1102_test_param[i].count_remain = g_1102_test_param[i].count; + g_1102_test_param[i].initial_value = 0; + + g_1102_used_test_index = i; +} + +void tc_1102_start(uint16_t data_len) +{ + if (NULL == p_tc_1102_mgr) + { + p_tc_1102_mgr = (TC_1102_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_1102_MGR)); + } + else + { + memset(p_tc_1102_mgr, 0, sizeof(TC_1102_MGR)); + } + memset(g_1102_test_param, 0, sizeof(g_1102_test_param)); + tc_1102_tx_config_with_fixed_length(data_len); + le_cbc_reg_psm(0x25, 1); + le_adv_start(); +} + +bool tc_1102_send_data(uint16_t *p_credit) +{ + void *p_buffer; + uint16_t length = g_1102_test_param[g_1102_cur_test_index].length; + + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, g_1102_test_param[g_1102_cur_test_index].initial_value, length); + } + else + { + return false; + } + + if (le_cbc_send_data(p_tc_1102_mgr->cid, p_buffer, length) == GAP_CAUSE_SUCCESS) + { + (*p_credit)--; + g_1102_test_param[g_1102_cur_test_index].initial_value++; + g_1102_test_param[g_1102_cur_test_index].count_remain--; + os_mem_free(p_buffer); + return true; + } + else + { + APP_PRINT_ERROR0("tc_1102_send_data send: failed"); + os_mem_free(p_buffer); + return false; + } +} + +void tc_1102_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_1102_test_param[g_1102_cur_test_index].con_interval == con_interval && + g_1102_test_param[g_1102_cur_test_index].conn_slave_latency == conn_slave_latency && + g_1102_test_param[g_1102_cur_test_index].conn_supervision_timeout == conn_supervision_timeout + ) + { + g_1102_test_param[g_1102_cur_test_index].is_update = true; + if (p_tc_1102_mgr->cid != 0) + { + uint16_t cur_credit; + g_1102_test_param[g_1102_cur_test_index].begin_time = os_sys_time_get(); + APP_PRINT_INFO1("tc 1102 test: begin time = %dms", + g_1102_test_param[g_1102_cur_test_index].begin_time); + le_cbc_get_chann_param(CBC_CHANN_PARAM_CUR_CREDITS, &cur_credit, p_tc_1102_mgr->cid); + while (cur_credit) + { + if (g_1102_test_param[g_1102_cur_test_index].count_remain) + { + if (tc_1102_send_data(&cur_credit) == false) + { + break; + } + } + else + { + break; + } + } + } + } + +} + +void tc_1102_mtu_size_info(uint8_t conn_id) +{ + g_1102_test_start = true; + g_1102_cur_test_index = 0; + + le_update_conn_param(g_1102_test_param[g_1102_cur_test_index].conn_id, + g_1102_test_param[g_1102_cur_test_index].con_interval, + g_1102_test_param[g_1102_cur_test_index].con_interval, + g_1102_test_param[g_1102_cur_test_index].conn_slave_latency, + g_1102_test_param[g_1102_cur_test_index].conn_supervision_timeout, + 2 * (g_1102_test_param[g_1102_cur_test_index].con_interval - 1), + 2 * (g_1102_test_param[g_1102_cur_test_index].con_interval - 1)); +} + + +static bool flag1102 = false; +void tc_1102_send_data_cmpl(uint16_t cause, uint16_t credit) +{ + uint16_t max_credit; + le_cbc_get_chann_param(CBC_CHANN_PARAM_MAX_CREDITS, &max_credit, p_tc_1102_mgr->cid); + while (credit) + { + if (g_1102_test_param[g_1102_cur_test_index].count_remain) + { + if (tc_1102_send_data(&credit) == false) + { + return; + } + } + else + { + if (credit == max_credit) + { + g_1102_test_param[g_1102_cur_test_index].end_time = os_sys_time_get(); + uint32_t elapsed_time = os_time_get_elapsed(g_1102_test_param[g_1102_cur_test_index].begin_time, + g_1102_test_param[g_1102_cur_test_index].end_time); + uint32_t data_rate = + g_1102_test_param[g_1102_cur_test_index].count * g_1102_test_param[g_1102_cur_test_index].length * + 1000 / + (elapsed_time); + + APP_PRINT_INFO8("tc 1102 test: end:conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_1102_test_param[g_1102_cur_test_index].con_interval, + g_1102_test_param[g_1102_cur_test_index].conn_slave_latency, + g_1102_test_param[g_1102_cur_test_index].length, + g_1102_test_param[g_1102_cur_test_index].count, + g_1102_test_param[g_1102_cur_test_index].begin_time, + g_1102_test_param[g_1102_cur_test_index].end_time, + elapsed_time, + data_rate); + if (false == flag1102) + { + data_uart_print(" conn_interval, latency, length, data rate(Bytes/s)\r\n"); + flag1102 = true; + } + data_uart_print(" %d, %d, %d, %d\r\n", + g_1102_test_param[g_1102_cur_test_index].con_interval, + g_1102_test_param[g_1102_cur_test_index].conn_slave_latency, + g_1102_test_param[g_1102_cur_test_index].length, + data_rate); + if (g_1102_cur_test_index < g_1102_used_test_index) + { + g_1102_cur_test_index++; + APP_PRINT_INFO2("g_1102_cur_test_index = %d, interval = %d", g_1102_cur_test_index, + g_1102_test_param[g_1102_cur_test_index].con_interval); + le_update_conn_param(g_1102_test_param[g_1102_cur_test_index].conn_id, + g_1102_test_param[g_1102_cur_test_index].con_interval, + g_1102_test_param[g_1102_cur_test_index].con_interval, + g_1102_test_param[g_1102_cur_test_index].conn_slave_latency, + g_1102_test_param[g_1102_cur_test_index].conn_supervision_timeout, + 2 * (g_1102_test_param[g_1102_cur_test_index].con_interval - 1), + 2 * (g_1102_test_param[g_1102_cur_test_index].con_interval - 1) + ); + + } + else + { + le_cbc_disc(p_tc_1102_mgr->cid); + } + } + break; + } + } +} + +void tc_1102_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1102_BT41_TP_TEST, reason); +} + +void tc_1102_chann_connected(uint16_t cid, uint16_t mtu, uint16_t credit) +{ + p_tc_1102_mgr->cid = cid; + p_tc_1102_mgr->mtu = mtu; + if (g_1102_test_param[g_1102_cur_test_index].is_update == true) + { + uint16_t cur_credit; + g_1102_test_param[g_1102_cur_test_index].begin_time = os_sys_time_get(); + APP_PRINT_INFO1("tc 1102 test: begin time = %dms", + g_1102_test_param[g_1102_cur_test_index].begin_time); + le_cbc_get_chann_param(CBC_CHANN_PARAM_CUR_CREDITS, &cur_credit, p_tc_1102_mgr->cid); + while (cur_credit) + { + if (g_1102_test_param[g_1102_cur_test_index].count_remain) + { + if (tc_1102_send_data(&cur_credit) == false) + { + break; + } + } + else + { + break; + } + } + } +} + +void tc_1102_chann_disconnected(uint16_t cid, uint16_t cause) +{ + if (cause == 0 || cause == (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + { + } + else + { + APP_PRINT_ERROR1("tc_1102: error disconnect cause 0x%x", cause); + } +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100.h new file mode 100644 index 00000000..9b8ef713 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100.h @@ -0,0 +1,82 @@ + +#ifndef _BLE_AUTO_TEST_TC_1100_H_ +#define _BLE_AUTO_TEST_TC_1100_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +void tc_1100_start(uint32_t count); +void tc_1100_link_connected(uint8_t conn_id); +void tc_1100_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1100_chann_connected(uint16_t cid); +void tc_1100_chann_disconnected(uint16_t cid, uint16_t cause); +void tc_1100_dump_result(void); +void tc_1100_receive_data(uint16_t cid); + +void tc_1101_start(uint32_t count, uint16_t data_len); +void tc_1101_dump_result(void); +void tc_1101_link_connected(uint8_t conn_id); +void tc_1101_receive_data(uint16_t cid, uint16_t length); +void tx_1101_send_data_cmpl(uint16_t cause, uint16_t credit); +void tc_1101_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1101_chann_connected(uint16_t cid, uint16_t mtu, uint16_t credit); +void tc_1101_chann_disconnected(uint16_t cid, uint16_t cause); + +void tc_1102_start(uint16_t data_len); +void tc_1102_conn_param_update_event(uint8_t conn_id); +void tc_1102_mtu_size_info(uint8_t conn_id); +void tc_1102_send_data_cmpl(uint16_t cause, uint16_t credit); +void tc_1102_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1102_chann_connected(uint16_t cid, uint16_t mtu, uint16_t credit); +void tc_1102_chann_disconnected(uint16_t cid, uint16_t cause); +#endif +#if 0 +typedef struct t_tp_test_config +{ + uint16_t con_interval; + uint16_t length; + uint8_t tx_octets; + +} T_TP_TEST_CONFIG; + + +typedef struct t_tp_test_param +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + uint16_t length; + uint32_t count; + uint32_t count_remain; + uint8_t initial_value; + + uint8_t conn_id; + uint32_t begin_time; + uint32_t end_time; + uint32_t data_rate; +} T_TP_TEST_PARAM; + + +/** + for case TC_0200_TP_NOTIFICATION_TX_01 +*/ +void tc_200_tp_notification_tx_start(void); +void tc_200_tp_notification_tx_init_config(uint16_t con_interval, uint16_t length, + uint8_t tx_octets); +void tc_200_tp_notification_tx_init_default_param(uint8_t conn_id); +void tc_200_tp_notification_tx_change_tx_octets(uint8_t conn_id, uint16_t tx_octets); +void tc_200_tp_notification_tx_config_with_fixed_interval(uint16_t con_interval); +void tc_200_tp_notification_tx_config_with_fixed_length(uint16_t length); +void tc_200_tp_notification_tx_conn_param_update_event(uint8_t conn_id); +void tc_200_tp_notification_tx_tx_data_complete(uint8_t credits); +void tc_200_tp_notification_tx_tx_config(void *pdata); +#endif +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100_sut.c new file mode 100644 index 00000000..866d198b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100_sut.c @@ -0,0 +1,453 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + + +#include +#include + + +#include +#include +#include + + +#if F_BT_LE_4_1_CBC_SUPPORT +#include "gap_credit_based_conn.h" +#endif + +#if TC_1100_SUT_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint32_t totol_connect_req; + uint32_t total_connect_count; + uint32_t total_disc_count; + uint32_t disc_error_cnt; + uint32_t data_send_cnt; + uint8_t remote_bd[6]; + uint16_t cid; +} TC_1100_SUT_MGR; + +TC_1100_SUT_MGR *p_tc_1100_sut_mgr = NULL; + +void tc_1100_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 10000; + + if (NULL == p_tc_1100_sut_mgr) + { + p_tc_1100_sut_mgr = (TC_1100_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_1100_SUT_MGR)); + } + else + { + memset(p_tc_1100_sut_mgr, 0, sizeof(TC_1100_SUT_MGR)); + } + + p_tc_1100_sut_mgr->total_test_count = count; + memcpy(p_tc_1100_sut_mgr->remote_bd, remote_bd, 6); + le_cbc_reg_psm(0x25, 1); + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_1100_sut_mgr->remote_bd, GAP_REMOTE_ADDR_LE_PUBLIC, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout + ); +} + +void tc_1100_sut_dump_result(void) +{ + if (p_tc_1100_sut_mgr != NULL) + { + APP_PRINT_INFO5("tc 1100 sut: end: total_test_count %d total_connect_count %d total_disc_count %d" + "disc_error_cnt %d data_send_cnt %d\r\n", + p_tc_1100_sut_mgr->total_test_count, p_tc_1100_sut_mgr->total_connect_count, + p_tc_1100_sut_mgr->total_disc_count, p_tc_1100_sut_mgr->disc_error_cnt, + p_tc_1100_sut_mgr->data_send_cnt); + + data_uart_print("tc 1100 sut: end: total_test_count %d total_connect_count %d total_disc_count %d" + "disc_error_cnt %d data_send_cnt %d\r\n", + p_tc_1100_sut_mgr->total_test_count, p_tc_1100_sut_mgr->total_connect_count, + p_tc_1100_sut_mgr->total_disc_count, p_tc_1100_sut_mgr->disc_error_cnt, + p_tc_1100_sut_mgr->data_send_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_1100_sut_link_connected(uint8_t conn_id) +{ + p_tc_1100_sut_mgr->totol_connect_req++; + le_cbc_create(conn_id, 0x25); +} + +void tc_1100_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(TC_1100_BT41_CONN_TEST, reason); + tc_1100_sut_dump_result(); +} + +void tc_1100_sut_chann_connected(uint16_t cid) +{ + uint8_t data[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; + p_tc_1100_sut_mgr->total_connect_count++; + p_tc_1100_sut_mgr->cid = cid; + le_cbc_send_data(cid, data, 20); +} + +void tc_1100_sut_chann_data_send_cmpl(uint16_t cause) +{ + if (cause == 0) + { + p_tc_1100_sut_mgr->data_send_cnt++; + } + le_cbc_disc(p_tc_1100_sut_mgr->cid); +} + +void tc_1100_sut_chann_disconnected(uint16_t cid, uint16_t cause) +{ + p_tc_1100_sut_mgr->total_disc_count++; + if (cause == 0 || cause == (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + } + else + { + p_tc_1100_sut_mgr->disc_error_cnt++; + APP_PRINT_ERROR1("tc_1100_sut: error disconnect cause 0x%x", cause); + } + if (p_tc_1100_sut_mgr->totol_connect_req == p_tc_1100_sut_mgr->total_test_count) + { + le_disconnect(0); + } + else + { + p_tc_1100_sut_mgr->totol_connect_req++; + le_cbc_create(0, 0x25); + } +} +#endif + +#if TC_1101_SUT_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint16_t data_len; + uint16_t mtu; + uint16_t cid; + uint32_t data_rx_cnt; + uint32_t data_tx_cmpl_cnt; + uint32_t data_tx_cnt; + uint8_t remote_bd[6]; +} TC_1101_SUT_MGR; + +TC_1101_SUT_MGR *p_tc_1101_sut_mgr = NULL; + +void tc_1101_sut_timeout_handler(void *pxTimer) +{ + APP_PRINT_INFO0("tc_1101_sut_timeout_handler"); + le_cbc_disc(p_tc_1101_sut_mgr->cid); +} + +void tc_1101_sut_start(uint32_t count, uint8_t remote_bd[6], uint16_t data_len) +{ + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 10000; + + if (NULL == p_tc_1101_sut_mgr) + { + p_tc_1101_sut_mgr = (TC_1101_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_1101_SUT_MGR)); + } + else + { + memset(p_tc_1101_sut_mgr, 0, sizeof(TC_1101_SUT_MGR)); + } + if (NULL == g_test_timer_handle) + { + os_timer_create(&g_test_timer_handle, "testTimer", 1, 5000, false, tc_1101_sut_timeout_handler); + } + + p_tc_1101_sut_mgr->data_len = data_len; + p_tc_1101_sut_mgr->total_test_count = count; + memcpy(p_tc_1101_sut_mgr->remote_bd, remote_bd, 6); + le_cbc_reg_psm(0x25, 1); + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_1101_sut_mgr->remote_bd, GAP_REMOTE_ADDR_LE_PUBLIC, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout + ); +} + +void tc_1101_sut_dump_result(void) +{ + if (p_tc_1101_sut_mgr != NULL) + { + APP_PRINT_INFO4("tc 1101 sut: end: total_test_count %d data_rx_cnt %d data_tx_cmpl_cnt %d" + "data_tx_cnt %d\r\n", + p_tc_1101_sut_mgr->total_test_count, + p_tc_1101_sut_mgr->data_rx_cnt, + p_tc_1101_sut_mgr->data_tx_cmpl_cnt, + p_tc_1101_sut_mgr->data_tx_cnt); + + data_uart_print("tc 1101 sut: end: total_test_count %d data_rx_cnt %d data_tx_cmpl_cnt %d" + "data_tx_cnt %d\r\n", + p_tc_1101_sut_mgr->total_test_count, + p_tc_1101_sut_mgr->data_rx_cnt, + p_tc_1101_sut_mgr->data_tx_cmpl_cnt, + p_tc_1101_sut_mgr->data_tx_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_1101_sut_link_connected(uint8_t conn_id) +{ + le_cbc_create(conn_id, 0x25); +} + +void tc_1101_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(TC_1101_BT41_TRX_STRESS_TEST, reason); + tc_1101_sut_dump_result(); +} + +void tc_1101_sut_chann_connected(uint16_t cid, uint16_t mtu, uint8_t credit) +{ + T_GAP_CAUSE cause; + void *p_buffer; + uint8_t i; + uint16_t length; + p_tc_1101_sut_mgr->mtu = mtu; + p_tc_1101_sut_mgr->cid = cid; + if (p_tc_1101_sut_mgr->data_len == 0 || p_tc_1101_sut_mgr->data_len >= p_tc_1101_sut_mgr->mtu) + { + p_tc_1101_sut_mgr->data_len = p_tc_1101_sut_mgr->mtu; + } + length = p_tc_1101_sut_mgr->data_len; + + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, 2, length); + } + for (i = 0; i < credit; i++) + { + cause = le_cbc_send_data(cid, p_buffer, length); + p_tc_1101_sut_mgr->data_tx_cnt++; + if (cause != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("tc_1101: send data failed 0x%x", cause); + break; + } + } + os_mem_free(p_buffer); +} + +void tc_1101_sut_receive_data(uint16_t cid, uint16_t length) +{ + p_tc_1101_sut_mgr->data_rx_cnt++; +} + +void tc_1101_sut_chann_data_send_cmpl(uint16_t cause, uint8_t credit) +{ + if (cause == 0) + { + p_tc_1101_sut_mgr->data_tx_cmpl_cnt++; + T_GAP_CAUSE cause; + void *p_buffer; + uint8_t i; + uint16_t length = p_tc_1101_sut_mgr->data_len; + + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, 2, length); + } + for (i = 0; i < credit; i++) + { + if (p_tc_1101_sut_mgr->data_tx_cnt == p_tc_1101_sut_mgr->total_test_count) + { + break; + } + cause = le_cbc_send_data(p_tc_1101_sut_mgr->cid, p_buffer, length); + p_tc_1101_sut_mgr->data_tx_cnt++; + if (cause != GAP_CAUSE_SUCCESS) + { + APP_PRINT_ERROR1("tc_1101: send data failed 0x%x", cause); + break; + } + } + os_mem_free(p_buffer); + } + if (p_tc_1101_sut_mgr->data_tx_cnt == p_tc_1101_sut_mgr->total_test_count) + { + uint16_t cur_credit; + uint16_t max_credit; + le_cbc_get_chann_param(CBC_CHANN_PARAM_CUR_CREDITS, &cur_credit, p_tc_1101_sut_mgr->cid); + le_cbc_get_chann_param(CBC_CHANN_PARAM_MAX_CREDITS, &max_credit, p_tc_1101_sut_mgr->cid); + if (cur_credit == max_credit) + { + //start total timer + os_timer_start(&g_test_timer_handle); + } + } +} + +void tc_1101_sut_chann_disconnected(uint16_t cid, uint16_t cause) +{ + if (cause == 0 || cause == (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + } + else + { + APP_PRINT_ERROR1("tc_1101_sut: error disconnect cause 0x%x", cause); + } + le_disconnect(0); +} +#endif + +#if TC_1102_SUT_SUPPORT +typedef struct +{ + uint32_t total_rx_count; + uint32_t rx_count; + uint16_t mtu; + uint16_t cid; + uint8_t remote_bd[6]; +} TC_1102_SUT_MGR; + +TC_1102_SUT_MGR *p_tc_1102_sut_mgr = NULL; + +void tc_1102_sut_start(uint8_t remote_bd[6]) +{ + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 10000; + + if (NULL == p_tc_1102_sut_mgr) + { + p_tc_1102_sut_mgr = (TC_1102_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_1102_SUT_MGR)); + } + else + { + memset(p_tc_1102_sut_mgr, 0, sizeof(TC_1102_SUT_MGR)); + } + + memcpy(p_tc_1102_sut_mgr->remote_bd, remote_bd, 6); + le_cbc_reg_psm(0x25, 1); + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_1102_sut_mgr->remote_bd, GAP_REMOTE_ADDR_LE_PUBLIC, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout + ); +} + +void tc_1102_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO4("tc_1102_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x, total_rx_count %d", + con_interval, conn_slave_latency, conn_supervision_timeout, + p_tc_1102_sut_mgr->rx_count); + + data_uart_print("interval = 0x%x, latency = 0x%x, timeout = 0x%x, total_rx_count %d\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout, + p_tc_1102_sut_mgr->rx_count); + p_tc_1102_sut_mgr->rx_count = 0; +} + +void tc_1102_sut_dump_result(void) +{ + if (p_tc_1102_sut_mgr != NULL) + { + APP_PRINT_INFO2("tc 1102 sut: end: rx_count %d total_rx_count %d\r\n", + p_tc_1102_sut_mgr->rx_count, + p_tc_1102_sut_mgr->total_rx_count); + + data_uart_print("tc 1102 sut: end: rx_count %d total_rx_count %d\r\n", + p_tc_1102_sut_mgr->rx_count, + p_tc_1102_sut_mgr->total_rx_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_1102_sut_link_connected(uint8_t conn_id) +{ + le_cbc_create(conn_id, 0x25); +} + +void tc_1102_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(TC_1102_BT41_TP_TEST, reason); + tc_1102_sut_dump_result(); +} + +void tc_1102_sut_chann_connected(uint16_t cid, uint16_t mtu, uint8_t credit) +{ + p_tc_1102_sut_mgr->mtu = mtu; + p_tc_1102_sut_mgr->cid = cid; +} + +void tc_1102_sut_receive_data(uint16_t cid, uint16_t length) +{ + p_tc_1102_sut_mgr->rx_count++; + p_tc_1102_sut_mgr->total_rx_count++; +} + +void tc_1102_sut_chann_disconnected(uint16_t cid, uint16_t cause) +{ + if (cause == 0 || cause == (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + } + else + { + APP_PRINT_ERROR1("tc_1102_sut: error disconnect cause 0x%x", cause); + } + le_disconnect(0); +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100_sut.h new file mode 100644 index 00000000..9af565ec --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1100_sut.h @@ -0,0 +1,89 @@ + +#ifndef _BLE_AUTO_TEST_TC_1100_SUT_H_ +#define _BLE_AUTO_TEST_TC_1100_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +void tc_1100_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_1100_sut_dump_result(void); +void tc_1100_sut_link_connected(uint8_t conn_id); +void tc_1100_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1100_sut_chann_connected(uint16_t cid); +void tc_1100_sut_chann_data_send_cmpl(uint16_t cause); +void tc_1100_sut_chann_disconnected(uint16_t cid, uint16_t cause); + +void tc_1101_sut_start(uint32_t count, uint8_t remote_bd[6], uint16_t data_len); +void tc_1101_sut_dump_result(void); +void tc_1101_sut_link_connected(uint8_t conn_id); +void tc_1101_sut_receive_data(uint16_t cid, uint16_t length); +void tc_1101_sut_chann_data_send_cmpl(uint16_t cause, uint8_t credit); +void tc_1101_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1101_sut_chann_connected(uint16_t cid, uint16_t mtu, uint8_t credit); +void tc_1101_sut_chann_disconnected(uint16_t cid, uint16_t cause); + +void tc_1102_sut_start(uint8_t remote_bd[6]); +void tc_1102_sut_conn_param_update_event(uint8_t conn_id); +void tc_1102_sut_dump_result(void); +void tc_1102_sut_link_connected(uint8_t conn_id); +void tc_1102_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1102_sut_chann_connected(uint16_t cid, uint16_t mtu, uint8_t credit); +void tc_1102_sut_receive_data(uint16_t cid, uint16_t length); +void tc_1102_sut_chann_disconnected(uint16_t cid, uint16_t cause); +#if 0 +typedef void (*P_FUN_PROFILE_CLIENT_RESULT_CB)(uint8_t conn_id, void *p_data); + +typedef enum +{ + TP_CONFIG_OP_SET_LL_DATA_LEN_27 = 1, + TP_CONFIG_OP_SET_LL_DATA_LEN_251 = 2, + TP_CONFIG_OP_START = 3, + + TP_CONFIG_OP_RFU = 0xFF +} T_TP_CONFIG_OP; + + +typedef enum +{ + TP_CONFIG_STATE_CONFIGING = 1, + TP_CONFIG_STATE_STARTED = 2, + + TP_CONFIG_STATE_RFU = 0xFF +} T_TP_CONFIG_STATE; + +void tc_20x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data); + + +/** + +*/ +typedef struct _T_TC_200_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_TP_CONFIG_STATE cur_config_state; + T_TP_CONFIG_OP cur_config_op; + uint32_t total_notify_rx_count; +} T_TC_200_SUT_IN_PARAM_DATA; + +void tc_200_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_200_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_200_sut_link_connected(uint8_t conn_id); +void tc_200_sut_conn_param_update_event(uint8_t conn_id); +void tc_200_sut_dump_result(void); +void tc_200_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200.c new file mode 100644 index 00000000..f2806e4f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200.c @@ -0,0 +1,1244 @@ + +#include +#include "os_timer.h" +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + + +#include +#include + +#include +#include +#include + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif + + +#if TC_1200_SUPPORT + +void tc_1200_start(uint32_t count) +{ + uint16_t scan_interval = 400; + uint16_t scan_window = 200; + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_start(); +} + +void tc_1200_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1200_timer_handle = NULL; + +void tc_1200_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_1200_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1200 Test success\r\n"); + le_disconnect(0); + } +} + +void tc_1200_link_connected(uint8_t conn_id) +{ + data_uart_print("tc_1200_link_connected: conn_id %d\r\n", conn_id); + uint8_t addr[6]; + T_GAP_REMOTE_ADDR_TYPE bd_type; + le_get_conn_addr(conn_id, addr, &bd_type); + data_uart_print("conn_id %d, bd_addr 0x%02x%02x%02x%02x%02x%02x\r\n", + conn_id, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); + + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[1].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[2].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[2].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[3].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[3].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1200_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1200_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1200_timer_handle); + } +} + +void tc_1200_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("tc_1200_link_disconnected: conn_id %d, reason 0x%x\r\n", conn_id, reason); + + if (reason != (HCI_ERR_LOCAL_HOST_TERMINATE | HCI_ERR)) + { + + data_uart_print(" TC 1200 Test fail\r\n"); + os_timer_stop(&g_tc_1200_timer_handle); + return; + } + + if (conn_id == 0) + { + le_disconnect(1); + } + else if (conn_id == 1) + { + le_disconnect(2); + } + else if (conn_id == 2) + { + le_disconnect(3); + } + else if (conn_id == 3) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + data_uart_print(" TC 1200 All link disconneced, Test again\r\n"); + } +} + +void tc_1200_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1200_timer_handle); +} + + + +void tc_1200_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1200_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + + +#if TC_1201_SUPPORT + +void tc_1201_start(uint32_t count) +{ + le_adv_start(); +} + +void tc_1201_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1201_timer_handle = NULL; + +void tc_1201_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + + APP_PRINT_INFO3("tc_1200_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1201 Test success\r\n"); + le_disconnect(1); + } +} + +void tc_1201_link_connected(uint8_t conn_id) +{ + data_uart_print("tc_1201_link_connected: conn_id %d\r\n", conn_id); + uint8_t addr[6]; + T_GAP_REMOTE_ADDR_TYPE bd_type; + le_get_conn_addr(conn_id, addr, &bd_type); + data_uart_print("conn_id %d, bd_addr 0x%02x%02x%02x%02x%02x%02x\r\n", + conn_id, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); + + if (conn_id == 0) + { + uint16_t scan_interval = 400; + uint16_t scan_window = 200; + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_start(); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[1].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[2].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[2].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1201_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1201_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1201_timer_handle); + } +} + +void tc_1201_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("tc_1201_link_disconnected: conn_id %d, reason 0x%x\r\n", conn_id, reason); + if (reason != (HCI_ERR_LOCAL_HOST_TERMINATE | HCI_ERR)) + { + data_uart_print(" TC 1201 Test fail\r\n"); + os_timer_stop(&g_tc_1201_timer_handle); + return; + } + + if (conn_id == 0) + { + le_disconnect(1); + } + else if (conn_id == 1) + { + le_disconnect(2); + } + else if (conn_id == 2) + { + le_disconnect(3); + } + else if (conn_id == 3) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + data_uart_print(" TC 1201 All link disconneced, Test again\r\n"); + } + +} + +void tc_1201_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1201_timer_handle); +} + +void tc_1201_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1201_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + +#if TC_1202_SUPPORT + +void tc_1202_start(uint32_t count) +{ + uint16_t scan_interval = 400; + uint16_t scan_window = 200; + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_start(); +} + +void tc_1202_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 6; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1202_timer_handle = NULL; + +void tc_1202_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_1200_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1200 Test success\r\n"); + le_disconnect(0); + } +} + +void tc_1202_link_connected(uint8_t conn_id) +{ + data_uart_print("tc_1202_link_connected: conn_id %d\r\n", conn_id); + uint8_t addr[6]; + T_GAP_REMOTE_ADDR_TYPE bd_type; + le_get_conn_addr(conn_id, addr, &bd_type); + data_uart_print("conn_id %d, bd_addr 0x%02x%02x%02x%02x%02x%02x\r\n", + conn_id, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); + + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 9; + conn_param.conn_interval_max = 18; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[1].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 24; + conn_param.conn_interval_max = 24; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[2].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[3].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1202_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1202_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1202_timer_handle); + } +} + +void tc_1202_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("tc_1202_link_disconnected: conn_id %d, reason 0x%x\r\n", conn_id, reason); + + if (reason != (HCI_ERR_LOCAL_HOST_TERMINATE | HCI_ERR)) + { + data_uart_print(" TC 1200 Test fail\r\n"); + os_timer_stop(&g_tc_1202_timer_handle); + return; + } + + if (conn_id == 0) + { + le_disconnect(1); + } + else if (conn_id == 1) + { + le_disconnect(2); + } + else if (conn_id == 2) + { + le_disconnect(3); + } + else if (conn_id == 3) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + data_uart_print(" TC 1202 All link disconneced, Test again\r\n"); + } + +} + +void tc_1202_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1202_timer_handle); +} + +void tc_1202_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1202_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + +#if TC_1203_SUPPORT + +void tc_1203_start(uint32_t count) +{ + uint16_t scan_interval = 400; + uint16_t scan_window = 200; + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_start(); +} + +void tc_1203_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 9; + conn_param.conn_interval_max = 18; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1203_timer_handle = NULL; + +void tc_1203_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_1200_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1203 Test success\r\n"); + le_disconnect(0); + } +} + +void tc_1203_link_connected(uint8_t conn_id) +{ + data_uart_print("tc_1203_link_connected: conn_id %d\r\n", conn_id); + uint8_t addr[6]; + T_GAP_REMOTE_ADDR_TYPE bd_type; + le_get_conn_addr(conn_id, addr, &bd_type); + data_uart_print("conn_id %d, bd_addr 0x%02x%02x%02x%02x%02x%02x\r\n", + conn_id, addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]); + + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 6; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[1].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 24; + conn_param.conn_interval_max = 24; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[2].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[3].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1203_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1203_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1203_timer_handle); + } +} + +void tc_1203_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("tc_1203_link_disconnected: conn_id %d, reason 0x%x\r\n", conn_id, reason); + + if (reason != (HCI_ERR_LOCAL_HOST_TERMINATE | HCI_ERR)) + { + data_uart_print(" TC 1203 Test fail\r\n"); + os_timer_stop(&g_tc_1203_timer_handle); + return; + } + + if (conn_id == 0) + { + le_disconnect(1); + } + else if (conn_id == 1) + { + le_disconnect(2); + } + else if (conn_id == 2) + { + le_disconnect(3); + } + else if (conn_id == 3) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + data_uart_print(" TC 1203 All link disconneced, Test again\r\n"); + } + +} + +void tc_1203_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1203_timer_handle); +} + +void tc_1203_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1203_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + +#if TC_1204_SUPPORT + +void tc_1204_start(uint32_t count) +{ + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint16_t ext_scan_duration = 0; + uint16_t ext_scan_period = 0; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + + link_mgr_clear_device_list(); + + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_DURATION, sizeof(ext_scan_duration), + &ext_scan_duration); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PERIOD, sizeof(ext_scan_period), + &ext_scan_period); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + le_ext_scan_start(); + +} + +void tc_1204_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(GAP_PHYS_CONN_INIT_1M_BIT, dev_list[0].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1204_timer_handle = NULL; + +void tc_1204_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_1200_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1200 Test success\r\n"); + } +} + +void tc_1204_link_connected(uint8_t conn_id) +{ + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_1M_BIT, dev_list[1].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_1M_BIT, dev_list[2].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_1M_BIT, dev_list[3].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1204_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1204_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1204_timer_handle); + } +} + +void tc_1204_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("tc_1204_link_disconnected: conn_id %d, reason 0x%x\r\n", conn_id, reason); + tc_update_disc_reason(reason); + data_uart_print(" TC 1204 Test fail\r\n"); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1204_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1204_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1204_timer_handle); +} + + + +void tc_1204_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1204_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +#if TC_1205_SUPPORT + +void tc_1205_start(uint32_t count) +{ + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint16_t ext_scan_duration = 0; + uint16_t ext_scan_period = 0; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + + link_mgr_clear_device_list(); + + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_DURATION, sizeof(ext_scan_duration), + &ext_scan_duration); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PERIOD, sizeof(ext_scan_period), + &ext_scan_period); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + le_ext_scan_start(); +} + +void tc_1205_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_2M, &conn_param); + + le_connect(GAP_PHYS_CONN_INIT_2M_BIT, dev_list[0].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1205_timer_handle = NULL; + +void tc_1205_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_1205_conn_param_update_timeout_handler update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1205 Test success\r\n"); + } +} + +void tc_1205_link_connected(uint8_t conn_id) +{ + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_2M_BIT, dev_list[1].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_2M_BIT, dev_list[2].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_2M_BIT, dev_list[3].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1205_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1205_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1205_timer_handle); + } +} + +void tc_1205_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1205_MULTI_LINK_4_MASTER, reason); + tc_update_disc_reason(reason); + data_uart_print(" TC 1205 Test fail\r\n"); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1205_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1205_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1205_timer_handle); +} + + + +void tc_1205_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1205_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +#if TC_1206_SUPPORT + +void tc_1206_start(uint32_t count) +{ + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint16_t ext_scan_duration = 0; + uint16_t ext_scan_period = 0; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + + link_mgr_clear_device_list(); + + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_DURATION, sizeof(ext_scan_duration), + &ext_scan_duration); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PERIOD, sizeof(ext_scan_period), + &ext_scan_period); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + le_ext_scan_start(); +} + +void tc_1206_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 1000; + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 12; + conn_param.conn_interval_max = 12; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_CODED, &conn_param); + + le_connect(GAP_PHYS_CONN_INIT_CODED_BIT, dev_list[0].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void *g_tc_1206_timer_handle = NULL; + +void tc_1206_conn_param_update_timeout_handler(void *pxTimer) +{ + uint8_t conn_id = 3; + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_1200_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 36) + { + con_interval++; + + le_update_conn_param(conn_id, con_interval, con_interval, + conn_slave_latency, conn_supervision_timeout, + 2 * (con_interval + 1), 2 * (con_interval + 1)); + } + else + { + //test case end here + data_uart_print(" TC 1200 Test success\r\n"); + } +} + +void tc_1206_link_connected(uint8_t conn_id) +{ + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_CODED_BIT, dev_list[1].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_CODED_BIT, dev_list[2].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + le_connect(GAP_PHYS_CONN_INIT_CODED_BIT, dev_list[3].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + uint16_t con_interval; + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + + os_timer_create(&g_tc_1206_timer_handle, "tc_1200_timer", 1, con_interval * 30, false, + tc_1206_conn_param_update_timeout_handler); + os_timer_start(&g_tc_1206_timer_handle); + } +} + +void tc_1206_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1206_MULTI_LINK_4_MASTER, reason); + tc_update_disc_reason(reason); + data_uart_print(" TC 1206 Test fail\r\n"); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1206_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1206_conn_param_update_evt(uint8_t conn_id) +{ + os_timer_start(&g_tc_1206_timer_handle); +} + + + +void tc_1206_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1206_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +#if TC_1207_SUPPORT + +void tc_1207_start(uint32_t count) +{ + uint16_t scan_interval = 400; + uint16_t scan_window = 200; + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_start(); +} + +void tc_1207_scan_state_change_to_idle() +{ + uint16_t scan_timeout = 0;//no timeout + T_GAP_LE_CONN_REQ_PARAM conn_param; + + conn_param.scan_interval = 0x10; + conn_param.scan_window = 0x10; + conn_param.conn_interval_min = 6; + conn_param.conn_interval_max = 6; + conn_param.conn_latency = 0; + conn_param.supv_tout = 1000; + conn_param.ce_len_min = 2 * (conn_param.conn_interval_min - 1); + conn_param.ce_len_max = 2 * (conn_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_param); + + le_connect(0, dev_list[0].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[0].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void tc_1207_link_connected(uint8_t conn_id) +{ + data_uart_print("tc_1207_link_connected: conn_id %d\r\n", conn_id); + + if (conn_id == 0) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[1].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 1) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[2].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else if (conn_id == 2) + { + uint16_t scan_timeout = 1000; + le_connect(0, dev_list[3].bd_addr, (T_GAP_REMOTE_ADDR_TYPE)dev_list[1].bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); + } + else + { + + } +} + +void tc_1207_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1207_MULTI_LINK_4_MASTER, reason); + tc_update_disc_reason(reason); + data_uart_print("tc_1207_link_disconnected: conn_id %d\r\n", conn_id); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1207_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1207_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1207_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200.h new file mode 100644 index 00000000..8c1d0210 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200.h @@ -0,0 +1,87 @@ + +#ifndef _BLE_AUTO_TEST_TC_1200_H_ +#define _BLE_AUTO_TEST_TC_1200_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + dut is slave, dut init connection param update +*/ + +typedef struct _T_TC_1200_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_1200_IN_PARAM_DATA; + + +void tc_1200_start(uint32_t count); +void tc_1200_scan_state_change_to_idle(void); +void tc_1200_link_connected(uint8_t conn_id); +void tc_1200_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1200_conn_param_update_evt(uint8_t conn_id); +void tc_1200_add_case(uint32_t max_count); + + +void tc_1201_start(uint32_t count); +void tc_1201_scan_state_change_to_idle(void); +void tc_1201_link_connected(uint8_t conn_id); +void tc_1201_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1201_conn_param_update_evt(uint8_t conn_id); +void tc_1201_add_case(uint32_t max_count); + + +void tc_1202_start(uint32_t count); +void tc_1202_scan_state_change_to_idle(void); +void tc_1202_link_connected(uint8_t conn_id); +void tc_1202_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1202_conn_param_update_evt(uint8_t conn_id); +void tc_1202_add_case(uint32_t max_count); + +void tc_1203_start(uint32_t count); +void tc_1203_scan_state_change_to_idle(void); +void tc_1203_link_connected(uint8_t conn_id); +void tc_1203_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1203_conn_param_update_evt(uint8_t conn_id); +void tc_1203_add_case(uint32_t max_count); + + +void tc_1204_start(uint32_t count); +void tc_1204_scan_state_change_to_idle(void); +void tc_1204_link_connected(uint8_t conn_id); +void tc_1204_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1204_conn_param_update_evt(uint8_t conn_id); +void tc_1204_add_case(uint32_t max_count); + +void tc_1205_start(uint32_t count); +void tc_1205_scan_state_change_to_idle(void); +void tc_1205_link_connected(uint8_t conn_id); +void tc_1205_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1205_conn_param_update_evt(uint8_t conn_id); +void tc_1205_add_case(uint32_t max_count); + +void tc_1206_start(uint32_t count); +void tc_1206_scan_state_change_to_idle(void); +void tc_1206_link_connected(uint8_t conn_id); +void tc_1206_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1206_conn_param_update_evt(uint8_t conn_id); +void tc_1206_add_case(uint32_t max_count); + +void tc_1207_start(uint32_t count); +void tc_1207_scan_state_change_to_idle(void); +void tc_1207_link_connected(uint8_t conn_id); +void tc_1207_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_1207_conn_param_update_evt(uint8_t conn_id); +void tc_1207_add_case(uint32_t max_count); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200_sut.c new file mode 100644 index 00000000..9156b6c7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200_sut.c @@ -0,0 +1,312 @@ + +#include +#include "os_timer.h" +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + + +#include +#include + +#include +#include +#include + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif + +#define GATT_UUID_SIMPLE_PROFILE 0xA00A + +#if F_BT_LE_5_0_AE_ADV_SUPPORT + +static const uint8_t ext_large_adv_data[] = +{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4 +}; + +static const uint8_t ext_large_scan_data[] = +{ + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; +#endif + + +#if TC_1204_SUT_SUPPORT + +void tc_1204_sut_start(uint32_t count) +{ + uint8_t update_flags = EXT_ADV_SET_ADV_PARAS; + uint8_t adv_handle = 0; + uint16_t adv_event_prop = GAP_EXT_ADV_EVT_PROP_CONNECTABLE_ADV | GAP_EXT_ADV_EVT_PROP_SCANNABLE_ADV + | GAP_EXT_ADV_EVT_PROP_USE_LEGACY_ADV; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t *p_peer_address = NULL; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_2M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_1M; + + adv_handle = le_ext_adv_add_adv_param(adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + + le_ext_adv_start_setting(adv_handle, update_flags); + +} + +void tc_1204_sut_link_connected(uint8_t conn_id) +{ + +} + +void tc_1204_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1204_MULTI_LINK_4_MASTER, reason); + tc_update_disc_reason(reason); + data_uart_print(" TC 1204 Test fail\r\n"); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1204_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1204_sut_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1204_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + + +#if TC_1205_SUT_SUPPORT +void tc_1205_sut_start(uint32_t count) +{ + uint8_t update_flags = EXT_ADV_SET_ADV_PARAS; + uint8_t adv_handle = 0; + uint16_t adv_event_prop = GAP_EXT_ADV_EVT_PROP_CONNECTABLE_ADV | GAP_EXT_ADV_EVT_PROP_SCANNABLE_ADV + | GAP_EXT_ADV_EVT_PROP_USE_LEGACY_ADV; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t *p_peer_address = NULL; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_2M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_2M; + + adv_handle = le_ext_adv_add_adv_param(adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + + le_ext_adv_start_setting(adv_handle, update_flags); + +} + +void tc_1205_sut_link_connected(uint8_t conn_id) +{ + +} + +void tc_1205_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1204_MULTI_LINK_4_MASTER, reason); + tc_update_disc_reason(reason); + data_uart_print(" TC 1204 Test fail\r\n"); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1204_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1205_sut_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1204_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + + +#if TC_1206_SUT_SUPPORT + +void tc_1206_sut_start(uint32_t count) +{ + uint8_t update_flags = EXT_ADV_SET_ADV_PARAS; + uint8_t adv_handle = 0; + uint16_t adv_event_prop = GAP_EXT_ADV_EVT_PROP_CONNECTABLE_ADV | GAP_EXT_ADV_EVT_PROP_SCANNABLE_ADV + | GAP_EXT_ADV_EVT_PROP_USE_LEGACY_ADV; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t *p_peer_address = NULL; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_2M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_CODED; + + adv_handle = le_ext_adv_add_adv_param(adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + + le_ext_adv_start_setting(adv_handle, update_flags); + +} + +void tc_1206_sut_link_connected(uint8_t conn_id) +{ + +} + +void tc_1206_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_1204_MULTI_LINK_4_MASTER, reason); + tc_update_disc_reason(reason); + data_uart_print(" TC 1204 Test fail\r\n"); + { + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_1204_MULTI_LINK_4_MASTER, 0, NULL); + } + } + +} + +void tc_1206_sut_add_case(uint32_t max_count) +{ + T_TC_1200_IN_PARAM_DATA *p_tc_1200_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_1200_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_1200_IN_PARAM_DATA)); + + p_tc_1200_param_data->id = TC_1204_MULTI_LINK_4_MASTER; + p_tc_1200_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_1200_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200_sut.h new file mode 100644 index 00000000..0f1b03c7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_1200_sut.h @@ -0,0 +1,34 @@ + +#ifndef _BLE_AUTO_TEST_TC_1200_SUT_H_ +#define _BLE_AUTO_TEST_TC_1200_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + dut is slave, dut init connection param update +*/ + + + +void tc_1204_sut_start(uint32_t count); +void tc_1204_sut_link_connected(uint8_t conn_id); +void tc_1204_sut_link_disconnected(uint8_t conn_id, uint16_t reason); + +void tc_1205_sut_start(uint32_t count); +void tc_1205_sut_link_connected(uint8_t conn_id); +void tc_1205_sut_link_disconnected(uint8_t conn_id, uint16_t reason); + +void tc_1206_sut_start(uint32_t count); +void tc_1206_sut_link_connected(uint8_t conn_id); +void tc_1206_sut_link_disconnected(uint8_t conn_id, uint16_t reason); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200.c new file mode 100644 index 00000000..1c9f1833 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200.c @@ -0,0 +1,1309 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "gap_adv.h" +#include "vendor_tp_service.h" +#include "os_sched.h" + +#include +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +#include +#endif + +#include +#include + + + +#if TC_200_SUPPORT + +T_TP_TEST_CONFIG g_tp_test_config; + +#define TP_TEST_PARAM_COUNT 12 +T_TP_TEST_PARAM g_tp_test_param[TP_TEST_PARAM_COUNT]; +uint8_t g_tp_cur_test_index = 0; +uint8_t g_tp_used_test_index = 0; +uint8_t g_tp_test_start = false; + + +#define MAX_TEST_COUNT 4000 +static uint8_t tp_test_mode; + + + +void tc_200_tp_notification_tx_start(void) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} +uint8_t tc_tp_notification_tx_01_fixed_len_array[] = {20, 150, 200, 236, 241}; +uint8_t tc_tp_notification_tx_01_fixed_len_array_len = + sizeof(tc_tp_notification_tx_01_fixed_len_array) / sizeof( + tc_tp_notification_tx_01_fixed_len_array[0]); +uint8_t tc_tp_notification_tx_01_fixed_len_array_cur_index = 0; + +void tc_200_tp_notification_tx_init_config(uint16_t con_interval, uint16_t length, + uint8_t tx_octets, bool test_drop_acl_data) +{ + g_tp_test_config.con_interval = con_interval; + g_tp_test_config.length = length; + g_tp_test_config.tx_octets = tx_octets; + g_tp_test_config.test_drop_acl_data = test_drop_acl_data; + + if (con_interval != 0) + { + tc_200_tp_notification_tx_config_with_fixed_interval(g_tp_test_config.con_interval); + } + else if (length != 0) + + { + tc_200_tp_notification_tx_config_with_fixed_length(g_tp_test_config.length); + } + else if (con_interval == 0 && length == 0) + { + tc_200_tp_notification_tx_config_with_fixed_length( + tc_tp_notification_tx_01_fixed_len_array[tc_tp_notification_tx_01_fixed_len_array_cur_index]); + } + + +} + +void tc_200_tp_notification_tx_config_with_fixed_interval(uint16_t con_interval) +{ + uint8_t i = 0; + g_tp_test_param[i].con_interval = con_interval; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = 20; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = g_tp_test_config.con_interval; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = 150; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + + i++; + + g_tp_test_param[i].con_interval = g_tp_test_config.con_interval; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = 200; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = g_tp_test_config.con_interval; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = 236; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + + g_tp_test_param[i].con_interval = g_tp_test_config.con_interval; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = 244; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + + + + + g_tp_used_test_index = i; +} + +void tc_200_tp_notification_tx_config_with_fixed_length(uint16_t length) +{ + uint8_t i = 0; + g_tp_test_param[i].con_interval = 6; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 6; + g_tp_test_param[i].conn_slave_latency = 50; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 8; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 8; + g_tp_test_param[i].conn_slave_latency = 50; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 10; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 10; + g_tp_test_param[i].conn_slave_latency = 50; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 12; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 12; + g_tp_test_param[i].conn_slave_latency = 50; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + + g_tp_test_param[i].con_interval = 15; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 15; + g_tp_test_param[i].conn_slave_latency = 50; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + +#if 0 + g_tp_test_param[i].con_interval = 18; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 19; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; +#endif + + g_tp_test_param[i].con_interval = 20; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 20; + g_tp_test_param[i].conn_slave_latency = 50; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + +#if 0 + i++; + + g_tp_test_param[i].con_interval = 24; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; + i++; + + g_tp_test_param[i].con_interval = 80; + g_tp_test_param[i].conn_slave_latency = 0; + g_tp_test_param[i].conn_supervision_timeout = 1000; + g_tp_test_param[i].length = length; + g_tp_test_param[i].count = MAX_TEST_COUNT; + g_tp_test_param[i].count_remain = g_tp_test_param[i].count; + g_tp_test_param[i].initial_value = 0; +#endif + + + g_tp_used_test_index = i; +} + +void tc_200_tp_notification_tx_init_default_param(uint8_t conn_id) +{ + for (uint8_t i = 0; i <= g_tp_used_test_index; i++) + { + g_tp_test_param[g_tp_cur_test_index].conn_id = conn_id; + } + +} + +void tc_200_tp_notification_tx_change_tx_octets(uint8_t conn_id, uint16_t tx_octets) +{ +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + le_set_data_len(conn_id, tx_octets, 0x0848); +#endif +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_200_tp_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + if (cause != 0) + { + if (tp_test_mode == 4 || tp_test_mode == 5) + { + le_set_phy(g_tp_test_param[g_tp_cur_test_index].conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (tp_test_mode == 6 || tp_test_mode == 7) + { + le_set_phy(g_tp_test_param[g_tp_cur_test_index].conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } + } +} +#endif + +void tc_200_tp_notification_tx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_tp_test_param[g_tp_cur_test_index].con_interval == con_interval && + g_tp_test_param[g_tp_cur_test_index].conn_slave_latency == conn_slave_latency && + g_tp_test_param[g_tp_cur_test_index].conn_supervision_timeout == conn_supervision_timeout) + { + if (g_tp_cur_test_index == 0 && tc_tp_notification_tx_01_fixed_len_array_cur_index == 0) + { +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + if (tp_test_mode == 4 || tp_test_mode == 5) + { + le_set_phy(g_tp_test_param[g_tp_cur_test_index].conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (tp_test_mode == 6 || tp_test_mode == 7) + { + le_set_phy(g_tp_test_param[g_tp_cur_test_index].conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } +#endif + } + + g_tp_test_param[g_tp_cur_test_index].begin_time = os_sys_time_get(); + APP_PRINT_INFO1("tp test:notification:begin:begin time = %dms", + g_tp_test_param[g_tp_cur_test_index].begin_time); + + uint8_t credits = 10; + while (credits) + { + if (g_tp_test_param[g_tp_cur_test_index].count_remain) + { + uint8_t value[250]; + memset(value, g_tp_test_param[g_tp_cur_test_index].initial_value, + g_tp_test_param[g_tp_cur_test_index].length); + if (vendor_tp_service_v1_notification(conn_id, gSimpleProfileServiceId, value, + g_tp_test_param[g_tp_cur_test_index].length)) + { + credits--; + g_tp_test_param[g_tp_cur_test_index].initial_value++; + g_tp_test_param[g_tp_cur_test_index].count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } + } + +} +static bool flag200 = false; +void tc_200_tp_notification_tx_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (g_tp_test_param[g_tp_cur_test_index].count_remain) + { + uint8_t value[250]; + memset(value, g_tp_test_param[g_tp_cur_test_index].initial_value, + g_tp_test_param[g_tp_cur_test_index].length); + if (vendor_tp_service_v1_notification(g_tp_test_param[g_tp_cur_test_index].conn_id, + gSimpleProfileServiceId, value, g_tp_test_param[g_tp_cur_test_index].length)) + { + credits--; + g_tp_test_param[g_tp_cur_test_index].initial_value++; + g_tp_test_param[g_tp_cur_test_index].count_remain--; + if (g_tp_test_config.test_drop_acl_data) + { + if ((g_tp_test_param[g_tp_cur_test_index].count_remain % 100) == 0) + { +#if 0 + le_vendor_drop_acl_data(g_tp_test_param[g_tp_cur_test_index].conn_id, 0, 0, 0); +#endif + } + } + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + g_tp_test_param[g_tp_cur_test_index].end_time = os_sys_time_get(); + uint32_t elapsed_time = os_time_get_elapsed(g_tp_test_param[g_tp_cur_test_index].begin_time, + g_tp_test_param[g_tp_cur_test_index].end_time); + uint32_t data_rate = + g_tp_test_param[g_tp_cur_test_index].count * g_tp_test_param[g_tp_cur_test_index].length * 1000 / + (elapsed_time); + + APP_PRINT_INFO8("tp test:notification:end:conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].conn_slave_latency, + g_tp_test_param[g_tp_cur_test_index].length, + g_tp_test_param[g_tp_cur_test_index].count, + g_tp_test_param[g_tp_cur_test_index].begin_time, + g_tp_test_param[g_tp_cur_test_index].end_time, + elapsed_time, + data_rate); + if (false == flag200) + { + data_uart_print(" conn_interval, latency, length, data rate(Bytes/s)\r\n"); + flag200 = true; + } + data_uart_print(" %d, %d, %d, %d\r\n", + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].conn_slave_latency, + g_tp_test_param[g_tp_cur_test_index].length, + data_rate); + if (g_tp_cur_test_index < g_tp_used_test_index) + { + g_tp_cur_test_index++; + APP_PRINT_INFO2("g_tp_cur_test_index = %d, interval = %d", g_tp_cur_test_index, + g_tp_test_param[g_tp_cur_test_index].con_interval); + le_update_conn_param(g_tp_test_param[g_tp_cur_test_index].conn_id, + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].conn_slave_latency, + g_tp_test_param[g_tp_cur_test_index].conn_supervision_timeout, + 2 * (g_tp_test_param[g_tp_cur_test_index].con_interval - 1), + 2 * (g_tp_test_param[g_tp_cur_test_index].con_interval - 1) + ); + + } + else + { + g_tp_cur_test_index = 0; + g_tp_used_test_index = 0; + g_tp_test_start = true; + if (tc_tp_notification_tx_01_fixed_len_array_cur_index < + tc_tp_notification_tx_01_fixed_len_array_len - 1) + { + tc_tp_notification_tx_01_fixed_len_array_cur_index++; + + APP_PRINT_INFO2("11tc_tp_notification_tx_01_fixed_len_array_cur_index = %d, tc_tp_notification_tx_01_fixed_len_array_len = %d", + tc_tp_notification_tx_01_fixed_len_array_cur_index, + tc_tp_notification_tx_01_fixed_len_array_len); + + tc_200_tp_notification_tx_init_config(0, + tc_tp_notification_tx_01_fixed_len_array[tc_tp_notification_tx_01_fixed_len_array_cur_index], + 251, g_tp_test_config.test_drop_acl_data); + + le_update_conn_param(g_tp_test_param[g_tp_cur_test_index].conn_id, + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].conn_slave_latency, + g_tp_test_param[g_tp_cur_test_index].conn_supervision_timeout, + 2 * (g_tp_test_param[g_tp_cur_test_index].con_interval - 1), + 2 * (g_tp_test_param[g_tp_cur_test_index].con_interval - 1) + ); + } + else + { + //all test end here + APP_PRINT_INFO2("tc_tp_notification_tx_01_fixed_len_array_cur_index = %d, tc_tp_notification_tx_01_fixed_len_array_len = %d", + tc_tp_notification_tx_01_fixed_len_array_cur_index, + tc_tp_notification_tx_01_fixed_len_array_len); + APP_PRINT_INFO0("tp test:notification:end: start next case\r\n"); + data_uart_print("tp test:notification:end: start next case\a\r\n"); + tc_tp_notification_tx_01_fixed_len_array_cur_index = 0; + tc_200_tp_notification_tx_init_config(0, + tc_tp_notification_tx_01_fixed_len_array[tc_tp_notification_tx_01_fixed_len_array_cur_index], + 251, g_tp_test_config.test_drop_acl_data); + + } + + + } + } + break; + } + } +} + +void tc_200_tp_notification_tx_tx_config(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + + switch (p_simp_client_cb_data->msg_data.write.opcode) + { + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM1: + { + //ThroughputTestSize = p_simp_client_cb_data->msg_data.write.u.notify_param.count; + //ThroughputTestNum = p_simp_client_cb_data->msg_data.write.u.notify_param.length; + + //APP_PRINT_INFO2("tp test:notification:config:count = %d, length = %d", ThroughputTestSize, ThroughputTestNum); + + //ThroughputTestSize = 20; + //ThroughputTestNum = 10000; + //ThroughputTestValue = 0; + tc_200_tp_notification_tx_change_tx_octets(g_tp_test_param[g_tp_cur_test_index].conn_id, 27); + } + break; + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM2: + { + tc_200_tp_notification_tx_change_tx_octets(g_tp_test_param[g_tp_cur_test_index].conn_id, 251); + } + break; + + case VENDOR_TP_OP_NOTIFY_START_TEST: + { + g_tp_test_start = true; + g_tp_cur_test_index = 0; + tc_tp_notification_tx_01_fixed_len_array_cur_index = 0; + tp_test_mode = p_simp_client_cb_data->msg_data.write.u.mode; + le_update_conn_param(g_tp_test_param[g_tp_cur_test_index].conn_id, + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].con_interval, + g_tp_test_param[g_tp_cur_test_index].conn_slave_latency, + g_tp_test_param[g_tp_cur_test_index].conn_supervision_timeout, + 2 * (g_tp_test_param[g_tp_cur_test_index].con_interval - 1), + 2 * (g_tp_test_param[g_tp_cur_test_index].con_interval - 1)); + } + break; + default: + break; + } + +} + +#endif + +#if TC_206_SUPPORT +T_TP_TEST_PARAM g_206_tp_test_param; +TTP_PERFER_PARAM g_206_prefer_param; +bool g_206_phy_update = false; + +void tc_206_tp_notification_tx_start(void) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_206_tp_notification_tx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check) +{ + memset(&g_206_tp_test_param, 0, sizeof(g_206_tp_test_param)); + g_206_prefer_param.con_interval = con_interval; + g_206_prefer_param.conn_slave_latency = slave_latency; + g_206_prefer_param.conn_supervision_timeout = 1000; + g_206_prefer_param.count = max_count; + g_206_prefer_param.length = length; + g_206_prefer_param.mode = mode; + g_206_prefer_param.initial_value = 0; + g_206_prefer_param.data_check = data_check; + + g_206_tp_test_param.length = length; + g_206_tp_test_param.count = max_count; + g_206_tp_test_param.count_remain = max_count; + g_206_tp_test_param.initial_value = 0; + + g_206_phy_update = false; + + vendor_tp_service_config_param(g_206_prefer_param); +} + +void tc_206_start_send_notification(uint8_t conn_id) +{ + uint8_t credits = 10; + g_206_tp_test_param.begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[206][TX]:begin time = %dms", + g_206_tp_test_param.begin_time); + + while (credits) + { + if (g_206_tp_test_param.count_remain) + { + uint8_t value[250]; + memset(value, g_206_tp_test_param.initial_value, + g_206_tp_test_param.length); + if (vendor_tp_service_v1_notification(conn_id, gSimpleProfileServiceId, value, + g_206_tp_test_param.length)) + { + credits--; + g_206_tp_test_param.initial_value++; + g_206_tp_test_param.count_remain--; + } + else + { + APP_PRINT_INFO0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } +} + +void tc_206_tp_notification_tx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_206_prefer_param.con_interval == con_interval && + g_206_prefer_param.conn_slave_latency == conn_slave_latency && + g_206_prefer_param.conn_supervision_timeout == conn_supervision_timeout) + { + tc_206_start_send_notification(0); + } + else + { + data_uart_print("[206][TX] error: Invalid conn parameter\r\n"); + le_disconnect(0); + } + +} +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_206_tp_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + if (g_206_phy_update) + { + return; + } + else + { + g_206_phy_update = true; + } + if (cause == 0) + { + if (g_206_prefer_param.mode == 4 || g_206_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_prefer_param.mode == 6 || g_206_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } + } +} +#endif + +void tc_206_tp_notification_tx_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (g_206_tp_test_param.count_remain) + { + uint8_t value[250]; + memset(value, g_206_tp_test_param.initial_value, + g_206_tp_test_param.length); + if (vendor_tp_service_v1_notification(0, gSimpleProfileServiceId, value, + g_206_tp_test_param.length)) + { + credits--; + g_206_tp_test_param.initial_value++; + g_206_tp_test_param.count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + g_206_tp_test_param.end_time = os_sys_time_get(); + g_206_tp_test_param.elapsed_time = os_time_get_elapsed(g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time); + g_206_tp_test_param.data_rate = + g_206_tp_test_param.count * g_206_tp_test_param.length * 1000 / + (g_206_tp_test_param.elapsed_time); + APP_PRINT_ERROR1("[206][TX]:end time = %dms", + g_206_tp_test_param.end_time); + } + break; + } + } +} + +void tc_206_tp_notification_tx_tx_config(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + + switch (p_simp_client_cb_data->msg_data.write.opcode) + { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM1: + { + le_set_data_len(0, 27, 0x0848); + } + break; + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM2: + { + le_set_data_len(0, 251, 0x0848); + } + break; +#endif + case VENDOR_TP_OP_NOTIFY_START_TEST: + break; + + default: + break; + } + +} + +void tc_206_dump_result(void) +{ + APP_PRINT_ERROR8("[206][TX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_206_prefer_param.con_interval, + g_206_prefer_param.conn_slave_latency, + g_206_prefer_param.length, + g_206_tp_test_param.count, + g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time, + g_206_tp_test_param.elapsed_time, + g_206_tp_test_param.data_rate); + data_uart_print("[206][TX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_206_prefer_param.con_interval, + g_206_prefer_param.conn_slave_latency, + g_206_prefer_param.length, + g_206_tp_test_param.count, + g_206_tp_test_param.begin_time, + g_206_tp_test_param.end_time, + g_206_tp_test_param.elapsed_time, + g_206_tp_test_param.data_rate); + APP_PRINT_ERROR2("[206][TX]: count %d count_remain %d", + g_206_prefer_param.count, g_206_tp_test_param.count_remain); + + data_uart_print("[206][TX]: count %d count_remain %d\r\n", + g_206_prefer_param.count, g_206_tp_test_param.count_remain); +} + +void tc_206_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + tc_206_dump_result(); +} +#endif + +#if TC_207_SUPPORT +T_TP_TEST_PARAM g_207_tp_test_param; +TTP_PERFER_PARAM g_207_prefer_param; + +void tc_207_tp_rx_start(void) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_207_tp_rx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check) +{ + memset(&g_207_tp_test_param, 0, sizeof(g_207_tp_test_param)); + g_207_prefer_param.con_interval = con_interval; + g_207_prefer_param.conn_slave_latency = slave_latency; + g_207_prefer_param.conn_supervision_timeout = 1000; + g_207_prefer_param.count = max_count; + g_207_prefer_param.length = length; + g_207_prefer_param.mode = mode; + g_207_prefer_param.initial_value = 0; + g_207_prefer_param.data_check = data_check; + + g_207_tp_test_param.length = length; + g_207_tp_test_param.count = 0; + g_207_tp_test_param.count_remain = 0; + g_207_tp_test_param.initial_value = 0; + + vendor_tp_service_config_param(g_207_prefer_param); +} + +void tc_207_tp_rx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_207_tp_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + if (cause == 0) + { + if (g_207_prefer_param.mode == 4 || g_207_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_prefer_param.mode == 6 || g_207_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } + } +} +#endif + +void tc_207_tp_handle_write_data(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + APP_PRINT_INFO1("tc_207_tp_handle_write_data: length %d", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + if (g_207_prefer_param.length == p_simp_client_cb_data->msg_data.write.u.write_data.length) + { + if (g_207_tp_test_param.count == 0) + { + g_207_tp_test_param.begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[207][RX]: :begin time = %dms", + g_207_tp_test_param.begin_time); + } + if (g_207_prefer_param.data_check) + { + uint16_t i; + uint8_t *p_value = p_simp_client_cb_data->msg_data.write.u.write_data.p_value; + for (i = 0; i < g_207_prefer_param.length; i++) + { + if (p_value[i] != g_207_tp_test_param.initial_value) + { + APP_PRINT_ERROR4("[207][RX]: data check failed: p_value[%d] 0x%x, initial_value %d, count %d", + i, p_value[i], + g_207_tp_test_param.initial_value, + g_207_tp_test_param.count); + data_uart_print("[207][RX]: data check failed\r\n"); + le_disconnect(0); + return; + } + } + } + } + else + { + APP_PRINT_ERROR1("[207][RX]: Len check failed: length %d", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + data_uart_print("[207][RX]: Len check failed: length %d\r\n", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + le_disconnect(0); + return; + } + g_207_tp_test_param.count++; + g_207_tp_test_param.initial_value++; + if (g_207_tp_test_param.count == g_207_prefer_param.count) + { + g_207_tp_test_param.end_time = os_sys_time_get(); + g_207_tp_test_param.elapsed_time = os_time_get_elapsed(g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time); + g_207_tp_test_param.data_rate = + g_207_tp_test_param.count * g_207_prefer_param.length * 1000 / + (g_207_tp_test_param.elapsed_time); + APP_PRINT_ERROR1("[207][RX]: :end time = %dms", + g_207_tp_test_param.end_time); + le_disconnect(0); + } +} + +void tc_207_dump_result(void) +{ + APP_PRINT_ERROR7("[207][RX]: conn_interval = %d,conn_latency = %d, length = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %d Bytes/s", + g_207_prefer_param.con_interval, + g_207_prefer_param.conn_slave_latency, + g_207_prefer_param.length, + g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time, + g_207_tp_test_param.elapsed_time, + g_207_tp_test_param.data_rate); + data_uart_print("[207][RX]: conn_interval %d, latency %d, length %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_207_prefer_param.con_interval, + g_207_prefer_param.conn_slave_latency, + g_207_prefer_param.length, + g_207_tp_test_param.begin_time, + g_207_tp_test_param.end_time, + g_207_tp_test_param.elapsed_time, + g_207_tp_test_param.data_rate); + APP_PRINT_ERROR2("[207][RX]: count %d rx_count %d", + g_207_prefer_param.count, g_207_tp_test_param.count); + + data_uart_print("[207][RX]: count %d rx_count %d\r\n", + g_207_prefer_param.count, g_207_tp_test_param.count); +} + +void tc_207_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + tc_207_dump_result(); +} +#endif + +#if TC_208_SUPPORT +typedef struct +{ + uint8_t tx_initial_value; + uint32_t tx_count; + uint32_t tx_count_remain; + + uint32_t tx_begin_time; + uint32_t tx_end_time; + uint32_t tx_elapsed_time; + uint32_t tx_data_rate; + + uint32_t rx_count; + uint8_t rx_initial_value; + uint32_t rx_begin_time; + uint32_t rx_end_time; + uint32_t rx_elapsed_time; + uint32_t rx_data_rate; +} T_TP_208_PARAM; +T_TP_208_PARAM g_208_tp_test_param; +TTP_PERFER_PARAM g_208_prefer_param; + +void tc_208_tp_trx_start(void) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_208_tp_trx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check) +{ + memset(&g_208_tp_test_param, 0, sizeof(g_208_tp_test_param)); + g_208_prefer_param.con_interval = con_interval; + g_208_prefer_param.conn_slave_latency = slave_latency; + g_208_prefer_param.conn_supervision_timeout = 1000; + g_208_prefer_param.count = max_count; + g_208_prefer_param.length = length; + g_208_prefer_param.mode = mode; + g_208_prefer_param.initial_value = 0; + g_208_prefer_param.data_check = data_check; + + g_208_tp_test_param.tx_count = 0; + g_208_tp_test_param.tx_count_remain = max_count; + g_208_tp_test_param.tx_initial_value = 0; + g_208_tp_test_param.rx_count = 0; + g_208_tp_test_param.rx_initial_value = 0; + vendor_tp_service_config_param(g_208_prefer_param); +} + +void tc_208_start_send_notification(uint8_t conn_id) +{ + uint8_t credits = 10; + g_208_tp_test_param.tx_begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[208]:tx begin time = %dms", + g_208_tp_test_param.tx_begin_time); + + while (credits) + { + if (g_208_tp_test_param.tx_count_remain) + { + uint8_t value[250]; + memset(value, g_208_tp_test_param.tx_initial_value, + g_208_prefer_param.length); + if (vendor_tp_service_v1_notification(conn_id, gSimpleProfileServiceId, value, + g_208_prefer_param.length)) + { + credits--; + g_208_tp_test_param.tx_initial_value++; + g_208_tp_test_param.tx_count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } +} + +void tc_208_tp_notification_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (g_208_tp_test_param.tx_count_remain) + { + uint8_t value[250]; + memset(value, g_208_tp_test_param.tx_initial_value, + g_208_prefer_param.length); + if (vendor_tp_service_v1_notification(0, gSimpleProfileServiceId, value, + g_208_prefer_param.length)) + { + credits--; + g_208_tp_test_param.tx_initial_value++; + g_208_tp_test_param.tx_count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + g_208_tp_test_param.tx_end_time = os_sys_time_get(); + g_208_tp_test_param.tx_elapsed_time = os_time_get_elapsed(g_208_tp_test_param.tx_begin_time, + g_208_tp_test_param.tx_end_time); + g_208_tp_test_param.tx_data_rate = + g_208_prefer_param.count * g_208_prefer_param.length * 1000 / + (g_208_tp_test_param.tx_elapsed_time); + APP_PRINT_ERROR1("[208]:tx end time = %dms", + g_208_tp_test_param.tx_end_time); + + tc_208_dump_tx_result(); + //le_disconnect(0); + } + break; + } + } +} + +void tc_208_tp_trx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("GAP_MSG_LE_CONN_PARAM_UPDATE update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + if (g_208_prefer_param.con_interval == con_interval && + g_208_prefer_param.conn_slave_latency == conn_slave_latency && + g_208_prefer_param.conn_supervision_timeout == conn_supervision_timeout) + { + tc_208_start_send_notification(0); + } + else + { + data_uart_print("[208] error: Invalid conn parameter\r\n"); + le_disconnect(0); + } +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_208_tp_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + if (cause == 0) + { + if (g_208_prefer_param.mode == 4 || g_208_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_208_prefer_param.mode == 6 || g_208_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } + } +} +#endif + +void tc_208_tp_notification_tx_tx_config(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + + switch (p_simp_client_cb_data->msg_data.write.opcode) + { +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM1: + { + le_set_data_len(0, 27, 0x0848); + } + break; + case VENDOR_TP_OP_CONFIG_NOTIFY_PARAM2: + { + le_set_data_len(0, 251, 0x0848); + } + break; +#endif + case VENDOR_TP_OP_NOTIFY_START_TEST: + break; + + default: + break; + } + +} + +void tc_208_tp_handle_write_data(void *pdata) +{ + TTP_CALLBACK_DATA *p_simp_client_cb_data = pdata; + APP_PRINT_INFO1("tc_208_tp_handle_write_data: length %d", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + if (g_208_prefer_param.length == p_simp_client_cb_data->msg_data.write.u.write_data.length) + { + if (g_208_tp_test_param.rx_count == 0) + { + g_208_tp_test_param.rx_begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[208]: rx begin time = %dms", + g_208_tp_test_param.rx_begin_time); + } + if (g_208_prefer_param.data_check) + { + uint16_t i; + uint8_t *p_value = p_simp_client_cb_data->msg_data.write.u.write_data.p_value; + for (i = 0; i < g_208_prefer_param.length; i++) + { + if (p_value[i] != g_208_tp_test_param.rx_initial_value) + { + APP_PRINT_ERROR4("[208][RX]: data check failed: p_value[%d] 0x%x, initial_value %d, count %d", + i, p_value[i], + g_208_tp_test_param.rx_initial_value, + g_208_tp_test_param.rx_count); + data_uart_print("[208][RX]: data check failed\r\n"); + le_disconnect(0); + return; + } + } + } + } + else + { + APP_PRINT_ERROR1("[208][RX]: Len check failed: length %d", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + data_uart_print("[208][RX]: Len check failed: length %d\r\n", + p_simp_client_cb_data->msg_data.write.u.write_data.length); + le_disconnect(0); + return; + } + g_208_tp_test_param.rx_count++; + g_208_tp_test_param.rx_initial_value++; + if (g_208_tp_test_param.rx_count == g_208_prefer_param.count) + { + g_208_tp_test_param.rx_end_time = os_sys_time_get(); + g_208_tp_test_param.rx_elapsed_time = os_time_get_elapsed(g_208_tp_test_param.rx_begin_time, + g_208_tp_test_param.rx_end_time); + g_208_tp_test_param.rx_data_rate = + g_208_tp_test_param.rx_count * g_208_prefer_param.length * 1000 / + (g_208_tp_test_param.rx_elapsed_time); + APP_PRINT_ERROR1("[208]:rx end time = %dms", + g_208_tp_test_param.rx_end_time); + + tc_208_dump_rx_result(); + } +} + +void tc_208_dump_tx_result(void) +{ + APP_PRINT_ERROR8("[208][TX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_208_prefer_param.con_interval, + g_208_prefer_param.conn_slave_latency, + g_208_prefer_param.length, + g_208_prefer_param.count, + g_208_tp_test_param.tx_begin_time, + g_208_tp_test_param.tx_end_time, + g_208_tp_test_param.tx_elapsed_time, + g_208_tp_test_param.tx_data_rate); + data_uart_print("[208][TX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_208_prefer_param.con_interval, + g_208_prefer_param.conn_slave_latency, + g_208_prefer_param.length, + g_208_prefer_param.count, + g_208_tp_test_param.tx_begin_time, + g_208_tp_test_param.tx_end_time, + g_208_tp_test_param.tx_elapsed_time, + g_208_tp_test_param.tx_data_rate); + APP_PRINT_ERROR2("[208][TX]: count %d tx_count_remain %d", + g_208_prefer_param.count, g_208_tp_test_param.tx_count_remain); + + data_uart_print("[208][TX]: count %d tx_count_remain %d\r\n", + g_208_prefer_param.count, g_208_tp_test_param.tx_count_remain); +} + +void tc_208_dump_rx_result(void) +{ + APP_PRINT_ERROR8("[208][RX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_208_prefer_param.con_interval, + g_208_prefer_param.conn_slave_latency, + g_208_prefer_param.length, + g_208_prefer_param.count, + g_208_tp_test_param.rx_begin_time, + g_208_tp_test_param.rx_end_time, + g_208_tp_test_param.rx_elapsed_time, + g_208_tp_test_param.rx_data_rate); + data_uart_print("[208][RX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_208_prefer_param.con_interval, + g_208_prefer_param.conn_slave_latency, + g_208_prefer_param.length, + g_208_prefer_param.count, + g_208_tp_test_param.rx_begin_time, + g_208_tp_test_param.rx_end_time, + g_208_tp_test_param.rx_elapsed_time, + g_208_tp_test_param.rx_data_rate); + APP_PRINT_ERROR2("[208][RX]: count %d rx_count %d", + g_208_prefer_param.count, g_208_tp_test_param.rx_count); + + data_uart_print("[208][RX]: count %d rx_count %d\r\n", + g_208_prefer_param.count, g_208_tp_test_param.rx_count); +} + +void tc_208_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + tc_208_dump_tx_result(); + tc_208_dump_rx_result(); +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200.h new file mode 100644 index 00000000..55df0b1e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200.h @@ -0,0 +1,104 @@ + +#ifndef _BLE_AUTO_TEST_TC_200_H_ +#define _BLE_AUTO_TEST_TC_200_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef struct t_tp_test_config +{ + uint16_t con_interval; + uint16_t length; + uint8_t tx_octets; + bool test_drop_acl_data; + +} T_TP_TEST_CONFIG; + + +typedef struct t_tp_test_param +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + uint16_t length; + uint32_t count; + uint32_t count_remain; + uint8_t initial_value; + + uint8_t conn_id; + uint32_t begin_time; + uint32_t end_time; + uint32_t elapsed_time; + uint32_t data_rate; +} T_TP_TEST_PARAM; + + +/** + for case TC_0200_TP_NOTIFICATION_TX_01 +*/ +void tc_200_tp_notification_tx_start(void); +void tc_200_tp_notification_tx_init_config(uint16_t con_interval, uint16_t length, + uint8_t tx_octets, bool test_drop_acl_data); +void tc_200_tp_notification_tx_init_default_param(uint8_t conn_id); +void tc_200_tp_notification_tx_change_tx_octets(uint8_t conn_id, uint16_t tx_octets); +void tc_200_tp_notification_tx_config_with_fixed_interval(uint16_t con_interval); +void tc_200_tp_notification_tx_config_with_fixed_length(uint16_t length); +void tc_200_tp_notification_tx_conn_param_update_event(uint8_t conn_id); +void tc_200_tp_notification_tx_tx_data_complete(uint8_t credits); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_200_tp_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +#endif +void tc_200_tp_notification_tx_tx_config(void *pdata); + +void tc_206_tp_notification_tx_start(void); +void tc_206_tp_notification_tx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check); +void tc_206_tp_notification_tx_tx_data_complete(uint8_t credits); +void tc_206_tp_notification_tx_tx_config(void *pdata); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_206_tp_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +#endif +void tc_206_tp_notification_tx_conn_param_update_event(uint8_t conn_id); +void tc_206_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_206_dump_result(void); + +void tc_207_tp_rx_start(void); +void tc_207_tp_rx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check); +void tc_207_tp_rx_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_207_tp_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +#endif +void tc_207_tp_handle_write_data(void *pdata); +void tc_207_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_207_dump_result(void); + +void tc_208_tp_trx_start(void); +void tc_208_tp_trx_init_config(uint16_t con_interval, uint16_t slave_latency, + uint16_t length, uint8_t mode, uint32_t max_count, uint8_t data_check); +void tc_208_tp_trx_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_208_tp_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +#endif +void tc_208_tp_notification_tx_data_complete(uint8_t credits); +void tc_208_tp_notification_tx_tx_config(void *pdata); +void tc_208_tp_handle_write_data(void *pdata); +void tc_208_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_208_dump_result(void); +void tc_208_dump_tx_result(void); +void tc_208_dump_rx_result(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200_sut.c new file mode 100644 index 00000000..3d5ef9be --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200_sut.c @@ -0,0 +1,1498 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + + +#include "os_sched.h" +#include +#include + + +#include +#include + +#include +#include + +#if TC_200_SUT_SUPPORT + + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint8_t remote_bd[6]; + uint8_t mode;/** 0 : 1M + w/o data length extension + 1 : 1M + w data length extension + 2 : 2M + w/o data length extension + 3 : 2M + w data length extension + 4 : Coded(s=2) + w/o data length extension + 5 : Coded(s=2) + w data length extension + 6 : Coded(s=8) + w/o data length extension + 7 : Coded(s=8) + w data length extension + */ + uint8_t mode_end; + T_TP_CONFIG_STATE cur_config_state; + T_TP_CONFIG_OP cur_config_op; + uint32_t total_notify_rx_count; +} TC_200_SUT_MGR; + +TC_200_SUT_MGR *p_tc_200_sut_mgr = NULL; +#endif + +#if TC_206_SUT_SUPPORT +typedef struct +{ + uint8_t initial_value; + uint32_t total_test_count; + uint8_t remote_bd[6]; + uint32_t total_notify_rx_count; + uint32_t begin_time; + uint32_t end_time; + uint32_t elapsed_time; + uint32_t data_rate; +} TC_206_SUT_MGR; + +TC_206_SUT_MGR *p_tc_206_sut_mgr = NULL; +TTP_PERFER_PARAM g_206_sut_prefer_param; +#endif + +#if TC_207_SUT_SUPPORT +typedef struct +{ + uint8_t initial_value; + uint32_t total_test_count; + uint8_t remote_bd[6]; + uint32_t count_remain; + uint32_t begin_time; + uint32_t end_time; + uint32_t elapsed_time; + uint32_t data_rate; +} TC_207_SUT_MGR; + +TC_207_SUT_MGR *p_tc_207_sut_mgr = NULL; +TTP_PERFER_PARAM g_207_sut_prefer_param; +#endif + +#if TC_208_SUT_SUPPORT +typedef struct +{ + uint8_t remote_bd[6]; + uint32_t rx_count; + uint8_t rx_initial_value; + uint32_t rx_begin_time; + uint32_t rx_end_time; + uint32_t rx_elapsed_time; + uint32_t rx_data_rate; + + uint32_t tx_count_remain; + uint8_t tx_initial_value; + uint32_t tx_begin_time; + uint32_t tx_end_time; + uint32_t tx_elapsed_time; + uint32_t tx_data_rate; +} TC_208_SUT_MGR; + +TC_208_SUT_MGR *p_tc_208_sut_mgr = NULL; +TTP_PERFER_PARAM g_208_sut_prefer_param; +#endif + +void tc_20x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data) +{ + T_TP_CB_DATA *p_cb = (T_TP_CB_DATA *)p_cb_data; + APP_PRINT_INFO1("tc_20x_sut_client_result_callback: %d.", p_cb->cb_type); + switch (p_cb->cb_type) + { + case TP_CLIENT_CB_TYPE_DISC_RESULT: + APP_PRINT_INFO2("TP_CLIENT_CB_TYPE_DISC_RESULT: is_found %d, value_handle 0x%x", + p_cb->cb_content.disc_result.is_found, + p_cb->cb_content.disc_result.char_tp.value_handle); + tp_client_write_cccd(conn_id, GATT_CLIENT_CHAR_CONFIG_NOTIFY); + break; + + case TP_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_cb->cb_content.write_result.type) + { + case TP_WRITE_CCCD: +#if TC_200_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { + T_TP_CONFIG_OP op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; + if (p_tc_200_sut_mgr->mode % 2 == 0) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; + data_uart_print("Off data length extension\r\n"); + } + else if (p_tc_200_sut_mgr->mode % 2 == 1) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_251; + data_uart_print("On data length extension\r\n"); + } + + APP_PRINT_INFO1("TP_WRITE_CCCD: cause 0x%x.", p_cb->cb_content.write_result.cause); + + tp_client_write_value(conn_id, 1, &op); + p_tc_200_sut_mgr->cur_config_state = TP_CONFIG_STATE_CONFIGING; + p_tc_200_sut_mgr->cur_config_op = op; + } +#endif +#if TC_206_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + tp_client_read_prefer_param(conn_id); + } +#endif +#if TC_207_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + tp_client_read_prefer_param(conn_id); + } +#endif +#if TC_208_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + tp_client_read_prefer_param(conn_id); + } +#endif + break; + case TP_WRITE_CHAR_VALUE: + APP_PRINT_INFO1("TP_WRITE_CHAR_VALUE: cause 0x%x.", p_cb->cb_content.write_result.cause); + if (p_cb->cb_content.write_result.write_type == GATT_WRITE_TYPE_REQ) + { +#if TC_200_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { + if (p_tc_200_sut_mgr->cur_config_state == TP_CONFIG_STATE_CONFIGING) + { + uint8_t data[2]; + data[0] = TP_CONFIG_OP_START; + data[1] = p_tc_200_sut_mgr->mode; + tp_client_write_value(conn_id, 2, data); + p_tc_200_sut_mgr->cur_config_state = TP_CONFIG_STATE_STARTED; + } + } +#endif + } + else if (p_cb->cb_content.write_result.write_type == GATT_WRITE_TYPE_CMD) + { + if (p_cb->cb_content.write_result.cause == 0) + { +#if TC_207_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + tc_207_sut_tx_data_complete(p_cb->cb_content.write_result.credits); + } +#endif +#if TC_208_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + tc_208_sut_tx_data_complete(p_cb->cb_content.write_result.credits); + } +#endif + } + } + break; + default: + break; + } + break; + case TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: +#if TC_200_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0200_TP_NOTIFICATION_TX_01) + { + p_tc_200_sut_mgr->total_notify_rx_count++; + APP_PRINT_INFO3("TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: is_notif 0x%x, value_size %d, total_notify_rx_count %d", + p_cb->cb_content.notif_ind_data.is_notif, + p_cb->cb_content.notif_ind_data.value_size, + p_tc_200_sut_mgr->total_notify_rx_count); + /* MAX_TEST_COUNT * TP_TEST_PARAM_COUNT * tc_tp_notification_tx_01_fixed_len_array_len */ + if (p_tc_200_sut_mgr->mode < p_tc_200_sut_mgr->mode_end && + p_tc_200_sut_mgr->total_notify_rx_count == 4000 * 12 * 5) + { + p_tc_200_sut_mgr->mode++; + p_tc_200_sut_mgr->total_notify_rx_count = 0; + p_tc_200_sut_mgr->total_connect_count--; + tc_200_sut_link_connected(conn_id); + } + } +#endif +#if TC_206_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + APP_PRINT_INFO3("TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: is_notif 0x%x, value_size %d, total_notify_rx_count %d", + p_cb->cb_content.notif_ind_data.is_notif, + p_cb->cb_content.notif_ind_data.value_size, + p_tc_206_sut_mgr->total_notify_rx_count); + if (g_206_sut_prefer_param.length == p_cb->cb_content.notif_ind_data.value_size) + { + if (p_tc_206_sut_mgr->total_notify_rx_count == 0) + { + p_tc_206_sut_mgr->begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[206 SUT]:start rx time = %dms", + p_tc_206_sut_mgr->begin_time); + } + if (g_206_sut_prefer_param.data_check) + { + uint16_t i; + uint8_t *p_value = p_cb->cb_content.notif_ind_data.pValue; + for (i = 0; i < g_206_sut_prefer_param.length; i++) + { + if (p_value[i] != p_tc_206_sut_mgr->initial_value) + { + APP_PRINT_ERROR4("[206 SUT][RX]: data check failed: p_value[%d] 0x%x, initial_value %d, total_notify_rx_count %d", + i, p_value[i], + p_tc_206_sut_mgr->initial_value, + p_tc_206_sut_mgr->total_notify_rx_count); + data_uart_print("[206 SUT][RX]: data check failed\r\n"); + le_disconnect(conn_id); + break; + } + } + } + } + else + { + APP_PRINT_ERROR1("[206 SUT][RX]: Len check failed: length %d", + p_cb->cb_content.notif_ind_data.value_size); + data_uart_print("[206 SUT][RX]: Len check failed: length %d\r\n", + p_cb->cb_content.notif_ind_data.value_size); + le_disconnect(conn_id); + break; + } + p_tc_206_sut_mgr->total_notify_rx_count++; + p_tc_206_sut_mgr->initial_value++; + if (p_tc_206_sut_mgr->total_notify_rx_count == g_206_sut_prefer_param.count) + { + p_tc_206_sut_mgr->end_time = os_sys_time_get(); + p_tc_206_sut_mgr->elapsed_time = os_time_get_elapsed(p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time); + p_tc_206_sut_mgr->data_rate = + g_206_sut_prefer_param.count * g_206_sut_prefer_param.length * 1000 / + (p_tc_206_sut_mgr->elapsed_time); + APP_PRINT_ERROR1("[206 SUT]:end rx time = %dms", + p_tc_206_sut_mgr->end_time); + le_disconnect(conn_id); + } + } +#endif +#if TC_208_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + APP_PRINT_INFO3("TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: is_notif 0x%x, value_size %d, total_notify_rx_count %d", + p_cb->cb_content.notif_ind_data.is_notif, + p_cb->cb_content.notif_ind_data.value_size, + p_tc_208_sut_mgr->rx_count); + if (g_208_sut_prefer_param.length == p_cb->cb_content.notif_ind_data.value_size) + { + if (p_tc_208_sut_mgr->rx_count == 0) + { + p_tc_208_sut_mgr->rx_begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[208 SUT]:start rx time = %dms", + p_tc_208_sut_mgr->rx_begin_time); + } + if (g_208_sut_prefer_param.data_check) + { + uint16_t i; + uint8_t *p_value = p_cb->cb_content.notif_ind_data.pValue; + for (i = 0; i < g_208_sut_prefer_param.length; i++) + { + if (p_value[i] != p_tc_208_sut_mgr->rx_initial_value) + { + APP_PRINT_ERROR4("[208 SUT][RX]: data check failed: p_value[%d] 0x%x, initial_value %d, total_notify_rx_count %d", + i, p_value[i], + p_tc_208_sut_mgr->rx_initial_value, + p_tc_208_sut_mgr->rx_count); + data_uart_print("[208 SUT][RX]: data check failed\r\n"); + le_disconnect(conn_id); + break; + } + } + } + } + else + { + APP_PRINT_ERROR1("[208 SUT][RX]: Len check failed: length %d", + p_cb->cb_content.notif_ind_data.value_size); + data_uart_print("[208 SUT][RX]: Len check failed: length %d\r\n", + p_cb->cb_content.notif_ind_data.value_size); + le_disconnect(conn_id); + break; + } + p_tc_208_sut_mgr->rx_count++; + p_tc_208_sut_mgr->rx_initial_value++; + if (p_tc_208_sut_mgr->rx_count == g_208_sut_prefer_param.count) + { + p_tc_208_sut_mgr->rx_end_time = os_sys_time_get(); + p_tc_208_sut_mgr->rx_elapsed_time = os_time_get_elapsed(p_tc_208_sut_mgr->rx_begin_time, + p_tc_208_sut_mgr->rx_end_time); + p_tc_208_sut_mgr->rx_data_rate = + g_208_sut_prefer_param.count * g_208_sut_prefer_param.length * 1000 / + (p_tc_208_sut_mgr->rx_elapsed_time); + APP_PRINT_ERROR1("[208 SUT]:end rx time = %dms", + p_tc_208_sut_mgr->rx_end_time); + tc_208_sut_dump_rx_result(); + } + } +#endif + break; + case TP_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO2("TP_CLIENT_CB_TYPE_READ_RESULT: cause 0x%x, value_size %d", + p_cb->cb_content.read_result.cause, + p_cb->cb_content.read_result.value_size); + switch (p_cb->cb_content.read_result.type) + { + case TP_READ_PREFER_PARAM: +#if TC_206_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0206_TP_NOTIFICATION_TX_02) + { + if (p_cb->cb_content.read_result.cause == GAP_SUCCESS + && p_cb->cb_content.read_result.value_size == sizeof(TTP_PERFER_PARAM)) + { + memcpy(&g_206_sut_prefer_param, p_cb->cb_content.read_result.p_value, sizeof(TTP_PERFER_PARAM)); + p_tc_206_sut_mgr->total_test_count = g_206_sut_prefer_param.count; + p_tc_206_sut_mgr->initial_value = g_206_sut_prefer_param.initial_value; + APP_PRINT_INFO6("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d", + g_206_sut_prefer_param.con_interval, g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, g_206_sut_prefer_param.mode, + g_206_sut_prefer_param.count, g_206_sut_prefer_param.data_check); + + data_uart_print("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d\r\n", + g_206_sut_prefer_param.con_interval, g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, g_206_sut_prefer_param.mode, + g_206_sut_prefer_param.count, g_206_sut_prefer_param.data_check); +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + if (g_206_sut_prefer_param.mode != 8) + { + T_TP_CONFIG_OP op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + tc_206_sut_phy_update(0); +#endif + if (g_206_sut_prefer_param.mode % 2 == 0) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; + data_uart_print("Off data length extension\r\n"); + } + else if (g_206_sut_prefer_param.mode % 2 == 1) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_251; + data_uart_print("On data length extension\r\n"); + } + tp_client_write_value(conn_id, 1, &op); + } + else +#endif + { + tc_206_sut_update_conn_param(0); + } + } + else + { + APP_PRINT_ERROR0("TP_CLIENT_CB_TYPE_READ_RESULT: TC_0206_TP_NOTIFICATION_TX_02 failed"); + } + } +#endif +#if TC_207_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0207_TP_WRITE_COMMAND_RX_02) + { + if (p_cb->cb_content.read_result.cause == GAP_SUCCESS + && p_cb->cb_content.read_result.value_size == sizeof(TTP_PERFER_PARAM)) + { + memcpy(&g_207_sut_prefer_param, p_cb->cb_content.read_result.p_value, sizeof(TTP_PERFER_PARAM)); + p_tc_207_sut_mgr->total_test_count = g_207_sut_prefer_param.count; + p_tc_207_sut_mgr->initial_value = g_207_sut_prefer_param.initial_value; + p_tc_207_sut_mgr->count_remain = g_207_sut_prefer_param.count; + APP_PRINT_INFO6("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d", + g_207_sut_prefer_param.con_interval, g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, g_207_sut_prefer_param.mode, + g_207_sut_prefer_param.count, g_207_sut_prefer_param.data_check); + + data_uart_print("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d\r\n", + g_207_sut_prefer_param.con_interval, g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, g_207_sut_prefer_param.mode, + g_207_sut_prefer_param.count, g_207_sut_prefer_param.data_check); +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + if (g_207_sut_prefer_param.mode != 8) + { +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + tc_207_sut_phy_update(0); +#endif + if (g_207_sut_prefer_param.mode % 2 == 0) + { + le_set_data_len(0, 27, 0x0848); + data_uart_print("Off data length extension\r\n"); + } + else if (g_207_sut_prefer_param.mode % 2 == 1) + { + le_set_data_len(0, 251, 0x0848); + data_uart_print("On data length extension\r\n"); + } + } + else +#endif + { + tc_207_sut_update_conn_param(0); + } + } + else + { + APP_PRINT_ERROR0("TP_CLIENT_CB_TYPE_READ_RESULT: TC_0207_TP_NOTIFICATION_TX_02 failed"); + } + } +#endif +#if TC_208_SUT_SUPPORT + if (app_get_cur_test_case() == TC_0208_TP_NOTIF_WRITE_CMD_TRX_02) + { + if (p_cb->cb_content.read_result.cause == GAP_SUCCESS + && p_cb->cb_content.read_result.value_size == sizeof(TTP_PERFER_PARAM)) + { + memcpy(&g_208_sut_prefer_param, p_cb->cb_content.read_result.p_value, sizeof(TTP_PERFER_PARAM)); + p_tc_208_sut_mgr->rx_initial_value = g_208_sut_prefer_param.initial_value; + p_tc_208_sut_mgr->tx_initial_value = g_208_sut_prefer_param.initial_value; + p_tc_208_sut_mgr->tx_count_remain = g_208_sut_prefer_param.count; + APP_PRINT_INFO6("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d", + g_208_sut_prefer_param.con_interval, g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.length, g_208_sut_prefer_param.mode, + g_208_sut_prefer_param.count, g_208_sut_prefer_param.data_check); + + data_uart_print("TP_READ_PREFER_PARAM: interval 0x%x, latency 0x%x, length %d, mode %d, count %d, check %d\r\n", + g_208_sut_prefer_param.con_interval, g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.length, g_208_sut_prefer_param.mode, + g_208_sut_prefer_param.count, g_208_sut_prefer_param.data_check); +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + if (g_208_sut_prefer_param.mode != 8) + { + T_TP_CONFIG_OP op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; + if (g_208_sut_prefer_param.mode % 2 == 0) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_27; + le_set_data_len(0, 27, 0x0848); + data_uart_print("Off data length extension\r\n"); + } + else if (g_208_sut_prefer_param.mode % 2 == 1) + { + op = TP_CONFIG_OP_SET_LL_DATA_LEN_251; + le_set_data_len(0, 251, 0x0848); + data_uart_print("On data length extension\r\n"); + } +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + tc_208_sut_phy_update(0); +#endif + tp_client_write_value(conn_id, 1, &op); + } + else +#endif + { + tc_208_sut_update_conn_param(0); + } + } + else + { + APP_PRINT_ERROR0("TP_CLIENT_CB_TYPE_READ_RESULT: TC_0207_TP_NOTIFICATION_TX_02 failed"); + } + } +#endif + break; + default: + break; + } + break; + default: + break; + } +} + +#if TC_200_SUT_SUPPORT +void tc_200_sut_start(uint32_t count, uint8_t mode, uint8_t mode_end, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_200_sut_mgr) + { + p_tc_200_sut_mgr = (TC_200_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_200_SUT_MGR)); + } + else + { + memset(p_tc_200_sut_mgr, 0, sizeof(TC_200_SUT_MGR)); + } + p_tc_200_sut_mgr->total_test_count = count; + if (mode > 7) + { + mode = 7; + } + if (mode_end < mode) + { + mode_end = mode; + } + else if (mode_end > 7) + { + mode_end = 7; + } + p_tc_200_sut_mgr->mode = mode; + p_tc_200_sut_mgr->mode_end = mode_end; + memcpy(p_tc_200_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_200_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_200_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0200_TP_NOTIFICATION_TX_01, reason); + tc_update_disc_reason(reason); + + os_delay(200); + + if (p_tc_200_sut_mgr->total_connect_count < p_tc_200_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 1000; + le_connect(0, p_tc_200_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_200_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0200_TP_NOTIFICATION_TX_01, 0, NULL); + } + } +} + +void tc_200_sut_link_connected(uint8_t conn_id) +{ + p_tc_200_sut_mgr->total_connect_count++; +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + if (p_tc_200_sut_mgr->mode == 2 || p_tc_200_sut_mgr->mode == 3) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + ); + data_uart_print("2M link\r\n"); + } + else if (p_tc_200_sut_mgr->mode == 4 || p_tc_200_sut_mgr->mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + data_uart_print("Coded (s = 2) link\r\n"); + } + else if (p_tc_200_sut_mgr->mode == 6 || p_tc_200_sut_mgr->mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + data_uart_print("Coded (s = 8) link\r\n"); + } + else + { + data_uart_print("1M link\r\n"); + } +#endif + tp_client_start_discovery(conn_id); +} + +void tc_200_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO4("tc_200_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x, total_notify_rx_count %d", + con_interval, conn_slave_latency, conn_supervision_timeout, + p_tc_200_sut_mgr->total_notify_rx_count); + + data_uart_print("tc_200_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x, total_notify_rx_count %d\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout, + p_tc_200_sut_mgr->total_notify_rx_count); + + +} + +void tc_200_sut_dump_result(void) +{ + if (p_tc_200_sut_mgr != NULL) + { + + APP_PRINT_INFO2("tc_200_sut_dump_result: end: total_test_count %d total_connect_count %d\r\n", + p_tc_200_sut_mgr->total_test_count, p_tc_200_sut_mgr->total_connect_count); + + data_uart_print("tc_200_sut_dump_result: end: total_test_count %d total_connect_count %d\r\n", + p_tc_200_sut_mgr->total_test_count, p_tc_200_sut_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } + + +} +void tc_200_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_200_SUT_IN_PARAM_DATA *p_tc_200_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_200_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_200_SUT_IN_PARAM_DATA)); + + p_tc_200_sut_param_data->id = TC_0200_TP_NOTIFICATION_TX_01; + p_tc_200_sut_param_data->total_test_count = max_count; + memcpy(p_tc_200_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_200_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif + +#if TC_206_SUT_SUPPORT + +void tc_206_sut_start(uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 0; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_206_sut_mgr) + { + p_tc_206_sut_mgr = (TC_206_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_206_SUT_MGR)); + } + else + { + memset(p_tc_206_sut_mgr, 0, sizeof(TC_206_SUT_MGR)); + } + + memcpy(p_tc_206_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_206_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_206_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + + tc_206_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0206_TP_NOTIFICATION_TX_02, 0, NULL); + } +} + +void tc_206_sut_link_connected(uint8_t conn_id) +{ + tp_client_start_discovery(conn_id); +} + +void tc_206_sut_update_conn_param(uint8_t conn_id) +{ + le_update_conn_param(conn_id, + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.conn_supervision_timeout, + 2 * (g_206_sut_prefer_param.con_interval - 1), + 2 * (g_206_sut_prefer_param.con_interval - 1) + ); +} + +void tc_206_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_206_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + data_uart_print("tc_206_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout); + + +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_206_sut_phy_update(uint8_t conn_id) +{ + if (g_206_sut_prefer_param.mode == 0 || g_206_sut_prefer_param.mode == 1) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_sut_prefer_param.mode == 2 || g_206_sut_prefer_param.mode == 3) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_sut_prefer_param.mode == 4 || g_206_sut_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_206_sut_prefer_param.mode == 6 || g_206_sut_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } +} + +void tc_206_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + bool phy_result = false; + if (cause == 0) + { + if (g_206_sut_prefer_param.mode == 0 || g_206_sut_prefer_param.mode == 1) + { + if (tx_phy == GAP_PHYS_1M && rx_phy == GAP_PHYS_1M) + { + phy_result = true; + } + } + else if (g_206_sut_prefer_param.mode == 2 || g_206_sut_prefer_param.mode == 3) + { + if (tx_phy == GAP_PHYS_2M && rx_phy == GAP_PHYS_2M) + { + phy_result = true; + } + } + else if (g_206_sut_prefer_param.mode == 4 || g_206_sut_prefer_param.mode == 5 || + g_206_sut_prefer_param.mode == 6 || g_206_sut_prefer_param.mode == 7) + { + if (tx_phy == GAP_PHYS_CODED && rx_phy == GAP_PHYS_CODED) + { + phy_result = true; + } + } + } + if (phy_result == false) + { + APP_PRINT_ERROR0("[206 SUT]: Update phy failed"); + + data_uart_print("[206 SUT]: Update phy failed\r\n"); + le_disconnect(0); + } + else + { + tc_206_sut_update_conn_param(0); + } +} +#endif + +void tc_206_sut_dump_result(void) +{ + if (p_tc_206_sut_mgr != NULL) + { + APP_PRINT_ERROR8("[206 SUT][RX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, + g_206_sut_prefer_param.count, + p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time, + p_tc_206_sut_mgr->elapsed_time, + p_tc_206_sut_mgr->data_rate); + data_uart_print("[206 SUT][RX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_206_sut_prefer_param.con_interval, + g_206_sut_prefer_param.conn_slave_latency, + g_206_sut_prefer_param.length, + g_206_sut_prefer_param.count, + p_tc_206_sut_mgr->begin_time, + p_tc_206_sut_mgr->end_time, + p_tc_206_sut_mgr->elapsed_time, + p_tc_206_sut_mgr->data_rate); + APP_PRINT_ERROR3("[206 SUT][RX]: total_test_count %d total_notify_rx_count %d, initial_value 0x%x\r\n", + p_tc_206_sut_mgr->total_test_count, p_tc_206_sut_mgr->total_notify_rx_count, + p_tc_206_sut_mgr->initial_value); + + data_uart_print("[206 SUT][RX]: total_test_count %d total_notify_rx_count %d, initial_value 0x%x\r\n", + p_tc_206_sut_mgr->total_test_count, p_tc_206_sut_mgr->total_notify_rx_count, + p_tc_206_sut_mgr->initial_value); + + } + else + { + data_uart_print("Not running\r\n"); + } +} + +#endif + +#if TC_207_SUT_SUPPORT + +void tc_207_sut_start(uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 0; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_207_sut_mgr) + { + p_tc_207_sut_mgr = (TC_207_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_207_SUT_MGR)); + } + else + { + memset(p_tc_207_sut_mgr, 0, sizeof(TC_207_SUT_MGR)); + } + + memcpy(p_tc_207_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_207_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_207_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + + tc_207_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0207_TP_WRITE_COMMAND_RX_02, 0, NULL); + } +} + +void tc_207_sut_link_connected(uint8_t conn_id) +{ + tp_client_start_discovery(conn_id); +} + +void tc_207_sut_update_conn_param(uint8_t conn_id) +{ + le_update_conn_param(conn_id, + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.conn_supervision_timeout, + 2 * (g_207_sut_prefer_param.con_interval - 1), + 2 * (g_207_sut_prefer_param.con_interval - 1) + ); +} + +void tc_207_sut_start_send_write_command(uint8_t conn_id) +{ + uint8_t credits = 10; + p_tc_207_sut_mgr->begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[207 SUT]:begin time = %dms", + p_tc_207_sut_mgr->begin_time); + + while (credits) + { + if (p_tc_207_sut_mgr->count_remain) + { + uint8_t value[250]; + memset(value, p_tc_207_sut_mgr->initial_value, + g_207_sut_prefer_param.length); + if (tp_client_write_command(conn_id, g_207_sut_prefer_param.length, value)) + { + credits--; + p_tc_207_sut_mgr->initial_value++; + p_tc_207_sut_mgr->count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } +} + +void tc_207_sut_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (p_tc_207_sut_mgr->count_remain) + { + uint8_t value[250]; + memset(value, p_tc_207_sut_mgr->initial_value, + g_207_sut_prefer_param.length); + if (tp_client_write_command(0, g_207_sut_prefer_param.length, value)) + { + credits--; + p_tc_207_sut_mgr->initial_value++; + p_tc_207_sut_mgr->count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + p_tc_207_sut_mgr->end_time = os_sys_time_get(); + p_tc_207_sut_mgr->elapsed_time = os_time_get_elapsed(p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time); + p_tc_207_sut_mgr->data_rate = + g_207_sut_prefer_param.count * g_207_sut_prefer_param.length * 1000 / + (p_tc_207_sut_mgr->elapsed_time); + APP_PRINT_ERROR1("[207 SUT]:end time = %dms", + p_tc_207_sut_mgr->end_time); + le_disconnect(0); + } + break; + } + } +} + +void tc_207_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_207_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + data_uart_print("tc_207_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_207_sut_prefer_param.con_interval == con_interval && + g_207_sut_prefer_param.conn_slave_latency == conn_slave_latency && + g_207_sut_prefer_param.conn_supervision_timeout == conn_supervision_timeout) + { + tc_207_sut_start_send_write_command(0); + } + else + { + data_uart_print("[207 SUT] error: Invalid conn parameter\r\n"); + le_disconnect(0); + } +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_207_sut_phy_update(uint8_t conn_id) +{ + if (g_207_sut_prefer_param.mode == 0 || g_207_sut_prefer_param.mode == 1) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_sut_prefer_param.mode == 2 || g_207_sut_prefer_param.mode == 3) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_sut_prefer_param.mode == 4 || g_207_sut_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_207_sut_prefer_param.mode == 6 || g_207_sut_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } +} + +void tc_207_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + bool phy_result = false; + if (cause == 0) + { + if (g_207_sut_prefer_param.mode == 0 || g_207_sut_prefer_param.mode == 1) + { + if (tx_phy == GAP_PHYS_1M && rx_phy == GAP_PHYS_1M) + { + phy_result = true; + } + } + else if (g_207_sut_prefer_param.mode == 2 || g_207_sut_prefer_param.mode == 3) + { + if (tx_phy == GAP_PHYS_2M && rx_phy == GAP_PHYS_2M) + { + phy_result = true; + } + } + else if (g_207_sut_prefer_param.mode == 4 || g_207_sut_prefer_param.mode == 5 || + g_207_sut_prefer_param.mode == 6 || g_207_sut_prefer_param.mode == 7) + { + if (tx_phy == GAP_PHYS_CODED && rx_phy == GAP_PHYS_CODED) + { + phy_result = true; + } + } + } + if (phy_result == false) + { + APP_PRINT_INFO0("[207 SUT]: Update phy failed"); + + data_uart_print("[207 SUT]: Update phy failed\r\n"); + le_disconnect(0); + } + else + { + tc_207_sut_update_conn_param(0); + } +} +#endif + +void tc_207_sut_dump_result(void) +{ + if (p_tc_207_sut_mgr != NULL) + { + APP_PRINT_ERROR8("[207 SUT][TX]: conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, + g_207_sut_prefer_param.count, + p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time, + p_tc_207_sut_mgr->elapsed_time, + p_tc_207_sut_mgr->data_rate); + data_uart_print("[207 SUT][TX]: conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_207_sut_prefer_param.con_interval, + g_207_sut_prefer_param.conn_slave_latency, + g_207_sut_prefer_param.length, + g_207_sut_prefer_param.count, + p_tc_207_sut_mgr->begin_time, + p_tc_207_sut_mgr->end_time, + p_tc_207_sut_mgr->elapsed_time, + p_tc_207_sut_mgr->data_rate); + APP_PRINT_ERROR3("[207 SUT][TX]: total_test_count %d count_remain %d, initial_value %d\r\n", + p_tc_207_sut_mgr->total_test_count, p_tc_207_sut_mgr->count_remain, + p_tc_207_sut_mgr->initial_value); + + data_uart_print("[207 SUT][TX]: total_test_count %d count_remain %d, initial_value %d\r\n", + p_tc_207_sut_mgr->total_test_count, p_tc_207_sut_mgr->count_remain, + p_tc_207_sut_mgr->initial_value); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +#endif + +#if TC_208_SUT_SUPPORT + +void tc_208_sut_start(uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 0; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_208_sut_mgr) + { + p_tc_208_sut_mgr = (TC_208_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_208_SUT_MGR)); + } + else + { + memset(p_tc_208_sut_mgr, 0, sizeof(TC_208_SUT_MGR)); + } + + memcpy(p_tc_208_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_208_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_208_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + data_uart_print("Disc reason 0x%04x\r\n", reason); + + tc_208_sut_dump_tx_result(); + tc_208_sut_dump_rx_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0208_TP_NOTIF_WRITE_CMD_TRX_02, 0, NULL); + } +} + +void tc_208_sut_link_connected(uint8_t conn_id) +{ + tp_client_start_discovery(conn_id); +} + +void tc_208_sut_update_conn_param(uint8_t conn_id) +{ + le_update_conn_param(conn_id, + g_208_sut_prefer_param.con_interval, + g_208_sut_prefer_param.con_interval, + g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.conn_supervision_timeout, + 2 * (g_208_sut_prefer_param.con_interval - 1), + 2 * (g_208_sut_prefer_param.con_interval - 1) + ); +} + +void tc_208_sut_start_send_write_command(uint8_t conn_id) +{ + uint8_t credits = 10; + p_tc_208_sut_mgr->tx_begin_time = os_sys_time_get(); + APP_PRINT_ERROR1("[208 SUT]:begin tx time = %dms", + p_tc_208_sut_mgr->tx_begin_time); + + while (credits) + { + if (p_tc_208_sut_mgr->tx_count_remain) + { + uint8_t value[250]; + memset(value, p_tc_208_sut_mgr->tx_initial_value, + g_208_sut_prefer_param.length); + if (tp_client_write_command(conn_id, g_208_sut_prefer_param.length, value)) + { + credits--; + p_tc_208_sut_mgr->tx_initial_value++; + p_tc_208_sut_mgr->tx_count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + + } + else + { + break; + } + } +} + +void tc_208_sut_tx_data_complete(uint8_t credits) +{ + while (credits) + { + if (p_tc_208_sut_mgr->tx_count_remain) + { + uint8_t value[250]; + memset(value, p_tc_208_sut_mgr->tx_initial_value, + g_208_sut_prefer_param.length); + if (tp_client_write_command(0, g_208_sut_prefer_param.length, value)) + { + credits--; + p_tc_208_sut_mgr->tx_initial_value++; + p_tc_208_sut_mgr->tx_count_remain--; + } + else + { + APP_PRINT_ERROR0("profile callback PROFILE_EVT_SEND_DATA_COMPLETE, send failed"); + break; + } + } + else + { + if (credits == 10) + { + p_tc_208_sut_mgr->tx_end_time = os_sys_time_get(); + p_tc_208_sut_mgr->tx_elapsed_time = os_time_get_elapsed(p_tc_208_sut_mgr->tx_begin_time, + p_tc_208_sut_mgr->tx_end_time); + p_tc_208_sut_mgr->tx_data_rate = + g_208_sut_prefer_param.count * g_208_sut_prefer_param.length * 1000 / + (p_tc_208_sut_mgr->tx_elapsed_time); + + APP_PRINT_ERROR1("[208 SUT]:end tx time = %dms", + p_tc_208_sut_mgr->tx_end_time); + tc_208_sut_dump_tx_result(); + + //le_disconnect(0); + } + break; + } + } +} + +void tc_208_sut_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_208_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + data_uart_print("tc_208_sut_conn_param_update_event: interval = 0x%x, latency = 0x%x, timeout = 0x%x\r\n", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (g_208_sut_prefer_param.con_interval == con_interval && + g_208_sut_prefer_param.conn_slave_latency == conn_slave_latency && + g_208_sut_prefer_param.conn_supervision_timeout == conn_supervision_timeout) + { + tc_208_sut_start_send_write_command(0); + } + else + { + data_uart_print("[208 SUT] error: Invalid conn parameter\r\n"); + le_disconnect(0); + } +} + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_208_sut_phy_update(uint8_t conn_id) +{ + if (g_208_sut_prefer_param.mode == 0 || g_208_sut_prefer_param.mode == 1) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_208_sut_prefer_param.mode == 2 || g_208_sut_prefer_param.mode == 3) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_208_sut_prefer_param.mode == 4 || g_208_sut_prefer_param.mode == 5) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + ); + } + else if (g_208_sut_prefer_param.mode == 6 || g_208_sut_prefer_param.mode == 7) + { + le_set_phy(conn_id, + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + ); + } +} + +void tc_208_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy) +{ + bool phy_result = false; + if (cause == 0) + { + if (g_208_sut_prefer_param.mode == 0 || g_208_sut_prefer_param.mode == 1) + { + if (tx_phy == GAP_PHYS_1M && rx_phy == GAP_PHYS_1M) + { + phy_result = true; + } + } + else if (g_208_sut_prefer_param.mode == 2 || g_208_sut_prefer_param.mode == 3) + { + if (tx_phy == GAP_PHYS_2M && rx_phy == GAP_PHYS_2M) + { + phy_result = true; + } + } + else if (g_208_sut_prefer_param.mode == 4 || g_208_sut_prefer_param.mode == 5 || + g_208_sut_prefer_param.mode == 6 || g_208_sut_prefer_param.mode == 7) + { + if (tx_phy == GAP_PHYS_CODED && rx_phy == GAP_PHYS_CODED) + { + phy_result = true; + } + } + } + if (phy_result == false) + { + APP_PRINT_INFO0("[208 SUT]: Update phy failed"); + + data_uart_print("[208 SUT]: Update phy failed\r\n"); + le_disconnect(0); + } + else + { + tc_208_sut_update_conn_param(0); + } +} +#endif + +void tc_208_sut_dump_rx_result(void) +{ + if (p_tc_208_sut_mgr != NULL) + { + APP_PRINT_ERROR8("[208 SUT][RX]:conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_208_sut_prefer_param.con_interval, + g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.length, + g_208_sut_prefer_param.count, + p_tc_208_sut_mgr->rx_begin_time, + p_tc_208_sut_mgr->rx_end_time, + p_tc_208_sut_mgr->rx_elapsed_time, + p_tc_208_sut_mgr->rx_data_rate); + data_uart_print("[208 SUT][RX]:conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_208_sut_prefer_param.con_interval, + g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.length, + g_208_sut_prefer_param.count, + p_tc_208_sut_mgr->rx_begin_time, + p_tc_208_sut_mgr->rx_end_time, + p_tc_208_sut_mgr->rx_elapsed_time, + p_tc_208_sut_mgr->rx_data_rate); + APP_PRINT_ERROR2("[208 SUT][RX]: count %d rx_count %d\r\n", + g_208_sut_prefer_param.count, p_tc_208_sut_mgr->rx_count); + + data_uart_print("[208 SUT][RX]: count %d rx_count %d\r\n", + g_208_sut_prefer_param.count, p_tc_208_sut_mgr->rx_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_208_sut_dump_tx_result(void) +{ + if (p_tc_208_sut_mgr != NULL) + { + APP_PRINT_ERROR8("[208 SUT][TX]:conn_interval = %d,conn_latency = %d, length = %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate = %dBytes/s", + g_208_sut_prefer_param.con_interval, + g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.length, + g_208_sut_prefer_param.count, + p_tc_208_sut_mgr->tx_begin_time, + p_tc_208_sut_mgr->tx_end_time, + p_tc_208_sut_mgr->tx_elapsed_time, + p_tc_208_sut_mgr->tx_data_rate); + data_uart_print("[208 SUT][TX]:conn_interval %d, latency %d, length %d, count = %d, begin time = %dms, end time = %dms, elapsed time = %dms, data rate(Bytes/s) %d\r\n", + g_208_sut_prefer_param.con_interval, + g_208_sut_prefer_param.conn_slave_latency, + g_208_sut_prefer_param.length, + g_208_sut_prefer_param.count, + p_tc_208_sut_mgr->tx_begin_time, + p_tc_208_sut_mgr->tx_end_time, + p_tc_208_sut_mgr->tx_elapsed_time, + p_tc_208_sut_mgr->tx_data_rate); + APP_PRINT_ERROR2("[208 SUT][TX]: count %d tx_count_remain %d\r\n", + g_208_sut_prefer_param.count, p_tc_208_sut_mgr->tx_count_remain); + + data_uart_print("[208 SUT][TX]: count %d tx_count_remain %d\r\n", + g_208_sut_prefer_param.count, p_tc_208_sut_mgr->tx_count_remain); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200_sut.h new file mode 100644 index 00000000..ff771709 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_200_sut.h @@ -0,0 +1,100 @@ + +#ifndef _BLE_AUTO_TEST_TC_200_SUT_H_ +#define _BLE_AUTO_TEST_TC_200_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*P_FUN_PROFILE_CLIENT_RESULT_CB)(uint8_t conn_id, void *p_data); + +typedef enum +{ + TP_CONFIG_OP_SET_LL_DATA_LEN_27 = 1, + TP_CONFIG_OP_SET_LL_DATA_LEN_251 = 2, + TP_CONFIG_OP_START = 3, + + TP_CONFIG_OP_RFU = 0xFF +} T_TP_CONFIG_OP; + + +typedef enum +{ + TP_CONFIG_STATE_CONFIGING = 1, + TP_CONFIG_STATE_STARTED = 2, + + TP_CONFIG_STATE_RFU = 0xFF +} T_TP_CONFIG_STATE; + +void tc_20x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data); + + +/** + +*/ +typedef struct _T_TC_200_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + T_TP_CONFIG_STATE cur_config_state; + T_TP_CONFIG_OP cur_config_op; + uint32_t total_notify_rx_count; +} T_TC_200_SUT_IN_PARAM_DATA; + +void tc_200_sut_start(uint32_t count, uint8_t mode, uint8_t mode_end, uint8_t remote_bd[6]); +void tc_200_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_200_sut_link_connected(uint8_t conn_id); +void tc_200_sut_conn_param_update_event(uint8_t conn_id); +void tc_200_sut_dump_result(void); +void tc_200_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + +void tc_206_sut_start(uint8_t remote_bd[6]); +void tc_206_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_206_sut_link_connected(uint8_t conn_id); +void tc_206_sut_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_206_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +void tc_206_sut_phy_update(uint8_t conn_id); +#endif +void tc_206_sut_update_conn_param(uint8_t conn_id); +void tc_206_sut_dump_result(void); + +void tc_207_sut_start(uint8_t remote_bd[6]); +void tc_207_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_207_sut_link_connected(uint8_t conn_id); +void tc_207_sut_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_207_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +void tc_207_sut_phy_update(uint8_t conn_id); +#endif +void tc_207_sut_update_conn_param(uint8_t conn_id); +void tc_207_sut_dump_result(void); +void tc_207_sut_tx_data_complete(uint8_t credits); + +void tc_208_sut_start(uint8_t remote_bd[6]); +void tc_208_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_208_sut_link_connected(uint8_t conn_id); +void tc_208_sut_conn_param_update_event(uint8_t conn_id); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void tc_208_sut_notification_phy_update_event(uint8_t conn_id, uint16_t cause, + T_GAP_PHYS_TYPE tx_phy, T_GAP_PHYS_TYPE rx_phy); +void tc_208_sut_phy_update(uint8_t conn_id); +#endif +void tc_208_sut_update_conn_param(uint8_t conn_id); +void tc_208_sut_dump_rx_result(void); +void tc_208_sut_dump_tx_result(void); +void tc_208_sut_tx_data_complete(uint8_t credits); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300.c new file mode 100644 index 00000000..d5fe68cf --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300.c @@ -0,0 +1,263 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + +#include "os_sched.h" +#include +#include + +#include +#include + + + +#if TC_300_SUPPORT +/** + TC_0301_ADV_DISC, +*/ + +typedef struct +{ + uint16_t id; + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; +} TC_300_MGR; +TC_300_MGR *p_tc_300_mgr = NULL; + +void tc_300_adv_only_start(uint32_t count) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + + if (NULL == p_tc_300_mgr) + { + p_tc_300_mgr = (TC_300_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_300_MGR)); + } + else + { + memset(p_tc_300_mgr, 0, sizeof(TC_300_MGR)); + } + p_tc_300_mgr->total_test_count = count; + + + le_adv_start(); +} + + + +void tc_300_adv_only_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + reset_vendor_counter(); + g_test_end_time = read_vendor_counter_no_display(); + p_tc_300_mgr->total_connect_count++; + +} + +void tc_300_adv_only_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + g_test_end_time = read_vendor_counter_no_display(); + + tc_check_remote_disc_reason(TC_0300_ADV_ONLY, reason); + tc_update_disc_reason(reason); + +#if 0 + if ((reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && + (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + data_uart_print( + "tc_300_adv_only_link_disconnected fail: reason 0x%4x, begin time= %d,end time=%d,elapase time=%dus, conn_interval: %d,conn_latency: %d, conn_supervision_timeout: %d\r\n", + reason, + g_test_begin_time, + g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK, + conn_interval, + conn_latency, + conn_supervision_timeout); + } +#endif + + if (p_tc_300_mgr->total_connect_count < p_tc_300_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_300_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0300_ADV_ONLY, 0, NULL); + } + } + +} + +void tc_300_dump_result(void) +{ + if (p_tc_300_mgr != NULL) + { + APP_PRINT_INFO2("tc 300 sut: end: total_test_count %d total_connect_count %d\r\n", + p_tc_300_mgr->total_test_count, p_tc_300_mgr->total_connect_count); + + data_uart_print("tc 300 sut: end: total_test_count %d total_connect_count %d\r\n", + p_tc_300_mgr->total_test_count, p_tc_300_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + + +void tc_300_add_case(uint32_t max_count) +{ + + T_TC_300_IN_PARAM_DATA *p_tc_300_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_300_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_300_IN_PARAM_DATA)); + + p_tc_300_param_data->id = TC_0300_ADV_ONLY; + p_tc_300_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_300_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + + +/** + TC_0301_ADV_DISC, +*/ +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; +} TC_301_MGR; +TC_301_MGR *p_tc_301_mgr = NULL; + +void tc_301_adv_disc_start(uint32_t count) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + + if (NULL == p_tc_301_mgr) + { + p_tc_301_mgr = (TC_301_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_301_MGR)); + } + else + { + memset(p_tc_301_mgr, 0, sizeof(TC_301_MGR)); + } + p_tc_301_mgr->total_test_count = count; + + + le_adv_start(); +} + + + +void tc_301_adv_disc_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + reset_vendor_counter(); + g_test_end_time = read_vendor_counter_no_display(); + + p_tc_301_mgr->total_connect_count++; + os_delay(200); + le_disconnect(conn_id); +} + +void tc_301_adv_disc_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + g_test_end_time = read_vendor_counter_no_display(); + + tc_check_local_disc_reason(TC_0301_ADV_DISC, reason); + tc_update_disc_reason(reason); + +#if 0 + if (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + data_uart_print( + "tc_301_adv_disc_link_disconnected fail: reason 0x%4x, begin time= %d,end time=%d,elapase time=%dus, conn_interval: %d,conn_latency: %d, conn_supervision_timeout: %d\r\n", + reason, + g_test_begin_time, + g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK, + conn_interval, + conn_latency, + conn_supervision_timeout); + } +#endif + + if (p_tc_301_mgr->total_connect_count < p_tc_301_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_301_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0301_ADV_DISC, 0, NULL); + } + } +} + +void tc_301_dump_result(void) +{ + if (p_tc_301_mgr != NULL) + { + APP_PRINT_INFO2("tc_301_dump_result: end: total_test_count %d total_connect_count %d\r\n", + p_tc_301_mgr->total_test_count, p_tc_301_mgr->total_connect_count); + + data_uart_print("tc_301_dump_result: end: total_test_count %d total_connect_count %d\r\n", + p_tc_301_mgr->total_test_count, p_tc_301_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_301_add_case(uint32_t max_count) +{ + T_TC_301_IN_PARAM_DATA *p_tc_301_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_301_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_301_IN_PARAM_DATA)); + + p_tc_301_param_data->id = TC_0301_ADV_DISC; + p_tc_301_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_301_param_data; + + os_queue_in(&tc_q, p_tc_param); + + +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300.h new file mode 100644 index 00000000..7cf6ce6b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300.h @@ -0,0 +1,49 @@ + +#ifndef _BLE_AUTO_TEST_TC_300_H_ +#define _BLE_AUTO_TEST_TC_300_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + + +typedef struct _T_TC_300_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_300_IN_PARAM_DATA; + + +void tc_300_adv_only_start(uint32_t count); +void tc_300_adv_only_link_connected(uint8_t conn_id); +void tc_300_adv_only_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_300_dump_result(void); +void tc_300_add_case(uint32_t max_count); + + +/** + TC_0301_ADV_DISC +*/ + +typedef struct _T_TC_301_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_301_IN_PARAM_DATA; + +void tc_301_adv_disc_start(uint32_t count); +void tc_301_adv_disc_link_connected(uint8_t conn_id); +void tc_301_adv_disc_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_301_dump_result(void); +void tc_301_add_case(uint32_t max_count); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300_sut.c new file mode 100644 index 00000000..8c276d2d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300_sut.c @@ -0,0 +1,312 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "os_sched.h" +#include +#include +#include +#include + + +#if TC_300_SUT_SUPPORT +/** + +*/ + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + +} TC_300_SUT_MGR; + +static TC_300_SUT_MGR *p_tc_300_sut_mgr = NULL; + +void tc_300_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 10000; + + if (NULL == p_tc_300_sut_mgr) + { + p_tc_300_sut_mgr = (TC_300_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_300_SUT_MGR)); + } + else + { + memset(p_tc_300_sut_mgr, 0, sizeof(TC_300_SUT_MGR)); + } + p_tc_300_sut_mgr->total_test_count = count; + memcpy(p_tc_300_sut_mgr->remote_bd, remote_bd, 6); + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_300_sut_mgr->remote_bd, remote_bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout + ); + +} + +void tc_300_sut_link_connected(uint8_t conn_id) +{ + APP_PRINT_TRACE1("tc_300_sut_link_connected: conn_id %d", conn_id); + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + reset_vendor_counter(); + g_test_end_time = read_vendor_counter_no_display(); + + p_tc_300_sut_mgr->total_connect_count++; + + os_delay(200); + + le_disconnect(conn_id); +} + +void tc_300_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + APP_PRINT_TRACE2("tc_300_sut_link_disconnected: conn_id %d, reason 0x%04x", conn_id, reason); + + g_test_end_time = read_vendor_counter_no_display(); + + + tc_check_local_disc_reason(TC_0300_ADV_ONLY, reason); + tc_update_disc_reason(reason); + +#if 0 + if ((reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && + (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + data_uart_print( + "tc_300_sut_link_disconnected fail: reason 0x%4x, begin time= %d,end time=%d,elapase time=%dus, conn_interval: %d,conn_latency: %d, conn_supervision_timeout: %d\r\n", + reason, + g_test_begin_time, + g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK, + conn_interval, + conn_latency, + conn_supervision_timeout); + } +#endif + + + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 10000; + + if (p_tc_300_sut_mgr->total_connect_count < p_tc_300_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + le_connect(0, p_tc_300_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_300_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0300_ADV_ONLY, 0, NULL); + } + } + } +} +void tc_300_sut_dump_result(void) +{ + if (p_tc_300_sut_mgr != NULL) + { + APP_PRINT_INFO2("tc_300_sut_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_300_sut_mgr->total_test_count, p_tc_300_sut_mgr->total_connect_count); + + data_uart_print("tc_300_sut_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_300_sut_mgr->total_test_count, p_tc_300_sut_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_300_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_300_SUT_IN_PARAM_DATA *p_tc_300_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_300_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_300_SUT_IN_PARAM_DATA)); + + p_tc_300_sut_param_data->id = TC_0300_ADV_ONLY; + p_tc_300_sut_param_data->total_test_count = max_count; + memcpy(p_tc_300_sut_param_data->remote_bd, remote_bd, 6); + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_300_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + + + +/** + TC_0301_ADV_DISC, +*/ + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} TC_301_SUT_MGR; + +static TC_301_SUT_MGR *p_tc_301_sut_mgr = NULL; +void tc_301_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 10000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_301_sut_mgr) + { + p_tc_301_sut_mgr = (TC_301_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_301_SUT_MGR)); + } + else + { + memset(p_tc_301_sut_mgr, 0, sizeof(TC_301_SUT_MGR)); + } + + p_tc_301_sut_mgr->total_test_count = count; + + + memcpy(p_tc_301_sut_mgr->remote_bd, remote_bd, 6); + le_connect(0, p_tc_301_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + + +void tc_301_sut_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + reset_vendor_counter(); + g_test_end_time = read_vendor_counter_no_display(); + p_tc_301_sut_mgr->total_connect_count++; + +} + +void tc_301_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + g_test_end_time = read_vendor_counter_no_display(); + + tc_check_remote_disc_reason(TC_0301_ADV_DISC, reason); + tc_update_disc_reason(reason); + +#if 0 + if (reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE) && + reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + data_uart_print( + "tc_301_sut_link_disconnected fail: reason 0x%4x, begin time= %d,end time=%d,elapase time=%dus, conn_interval: %d,conn_latency: %d, conn_supervision_timeout: %d\r\n", + reason, + g_test_begin_time, + g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK, + conn_interval, + conn_latency, + conn_supervision_timeout); + } +#endif + + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 1000; + + + + if (p_tc_301_sut_mgr->total_connect_count < p_tc_301_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + le_connect(0, p_tc_301_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_301_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0301_ADV_DISC, 0, NULL); + } + } + } + +} + +void tc_301_sut_dump_result(void) +{ + if (p_tc_301_sut_mgr != NULL) + { + APP_PRINT_INFO2("tc_301_sut_dump_result: end: total_test_count %d total_connect_count %d\r\n", + p_tc_301_sut_mgr->total_test_count, p_tc_301_sut_mgr->total_connect_count); + + data_uart_print("tc_301_sut_dump_result: end: total_test_count %d total_connect_count %d\r\n", + p_tc_301_sut_mgr->total_test_count, p_tc_301_sut_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_301_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_301_SUT_IN_PARAM_DATA *p_tc_301_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_301_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_301_SUT_IN_PARAM_DATA)); + + p_tc_301_sut_param_data->id = TC_0301_ADV_DISC; + p_tc_301_sut_param_data->total_test_count = max_count; + memcpy(p_tc_301_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_301_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300_sut.h new file mode 100644 index 00000000..f3b360df --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_300_sut.h @@ -0,0 +1,55 @@ + +#ifndef _BLE_AUTO_TEST_TC_300_SUT_H_ +#define _BLE_AUTO_TEST_TC_300_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if TC_300_SUT_SUPPORT +/** + TC_0300_ADV_ONLY +*/ +typedef struct _T_TC_300_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} T_TC_300_SUT_IN_PARAM_DATA; +void tc_300_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_300_sut_link_connected(uint8_t conn_id); +void tc_300_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_300_sut_dump_result(void); +void tc_300_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + +/** + TC_0301_ADV_DISC +*/ +typedef struct _T_TC_301_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} T_TC_301_SUT_IN_PARAM_DATA; +void tc_301_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_301_sut_link_connected(uint8_t conn_id); +void tc_301_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_301_sut_dump_result(void); +void tc_301_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310.c new file mode 100644 index 00000000..4d1cde91 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310.c @@ -0,0 +1,376 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + + +#include +#include + +#include +#include + +#if TC_310_SUPPORT + + +/** + TC_0301_ADV_DISC, +*/ + +typedef struct +{ + uint16_t id; + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; +} TC_310_MGR; +TC_310_MGR *p_tc_310_mgr = NULL; + +typedef struct +{ + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + T_GAP_PHYS_OPTIONS phy_options; +} TC_310_PHY_ARRAY; + +typedef struct +{ + T_GAP_PHYS_TYPE tx_phy; + T_GAP_PHYS_TYPE rx_phy; +} TC_310_PHY_ARRAY_RESULT; + +TC_310_PHY_ARRAY tc_31x_phy_array[6] = +{ + { + GAP_PHYS_NO_PREFER_TX_BIT | + GAP_PHYS_NO_PREFER_RX_BIT, + + GAP_PHYS_PREFER_1M_BIT | + GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT, + + GAP_PHYS_PREFER_1M_BIT | + GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT, + + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + } +}; + +uint8_t tc_31x_phy_array_index = 0; + + +const TC_310_PHY_ARRAY_RESULT tc_31x_phy_array_result[6] = +{ + {GAP_PHYS_1M, GAP_PHYS_1M}, + {GAP_PHYS_1M, GAP_PHYS_1M}, + {GAP_PHYS_1M, GAP_PHYS_2M}, + {GAP_PHYS_CODED, GAP_PHYS_CODED}, + {GAP_PHYS_CODED, GAP_PHYS_CODED}, + {GAP_PHYS_CODED, GAP_PHYS_CODED} +}; + +void tc_310_adv_only_start(uint32_t count) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + + if (NULL == p_tc_310_mgr) + { + p_tc_310_mgr = (TC_310_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_310_MGR)); + } + else + { + memset(p_tc_310_mgr, 0, sizeof(TC_310_MGR)); + } + p_tc_310_mgr->total_test_count = count; + + + le_adv_start(); +} + + + +void tc_310_adv_only_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + p_tc_310_mgr->total_connect_count++; + + le_set_phy(conn_id, tc_31x_phy_array[tc_31x_phy_array_index].all_phys, + tc_31x_phy_array[tc_31x_phy_array_index].tx_phys, + tc_31x_phy_array[tc_31x_phy_array_index].rx_phys, + tc_31x_phy_array[tc_31x_phy_array_index].phy_options); + + +} + +void tc_310_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy) +{ + if ((cause == GAP_SUCCESS) && + (tc_31x_phy_array_result[tc_31x_phy_array_index].tx_phy == tx_phy) && + (tc_31x_phy_array_result[tc_31x_phy_array_index].rx_phy == rx_phy)) + { + tc_31x_phy_array_index++; + if (tc_31x_phy_array_index < (sizeof(tc_31x_phy_array_result) / sizeof(tc_31x_phy_array_result[0]))) + { + le_set_phy(conn_id, tc_31x_phy_array[tc_31x_phy_array_index].all_phys, + tc_31x_phy_array[tc_31x_phy_array_index].tx_phys, + tc_31x_phy_array[tc_31x_phy_array_index].rx_phys, + tc_31x_phy_array[tc_31x_phy_array_index].phy_options); + } + else + { + /*one round test complete, start next round, wait for link disconnected*/ + tc_31x_phy_array_index = 0; + } + + } + else + { + + } +} + +void tc_310_adv_only_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + g_test_end_time = read_vendor_counter_no_display(); + + tc_check_remote_disc_reason(TC_0310_2M_LONGRANGE_1, reason); + tc_update_disc_reason(reason); + + if (p_tc_310_mgr->total_connect_count < p_tc_310_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_310_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0310_2M_LONGRANGE_1, 0, NULL); + } + } + +} + +void tc_310_dump_result(void) +{ + if (p_tc_310_mgr != NULL) + { + APP_PRINT_INFO2("tc_310_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_310_mgr->total_test_count, p_tc_310_mgr->total_connect_count); + + data_uart_print("tc_310_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_310_mgr->total_test_count, p_tc_310_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + + +void tc_310_add_case(uint32_t max_count) +{ + + T_TC_310_IN_PARAM_DATA *p_tc_310_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_310_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_310_IN_PARAM_DATA)); + + p_tc_310_param_data->id = TC_0310_2M_LONGRANGE_1; + p_tc_310_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_310_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + + +/** + TC_0301_ADV_DISC, +*/ +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; +} TC_311_MGR; +TC_311_MGR *p_tc_311_mgr = NULL; + +void tc_311_adv_disc_start(uint32_t count) +{ + uint8_t secReqEnable = false; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + + if (NULL == p_tc_311_mgr) + { + p_tc_311_mgr = (TC_311_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_311_MGR)); + } + else + { + memset(p_tc_311_mgr, 0, sizeof(TC_311_MGR)); + } + p_tc_311_mgr->total_test_count = count; + + + le_adv_start(); +} + + + +void tc_311_adv_disc_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + reset_vendor_counter(); + g_test_end_time = read_vendor_counter_no_display(); + + p_tc_311_mgr->total_connect_count++; + + le_disconnect(conn_id); +} + +void tc_311_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy) +{ + if ((cause == GAP_SUCCESS) && + (tc_31x_phy_array_result[tc_31x_phy_array_index].tx_phy == tx_phy) && + (tc_31x_phy_array_result[tc_31x_phy_array_index].rx_phy == rx_phy)) + { + tc_31x_phy_array_index++; + if (tc_31x_phy_array_index < sizeof(tc_31x_phy_array_result) / sizeof(tc_31x_phy_array_result[0])) + { + + } + else + { + /*one round test complete, start next round, wait for link disconnected*/ + tc_31x_phy_array_index = 0; + } + + } + else + { + APP_PRINT_ERROR6("tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_311_mgr->total_test_count, p_tc_311_mgr->total_connect_count, + cause, tx_phy, rx_phy, tc_31x_phy_array_index); + + data_uart_print("!!!tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_311_mgr->total_test_count, p_tc_311_mgr->total_connect_count, + cause, tx_phy, rx_phy, tc_31x_phy_array_index); + } +} + +void tc_311_adv_disc_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0311_2M_LONGRANGE_2, reason); + tc_update_disc_reason(reason); + + if (p_tc_311_mgr->total_connect_count < p_tc_311_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_311_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0311_2M_LONGRANGE_2, 0, NULL); + } + } +} + +void tc_311_dump_result(void) +{ + if (p_tc_311_mgr != NULL) + { + APP_PRINT_INFO2("tc_311_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_311_mgr->total_test_count, p_tc_311_mgr->total_connect_count); + + data_uart_print("tc_311_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_311_mgr->total_test_count, p_tc_311_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_311_add_case(uint32_t max_count) +{ + T_TC_311_IN_PARAM_DATA *p_tc_311_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_311_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_311_IN_PARAM_DATA)); + + p_tc_311_param_data->id = TC_0311_2M_LONGRANGE_2; + p_tc_311_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_311_param_data; + + os_queue_in(&tc_q, p_tc_param); + + +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310.h new file mode 100644 index 00000000..893006e8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310.h @@ -0,0 +1,54 @@ + +#ifndef _BLE_AUTO_TEST_TC_310_H_ +#define _BLE_AUTO_TEST_TC_310_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if TC_301_SUPPORT + +typedef struct _T_TC_310_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_310_IN_PARAM_DATA; + + +void tc_310_adv_only_start(uint32_t count); +void tc_310_adv_only_link_connected(uint8_t conn_id); +void tc_310_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy); +void tc_310_adv_only_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_310_dump_result(void); +void tc_310_add_case(uint32_t max_count); + + +/** + TC_0301_ADV_DISC +*/ + +typedef struct _T_TC_311_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_311_IN_PARAM_DATA; + +void tc_311_adv_disc_start(uint32_t count); +void tc_311_adv_disc_link_connected(uint8_t conn_id); +void tc_311_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy); + +void tc_311_adv_disc_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_311_dump_result(void); +void tc_311_add_case(uint32_t max_count); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310_sut.c new file mode 100644 index 00000000..b1b0cf11 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310_sut.c @@ -0,0 +1,450 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + +#include "os_sched.h" +#include +#include + + +#include +#include + + +#if TC_310_SUT_SUPPORT + +/** + +*/ + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; + +} TC_310_SUT_MGR; + +static TC_310_SUT_MGR *p_tc_310_sut_mgr = NULL; + +typedef struct +{ + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + T_GAP_PHYS_OPTIONS phy_options; +} TC_310_SUT_PHY_ARRAY; + +typedef struct +{ + T_GAP_PHYS_TYPE tx_phy; + T_GAP_PHYS_TYPE rx_phy; +} TC_310_SUT_PHY_ARRAY_RESULT; + +TC_310_SUT_PHY_ARRAY tc_31x_sut_phy_array[6] = +{ + { + GAP_PHYS_NO_PREFER_TX_BIT | + GAP_PHYS_NO_PREFER_RX_BIT, + + GAP_PHYS_PREFER_1M_BIT | + GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT, + + GAP_PHYS_PREFER_1M_BIT | + GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT, + + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_PREFER_2M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + } +}; + +uint8_t tc_31x_sut_phy_array_index = 0; + + +const TC_310_SUT_PHY_ARRAY_RESULT tc_31x_sut_phy_array_result[6] = +{ + {GAP_PHYS_1M, GAP_PHYS_1M}, + {GAP_PHYS_1M, GAP_PHYS_1M}, + {GAP_PHYS_1M, GAP_PHYS_2M}, + {GAP_PHYS_CODED, GAP_PHYS_CODED}, + {GAP_PHYS_CODED, GAP_PHYS_CODED}, + {GAP_PHYS_CODED, GAP_PHYS_CODED} +}; + + +void tc_310_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + if (NULL == p_tc_310_sut_mgr) + { + p_tc_310_sut_mgr = (TC_310_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_310_SUT_MGR)); + } + else + { + memset(p_tc_310_sut_mgr, 0, sizeof(TC_310_SUT_MGR)); + } + p_tc_310_sut_mgr->total_test_count = count; + memcpy(p_tc_310_sut_mgr->remote_bd, remote_bd, 6); + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_310_sut_mgr->remote_bd, remote_bd_type, + GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout + ); + +} + +void tc_310_sut_link_connected(uint8_t conn_id) +{ + APP_PRINT_TRACE1("tc_310_sut_link_connected: conn_id %d", conn_id); + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + p_tc_310_sut_mgr->total_connect_count++; + +} + +void tc_310_sut_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy) +{ + if ((cause == GAP_SUCCESS) && + (tc_31x_sut_phy_array_result[tc_31x_sut_phy_array_index].tx_phy == tx_phy) && + (tc_31x_sut_phy_array_result[tc_31x_sut_phy_array_index].rx_phy == rx_phy)) + { + tc_31x_sut_phy_array_index++; + if (tc_31x_sut_phy_array_index < sizeof(tc_31x_sut_phy_array_result) / sizeof( + tc_31x_sut_phy_array_result[0])) + { + APP_PRINT_INFO6("tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x tx_phy %d rx_phy %d index %d\r\n", + p_tc_310_sut_mgr->total_test_count, + p_tc_310_sut_mgr->total_connect_count, + cause, + tx_phy, + rx_phy, + tc_31x_sut_phy_array_index); + } + else + { + /*one round test complete, start next round, disconect link */ + tc_31x_sut_phy_array_index = 0; + le_disconnect(conn_id); + } + } + else + { + APP_PRINT_ERROR6("tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_310_sut_mgr->total_test_count, p_tc_310_sut_mgr->total_connect_count, + cause, tx_phy, rx_phy, tc_31x_sut_phy_array_index); + + data_uart_print("!!!tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_310_sut_mgr->total_test_count, p_tc_310_sut_mgr->total_connect_count, + cause, tx_phy, rx_phy, tc_31x_sut_phy_array_index); + } +} + +void tc_310_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + APP_PRINT_TRACE2("tc_300_sut_link_disconnected: conn_id %d, reason 0x%04x", conn_id, reason); + + tc_check_local_disc_reason(TC_0310_2M_LONGRANGE_1, reason); + tc_update_disc_reason(reason); + + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 1000; + + if (p_tc_310_sut_mgr->total_connect_count < p_tc_310_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + le_connect(0, p_tc_310_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_310_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0310_2M_LONGRANGE_1, 0, NULL); + } + } + } +} +void tc_310_sut_dump_result(void) +{ + if (p_tc_310_sut_mgr != NULL) + { + APP_PRINT_INFO2("tc_300_sut_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_310_sut_mgr->total_test_count, p_tc_310_sut_mgr->total_connect_count); + + data_uart_print("tc_300_sut_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_310_sut_mgr->total_test_count, p_tc_310_sut_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_310_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_310_SUT_IN_PARAM_DATA *p_tc_310_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_310_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_310_SUT_IN_PARAM_DATA)); + + p_tc_310_sut_param_data->id = TC_0310_2M_LONGRANGE_1; + p_tc_310_sut_param_data->total_test_count = max_count; + memcpy(p_tc_310_sut_param_data->remote_bd, remote_bd, 6); + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_310_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + + + +/** + TC_0301_ADV_DISC, +*/ + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} TC_311_SUT_MGR; + +static TC_311_SUT_MGR *p_tc_311_sut_mgr = NULL; +void tc_311_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_311_sut_mgr) + { + p_tc_311_sut_mgr = (TC_311_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_311_SUT_MGR)); + } + else + { + memset(p_tc_311_sut_mgr, 0, sizeof(TC_311_SUT_MGR)); + } + + p_tc_311_sut_mgr->total_test_count = count; + + + memcpy(p_tc_311_sut_mgr->remote_bd, remote_bd, 6); + le_connect(0, p_tc_311_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + + +void tc_311_sut_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + reset_vendor_counter(); + g_test_end_time = read_vendor_counter_no_display(); + p_tc_311_sut_mgr->total_connect_count++; +} + +void tc_311_sut_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy) +{ + if ((cause == GAP_SUCCESS) && + (tc_31x_sut_phy_array_result[tc_31x_sut_phy_array_index].tx_phy == tx_phy) && + (tc_31x_sut_phy_array_result[tc_31x_sut_phy_array_index].rx_phy == rx_phy)) + { + tc_31x_sut_phy_array_index++; + if (tc_31x_sut_phy_array_index < sizeof(tc_31x_sut_phy_array_result) / sizeof( + tc_31x_sut_phy_array_result[0])) + { + APP_PRINT_INFO6("tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_310_sut_mgr->total_test_count, + p_tc_310_sut_mgr->total_connect_count, + cause, + tx_phy, + rx_phy, + tc_31x_sut_phy_array_index); + + le_set_phy(conn_id, tc_31x_sut_phy_array[tc_31x_sut_phy_array_index].all_phys, + tc_31x_sut_phy_array[tc_31x_sut_phy_array_index].tx_phys, + tc_31x_sut_phy_array[tc_31x_sut_phy_array_index].rx_phys, + tc_31x_sut_phy_array[tc_31x_sut_phy_array_index].phy_options); + + } + else + { + /*one round test complete, start next round, disconect link */ + tc_31x_sut_phy_array_index = 0; + le_disconnect(conn_id); + } + } + else + { + APP_PRINT_ERROR6("tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d" + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_310_sut_mgr->total_test_count, p_tc_310_sut_mgr->total_connect_count, + cause, tx_phy, rx_phy, tc_31x_sut_phy_array_index); + + data_uart_print("!!!tc_310_sut_phy_update_evt: total_test_count %d total_connect_count %d", + "cause 0x%04x: tx_phy %d rx_phy %d index %d\r\n", + p_tc_310_sut_mgr->total_test_count, p_tc_310_sut_mgr->total_connect_count, + cause, tx_phy, rx_phy, tc_31x_sut_phy_array_index); + } +} + +void tc_311_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + g_test_end_time = read_vendor_counter_no_display(); + if (reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE) && + reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + data_uart_print( + "tc_311_sut_link_disconnected fail: reason 0x%4x, begin time= %d,end time=%d,elapase time=%dus, conn_interval: %d,conn_latency: %d, conn_supervision_timeout: %d\r\n", + reason, + g_test_begin_time, + g_test_end_time, + (g_test_end_time - g_test_begin_time) / TEST_CPU_CLOCK, + conn_interval, + conn_latency, + conn_supervision_timeout); + } + + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 1000; + + if (p_tc_311_sut_mgr->total_connect_count < p_tc_311_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + le_connect(0, p_tc_311_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_310_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0311_2M_LONGRANGE_2, 0, NULL); + } + } + } + +} + +void tc_311_sut_dump_result(void) +{ + if (p_tc_311_sut_mgr != NULL) + { + APP_PRINT_INFO2("tc_301_sut_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_311_sut_mgr->total_test_count, p_tc_311_sut_mgr->total_connect_count); + + data_uart_print("tc_301_sut_dump_result: total_test_count %d total_connect_count %d\r\n", + p_tc_311_sut_mgr->total_test_count, p_tc_311_sut_mgr->total_connect_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_311_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_311_SUT_IN_PARAM_DATA *p_tc_311_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_311_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_311_SUT_IN_PARAM_DATA)); + + p_tc_311_sut_param_data->id = TC_0311_2M_LONGRANGE_2; + p_tc_311_sut_param_data->total_test_count = max_count; + memcpy(p_tc_311_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_311_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310_sut.h new file mode 100644 index 00000000..37419f4a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_310_sut.h @@ -0,0 +1,59 @@ + +#ifndef _BLE_AUTO_TEST_TC_310_SUT_H_ +#define _BLE_AUTO_TEST_TC_310_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#if TC_310_SUT_SUPPORT +/** + TC_0300_ADV_ONLY +*/ +typedef struct _T_TC_310_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} T_TC_310_SUT_IN_PARAM_DATA; +void tc_310_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_310_sut_link_connected(uint8_t conn_id); +void tc_310_sut_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy); +void tc_310_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_310_sut_dump_result(void); +void tc_310_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + +/** + TC_0301_ADV_DISC +*/ +typedef struct _T_TC_311_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} T_TC_311_SUT_IN_PARAM_DATA; +void tc_311_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_311_sut_link_connected(uint8_t conn_id); +void tc_311_sut_phy_update_evt(uint8_t conn_id, uint16_t cause, T_GAP_PHYS_TYPE tx_phy, + T_GAP_PHYS_TYPE rx_phy); +void tc_311_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_311_sut_dump_result(void); +void tc_311_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400.c new file mode 100644 index 00000000..0e26dc8e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400.c @@ -0,0 +1,284 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + + +#include +#include + +#include +#include + +#if TC_400_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t ce_length_min; + uint16_t ce_length_max; +} TC_400_MGR; +TC_400_MGR *p_tc_400_mgr = NULL; + +void tc_400_start(uint32_t count) +{ + /** + Advertising_Interval_Min: Range: 0x0020 to 0x4000 + */ + if (NULL == p_tc_400_mgr) + { + p_tc_400_mgr = (TC_400_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_400_MGR)); + } + else + { + memset(p_tc_400_mgr, 0, sizeof(TC_400_MGR)); + } + p_tc_400_mgr->total_test_count = count; + + + p_tc_400_mgr->conn_interval_min = 0x0020; + p_tc_400_mgr->conn_interval_max = 0x0020; + p_tc_400_mgr->conn_latency = 0; + p_tc_400_mgr->supervision_timeout = 500; + p_tc_400_mgr->ce_length_min = 2 * (p_tc_400_mgr->conn_interval_min - 1); + p_tc_400_mgr->ce_length_max = 2 * (p_tc_400_mgr->conn_interval_max - 1); + + le_adv_start(); +} + +void tc_400_link_connected(uint8_t conn_id) +{ + + + p_tc_400_mgr->total_connect_count++; + + le_update_conn_param(conn_id, p_tc_400_mgr->conn_interval_min, p_tc_400_mgr->conn_interval_max, + p_tc_400_mgr->conn_latency, p_tc_400_mgr->supervision_timeout, + p_tc_400_mgr->ce_length_min, p_tc_400_mgr->ce_length_max); + +} + +void tc_400_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0400_CONN_PARAM_UPDATE_SLAVE, reason); + tc_update_disc_reason(reason); + + if (p_tc_400_mgr->total_connect_count < p_tc_400_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_400_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0400_CONN_PARAM_UPDATE_SLAVE, 0, NULL); + } + } + +} + +void tc_400_conn_param_update_evt(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_400_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + + if (con_interval < 0x4000) + { + p_tc_400_mgr->conn_interval_min++; + p_tc_400_mgr->conn_interval_max++; + + le_update_conn_param(conn_id, p_tc_400_mgr->conn_interval_min, p_tc_400_mgr->conn_interval_max, + p_tc_400_mgr->conn_latency, p_tc_400_mgr->supervision_timeout, + p_tc_400_mgr->ce_length_min, p_tc_400_mgr->ce_length_max); + } + else + { + p_tc_400_mgr->conn_interval_min = 0x0020; + p_tc_400_mgr->conn_interval_max = 0x0020; + + le_disconnect(conn_id); + } + + +} + +void tc_400_dump_result(void) +{ + if (p_tc_400_mgr != NULL) + { + APP_PRINT_INFO3("tc_400_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_400_mgr->total_test_count, p_tc_400_mgr->total_connect_count, + p_tc_400_mgr->conn_interval_min); + + data_uart_print("tc_400_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_400_mgr->total_test_count, p_tc_400_mgr->total_connect_count, + p_tc_400_mgr->conn_interval_min); + + } + else + { + data_uart_print("Not running\r\n"); + } + +} + +void tc_400_add_case(uint32_t max_count) +{ + T_TC_400_IN_PARAM_DATA *p_tc_400_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_400_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_400_IN_PARAM_DATA)); + + p_tc_400_param_data->id = TC_0400_CONN_PARAM_UPDATE_SLAVE; + p_tc_400_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_400_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +#if TC_401_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t ce_length_min; + uint16_t ce_length_max; +} TC_401_MGR; +TC_401_MGR *p_tc_401_mgr = NULL; + +void tc_401_start(uint32_t count) +{ + /** + Advertising_Interval_Min: Range: 0x0020 to 0x4000 + */ + if (NULL == p_tc_401_mgr) + { + p_tc_401_mgr = (TC_401_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_401_MGR)); + } + else + { + memset(p_tc_401_mgr, 0, sizeof(TC_401_MGR)); + } + p_tc_401_mgr->total_test_count = count; + + + p_tc_401_mgr->conn_interval_min = 0x0020; + p_tc_401_mgr->conn_interval_max = 0x0020; + p_tc_401_mgr->conn_latency = 0; + p_tc_401_mgr->supervision_timeout = 500; + p_tc_401_mgr->ce_length_min = 2 * (p_tc_401_mgr->conn_interval_min - 1); + p_tc_401_mgr->ce_length_max = 2 * (p_tc_401_mgr->conn_interval_max - 1); + + le_adv_start(); +} + +void tc_401_link_connected(uint8_t conn_id) +{ + p_tc_401_mgr->total_connect_count++; +} + +void tc_401_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0401_CONN_PARAM_UPDATE_SLAVE_01, reason); + tc_update_disc_reason(reason); + + if (p_tc_401_mgr->total_connect_count < p_tc_401_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_401_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0401_CONN_PARAM_UPDATE_SLAVE_01, 0, NULL); + } + } + +} + +void tc_401_conn_param_update_evt(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_401_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + p_tc_401_mgr->conn_interval_min = con_interval; + p_tc_401_mgr->conn_interval_max = con_interval; + p_tc_401_mgr->conn_latency = conn_slave_latency; + p_tc_401_mgr->supervision_timeout = conn_supervision_timeout; + + if (con_interval == 0x4000) + { + le_disconnect(conn_id); + } +} + +void tc_401_dump_result(void) +{ + if (p_tc_401_mgr != NULL) + { + APP_PRINT_INFO3("tc_401_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_401_mgr->total_test_count, p_tc_401_mgr->total_connect_count, + p_tc_401_mgr->conn_interval_min); + + data_uart_print("tc_401_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_401_mgr->total_test_count, p_tc_401_mgr->total_connect_count, + p_tc_401_mgr->conn_interval_min); + } + else + { + data_uart_print("Not running\r\n"); + } + +} + +void tc_401_add_case(uint32_t max_count) +{ + T_TC_401_IN_PARAM_DATA *p_tc_401_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_401_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_401_IN_PARAM_DATA)); + + p_tc_401_param_data->id = TC_0401_CONN_PARAM_UPDATE_SLAVE_01; + p_tc_401_param_data->total_test_count = max_count; + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_401_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400.h new file mode 100644 index 00000000..87f1e551 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400.h @@ -0,0 +1,52 @@ + +#ifndef _BLE_AUTO_TEST_TC_400_H_ +#define _BLE_AUTO_TEST_TC_400_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + dut is slave, dut init connection param update +*/ + +typedef struct _T_TC_400_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_400_IN_PARAM_DATA; + + +void tc_400_start(uint32_t count); +void tc_400_link_connected(uint8_t conn_id); +void tc_400_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_400_conn_param_update_evt(uint8_t conn_id); +void tc_400_dump_result(void); +void tc_400_add_case(uint32_t max_count); + + +/** + dut is slave, sut init connection param update +*/ + +typedef struct _T_TC_401_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_401_IN_PARAM_DATA; + + +void tc_401_start(uint32_t count); +void tc_401_link_connected(uint8_t conn_id); +void tc_401_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_401_conn_param_update_evt(uint8_t conn_id); +void tc_401_dump_result(void); +void tc_401_add_case(uint32_t max_count); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400_sut.c new file mode 100644 index 00000000..88fdef07 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400_sut.c @@ -0,0 +1,317 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + + +#include +#include + + +#include +#include + +#if TC_400_SUT_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} TC_400_SUT_MGR; +TC_400_SUT_MGR *p_tc_400_sut_mgr = NULL; + + +void tc_400_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + uint16_t scan_timeout = 1000; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_400_sut_mgr) + { + p_tc_400_sut_mgr = (TC_400_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_400_SUT_MGR)); + } + else + { + memset(p_tc_400_sut_mgr, 0, sizeof(TC_400_SUT_MGR)); + } + + p_tc_400_sut_mgr->total_test_count = count; + memcpy(p_tc_400_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void tc_400_sut_link_connected(uint8_t conn_id) +{ + p_tc_400_sut_mgr->total_connect_count++; +} + +void tc_400_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0400_CONN_PARAM_UPDATE_SLAVE, reason); + tc_update_disc_reason(reason); + + if (p_tc_400_sut_mgr->total_connect_count < p_tc_400_sut_mgr->total_test_count) + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_400_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_400_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0400_CONN_PARAM_UPDATE_SLAVE, 0, NULL); + } + } +} + +void tc_400_sut_conn_param_update_evt(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_400_sut_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + p_tc_400_sut_mgr->conn_interval = con_interval; + p_tc_400_sut_mgr->conn_latency = conn_slave_latency; + p_tc_400_sut_mgr->conn_supervision_timeout = conn_supervision_timeout; +} + +void tc_400_sut_dump_result(void) +{ + if (p_tc_400_sut_mgr != NULL) + { + APP_PRINT_INFO3("tc_400_sut_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_400_sut_mgr->total_test_count, p_tc_400_sut_mgr->total_connect_count, + p_tc_400_sut_mgr->conn_interval); + + data_uart_print("tc_400_sut_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_400_sut_mgr->total_test_count, p_tc_400_sut_mgr->total_connect_count, + p_tc_400_sut_mgr->conn_interval); + } + else + { + data_uart_print("Not running\r\n"); + } + +} + +void tc_400_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_400_SUT_IN_PARAM_DATA *p_tc_400_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_400_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_400_SUT_IN_PARAM_DATA)); + + p_tc_400_sut_param_data->id = TC_0400_CONN_PARAM_UPDATE_SLAVE; + p_tc_400_sut_param_data->total_test_count = max_count; + memcpy(p_tc_400_sut_param_data->remote_bd, remote_bd, 6); + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_400_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +#if TC_401_SUT_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} TC_401_SUT_MGR; +TC_401_SUT_MGR *p_tc_401_sut_mgr = NULL; + + +void tc_401_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + uint16_t scan_timeout = 1000; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_401_sut_mgr) + { + p_tc_401_sut_mgr = (TC_401_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_401_SUT_MGR)); + } + else + { + memset(p_tc_401_sut_mgr, 0, sizeof(TC_401_SUT_MGR)); + } + + p_tc_401_sut_mgr->total_test_count = count; + memcpy(p_tc_401_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, scan_timeout); +} + +void tc_401_sut_link_connected(uint8_t conn_id) +{ + p_tc_401_sut_mgr->total_connect_count++; + + le_update_conn_param(conn_id, p_tc_401_sut_mgr->conn_interval_min, + p_tc_401_sut_mgr->conn_interval_max, + p_tc_401_sut_mgr->conn_latency, p_tc_401_sut_mgr->conn_supervision_timeout, + 2 * (p_tc_401_sut_mgr->conn_interval_min - 1), + 2 * (p_tc_401_sut_mgr->conn_interval_max - 1)); +} + +void tc_401_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0401_CONN_PARAM_UPDATE_SLAVE_01, reason); + tc_update_disc_reason(reason); + + if (p_tc_401_sut_mgr->total_connect_count < p_tc_401_sut_mgr->total_test_count) + { + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_401_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_401_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0401_CONN_PARAM_UPDATE_SLAVE_01, 0, NULL); + } + } +} + +void tc_401_sut_conn_param_update_evt(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO3("tc_401_sut_conn_param_update_evt update success, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + con_interval, conn_slave_latency, conn_supervision_timeout); + + if (con_interval < 0x4000) + { + p_tc_401_sut_mgr->conn_interval_min++; + p_tc_401_sut_mgr->conn_interval_max++; + + le_update_conn_param(conn_id, p_tc_401_sut_mgr->conn_interval_min, + p_tc_401_sut_mgr->conn_interval_max, + p_tc_401_sut_mgr->conn_latency, p_tc_401_sut_mgr->conn_supervision_timeout, + 2 * (p_tc_401_sut_mgr->conn_interval_min - 1), + 2 * (p_tc_401_sut_mgr->conn_interval_max - 1)); + } + else + { + p_tc_401_sut_mgr->conn_interval_min = 0x0020; + p_tc_401_sut_mgr->conn_interval_max = 0x0020; + } + + + +} + +void tc_401_sut_dump_result(void) +{ + if (p_tc_401_sut_mgr != NULL) + { + APP_PRINT_INFO3("tc_401_sut_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_401_sut_mgr->total_test_count, p_tc_401_sut_mgr->total_connect_count, + p_tc_401_sut_mgr->conn_interval_min); + + data_uart_print("tc_401_sut_dump_result: total_test_count %d total_connect_count %d conn_interval_min 0x%04x\r\n", + p_tc_401_sut_mgr->total_test_count, p_tc_401_sut_mgr->total_connect_count, + p_tc_401_sut_mgr->conn_interval_min); + } + else + { + data_uart_print("Not running\r\n"); + } + +} + +void tc_401_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_401_SUT_IN_PARAM_DATA *p_tc_401_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_401_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_401_SUT_IN_PARAM_DATA)); + + p_tc_401_sut_param_data->id = TC_0401_CONN_PARAM_UPDATE_SLAVE_01; + p_tc_401_sut_param_data->total_test_count = max_count; + memcpy(p_tc_401_sut_param_data->remote_bd, remote_bd, 6); + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_401_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400_sut.h new file mode 100644 index 00000000..6528e3ea --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_400_sut.h @@ -0,0 +1,48 @@ + +#ifndef _BLE_AUTO_TEST_TC_400_SUT_H_ +#define _BLE_AUTO_TEST_TC_400_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef struct _T_TC_400_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint8_t remote_bd[6]; +} T_TC_400_SUT_IN_PARAM_DATA; + + +void tc_400_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_400_sut_link_connected(uint8_t conn_id); +void tc_400_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_400_sut_conn_param_update_evt(uint8_t conn_id); +void tc_400_sut_dump_result(void); +void tc_400_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + +typedef struct _T_TC_401_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint8_t remote_bd[6]; +} T_TC_401_SUT_IN_PARAM_DATA; + +void tc_401_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_401_sut_link_connected(uint8_t conn_id); +void tc_401_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_401_sut_conn_param_update_evt(uint8_t conn_id); +void tc_401_sut_dump_result(void); +void tc_401_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500.c new file mode 100644 index 00000000..1f318bfa --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500.c @@ -0,0 +1,311 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + + +#include +#include + +#include +#include + +#if TC_500_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_read_count; + uint32_t total_write_count; +} TC_500_MGR; + +TC_500_MGR *p_tc_500_mgr = NULL; + + +/***/ +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_read_count; + uint32_t total_write_count; +} TC_501_MGR; + +TC_501_MGR *p_tc_501_mgr = NULL; + + +//TC_0500_SLAVE_AUTO_ADV +void tc_500_salve_auto_adv_start(uint32_t count) +{ + uint8_t secReqEnable = false; + + if (NULL == p_tc_500_mgr) + { + p_tc_500_mgr = (TC_500_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_500_MGR)); + } + else + { + memset(p_tc_500_mgr, 0, sizeof(TC_500_MGR)); + } + + p_tc_500_mgr->total_test_count = count; + + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_500_salve_auto_adv_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0500_SLAVE_AUTO_ADV, reason); + tc_update_disc_reason(reason); + + if (p_tc_500_mgr->total_connect_count < p_tc_500_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_500_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0500_SLAVE_AUTO_ADV, 0, NULL); + } + } +} + +void tc_500_salve_auto_adv_link_connected(uint8_t conn_id) +{ + p_tc_500_mgr->total_connect_count++; + + +} + +void tc_500_dump_result(void) +{ + if (p_tc_500_mgr != NULL) + { + + APP_PRINT_INFO4("tc 500: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_500_mgr->total_test_count, p_tc_500_mgr->total_connect_count, + p_tc_500_mgr->total_read_count, p_tc_500_mgr->total_write_count); + + data_uart_print("tc 500: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_500_mgr->total_test_count, p_tc_500_mgr->total_connect_count, + p_tc_500_mgr->total_read_count, p_tc_500_mgr->total_write_count); + } + else + { + data_uart_print("Not running\r\n"); + } + + +} + +void tc_500_add_case(uint32_t max_count) +{ + T_TC_500_IN_PARAM_DATA *p_tc_500_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_500_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_500_IN_PARAM_DATA)); + + p_tc_500_param_data->id = TC_0500_SLAVE_AUTO_ADV; + p_tc_500_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_500_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} + +//TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ +void tc_501_salve_auto_adv_with_sec_req_start(uint32_t count) +{ + uint8_t secReqEnable = true; + + if (NULL == p_tc_501_mgr) + { + p_tc_501_mgr = (TC_501_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_501_MGR)); + } + else + { + memset(p_tc_501_mgr, 0, sizeof(TC_501_MGR)); + } + + p_tc_501_mgr->total_test_count = count; + + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_501_salve_auto_adv_with_sec_req_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ, reason); + tc_update_disc_reason(reason); + + if (p_tc_501_mgr->total_connect_count < p_tc_501_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_501_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ, 0, NULL); + } + } +} + +void tc_501_salve_auto_adv_with_sec_req_link_connected(uint8_t conn_id) +{ + p_tc_501_mgr->total_connect_count ++; +} + +void tc_501_dump_result(void) +{ + if (p_tc_501_mgr != NULL) + { + APP_PRINT_INFO4("tc 501: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_501_mgr->total_test_count, p_tc_501_mgr->total_connect_count, + p_tc_501_mgr->total_read_count, p_tc_501_mgr->total_write_count); + + data_uart_print("tc 501: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_501_mgr->total_test_count, p_tc_501_mgr->total_connect_count, + p_tc_501_mgr->total_read_count, p_tc_501_mgr->total_write_count); + + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_501_add_case(uint32_t max_count) +{ + T_TC_501_IN_PARAM_DATA *p_tc_501_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_501_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_501_IN_PARAM_DATA)); + + p_tc_501_param_data->id = TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ; + p_tc_501_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_501_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} + + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_read_count; + uint32_t total_write_count; +} TC_502_MGR; + +TC_502_MGR *p_tc_502_mgr = NULL; + +//TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV +void tc_502_salve_auto_adv_start(uint32_t count) +{ + uint8_t secReqEnable = false; + + if (NULL == p_tc_502_mgr) + { + p_tc_502_mgr = (TC_502_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_502_MGR)); + } + else + { + memset(p_tc_502_mgr, 0, sizeof(TC_502_MGR)); + } + + p_tc_502_mgr->total_test_count = count; + + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_502_salve_auto_adv_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_remote_disc_reason(TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV, reason); + tc_update_disc_reason(reason); + + if (p_tc_502_mgr->total_connect_count < p_tc_502_mgr->total_test_count) + { + + le_adv_start(); + } + else + { + tc_502_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV, 0, NULL); + } + } +} + +void tc_502_salve_auto_adv_link_connected(uint8_t conn_id) +{ + p_tc_502_mgr->total_connect_count++; + + le_adv_start(); + +} + +void tc_502_dump_result(void) +{ + if (p_tc_502_mgr != NULL) + { + + APP_PRINT_INFO4("tc 502: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_502_mgr->total_test_count, p_tc_502_mgr->total_connect_count, + p_tc_502_mgr->total_read_count, p_tc_502_mgr->total_write_count); + + data_uart_print("tc 502: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_502_mgr->total_test_count, p_tc_502_mgr->total_connect_count, + p_tc_502_mgr->total_read_count, p_tc_502_mgr->total_write_count); + } + else + { + data_uart_print("Not running\r\n"); + } + + +} + +void tc_502_add_case(uint32_t max_count) +{ + T_TC_502_IN_PARAM_DATA *p_tc_502_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_502_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_502_IN_PARAM_DATA)); + + p_tc_502_param_data->id = TC_0502_SLAVE_MULTIPLE_LINK_AUTO_ADV; + p_tc_502_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_502_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500.h new file mode 100644 index 00000000..ee08e2ba --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500.h @@ -0,0 +1,61 @@ + +#ifndef _BLE_AUTO_TEST_TC_500_H_ +#define _BLE_AUTO_TEST_TC_500_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +/** + TC_0500_SLAVE_AUTO_ADV +*/ + +typedef struct _T_TC_500_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_500_IN_PARAM_DATA; +void tc_500_salve_auto_adv_start(uint32_t count); +void tc_500_salve_auto_adv_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_500_salve_auto_adv_link_connected(uint8_t conn_id); +void tc_500_dump_result(void); +void tc_500_add_case(uint32_t max_count); + + +/** + TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ +*/ +typedef struct _T_TC_501_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_501_IN_PARAM_DATA; +void tc_501_salve_auto_adv_with_sec_req_start(uint32_t count); +void tc_501_salve_auto_adv_with_sec_req_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_501_salve_auto_adv_with_sec_req_link_connected(uint8_t conn_id); +void tc_501_dump_result(void); +void tc_501_add_case(uint32_t max_count); + + +typedef struct _T_TC_502_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_502_IN_PARAM_DATA; +void tc_502_salve_auto_adv_start(uint32_t count); +void tc_502_salve_auto_adv_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_502_salve_auto_adv_link_connected(uint8_t conn_id); +void tc_502_dump_result(void); +void tc_502_add_case(uint32_t max_count); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500_sut.c new file mode 100644 index 00000000..a5995c1d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500_sut.c @@ -0,0 +1,316 @@ +#include +#if TC_500_SUT_SUPPORT +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + +#include "os_sched.h" +#include + + +#include +#include + +#include + + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_read_count; + uint32_t total_write_count; + uint8_t remote_bd[6]; +} TC_500_SUT_MGR; + +TC_500_SUT_MGR *p_tc_500_sut_mgr = NULL; + + +P_FUN_PROFILE_CLIENT_RESULT_CB tc_500_sut_client_result_cb; + + + +void tc_50x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data) +{ + T_PXP_CB_DATA *p_cb = (T_PXP_CB_DATA *)p_cb_data; + APP_PRINT_INFO1("vendor_pxp_client_id: %d.", p_cb->cb_type); + switch (p_cb->cb_type) + { + case PXP_CLIENT_CB_TYPE_DISC_RESULT: + APP_PRINT_INFO2("PXP_CLIENT_CB_TYPE_DISC_RESULT: is_found %d, value_handle 0x%x", + p_cb->cb_content.disc_result.is_found, + p_cb->cb_content.disc_result.pxp_char.value_handle); + if (p_cb->cb_content.disc_result.is_found) + { + uint8_t data[2] = {0x12, 0x34}; + vendor_pxpext_write_value(conn_id, sizeof(data), data); + } + break; + + case PXP_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO1("PXP_CLIENT_CB_TYPE_WRITE_RESULT: cause 0x%x.", + p_cb->cb_content.write_result.cause); + vendor_pxpext_read_value(conn_id); + break; + + case PXP_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO2("PXP_CLIENT_CB_TYPE_READ_RESULT: cause 0x%x, value_size %d", + p_cb->cb_content.read_result.cause, + p_cb->cb_content.read_result.value_size); + if (p_cb->cb_content.read_result.cause == GAP_CAUSE_SUCCESS) + { + uint8_t data[2] = {0x12, 0x34}; + if ((p_cb->cb_content.read_result.value_size == sizeof(data)) && + (0 == memcmp(p_cb->cb_content.read_result.pValue, data, sizeof(data)))) + { + os_delay(1000); + le_disconnect(conn_id); + } + } + break; + default: + break; + } +} + + + +//TC_0500_SLAVE_AUTO_ADV +void tc_500_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + if (NULL == p_tc_500_sut_mgr) + { + p_tc_500_sut_mgr = (TC_500_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_500_SUT_MGR)); + } + else + { + memset(p_tc_500_sut_mgr, 0, sizeof(TC_500_SUT_MGR)); + } + p_tc_500_sut_mgr->total_test_count = count; + memcpy(p_tc_500_sut_mgr->remote_bd, remote_bd, 6); + + le_connect(0, p_tc_500_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_500_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(TC_0500_SLAVE_AUTO_ADV, reason); + tc_update_disc_reason(reason); + + if (p_tc_500_sut_mgr->total_connect_count < p_tc_500_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 1000; + le_connect(0, p_tc_500_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + } + else + { + tc_500_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0500_SLAVE_AUTO_ADV, 0, NULL); + } + } +} + +void tc_500_sut_link_connected(uint8_t conn_id) +{ + p_tc_500_sut_mgr->total_connect_count++; + //gatt write /read + vendor_pxpext_start_discovery(conn_id); + +} + +void tc_500_sut_dump_result(void) +{ + if (p_tc_500_sut_mgr != NULL) + { + + APP_PRINT_INFO4("tc_500_sut_dump_result: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_500_sut_mgr->total_test_count, p_tc_500_sut_mgr->total_connect_count, + p_tc_500_sut_mgr->total_read_count, p_tc_500_sut_mgr->total_write_count); + + data_uart_print("tc_500_sut_dump_result: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_500_sut_mgr->total_test_count, p_tc_500_sut_mgr->total_connect_count, + p_tc_500_sut_mgr->total_read_count, p_tc_500_sut_mgr->total_write_count); + } + else + { + data_uart_print("Not running\r\n"); + } + + +} +void tc_500_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_500_SUT_IN_PARAM_DATA *p_tc_500_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_500_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_500_SUT_IN_PARAM_DATA)); + + p_tc_500_sut_param_data->id = TC_0500_SLAVE_AUTO_ADV; + p_tc_500_sut_param_data->total_test_count = max_count; + memcpy(p_tc_500_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_500_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + + + +//TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ +/***/ +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_read_count; + uint32_t total_write_count; + uint8_t remote_bd[6]; +} TC_501_SUT_MGR; + +TC_501_SUT_MGR *p_tc_501_sut_mgr = NULL; + +void tc_501_sut_start(uint32_t count, uint8_t remote_bd[6]) +{ + uint8_t secReqEnable = true; + uint16_t scan_timeout = 1000; + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + + if (NULL == p_tc_501_sut_mgr) + { + p_tc_501_sut_mgr = (TC_501_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_501_SUT_MGR)); + } + else + { + memset(p_tc_501_sut_mgr, 0, sizeof(TC_501_SUT_MGR)); + } + + p_tc_501_sut_mgr->total_test_count = count; + memcpy(p_tc_501_sut_mgr->remote_bd, remote_bd, 6); + + + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + + le_connect(0, remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_501_sut_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ, reason); + tc_update_disc_reason(reason); + + if (p_tc_501_sut_mgr->total_connect_count < p_tc_501_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_501_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + + } + else + { + tc_501_sut_dump_result(); + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ, 0, NULL); + } + } +} + +void tc_501_sut_link_connected(uint8_t conn_id) +{ + p_tc_501_sut_mgr->total_connect_count ++; + //gatt write/read + vendor_pxpext_start_discovery(conn_id); +} + +void tc_501_sut_dump_result(void) +{ + if (p_tc_501_sut_mgr != NULL) + { + APP_PRINT_INFO4("tc_501_sut_dump_result: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_501_sut_mgr->total_test_count, p_tc_501_sut_mgr->total_connect_count, + p_tc_501_sut_mgr->total_read_count, p_tc_501_sut_mgr->total_write_count); + + data_uart_print("tc_501_sut_dump_result: end: total_test_count %d total_connect_count %d total_read_count %d" + "total_write_count %d\r\n", + p_tc_501_sut_mgr->total_test_count, p_tc_501_sut_mgr->total_connect_count, + p_tc_501_sut_mgr->total_read_count, p_tc_501_sut_mgr->total_write_count); + + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_501_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_501_SUT_IN_PARAM_DATA *p_tc_501_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_501_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_501_SUT_IN_PARAM_DATA)); + + p_tc_501_sut_param_data->id = TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ; + p_tc_501_sut_param_data->total_test_count = max_count; + memcpy(p_tc_501_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_501_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500_sut.h new file mode 100644 index 00000000..97299bcf --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_500_sut.h @@ -0,0 +1,61 @@ + +#ifndef _BLE_AUTO_TEST_TC_500_SUT_H_ +#define _BLE_AUTO_TEST_TC_500_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*P_FUN_PROFILE_CLIENT_RESULT_CB)(uint8_t conn_id, void *p_data); + + +void tc_50x_sut_client_result_callback(uint8_t conn_id, void *p_cb_data); + + +/** + TC_0500_SLAVE_AUTO_ADV +*/ +typedef struct _T_TC_500_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} T_TC_500_SUT_IN_PARAM_DATA; +void tc_500_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_500_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_500_sut_link_connected(uint8_t conn_id); +void tc_500_sut_dump_result(void); +void tc_500_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + +/** + TC_0501_SLAVE_AUTO_ADV_WITH_SEC_REQ +*/ +typedef struct _T_TC_501_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint8_t remote_bd[6]; +} T_TC_501_SUT_IN_PARAM_DATA; +void tc_501_sut_start(uint32_t count, uint8_t remote_bd[6]); +void tc_501_sut_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_501_sut_link_connected(uint8_t conn_id); +void tc_501_sut_dump_result(void); +void tc_501_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600.c new file mode 100644 index 00000000..c7a7dfbe --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600.c @@ -0,0 +1,304 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "gap_adv.h" +#include "vendor_tp_service.h" + +#include +#include +#include "privacy_mgnt.h" +#include + +#include +#include +#include "hids_kb.h" + + +#if TC_600_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t disc_cmpl_fail_cnt; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; +} TC_600_MGR; + +TC_600_MGR *p_tc_600_mgr = NULL; + + +void tc_600_iop_android_legacl_pair_start(uint32_t count) +{ + // hids_add_service(app_profile_callback); + + uint8_t secReqEnable = true; + if (NULL == p_tc_600_mgr) + { + p_tc_600_mgr = (TC_600_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_600_MGR)); + } + else + { + memset(p_tc_600_mgr, 0, sizeof(TC_600_MGR)); + } + memset(&g_ble_disconn_reason, 0, sizeof(g_ble_disconn_reason)); + p_tc_600_mgr->total_test_count = count; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_600_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + + tc_check_remote_disc_reason(TC_0600_IOP_PAIR_LEGACL, reason); + tc_update_disc_reason(reason); + + if ((reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && + (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + p_tc_600_mgr->disc_cmpl_fail_cnt++; + APP_PRINT_ERROR2("tc_600_iop_android_legacl_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_600_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_600_iop_android_legacl_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_600_mgr->disc_cmpl_fail_cnt); + + } + + if (p_tc_600_mgr->total_connect_count < p_tc_600_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_600_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0600_IOP_PAIR_LEGACL, 0, NULL); + } + } +} + +void tc_600_iop_android_legacl_pair_link_connected(uint8_t conn_id) +{ + p_tc_600_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_600_iop_android_legacl_pair_link_connected total_connect_count %d\r\n", + p_tc_600_mgr->total_connect_count); +} + +void tc_600_iop_android_legacl_pair_state_to_start(uint8_t conn_id) +{ + + p_tc_600_mgr->total_pair_start_count++; +} +void tc_600_iop_android_legacl_pair_state_to_success(uint8_t conn_id) +{ + p_tc_600_mgr->total_pair_success_count++; +} + +void tc_600_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason) +{ + p_tc_600_mgr->total_pair_fail_count++; + APP_PRINT_ERROR2("tc_600_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_600_mgr->total_connect_count); + + data_uart_print("tc_600_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_600_mgr->total_connect_count); +} + +void tc_600_dump_result(void) +{ + if (p_tc_600_mgr != NULL) + { + APP_PRINT_INFO6("tc 600: end: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d disc_cmpl_fail_cnt %d\r\n", + p_tc_600_mgr->total_test_count, p_tc_600_mgr->total_connect_count, + p_tc_600_mgr->total_pair_start_count, p_tc_600_mgr->total_pair_success_count, + p_tc_600_mgr->total_pair_fail_count, p_tc_600_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc 600: end: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d disc_cmpl_fail_cnt %d\r\n", + p_tc_600_mgr->total_test_count, p_tc_600_mgr->total_connect_count, + p_tc_600_mgr->total_pair_start_count, p_tc_600_mgr->total_pair_success_count, + p_tc_600_mgr->total_pair_fail_count, p_tc_600_mgr->disc_cmpl_fail_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_600_add_case(uint32_t max_count) +{ + T_TC_600_IN_PARAM_DATA *p_tc_600_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_600_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_600_IN_PARAM_DATA)); + + p_tc_600_param_data->id = TC_0600_IOP_PAIR_LEGACL; + p_tc_600_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_600_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} +#endif + +/**************************************************************************** +TC +****************************************************************************/ + +#if TC_601_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t disc_cmpl_fail_cnt; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; +} TC_601_MGR; + +TC_601_MGR *p_tc_601_mgr = NULL; + +void tc_601_iop_android_sc_pair_start(uint32_t count) +{ + uint8_t sec_req_enable = true; + uint16_t sec_req_auth = GAP_AUTHEN_BIT_MITM_FLAG | GAP_AUTHEN_BIT_SC_FLAG; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_SC_FLAG; + + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &sec_req_auth); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(uint16_t), &auth_flags); + gap_set_pairable_mode(); + + if (NULL == p_tc_601_mgr) + { + p_tc_601_mgr = (TC_601_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_601_MGR)); + } + else + { + memset(p_tc_601_mgr, 0, sizeof(TC_601_MGR)); + } + + memset(&g_ble_disconn_reason, 0, sizeof(g_ble_disconn_reason)); + p_tc_601_mgr->total_test_count = count; + + le_adv_start(); +} + +void tc_601_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + + tc_check_remote_disc_reason(TC_0600_IOP_PAIR_LEGACL, reason); + tc_update_disc_reason(reason); + + if ((reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && + (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + p_tc_601_mgr->disc_cmpl_fail_cnt++; + APP_PRINT_ERROR2("tc_601_iop_android_sc_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_601_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_601_iop_android_sc_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_601_mgr->disc_cmpl_fail_cnt); + + } + + if (p_tc_601_mgr->total_connect_count < p_tc_601_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_601_dump_result(); + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0601_IOP_PAIR_SC, 0, NULL); + } + } +} + +void tc_601_iop_android_sc_pair_link_connected(uint8_t conn_id) +{ + p_tc_601_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_601_iop_android_sc_pair_link_connected total_connect_count %d\r\n", + p_tc_601_mgr->total_connect_count); + +} + +void tc_601_iop_android_sc_pair_state_to_start(uint8_t conn_id) +{ + + p_tc_601_mgr->total_pair_start_count++; +} +void tc_601_iop_android_sc_pair_state_to_success(uint8_t conn_id) +{ + p_tc_601_mgr->total_pair_success_count++; +} + +void tc_601_iop_android_sc_pair_state_to_fail(uint8_t conn_id) +{ + p_tc_601_mgr->total_pair_fail_count++; + + APP_PRINT_INFO1("tc_601_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_601_mgr->total_connect_count); + + data_uart_print("tc_601_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_601_mgr->total_connect_count); + +} + +void tc_601_dump_result(void) +{ + if (p_tc_601_mgr != NULL) + { + APP_PRINT_INFO6("tc_601_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d disc_cmpl_fail_cnt %d\r\n", + p_tc_601_mgr->total_test_count, p_tc_601_mgr->total_connect_count, + p_tc_601_mgr->total_pair_start_count, p_tc_601_mgr->total_pair_success_count, + p_tc_601_mgr->total_pair_fail_count, p_tc_601_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_601_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d, disc_cmpl_fail_cnt %d\r\n", + p_tc_601_mgr->total_test_count, p_tc_601_mgr->total_connect_count, + p_tc_601_mgr->total_pair_start_count, p_tc_601_mgr->total_pair_success_count, + p_tc_601_mgr->total_pair_fail_count, p_tc_601_mgr->disc_cmpl_fail_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_601_add_case(uint32_t max_count) +{ + T_TC_601_IN_PARAM_DATA *p_tc_601_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_601_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_601_IN_PARAM_DATA)); + + p_tc_601_param_data->id = TC_0601_IOP_PAIR_SC; + p_tc_601_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_601_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600.h new file mode 100644 index 00000000..392016b5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600.h @@ -0,0 +1,55 @@ + +#ifndef _BLE_AUTO_TEST_TC_600_H_ +#define _BLE_AUTO_TEST_TC_600_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + TC_0600_IOP_PAIR_LEGACL +*/ +typedef struct _T_TC_600_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_600_IN_PARAM_DATA; +void tc_600_iop_android_legacl_pair_start(uint32_t count); +void tc_600_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_600_iop_android_legacl_pair_link_connected(uint8_t conn_id); +void tc_600_iop_android_legacl_pair_state_to_start(uint8_t conn_id); +void tc_600_iop_android_legacl_pair_state_to_success(uint8_t conn_id); +void tc_600_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason); +void tc_600_dump_result(void); +void tc_600_add_case(uint32_t max_count); + + + + + + +/** + TC_0601_IOP_PAIR_SC +*/ +typedef struct _T_TC_601_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_601_IN_PARAM_DATA; +void tc_601_iop_android_sc_pair_start(uint32_t count); +void tc_601_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_601_iop_android_sc_pair_link_connected(uint8_t conn_id); +void tc_601_iop_android_sc_pair_state_to_start(uint8_t conn_id); +void tc_601_iop_android_sc_pair_state_to_success(uint8_t conn_id); +void tc_601_iop_android_sc_pair_state_to_fail(uint8_t conn_id); +void tc_601_dump_result(void); +void tc_601_add_case(uint32_t max_count); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600_sut.c new file mode 100644 index 00000000..3e134e84 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600_sut.c @@ -0,0 +1,354 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + + +#include "os_sched.h" +#include +#include +#include + +#include +#include + +#if TC_600_SUT_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} TC_600_SUT_MGR; + +TC_600_SUT_MGR *p_tc_600_sut_mgr = NULL; + + +void tc_600_sut_iop_android_legacl_pair_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 10000; + + uint8_t sec_req_enable = true; + uint16_t sec_req_auth = GAP_AUTHEN_BIT_MITM_FLAG | + GAP_AUTHEN_BIT_FORCE_BONDING_FLAG; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &sec_req_auth); + + + if (NULL == p_tc_600_sut_mgr) + { + p_tc_600_sut_mgr = (TC_600_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_600_SUT_MGR)); + } + else + { + memset(p_tc_600_sut_mgr, 0, sizeof(TC_600_SUT_MGR)); + } + + p_tc_600_sut_mgr->total_test_count = count; + memcpy(p_tc_600_sut_mgr->remote_bd, remote_bd, 6); + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + + le_connect(0, remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + +} + +void tc_600_sut_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(conn_id, reason); + tc_update_disc_reason(reason); + + if (p_tc_600_sut_mgr->total_connect_count < p_tc_600_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 10000; + + le_connect(0, p_tc_600_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + + } + else + { + tc_600_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0600_IOP_PAIR_LEGACL, 0, NULL); + } + } +} +void tc_600_sut_iop_android_legacl_pair_link_connected(uint8_t conn_id) +{ + p_tc_600_sut_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_600_sut_iop_android_legacl_pair_link_connected total_connect_count %d\r\n", + p_tc_600_sut_mgr->total_connect_count); + //initiate pairing + //le_bond_pair(conn_id); +} + +void tc_600_sut_iop_android_legacl_pair_state_to_start(uint8_t conn_id) +{ + + p_tc_600_sut_mgr->total_pair_start_count++; +} +void tc_600_sut_iop_android_legacl_pair_state_to_success(uint8_t conn_id) +{ + p_tc_600_sut_mgr->total_pair_success_count++; + os_delay(1000); + le_disconnect(conn_id); +} + +void tc_600_sut_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason) +{ + p_tc_600_sut_mgr->total_pair_fail_count++; + APP_PRINT_INFO2("tc_600_sut_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_600_sut_mgr->total_connect_count); + + data_uart_print("tc_600_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_600_sut_mgr->total_connect_count); + +} + +void tc_600_sut_dump_result(void) +{ + if (p_tc_600_sut_mgr != NULL) + { + APP_PRINT_INFO5("tc 600: end: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_600_sut_mgr->total_test_count, p_tc_600_sut_mgr->total_connect_count, + p_tc_600_sut_mgr->total_pair_start_count, p_tc_600_sut_mgr->total_pair_success_count, + p_tc_600_sut_mgr->total_pair_fail_count); + + data_uart_print("tc 600: end: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_600_sut_mgr->total_test_count, p_tc_600_sut_mgr->total_connect_count, + p_tc_600_sut_mgr->total_pair_start_count, p_tc_600_sut_mgr->total_pair_success_count, + p_tc_600_sut_mgr->total_pair_fail_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_600_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_600_SUT_IN_PARAM_DATA *p_tc_600_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_600_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_600_SUT_IN_PARAM_DATA)); + + p_tc_600_sut_param_data->id = TC_0600_IOP_PAIR_LEGACL; + p_tc_600_sut_param_data->total_test_count = max_count; + memcpy(p_tc_600_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_600_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +/**************************************************************************** +TC +****************************************************************************/ + +#if TC_601_SUT_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} TC_601_MGR; + +TC_601_MGR *p_tc_601_sut_mgr = NULL; + +void tc_601_sut_iop_android_sc_pair_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 100; + + uint8_t sec_req_enable = false; + uint16_t sec_req_auth = GAP_AUTHEN_BIT_MITM_FLAG | GAP_AUTHEN_BIT_SC_FLAG | + GAP_AUTHEN_BIT_FORCE_BONDING_FLAG; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG | GAP_AUTHEN_BIT_SC_FLAG; + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(uint16_t), &auth_flags); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &sec_req_auth); + gap_set_pairable_mode(); + + if (NULL == p_tc_601_sut_mgr) + { + p_tc_601_sut_mgr = (TC_601_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_601_MGR)); + } + else + { + memset(p_tc_601_sut_mgr, 0, sizeof(TC_601_MGR)); + } + + p_tc_601_sut_mgr->total_test_count = count; + memcpy(p_tc_601_sut_mgr->remote_bd, remote_bd, 6); + + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_bond_clear_all_keys(); + + le_connect(0, p_tc_601_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_601_sut_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(conn_id, reason); + tc_update_disc_reason(reason); + + if (p_tc_601_sut_mgr->total_connect_count < p_tc_601_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 100; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + le_bond_clear_all_keys(); + le_connect(0, p_tc_601_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + + } + else + { + tc_600_sut_dump_result(); + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0601_IOP_PAIR_SC, 0, NULL); + } + } +} + +void tc_601_sut_iop_android_sc_pair_link_connected(uint8_t conn_id) +{ + p_tc_601_sut_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_601_iop_android_sc_pair_link_connected total_connect_count %d\r\n", + p_tc_601_sut_mgr->total_connect_count); + + //initiate pairing + //le_bond_pair(conn_id); + +} + +void tc_601_sut_iop_android_sc_pair_state_to_start(uint8_t conn_id) +{ + + p_tc_601_sut_mgr->total_pair_start_count++; +} +void tc_601_sut_iop_android_sc_pair_state_to_success(uint8_t conn_id) +{ + p_tc_601_sut_mgr->total_pair_success_count++; + os_delay(1000); + le_disconnect(conn_id); +} + +void tc_601_sut_iop_android_sc_pair_state_to_fail(uint8_t conn_id) +{ + p_tc_601_sut_mgr->total_pair_fail_count++; + + APP_PRINT_INFO1("tc_601_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_601_sut_mgr->total_connect_count); + + data_uart_print("tc_601_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_601_sut_mgr->total_connect_count); + +} + +void tc_601_sut_dump_result(void) +{ + if (p_tc_601_sut_mgr != NULL) + { + APP_PRINT_INFO5("tc 601: end: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_601_sut_mgr->total_test_count, p_tc_601_sut_mgr->total_connect_count, + p_tc_601_sut_mgr->total_pair_start_count, p_tc_601_sut_mgr->total_pair_success_count, + p_tc_601_sut_mgr->total_pair_fail_count); + + data_uart_print("tc 601: end: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_601_sut_mgr->total_test_count, p_tc_601_sut_mgr->total_connect_count, + p_tc_601_sut_mgr->total_pair_start_count, p_tc_601_sut_mgr->total_pair_success_count, + p_tc_601_sut_mgr->total_pair_fail_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_601_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_601_SUT_IN_PARAM_DATA *p_tc_601_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_601_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_601_SUT_IN_PARAM_DATA)); + + p_tc_601_sut_param_data->id = TC_0601_IOP_PAIR_SC; + p_tc_601_sut_param_data->total_test_count = max_count; + memcpy(p_tc_601_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_601_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600_sut.h new file mode 100644 index 00000000..1dac7ab6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_600_sut.h @@ -0,0 +1,69 @@ + +#ifndef _BLE_AUTO_TEST_TC_600_SUT_H_ +#define _BLE_AUTO_TEST_TC_600_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + TC_0600_IOP_PAIR_LEGACL +*/ +typedef struct _T_TC_600_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} T_TC_600_SUT_IN_PARAM_DATA; + +void tc_600_sut_iop_android_legacl_pair_start(uint32_t count, uint8_t remote_bd[6]); +void tc_600_sut_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_600_sut_iop_android_legacl_pair_link_connected(uint8_t conn_id); +void tc_600_sut_iop_android_legacl_pair_state_to_start(uint8_t conn_id); +void tc_600_sut_iop_android_legacl_pair_state_to_success(uint8_t conn_id); +void tc_600_sut_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason); +void tc_600_sut_dump_result(void); +void tc_600_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + + + +/** + TC_0601_IOP_PAIR_SC +*/ +typedef struct _T_TC_601_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} T_TC_601_SUT_IN_PARAM_DATA; +void tc_601_sut_iop_android_sc_pair_start(uint32_t count, uint8_t remote_bd[6]); +void tc_601_sut_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_601_sut_iop_android_sc_pair_link_connected(uint8_t conn_id); +void tc_601_sut_iop_android_sc_pair_state_to_start(uint8_t conn_id); +void tc_601_sut_iop_android_sc_pair_state_to_success(uint8_t conn_id); +void tc_601_sut_iop_android_sc_pair_state_to_fail(uint8_t conn_id); +void tc_601_sut_dump_result(void); +void tc_601_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_700.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_700.c new file mode 100644 index 00000000..c141be88 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_700.c @@ -0,0 +1,147 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "gap_adv.h" +#include "vendor_tp_service.h" + +#include +#include +#include +#include "privacy_mgnt.h" + + +#include +#include + + +#if TC_700_SUPPORT + +void *g_tc_stable_notification_tx_timer_handle = NULL; + + +void tc_700_stable_notification_tx_01_start(void) +{ + le_adv_start(); +} + + +void tc_700_stable_notification_tx_01_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + le_adv_start(); +} + + +void tc_700_stable_notification_tx_01_link_connected(uint8_t conn_id) +{ + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + data_uart_print( + "TC_0700_STABLE_NOTIFICATION_TX_01: conn_interval: %d,conn_latency: %d, conn_supervision_timeout: %d\r\n", + conn_interval, + conn_latency, + conn_supervision_timeout); +} + +void tc_stable_notification_TimeoutHandler(void *pxTimer) +{ + uint8_t value[244] = {0}; + uint32_t conn_id; + os_timer_id_get(&g_tc_stable_notification_tx_timer_handle, &conn_id); + APP_PRINT_INFO1("tc_stable_notification_TimeoutHandler conn_id = %d", conn_id); + + vendor_tp_service_v1_notification((uint8_t)conn_id, gSimpleProfileServiceId, value, 20); +} + +void tc_stable_indication_tx_start_auto_notification_timer(uint8_t conn_id, + uint16_t connection_interval) +{ + if (NULL == g_tc_stable_notification_tx_timer_handle) + { + + os_timer_create(&g_tc_stable_notification_tx_timer_handle, "tc_stable_indication_timer", conn_id, + (connection_interval * 125) / 100, true, tc_stable_notification_TimeoutHandler); + } + + os_timer_start(&g_tc_stable_notification_tx_timer_handle); + +} +void tc_700_stable_notification_tx_01_cccd_enable(uint8_t conn_id, bool bEnable) +{ + if (bEnable) + { +#if 0 + uint16_t con_interval = 12; + uint16_t conn_slave_latency = 4; + uint16_t conn_supervision_timeout = 300; + le_update_conn_param(conn_id, + con_interval, + con_interval, + conn_slave_latency, + conn_supervision_timeout, + 2 * (con_interval - 1), + 2 * (con_interval - 1), + 0); + +#endif + + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO4("tc_700_stable_notification_tx_01_cccd_enable, conn_id = %d, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + conn_id, con_interval, conn_slave_latency, conn_supervision_timeout); + + tc_stable_indication_tx_start_auto_notification_timer(conn_id, con_interval); + + } + else + { + if (g_tc_stable_notification_tx_timer_handle != NULL) + { + os_timer_stop(&g_tc_stable_notification_tx_timer_handle); + } + } + +} + +void tc_700_stable_notification_tx_01_tx_data_complete(uint8_t credits) +{ + //do nothing +} + + +void tc_700_stable_notification_tx_conn_param_update_event(uint8_t conn_id) +{ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &con_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + + APP_PRINT_INFO4("tc_700_stable_notification_tx_conn_param_update_event conn_id = %d, con_interval = 0x%x, conn_slave_latency = 0x%x, conn_supervision_timeout = 0x%x", + conn_id, con_interval, conn_slave_latency, conn_supervision_timeout); + + tc_stable_indication_tx_start_auto_notification_timer(conn_id, con_interval); +} + + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_700.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_700.h new file mode 100644 index 00000000..b359bf31 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_700.h @@ -0,0 +1,26 @@ + +#ifndef _BLE_AUTO_TEST_TC_700_H_ +#define _BLE_AUTO_TEST_TC_700_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + TC_0700_STABLE_NOTIFICATION_TX_01 +*/ +void tc_700_stable_notification_tx_01_start(void); +void tc_700_stable_notification_tx_01_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_700_stable_notification_tx_01_link_connected(uint8_t conn_id); +void tc_700_stable_notification_tx_01_tx_data_complete(uint8_t credits); +void tc_700_stable_notification_tx_01_cccd_enable(uint8_t conn_id, bool bEnable); +void tc_700_stable_notification_tx_conn_param_update_event(uint8_t conn_id); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800.c new file mode 100644 index 00000000..1d08f89d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800.c @@ -0,0 +1,287 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "gap_adv.h" + +#include +#include +#include + +#include +#include + +#if TC_800_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t disc_cmpl_fail_cnt; \ + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; +} TC_800_MGR; + +TC_800_MGR *p_tc_800_mgr = NULL; + + +void tc_800_iop_android_legacl_pair_start(uint32_t count) +{ + + uint8_t secReqEnable = true; + if (NULL == p_tc_800_mgr) + { + p_tc_800_mgr = (TC_800_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_800_MGR)); + } + else + { + memset(p_tc_800_mgr, 0, sizeof(TC_800_MGR)); + } + + p_tc_800_mgr->total_test_count = count; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_adv_start(); +} + +void tc_800_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + + if ((reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && + (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + p_tc_800_mgr->disc_cmpl_fail_cnt++; + APP_PRINT_ERROR2("tc_600_iop_android_legacl_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_800_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_600_iop_android_legacl_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_800_mgr->disc_cmpl_fail_cnt); + + } + + if (p_tc_800_mgr->total_connect_count < p_tc_800_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_800_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0600_IOP_PAIR_LEGACL, 0, NULL); + } + } +} + +void tc_800_iop_android_legacl_pair_link_connected(uint8_t conn_id) +{ + p_tc_800_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_800_iop_android_legacl_pair_link_connected total_connect_count %d\r\n", + p_tc_800_mgr->total_connect_count); +} + +void tc_800_iop_android_legacl_pair_state_to_start(uint8_t conn_id) +{ + + p_tc_800_mgr->total_pair_start_count++; +} +void tc_800_iop_android_legacl_pair_state_to_success(uint8_t conn_id) +{ + p_tc_800_mgr->total_pair_success_count++; +} + +void tc_800_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason) +{ + p_tc_800_mgr->total_pair_fail_count++; + APP_PRINT_ERROR2("tc_800_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_800_mgr->total_connect_count); + + data_uart_print("tc_800_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_800_mgr->total_connect_count); +} + +void tc_800_dump_result(void) +{ + if (p_tc_800_mgr != NULL) + { + APP_PRINT_INFO6("tc_800_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d disc_cmpl_fail_cnt %d\r\n", + p_tc_800_mgr->total_test_count, p_tc_800_mgr->total_connect_count, + p_tc_800_mgr->total_pair_start_count, p_tc_800_mgr->total_pair_success_count, + p_tc_800_mgr->total_pair_fail_count, p_tc_800_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_800_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d disc_cmpl_fail_cnt %d\r\n", + p_tc_800_mgr->total_test_count, p_tc_800_mgr->total_connect_count, + p_tc_800_mgr->total_pair_start_count, p_tc_800_mgr->total_pair_success_count, + p_tc_800_mgr->total_pair_fail_count, p_tc_800_mgr->disc_cmpl_fail_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_800_add_case(uint32_t max_count) +{ + T_TC_800_IN_PARAM_DATA *p_tc_800_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_800_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_800_IN_PARAM_DATA)); + + p_tc_800_param_data->id = TC_0800_IOP_PAIR_LEGACL; + p_tc_800_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_800_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} +#endif + +/**************************************************************************** +TC +****************************************************************************/ + +#if TC_801_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t disc_cmpl_fail_cnt; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; +} TC_801_MGR; + +TC_801_MGR *p_tc_801_mgr = NULL; + +void tc_801_iop_android_sc_pair_start(uint32_t count) +{ + uint8_t sec_req_enable = true; + uint16_t sec_req_auth = GAP_AUTHEN_BIT_MITM_FLAG; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &sec_req_auth); + + if (NULL == p_tc_801_mgr) + { + p_tc_801_mgr = (TC_801_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_801_MGR)); + } + else + { + memset(p_tc_801_mgr, 0, sizeof(TC_801_MGR)); + } + + p_tc_801_mgr->total_test_count = count; + + le_adv_start(); +} + +void tc_801_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + + if ((reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) && + (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + p_tc_801_mgr->disc_cmpl_fail_cnt++; + APP_PRINT_ERROR2("tc_801_iop_android_sc_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_801_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_801_iop_android_sc_pair_link_disconnected: reason 0x%04x, disc_cmpl_fail_cnt %d\r\n", + reason, p_tc_801_mgr->disc_cmpl_fail_cnt); + + } + + + if (p_tc_801_mgr->total_connect_count < p_tc_801_mgr->total_test_count) + { + le_adv_start(); + } + else + { + tc_801_dump_result(); + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0601_IOP_PAIR_SC, 0, NULL); + } + } +} + +void tc_801_iop_android_sc_pair_link_connected(uint8_t conn_id) +{ + p_tc_801_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_801_iop_android_sc_pair_link_connected total_connect_count %d\r\n", + p_tc_801_mgr->total_connect_count); + +} + +void tc_801_iop_android_sc_pair_state_to_start(uint8_t conn_id) +{ + + p_tc_801_mgr->total_pair_start_count++; +} +void tc_801_iop_android_sc_pair_state_to_success(uint8_t conn_id) +{ + p_tc_801_mgr->total_pair_success_count++; +} + +void tc_801_iop_android_sc_pair_state_to_fail(uint8_t conn_id) +{ + p_tc_801_mgr->total_pair_fail_count++; + + APP_PRINT_INFO1("tc_801_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_801_mgr->total_connect_count); + + data_uart_print("tc_801_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_801_mgr->total_connect_count); + +} + +void tc_801_dump_result(void) +{ + if (p_tc_801_mgr != NULL) + { + APP_PRINT_INFO6("tc_801_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d disc_cmpl_fail_cnt %d\r\n", + p_tc_801_mgr->total_test_count, p_tc_801_mgr->total_connect_count, + p_tc_801_mgr->total_pair_start_count, p_tc_801_mgr->total_pair_success_count, + p_tc_801_mgr->total_pair_fail_count, p_tc_801_mgr->disc_cmpl_fail_cnt); + + data_uart_print("tc_801_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d, disc_cmpl_fail_cnt %d\r\n", + p_tc_801_mgr->total_test_count, p_tc_801_mgr->total_connect_count, + p_tc_801_mgr->total_pair_start_count, p_tc_801_mgr->total_pair_success_count, + p_tc_801_mgr->total_pair_fail_count, p_tc_801_mgr->disc_cmpl_fail_cnt); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_801_add_case(uint32_t max_count) +{ + T_TC_801_IN_PARAM_DATA *p_tc_801_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_801_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_801_IN_PARAM_DATA)); + + p_tc_801_param_data->id = TC_0801_IOP_PAIR_SC; + p_tc_801_param_data->total_test_count = max_count; + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_801_param_data; + + os_queue_in(&tc_q, p_tc_param); + +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800.h new file mode 100644 index 00000000..02078883 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800.h @@ -0,0 +1,55 @@ + +#ifndef _BLE_AUTO_TEST_TC_800_H_ +#define _BLE_AUTO_TEST_TC_800_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + TC_0600_IOP_PAIR_LEGACL +*/ +typedef struct _T_TC_800_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_800_IN_PARAM_DATA; +void tc_800_iop_android_legacl_pair_start(uint32_t count); +void tc_800_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_800_iop_android_legacl_pair_link_connected(uint8_t conn_id); +void tc_800_iop_android_legacl_pair_state_to_start(uint8_t conn_id); +void tc_800_iop_android_legacl_pair_state_to_success(uint8_t conn_id); +void tc_800_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason); +void tc_800_dump_result(void); +void tc_800_add_case(uint32_t max_count); + + + + + + +/** + TC_0601_IOP_PAIR_SC +*/ +typedef struct _T_TC_801_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; +} T_TC_801_IN_PARAM_DATA; +void tc_801_iop_android_sc_pair_start(uint32_t count); +void tc_801_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_801_iop_android_sc_pair_link_connected(uint8_t conn_id); +void tc_801_iop_android_sc_pair_state_to_start(uint8_t conn_id); +void tc_801_iop_android_sc_pair_state_to_success(uint8_t conn_id); +void tc_801_iop_android_sc_pair_state_to_fail(uint8_t conn_id); +void tc_801_dump_result(void); +void tc_801_add_case(uint32_t max_count); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800_sut.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800_sut.c new file mode 100644 index 00000000..ee4bfb53 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800_sut.c @@ -0,0 +1,402 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" + +#include "os_sched.h" +#include +#include + +#include + +#include +#include + +#if TC_800_SUT_SUPPORT + +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} TC_800_SUT_MGR; + +TC_800_SUT_MGR *p_tc_800_sut_mgr = NULL; + +typedef struct +{ + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + T_GAP_PHYS_OPTIONS phy_options; +} TC_800_PHY_ARRAY; + +TC_800_PHY_ARRAY tc_80x_phy_array[5] = +{ + { + GAP_PHYS_NO_PREFER_TX_BIT | + GAP_PHYS_NO_PREFER_RX_BIT, + + GAP_PHYS_PREFER_1M_BIT | + GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT, + + GAP_PHYS_PREFER_1M_BIT | + GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT, + + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_PREFER_1M_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_NO + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S2 + }, + + { + 0, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_PREFER_CODED_BIT, + GAP_PHYS_OPTIONS_CODED_PREFER_S8 + } +}; + +uint8_t tc_80x_phy_array_index = 0; + +void tc_800_sut_iop_android_legacl_pair_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 1000; + + uint8_t sec_req_enable = false; + uint16_t sec_req_auth = GAP_AUTHEN_BIT_MITM_FLAG | + GAP_AUTHEN_BIT_FORCE_BONDING_FLAG; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &sec_req_auth); + + + if (NULL == p_tc_800_sut_mgr) + { + p_tc_800_sut_mgr = (TC_800_SUT_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_800_SUT_MGR)); + } + else + { + memset(p_tc_800_sut_mgr, 0, sizeof(TC_800_SUT_MGR)); + } + + p_tc_800_sut_mgr->total_test_count = count; + memcpy(p_tc_800_sut_mgr->remote_bd, remote_bd, 6); + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + + le_connect(0, remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + +} + +void tc_800_sut_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(conn_id, reason); + tc_update_disc_reason(reason); + + if (p_tc_800_sut_mgr->total_connect_count < p_tc_800_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint16_t scan_timeout = 100; + + le_connect(0, p_tc_800_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + + } + else + { + tc_800_sut_dump_result(); + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0600_IOP_PAIR_LEGACL, 0, NULL); + } + } +} +void tc_800_sut_iop_android_legacl_pair_link_connected(uint8_t conn_id) +{ + p_tc_800_sut_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_600_sut_iop_android_legacl_pair_link_connected total_connect_count %d\r\n", + p_tc_800_sut_mgr->total_connect_count); + //initiate pairing + //le_bond_pair(conn_id); + le_set_phy(conn_id, tc_80x_phy_array[tc_80x_phy_array_index].all_phys, + tc_80x_phy_array[tc_80x_phy_array_index].tx_phys, + tc_80x_phy_array[tc_80x_phy_array_index].rx_phys, + tc_80x_phy_array[tc_80x_phy_array_index].phy_options); + + tc_80x_phy_array_index++; +} + +void tc_800_sut_iop_android_legacl_pair_state_to_start(uint8_t conn_id) +{ + p_tc_800_sut_mgr->total_pair_start_count++; +} +void tc_800_sut_iop_android_legacl_pair_state_to_success(uint8_t conn_id) +{ + p_tc_800_sut_mgr->total_pair_success_count++; + le_disconnect(conn_id); +} + +void tc_800_sut_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason) +{ + p_tc_800_sut_mgr->total_pair_fail_count++; + APP_PRINT_INFO2("tc_600_sut_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_800_sut_mgr->total_connect_count); + + data_uart_print("tc_600_iop_android_legacl_pair_state_to_fail: reason 0x%04x, total_connect_count %d\r\n", + reason, p_tc_800_sut_mgr->total_connect_count); +} + +void tc_800_sut_dump_result(void) +{ + if (p_tc_800_sut_mgr != NULL) + { + APP_PRINT_INFO5("tc_800_sut_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_800_sut_mgr->total_test_count, p_tc_800_sut_mgr->total_connect_count, + p_tc_800_sut_mgr->total_pair_start_count, p_tc_800_sut_mgr->total_pair_success_count, + p_tc_800_sut_mgr->total_pair_fail_count); + + data_uart_print("tc_800_sut_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_800_sut_mgr->total_test_count, p_tc_800_sut_mgr->total_connect_count, + p_tc_800_sut_mgr->total_pair_start_count, p_tc_800_sut_mgr->total_pair_success_count, + p_tc_800_sut_mgr->total_pair_fail_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_800_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_800_SUT_IN_PARAM_DATA *p_tc_800_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_800_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_800_SUT_IN_PARAM_DATA)); + + p_tc_800_sut_param_data->id = TC_0800_IOP_PAIR_LEGACL; + p_tc_800_sut_param_data->total_test_count = max_count; + memcpy(p_tc_800_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_800_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} +#endif + +/**************************************************************************** +TC +****************************************************************************/ +#if TC_801_SUT_SUPPORT +typedef struct +{ + uint32_t total_test_count; + uint32_t total_connect_count; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} TC_801_MGR; + +TC_801_MGR *p_tc_801_sut_mgr = NULL; + +void tc_801_sut_iop_android_sc_pair_start(uint32_t count, uint8_t remote_bd[6]) +{ + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 100; + + uint8_t sec_req_enable = false; + uint16_t sec_req_auth = GAP_AUTHEN_BIT_MITM_FLAG | GAP_AUTHEN_BIT_SC_FLAG | + GAP_AUTHEN_BIT_FORCE_BONDING_FLAG; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &sec_req_auth); + + if (NULL == p_tc_801_sut_mgr) + { + p_tc_801_sut_mgr = (TC_801_MGR *)os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(TC_801_MGR)); + } + else + { + memset(p_tc_801_sut_mgr, 0, sizeof(TC_801_MGR)); + } + + p_tc_801_sut_mgr->total_test_count = count; + memcpy(p_tc_801_sut_mgr->remote_bd, remote_bd, 6); + + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_801_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); +} + +void tc_801_sut_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason) +{ + tc_check_local_disc_reason(conn_id, reason); + tc_update_disc_reason(reason); + + if (p_tc_801_sut_mgr->total_connect_count < p_tc_801_sut_mgr->total_test_count + + g_ble_disconn_reason.reason_3e) + { + os_delay(200); + + T_GAP_REMOTE_ADDR_TYPE remote_bd_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint16_t scan_timeout = 100; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 6; + conn_req_param.conn_interval_max = 6; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 300; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + le_connect(0, p_tc_801_sut_mgr->remote_bd, remote_bd_type, GAP_LOCAL_ADDR_LE_PUBLIC, + scan_timeout + ); + + } + else + { + tc_801_sut_dump_result(); + + if (p_tc_result_cb != NULL) + { + p_tc_result_cb(TC_0801_IOP_PAIR_SC, 0, NULL); + } + } +} + +void tc_801_sut_iop_android_sc_pair_link_connected(uint8_t conn_id) +{ + p_tc_801_sut_mgr->total_connect_count++; + APP_PRINT_INFO1("tc_801_sut_iop_android_sc_pair_link_connected total_connect_count %d\r\n", + p_tc_801_sut_mgr->total_connect_count); + + //initiate pairing + //le_bond_pair(conn_id); + +} + +void tc_801_sut_iop_android_sc_pair_state_to_start(uint8_t conn_id) +{ + p_tc_801_sut_mgr->total_pair_start_count++; +} +void tc_801_sut_iop_android_sc_pair_state_to_success(uint8_t conn_id) +{ + p_tc_801_sut_mgr->total_pair_success_count++; + le_disconnect(conn_id); +} + +void tc_801_sut_iop_android_sc_pair_state_to_fail(uint8_t conn_id) +{ + p_tc_801_sut_mgr->total_pair_fail_count++; + + APP_PRINT_INFO1("tc_801_sut_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_801_sut_mgr->total_connect_count); + + data_uart_print("tc_801_sut_iop_android_sc_pair_state_to_fail at total_connect_count %d\r\n", + p_tc_801_sut_mgr->total_connect_count); +} + +void tc_801_sut_dump_result(void) +{ + if (p_tc_801_sut_mgr != NULL) + { + APP_PRINT_INFO5("tc_801_sut_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_801_sut_mgr->total_test_count, p_tc_801_sut_mgr->total_connect_count, + p_tc_801_sut_mgr->total_pair_start_count, p_tc_801_sut_mgr->total_pair_success_count, + p_tc_801_sut_mgr->total_pair_fail_count); + + data_uart_print("tc_801_sut_dump_result: total_test_count %d total_connect_count %d total_pair_start_count %d" + "total_pair_success_count %d total_pair_fail_count %d\r\n", + p_tc_801_sut_mgr->total_test_count, p_tc_801_sut_mgr->total_connect_count, + p_tc_801_sut_mgr->total_pair_start_count, p_tc_801_sut_mgr->total_pair_success_count, + p_tc_801_sut_mgr->total_pair_fail_count); + } + else + { + data_uart_print("Not running\r\n"); + } +} + +void tc_801_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]) +{ + T_TC_801_SUT_IN_PARAM_DATA *p_tc_801_sut_param_data; + T_TC_PARAM *p_tc_param = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_PARAM)); + p_tc_801_sut_param_data = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_TC_801_SUT_IN_PARAM_DATA)); + + p_tc_801_sut_param_data->id = TC_0801_IOP_PAIR_SC; + p_tc_801_sut_param_data->total_test_count = max_count; + memcpy(p_tc_801_sut_param_data->remote_bd, remote_bd, 6); + + + p_tc_param->p_data = (T_TC_PARAM_DATA *)p_tc_801_sut_param_data; + + os_queue_in(&tc_q, p_tc_param); +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800_sut.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800_sut.h new file mode 100644 index 00000000..2d1665f1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_800_sut.h @@ -0,0 +1,69 @@ + +#ifndef _BLE_AUTO_TEST_TC_800_SUT_H_ +#define _BLE_AUTO_TEST_TC_800_SUT_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + TC_0600_IOP_PAIR_LEGACL +*/ +typedef struct _T_TC_800_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} T_TC_800_SUT_IN_PARAM_DATA; + +void tc_800_sut_iop_android_legacl_pair_start(uint32_t count, uint8_t remote_bd[6]); +void tc_800_sut_iop_android_legacl_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_800_sut_iop_android_legacl_pair_link_connected(uint8_t conn_id); +void tc_800_sut_iop_android_legacl_pair_state_to_start(uint8_t conn_id); +void tc_800_sut_iop_android_legacl_pair_state_to_success(uint8_t conn_id); +void tc_800_sut_iop_android_legacl_pair_state_to_fail(uint8_t conn_id, uint16_t reason); +void tc_800_sut_dump_result(void); +void tc_800_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + + + + +/** + TC_0601_IOP_PAIR_SC +*/ +typedef struct _T_TC_801_SUT_IN_PARAM_DATA +{ + uint16_t id; + uint32_t total_test_count; + uint16_t conn_interval; + uint16_t conn_latency; + uint16_t conn_supervision_timeout; + uint32_t total_pair_start_count; + uint32_t total_pair_success_count; + uint32_t total_pair_fail_count; + uint8_t remote_bd[6]; +} T_TC_801_SUT_IN_PARAM_DATA; +void tc_801_sut_iop_android_sc_pair_start(uint32_t count, uint8_t remote_bd[6]); +void tc_801_sut_iop_android_sc_pair_link_disconnected(uint8_t conn_id, uint16_t reason); +void tc_801_sut_iop_android_sc_pair_link_connected(uint8_t conn_id); +void tc_801_sut_iop_android_sc_pair_state_to_start(uint8_t conn_id); +void tc_801_sut_iop_android_sc_pair_state_to_success(uint8_t conn_id); +void tc_801_sut_iop_android_sc_pair_state_to_fail(uint8_t conn_id); +void tc_801_sut_dump_result(void); +void tc_801_sut_add_case(uint32_t max_count, uint8_t remote_bd[6]); + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_900.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_900.c new file mode 100644 index 00000000..21aca43c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_900.c @@ -0,0 +1,170 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "gap_bond_le.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#include "profile_server.h" +#include "gap_adv.h" + + +#include +#include "privacy_mgnt.h" + + +#include +#include + +#if TC_900_SUPPORT + +T_PRIVACY_INIT_STATE g_privacy_init_state = PRIVACY_INIT_STATE_INIT; +T_PRIVACY_STATE PrivacyState = PRIVACY_STATE_INIT; + + +void privacy_state_callback(T_PRI_CB_TYPE type, uint8_t status) +{ + if (type == PRIVACY_STATE_MSGTYPE) + { + APP_PRINT_INFO2("privacy_state_callback: state (%d->%d)", PrivacyState, status); + PrivacyState = (T_PRIVACY_STATE)status; + if (PrivacyState == PRIVACY_STATE_IDLE) + { + if (app_get_cur_test_case() == TC_0900_PRIVACY_TEST_SLAVE) + { + if (g_privacy_init_state == PRIVACY_INIT_STATE_REL_LIST) + { + le_privacy_set_addr_resolution(true); + g_privacy_init_state = PRIVACY_INIT_STATE_REL_ENABLE; + } + } + } + } + else if (type == PRIVACY_RESOLUTION_STATUS_MSGTYPE) + { + if (status == LE_PRIVACY_RESOLUTION_ENABLED) + { + if (app_get_cur_test_case() == TC_0900_PRIVACY_TEST_SLAVE) + { + if (g_privacy_init_state == PRIVACY_INIT_STATE_REL_ENABLE) + { + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_PUBLIC; + le_adv_get_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, &local_bd_type); + if (local_bd_type == GAP_LOCAL_ADDR_LE_RAP_OR_PUBLIC + || local_bd_type == GAP_LOCAL_ADDR_LE_RAP_OR_RAND) + { + uint8_t i = 0; + uint8_t advDirectType = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t advDirectAddr[GAP_BD_ADDR_LEN] = {0}; + + for (i = 0; i < 4; i++) + { + if ((privacy_table[i].is_used == true) && (privacy_table[i].is_add_to_list == true)) + { + advDirectType = privacy_table[i].remote_bd_type; + memcpy(advDirectAddr, privacy_table[i].addr, 6); + break; + } + } + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(advDirectType), &advDirectType); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(advDirectAddr), advDirectAddr); + } + le_adv_start(); + g_privacy_init_state = PRIVACY_INIT_STATE_REL_IDLE; + } + } + } + } + else + { + } +} + +void tc_900_privacy_slave(void) +{ + uint8_t secReqEnable = true; + uint16_t secReqRequirement = GAP_AUTHEN_BIT_MITM_FLAG; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &secReqRequirement); + //gaps_set_central_address_resolution(true); + privacy_init_resolving_list(privacy_state_callback); + if (privacy_handle_pending_resolving_list() == PRIVACY_STATE_IDLE) + { + } + else + { + g_privacy_init_state = PRIVACY_INIT_STATE_REL_LIST; + } +} + +void tc_901_privacy_master(void) +{ + uint8_t secReqEnable = true; + //uint16_t secReqRequirement = GAP_AUTHEN_BIT_MITM_FLAG; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &secReqEnable); + //le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(uint16_t), &secReqRequirement); + //gaps_set_central_address_resolution(true); + privacy_init_resolving_list(privacy_state_callback); + privacy_handle_pending_resolving_list(); +} + +void tc_901_handle_bond_modify_msg(T_LE_BOND_MODIFY_TYPE type, T_LE_KEY_ENTRY *p_entry) +{ + APP_PRINT_INFO1("tc_901_handle_bond_modify_msg GAP_MSG_LE_BOND_MODIFY_INFO:type=0x%x", + type); + if (type == LE_BOND_CLEAR) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_CLEAR, GAP_IDENT_ADDR_PUBLIC, + NULL); + privacy_handle_pending_resolving_list(); + } + else if (type == LE_BOND_ADD) + { + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + else if (p_entry->flags & LE_KEY_STORE_LOCAL_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + else + { + } + privacy_handle_pending_resolving_list(); + } + else if (type == LE_BOND_DELETE) + { + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + else if (p_entry->flags & LE_KEY_STORE_LOCAL_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, + (T_GAP_IDENT_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + else + { + } + privacy_handle_pending_resolving_list(); + } + else + { + } +} + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_900.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_900.h new file mode 100644 index 00000000..8d8d1d25 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_900.h @@ -0,0 +1,42 @@ + +#ifndef _BLE_AUTO_TEST_TC_900_H_ +#define _BLE_AUTO_TEST_TC_900_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + + +typedef enum +{ + PRIVACY_INIT_STATE_INIT, + PRIVACY_INIT_STATE_REL_LIST, //!< Disconnected. + PRIVACY_INIT_STATE_REL_ENABLE, + PRIVACY_INIT_STATE_REL_IDLE +} T_PRIVACY_INIT_STATE; + + + +extern T_PRIVACY_INIT_STATE g_privacy_init_state; + +/** + TC_0900_PRIVACY_TEST_SLAVE +*/ +void tc_900_privacy_slave(void); + +/** + TC_0901_PRIVACY_TEST_MASTER +*/ +void tc_901_privacy_master(void); +void tc_901_handle_bond_modify_msg(T_LE_BOND_MODIFY_TYPE type, T_LE_KEY_ENTRY *p_entry); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_common.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_common.c new file mode 100644 index 00000000..6f5b6b93 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_common.c @@ -0,0 +1,125 @@ + +#include +#include "app_msg.h" +#include "trace_app.h" +#include "gap_scan.h" +#include "gap.h" +#include "gap_msg.h" +#include "ble_auto_test_application.h" + +#include "user_cmd.h" +#include "user_cmd_parse.h" +#if F_BT_LE_GATT_SERVER_SUPPORT +#include "profile_server.h" +#endif + +#include +#include + + +void *g_test_timer_handle = NULL; +uint32_t g_test_begin_time = 0; +uint32_t g_test_end_time = 0; + + + +uint16_t conn_interval = 0; +uint16_t conn_latency = 0; +uint16_t conn_supervision_timeout = 0; + +BLE_DISCONN_REASON g_ble_disconn_reason; + + +P_FUN_TC_RESULT_CB p_tc_result_cb = NULL; + +void tc_check_remote_disc_reason(uint16_t case_id, uint16_t reason) +{ + if (reason != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + { + data_uart_print("WARNING: tc %d: disc reason 0x%04x\r\n", case_id, reason); + } +} + +void tc_check_local_disc_reason(uint16_t case_id, uint16_t reason) +{ + if (reason != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE)) + { + data_uart_print("WARNING: tc %d: disc reason 0x%04x\r\n", case_id, reason); + } +} + + +void tc_update_disc_reason(uint16_t reason) +{ + switch (reason) + { + case HCI_ERR_CONN_TIMEOUT|HCI_ERR: + g_ble_disconn_reason.reason_08++; + break; + + case HCI_ERR_REMOTE_USER_TERMINATE|HCI_ERR: + g_ble_disconn_reason.reason_13++; + break; + + case HCI_ERR_REMOTE_POWER_OFF|HCI_ERR: + g_ble_disconn_reason.reason_15++; + break; + + case HCI_ERR_LOCAL_HOST_TERMINATE|HCI_ERR: + g_ble_disconn_reason.reason_16++; + break; + + case HCI_ERR_LMP_RESPONSE_TIMEOUT|HCI_ERR: + g_ble_disconn_reason.reason_22++; + break; + + case HCI_ERR_INSTANT_PASSED|HCI_ERR: + g_ble_disconn_reason.reason_28++; + break; + + case HCI_ERR_MIC_FAILURE|HCI_ERR: + g_ble_disconn_reason.reason_3d++; + break; + + case HCI_ERR_FAIL_TO_ESTABLISH_CONN|HCI_ERR: + g_ble_disconn_reason.reason_3e++; + break; + + default: + g_ble_disconn_reason.reason_others++; + break; + } +} + + +void tc_dump_disc_reason(void) +{ + APP_PRINT_ERROR8("disc_reason: err_08 %d, err_13 %d, err_16 %d, err_22 %d, err_28 %d, err_3d %d, err_3e %d, err_others %d", + g_ble_disconn_reason.reason_08, + g_ble_disconn_reason.reason_13, + g_ble_disconn_reason.reason_16, + g_ble_disconn_reason.reason_22, + g_ble_disconn_reason.reason_28, + g_ble_disconn_reason.reason_3d, + g_ble_disconn_reason.reason_3e, + g_ble_disconn_reason.reason_others); + data_uart_print("disc_reason: err_08, err_13, err_15, err_16, err_22, err_28, err_3d, err_3e, err_others\r\n"); + data_uart_print(" %d, %d, %d, %d, %d, %d, %d, %d, %d\r\n", + g_ble_disconn_reason.reason_08, + g_ble_disconn_reason.reason_13, + g_ble_disconn_reason.reason_15, + g_ble_disconn_reason.reason_16, + g_ble_disconn_reason.reason_22, + g_ble_disconn_reason.reason_28, + g_ble_disconn_reason.reason_3d, + g_ble_disconn_reason.reason_3e, + g_ble_disconn_reason.reason_others); +} + + +void tc_reg_result_callback(P_FUN_TC_RESULT_CB tc_result_cb) +{ + p_tc_result_cb = tc_result_cb; +} + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_common.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_common.h new file mode 100644 index 00000000..a44e5a2e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/tc_common.h @@ -0,0 +1,100 @@ + +#ifndef _BLE_AUTO_TEST_TC_COMMON_H_ +#define _BLE_AUTO_TEST_TC_COMMON_H_ +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +//#include "board.h" + +extern uint8_t gSimpleProfileServiceId; + +extern void *g_test_timer_handle; +extern uint32_t g_test_begin_time; +extern uint32_t g_test_end_time; + +extern uint16_t conn_interval; +extern uint16_t conn_latency; +extern uint16_t conn_supervision_timeout; + +typedef void(*P_FUN_TC_RESULT_CB)(uint16_t case_id, uint16_t result, void *p_cb_data); + + +extern P_FUN_TC_RESULT_CB p_tc_result_cb; + +typedef struct _BLE_DISCONN_REASON +{ + uint16_t reason_08; + uint16_t reason_13; + uint16_t reason_15; + uint16_t reason_16; + uint16_t reason_22; + uint16_t reason_28; + uint16_t reason_3d; + uint16_t reason_3e; + uint16_t reason_others; +} BLE_DISCONN_REASON; + +extern BLE_DISCONN_REASON g_ble_disconn_reason; + +#define VENDOR_BASE_ADDRESS 0x40058000 +#define VENDOR_READ(Vendor_offset) \ + ((uint32_t)*((volatile uint32_t*)(VENDOR_BASE_ADDRESS+(Vendor_offset)))) +#define VENDOR_WRITE(Vendor_offset, Value) \ + ((*((volatile uint32_t*)(VENDOR_BASE_ADDRESS + (Vendor_offset)))) = (Value)) + +#define TEST_CPU_CLOCK 20// MHz + +static inline void reset_vendor_counter(void) +{ +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI + /* reser the counter */ + VENDOR_WRITE(0x17C, (1U << 31)); + + /* set the counter */ + VENDOR_WRITE(0x17C, 0); +#else + +#endif +} +static inline uint32_t read_vendor_counter_no_display(void) +{ +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI + return (VENDOR_READ(0x17C) & 0x3FFFFFF); +#else + return 0; +#endif +} +void tc_check_remote_disc_reason(uint16_t case_id, uint16_t reason); +void tc_check_local_disc_reason(uint16_t case_id, uint16_t reason); + + +void tc_reg_result_callback(P_FUN_TC_RESULT_CB tc_result_cb); +void tc_update_disc_reason(uint16_t reason); +void tc_dump_disc_reason(void); + + + +typedef struct _T_TC_PARAM_DATA +{ + uint16_t id; +} T_TC_PARAM_DATA; + + +typedef struct _T_TC_PARAM +{ + struct _T_TC_PARAM *p_next; + T_TC_PARAM_DATA *p_data; +} T_TC_PARAM; + +extern T_OS_QUEUE tc_q; + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_client.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_client.c new file mode 100644 index 00000000..552786ee --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_client.c @@ -0,0 +1,217 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_client.c + * @brief + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +/** Add Includes here **/ +#include "trace_app.h" +#include +#include "profile_client.h" +#include "vendor_pxpext_client.h" + + +typedef struct +{ + bool is_find_pxp_char; + T_GATT_CHARACT_ELEM128 pxp_char; +} T_PXP_LINK; + +/** @brief App link table */ +T_PXP_LINK pxp_table[4]; +static T_CLIENT_ID pxp_client_id = CLIENT_PROFILE_GENERAL_ID; + +static P_FUN_GENERAL_APP_CB pxp_client_cb = NULL; + +const uint8_t GATT_UUID128_PXP_CHAR[16] = +{0xA6, 0xF6, 0xF6, 0x07, 0x4D, 0xC4, 0x9D, 0x98, 0x6D, 0x45, 0x29, 0xBB, 0xD1, 0xFF, 0x00, 0x00}; + +bool vendor_pxpext_start_discovery(uint8_t conn_id) +{ + return client_by_uuid128_char_discovery(conn_id, pxp_client_id, 1, 0xffff, + (uint8_t *)GATT_UUID128_PXP_CHAR); +} + +bool vendor_pxpext_write_value(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + uint16_t handle; + bool hdl_valid = false; + + if (pxp_table[conn_id].pxp_char.value_handle) + { + handle = pxp_table[conn_id].pxp_char.value_handle; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, pxp_client_id, GATT_WRITE_TYPE_REQ, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("vendor_pxpext_write_value: Request fail! Please check!"); + return false; +} + +bool vendor_pxpext_read_value(uint8_t conn_id) +{ + uint16_t handle; + bool hdl_valid = false; + + if (pxp_table[conn_id].pxp_char.value_handle) + { + handle = pxp_table[conn_id].pxp_char.value_handle; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, pxp_client_id, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("vendor_pxpext_read_value: Request fail! Please check!"); + return false; +} + +static void vendor_pxpext_client_discover_state_cb(uint8_t conn_id, + T_DISCOVERY_STATE discovery_state) +{ + T_PXP_CB_DATA cb_data; + cb_data.cb_type = PXP_CLIENT_CB_TYPE_DISC_RESULT; + cb_data.cb_content.disc_result.is_found = false; + + APP_PRINT_INFO1("vendor_pxpext_client_discover_state_cb: discovery_state = %d", discovery_state); + if (discovery_state == DISC_STATE_CHAR_UUID128_DONE) + { + if (pxp_table[conn_id].is_find_pxp_char) + { + cb_data.cb_content.disc_result.is_found = true; + memcpy(&cb_data.cb_content.disc_result.pxp_char, &pxp_table[conn_id].pxp_char, + sizeof(T_GATT_CHARACT_ELEM128)); + } + } + else if (discovery_state == DISC_STATE_FAILED) + { + } + + /* Send discover state to application if needed. */ + if (pxp_client_cb) + { + (*pxp_client_cb)(pxp_client_id, conn_id, &cb_data); + } + return; +} + +static void vendor_pxpext_client_discover_result_cb(uint8_t conn_id, + T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + APP_PRINT_INFO1("vendor_pxpext_client_discover_result_cb: result_type = %d", result_type); + if (result_type == DISC_RESULT_BY_UUID128_CHAR) + { + memcpy(&pxp_table[conn_id].pxp_char, result_data.p_char_uuid128_disc_data, + sizeof(T_GATT_CHARACT_ELEM128)); + pxp_table[conn_id].is_find_pxp_char = true; + } + + return; +} + +static void vendor_pxpext_client_write_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_PXP_CB_DATA cb_data; + cb_data.cb_type = PXP_CLIENT_CB_TYPE_WRITE_RESULT; + + APP_PRINT_INFO1("vendor_pxpext_client_write_cb: result = 0x%x", cause); + + /* If write req success, branch to fetch value and send to application. */ + if (handle == pxp_table[conn_id].pxp_char.value_handle) + { + cb_data.cb_content.write_result.cause = cause; + } + + /* Inform application the write result. */ + if (pxp_client_cb) + { + (*pxp_client_cb)(pxp_client_id, conn_id, &cb_data); + } + + return; +} + +static void vendor_pxpext_client_read_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *pValue) +{ + T_PXP_CB_DATA cb_data; + cb_data.cb_type = PXP_CLIENT_CB_TYPE_READ_RESULT; + + APP_PRINT_INFO3("vendor_pxpext_client_read_cb: result= %d, handle = 0x%4.4x, size = %d", cause, + handle, value_size); + + if (handle == pxp_table[conn_id].pxp_char.value_handle) + { + cb_data.cb_content.read_result.cause = cause; + cb_data.cb_content.read_result.value_size = value_size; + cb_data.cb_content.read_result.pValue = pValue; + /* Inform application the read result. */ + if (pxp_client_cb) + { + (*pxp_client_cb)(pxp_client_id, conn_id, &cb_data); + } + } + + + return; +} + +static void vendor_pxpext_client_disc_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("vendor_pxpext_client_disc_cb."); + memset(&pxp_table[conn_id], 0, sizeof(T_PXP_LINK)); + return; +} + +const T_FUN_CLIENT_CBS PXP_CLIENT_CBS = +{ + vendor_pxpext_client_discover_state_cb, //!< Discovery State callback function pointer + vendor_pxpext_client_discover_result_cb, //!< Discovery result callback function pointer + vendor_pxpext_client_read_cb, //!< Read response callback function pointer + vendor_pxpext_client_write_cb, //!< Write result callback function pointer + NULL, //!< Notify Indicate callback function pointer + vendor_pxpext_client_disc_cb //!< Link disconnection callback function pointer +}; + + +T_CLIENT_ID vendor_pxpext_client_add(P_FUN_GENERAL_APP_CB app_cb) +{ + T_CLIENT_ID client_id; + if (false == client_register_spec_client_cb(&client_id, &PXP_CLIENT_CBS)) + { + pxp_client_id = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("vendor_pxpext_client_add Fail !!!"); + return pxp_client_id; + } + pxp_client_id = client_id; + APP_PRINT_INFO1("vendor_pxpext_client_add: client ID = %d", pxp_client_id); + + /* register callback for profile to inform application that some events happened. */ + pxp_client_cb = app_cb; + + return client_id; +} +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_client.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_client.h new file mode 100644 index 00000000..9f343d0e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_client.h @@ -0,0 +1,74 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_client.h + * @brief + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _VD_PXP_CLIENT_H_ +#define _VD_PXP_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_client.h" + +typedef enum +{ + PXP_CLIENT_CB_TYPE_DISC_RESULT, //!< Discovery procedure state, done or pending. + PXP_CLIENT_CB_TYPE_WRITE_RESULT, //!< Read request's result data, responsed from server. + PXP_CLIENT_CB_TYPE_READ_RESULT, + PXP_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_PXP_CB_TYPE; + +typedef struct +{ + bool is_found; + T_GATT_CHARACT_ELEM128 pxp_char; +} T_PXP_DISC_RESULT; + +typedef struct +{ + uint16_t cause; + uint16_t value_size; + uint8_t *pValue; +} T_PXP_READ_RESULT; + +typedef struct +{ + uint16_t cause; +} T_PXP_WRITE_RESULT; + +typedef union +{ + T_PXP_DISC_RESULT disc_result; + T_PXP_WRITE_RESULT write_result; + T_PXP_READ_RESULT read_result; +} T_PXP_DATA; + +typedef struct +{ + T_PXP_CB_TYPE cb_type; + T_PXP_DATA cb_content; +} T_PXP_CB_DATA; + + +T_CLIENT_ID vendor_pxpext_client_add(P_FUN_GENERAL_APP_CB app_cb); +bool vendor_pxpext_start_discovery(uint8_t conn_id); +bool vendor_pxpext_write_value(uint8_t conn_id, uint16_t length, uint8_t *p_value); +bool vendor_pxpext_read_value(uint8_t conn_id); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _VD_PXP_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_service.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_service.c new file mode 100644 index 00000000..a7777473 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_service.c @@ -0,0 +1,156 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file vendor_tp_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#include "trace_app.h" +#include +#include "vendor_pxpext_service.h" +#include "gap.h" + + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +T_SERVER_ID vendor_pxpext_service_id; +uint8_t test_rw_value[255] = {0}; +uint8_t test_rw_value_len = 0; + +/**< Function pointer used to send event to application from simple profile. Initiated in vendor_tp_service_add. */ +//static P_FUN_SERVER_GENERAL_CB pfn_vendor_pxpext_service_cb = NULL; + +const uint8_t GATT_UUID128_PXPEXT_SERVICE[16] = +{0xA6, 0xF6, 0xF6, 0x07, 0x4D, 0xC4, 0x9D, 0x98, 0x6D, 0x45, 0x29, 0xBB, 0xD0, 0xFF, 0x00, 0x00}; +#define GATT_UUID128_CHAR_PARAM 0xA6, 0xF6, 0xF6, 0x07, 0x4D, 0xC4, 0x9D, 0x98, 0x6D, 0x45, 0x29, 0xBB, 0xD1, 0xFF, 0x00, 0x00, + +static const T_ATTRIB_APPL vendor_pxpext_service_tbl[] = +{ + { + (ATTRIB_FLAG_VOID | ATTRIB_FLAG_LE), + { + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + }, + UUID_128BIT_SIZE, + (void *)GATT_UUID128_PXPEXT_SERVICE, + GATT_PERM_READ + }, + + { + ATTRIB_FLAG_VALUE_INCL, + { + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ | GATT_CHAR_PROP_WRITE, + }, + 1, + NULL, + GATT_PERM_READ + }, + + { + ATTRIB_FLAG_VALUE_APPL | ATTRIB_FLAG_UUID_128BIT, + { + GATT_UUID128_CHAR_PARAM + }, + 0, + NULL, + GATT_PERM_READ | GATT_PERM_WRITE + }, + +}; + + + + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param iAttribIndex Attribute index of getting characteristic data. + * @param iOffset Used for Blob Read. + * @param piLength length of getting characteristic data. + * @param ppValue data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT vendor_pxpext_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t iAttribIndex, uint16_t iOffset, uint16_t *piLength, uint8_t **ppValue) +{ + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + + switch (iAttribIndex) + { + default: + APP_PRINT_INFO1("vendor_tp_service_attr_read_cb, iAttribIndex=%d", iAttribIndex); + *ppValue = test_rw_value; + *piLength = test_rw_value_len; + break; + } + + return (wCause); +} + + +/** + * @brief write characteristic data from service. + * + * @param ServiceID ServiceID to be written. + * @param iAttribIndex Attribute index of characteristic. + * @param wLength length of value to be written. + * @param pValue value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT vendor_pxpext_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t iAttribIndex, T_WRITE_TYPE write_type, uint16_t wLength, uint8_t *pValue, + P_FUN_WRITE_IND_POST_PROC *pWriteIndPostProc) +{ + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + APP_PRINT_INFO3("vendor_pxpext_service_attr_write_cb, iAttribIndex=%d, wLength = %d, pValue:%b", + iAttribIndex, + wLength, + TRACE_BINARY(wLength, pValue)); + + memcpy(test_rw_value, pValue, wLength); + test_rw_value_len = wLength; + return wCause; +} + + +const T_FUN_GATT_SERVICE_CBS vendor_pxpext_service_cbs = +{ + vendor_pxpext_service_attr_read_cb, // Read callback function pointer + vendor_pxpext_service_attr_write_cb, // Write callback function pointer + NULL // CCCD update callback function pointer +}; + + +/** + * @brief add Simple BLE service to application. + * + * @param[in] pFunc pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + * @retval service_id + */ +T_SERVER_ID vendor_pxpext_service_add(void *pFunc) +{ + if (false == server_add_service(&vendor_pxpext_service_id, + (uint8_t *)vendor_pxpext_service_tbl, + sizeof(vendor_pxpext_service_tbl), + vendor_pxpext_service_cbs)) + { + APP_PRINT_ERROR1("vendor_pxpext_service_add: service_id %d", vendor_pxpext_service_id); + vendor_pxpext_service_id = 0xff; + return vendor_pxpext_service_id; + } + +// pfn_vendor_pxpext_service_cb = (P_FUN_SERVER_GENERAL_CB)pFunc; + return vendor_pxpext_service_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_service.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_service.h new file mode 100644 index 00000000..24a515d3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_pxpext_service.h @@ -0,0 +1,32 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author ethan + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _VENDOR_PXPEXT_SERVICE_H_ +#define _VENDOR_PXPEXT_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Add Includes here */ +#include "profile_server.h" + + + +T_SERVER_ID vendor_pxpext_service_add(void *pFunc); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_client.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_client.c new file mode 100644 index 00000000..39339050 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_client.c @@ -0,0 +1,291 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_client.c + * @brief + * @details + * @author jane + * @date 2016-02-18 + * @version v0.1 + ****************************************************************************** + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +/** Add Includes here **/ +#include "trace_app.h" +#include +#include "vendor_tp_client.h" +#include "vendor_tp_config.h" + +typedef struct +{ + bool is_find_tp_char; + T_GATT_CHARACT_ELEM16 tp_char; + uint16_t cccd_handle; +} T_TP_LINK; + +/** @brief App link table */ +T_TP_LINK tp_table[4]; +static T_CLIENT_ID tp_client_id = CLIENT_PROFILE_GENERAL_ID; + +static P_FUN_GENERAL_APP_CB tp_client_cb = NULL; + +bool tp_client_start_discovery(uint8_t conn_id) +{ + return client_by_uuid_char_discovery(conn_id, tp_client_id, 1, 0xffff, + GATT_UUID_VENDOR_TP_NOTIFY_INDICATE); +} + +bool tp_client_write_cccd(uint8_t conn_id, uint16_t cccd_bits) +{ + uint16_t handle; + uint16_t length; + uint8_t *p_data; + bool hdl_valid = false; + + APP_PRINT_INFO1("tp_client_write_cccd: cccd_bits = 0x%x", cccd_bits); + + if (tp_table[conn_id].cccd_handle) + { + handle = tp_table[conn_id].cccd_handle; + length = sizeof(uint16_t); + p_data = (uint8_t *)&cccd_bits; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, tp_client_id, GATT_WRITE_TYPE_REQ, handle, + length, p_data) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("tp_client_write_cccd: Request fail! Please check!"); + return false; +} + +bool tp_client_write_value(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + uint16_t handle; + bool hdl_valid = false; + + if (tp_table[conn_id].tp_char.value_handle) + { + handle = tp_table[conn_id].tp_char.value_handle; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, tp_client_id, GATT_WRITE_TYPE_REQ, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("tp_client_write_value: Request fail! Please check!"); + return false; +} + +bool tp_client_write_command(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + uint16_t handle; + bool hdl_valid = false; + + if (tp_table[conn_id].tp_char.value_handle) + { + handle = tp_table[conn_id].tp_char.value_handle; + hdl_valid = true; + } + + if (hdl_valid) + { + if (client_attr_write(conn_id, tp_client_id, GATT_WRITE_TYPE_CMD, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("tp_client_write_command: Request fail! Please check!"); + return false; +} + +bool tp_client_read_prefer_param(uint8_t conn_id) +{ + if (client_attr_read_using_uuid(conn_id, tp_client_id, 0x01, 0xffff, + GATT_UUID_VENDOR_TP_PREFER_PARAM, NULL) == GAP_CAUSE_SUCCESS) + { + return true; + } + + APP_PRINT_WARN0("tp_client_read_prefer_param: Request fail! Please check!"); + return false; +} + +static void tp_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + T_TP_CB_DATA cb_data; + cb_data.cb_type = TP_CLIENT_CB_TYPE_DISC_RESULT; + cb_data.cb_content.disc_result.is_found = false; + + APP_PRINT_INFO1("tp_client_discover_state_cb: discovery_state = %d", discovery_state); + if (discovery_state == DISC_STATE_CHAR_UUID16_DONE) + { + if (tp_table[conn_id].is_find_tp_char) + { + cb_data.cb_content.disc_result.is_found = true; + memcpy(&cb_data.cb_content.disc_result.char_tp, &tp_table[conn_id].tp_char, + sizeof(T_GATT_CHARACT_ELEM16)); + } + } + else if (discovery_state == DISC_STATE_FAILED) + { + } + + /* Send discover state to application if needed. */ + if (tp_client_cb) + { + (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + return; +} + +static void tp_client_discover_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + APP_PRINT_INFO1("tp_client_discover_result_cb: result_type = %d", result_type); + if (result_type == DISC_RESULT_BY_UUID16_CHAR) + { + tp_table[conn_id].tp_char.decl_handle = result_data.p_char_uuid16_disc_data->decl_handle; + tp_table[conn_id].tp_char.properties = result_data.p_char_uuid16_disc_data->properties; + tp_table[conn_id].tp_char.value_handle = result_data.p_char_uuid16_disc_data->value_handle; + tp_table[conn_id].tp_char.uuid16 = result_data.p_char_uuid16_disc_data->uuid16; + tp_table[conn_id].is_find_tp_char = true; + tp_table[conn_id].cccd_handle = tp_table[conn_id].tp_char.value_handle + 1; + } + + return; +} + +static void tp_client_write_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_TP_CB_DATA cb_data; + cb_data.cb_type = TP_CLIENT_CB_TYPE_WRITE_RESULT; + cb_data.cb_content.write_result.credits = credits; + cb_data.cb_content.write_result.write_type = type; + + APP_PRINT_INFO1("tp_client_write_cb: result = 0x%x", cause); + + /* If write req success, branch to fetch value and send to application. */ + if (handle == tp_table[conn_id].tp_char.value_handle) + { + cb_data.cb_content.write_result.type = TP_WRITE_CHAR_VALUE; + cb_data.cb_content.write_result.cause = cause; + } + else if (handle == tp_table[conn_id].cccd_handle) + { + cb_data.cb_content.write_result.type = TP_WRITE_CCCD; + cb_data.cb_content.write_result.cause = cause; + } + + /* Inform application the write result. */ + if (tp_client_cb) + { + (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + + return; +} + +static T_APP_RESULT tp_client_notify_ind_cb(uint8_t conn_id, bool notify, uint16_t handle, + uint16_t value_size, uint8_t *pValue) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + T_TP_CB_DATA cb_data; + + cb_data.cb_type = TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + + if (handle == tp_table[conn_id].tp_char.value_handle) + { + cb_data.cb_content.notif_ind_data.is_notif = notify; + cb_data.cb_content.notif_ind_data.value_size = value_size; + cb_data.cb_content.notif_ind_data.pValue = pValue; + } + else + { + return app_result; + } + /* Inform application the notif/ind result. */ + if (tp_client_cb) + { + app_result = (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + + return app_result; +} + +static void tp_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_TP_CB_DATA cb_data; + cb_data.cb_type = TP_CLIENT_CB_TYPE_READ_RESULT; + + PROFILE_PRINT_INFO2("tp_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + cb_data.cb_content.read_result.type = TP_READ_PREFER_PARAM; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.value_size = value_size; + cb_data.cb_content.read_result.p_value = p_value; + } + + if (tp_client_cb) + { + (*tp_client_cb)(tp_client_id, conn_id, &cb_data); + } + return; +} + +static void tp_client_disc_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("tp_client_disc_cb."); + memset(&tp_table[conn_id], 0, sizeof(T_TP_LINK)); + return; +} + +const T_FUN_CLIENT_CBS TP_CLIENT_CBS = +{ + tp_client_discover_state_cb, //!< Discovery State callback function pointer + tp_client_discover_result_cb, //!< Discovery result callback function pointer + tp_client_read_result_cb, //!< Read response callback function pointer + tp_client_write_cb, //!< Write result callback function pointer + tp_client_notify_ind_cb, //!< Notify Indicate callback function pointer + tp_client_disc_cb //!< Link disconnection callback function pointer +}; + + +T_CLIENT_ID tp_client_add(P_FUN_GENERAL_APP_CB app_cb) +{ + T_CLIENT_ID client_id; + if (false == client_register_spec_client_cb(&client_id, &TP_CLIENT_CBS)) + { + tp_client_id = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("tp_client_add_client Fail !!!"); + return tp_client_id; + } + tp_client_id = client_id; + APP_PRINT_INFO1("tp_client_add_client: client ID = %d", tp_client_id); + + /* register callback for profile to inform application that some events happened. */ + tp_client_cb = app_cb; + + return client_id; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_client.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_client.h new file mode 100644 index 00000000..eefa0116 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_client.h @@ -0,0 +1,99 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_client.h + * @brief + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _VD_TP_CLIENT_H_ +#define _VD_TP_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_client.h" + +typedef enum +{ + TP_CLIENT_CB_TYPE_DISC_RESULT, //!< Discovery procedure state, done or pending. + TP_CLIENT_CB_TYPE_WRITE_RESULT, //!< Read request's result data, responsed from server. + TP_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + TP_CLIENT_CB_TYPE_NOTIF_IND_RESULT, + TP_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_TP_CB_TYPE; + +typedef enum +{ + TP_WRITE_CCCD, + TP_WRITE_CHAR_VALUE, +} T_TP_WRITE_TYPE; + +typedef struct +{ + bool is_found; + T_GATT_CHARACT_ELEM16 char_tp; +} T_TP_DISC_RESULT; + +typedef struct +{ + uint8_t is_notif; + uint16_t value_size; + uint8_t *pValue; +} T_TP_NOTIF_IND_DATA; + +typedef struct +{ + T_TP_WRITE_TYPE type; + T_GATT_WRITE_TYPE write_type; + uint16_t cause; + uint8_t credits; +} T_TP_WRITE_RESULT; + +typedef enum +{ + TP_READ_PREFER_PARAM, +} T_TP_READ_TYPE; + +typedef struct +{ + T_TP_READ_TYPE type; + uint16_t cause; + uint16_t value_size; + uint8_t *p_value; +} T_TP_READ_RESULT; + +typedef union +{ + T_TP_DISC_RESULT disc_result; + T_TP_NOTIF_IND_DATA notif_ind_data; + T_TP_WRITE_RESULT write_result; + T_TP_READ_RESULT read_result; +} T_TP_DATA; + +typedef struct +{ + T_TP_CB_TYPE cb_type; + T_TP_DATA cb_content; +} T_TP_CB_DATA; + +T_CLIENT_ID tp_client_add(P_FUN_GENERAL_APP_CB app_cb); +bool tp_client_start_discovery(uint8_t conn_id); +bool tp_client_write_cccd(uint8_t conn_id, uint16_t cccd_bits); +bool tp_client_write_value(uint8_t conn_id, uint16_t length, uint8_t *p_value); +bool tp_client_write_command(uint8_t conn_id, uint16_t length, uint8_t *p_value); +bool tp_client_read_prefer_param(uint8_t conn_id); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _VD_TP_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_config.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_config.h new file mode 100644 index 00000000..84b06224 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_config.h @@ -0,0 +1,53 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file simple_ble_config.h + * @brief This file includes common constants or types for Simple BLE service/client. + * And some optional feature may be defined in this file. + * @details + * @author Ethan + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion **/ +#ifndef _VENDOR_TP_CONFIG_H_ +#define _VENDOR_TP_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint8_t data_check; + uint8_t initial_value; + uint8_t mode; + /** 0 : 1M + w/o data length extension + 1 : 1M + w data length extension + 2 : 2M + w/o data length extension + 3 : 2M + w data length extension + 4 : Coded(s=2) + w/o data length extension + 5 : Coded(s=2) + w data length extension + 6 : Coded(s=8) + w/o data length extension + 7 : Coded(s=8) + w data length extension + 8 : 1M + w/o data length extension(BT4.0) + */ + uint16_t con_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + uint16_t length; + uint32_t count; +} TTP_PERFER_PARAM; + +#define GATT_UUID_VENDOR_TP_SERVICE 0xA00D +#define GATT_UUID_VENDOR_TP_NOTIFY_INDICATE 0xB001 +#define GATT_UUID_VENDOR_TP_PREFER_PARAM 0xB002 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_service.c b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_service.c new file mode 100644 index 00000000..a3b441d0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_service.c @@ -0,0 +1,343 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file vendor_tp_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#include "trace_app.h" +#include +#include "vendor_tp_service.h" +#include "gap.h" + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +T_SERVER_ID vendor_tp_service_id; + + +/**< Function pointer used to send event to application from simple profile. Initiated in vendor_tp_service_add. */ +static P_FUN_SERVER_GENERAL_CB pfn_vendor_tp_service_cb = NULL; +TTP_PERFER_PARAM vendor_tp_param; + + +/**< @brief profile/service definition. */ +const T_ATTRIB_APPL vendor_tp_service_tbl[] = +{ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_VENDOR_TP_SERVICE), /* service UUID */ + HI_WORD(GATT_UUID_VENDOR_TP_SERVICE) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_NOTIFY | GATT_CHAR_PROP_INDICATE | GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_VENDOR_TP_NOTIFY_INDICATE), + HI_WORD(GATT_UUID_VENDOR_TP_NOTIFY_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /* characteristic properties */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VOID, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_VENDOR_TP_PREFER_PARAM), + HI_WORD(GATT_UUID_VENDOR_TP_PREFER_PARAM) + }, + sizeof(vendor_tp_param), /* bValueLen */ + (void *) &vendor_tp_param, + GATT_PERM_READ /* permissions */ + }, +}; + +void vendor_tp_service_config_param(TTP_PERFER_PARAM param) +{ + memcpy(&vendor_tp_param, ¶m, sizeof(TTP_PERFER_PARAM)); +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param iAttribIndex Attribute index of getting characteristic data. + * @param iOffset Used for Blob Read. + * @param piLength length of getting characteristic data. + * @param ppValue data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT vendor_tp_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t iAttribIndex, uint16_t iOffset, uint16_t *piLength, uint8_t **ppValue) +{ + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + + switch (iAttribIndex) + { + default: + APP_PRINT_ERROR1("vendor_tp_service_attr_read_cb, Attr not found, index=%d", iAttribIndex); + wCause = APP_RESULT_ATTR_NOT_FOUND; + break; + + + } + + return (wCause); +} + + +/** + * @brief write characteristic data from service. + * + * @param ServiceID ServiceID to be written. + * @param iAttribIndex Attribute index of characteristic. + * @param wLength length of value to be written. + * @param pValue value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT vendor_tp_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t iAttribIndex, T_WRITE_TYPE write_type, uint16_t wLength, uint8_t *pValue, + P_FUN_WRITE_IND_POST_PROC *pWriteIndPostProc) +{ + TTP_CALLBACK_DATA callback_data; + T_APP_RESULT wCause = APP_RESULT_SUCCESS; + if (VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX == iAttribIndex) + { + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.write_type = write_type; + if (write_type == WRITE_REQUEST) + { + /* Notify Application. */ + uint8_t *p_param = pValue; + callback_data.msg_data.write.opcode = (VENDOR_TP_OP) * p_param; + p_param += 1; + + LE_ARRAY_TO_UINT32(callback_data.msg_data.write.u.notify_param.count, p_param); + p_param += 4; + + LE_ARRAY_TO_UINT16(callback_data.msg_data.write.u.notify_param.length, p_param); + + if (pfn_vendor_tp_service_cb) + { + pfn_vendor_tp_service_cb(service_id, (void *)&callback_data); + } + } + else + { + callback_data.msg_data.write.u.write_data.length = wLength; + callback_data.msg_data.write.u.write_data.p_value = pValue; + if (pfn_vendor_tp_service_cb) + { + pfn_vendor_tp_service_cb(service_id, (void *)&callback_data); + } + } + } + else + { + APP_PRINT_ERROR2("--> vendor_tp_service_attr_write_cb Error iAttribIndex = 0x%x wLength=%d", + iAttribIndex, + wLength); + wCause = APP_RESULT_ATTR_NOT_FOUND; + } + return wCause; +} + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] service_id service ID of service. + * @param[in] value characteristic value to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool vendor_tp_service_v1_notification(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + uint8_t *p_data = (uint8_t *)p_value; + uint16_t dataLen = length; + + APP_PRINT_INFO0("<-- vendor_tp_service_v1_notification"); + // send notification to client + return server_send_data(conn_id, service_id, VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX, p_data, + dataLen, GATT_PDU_TYPE_NOTIFICATION); +} + +bool vendor_tp_service_v1_indication(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + uint8_t *p_data = (uint8_t *)p_value; + uint16_t dataLen = length; + + APP_PRINT_INFO0("<-- vendor_tp_service_v1_indication"); + // send notification to client + return server_send_data(conn_id, service_id, VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX, p_data, + dataLen, GATT_PDU_TYPE_INDICATION); +} + +/** + * @brief update CCCD bits from stack. + * + * @param service_id Service ID. + * @param Index Attribute index of characteristic data. + * @param wCCCBits CCCD bits from stack. + * @return None +*/ +void vendor_tp_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID serviceId, uint16_t Index, + uint16_t wCCCBits) +{ + TTP_CALLBACK_DATA callback_data; + + callback_data.conn_id = conn_id; + APP_PRINT_INFO2("vendor_tp_service_cccd_update_cb Index = %d wCCCDBits %x", Index, + wCCCBits); + switch (Index) + { + case VENDOR_TP_SERVICE_CHAR_TP_NOTIFY_INDICATE_CCCD_INDEX: + { + bool bHandle = true; + if (wCCCBits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + else + { + // Disable Notification + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + + if (wCCCBits & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_INDICATION_ENABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + else + { + // Disable Indication + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + callback_data.msg_data.notification_indification_index = VENDOR_TP_SERVICE_V1_INDICATION_DISABLE; + + /* Notify Application. */ + if (pfn_vendor_tp_service_cb && (bHandle == true)) + { + pfn_vendor_tp_service_cb(serviceId, (void *)&callback_data); + } + } + + } + break; + + default: + break; + } +} + + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS vendor_tp_service_cbs = +{ + vendor_tp_service_attr_read_cb, // Read callback function pointer + vendor_tp_service_attr_write_cb, // Write callback function pointer + vendor_tp_service_cccd_update_cb // CCCD update callback function pointer +}; + + + +/** + * @brief add Simple BLE service to application. + * + * @param[in] pFunc pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + * @retval service_id + */ +T_SERVER_ID vendor_tp_service_add(void *pFunc) +{ + if (false == server_add_service(&vendor_tp_service_id, + (uint8_t *)vendor_tp_service_tbl, + sizeof(vendor_tp_service_tbl), + vendor_tp_service_cbs)) + { + APP_PRINT_ERROR1("vendor_tp_service_add: service_id %d", vendor_tp_service_id); + vendor_tp_service_id = 0xff; + return vendor_tp_service_id; + } + + pfn_vendor_tp_service_cb = (P_FUN_SERVER_GENERAL_CB)pFunc; + return vendor_tp_service_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_service.h b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_service.h new file mode 100644 index 00000000..e8cf08aa --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_auto_test/vendor_tp_service.h @@ -0,0 +1,174 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file vendor_tp_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author ethan + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _VENDOR_TP_SERVICE_H_ +#define _VENDOR_TP_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include "profile_server.h" +#include "vendor_tp_config.h" + +/** @addtogroup SIMP SIMP + * @brief Simple BLE Profile + * @{ + */ + +/** @defgroup SIMP_Service SIMP Service + * @brief Simple BLE Service + * @{ + */ + +/** @defgroup SIMP_Service_Exported_Constants SIMP Service Exported Constants + * @brief macros that other .c files may use all defined here + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +#define SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL 0x01 +#define SIMPLE_BLE_SERVICE_PARAM_CTL_PNT_PROG_CLR 0x02 +/** @} */ + +///@cond +/** @brief Index of each characteristic in Demo Profile service database. */ +#define VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX 0x02 +#define VENDOR_TP_SERVICE_CHAR_TP_NOTIFY_INDICATE_CCCD_INDEX (VENDOR_TP_SERVICE_CHAR_TP_WRITE_INDEX + 1) +///@endcond + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ + +#define SIMP_WRITE_V1 1 + + +/** @} */ + +/** @defgroup SIMP_Service_Notify_Indicate_Info SIMP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define VENDOR_TP_SERVICE_V1_NOTIFICATION_ENABLE 1 +#define VENDOR_TP_SERVICE_V1_NOTIFICATION_DISABLE 2 +#define VENDOR_TP_SERVICE_V1_INDICATION_ENABLE 3 +#define VENDOR_TP_SERVICE_V1_INDICATION_DISABLE 4 + + + +/** @} */ + +/** @} End of SIMP_Service_Upstream_Message */ + + + +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief types that other.c files may use all defined here + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ + +typedef enum +{ + VENDOR_TP_OP_CONFIG_NOTIFY_PARAM1 = 0x01, + VENDOR_TP_OP_CONFIG_NOTIFY_PARAM2 = 0x02, + VENDOR_TP_OP_NOTIFY_START_TEST = 0x03, + +} VENDOR_TP_OP; + +typedef struct _TVENDOR_TP_CONFIG_NOTIFY_PARAM +{ + uint32_t count; + uint16_t length; +} TVENDOR_TP_CONFIG_NOTIFY_PARAM; + +typedef struct +{ + uint16_t length; + uint8_t *p_value; +} TVENDOR_TP_WRITE_DATA; + +typedef struct _TTP_WRITE_MSG +{ + T_WRITE_TYPE write_type; + VENDOR_TP_OP opcode; //!< ref: @ref SIMP_Control_Point_OpCodes, @ref SIMP_Service_Write_Info + union + { + TVENDOR_TP_CONFIG_NOTIFY_PARAM notify_param; + TVENDOR_TP_WRITE_DATA write_data; + uint8_t mode; + } u; +} TTP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union _TTP_UPSTREAM_MSG_DATA +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + TTP_WRITE_MSG write; +} TTP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct _TTP_CALLBACK_DATA +{ + T_SERVICE_CALLBACK_TYPE msg_type; + uint8_t conn_id; + TTP_UPSTREAM_MSG_DATA msg_data; +} TTP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ + +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief functions that other .c files may use all defined here + * @{ + */ +T_SERVER_ID vendor_tp_service_add(void *pFunc); +void vendor_tp_service_config_param(TTP_PERFER_PARAM param); +bool vendor_tp_service_v1_notification(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length); +bool vendor_tp_service_v1_indication(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length); + + +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +/** @} End of SIMP */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_flags.h b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_flags.h new file mode 100644 index 00000000..47e26185 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_flags.h @@ -0,0 +1,37 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include +#include + +/** @defgroup CENTRAL_CLIENT_Config Central Client App Configuration + * @brief This file is used to config app functions. + * @{ + */ +/*============================================================================* + * Constants + *============================================================================*/ + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 3 + +/** @brief Config the discovery table number of gcs_client */ +#define APP_MAX_DISCOV_TABLE_NUM 40 + +/** @} */ /* End of group CENTRAL_CLIENT_Config */ + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_task.c b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_task.c new file mode 100644 index 00000000..52b41ef8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_task.c @@ -0,0 +1,109 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @defgroup CENTRAL_CLIENT_APP_TASK Central Client App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 6 //!< Task stack size +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 //!< GAP message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +void app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + data_uart_init(evt_queue_handle, io_queue_handle); + user_cmd_init(&user_cmd_if, "central_client"); + + driver_init(); + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + +/** @} */ /* End of group CENTRAL_CLIENT_APP_TASK */ + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_task.h b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_task.h new file mode 100644 index 00000000..8dfcd2ac --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/app_task.h @@ -0,0 +1,27 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +extern void driver_init(void); + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/ble_app_main.c b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/ble_app_main.c new file mode 100644 index 00000000..34845b0c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/ble_app_main.c @@ -0,0 +1,189 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE central client project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace_uart.h" + +/** @defgroup CENTRAL_CLIENT_DEMO_MAIN Central Client Main + * @brief Main file to initialize hardware and BT stack and start task scheduling + * @{ + */ + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default scan interval (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_INTERVAL 0x10 +/** @brief Default scan window (units of 0.625ms, 0x10=2.5ms) */ +#define DEFAULT_SCAN_WINDOW 0x10 + + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); +} + +/** + * @brief Initialize central and gap bond manager related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BLE_CENTRAL_CLIENT"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + + /* Scan parameters */ + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); +} + +/** + * @brief Add GATT clients and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + client_init(1); + gcs_client_id = gcs_add_client(gcs_client_callback, APP_MAX_LINKS, APP_MAX_DISCOV_TABLE_NUM); +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +void board_init(void) +{ + +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Central Client APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int ble_app_main(void) +{ + bt_trace_init(); + bt_stack_config_init(); + bte_init(); + board_init(); + le_gap_init(APP_MAX_LINKS); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); + task_init(); + + return 0; +} +/** @} */ /* End of group CENTRAL_CLIENT_DEMO_MAIN */ + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/central_client_app.c b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/central_client_app.c new file mode 100644 index 00000000..80a163b8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/central_client_app.c @@ -0,0 +1,878 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file central_client_app.c + * @brief This file handles BLE central application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @defgroup CENTRAL_CLIENT_APP Central Client Application + * @brief This file handles BLE central client application routines. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup CENTRAL_CLIIENT_CALLBACK + * @{ + */ +T_CLIENT_ID gcs_client_id; /**< General Common Services client client id*/ +/** @} */ /* End of group CENTRAL_CLIIENT_CALLBACK */ + +/** @defgroup CENTRAL_CLIENT_GAP_MSG GAP Message Handler + * @brief Handle GAP Message + * @{ + */ +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + uint8_t rx_char; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + /* We handle user command informations from Data UART in this branch. */ + rx_char = (uint8_t)io_msg.subtype; + user_cmd_collect(&user_cmd_if, &rx_char, sizeof(rx_char), user_cmd_table); + break; + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO3("app_handle_dev_state_evt: init state %d, scan state %d, cause 0x%x", + new_state.gap_init_state, + new_state.gap_scan_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + uint8_t bt_addr[6]; + APP_PRINT_INFO0("GAP stack ready"); + /*stack ready*/ + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], + bt_addr[4], + bt_addr[3], + bt_addr[2], + bt_addr[1], + bt_addr[0]); + } + } + + if (gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + data_uart_print("GAP scan start\r\n"); + } + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] disc_cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, app_link_table[conn_id].conn_state, new_state, disc_cause); + + app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + + data_uart_print("Disconnect conn_id %d\r\n", conn_id); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + le_get_conn_addr(conn_id, app_link_table[conn_id].bd_addr, + &app_link_table[conn_id].bd_type); + data_uart_print("Connected success conn_id %d\r\n", conn_id); + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_print("Pair success\r\n"); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + + } + else + { + data_uart_print("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + APP_PRINT_INFO4("app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + APP_PRINT_ERROR2("app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + } + break; + + default: + break; + } +} + +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + data_uart_print("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d", conn_id); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} +/** @} */ /* End of group CENTRAL_CLIENT_GAP_MSG */ + +/** @defgroup CENTRAL_CLIENT_GAP_CALLBACK GAP Callback Event Handler + * @brief Handle GAP callback event + * @{ + */ +/** + * @brief Used to parse advertising data and scan response data + * @param[in] scan_info point to scan information data. + * @retval void + */ +void app_parse_scan_info(T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + APP_PRINT_TRACE2("app_parse_scan_info: AD Structure Info: AD type 0x%x, AD Data Length %d", type, + length - 1); + + switch (type) + { + case GAP_ADTYPE_FLAGS: + { + /* (flags & 0x01) -- LE Limited Discoverable Mode */ + /* (flags & 0x02) -- LE General Discoverable Mode */ + /* (flags & 0x04) -- BR/EDR Not Supported */ + /* (flags & 0x08) -- Simultaneous LE and BR/EDR to Same Device Capable (Controller) */ + /* (flags & 0x10) -- Simultaneous LE and BR/EDR to Same Device Capable (Host) */ + uint8_t flags = scan_info->data[pos + 1]; + APP_PRINT_INFO1("GAP_ADTYPE_FLAGS: 0x%x", flags); + } + break; + + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO1("GAP_ADTYPE_16BIT_XXX: 0x%x", *p_uuid++); + i -= 2; + } + } + break; + + case GAP_ADTYPE_32BIT_MORE: + case GAP_ADTYPE_32BIT_COMPLETE: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 4) + { + APP_PRINT_INFO1("GAP_ADTYPE_32BIT_XXX: 0x%x", *p_uuid++); + i -= 4; + } + } + break; + + case GAP_ADTYPE_128BIT_MORE: + case GAP_ADTYPE_128BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_128BIT: + { + uint32_t *p_uuid = (uint32_t *)(buffer); + APP_PRINT_INFO4("GAP_ADTYPE_128BIT_XXX: 0x%8.8x%8.8x%8.8x%8.8x", + p_uuid[3], p_uuid[2], p_uuid[1], p_uuid[0]); + } + break; + + case GAP_ADTYPE_LOCAL_NAME_SHORT: + case GAP_ADTYPE_LOCAL_NAME_COMPLETE: + { + buffer[length - 1] = '\0'; + APP_PRINT_INFO1("GAP_ADTYPE_LOCAL_NAME_XXX: %s", TRACE_STRING(buffer)); + } + break; + + case GAP_ADTYPE_POWER_LEVEL: + { + APP_PRINT_INFO1("GAP_ADTYPE_POWER_LEVEL: 0x%x", scan_info->data[pos + 1]); + } + break; + + case GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: + { + uint16_t *p_min = (uint16_t *)(buffer); + uint16_t *p_max = p_min + 1; + APP_PRINT_INFO2("GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE: 0x%x - 0x%x", *p_min, + *p_max); + } + break; + + case GAP_ADTYPE_SERVICE_DATA: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t data_len = length - 3; + + APP_PRINT_INFO3("GAP_ADTYPE_SERVICE_DATA: UUID 0x%x, len %d, data %b", *p_uuid, + data_len, TRACE_BINARY(data_len, &buffer[2])); + } + break; + case GAP_ADTYPE_APPEARANCE: + { + uint16_t *p_appearance = (uint16_t *)(buffer); + APP_PRINT_INFO1("GAP_ADTYPE_APPEARANCE: %d", *p_appearance); + } + break; + + case GAP_ADTYPE_MANUFACTURER_SPECIFIC: + { + uint8_t data_len = length - 3; + uint16_t *p_company_id = (uint16_t *)(buffer); + APP_PRINT_INFO3("GAP_ADTYPE_MANUFACTURER_SPECIFIC: company_id 0x%x, len %d, data %b", + *p_company_id, data_len, TRACE_BINARY(data_len, &buffer[2])); + } + break; + + default: + { + uint8_t i = 0; + + for (i = 0; i < (length - 1); i++) + { + APP_PRINT_INFO1(" AD Data: Unhandled Data = 0x%x", scan_info->data[pos + i]); + } + } + break; + } + } + + pos += length; + } +} +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + /* If you want to parse the scan info, please reference function app_parse_scan_info. */ + app_parse_scan_info(p_data->p_le_scan_info); + break; + + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + result = APP_RESULT_ACCEPT; + break; + + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} +/** @} */ /* End of group CENTRAL_CLIENT_GAP_CALLBACK */ + +/** @defgroup GCS_CLIIENT_CALLBACK GCS Client Callback Event Handler + * @brief Handle profile client callback event + * @{ + */ +void gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + APP_PRINT_INFO4("ALL SRV UUID16[%d]: service range: 0x%x-0x%x, uuid16 0x%x", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + APP_PRINT_INFO4("ALL SRV UUID128[%d]: service range: 0x%x-0x%x, service=<%b>", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + TRACE_BINARY(16, p_result_table->result_data.srv_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + APP_PRINT_INFO3("SRV DATA[%d]: service range: 0x%x-0x%x", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID16[%d]: decl_handle 0x%x, properties 0x%x, value_handle 0x%x, uuid16 0x%x", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("CHAR UUID128[%d]: decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + APP_PRINT_INFO5("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + APP_PRINT_INFO5("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%x, prop=0x%x, value hndl=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + TRACE_BINARY(16, p_result_table->result_data.char_uuid128_disc_data.uuid128)); + APP_PRINT_INFO5("properties:indicate %d, read %d, write cmd %d, write %d, notify %d", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + APP_PRINT_INFO2("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + APP_PRINT_INFO3("DESC UUID16[%d]: Descriptors handle=0x%x, uuid16=<0x%x>", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + APP_PRINT_INFO3("DESC UUID128[%d]: Descriptors handle=0x%x, uuid128=<%b>", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + TRACE_BINARY(16, p_result_table->result_data.char_desc_uuid128_disc_data.uuid128)); + break; + + default: + APP_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + default: + APP_PRINT_ERROR2("Invalid disc type: conn_id %d, discov_type %d", + conn_id, discov_result.discov_type); + break; + } +} +/** + * @brief Callback will be called when data sent from gcs client. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + APP_PRINT_INFO3("READ RESULT: cause 0x%x, handle 0x%x, value_len %d", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + if (p_gcs_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + } + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + APP_PRINT_INFO3("WRITE RESULT: cause 0x%x ,handle 0x%x, type %d", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + APP_PRINT_INFO2("INDICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + } + else + { + APP_PRINT_INFO2("NOTIFICATION: handle 0x%x, value_size %d", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + } + break; + default: + break; + } + } + + return result; +} + +/** @} */ /* End of group GCS_CLIIENT_CALLBACK */ +/** @} */ /* End of group CENTRAL_CLIENT_APP */ + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/central_client_app.h b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/central_client_app.h new file mode 100644 index 00000000..d2308e50 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/central_client_app.h @@ -0,0 +1,67 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file central_client_app.h + * @brief This file handles BLE central client application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _CENTRAL_CLIENT_APP_H_ +#define _CENTRAL_CLIENT_APP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_CLIENT_ID gcs_client_id; /**< General Common Services client client id*/ + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/link_mgr.c b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/link_mgr.c new file mode 100644 index 00000000..1b08c42f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/link_mgr.c @@ -0,0 +1,28 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include + +/*============================================================================* + * Variables + *============================================================================*/ +/** @addtogroup CENTRAL_CLIENT_GAP_MSG + * @{ + */ +T_APP_LINK app_link_table[APP_MAX_LINKS]; + +/** @} */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/link_mgr.h b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/link_mgr.h new file mode 100644 index 00000000..fd7f2794 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/link_mgr.h @@ -0,0 +1,52 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _LINK_MANAGER_H_ +#define _LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include + +/*============================================================================* + * Constants + *============================================================================*/ +/** @addtogroup CENTRAL_CLIENT_GAP_MSG + * @{ + */ +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ + T_GAP_REMOTE_ADDR_TYPE bd_type; /**< remote BD type*/ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ +} T_APP_LINK; +/** @} */ /* End of group CENTRAL_CLIENT_GAP_MSG */ +/** @addtogroup CENTRAL_CLIENT_SCAN_MGR + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK app_link_table[APP_MAX_LINKS]; + +/*============================================================================* + * Functions + *============================================================================*/ + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/user_cmd.c b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/user_cmd.c new file mode 100644 index 00000000..f67b3dd7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/user_cmd.c @@ -0,0 +1,937 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file user_cmd.c + * @brief User defined test commands. + * @details User command interfaces. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include + +/** @defgroup CENTRAL_CLIENT_CMD Central Client User Command + * @brief This file handles Central Client User Command. + * @{ + */ +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief User command interface data, used to parse the commands from Data UART. */ +T_USER_CMD_IF user_cmd_if; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Show all devices connecting status + * + * Command table define + * \code{.c} + { + "showcon", + "showcon\n\r", + "Show all devices connecting status\n\r", + cmd_showcon + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_showcon(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id; + T_GAP_CONN_INFO conn_info; + for (conn_id = 0; conn_id < APP_MAX_LINKS; conn_id++) + { + if (le_get_conn_info(conn_id, &conn_info)) + { + data_uart_print("ShowCon conn_id %d state 0x%x role %d\r\n", conn_id, + conn_info.conn_state, conn_info.role); + data_uart_print("RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + conn_info.remote_bd[5], conn_info.remote_bd[4], + conn_info.remote_bd[3], conn_info.remote_bd[2], + conn_info.remote_bd[1], conn_info.remote_bd[0], + conn_info.remote_bd_type); + } + } + data_uart_print("active link num %d, idle link num %d\r\n", + le_get_active_link_num(), le_get_idle_link_num()); + return (RESULT_SUCESS); +} + +/** + * @brief LE connection param update request + * + * Command table define + * \code{.c} + { + "conupdreq", + "conupdreq [conn_id] [interval_min] [interval_max] [latency] [supervision_timeout]\n\r", + "LE connection param update request\r\n\ + sample: conupdreq 0 0x30 0x40 0 500\n\r", + cmd_conupdreq + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_conupdreq(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t conn_interval_min = p_parse_value->dw_param[1]; + uint16_t conn_interval_max = p_parse_value->dw_param[2]; + uint16_t conn_latency = p_parse_value->dw_param[3]; + uint16_t supervision_timeout = p_parse_value->dw_param[4]; + + + cause = le_update_conn_param(conn_id, + conn_interval_min, + conn_interval_max, + conn_latency, + supervision_timeout, + 2 * (conn_interval_min - 1), + 2 * (conn_interval_max - 1) + ); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Disconnect to remote device + * + * Command table define + * \code{.c} + { + "disc", + "disc [conn_id]\n\r", + "Disconnect to remote device\n\r", + cmd_disc + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_disc(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_disconnect(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Config authentication mode + * + * Command table define + * \code{.c} + { + "authmode", + "authmode [auth_flags] [io_cap] [sec_enable] [oob_enable]\n\r", + "Config authentication mode\r\n\ + [auth_flags]:authentication req bit field: bit0-(bonding), bit2-(MITM), bit3-(SC)\r\n\ + [io_cap]:set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\ + [sec_enable]:Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\ + [oob_enable]:Enable oob flag: 0-(disable), 1-(enable)\r\n\ + sample: authmode 0x5 2 1 0\n\r", + cmd_authmode + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_authmode(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t oob_enable = false; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + if (p_parse_value->param_count > 0) + { + auth_flags = p_parse_value->dw_param[0]; + auth_sec_req_flags = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + auth_io_cap = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + auth_sec_req_enable = p_parse_value->dw_param[2]; + } + if (p_parse_value->param_count > 3) + { + oob_enable = p_parse_value->dw_param[3]; + } + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + cause = gap_set_pairable_mode(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Send authentication request + * + * Command table define + * \code{.c} + { + "sauth", + "sauth [conn_id]\n\r", + "Send authentication request\n\r", + cmd_sauth + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_sauth(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_bond_pair(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION + * + * Command table define + * \code{.c} + { + "userconf", + "userconf [conn_id] [conf]\n\r", + "Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION\r\n\ + [conf]: 0-(Reject), 1-(Accept)\r\n\ + sample: userconf 0 1\n\r", + cmd_userconf + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_userconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT; + T_GAP_CAUSE cause; + if (p_parse_value->dw_param[1] == 0) + { + confirm = GAP_CFM_CAUSE_REJECT; + } + cause = le_bond_user_confirm(conn_id, confirm); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT + * + * Command table define + * \code{.c} + { + "authkey", + "authkey [conn_id] [passkey]\n\r", + "Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT\r\n\ + [passkey]: 0 - 999999\r\n\ + sample: authkey 0 123456\n\r", + cmd_authkey + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_authkey(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint32_t passcode = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT; + if (passcode > GAP_PASSCODE_MAX) + { + confirm = GAP_CFM_CAUSE_REJECT; + } + cause = le_bond_passkey_input_confirm(conn_id, passcode, + confirm); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Clear all bonded devices information + * + * Command table define + * \code{.c} + { + "bondclear", + "bondclear\n\r", + "Clear all bonded devices information\n\r", + cmd_bondclear + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_bondclear(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + le_bond_clear_all_keys(); + return (RESULT_SUCESS); +} + +/** + * @brief Get all Bonded devices information + * + * Command table define + * \code{.c} + { + "bondinfo", + "bondinfo\n\r", + "Get all Bonded devices information\n\r", + cmd_bondinfo + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_bondinfo(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + T_LE_KEY_ENTRY *p_entry; + for (i = 0; i < bond_storage_num; i++) + { + p_entry = le_find_key_entry_by_idx(i); + if (p_entry != NULL) + { + data_uart_print("bond_dev[%d]: bd 0x%02x%02x%02x%02x%02x%02x, addr_type %d, flags 0x%x\r\n", + p_entry->idx, + p_entry->remote_bd.addr[5], + p_entry->remote_bd.addr[4], + p_entry->remote_bd.addr[3], + p_entry->remote_bd.addr[2], + p_entry->remote_bd.addr[1], + p_entry->remote_bd.addr[0], + p_entry->remote_bd.remote_bd_type, + p_entry->flags); + } + } + + return (RESULT_SUCESS); +} +/************************** Central only *************************************/ +/** + * @brief Start scan + * + * Command table define + * \code{.c} + { + "scan", + "scan [filter_policy] [filter_duplicate]\n\r", + "Start scan\r\n\ + [filter_policy]: 0-(any), 1-(whitelist), 2-(any RPA), 3-(whitelist RPA) \r\n\ + [filter_duplicate]: 0-(disable), 1-(enable) \n\r", + cmd_scan + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_scan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + if (p_parse_value->param_count > 0) + { + scan_filter_policy = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + scan_filter_duplicate = p_parse_value->dw_param[1]; + } + + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + cause = le_scan_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Stop scan + * + * Command table define + * \code{.c} + { + "stopscan", + "stopscan\n\r", + "Stop scan\n\r", + cmd_stopscan + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_stopscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_scan_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Connect to remote device: use address + * + * Command table define + * \code{.c} + { + "con", + "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [addr_type]\n\r", + "Connect to remote device: use address\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: remote device address\r\n\ + [addr_type]: 0-(public), 1-(random)\r\n\ + sample: con x11 x22 x33 x44 x55 x66 0 \n\r", + cmd_con + }, + * \endcode + */ +static T_USER_CMD_PARSE_RESULT cmd_con(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t addr[6] = {0}; + uint8_t addr_len; + uint8_t addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + if (p_parse_value->param_count >= 7) + { + addr_type = p_parse_value->dw_param[6]; + } + + cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, addr, (T_GAP_REMOTE_ADDR_TYPE)addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/************************** GATT client *************************************/ +/** + * @brief Send indication confimation + * + * Command table define + * \code{.c} + { + "indconf", + "indconf [conn_id]\n\r", + "Send indication confimation\r\n\ + sample: indconf 0\n\r", + cmd_indconf + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_indconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE ret; + uint8_t conn_id = p_parse_value->dw_param[0]; + ret = gcs_attr_ind_confirm(conn_id); + return (T_USER_CMD_PARSE_RESULT)ret; +} + +/** + * @brief Write data to service + * + * Command table define + * \code{.c} + { + "write", + "write [conn_id] [type] [handle] [length] [value0] [...]\n\r", + "Write data to service\r\n\ + [type]: write type: 1-(write request), 2-(write command)\r\n\ + [handle]:attribute handle\r\n\ + [length]:value length\r\n\ + [value0]:overwrite the value0\r\n\ + sample: write 0 1 x17 2 02 00\r\n\ + sample: write 0 2 x19 10\n\r", + cmd_write + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_write(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t write_type = p_parse_value->dw_param[1]; + uint16_t handle = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t data[512] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + if (p_parse_value->param_count > 4) + { + for (uint8_t i = 0; i < p_parse_value->param_count - 4; ++i) + { + data[i] = p_parse_value->dw_param[i + 4]; + } + } + + T_GAP_CAUSE ret = gcs_attr_write(conn_id, (T_GATT_WRITE_TYPE)write_type, handle, + length, data); + return (T_USER_CMD_PARSE_RESULT)ret; +} + +/** + * @brief Discover all primary services + * + * Command table define + * \code{.c} + { + "gsrvdis", + "gsrvdis [conn_id]\n\r", + "Discover all primary services\r\n\ + sample: gsrvdis 0\n\r", + cmd_gsrvdis + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_gsrvdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause = gcs_all_primary_srv_discovery(conn_id); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Discover services by uuid + * + * Command table define + * \code{.c} + { + "srvuuid", + "srvdis [conn_id] [type] [uuid]\n\r", + "Discover services by uuid\r\n\ + [type]:UUID type: 0-(uuid16), 1-(uuid128)\r\n\ + [uuid]:Sevice uuid\r\n\ + sample(uuid128): srvuuid 0 1 0x00006287 0x3c17d293 0x8e4814fe 0x2e4da212\r\n\ + sample(uuid16): srvuuid 0 0 0x1801\n\r", + cmd_srvuuid + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_srvuuid(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->dw_param[1] == 0) + { + uint16_t uuid16 = p_parse_value->dw_param[2]; + cause = gcs_by_uuid_srv_discovery(conn_id, uuid16); + } + else if (p_parse_value->dw_param[1] == 1) + { + uint32_t u0 = p_parse_value->dw_param[2]; + uint32_t u1 = p_parse_value->dw_param[3]; + uint32_t u2 = p_parse_value->dw_param[4]; + uint32_t u3 = p_parse_value->dw_param[5]; + uint8_t uuid128[16] = + { + (uint8_t)u3, (uint8_t)(u3 >> 8), (uint8_t)(u3 >> 16), (uint8_t)(u3 >> 24), + (uint8_t)u2, (uint8_t)(u2 >> 8), (uint8_t)(u2 >> 16), (uint8_t)(u2 >> 24), + (uint8_t)u1, (uint8_t)(u1 >> 8), (uint8_t)(u1 >> 16), (uint8_t)(u1 >> 24), + (uint8_t)u0, (uint8_t)(u0 >> 8), (uint8_t)(u0 >> 16), (uint8_t)(u0 >> 24) + }; + cause = gcs_by_uuid128_srv_discovery(conn_id, uuid128); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Discover characteristic + * + * Command table define + * \code{.c} + { + "chardis", + "chardis [conn_id] [start handle] [end handle]\n\r", + "Discover characteristic\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + sample: chardis 0 xc xff\n\r", + cmd_chardis + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_chardis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + + T_GAP_CAUSE cause = gcs_all_char_discovery(conn_id, start_handle, end_handle); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Discover characteristic by uuid + * + * Command table define + * \code{.c} + { + "charuuid", + "charuuid [conn_id] [start handle] [end handle] [type] [uuid]\n\r", + "Discover characteristic by uuid\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + [type]:UUID type: 0-(uuid16), 1-(uuid128)\r\n\ + [uuid]:Sevice uuid\r\n\ + sample(uuid128): charuuid 0 x1 xffff 1 x00006387 x3c17d293 x8e4814fe x2e4da212\r\n\ + sample(uuid16): charuuid 0 x1 xffff 0 xb001\n\r", + cmd_charuuid + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_charuuid(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->dw_param[3] == 0) + { + uint16_t uuid16 = p_parse_value->dw_param[4]; + T_GAP_CAUSE cause = gcs_by_uuid_char_discovery(conn_id, start_handle, end_handle, + uuid16); + } + else if (p_parse_value->dw_param[3] == 1) + { + uint32_t u0 = p_parse_value->dw_param[4]; + uint32_t u1 = p_parse_value->dw_param[5]; + uint32_t u2 = p_parse_value->dw_param[6]; + uint32_t u3 = p_parse_value->dw_param[7]; + uint8_t uuid128[16] = + { + (uint8_t)u3, (uint8_t)(u3 >> 8), (uint8_t)(u3 >> 16), (uint8_t)(u3 >> 24), + (uint8_t)u2, (uint8_t)(u2 >> 8), (uint8_t)(u2 >> 16), (uint8_t)(u2 >> 24), + (uint8_t)u1, (uint8_t)(u1 >> 8), (uint8_t)(u1 >> 16), (uint8_t)(u1 >> 24), + (uint8_t)u0, (uint8_t)(u0 >> 8), (uint8_t)(u0 >> 16), (uint8_t)(u0 >> 24) + }; + T_GAP_CAUSE cause = gcs_by_uuid128_char_discovery(conn_id, start_handle, + end_handle, + uuid128); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Discover characteristic descriptor + * + * Command table define + * \code{.c} + { + "charddis", + "charddis [conn_id] [start handle] [end handle]\n\r", + "Discover characteristic descriptor\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + sample: charddis 0 xc x14\n\r", + cmd_charddis + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_charddis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + + T_GAP_CAUSE cause = gcs_all_char_descriptor_discovery(conn_id, start_handle, + end_handle); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Read characteristic + * + * Command table define + * \code{.c} + { + "read", + "read [conn_id] [handle]\n\r", + "Read characteristic\r\n\ + [handle]:attribute handle\r\n\ + sample: read 0 x1b\n\r", + cmd_read + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_read(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t handle = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->param_count <= 2) + { + cause = gcs_attr_read(conn_id, handle); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** + * @brief Read characterristic value by uuid + * + * Command table define + * \code{.c} + { + "readu", + "readu [conn_id] [start handle] [end handle] [type] [uuid]\n\r", + "Read characterristic value by uuid\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + [type]:UUID type: 0-(uuid16), 1-(uuid128)\r\n\ + [uuid]:Sevice uuid\r\n\ + sample(uuid128): readu 0 x1 xffff 1 x00006387 x3c17d293 x8e4814fe x2e4da212\r\n\ + sample(uuid16): readu 0 x1 xffff 0 0xb001\n\r", + cmd_readu + }, + * \endcode + */ +T_USER_CMD_PARSE_RESULT cmd_readu(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->dw_param[3] == 0) + { + uint16_t uuid16 = p_parse_value->dw_param[4]; + cause = gcs_attr_read_using_uuid16(conn_id, start_handle, end_handle, uuid16); + } + else if (p_parse_value->dw_param[3] == 1) + { + uint32_t u0 = p_parse_value->dw_param[4]; + uint32_t u1 = p_parse_value->dw_param[5]; + uint32_t u2 = p_parse_value->dw_param[6]; + uint32_t u3 = p_parse_value->dw_param[7]; + uint8_t uuid128[16] = + { + (uint8_t)u3, (uint8_t)(u3 >> 8), (uint8_t)(u3 >> 16), (uint8_t)(u3 >> 24), + (uint8_t)u2, (uint8_t)(u2 >> 8), (uint8_t)(u2 >> 16), (uint8_t)(u2 >> 24), + (uint8_t)u1, (uint8_t)(u1 >> 8), (uint8_t)(u1 >> 16), (uint8_t)(u1 >> 24), + (uint8_t)u0, (uint8_t)(u0 >> 8), (uint8_t)(u0 >> 16), (uint8_t)(u0 >> 24) + }; + cause = gcs_attr_read_using_uuid128(conn_id, start_handle, end_handle, uuid128); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +/** @brief User command table */ +const T_USER_CMD_TABLE_ENTRY user_cmd_table[] = +{ + /************************** Common cmd *************************************/ + { + "conupdreq", + "conupdreq [conn_id] [interval_min] [interval_max] [latency] [supervision_timeout]\n\r", + "LE connection param update request\r\n\ + sample: conupdreq 0 0x30 0x40 0 500\n\r", + cmd_conupdreq + }, + { + "showcon", + "showcon\n\r", + "Show all devices connecting status\n\r", + cmd_showcon + }, + { + "disc", + "disc [conn_id]\n\r", + "Disconnect to remote device\n\r", + cmd_disc + }, + { + "authmode", + "authmode [auth_flags] [io_cap] [sec_enable] [oob_enable]\n\r", + "Config authentication mode\r\n\ + [auth_flags]:authentication req bit field: bit0-(bonding), bit2-(MITM), bit3-(SC)\r\n\ + [io_cap]:set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\ + [sec_enable]:Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\ + [oob_enable]:Enable oob flag: 0-(disable), 1-(enable)\r\n\ + sample: authmode 0x5 2 1 0\n\r", + cmd_authmode + }, + { + "sauth", + "sauth [conn_id]\n\r", + "Send authentication request\n\r", + cmd_sauth + }, + { + "userconf", + "userconf [conn_id] [conf]\n\r", + "Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION\r\n\ + [conf]: 0-(Reject), 1-(Accept)\r\n\ + sample: userconf 0 1\n\r", + cmd_userconf + }, + { + "authkey", + "authkey [conn_id] [passkey]\n\r", + "Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT\r\n\ + [passkey]: 0 - 999999\r\n\ + sample: authkey 0 123456\n\r", + cmd_authkey + }, + { + "bondinfo", + "bondinfo\n\r", + "Get all Bonded devices information\n\r", + cmd_bondinfo + }, + { + "bondclear", + "bondclear\n\r", + "Clear all bonded devices information\n\r", + cmd_bondclear + }, + /************************** Central only *************************************/ + { + "scan", + "scan [filter_policy] [filter_duplicate]\n\r", + "Start scan\r\n\ + [filter_policy]: 0-(any), 1-(whitelist), 2-(any RPA), 3-(whitelist RPA) \r\n\ + [filter_duplicate]: 0-(disable), 1-(enable) \n\r", + cmd_scan + }, + { + "stopscan", + "stopscan\n\r", + "Stop scan\n\r", + cmd_stopscan + }, + { + "con", + "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [addr_type]\n\r", + "Connect to remote device: use address\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: remote device address\r\n\ + [addr_type]: 0-(public), 1-(random)\r\n\ + sample: con x11 x22 x33 x44 x55 x66 0 \n\r", + cmd_con + }, + /************************** GATT client *************************************/ + { + "indconf", + "indconf [conn_id]\n\r", + "Send indication confimation\r\n\ + sample: indconf 0\n\r", + cmd_indconf + }, + { + "write", + "write [conn_id] [type] [handle] [length] [value0] [...]\n\r", + "Write data to service\r\n\ + [type]: write type: 1-(write request), 2-(write command)\r\n\ + [handle]:attribute handle\r\n\ + [length]:value length\r\n\ + [value0]:overwrite the value0\r\n\ + sample: write 0 1 x17 2 02 00\r\n\ + sample: write 0 2 x19 10\n\r", + cmd_write + }, + { + "gsrvdis", + "gsrvdis [conn_id]\n\r", + "Discover all primary services\r\n\ + sample: gsrvdis 0\n\r", + cmd_gsrvdis + }, + { + "srvuuid", + "srvdis [conn_id] [type] [uuid]\n\r", + "Discover services by uuid\r\n\ + [type]:UUID type: 0-(uuid16), 1-(uuid128)\r\n\ + [uuid]:Sevice uuid\r\n\ + sample(uuid128): srvuuid 0 1 0x00006287 0x3c17d293 0x8e4814fe 0x2e4da212\r\n\ + sample(uuid16): srvuuid 0 0 0x1801\n\r", + cmd_srvuuid + }, + { + "chardis", + "chardis [conn_id] [start handle] [end handle]\n\r", + "Discover characteristic\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + sample: chardis 0 xc xff\n\r", + cmd_chardis + }, + { + "charuuid", + "charuuid [conn_id] [start handle] [end handle] [type] [uuid]\n\r", + "Discover characteristic by uuid\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + [type]:UUID type: 0-(uuid16), 1-(uuid128)\r\n\ + [uuid]:Sevice uuid\r\n\ + sample(uuid128): charuuid 0 x1 xffff 1 x00006387 x3c17d293 x8e4814fe x2e4da212\r\n\ + sample(uuid16): charuuid 0 x1 xffff 0 xb001\n\r", + cmd_charuuid + }, + { + "charddis", + "charddis [conn_id] [start handle] [end handle]\n\r", + "Discover characteristic descriptor\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + sample: charddis 0 xc x14\n\r", + cmd_charddis + }, + { + "read", + "read [conn_id] [handle]\n\r", + "Read characteristic\r\n\ + [handle]:attribute handle\r\n\ + sample: read 0 x1b\n\r", + cmd_read + }, + { + "readu", + "readu [conn_id] [start handle] [end handle] [type] [uuid]\n\r", + "Read characterristic value by uuid\r\n\ + [start handle]:Start handle\r\n\ + [end handle]:End handle\r\n\ + [type]:UUID type: 0-(uuid16), 1-(uuid128)\r\n\ + [uuid]:Sevice uuid\r\n\ + sample(uuid128): readu 0 x1 xffff 1 x00006387 x3c17d293 x8e4814fe x2e4da212\r\n\ + sample(uuid16): readu 0 x1 xffff 0 0xb001\n\r", + cmd_readu + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; +/** @} */ /* End of group CENTRAL_CLIENT_CMD */ + diff --git a/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/user_cmd.h b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/user_cmd.h new file mode 100644 index 00000000..c1615aa2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/ble_central_client/user_cmd.h @@ -0,0 +1,31 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file user_cmd.h +* @brief Define user command. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _USER_CMD_H_ +#define _USER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[]; +extern T_USER_CMD_IF user_cmd_if; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_flags.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_flags.h new file mode 100644 index 00000000..c3b377b5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_flags.h @@ -0,0 +1,16 @@ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#include "bt_flags.h" + +#define F_BT_GAPS_CHAR_WRITEABLE 0 +#define F_BT_AIRPLANE_MODE_SUPPORT 0 +#define F_BT_ANCS_CLIENT_SUPPORT 0 +#define F_BT_ANCS_APP_FILTER (F_BT_ANCS_CLIENT_SUPPORT & 0) +#define F_BT_ANCS_GET_APP_ATTR (F_BT_ANCS_CLIENT_SUPPORT & 0) +#define F_BT_ANCS_CLIENT_DEBUG (F_BT_ANCS_CLIENT_SUPPORT & 0) + +#define F_BT_TASK_SCHEDULE_DEBUG 0 + +#define APP_HID_TEST 0 +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_task.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_task.c new file mode 100644 index 00000000..0c9545d7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_task.c @@ -0,0 +1,139 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*============================================================================* + * Macros + *============================================================================*/ +//! Task priorities +#define APP_TASK_PRIORITY 1 +//!Task stack size +#define APP_TASK_STACK_SIZE 256 * 8 + +//!IO message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 +//!Event message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +void app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +void app_task_deinit() +{ + if (io_queue_handle) + { + os_msg_queue_delete(io_queue_handle); + } + if (evt_queue_handle) + { + os_msg_queue_delete(evt_queue_handle); + } + if (app_task_handle) + { + os_task_delete(app_task_handle); + } + io_queue_handle = NULL; + evt_queue_handle = NULL; + app_task_handle = NULL; + gap_dev_state.gap_init_state = 0; + gap_dev_state.gap_adv_state = 0; + gap_dev_state.gap_scan_state = 0; + gap_dev_state.gap_conn_state = 0; +} + +void app_send_msg(uint16_t sub_type) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + APP_PRINT_ERROR1("app_send_msg msg fail: subtype 0x%x", io_msg.subtype); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR1("app_send_msg event fail: subtype 0x%x", io_msg.subtype); + } +} + +/** + * @brief App task to handle events & messages + * @param[in] p_params Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + + APP_PRINT_INFO0("app_main_task"); + + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE); + + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_task.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_task.h new file mode 100644 index 00000000..01d0a658 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/app_task.h @@ -0,0 +1,34 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 + +extern void *evt_queue_handle; +extern void *io_queue_handle; +/** + * @brief Initialize App task + * @return void + */ +void app_task_init(void); +void app_task_deinit(void); +void app_send_msg(uint16_t sub_type); +void app_init(void); +bool upper_task_init(void); +void app_deinit(void); +void upper_task_deinit(void); +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/application_deinit.ewp b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/application_deinit.ewp new file mode 100644 index 00000000..84e60c50 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/application_deinit.ewp @@ -0,0 +1,2695 @@ + + + 3 + + Debug + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\postbuild_is.vbs" "$TARGET_DIR$" "$PROJ_DIR$" "$CONFIG_NAME$" "$TOOLKIT_DIR$" + + + + ILINK + 0 + + 21 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + @ERAM + + Debug + + ICCARM + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @SRAM + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\flash_api.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\flash_api_ext.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\flash_fatfs.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_flash.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_s\hal_lpcram.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_spic.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\power_mode_api.c + + + Debug + + ICCARM + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bluetooth + + board + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\bt_fwconfig.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\cycle_queue.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\data_uart\data_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\ftl.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\hci_board.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\hci_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\os\freertos_v10.0.1_IAR\osif_freertos.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\platform_utils.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\rtk_coex.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\trace_uart.c + + + + common + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\bt_uart_bridge.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\dis.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\gaps_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\hci_adapter.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\hci_process.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids_kb.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids_rmc.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\trace_task.c + + + + example + + ble_peripheral + + Debug + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\ble_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\peripheral_app.c + + + + deinit + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\ble_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\complete_ble_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\complete_ble_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\gap_test_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\link_mgr.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\privacy_mgnt.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\test_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\uart_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\app\deinit_test\user_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\mcu\module\data_uart_cmd\user_cmd_parse.c + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\bt_example_entry.c + + + + + cmsis + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram_s\app_start.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\utilities\source\ram\libc_wrap.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram\mpu_config.c + + + + console + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_bt.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_isp.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_lwip.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_media.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_mp.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_mp_ext0.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\app\shell\cmd_shell.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\app\shell\ram_s\consol_cmds.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\low_level_io.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\rtl_console.c + + + + lib + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\lib\btgap.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\lib\lib\hal_pmc.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_dct.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_eap.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_googlenest.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_http.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_soc_is.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_websocket.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_wlan.a + + + + network + + api + + wifi + + rtw_wpa_supplicant + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\src\crypto\tls_polarssl.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_eap_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_p2p_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + + + + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + + + + app + + mqtt + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTClient\MQTTClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTConnectClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTConnectServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTDeserializePublish.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTFormat.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTClient\MQTTFreertos.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTPacket.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSerializePublish.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSubscribeClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSubscribeServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTUnsubscribeClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTUnsubscribeServer.c + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\platform\ota_8710c.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client_ext.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + + + + coap + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_ameba_port.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_builder.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_header_check.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_parser.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_protocol.c + + + + googlenest + + $PROJ_DIR$\..\..\..\component\common\application\google\google_tls.c + + + + http + + $PROJ_DIR$\..\..\..\component\common\network\httpc\httpc_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\httpd\httpd_tls.c + + + + lwip + + api + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\api_lib.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\api_msg.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\err.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netdb.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netifapi.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\tcpip.c + + + + core + + ipv4 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\autoip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\dhcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\etharp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\icmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\igmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4_frag.c + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\def.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\dns.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\inet_chksum.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\init.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\mem.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\memp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\netif.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\pbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\raw.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\stats.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\sys.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp_in.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp_out.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\timeouts.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\udp.c + + + + netif + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\netif\ethernet.c + + + + port + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\port\realtek\freertos\ethernetif.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\port\realtek\freertos\sys_arch.c + + + + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + + + $PROJ_DIR$\..\..\..\component\common\network\sntp\sntp.c + + + + mdns + + $PROJ_DIR$\..\..\..\component\common\network\mDNS\mDNSPlatform.c + + + + ssl + + mbedtls + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\aesni.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\blowfish.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\camellia.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ccm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\certs.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cipher.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cipher_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cmac.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\debug.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\gcm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\havege.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\memory_buffer_alloc.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\net_sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\padlock.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs11.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs12.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkparse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\platform.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ripemd160.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cache.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_ciphersuites.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cli.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cookie.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_srv.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_ticket.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\threading.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\timing.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\version.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\version_features.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_create.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_crl.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509write_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509write_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\xtea.c + + + + ssl_ram_map + + $PROJ_DIR$\..\..\..\component\common\network\ssl\ssl_ram_map\rom\rom_ssl_ram_map.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\ssl_func_stubs\ssl_func_stubs.c + + + + + websocket + + $PROJ_DIR$\..\..\..\component\common\network\websocket\wsclient_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\websocket\wsserver_tls.c + + + + + os + + freertos + + portable + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\portable\MemMang\heap_4.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\portable\IAR\ARM_RTL8710C\port.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\portable\IAR\ARM_RTL8710C\portasm.s + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\croutine.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\event_groups.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\list.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\queue.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\stream_buffer.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\tasks.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.0.1\Source\timers.c + + + + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\device_lock.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_cb.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_service.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_service.c + + + + peripheral + + api + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\crypto_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\dma_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\gpio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\gpio_irq_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\i2c_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pinmap.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pinmap_common.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\port_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pwmout_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\serial_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\spdio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\spi_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\sys_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\timer_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\us_ticker.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\us_ticker_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\wait_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\wdt_api.c + + + + hal + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_s\hal_efuse.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_gdma.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_i2c.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_misc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_s\hal_pinmux_nsc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_sdio_dev.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_uart.c + + + + + user + + $PROJ_DIR$\..\src\main.c + + + + utilities + + example + + $PROJ_DIR$\..\..\..\component\common\example\amazon_awsiot\example_amazon_awsiot.c + + + $PROJ_DIR$\..\..\..\component\common\example\bcast\example_bcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\cJSON\example_cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\example\coap\example_coap.c + + + $PROJ_DIR$\..\..\..\component\common\example\dct\example_dct.c + + + $PROJ_DIR$\..\..\..\component\common\example\eap\example_eap.c + + + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + + + $PROJ_DIR$\..\..\..\component\common\example\get_beacon_frame\example_get_beacon_frame.c + + + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + + + $PROJ_DIR$\..\..\..\component\common\example\high_load_memory_use\example_high_load_memory_use.c + + + $PROJ_DIR$\..\..\..\component\common\example\http_client\example_http_client.c + + + $PROJ_DIR$\..\..\..\component\common\example\http_download\example_http_download.c + + + $PROJ_DIR$\..\..\..\component\common\example\httpc\example_httpc.c + + + $PROJ_DIR$\..\..\..\component\common\example\httpd\example_httpd.c + + + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\mqtt\example_mqtt.c + + + $PROJ_DIR$\..\..\..\component\common\example\nonblock_connect\example_nonblock_connect.c + + + $PROJ_DIR$\..\..\..\component\common\example\ota_http\example_ota_http.c + + + $PROJ_DIR$\..\..\..\component\common\example\rarp\example_rarp.c + + + $PROJ_DIR$\..\..\..\component\common\example\sntp_showtime\example_sntp_showtime.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_select\example_socket_select.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_tcp_trx\example_socket_tcp_trx_1.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_tcp_trx\example_socket_tcp_trx_2.c + + + $PROJ_DIR$\..\..\..\component\common\example\ssl_download\example_ssl_download.c + + + $PROJ_DIR$\..\..\..\component\common\example\ssl_server\example_ssl_server.c + + + $PROJ_DIR$\..\..\..\component\common\example\tcp_keepalive\example_tcp_keepalive.c + + + $PROJ_DIR$\..\..\..\component\common\example\uart_atcmd\example_uart_atcmd.c + + + $PROJ_DIR$\..\..\..\component\common\example\wifi_mac_monitor\example_wifi_mac_monitor.c + + + $PROJ_DIR$\..\..\..\component\common\example\wifi_roaming\example_wifi_roaming.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_scenario\example_wlan_scenario.c + + + $PROJ_DIR$\..\..\..\component\common\example\websocket_client\example_wsclient.c + + + $PROJ_DIR$\..\..\..\component\common\example\xml\example_xml.c + + + + FatFs + + Debug + + + disk_if + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\sdcard.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\sdio\realtek\sdio_host\src\sdio_combine.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\usbdisk.c + + + + fatfs_ext + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\fatfs_ext\src\ff_driver.c + + + + r0.10c + + option + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\option\ccsbcs.c + + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\diskio.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\ff.c + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\http_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\xml.c + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/ble_app_main.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/ble_app_main.c new file mode 100644 index 00000000..d74f220b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/ble_app_main.c @@ -0,0 +1,317 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace_uart.h" +#include + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default scan interval (units of 0.625ms) */ +#define DEFAULT_SCAN_INTERVAL 400 +/** @brief Default scan window (units of 0.625ms) */ +#define DEFAULT_SCAN_WINDOW 200 + +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default Maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, + GAP_ADTYPE_APPEARANCE, +#if 0 + LO_WORD(GAP_GATT_APPEARANCE_KEYBOARD), + HI_WORD(GAP_GATT_APPEARANCE_KEYBOARD), +#else + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +#endif +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, +#if 0 + 0x12, + 0x18, +#else + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), +#endif + 0x0C, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'B', '3', '_', 'G', 'a', 'p', 'T', 'e', 's', 't' +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); +} +/** + * @brief Initialize gap related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BB3_GapTest"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_gatt_mtu_req = false; + + /* Scan parameters */ + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MIN; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t auth_oob = false; + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_gatt_mtu_req), + &slave_init_gatt_mtu_req); + + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); + gap_register_app_cb(app_gap_common_callback); + //gap_register_vendor_cb(app_gap_vendor_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(1); + simp_srv_id = simp_ble_service_add_service((void *)app_profile_callback); + server_register_app_cb(app_profile_callback); +#if 0 + client_init(2); + //gaps_client_id = gaps_add_client(app_client_callback, APP_MAX_LINKS); + //simple_ble_client_id = simp_ble_add_client(app_client_callback, APP_MAX_LINKS); +#endif +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +#if F_BT_TASK_SCHEDULE_DEBUG +#include "test_os_schedule.c" +#endif + +void board_init(void) +{ +#if F_BT_TASK_SCHEDULE_DEBUG + test_os_schedule_main(); +#endif +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +#if F_BT_DLPS_EN + data_uart_dlps_init(); + lps_mode_set(LPM_DLPS_MODE); + lps_mode_pause(); +#endif +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void app_init(void) +{ + APP_PRINT_INFO1("app_init s: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + board_init(); + driver_init(); + le_gap_init(APP_MAX_LINKS); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); + app_task_init(); + APP_PRINT_INFO1("app_init end: %d", os_mem_peek(RAM_TYPE_DATA_ON)); +} + +bool upper_task_init(void) +{ + bool ret; + APP_PRINT_INFO1("bte_init s: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + bt_stack_config_init(); + ret = bte_init(); + APP_PRINT_INFO1("bte_init end: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + return ret; +} + +void app_deinit(void) +{ + APP_PRINT_INFO1("app_deinit s: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + app_task_deinit(); + APP_PRINT_INFO1("app_deinit end: %d", os_mem_peek(RAM_TYPE_DATA_ON)); +} + +void upper_task_deinit(void) +{ + APP_PRINT_INFO1("upper_task_deinit s: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + bte_deinit(); + APP_PRINT_INFO1("upper_task_deinit end: %d", os_mem_peek(RAM_TYPE_DATA_ON)); +} + +void user_cmd_task_init(void) +{ + uart_task_init(); +} +#include "bt_board.h" +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int ble_app_main(void) +{ + bt_trace_init(); + #if 0 + bt_stack_config_init(); + APP_PRINT_INFO1("next upper_task_init: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + if (upper_task_init() == false) + { + APP_PRINT_ERROR0("ble_app_main: upper_task_init failed"); + } + APP_PRINT_INFO1("next app_init: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + app_init(); + APP_PRINT_INFO1("next user_cmd_task_init: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + #endif + user_cmd_task_init(); + APP_PRINT_INFO1("ble_app_main end: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + + return 0; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_client.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_client.c new file mode 100644 index 00000000..059755c8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_client.c @@ -0,0 +1,797 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_client.c + * @brief Complete Simple BLE client source file. + * @details + * @author jane + * @date 2016-02-18 + * @version v1.0 + ****************************************************************************** + */ + +/** Add Includes here **/ +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include +#include +#include + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ + +typedef struct +{ + T_SIMP_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN]; +} T_SIMP_LINK, *P_SIMP_LINK; + +static P_SIMP_LINK simp_table; +static uint8_t simp_link_num; + +/**< Simple BLE client ID. */ +static T_CLIENT_ID simp_client = CLIENT_PROFILE_GENERAL_ID; +/**< Callback used to send data to app from Simple BLE client layer. */ +static P_FUN_GENERAL_APP_CB simp_client_cb = NULL; + + +bool simp_ble_client_start_discovery(uint8_t conn_id) +{ + APP_PRINT_INFO0("simp_ble_client_start_discovery"); + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + /* First clear handle cache. */ + memset(&simp_table[conn_id], 0, sizeof(T_SIMP_LINK)); + simp_table[conn_id].disc_state = DISC_SIMP_START; + if (client_by_uuid_srv_discovery(conn_id, simp_client, + GATT_UUID_SIMPLE_PROFILE) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +bool simp_ble_client_read_by_handle(uint8_t conn_id, T_SIMP_READ_TYPE read_type) +{ + bool hdl_valid = false; + uint16_t handle; + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case SIMP_READ_V1_READ: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V1_READ]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V1_READ]; + hdl_valid = true; + } + break; + case SIMP_READ_V3_NOTIFY_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]; + hdl_valid = true; + } + break; + case SIMP_READ_V4_INDICATE_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]; + hdl_valid = true; + } + break; + + case SIMP_READ_V7_READ_LONG: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V7_READ_LONG]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V7_READ_LONG]; + hdl_valid = true; + } + break; + case SIMP_READ_V8_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + hdl_valid = true; + } + break; + + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, simp_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_read_by_handle: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_read_by_uuid(uint8_t conn_id, T_SIMP_READ_TYPE read_type) +{ + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_read_by_uuid: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case SIMP_READ_V1_READ: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_SIMPLE_V1_READ; + break; + case SIMP_READ_V3_NOTIFY_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case SIMP_READ_V4_INDICATE_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case SIMP_READ_V7_READ_LONG: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_SIMPLE_V7_READ_LONG; + break; + case SIMP_READ_V8_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + default: + return false; + } + + if (client_attr_read_using_uuid(conn_id, simp_client, start_handle, end_handle, + uuid16, NULL) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +bool simp_ble_client_set_v3_notify(uint8_t conn_id, bool notify) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v3_notify: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = notify ? 1 : 0; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_set_v3_notify: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_set_v4_ind(uint8_t conn_id, bool ind) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v4_ind: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = ind ? 2 : 0; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_set_v4_ind: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_set_v8_cccd(uint8_t conn_id, uint16_t cccd_bits) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v8_cccd: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + uint16_t length = sizeof(uint16_t); + uint8_t *p_data = (uint8_t *)&cccd_bits; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, p_data) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + APP_PRINT_WARN0("simp_ble_client_set_v8_cccd: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_write_v2_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_write_v2_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V2_WRITE]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V2_WRITE]; + if (client_attr_write(conn_id, simp_client, type, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_write_v2_char: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_write_v6_char(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_write_v6_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + APP_PRINT_WARN0("simp_ble_client_write_v6_char: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (simp_table[conn_id].disc_state != DISC_SIMP_DONE) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid state %d", + simp_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, simp_table[conn_id].hdl_cache, len); + return true; +} + +bool simp_ble_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (simp_table[conn_id].disc_state != DISC_SIMP_IDLE) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid state %d", + simp_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(simp_table[conn_id].hdl_cache, p_hdl_cache, len); + simp_table[conn_id].disc_state = DISC_SIMP_DONE; + return true; +} + +static bool simp_ble_client_start_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("simp_ble_client_start_simp_char_discovery"); + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + if (client_all_char_discovery(conn_id, simp_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +static bool simp_ble_client_start_char_descriptor_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("simp_ble_client_start_char_descriptor_discovery"); + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + if (client_all_char_descriptor_discovery(conn_id, simp_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} +static void simp_ble_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + bool cb_flag = false; + T_SIMP_CLIENT_CB_DATA cb_data; + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_DISC_STATE; + + APP_PRINT_INFO1("simp_ble_client_discover_state_cb: discovery_state %d", discovery_state); + if (simp_table[conn_id].disc_state == DISC_SIMP_START) + { + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + switch (discovery_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((hdl_cache[HDL_SIMBLE_SRV_START] != 0) + || (hdl_cache[HDL_SIMBLE_SRV_END] != 0)) + { + if (simp_ble_client_start_char_discovery(conn_id) == false) + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + } + /* No Simple BLE service handle found. Discover procedure complete. */ + else + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + if (hdl_cache[HDL_SIMBLE_V3_NOTIFY] != 0) + { + if (simp_ble_client_start_char_descriptor_discovery(conn_id) == false) + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + } + else + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + simp_table[conn_id].disc_state = DISC_SIMP_DONE; + cb_flag = true; + break; + case DISC_STATE_FAILED: + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + break; + default: + APP_PRINT_ERROR0("simp_handle_discover_state: Invalid Discovery State!"); + break; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && simp_client_cb) + { + cb_data.cb_content.disc_state = simp_table[conn_id].disc_state; + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + return; +} + +/** + * @brief Called by profile client layer, when discover result fetched. + * @param conn_id: connection ID. + * @param result_type: indicate which type of value discovered in service discovery procedure. + * @param result_data: value discovered. + * @retval None + */ +static void simp_ble_client_discover_result_cb(uint8_t conn_id, + T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + APP_PRINT_INFO1("simp_ble_client_discover_result_cb: result_type %d", result_type); + if (simp_table[conn_id].disc_state == DISC_SIMP_START) + { + uint16_t handle; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + hdl_cache[HDL_SIMBLE_SRV_START] = result_data.p_srv_disc_data->att_handle; + hdl_cache[HDL_SIMBLE_SRV_END] = result_data.p_srv_disc_data->end_group_handle; + break; + + case DISC_RESULT_CHAR_UUID16: + handle = result_data.p_char_uuid16_disc_data->value_handle; + switch (result_data.p_char_uuid16_disc_data->uuid16) + { + case GATT_UUID_CHAR_SIMPLE_V1_READ: + hdl_cache[HDL_SIMBLE_V1_READ] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V2_WRITE: + hdl_cache[HDL_SIMBLE_V2_WRITE] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V3_NOTIFY: + hdl_cache[HDL_SIMBLE_V3_NOTIFY] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V4_INDICATE: + hdl_cache[HDL_SIMBLE_V4_INDICATE] = handle; + break; + + + case GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG: + hdl_cache[HDL_SIMBLE_V6_WRITE_LONG] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V7_READ_LONG: + hdl_cache[HDL_SIMBLE_V7_READ_LONG] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V8: + hdl_cache[HDL_SIMBLE_V8] = handle; + break; + + default: + /* have no intrest on this handle. */ + break; + } + + break; + + case DISC_RESULT_CHAR_DESC_UUID16: + /* When use client_all_char_descriptor_discovery. */ + if (result_data.p_char_desc_uuid16_disc_data->uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) + { + handle = result_data.p_char_desc_uuid16_disc_data->handle; + if ((handle > hdl_cache[HDL_SIMBLE_V3_NOTIFY]) + && (handle < hdl_cache[HDL_SIMBLE_V4_INDICATE])) + { + hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_SIMBLE_V4_INDICATE]) && + (handle < hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) && + (hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD] == 0)) + { + hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_SIMBLE_V8]) + && (hdl_cache[HDL_SIMBLE_V8_CCCD] == 0)) + { + hdl_cache[HDL_SIMBLE_V8_CCCD] = handle; + } + } + break; + + default: + APP_PRINT_ERROR0("simp_handle_discover_result: Invalid Discovery Result Type!"); + break; + } + } + + return; +} + +static void simp_ble_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_READ_RESULT; + + APP_PRINT_INFO2("simp_ble_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + + if (handle == hdl_cache[HDL_SIMBLE_V1_READ]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V1_READ; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.v1_read.p_value = p_value; + cb_data.cb_content.read_result.data.v1_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.v1_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V3_NOTIFY_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + cb_data.cb_content.read_result.data.v3_notify_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.v3_notify_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V4_INDICATE_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + cb_data.cb_content.read_result.data.v4_indicate_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.v4_indicate_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V7_READ_LONG]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V7_READ_LONG; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.v7_read.p_value = p_value; + cb_data.cb_content.read_result.data.v7_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.v7_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V8_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + cb_data.cb_content.read_result.data.v8_notify_ind_cccd = ccc_bit; + } + } + else + { + return; + } + /* Inform application the read result. */ + if (simp_client_cb) + { + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return; +} + +/** + * @brief Called by profile client layer, when write request complete. + * @param conn_id: connection ID. + * @param result: write request send success or not. + * @retval None + */ +static void simp_ble_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_WRITE_RESULT; + + APP_PRINT_INFO2("simp_ble_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.write_result.cause = cause; + + if (handle == hdl_cache[HDL_SIMBLE_V2_WRITE]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V2_WRITE; + } + else if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V3_NOTIFY_CCCD; + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V4_INDICATE_CCCD; + } + else if (handle == hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V6_WRITE_LONG; + } + else if (handle == hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V8_CCCD; + } + else + { + return; + } + /* Inform application the write result. */ + if (simp_client_cb) + { + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return; +} + +static T_APP_RESULT simp_ble_client_notif_ind_result_cb(uint8_t conn_id, bool notify, + uint16_t handle, + uint16_t value_size, uint8_t *p_value) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + + if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY]) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V3_NOTIFY; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE]) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V4_INDICATE; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_SIMBLE_V8]) + { + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + if (notify) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V8_NOTIFY; + + } + else + { + cb_data.cb_content.notif_ind_data.type = SIMP_V8_INDICATE; + } + } + else + { + return app_result; + } + /* Inform application the notif/ind result. */ + if (simp_client_cb) + { + app_result = (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return app_result; +} + +static void simp_ble_client_disconnect_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("simp_ble_client_disconnect_cb."); + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_disconnect_cb: failed invalid conn_id %d", conn_id); + return; + } + memset(&simp_table[conn_id], 0, sizeof(T_SIMP_LINK)); + return; +} + +/** + * @brief Simple BLE Client Callbacks. +*/ +const T_FUN_CLIENT_CBS simp_ble_client_cbs = +{ + simp_ble_client_discover_state_cb, //!< Discovery State callback function pointer + simp_ble_client_discover_result_cb, //!< Discovery result callback function pointer + simp_ble_client_read_result_cb, //!< Read response callback function pointer + simp_ble_client_write_result_cb, //!< Write result callback function pointer + simp_ble_client_notif_ind_result_cb, //!< Notify Indicate callback function pointer + simp_ble_client_disconnect_cb //!< Link disconnection callback function pointer +}; + +T_CLIENT_ID simp_ble_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > SIMP_MAX_LINKS) + { + APP_PRINT_ERROR1("simp_ble_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&simp_client, &simp_ble_client_cbs)) + { + simp_client = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("simp_ble_add_client failed"); + return simp_client; + } + APP_PRINT_INFO1("simp_ble_add_client: simp_client %d", simp_client); + + /* register callback for profile to inform application that some events happened. */ + simp_client_cb = app_cb; + simp_link_num = link_num; + size = simp_link_num * sizeof(T_SIMP_LINK); + simp_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + return simp_client; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_client.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_client.h new file mode 100644 index 00000000..10a72381 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_client.h @@ -0,0 +1,332 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_client.h + * @brief Head file for using Simple BLE Client. + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _COMPLETE_BLE_CLIENT_H_ +#define _COMPLETE_BLE_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include + +/** @addtogroup PROFILE_API Profile APIs + * @{ + */ + +/** @addtogroup Bluetooth_Clients Bluetooth Clients + * @{ + */ + +/** @defgroup SIMP_Client Simple Ble service client + * @brief Simple BLE service client + * @details + Simple BLE Profile is a customized BLE-based Profile. Simple ble service please refer to @ref SIMP_Service . + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Client_Exported_Macros SIMP Client Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_UUIDs1 SIMP UUIDs + * @brief Simple BLE Profile UUID definitions + * @{ + */ +#define GATT_UUID_SIMPLE_PROFILE 0xA00A +#define GATT_UUID_CHAR_SIMPLE_V1_READ 0xB001 +#define GATT_UUID_CHAR_SIMPLE_V2_WRITE 0xB002 +#define GATT_UUID_CHAR_SIMPLE_V3_NOTIFY 0xB003 +#define GATT_UUID_CHAR_SIMPLE_V4_INDICATE 0xB004 +#define GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG 0xB006 +#define GATT_UUID_CHAR_SIMPLE_V7_READ_LONG 0xB007 +#define GATT_UUID_CHAR_SIMPLE_V8 0xB008 +/** @} End of SIMP_UUIDs */ + +/** @brief Define links number. range: 0-4 */ +#define SIMP_MAX_LINKS 4 +/** End of SIMP_Client_Exported_Macros + * @} + */ + + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Client_Exported_Types SIMP Client Exported Types + * @brief + * @{ + */ + +/** @brief SIMP client handle type*/ +typedef enum +{ + HDL_SIMBLE_SRV_START, //!< start handle of simple ble service + HDL_SIMBLE_SRV_END, //!< end handle of simple ble service + HDL_SIMBLE_V1_READ, //!< V1 read characteristic value handle + HDL_SIMBLE_V2_WRITE, //!< V2 write characteristic value handle + HDL_SIMBLE_V3_NOTIFY, //!< V3 notify characteristic value handle + HDL_SIMBLE_V3_NOTIFY_CCCD, //!< V3 notify characteristic CCCD handle + HDL_SIMBLE_V4_INDICATE, //!< V4 indicate characteristic value handle + HDL_SIMBLE_V4_INDICATE_CCCD, //!< V4 indicate characteristic CCCD handle + HDL_SIMBLE_V6_WRITE_LONG, // V6 write long value handle + HDL_SIMBLE_V7_READ_LONG, // V7 read long value handle + HDL_SIMBLE_V8, // V3 notify value handle + HDL_SIMBLE_V8_CCCD, // V3 notify CCCD handle + HDL_SIMBLE_CACHE_LEN //!< handle cache length +} T_SIMP_HANDLE_TYPE; + +/** @brief SIMP client discovery state*/ +typedef enum +{ + DISC_SIMP_IDLE, + DISC_SIMP_START, + DISC_SIMP_DONE, + DISC_SIMP_FAILED +} T_SIMP_DISC_STATE; + +/** @brief SIMP client read type*/ +typedef enum +{ + SIMP_READ_V1_READ, + SIMP_READ_V3_NOTIFY_CCCD, + SIMP_READ_V4_INDICATE_CCCD, + SIMP_READ_V7_READ_LONG = 4, + SIMP_READ_V8_CCCD = 5, +} T_SIMP_READ_TYPE; + +/** @brief SIMP client read value*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_SIMP_READ_VALUE; + +/** @brief SIMP client read data*/ +typedef union +{ + T_SIMP_READ_VALUE v1_read; + bool v3_notify_cccd; + bool v4_indicate_cccd; + uint16_t v8_notify_ind_cccd; + T_SIMP_READ_VALUE v7_read; +} T_SIMP_READ_DATA; + +/** @brief SIMP client read result*/ +typedef struct +{ + T_SIMP_READ_TYPE type; + T_SIMP_READ_DATA data; + uint16_t cause; +} T_SIMP_READ_RESULT; + + +/** @brief SIMP client write type*/ +typedef enum +{ + SIMP_WRITE_V2_WRITE, + SIMP_WRITE_V3_NOTIFY_CCCD, + SIMP_WRITE_V4_INDICATE_CCCD, + SIMP_WRITE_V6_WRITE_LONG, + SIMP_WRITE_V8_CCCD, +} T_SIMP_WRTIE_TYPE; + +/** @brief SIMP client write result*/ +typedef struct +{ + T_SIMP_WRTIE_TYPE type; + uint16_t cause; +} T_SIMP_WRITE_RESULT; + +/** @brief SIMP client notif/ind receive type*/ +typedef enum +{ + SIMP_V3_NOTIFY, + SIMP_V4_INDICATE, + SIMP_V8_NOTIFY, + SIMP_V8_INDICATE, +} T_SIMP_NOTIF_IND_TYPE; + +/** @brief SIMP client notif/ind receive data*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_SIMP_NOTIF_IND_VALUE; + +/** @brief SIMP client notif/ind receive content*/ +typedef struct +{ + T_SIMP_NOTIF_IND_TYPE type; + T_SIMP_NOTIF_IND_VALUE data; +} T_SIMP_NOTIF_IND_DATA; + +/** @brief SIMP client callback type*/ +typedef enum +{ + SIMP_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + SIMP_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + SIMP_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + SIMP_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_SIMP_CLIENT_CB_TYPE; + +/** @brief SIMP client callback content*/ +typedef union +{ + T_SIMP_DISC_STATE disc_state; + T_SIMP_READ_RESULT read_result; + T_SIMP_WRITE_RESULT write_result; + T_SIMP_NOTIF_IND_DATA notif_ind_data; +} T_SIMP_CLIENT_CB_CONTENT; + +/** @brief SIMP client callback data*/ +typedef struct +{ + T_SIMP_CLIENT_CB_TYPE cb_type; + T_SIMP_CLIENT_CB_CONTENT cb_content; +} T_SIMP_CLIENT_CB_DATA; + +/** End of SIMP_Client_Exported_Types * @} */ + +/** @defgroup SIMP_Client_Exported_Functions SIMP Client Exported Functions + * @{ + */ + +/** + * @brief Add simple ble service client to application. + * @param[in] app_cb pointer of app callback function to handle specific client module data. + * @param[in] link_num initialize link num. + * @return Client ID of the specific client module. + * @retval 0xff failed. + * @retval other success. + * + * Example usage + * \code{.c} + void app_le_profile_init(void) + { + client_init(1); + simple_ble_client_id = simp_ble_add_client(app_client_callback, APP_MAX_LINKS); + } + * \endcode + */ +T_CLIENT_ID simp_ble_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num); + +/** + * @brief Used by application, to start the discovery procedure of Simple BLE server. + * @param[in] conn_id connection ID. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_start_discovery(uint8_t conn_id); + +/** + * @brief Used by application, to read data from server by using handles. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_read_by_handle(uint8_t conn_id, T_SIMP_READ_TYPE read_type); + +/** + * @brief Used by application, to read data from server by using UUIDs. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_read_by_uuid(uint8_t conn_id, T_SIMP_READ_TYPE read_type); + +/** + * @brief Used by application, to write data of V2 write Characteristic. + * @param[in] conn_id connection ID. + * @param[in] length write data length + * @param[in] p_value point the value to write + * @param[in] type write type. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_write_v2_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type); + +/** + * @brief Used by application, to send write request to peer server's V6 Long Write Characteristic. + * @param conn_id: connection ID. + * @param length: value length. + * @param p_value: value point. + * @retval true--send request to upper stack success. + * false--send request to upper stack failed. + */ +bool simp_ble_client_write_v6_char(uint8_t conn_id, uint16_t length, uint8_t *p_value); +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param[in] conn_id connection ID. + * @param[in] notify 0--disable the notification, 1--enable the notification. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_set_v3_notify(uint8_t conn_id, bool notify); + +/** + * @brief Used by application, to enable or disable the indication of peer server's V4 Indicate Characteristic. + * @param[in] conn_id connection ID. + * @param[in] ind 0--disable the indication, 1--enable the indication. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_set_v4_ind(uint8_t conn_id, bool ind); + +bool simp_ble_client_set_v8_cccd(uint8_t conn_id, uint16_t cccd_bits); + + + + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool simp_ble_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief Used by application, to set handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool simp_ble_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** @} End of SIMP_Client_Exported_Functions */ + +/** @} End of SIMP_Client */ + +/** @} End of Bluetooth_Clients */ + +/** @} End of PROFILE_API */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SIMPLE_BLE_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_service.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_service.c new file mode 100644 index 00000000..36ee786c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_service.c @@ -0,0 +1,609 @@ +/** +********************************************************************************************************* +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file simple_ble_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date +* @version +********************************************************************************************************* +*/ + +#include +#include +#include +#include + +#define GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG 0xB006 +#define GATT_UUID_CHAR_SIMPLE_V7_READ_LONG 0xB007 +#define GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE 0xB008 + +T_SERVER_ID simp_service_id; +/**< Function pointer used to send event to application from simple profile. Initiated in simp_ble_service_add_service. */ +static P_FUN_SERVER_GENERAL_CB pfn_simp_ble_service_cb = NULL; + +/**< Value of simple read characteristic. */ +static uint8_t simple_v1_read_value = 0xf0; +uint8_t v7_char_value[SIMP_READ_V7_MAX_LEN] = {0}; +uint16_t v7_char_value_len = SIMP_READ_V7_MAX_LEN; +char v1_user_descr[] = "V1 read characteristic"; + +/**< @brief profile/service definition. */ +const T_ATTRIB_APPL simple_ble_service_tbl[] = +{ + /* <>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_SIMPLE_PROFILE), /* service UUID */ + HI_WORD(GATT_UUID_SIMPLE_PROFILE) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + /* <> demo for read */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_USER_DESCR), + HI_WORD(GATT_UUID_CHAR_USER_DESCR), + }, + (sizeof(v1_user_descr) - 1), /* bValueLen */ + (void *)v1_user_descr, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for write */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE_AUTHEN_SIGNED) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <>, demo for notify */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for write Long*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <> demo for read Long*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V7_READ_LONG), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V7_READ_LONG) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE | GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, +}; + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value) +{ + bool ret = true; + + switch (param_type) + { + default: + ret = false; + break; + case SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL: + if (len == 1) + { + simple_v1_read_value = *(uint8_t *)p_value; + } + else + { + ret = false; + } + break; + + case SIMPLE_BLE_SERVICE_PARAM_V7_LEN: + if (len <= SIMP_READ_V7_MAX_LEN) + { + memcpy(v7_char_value, p_value, len); + v7_char_value_len = len; + } + else + { + ret = false; + } + break; + } + + if (!ret) + { + APP_PRINT_ERROR0("simp_ble_service_set_parameter failed"); + } + + return ret; +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param attrib_index Attribute index of getting characteristic data. + * @param offset Used for Blob Read. + * @param p_length length of getting characteristic data. + * @param pp_value data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT simp_ble_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + default: + APP_PRINT_ERROR1("simp_ble_service_attr_read_cb, Attr not found, index %d", attrib_index); + cause = APP_RESULT_ATTR_NOT_FOUND; + break; + case SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = SIMP_READ_V1; + callback_data.conn_id = conn_id; + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = &simple_v1_read_value; + *p_length = sizeof(simple_v1_read_value); + } + break; + case SIMPLE_BLE_SERVICE_CHAR_V7_READ_LONG_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = SIMP_READ_V7; + callback_data.conn_id = conn_id; + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = v7_char_value; + *p_length = v7_char_value_len; + } + break; + } + + return (cause); +} + + +void simple_write_post_callback(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t length, uint8_t *p_value) +{ + APP_PRINT_INFO4("simple_write_post_callback: conn_id %d, service_id %d, attrib_index 0x%x, length %d", + conn_id, service_id, attrib_index, length); +} +/** + * @brief write characteristic data from service. + * + * @param conn_id + * @param service_id ServiceID to be written. + * @param attrib_index Attribute index of characteristic. + * @param length length of value to be written. + * @param p_value value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT simp_ble_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + TSIMP_CALLBACK_DATA callback_data; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("simp_ble_service_attr_write_cb write_type = 0x%x", write_type); + *p_write_ind_post_proc = simple_write_post_callback; + if (SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX == attrib_index) + { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = SIMP_WRITE_V2; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + } + else if (SIMPLE_BLE_SERVICE_CHAR_V6_WRITE_INDEX == attrib_index) + { + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = SIMP_WRITE_V6; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(simp_service_id, (void *)&callback_data); + } + } + else + { + APP_PRINT_ERROR2("simp_ble_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, + length); + cause = APP_RESULT_ATTR_NOT_FOUND; + } + return cause; +} + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("simp_ble_service_send_v3_notify"); + // send notification to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX, p_value, + length, + GATT_PDU_TYPE_ANY); +} + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("simp_ble_service_send_v4_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX, p_value, + length, GATT_PDU_TYPE_ANY); +} + +bool simp_ble_service_simple_v8_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("<-- simp_ble_service_simple_v8_notify"); + // send notification to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX, + p_value, length, GATT_PDU_TYPE_NOTIFICATION); +} + +bool simp_ble_service_simple_v8_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("<-- simp_ble_service_simple_v8_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX, + p_value, + length, GATT_PDU_TYPE_INDICATION); +} + + +void simp_ble_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index, + uint16_t cccbits) +{ + TSIMP_CALLBACK_DATA callback_data; + bool is_handled = false; + callback_data.conn_id = conn_id; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + APP_PRINT_INFO2("simp_ble_service_cccd_update_cb: index = %d, cccbits 0x%x", index, cccbits); + switch (index) + { + case SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V3_ENABLE; + } + else + { + // Disable Notification + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V3_DISABLE; + } + is_handled = true; + } + break; + case SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V4_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V4_DISABLE; + } + is_handled = true; + } + break; + + case SIMPLE_BLE_SERVICE_CHAR_V8_CCCD_INDEX: + { + if (cccbits == GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE; + } + else if (cccbits == GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE; + } + else if (cccbits == GATT_CLIENT_CHAR_CONFIG_NOTIFY_INDICATE) + { + // Disable Indication + callback_data.msg_data.notification_indification_index = + SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_DISABLE; + } + + is_handled = true; + } + break; + default: + break; + } + /* Notify Application. */ + if (pfn_simp_ble_service_cb && (is_handled == true)) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } +} + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS simp_ble_service_cbs = +{ + simp_ble_service_attr_read_cb, // Read callback function pointer + simp_ble_service_attr_write_cb, // Write callback function pointer + simp_ble_service_cccd_update_cb // CCCD update callback function pointer +}; + +/** + * @brief add Simple BLE service to application. + * + * @param[in] p_func pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + */ +T_SERVER_ID simp_ble_service_add_service(void *p_func) +{ + if (false == server_add_service(&simp_service_id, + (uint8_t *)simple_ble_service_tbl, + sizeof(simple_ble_service_tbl), + simp_ble_service_cbs)) + { + APP_PRINT_ERROR0("simp_ble_service_add_service: fail"); + simp_service_id = 0xff; + return simp_service_id; + } + + pfn_simp_ble_service_cb = (P_FUN_SERVER_GENERAL_CB)p_func; + return simp_service_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_service.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_service.h new file mode 100644 index 00000000..d9c3644f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/complete_ble_service.h @@ -0,0 +1,255 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _COMPLETE_BLE_SERVICE_H_ +#define _COMPLETE_BLE_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include +#include + +/** @addtogroup PROFILE_API Profile APIs + * @{ + */ + + +/** @addtogroup Bluetooth_Services Bluetooth Services + * @{ + */ + +/** @defgroup SIMP_Service Simple Ble Service + * @brief Simple BLE service + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Macros SIMP Service Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +typedef enum +{ + SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL = 0x01, + SIMPLE_BLE_SERVICE_PARAM_V7_LEN = 0x02, +} T_SIMP_PARAM_TYPE; + +/** @} */ + + + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ +/** @brief Index of each characteristic in Demo Profile service database. */ +#define SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX 0x02 +#define SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX 0x05 +#define SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX 0x07 +#define SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX 0x0a +#define SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX + 1) +#define SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX + 1) +#define SIMPLE_BLE_SERVICE_CHAR_V6_WRITE_INDEX 0xd +#define SIMPLE_BLE_SERVICE_CHAR_V7_READ_LONG_INDEX 0xf +#define SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX 0x11 +#define SIMPLE_BLE_SERVICE_CHAR_V8_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX + 1) + +/** @defgroup SIMP_Service_Read_Info SIMP Service Read Info + * @brief Parameter for reading characteristic value. + * @{ + */ +#define SIMP_READ_V1 1 +#define SIMP_READ_V7 2 +/** @} */ + +/** @defgroup SIMP_Service_Write_Info SIMP Service Write Info + * @brief Parameter for writing characteristic value. + * @{ + */ +#define SIMP_WRITE_V2 1 +#define SIMP_WRITE_V6 2 +/** @} */ + +/** @defgroup SIMP_Service_Notify_Indicate_Info SIMP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define SIMP_NOTIFY_INDICATE_V3_ENABLE 1 +#define SIMP_NOTIFY_INDICATE_V3_DISABLE 2 +#define SIMP_NOTIFY_INDICATE_V4_ENABLE 3 +#define SIMP_NOTIFY_INDICATE_V4_DISABLE 4 +#define SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE 7 +#define SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE 8 +#define SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE 9 +#define SIMP_NOTIFY_INDICATE_V8_DISABLE 10 +/** @} */ + +#define SIMP_READ_V7_MAX_LEN 300 + +/** @} End of SIMP_Service_Upstream_Message */ + + + +/** @} End of SIMP_Service_Exported_Macros */ +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +typedef struct +{ + uint8_t opcode; //!< ref: @ref SIMP_Control_Point_OpCodes, @ref SIMP_Service_Write_Info + T_WRITE_TYPE write_type; + uint16_t len; + uint8_t *p_value; +} TSIMP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + TSIMP_WRITE_MSG write; +} TSIMP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct +{ + uint8_t conn_id; + T_SERVICE_CALLBACK_TYPE msg_type; + TSIMP_UPSTREAM_MSG_DATA msg_data; +} TSIMP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief + * @{ + */ + +/** + * @brief add Simple BLE service to application. + * + * @param[in] p_func pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + */ +T_SERVER_ID simp_ble_service_add_service(void *p_func); + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value); + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_simple_v8_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, + uint16_t length); + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_simple_v8_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +/** @} End of Bluetooth_Services */ + +/** @} End of PROFILE_API */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/gap_test_app.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/gap_test_app.c new file mode 100644 index 00000000..59270384 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/gap_test_app.c @@ -0,0 +1,1730 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_test_app.c + * @brief Gap roles test application implementation. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif +#if F_BT_LE_PRIVACY_SUPPORT +#include +#include +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#include +#endif +#if F_BT_ANCS_CLIENT_SUPPORT +#include +#include +#endif +#include +#include +#include +#include "os_mem.h" +/*============================================================================* + * Variables + *============================================================================*/ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_CLIENT_ID simple_ble_client_id = 0xf0; /**< Simple ble service client id*/ +T_CLIENT_ID gaps_client_id = 0xf0; /**< gap service client id*/ +#endif +T_SERVER_ID simp_srv_id = 0xff; /**< Simple ble service id*/ +T_SERVER_ID hid_srv_id = 0xff; + +T_GAP_TEST_CASE gap_test_case = GAP_TC_00_NORMAL; +T_GAP_V3_NOTIF_TEST gap_v3_notif_test; + +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +#if F_BT_LE_PRIVACY_SUPPORT +T_PRIVACY_STATE priv_state = PRIVACY_STATE_INIT; +#endif +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); +void app_handle_bond_modify_msg(T_LE_BOND_MODIFY_TYPE type, T_LE_KEY_ENTRY *p_entry); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_QDECODE: + { + if (io_msg.subtype == 0) + { + le_adv_start(); + } + else if (io_msg.subtype == 1) + { + le_scan_start(); + } + } + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO5("app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, conn state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, new_state.gap_conn_state, cause); + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + uint8_t bt_addr[6]; + data_uart_print("GAP stack ready\r\n"); + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + if (test_case_id != TC_IDLE) + { + app_send_msg_to_uart_app(TC_STACK_STARTED, 0); + } +#if F_BT_LE_PRIVACY_SUPPORT + if (gap_test_case == GAP_TC_03_PRIVACY) + { + privacy_init_resolving_list(app_privacy_callback); + } +#endif + APP_PRINT_INFO1("GAP_INIT_STATE_STACK_READY: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + } + } + + if (gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + data_uart_print("GAP scan start\r\n"); + if (test_case_id == TC_0003_SCAN) + { + app_send_msg_to_uart_app(TC_START_SCAN, 0); + } + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + data_uart_print("GAP adv stoped:because conn\r\n"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + data_uart_print("GAP adv stoped\r\n"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + data_uart_print("GAP adv start\r\n"); + if (test_case_id == TC_0002_ADV) + { + app_send_msg_to_uart_app(TC_START_ADV, 0); + } + } + } + + if (gap_dev_state.gap_conn_state != new_state.gap_conn_state) + { + APP_PRINT_INFO2("conn state: %d -> %d", + gap_dev_state.gap_conn_state, + new_state.gap_conn_state); + } +#if F_BT_LE_PRIVACY_SUPPORT + if (gap_test_case == GAP_TC_03_PRIVACY) + { + if ((new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + && (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + && (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + && (new_state.gap_conn_state == GAP_CONN_DEV_STATE_IDLE)) + { + privacy_handle_pending_resolving_list(); + } + } +#endif + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, app_link_table[conn_id].conn_state, new_state, disc_cause); + + app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + + data_uart_print("Disconnect conn_id %d, cause 0x%x\r\n", conn_id, disc_cause); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + if (gap_v3_notif_test.v3_tx_num != 0 && gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + memset(&gap_v3_notif_test, 0, sizeof(T_GAP_V3_NOTIF_TEST)); + } + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint8_t local_bd_type; + uint8_t features[8]; + uint8_t remote_bd_type; + le_get_conn_param(GAP_PARAM_CONN_LOCAL_BD_TYPE, &local_bd_type, conn_id); + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR_TYPE, &remote_bd_type, conn_id); + APP_PRINT_INFO3("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d", + conn_id, local_bd_type, remote_bd_type); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif +#if F_BT_LE_READ_REMOTE_FEATS + le_get_conn_param(GAP_PARAM_CONN_REMOTE_FEATURES, &features, conn_id); +#endif +#if F_BT_LE_5_0_CSA2_SUPPORT + { + uint8_t csa; + le_get_conn_param(GAP_PARAM_CONN_CHANN_ALGORITHM, &csa, conn_id); + APP_PRINT_INFO1("GAP_CONN_STATE_CONNECTED: csa %d", csa); + } +#endif + data_uart_print("connected success conn_id = %d, local_bd_type %d\r\n", conn_id, + local_bd_type); + if (gap_test_case == GAP_TC_09_SLAVE_LATENCY) + { + le_update_conn_param(conn_id, 10, 10, 50, 500, 19, 19); + } + if (test_case_id == TC_0004_CON_TX + || test_case_id == TC_0005_CON_RX) + { + os_timer_start(&auto_test_timer); + } + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + data_uart_print("pair start\r\n"); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_print("Pair success\r\n"); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); +#if F_BT_GAP_KEY_MANAGER_SUPPORT + { + uint8_t addr[6]; + T_GAP_REMOTE_ADDR_TYPE bd_type; + uint8_t resolved_addr[6]; + T_GAP_IDENT_ADDR_TYPE resolved_bd_type; + le_get_conn_addr(conn_id, addr, &bd_type); + if (bd_type == GAP_REMOTE_ADDR_LE_RANDOM) + { + if (le_resolve_random_address(addr, resolved_addr, &resolved_bd_type)) + { + APP_PRINT_INFO2("GAP_AUTHEN_STATE_COMPLETE: resolved_addr %s, resolved_addr_type %d", + TRACE_BDADDR(resolved_addr), resolved_bd_type); + } + else + { + APP_PRINT_INFO0("GAP_AUTHEN_STATE_COMPLETE: resolved addr failed"); + } + } + } +#endif + } + else + { + data_uart_print("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + data_uart_print("conn param update success\r\n"); + APP_PRINT_INFO4("app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + data_uart_print("conn param update fail\r\n"); + APP_PRINT_ERROR2("app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + } + break; + default: + break; + } +} + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void app_handle_ext_adv_state_evt(uint8_t adv_handle, T_GAP_EXT_ADV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_ext_adv_state_evt: adv_handle = %d newState = %d", + adv_handle, new_state); + switch (new_state) + { + /*device is disconnected.*/ + case EXT_ADV_STATE_IDLE: + { + APP_PRINT_INFO2("EXT_ADV_STATE_IDLE: adv_handle %d, cause 0x%x", + adv_handle, cause); + } + break; + + /*device is connected*/ + case EXT_ADV_STATE_ADVERTISING: + { + APP_PRINT_INFO2("EXT_ADV_STATE_ADVERTISING: adv_handle %d, cause 0x%x", + adv_handle, cause); + } + break; + + /*error comes here*/ + default: + break; + } +} +#endif +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + data_uart_print("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + data_uart_print("GAP_MSG_LE_BOND_OOB_INPUT conn id=%d\r\n", conn_id); + //uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + //le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + //le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case GAP_MSG_LE_EXT_ADV_STATE_CHANGE: + { + app_handle_ext_adv_state_evt(gap_msg.msg_data.gap_ext_adv_state_change.adv_handle, + (T_GAP_EXT_ADV_STATE)gap_msg.msg_data.gap_ext_adv_state_change.new_state, + gap_msg.msg_data.gap_ext_adv_state_change.cause); + } + break; +#endif + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Use 16 bit uuid to filter scan information + * @param[in] uuid 16 bit UUID. + * @param[in] scan_info point to scan information data. + * @return filter result + * @retval true found success + * @retval false not found + */ +bool filter_scan_info_by_uuid(uint16_t uuid, T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *p_uuid); + if (*p_uuid == uuid) + { + return true; + } + p_uuid++; + i -= 2; + } + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} + +#if F_BT_LE_APP_KEY_MANAGER +void app_handle_authen_result_ind(T_LE_AUTHEN_RESULT_IND *auth_ind) +{ + APP_PRINT_INFO5("app_handle_authen_result_ind: bd_addr %s, remote_addr_type %d, key_len %d, key_type %d, cause 0x%x", + TRACE_BDADDR(auth_ind->bd_addr), + auth_ind->remote_addr_type, + auth_ind->key_len, + auth_ind->key_type, + auth_ind->cause); + le_bond_authen_result_confirm(auth_ind->bd_addr, auth_ind->remote_addr_type, + auth_ind->key_type, GAP_CFM_CAUSE_ACCEPT); +} +void app_handle_authen_key_req_ind(T_LE_AUTHEN_KEY_REQ_IND *key_req_ind) +{ + APP_PRINT_INFO3("app_handle_authen_key_req_ind: bd_addr %s, remote_addr_type %d, key_type %d", + TRACE_BDADDR(key_req_ind->bd_addr), + key_req_ind->remote_addr_type, + key_req_ind->key_type); + le_bond_authen_key_req_confirm(key_req_ind->bd_addr, + key_req_ind->remote_addr_type, + 0, + NULL, + key_req_ind->key_type, + GAP_CFM_CAUSE_REJECT + ); +} +void app_handle_gatt_server_store_ind(T_LE_GATT_SERVER_STORE_IND *store_ind) +{ + APP_PRINT_INFO4("app_handle_gatt_server_store_ind: bd_addr %s, remote_addr_type %d, op %d, data_len %d", + TRACE_BDADDR(store_ind->bd_addr), + store_ind->remote_addr_type, + store_ind->op, + store_ind->data_len); + le_bond_gatt_server_store_confirm(store_ind->op, + store_ind->bd_addr, + store_ind->remote_addr_type, + 0, + NULL, + GAP_CFM_CAUSE_REJECT + ); +} +#endif + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, max_tx_octets 0x%x, max_tx_time 0x%x, max_rx_octets 0x%x, max_rx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time, + p_data->p_le_data_len_change_info->max_rx_octets, + p_data->p_le_data_len_change_info->max_rx_time); + break; + + case GAP_MSG_LE_SET_DATA_LEN: + APP_PRINT_INFO2("GAP_MSG_LE_SET_DATA_LEN: conn_id 0x%x, cause 0x%x", + p_data->p_le_set_data_len_rsp->conn_id, + p_data->p_le_set_data_len_rsp->cause); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + + /* User can split interested information by using the function as follow. */ + if (filter_scan_info_by_uuid(GATT_UUID_SIMPLE_PROFILE, p_data->p_le_scan_info)) + { + APP_PRINT_INFO0("Found simple ble service"); + link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type); + } + /* If you want to parse the scan info, please reference function app_parse_scan_info in observer app. */ + break; +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + if (p_data->p_le_conn_update_ind->conn_latency > 60)//only used for test + { + result = APP_RESULT_REJECT; + } + else + { + result = APP_RESULT_ACCEPT; + } + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif +#if F_BT_LE_READ_CHANN_MAP + case GAP_MSG_LE_READ_CHANN_MAP: + APP_PRINT_INFO7("GAP_MSG_LE_READ_CHANN_MAP: conn_id 0x%x, cause 0x%x, map[0x%x:0x%x:0x%x:0x%x:0x%x]", + p_data->p_le_read_chann_map_rsp->conn_id, + p_data->p_le_read_chann_map_rsp->cause, + p_data->p_le_read_chann_map_rsp->channel_map[0], + p_data->p_le_read_chann_map_rsp->channel_map[1], + p_data->p_le_read_chann_map_rsp->channel_map[2], + p_data->p_le_read_chann_map_rsp->channel_map[3], + p_data->p_le_read_chann_map_rsp->channel_map[4]); + break; +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + case GAP_MSG_LE_ADV_READ_TX_POWER: + APP_PRINT_INFO2("GAP_MSG_LE_ADV_READ_TX_POWER: cause 0x%x, tx_power_level 0x%x", + p_data->p_le_adv_read_tx_power_rsp->cause, + p_data->p_le_adv_read_tx_power_rsp->tx_power_level); + break; +#endif + + case GAP_MSG_LE_SET_RAND_ADDR: + APP_PRINT_INFO1("GAP_MSG_LE_SET_RAND_ADDR: cause 0x%x", + p_data->p_le_set_rand_addr_rsp->cause); + break; + + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + break; +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; +#endif + case GAP_MSG_LE_CREATE_CONN_IND: + APP_PRINT_INFO0("GAP_MSG_LE_CREATE_CONN_IND"); + result = APP_RESULT_ACCEPT; + break; +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + case GAP_MSG_LE_KEYPRESS_NOTIFY: + APP_PRINT_INFO2("GAP_MSG_LE_KEYPRESS_NOTIFY:conn %d, cause 0x%x", + p_data->p_le_keypress_notify_rsp->conn_id, p_data->p_le_keypress_notify_rsp->cause); + break; + + case GAP_MSG_LE_KEYPRESS_NOTIFY_INFO: + APP_PRINT_INFO2("GAP_MSG_LE_KEYPRESS_NOTIFY_INFO:conn %d, type 0x%x", + p_data->p_le_keypress_notify_info->conn_id, p_data->p_le_keypress_notify_info->event_type); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; +#endif +#if F_BT_LE_READ_REMOTE_FEATS + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + case GAP_MSG_LE_EXT_ADV_REPORT_INFO: + APP_PRINT_INFO6("GAP_MSG_LE_EXT_ADV_REPORT_INFO:connectable %d, scannable %d, direct %d, scan response %d, legacy %d, data status 0x%x", + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_CONNECTABLE_ADV, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_SCANNABLE_ADV, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_DIRECTED_ADV, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_SCAN_RESPONSE, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_USE_LEGACY_ADV, + p_data->p_le_ext_adv_report_info->data_status); + APP_PRINT_INFO5("GAP_MSG_LE_EXT_ADV_REPORT_INFO:event_type 0x%x, bd_addr %s, addr_type %d, rssi %d, data_len %d", + p_data->p_le_ext_adv_report_info->event_type, + TRACE_BDADDR(p_data->p_le_ext_adv_report_info->bd_addr), + p_data->p_le_ext_adv_report_info->addr_type, + p_data->p_le_ext_adv_report_info->rssi, + p_data->p_le_ext_adv_report_info->data_len); + APP_PRINT_INFO5("GAP_MSG_LE_EXT_ADV_REPORT_INFO:primary_phy %d, secondary_phy %d, adv_sid %d, tx_power %d, peri_adv_interval %d", + p_data->p_le_ext_adv_report_info->primary_phy, + p_data->p_le_ext_adv_report_info->secondary_phy, + p_data->p_le_ext_adv_report_info->adv_sid, + p_data->p_le_ext_adv_report_info->tx_power, + p_data->p_le_ext_adv_report_info->peri_adv_interval); + APP_PRINT_INFO2("GAP_MSG_LE_EXT_ADV_REPORT_INFO:direct_addr_type 0x%x, direct_addr %s", + p_data->p_le_ext_adv_report_info->direct_addr_type, + TRACE_BDADDR(p_data->p_le_ext_adv_report_info->direct_addr)); + link_mgr_add_device(p_data->p_le_ext_adv_report_info->bd_addr, + p_data->p_le_ext_adv_report_info->addr_type); + break; +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case GAP_MSG_LE_EXT_ADV_START_SETTING: + APP_PRINT_INFO3("GAP_MSG_LE_EXT_ADV_START_SETTING:cause 0x%x, flag 0x%x, adv_handle %d", + p_data->p_le_ext_adv_start_setting_rsp->cause, + p_data->p_le_ext_adv_start_setting_rsp->flag, + p_data->p_le_ext_adv_start_setting_rsp->adv_handle); + break; + case GAP_MSG_LE_EXT_ADV_REMOVE_SET: + APP_PRINT_INFO2("GAP_MSG_LE_EXT_ADV_REMOVE_SET:cause 0x%x, adv_handle %d", + p_data->p_le_ext_adv_remove_set_rsp->cause, + p_data->p_le_ext_adv_remove_set_rsp->adv_handle); + break; + case GAP_MSG_LE_EXT_ADV_CLEAR_SET: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_CLEAR_SET:cause 0x%x", + p_data->p_le_ext_adv_clear_set_rsp->cause); + break; + case GAP_MSG_LE_EXT_ADV_ENABLE: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_ENABLE:cause 0x%x", + p_data->le_cause.cause); + break; + case GAP_MSG_LE_EXT_ADV_DISABLE: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_DISABLE:cause 0x%x", + p_data->le_cause.cause); + break; + case GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO:adv_handle %d, scanner_addr_type 0x%x, scanner_addr %s", + p_data->p_le_scan_req_received_info->adv_handle, + p_data->p_le_scan_req_received_info->scanner_addr_type, + TRACE_BDADDR(p_data->p_le_scan_req_received_info->scanner_addr)); + break; +#endif + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO2("GAP_MSG_LE_BOND_MODIFY_INFO: 0x%x, p_entry %p", + p_data->p_le_bond_modify_info->type, p_data->p_le_bond_modify_info->p_entry); +#if F_BT_LE_PRIVACY_SUPPORT + if (gap_test_case == GAP_TC_03_PRIVACY) + { + app_handle_bond_modify_msg(p_data->p_le_bond_modify_info->type, + p_data->p_le_bond_modify_info->p_entry); + } +#endif + break; +#if F_BT_LE_ATT_SIGNED_WRITE_SUPPORT + case GAP_MSG_LE_GATT_SIGNED_STATUS_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_GATT_SIGNED_STATUS_INFO:conn_id %d, cause 0x%x, update_local %d, local_sign_count %d,remote_sign_count %d", + p_data->p_le_gatt_signed_status_info->conn_id, + p_data->p_le_gatt_signed_status_info->cause, + p_data->p_le_gatt_signed_status_info->update_local, + p_data->p_le_gatt_signed_status_info->local_sign_count, + p_data->p_le_gatt_signed_status_info->remote_sign_count); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE: cause 0x%x", + p_data->le_cause.cause); + break; + case GAP_MSG_LE_VENDOR_ADV_3_DATA_SET: + APP_PRINT_INFO2("GAP_MSG_LE_VENDOR_ADV_3_DATA_SET: type %d, cause 0x%x", + p_data->p_le_vendor_adv_3_data_set_rsp->type, + p_data->p_le_vendor_adv_3_data_set_rsp->cause); + break; +#endif +#if F_BT_LE_GAP_MSG_INFO_WAY + case GAP_MSG_LE_GAP_STATE_MSG: + APP_PRINT_INFO0("GAP_MSG_LE_GAP_STATE_MSG"); + app_handle_gap_msg(p_data->p_gap_state_msg); + break; +#endif +#if F_BT_LE_APP_KEY_MANAGER + case GAP_MSG_LE_AUTHEN_RESULT_IND: + app_handle_authen_result_ind(p_data->p_le_authen_result_ind); + break; + case GAP_MSG_LE_AUTHEN_KEY_REQ_IND: + app_handle_authen_key_req_ind(p_data->p_le_authen_key_req_ind); + break; + case GAP_MSG_LE_GATT_SERVER_STORE_IND: + app_handle_gatt_server_store_ind(p_data->p_le_gatt_server_store_ind); + break; +#endif + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + + +/** + * @brief Callback for gap common module to notify app + * @param[in] cb_type callback msy type @ref GAP_COMMON_MSG_TYPE. + * @param[in] p_cb_data point to callback data @ref T_GAP_CB_DATA. + * @retval void + */ +void app_gap_common_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_CB_DATA)); + APP_PRINT_INFO1("app_gap_common_callback: cb_type = %d", cb_type); + switch (cb_type) + { +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_WRITE_AIRPLAN_MODE: + APP_PRINT_INFO1("GAP_MSG_WRITE_AIRPLAN_MODE: cause 0x%x", + cb_data.p_gap_write_airplan_mode_rsp->cause); + break; + case GAP_MSG_READ_AIRPLAN_MODE: + APP_PRINT_INFO2("GAP_MSG_READ_AIRPLAN_MODE: cause 0x%x, mode %d", + cb_data.p_gap_read_airplan_mode_rsp->cause, + cb_data.p_gap_read_airplan_mode_rsp->mode); + break; +#endif +#if F_BT_CONTROLLER_POWER_CONTROL + case GAP_MSG_BT_POWER_ON_RSP: + APP_PRINT_INFO1("GAP_MSG_BT_POWER_ON_RSP: cause 0x%x", + cb_data.p_gap_bt_power_on_rsp->cause); + break; + case GAP_MSG_BT_POWER_OFF_RSP: + APP_PRINT_INFO1("GAP_MSG_BT_POWER_OFF_RSP: cause 0x%x", + cb_data.p_gap_bt_power_off_rsp->cause); + break; +#endif + default: + break; + } + return; +} +#if 0 +void app_gap_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("app_gap_common_callback: cb_type = %d", cb_type); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + APP_PRINT_INFO4("GAP_MSG_VENDOR_CMD_RSP: command 0x%x, cause 0x%x, is_cmpl_evt %d, param_len %d", + cb_data.p_gap_vendor_cmd_rsp->command, + cb_data.p_gap_vendor_cmd_rsp->cause, + cb_data.p_gap_vendor_cmd_rsp->is_cmpl_evt, + cb_data.p_gap_vendor_cmd_rsp->param_len); + break; + case GAP_MSG_VENDOR_EVT_INFO: + APP_PRINT_INFO1("GAP_MSG_VENDOR_EVT_INFO: param_len %d", + cb_data.p_gap_vendor_evt_info->param_len); + break; + default: + break; + } + return; +} +#endif +#if F_BT_GAPS_CHAR_WRITEABLE +/** + * @brief All the BT GAP service callback events are handled in this function + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; + APP_PRINT_INFO2("gap_service_callback conn_id = %d msg_type = %d\n", p_gap_data->conn_id, + p_gap_data->msg_type); + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) + { + switch (p_gap_data->msg_data.opcode) + { + case GAPS_WRITE_DEVICE_NAME: + { + T_LOCAL_NAME device_name; + memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); + device_name.local_name[p_gap_data->msg_data.len] = 0; + flash_save_local_name(&device_name); + } + break; + + case GAPS_WRITE_APPEARANCE: + { + uint16_t appearance_val; + T_LOCAL_APPEARANCE appearance; + + LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); + appearance.local_appearance = appearance_val; + flash_save_local_appearance(&appearance); + } + break; + + default: + break; + } + } + return result; +} +#endif + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + else if (client_id == gaps_client_id) + { + T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data; + switch (p_gaps_cb_data->cb_type) + { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_gaps_cb_data->cb_content.disc_state) + { + case DISC_GAPS_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("app_client_callback: discover gaps procedure done."); + break; + case DISC_GAPS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("app_client_callback: discover gaps request failed."); + break; + default: + break; + } + break; + case GAPS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_gaps_cb_data->cb_content.read_result.type) + { + case GAPS_READ_DEVICE_NAME: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.", + TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value)); + } + else + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_APPEARANCE: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance %d", + p_gaps_cb_data->cb_content.read_result.data.appearance); + } + else + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_CENTRAL_ADDR_RESOLUTION: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d", + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + } + else + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + default: + break; + } + break; + + default: + break; + } + } + else if (client_id == simple_ble_client_id) + { + T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data = (T_SIMP_CLIENT_CB_DATA *)p_data; + uint16_t value_size; + uint8_t *p_value; + switch (p_simp_client_cb_data->cb_type) + { + case SIMP_CLIENT_CB_TYPE_DISC_STATE: + switch (p_simp_client_cb_data->cb_content.disc_state) + { + case DISC_SIMP_DONE: + APP_PRINT_INFO0("app_client_callback: discover simp procedure done."); + break; + case DISC_SIMP_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("app_client_callback: discover simp request failed."); + break; + default: + break; + } + break; + case SIMP_CLIENT_CB_TYPE_READ_RESULT: + switch (p_simp_client_cb_data->cb_content.read_result.type) + { + case SIMP_READ_V1_READ: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_simp_client_cb_data->cb_content.read_result.data.v1_read.value_size; + p_value = p_simp_client_cb_data->cb_content.read_result.data.v1_read.p_value; + APP_PRINT_INFO2("SIMP_READ_V1_READ: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V1_READ: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + break; + case SIMP_READ_V3_NOTIFY_CCCD: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V3_NOTIFY_CCCD: notify %d", + p_simp_client_cb_data->cb_content.read_result.data.v3_notify_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V3_NOTIFY_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + }; + break; + case SIMP_READ_V4_INDICATE_CCCD: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V4_INDICATE_CCCD: indicate %d", + p_simp_client_cb_data->cb_content.read_result.data.v4_indicate_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V4_INDICATE_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + }; + break; + + case SIMP_READ_V8_CCCD: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V8_CCCD: cccd 0x%x", + p_simp_client_cb_data->cb_content.read_result.data.v8_notify_ind_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V8_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + }; + break; + + case SIMP_READ_V7_READ_LONG: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_simp_client_cb_data->cb_content.read_result.data.v7_read.value_size; + p_value = p_simp_client_cb_data->cb_content.read_result.data.v7_read.p_value; + APP_PRINT_INFO2("SIMP_READ_V7_READ_LONG: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V7_READ_LONG: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + break; + + default: + break; + } + break; + + case SIMP_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_simp_client_cb_data->cb_content.write_result.type) + { + case SIMP_WRITE_V2_WRITE: + APP_PRINT_INFO1("SIMP_WRITE_V2_WRITE: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V3_NOTIFY_CCCD: + APP_PRINT_INFO1("SIMP_WRITE_V3_NOTIFY_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V4_INDICATE_CCCD: + APP_PRINT_INFO1("SIMP_WRITE_V4_INDICATE_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V6_WRITE_LONG: + APP_PRINT_INFO1("SIMP_WRITE_V6_WRITE_LONG: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V8_CCCD: + APP_PRINT_INFO1("SIMP_WRITE_V8_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + + case SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + value_size = p_simp_client_cb_data->cb_content.notif_ind_data.data.value_size; + p_value = p_simp_client_cb_data->cb_content.notif_ind_data.data.p_value; + switch (p_simp_client_cb_data->cb_content.notif_ind_data.type) + { + case SIMP_V3_NOTIFY: + APP_PRINT_INFO2("SIMP_V3_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + if (gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + gap_v3_notif_test.v3_rx_num++; + } + break; + case SIMP_V4_INDICATE: + APP_PRINT_INFO2("SIMP_V4_INDICATE: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + case SIMP_V8_INDICATE: + APP_PRINT_INFO2("SIMP_V8_INDICATE: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + case SIMP_V8_NOTIFY: + if (gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + gap_v3_notif_test.v8_rx_num++; + } + APP_PRINT_INFO2("SIMP_V8_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + default: + break; + } + break; + + default: + break; + } + } + + return result; +} +#endif +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id. + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + if (test_case_id == TC_0004_CON_TX) + { + uint8_t data[100] = {0, 1, 2}; + simp_ble_service_send_v3_notify(0, simp_srv_id, data, 100); + } +#if 0 + if (gap_v3_notif_test.v3_tx_conn_id == p_param->event_data.send_data_result.conn_id) + { + uint8_t credit = p_param->event_data.send_data_result.credits; + uint8_t notif_val[244]; + gap_v3_notif_test.v3_tx_cmp_num++; + + for (; credit > 0; credit--) + { + if (gap_v3_notif_test.v3_tx_num == 0) + { + break; + } + memset(notif_val, gap_v3_notif_test.v3_tx_idx, gap_v3_notif_test.v3_tx_len); + if (gap_v3_notif_test.v3_tx_num % 2 == 0 || gap_test_case != GAP_TC_13_V3_V8_TX) + { + + if (simp_ble_service_send_v3_notify(gap_v3_notif_test.v3_tx_conn_id, simp_srv_id, + ¬if_val, + gap_v3_notif_test.v3_tx_len)) + { + gap_v3_notif_test.v3_tx_idx++; + gap_v3_notif_test.v3_tx_num--; + gap_v3_notif_test.v3_tx_cnt++; + } + else + { + break; + } + } + else + { + + if (simp_ble_service_simple_v8_notify(gap_v3_notif_test.v3_tx_conn_id, simp_srv_id, + ¬if_val, + gap_v3_notif_test.v3_tx_len)) + { + gap_v3_notif_test.v3_tx_idx++; + gap_v3_notif_test.v3_tx_num--; + gap_v3_notif_test.v8_tx_cnt++; + } + else + { + break; + } + } + } + } +#endif + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + if (test_case_id == TC_0004_CON_TX) + { + uint8_t data[100] = {0, 1, 2}; + uint8_t credits = 0; + le_get_gap_param(GAP_PARAM_LE_REMAIN_CREDITS, &credits); + for (; credits > 0; credits--) + { + simp_ble_service_send_v3_notify(0, simp_srv_id, data, 100); + } + } + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_DISABLE"); + } + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value = 0x88; + APP_PRINT_INFO1("SIMP_READ_V1: 0x%x", value); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 1, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + + case SIMP_WRITE_V6: + { + APP_PRINT_INFO1("SIMP_WRITE_V6: len = 0x%x", p_simp_cb_data->msg_data.write.len); + data_uart_print("V6 len = %d\r\n", p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } +#if APP_HID_TEST + else if (service_id == hid_srv_id) + { + T_HID_CALLBACK_DATA *p_hid_cb_data = (T_HID_CALLBACK_DATA *)p_data; + + switch (p_hid_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + APP_PRINT_INFO2("SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: index %d, value %d", + p_hid_cb_data->msg_data.not_ind_data.index, + p_hid_cb_data->msg_data.not_ind_data.value); + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_hid_cb_data->msg_data.read_value_index) + { + case GATT_SVC_HID_PROTOCOL_MODE_INDEX: + { + APP_PRINT_INFO1("HID_WRITE_PROTOCOL MODE %d\n", + p_hid_cb_data->msg_data.write_msg.write_parameter.protocol_mode); + break; + } + case GATT_SVC_HID_REPORT_OUTPUT_INDEX: + { + //callback data definition need to modify. + APP_PRINT_INFO1("HID_OUTPUT value %d\n", p_hid_cb_data->msg_data.write_msg.write_parameter.output); + break; + } + default: + break; + } + } + break; + default: + break; + } + } +#endif + return app_result; +} + + +#if F_BT_LE_PRIVACY_SUPPORT +void app_privacy_callback(T_PRI_CB_TYPE type, uint8_t status) +{ + if (type == PRIVACY_STATE_MSGTYPE) + { + APP_PRINT_INFO2("app_privacy_callback: state (%d->%d)", priv_state, status); + priv_state = (T_PRIVACY_STATE)status; + } +} + +void app_handle_bond_modify_msg(T_LE_BOND_MODIFY_TYPE type, T_LE_KEY_ENTRY *p_entry) +{ + APP_PRINT_INFO1("app_handle_bond_modify_msg GAP_MSG_LE_BOND_MODIFY_INFO:type=0x%x", + type); + if (type == LE_BOND_CLEAR) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_CLEAR, GAP_IDENT_ADDR_PUBLIC, + NULL); + privacy_handle_pending_resolving_list(); + } + else if (type == LE_BOND_ADD) + { + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + else if (p_entry->flags & LE_KEY_STORE_LOCAL_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + else + { + } + privacy_handle_pending_resolving_list(); + } + else if (type == LE_BOND_DELETE) + { + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + else if (p_entry->flags & LE_KEY_STORE_LOCAL_IRK_BIT) + { + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, + (T_GAP_IDENT_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + else + { + } + privacy_handle_pending_resolving_list(); + } + else + { + } +} +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CBC_DATA cb_data; + memcpy(&cb_data, p_cbc_data, sizeof(T_LE_CBC_DATA)); + APP_PRINT_TRACE1("app_credit_based_conn_callback: cbc_type = %d", cbc_type); + switch (cbc_type) + { + case GAP_CBC_MSG_LE_CHANN_STATE: + APP_PRINT_INFO4("GAP_CBC_MSG_LE_CHANN_STATE: conn_id %d, cid 0x%x, conn_state %d, cause 0x%x", + cb_data.p_le_chann_state->conn_id, + cb_data.p_le_chann_state->cid, + cb_data.p_le_chann_state->conn_state, + cb_data.p_le_chann_state->cause); + if (cb_data.p_le_chann_state->conn_state == GAP_CHANN_STATE_CONNECTED) + { + uint16_t mtu; + le_cbc_get_chann_param(CBC_CHANN_PARAM_MTU, &mtu, cb_data.p_le_chann_state->cid); + APP_PRINT_INFO1("GAP_CHANN_STATE_CONNECTED: mtu %d", mtu); + } + break; + + case GAP_CBC_MSG_LE_REG_PSM: + APP_PRINT_INFO2("GAP_CBC_MSG_LE_REG_PSM: le_psm 0x%x, cause 0x%x", + cb_data.p_le_reg_psm_rsp->le_psm, + cb_data.p_le_reg_psm_rsp->cause); + break; + + case GAP_CBC_MSG_LE_SET_PSM_SECURITY: + APP_PRINT_INFO1("GAP_CBC_MSG_LE_SET_PSM_SECURITY: cause 0x%x", + cb_data.p_le_set_psm_security_rsp->cause); + break; + + case GAP_CBC_MSG_LE_SEND_DATA: + APP_PRINT_INFO4("GAP_CBC_MSG_LE_SEND_DATA: conn_id %d, cid 0x%x, cause 0x%x, credit %d", + cb_data.p_le_send_data->conn_id, + cb_data.p_le_send_data->cid, + cb_data.p_le_send_data->cause, + cb_data.p_le_send_data->credit); + break; + + case GAP_CBC_MSG_LE_RECEIVE_DATA: + APP_PRINT_INFO3("GAP_CBC_MSG_LE_RECEIVE_DATA: conn_id %d, cid 0x%x, value_len %d", + cb_data.p_le_receive_data->conn_id, + cb_data.p_le_receive_data->cid, + cb_data.p_le_receive_data->value_len); + break; + + default: + break; + } + return result; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/gap_test_app.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/gap_test_app.h new file mode 100644 index 00000000..8026fc23 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/gap_test_app.h @@ -0,0 +1,132 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_test_app.h + * @brief GAP roles test application implementation + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _GAP_TEST_APP_H_ +#define _GAP_TEST_APP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +#include +#include +#if F_BT_LE_PRIVACY_SUPPORT +#include +#endif +#include + +typedef enum +{ + GAP_TC_00_NORMAL = 0, + GAP_TC_01_ANCS = 1, + GAP_TC_02_GAPS_WRITEABLE = 2, + GAP_TC_03_PRIVACY = 3, + GAP_TC_04_PIN_CODE = 4, + GAP_TC_05_BT5 = 5, + GAP_TC_07_CCCD = 7, + GAP_TC_08_LOCAL_IRK = 8, + GAP_TC_09_SLAVE_LATENCY = 9, + GAP_TC_10_BT41 = 10, + GAP_TC_11_MIN_REM_SCA = 11, + GAP_TC_12_GAP_MSG_CALLBACK = 12, + GAP_TC_13_V3_V8_TX = 13, + GAP_TC_14_SRV_CHANGE = 14, + GAP_TC_15_HID_PROFILE = 15, +} T_GAP_TEST_CASE; + +typedef struct +{ + uint8_t v3_tx_idx; + uint8_t v3_tx_conn_id; + uint8_t v3_tx_len; + uint16_t v3_tx_num; + uint16_t v3_tx_cmp_num; + uint16_t v3_rx_num; + uint16_t v3_tx_cnt; + uint16_t v8_tx_cnt; + uint16_t v8_rx_num; +} T_GAP_V3_NOTIF_TEST; + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_GAP_DEV_STATE gap_dev_state; +extern T_GAP_TEST_CASE gap_test_case; +extern T_GAP_V3_NOTIF_TEST gap_v3_notif_test; +#if F_BT_LE_GATT_CLIENT_SUPPORT +extern T_CLIENT_ID gaps_client_id; /**< Simple ble service client id*/ +extern T_CLIENT_ID simple_ble_client_id; /**< gap service client id*/ +#endif +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID hid_srv_id; + +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#endif +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +void app_gap_common_callback(uint8_t cb_type, void *p_cb_data); +void app_gap_vendor_callback(uint8_t cb_type, void *p_cb_data); + +#if F_BT_GAPS_CHAR_WRITEABLE +T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para); +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +void app_privacy_callback(T_PRI_CB_TYPE type, uint8_t status); +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/link_mgr.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/link_mgr.c new file mode 100644 index 00000000..5ada60a2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/link_mgr.c @@ -0,0 +1,77 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +T_APP_LINK app_link_table[APP_MAX_LINKS]; +T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +uint8_t dev_list_count = 0; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (dev_list_count < APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < dev_list_count; i++) + { + if (memcmp(bd_addr, dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(dev_list[dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + dev_list[dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void link_mgr_clear_device_list(void) +{ + dev_list_count = 0; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/link_mgr.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/link_mgr.h new file mode 100644 index 00000000..d69ffbb8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/link_mgr.h @@ -0,0 +1,79 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _LINK_MANAGER_H_ +#define _LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Define links number. range: 0-4 */ +#define APP_MAX_LINKS 2 +#define APP_HDL_CACHE_LEN 24/** @brief Define device list table size. */ +#define APP_MAX_DEVICE_INFO 15 +typedef struct +{ + uint16_t uuid16; + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ + uint8_t reserved[3]; /**< used to T_GATT_SERVER_DATABASE_INFO four byte alignment*/ + uint16_t hdl_cache[APP_HDL_CACHE_LEN]; +} T_GATT_SERVER_DATABASE_INFO; +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ +#if F_BT_LE_GATT_CLIENT_SUPPORT + T_CLIENT_ID client_id; +#endif + uint8_t end_handle_idx; + uint8_t disc_state; + uint8_t state; + T_GATT_SERVER_DATABASE_INFO server_info; +} T_APP_LINK; +/** + * @brief Device list block defination. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK app_link_table[APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void link_mgr_clear_device_list(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/privacy_mgnt.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/privacy_mgnt.c new file mode 100644 index 00000000..131328f7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/privacy_mgnt.c @@ -0,0 +1,386 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file privacy_mgnt.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#include "trace_app.h" +#include +#include "gap.h" +#include +#if F_BT_LE_PRIVACY_SUPPORT +T_LE_PRIVACY_ENTRY privacy_table[PRIVACY_ENTRY_SIZE]; +bool clear_resolving_list_pending = false; +uint8_t modify_resolving_list_waiting_idx = 0xff; +bool wait_modify_resolving_list_rsp = false; +T_PRIVACY_STATE privacy_state = PRIVACY_STATE_INIT; +static P_FUN_PRIVACY_STATE_CB pfnPrivacyCB = NULL; + +void privacy_init_resolving_list(P_FUN_PRIVACY_STATE_CB p_fun) +{ + APP_PRINT_INFO0("privacy_init_resolving_list"); + uint8_t i; + T_LE_KEY_ENTRY *p_entry; + memset(privacy_table, 0, PRIVACY_ENTRY_SIZE * sizeof(T_LE_PRIVACY_ENTRY)); + pfnPrivacyCB = p_fun; + + for (i = 0; i < bond_storage_num; i++) + { + p_entry = le_find_key_entry_by_idx(i); + if (p_entry != NULL && p_entry->is_used) + { + if (p_entry->flags & LE_KEY_STORE_REMOTE_IRK_BIT) + { + APP_PRINT_INFO2("privacy_init_resolving_list: add BD=%s type=%d", + TRACE_BDADDR(p_entry->resolved_remote_bd.addr), + p_entry->resolved_remote_bd.remote_bd_type); + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, + (T_GAP_IDENT_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + p_entry->resolved_remote_bd.addr); + } + } + } +} + +T_PRIVACY_STATE privacy_handle_pending_resolving_list_int(void) +{ + APP_PRINT_INFO0("privacy_handle_pending_resolving_list"); + uint8_t i; + T_PRIVACY_STATE state = PRIVACY_STATE_BUSY; + if (wait_modify_resolving_list_rsp) + { + APP_PRINT_INFO0("wait rsp"); + return state; + } + if (clear_resolving_list_pending) + { + APP_PRINT_INFO0("clear"); + if (le_privacy_modify_resolv_list(GAP_RESOLV_LIST_OP_CLEAR, GAP_IDENT_ADDR_PUBLIC, + NULL) == GAP_CAUSE_SUCCESS) + { + wait_modify_resolving_list_rsp = true; + return state; + } + else + { + return state; + } + } + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used && privacy_table[i].pending != PRIVACY_RESOLVING_LIST_IDLE) + { + T_GAP_CAUSE status; + if (privacy_table[i].pending == PRIVACY_RESOLVING_LIST_ADD_PENDING) + { + + APP_PRINT_INFO3("add i=%d BD=%s type=%d\n", i, + TRACE_BDADDR(privacy_table[i].addr), + privacy_table[i].remote_bd_type); + status = le_privacy_modify_resolv_list(GAP_RESOLV_LIST_OP_ADD, + privacy_table[i].remote_bd_type, + privacy_table[i].addr); + if (status == GAP_CAUSE_SUCCESS) + { + wait_modify_resolving_list_rsp = true; + modify_resolving_list_waiting_idx = i; + return state; + } + else if (status != GAP_CAUSE_INVALID_STATE) + { + APP_PRINT_INFO1("remove i=%d from pend add\n", i); + memset(&privacy_table[i], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + else + { + return state; + } + } + else + { + APP_PRINT_INFO3("remove i=%d BD=%s type=%d", i, + TRACE_BDADDR(privacy_table[i].addr), + privacy_table[i].remote_bd_type); + status = le_privacy_modify_resolv_list(GAP_RESOLV_LIST_OP_REMOVE, + privacy_table[i].remote_bd_type, + privacy_table[i].addr); + if (status == GAP_CAUSE_SUCCESS) + { + wait_modify_resolving_list_rsp = true; + modify_resolving_list_waiting_idx = i; + return state; + } + else if (status != GAP_CAUSE_INVALID_STATE) + { + APP_PRINT_INFO1("remove i=%d from pend remove\n", i); + memset(&privacy_table[i], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + else + { + return state; + } + } + } + } + APP_PRINT_INFO0("privacy_handle_pending_resolving_list: idle"); + state = PRIVACY_STATE_IDLE; + return state; +} + +T_PRIVACY_STATE privacy_handle_pending_resolving_list(void) +{ + T_PRIVACY_STATE state = privacy_handle_pending_resolving_list_int(); + if (privacy_state != state) + { + privacy_state = state; + if (pfnPrivacyCB) + { + pfnPrivacyCB(PRIVACY_STATE_MSGTYPE, privacy_state); + } + } + return state; +} +void privacy_add_pending_resolving_list(T_GAP_RESOLV_LIST_OP op, + T_GAP_IDENT_ADDR_TYPE addr_type, uint8_t *addr) +{ + APP_PRINT_INFO1("privacy_add_pending_resolving_list op = %d", op); + switch (op) + { + case GAP_RESOLV_LIST_OP_CLEAR: + clear_resolving_list_pending = true; + break; + + case GAP_RESOLV_LIST_OP_ADD: + //if((addr_type == BTIF_RemoteBDTypeLEPublic) + //||(addr_type == BTIF_RemoteBDTypeLEPublicIdentityAddress) + //||(addr_type == BTIF_RemoteBDTypeLERandomIdentityAddress) + //||((addr_type == BTIF_RemoteBDTypeLERandom) && (addr[5]&RANDOM_ADDR_MASK == RANDOM_ADDR_MASK_STATIC))) + { + uint8_t i; + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used) + { + if ((privacy_table[i].remote_bd_type == addr_type) + && (memcmp(privacy_table[i].addr, addr, 6) == 0)) + { + if (!privacy_table[i].is_add_to_list) + { + privacy_table[i].pending = PRIVACY_RESOLVING_LIST_ADD_PENDING; + } + break; + } + } + } + if (i != PRIVACY_ENTRY_SIZE) + { + break; + } + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (!privacy_table[i].is_used) + { + privacy_table[i].is_used = true; + privacy_table[i].remote_bd_type = addr_type; + memcpy(privacy_table[i].addr, addr, 6); + privacy_table[i].pending = PRIVACY_RESOLVING_LIST_ADD_PENDING; + break; + } + } + } + break; + + case GAP_RESOLV_LIST_OP_REMOVE: + //if((addr_type == BTIF_RemoteBDTypeLEPublicIdentityAddress) + //||(addr_type == BTIF_RemoteBDTypeLERandomIdentityAddress)) + { + uint8_t i; + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used) + { + if ((privacy_table[i].remote_bd_type == addr_type) + && (memcmp(privacy_table[i].addr, addr, 6) == 0)) + { + if (privacy_table[i].is_add_to_list) + { + privacy_table[i].pending = PRIVACY_RESOLVING_LIST_REMOVE_PENDING; + } + else + { + memset(&privacy_table[i], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + break; + } + } + } + } + break; + default: + break; + } +} + +void privacy_handle_LE_ADDRESS_RESOLUTION_STATUS_INFO_MSGTYPE(T_LE_PRIVACY_RESOLUTION_STATUS_INFO + res_status) +{ + APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_RESOLUTION_STATUS_INFO: status = 0x%x\n", res_status.status); + if (pfnPrivacyCB) + { + pfnPrivacyCB(PRIVACY_RESOLUTION_STATUS_MSGTYPE, res_status.status); + } +} + +void privacy_handle_LE_MODIFY_RESOLVING_LIST_MSGTYPE(T_LE_PRIVACY_MODIFY_RESOLV_LIST_RSP + *pListRsp) +{ + APP_PRINT_INFO2("GAP_MSG_LE_PRIVACY_MODIFY_RESOLV_LIST: operation = 0x%x casue = 0x%x", + pListRsp->operation, pListRsp->cause); + wait_modify_resolving_list_rsp = false; + if (pListRsp->cause != GAP_SUCCESS) + { + if (pListRsp->cause == (HCI_ERR | HCI_ERR_UNKNOWN_CONN_ID) + || pListRsp->cause == (HCI_ERR | HCI_ERR_MEMORY_FULL) + || pListRsp->cause == (HCI_ERR | HCI_ERR_INVALID_PARAM)) + { + memset(&privacy_table[modify_resolving_list_waiting_idx], 0, sizeof(T_LE_PRIVACY_ENTRY)); + } + modify_resolving_list_waiting_idx = 0xff; + } + else + { + if (pListRsp->operation == GAP_RESOLV_LIST_OP_CLEAR) + { + clear_resolving_list_pending = false; + memset(privacy_table, 0, PRIVACY_ENTRY_SIZE * sizeof(T_LE_PRIVACY_ENTRY)); + } + else if (pListRsp->operation == GAP_RESOLV_LIST_OP_ADD) + { + if (modify_resolving_list_waiting_idx < PRIVACY_ENTRY_SIZE) + { + privacy_table[modify_resolving_list_waiting_idx].is_add_to_list = true; + privacy_table[modify_resolving_list_waiting_idx].pending = PRIVACY_RESOLVING_LIST_IDLE; + modify_resolving_list_waiting_idx = 0xff; + } + } + else + { + if (modify_resolving_list_waiting_idx < PRIVACY_ENTRY_SIZE) + { + memset(&privacy_table[modify_resolving_list_waiting_idx], 0, sizeof(T_LE_PRIVACY_ENTRY)); + modify_resolving_list_waiting_idx = 0xff; + } + } + privacy_handle_pending_resolving_list(); + } +} + +void privacy_handle_LE_READ_PEER_RESOLVABLE_ADDRESS_MSGTYPE( + T_LE_PRIVACY_READ_PEER_RESOLV_ADDR_RSP *pLEReadPeerResolvableAddressRsp) +{ + APP_PRINT_INFO2("GAP_MSG_LE_PRIVACY_READ_PEER_RESOLV_ADDR: cause = 0x%x BD=%s", + pLEReadPeerResolvableAddressRsp->cause, + TRACE_BDADDR(pLEReadPeerResolvableAddressRsp->peer_resolv_addr)); +} + +extern bool le_check_local_resolved_address(uint8_t *unresolved_addr, uint8_t *local_irk); +//extern T_LOCAL_IRK gap_local_irk; +void privacy_handle_LE_READ_LOCAL_RESOLVABLE_ADDRESS_MSGTYPE( + T_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR_RSP * + pLEReadLocalResolvableAddressRsp) +{ + APP_PRINT_INFO2("GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR: cause = 0x%x BD=%s", + pLEReadLocalResolvableAddressRsp->cause, + TRACE_BDADDR(pLEReadLocalResolvableAddressRsp->local_resolv_addr)); + if (pLEReadLocalResolvableAddressRsp->cause == 0) + { + //bool is_local = le_check_local_resolved_address(pLEReadLocalResolvableAddressRsp->local_resolv_addr, + //gap_local_irk.local_irk); + //APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR: is_local=%d", + //is_local); + } +} + +void privacy_handle_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_MSGTYPE( + T_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT_RSP *pTimeoutRsp) +{ + APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT: cause = 0x%x", + pTimeoutRsp->cause); +} + +#if 0 +void privacy_handle_LE_BOND_MODIFY_MSGTYPE(P_LE_BOND_MODIFY_INFO pDeleteInfo) +{ + APP_PRINT_INFO2("LE_BOND_MODIFY_MSGTYPE: type = 0x%x bd_addr = %s", + pDeleteInfo->remote_bd_type, TRACE_BDADDR(pDeleteInfo->remote_bd)); + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_REMOVE, pDeleteInfo->remote_bd_type, + pDeleteInfo->remote_bd); + privacy_handle_pending_resolving_list(); +} +#endif + +#if 0 +void privacy_handle_LE_REMOTE_IRK_RECEIVE_MSGTYPE(P_LE_REMOTE_IRK_RECEIVE p_irk) +{ + APP_PRINT_INFO2("LE_REMOTE_IRK_RECEIVE_MSGTYPE: type = 0x%x bd_addr = %s", + p_irk->remote_bd_type, TRACE_BDADDR(p_irk->remote_bd)); + privacy_add_pending_resolving_list(GAP_RESOLV_LIST_OP_ADD, p_irk->remote_bd_type, + p_irk->remote_bd); + privacy_handle_pending_resolving_list(); +} +#endif +void privacy_handle_LE_SET_PRIVACY_MODE_MSGTYPE(T_LE_PRIVACY_SET_MODE_RSP *p_privacy_mode) +{ + APP_PRINT_INFO1("GAP_MSG_LE_PRIVACY_SET_MODE: cause = %d", + p_privacy_mode->cause); +} + +T_APP_RESULT privacy_msg_callback(uint8_t msg_type, T_LE_PRIVACY_CB_DATA msg_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("privacy_msg_callback: msg_type = %d", msg_type); + switch (msg_type) + { + case GAP_MSG_LE_PRIVACY_RESOLUTION_STATUS_INFO: + privacy_handle_LE_ADDRESS_RESOLUTION_STATUS_INFO_MSGTYPE( + msg_data.le_privacy_resolution_status_info); + break; + case GAP_MSG_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT: + privacy_handle_LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT_MSGTYPE( + msg_data.p_le_privacy_set_resolv_priv_addr_timeout_rsp); + break; + + case GAP_MSG_LE_PRIVACY_MODIFY_RESOLV_LIST: + privacy_handle_LE_MODIFY_RESOLVING_LIST_MSGTYPE(msg_data.p_le_privacy_modify_resolv_list_rsp); + break; + case GAP_MSG_LE_PRIVACY_READ_PEER_RESOLV_ADDR: + privacy_handle_LE_READ_PEER_RESOLVABLE_ADDRESS_MSGTYPE( + msg_data.p_le_privacy_read_peer_resolv_addr_rsp); + break; + case GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR: + privacy_handle_LE_READ_LOCAL_RESOLVABLE_ADDRESS_MSGTYPE( + msg_data.p_le_privacy_read_local_resolv_addr_rsp); + break; + //case LE_BOND_DELETE_MSGTYPE: + //privacy_handle_LE_BOND_DELETE_MSGTYPE(msg_data.p_le_bond_delete_info); + //break; + + //case LE_REMOTE_IRK_RECEIVE_MSGTYPE: + //privacy_handle_LE_REMOTE_IRK_RECEIVE_MSGTYPE(msg_data.p_remote_irk_rec); + //break; + case GAP_MSG_LE_PRIVACY_SET_MODE: + privacy_handle_LE_SET_PRIVACY_MODE_MSGTYPE(msg_data.p_le_privacy_set_mode_rsp); + break; + default: + break; + } + return result; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/privacy_mgnt.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/privacy_mgnt.h new file mode 100644 index 00000000..d38861af --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/privacy_mgnt.h @@ -0,0 +1,66 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file privacy_mgnt.h + * @brief privacy managerment. + * @details privacy managerment. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _PRIVACY_MGNT_H_ +#define _PRIVACY_MGNT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#if F_BT_LE_PRIVACY_SUPPORT +#include +#include + +#define PRIVACY_ENTRY_SIZE 4 +#define PRIVACY_RESOLVING_LIST_IDLE 0 +#define PRIVACY_RESOLVING_LIST_ADD_PENDING 1 +#define PRIVACY_RESOLVING_LIST_REMOVE_PENDING 2 +typedef struct +{ + bool is_used; + uint8_t addr[6]; + T_GAP_IDENT_ADDR_TYPE remote_bd_type; + bool is_add_to_list; + uint8_t pending; + +} T_LE_PRIVACY_ENTRY, *P_LE_PRIVACY_ENTRY; + +typedef enum +{ + PRIVACY_STATE_MSGTYPE, + PRIVACY_RESOLUTION_STATUS_MSGTYPE +} T_PRI_CB_TYPE; + +typedef enum +{ + PRIVACY_STATE_INIT, + PRIVACY_STATE_IDLE, //!< Disconnected. + PRIVACY_STATE_BUSY +} T_PRIVACY_STATE; +extern T_LE_PRIVACY_ENTRY privacy_table[PRIVACY_ENTRY_SIZE]; +typedef void(*P_FUN_PRIVACY_STATE_CB)(T_PRI_CB_TYPE type, uint8_t status); + +T_APP_RESULT privacy_msg_callback(uint8_t msg_type, T_LE_PRIVACY_CB_DATA msg_data); +void privacy_init_resolving_list(P_FUN_PRIVACY_STATE_CB p_fun); +T_PRIVACY_STATE privacy_handle_pending_resolving_list(void); +void privacy_add_pending_resolving_list(T_GAP_RESOLV_LIST_OP op, + T_GAP_IDENT_ADDR_TYPE addr_type, uint8_t *addr); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _PRIVACY_MGNT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/test_task.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/test_task.c new file mode 100644 index 00000000..3188c4ed --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/test_task.c @@ -0,0 +1,88 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include + +/*============================================================================* + * Macros + *============================================================================*/ +//! Task priorities +#define TEST_TASK_PRIORITY 1 +//!Task stack size +#define TEST_TASK_STACK_SIZE 256 * 4 + +/*============================================================================* + * Variables + *============================================================================*/ +void *test_task_handle; //!< APP Task handle + +/*============================================================================* + * Functions + *============================================================================*/ +void test_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void test_task_init() +{ + if (os_task_create(&test_task_handle, "test app", test_main_task, 0, TEST_TASK_STACK_SIZE, + TEST_TASK_PRIORITY)) + { + APP_PRINT_INFO0("test_task_init: success"); + } + else + { + APP_PRINT_INFO0("test_task_init: failed"); + } +} + +void test_task_deinit() +{ + if (os_task_delete(test_task_handle)) + { + APP_PRINT_INFO0("test_task_deinit: success"); + } + else + { + APP_PRINT_INFO0("test_task_deinit: failed"); + } + //test_task_handle = NULL; +} + +/** + * @brief App task to handle events & messages + * @param[in] p_params Parameters sending to the task + * @return void + */ +void test_main_task(void *p_param) +{ + while (true) + { + //os_delay(1000); + APP_PRINT_ERROR0("test task"); + } +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/test_task.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/test_task.h new file mode 100644 index 00000000..e862c85e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/test_task.h @@ -0,0 +1,26 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _TEST_TASK_H_ +#define _TEST_TASK_H_ + +/** + * @brief Initialize App task + * @return void + */ +void test_task_init(void); +void test_task_deinit(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/uart_task.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/uart_task.c new file mode 100644 index 00000000..8c50367e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/uart_task.c @@ -0,0 +1,229 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "app_task.h" +#include +#include + +/*============================================================================* + * Macros + *============================================================================*/ +//! Task priorities +#define UART_TASK_PRIORITY 1 +//!Task stack size +#define UART_TASK_STACK_SIZE 256 * 8 + +/*============================================================================* + * Variables + *============================================================================*/ +void *uart_task_handle; //!< APP Task handle +void *uart_evt_queue_handle; //!< Event queue handle +void *uart_io_queue_handle; //!< IO queue handle +void *auto_test_timer; + +/*============================================================================* + * Functions + *============================================================================*/ + +T_CUR_TEST_CASE test_case_id = TC_IDLE; +uint32_t test_cur_count = 0; +uint32_t test_max_count = 0; +uint32_t dump_memory_start; +uint32_t dump_memory_end; + +void uart_main_task(void *p_param); + +void app_send_msg_to_uart_app(T_TEST_PROC_SUBTYPE sub_type, uint16_t cause) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = sub_type; + io_msg.u.param = cause; + + if (os_msg_send(uart_io_queue_handle, &io_msg, 0) == false) + { + APP_PRINT_ERROR1("app_send_msg_to_uart_app msg fail: subtype 0x%x", io_msg.subtype); + } + else if (os_msg_send(uart_evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR1("app_send_msg_to_uart_app event fail: subtype 0x%x", io_msg.subtype); + } +} + +void app_handle_uart_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + uint8_t rx_char; + + switch (msg_type) + { + case IO_MSG_TYPE_UART: + /* We handle user command informations from Data UART in this branch. */ + rx_char = (uint8_t)io_msg.subtype; + user_cmd_collect(&user_cmd_if, &rx_char, sizeof(rx_char), user_cmd_table); + break; + case IO_MSG_TYPE_ANCS: + switch (io_msg.subtype) + { + case TC_START: + { + APP_PRINT_ERROR2("test case[%d] TC_START: test_max_count %d", + test_case_id, test_max_count); + dump_memory_start = os_mem_peek(RAM_TYPE_DATA_ON); + app_send_msg_to_uart_app(TC_DEL_STACK, 0); + } + break; + + case TC_DEL_STACK: + { + APP_PRINT_ERROR2("test case[%d] TC_DEL_STACK: test_cur_count %d", + test_case_id, test_cur_count); + app_deinit(); + upper_task_deinit(); + app_send_msg_to_uart_app(TC_ADD_STACK, 0); + } + break; + + case TC_ADD_STACK: + { + APP_PRINT_ERROR2("test case[%d] TC_ADD_STACK: test_cur_count %d", + test_case_id, test_cur_count); + upper_task_init(); + app_init(); + } + break; + + case TC_STACK_STARTED: + { + test_cur_count++; + APP_PRINT_ERROR2("test case[%d] TC_STACK_STARTED: test_cur_count %d", + test_case_id, test_cur_count); + if (test_cur_count < test_max_count) + { + if (test_case_id == TC_0001_IDLE) + { + app_send_msg_to_uart_app(TC_DEL_STACK, 0); + } + else if (test_case_id == TC_0002_ADV) + { + app_send_msg(0); + } + else if (test_case_id == TC_0003_SCAN) + { + app_send_msg(1); + } + else if (test_case_id == TC_0005_CON_RX) + { + app_send_msg(0); + } + else if (test_case_id == TC_0004_CON_TX) + { + app_send_msg(0); + } + } + else + { + dump_memory_end = os_mem_peek(RAM_TYPE_DATA_ON); + APP_PRINT_ERROR4("test case[%d]: complete test_max_count %d, dump_memory_start %d, dump_memory_end %d", + test_case_id, test_max_count, dump_memory_start, dump_memory_end); + } + } + break; + case TC_START_ADV: + APP_PRINT_ERROR2("test case[%d] TC_START_ADV: test_cur_count %d", + test_case_id, test_cur_count); + if (test_case_id == TC_0002_ADV) + { + app_send_msg_to_uart_app(TC_DEL_STACK, 0); + } + break; + + case TC_START_SCAN: + APP_PRINT_ERROR2("test case[%d] TC_START_SCAN: test_cur_count %d", + test_case_id, test_cur_count); + if (test_case_id == TC_0003_SCAN) + { + app_send_msg_to_uart_app(TC_DEL_STACK, 0); + } + break; + default: + break; + } + break; + default: + break; + } +} + +void auto_test_timeout(void *pxTimer) +{ + APP_PRINT_ERROR2("test case[%d] auto_test_timeout: test_cur_count %d", + test_case_id, test_cur_count); + app_send_msg_to_uart_app(TC_DEL_STACK, 0); +} +/** + * @brief Initialize App task + * @return void + */ +void uart_task_init() +{ + os_timer_create(&auto_test_timer, "auto test timer", 1, 1000, false, auto_test_timeout); + os_task_create(&uart_task_handle, "uart app", uart_main_task, 0, UART_TASK_STACK_SIZE, + UART_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_params Parameters sending to the task + * @return void + */ +void uart_main_task(void *p_param) +{ + uint8_t event; + + os_msg_queue_create(&uart_io_queue_handle, 0x20, sizeof(T_IO_MSG)); + os_msg_queue_create(&uart_evt_queue_handle, 0x20, sizeof(uint8_t)); + + data_uart_init(uart_evt_queue_handle, uart_io_queue_handle); + user_cmd_init(&user_cmd_if, "gap_test"); + + while (true) + { + if (os_msg_recv(uart_evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(uart_io_queue_handle, &io_msg, 0) == true) + { + app_handle_uart_msg(io_msg); + } + } + } + } +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/uart_task.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/uart_task.h new file mode 100644 index 00000000..1fb8b53b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/uart_task.h @@ -0,0 +1,55 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _UART_TASK_H_ +#define _UART_TASK_H_ + + +typedef enum +{ + TC_IDLE = 0x0000, + TC_0001_IDLE = 1, + TC_0002_ADV, + TC_0003_SCAN, + TC_0004_CON_TX, + TC_0005_CON_RX, + + TC_MAX = 65535 +} T_CUR_TEST_CASE; + +typedef enum +{ + TC_START = 0x0000, + TC_DEL_STACK, + TC_ADD_STACK, + TC_STACK_STARTED, + TC_START_ADV, + TC_START_SCAN, + + TC_END +} T_TEST_PROC_SUBTYPE; + +extern T_CUR_TEST_CASE test_case_id; +extern uint32_t test_cur_count; +extern uint32_t test_max_count; +extern void *auto_test_timer; +void app_send_msg_to_uart_app(T_TEST_PROC_SUBTYPE sub_type, uint16_t cause); +/** + * @brief Initialize App task + * @return void + */ +void uart_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/user_cmd.c b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/user_cmd.c new file mode 100644 index 00000000..ba9cbad8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/user_cmd.c @@ -0,0 +1,3252 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file user_cmd.c + * @brief User defined test commands. + * @details User command interfaces. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +#include +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#if F_BT_ANCS_CLIENT_SUPPORT +#include +#include +#endif +#if F_BT_LE_PRIVACY_SUPPORT +#include +#include +#endif +#if F_BT_DLPS_EN +#include +#include +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#include +#endif +#if APP_HID_TEST +#include +#endif +#if F_BT_LE_6_0_AOA_AOD_SUPPORT +#include +#endif +/*common*/ +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI +//#include +#endif + +#ifdef AMEBAD_BOARD +#include "ameba_soc.h" +#endif +#if APP_HID_TEST +#include +#endif +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief User command interface data, used to parse the commands from Data UART. */ +T_USER_CMD_IF user_cmd_if; + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +// GAP - SCAN RSP data (max size = 31 bytes) +static const uint8_t ext_scan_response[] = +{ + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + 0x03, + GAP_ADTYPE_APPEARANCE, + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +// best kept short to conserve power while advertisting) +static const uint8_t ext_adv_data[] = +{ + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + + 0x03, + GAP_ADTYPE_APPEARANCE, + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + + 0x0C, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'B', '3', '_', 'G', 'a', 'p', 'T', 'e', 's', 't' +}; + +static const uint8_t ext_large_adv_data[] = +{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4 +}; + +/* Reduce length of ext_large_scan_data to 247 for testing two advertising sets simultaneously. + + Because another advertising set of connectable and scannable undirected advertisement with + scan response data and advertising data will use three adv tasks. So only three adv tasks could + be used by scannable undirected advertisement with extended advertising PDUs. */ +static const uint8_t ext_large_scan_data[] = +{ + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 7 +}; +#if 0 +, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1 +}; +#endif +#endif + +/*============================================================================* + * Functions + *============================================================================*/ + +#if APP_HID_TEST +typedef enum +{ + /****Keyboard*******/ + NO_EVENT = 0x00, + KB_ErrorRollOver = 0x01, + KB_POSTFail = 0x02, + KB_ErrorUndefined = 0x03, + KB_a_A = 0x04, + KB_b_B = 0x05, + KB_c_C = 0x06, + KB_d_D = 0x07, + KB_e_E = 0x08, + KB_f_F = 0x09, + KB_g_G = 0x0A, + KB_h_H = 0x0B, + KB_i_I = 0x0C, + KB_j_J = 0x0D, + KB_k_K = 0x0E, + KB_l_L = 0x0F, + KB_m_M = 0x10, + KB_n_N = 0x11, + KB_o_O = 0x12, + KB_p_P = 0x13, + KB_q_Q = 0x14, + KB_r_R = 0x15, + KB_s_S = 0x16, + KB_t_T = 0x17, + KB_u_U = 0x18, + KB_v_V = 0x19, + KB_w_W = 0x1A, + KB_x_X = 0x1B, + KB_y_Y = 0x1C, + KB_z_Z = 0x1D, + KB_1 = 0x1E, + KB_2 = 0x1F, + KB_3 = 0x20, + KB_4 = 0x21, + KB_5 = 0x22, + KB_6 = 0x23, + KB_7 = 0x24, + KB_8 = 0x25, + KB_9 = 0x26, + KB_0 = 0x27, + KB_Return_ENTER = 0x28, + KB_ESCAPE = 0x29, + KB_DELETE_Backspace = 0x2A, + KB_Tab = 0x2B, + KB_Spacebar = 0x2C, + KB_Minus_Underscore = 0x2D, + KB_Equal_Plus = 0x2E, + KB_LeftBracket_LeftBrace = 0x2F, + KB_RightBracket_RightBrace = 0x30, + KB_BackSlash_VerticalBar = 0x31, + KB_NON_US_Pound = 0x32, + KB_Semicolon_Colon = 0x33, + KB_QuotationMark = 0x34, + KB_GraveAccent_Tilde = 0x35, + KB_Comma_LessThan = 0x36, + KB_Dot_LargerThan = 0x37, + KB_Slash_QuestionMark = 0x38, + KB_CapsLock = 0x39, + KB_F1 = 0x3A, + KB_F2 = 0x3B, + KB_F3 = 0x3C, + KB_F4 = 0x3D, + KB_F5 = 0x3E, + KB_F6 = 0x3F, + KB_F7 = 0x40, + KB_F8 = 0x41, + KB_F9 = 0x42, + KB_F10 = 0x43, + KB_F11 = 0x44, + KB_F12 = 0x45, + KB_PrintScreen = 0x46, + KB_ScrollLock = 0x47, + KB_Pause = 0x48, + KB_Insert = 0x49, + KB_Home = 0x4A, + KB_PageUp = 0x4B, + KB_DeleteForward = 0x4C, + KB_End = 0x4D, + KB_PageDown = 0x4E, + KB_RightArrow = 0x4F, + KB_LeftArrow = 0x50, + KB_DownArrow = 0x51, + KB_UpArrow = 0x52, + + /****Keypad*******/ + KP_NumLock_Clear = 0x53, + KP_Divide = 0x54, + KP_Multiply = 0x55, + KP_Minus = 0x56, + KP_Plus = 0x57, + KP_Enter = 0x58, + KP_1_End = 0x59, + KP_2_DownArrow = 0x5A, + KP_3_PageDn = 0x5B, + KP_4_LeftArrow = 0x5C, + KP_5 = 0x5D, + KP_6_RightArrow = 0x5E, + KP_7_Home = 0x5F, + KP_8_UpArrow = 0x60, + KP_9_PageUp = 0x61, + KP_0_Insert = 0x62, + KP_Dot_Delete = 0x63, + + /****Keyboard*******/ + KB_NON_US_BackSlash = 0x64, + KB_Application = 0x65, + KB_Power = 0x66, + + /****Keypad*******/ + KP_Equal = 0x67, + + /****Keyboard*******/ + KB_F13 = 0x68, + KB_F14 = 0x69, + KB_F15 = 0x6A, + KB_F16 = 0x6B, + KB_F17 = 0x6C, + KB_F18 = 0x6D, + KB_F19 = 0x6E, + KB_F20 = 0x6F, + KB_F21 = 0x70, + KB_F22 = 0x71, + KB_F23 = 0x72, + KB_F24 = 0x73, + KB_Execute = 0x74, + KB_Help = 0x75, + KB_Menu = 0x76, + KB_Select = 0x77, + KB_Stop = 0x78, + KB_Again = 0x79, + KB_Undo = 0x7A, + KB_Cut = 0x7B, + KB_Copy = 0x7C, + KB_Paste = 0x7D, + KB_Find = 0x7E, + KB_Mute = 0x7F, + KB_VolumeUp = 0x80, + KB_VolumeDown = 0x81, + KB_LockingCapsLock = 0x82, + KB_LockingNumLock = 0x83, + KB_LockingScrollLock = 0x84, + KB_Comma = 0x85, + KB_EqualSign = 0x86, + KB_International1 = 0x87, + KB_International2 = 0x88, + KB_International3 = 0x89, + KB_International4 = 0x8A, + KB_International5 = 0x8B, + KB_International6 = 0x8C, + KB_International7 = 0x8D, + KB_International8 = 0x8E, + KB_International9 = 0x8F, + KB_LANG1 = 0x90, + KB_LANG2 = 0x91, + KB_LANG3 = 0x92, + KB_LANG4 = 0x93, + KB_LANG5 = 0x94, + KB_LANG6 = 0x95, + KB_LANG7 = 0x96, + KB_LANG8 = 0x97, + KB_LANG9 = 0x98, + KB_AlternateErase = 0x99, + KB_SysReq_Attention = 0x9A, + KB_Cancel = 0x9B, + KB_Clear = 0x9C, + KB_Prior = 0x9D, + KB_Return = 0x9E, + KB_Separator = 0x9F, + KB_Out = 0xA0, + KB_Oper = 0xA1, + KB_Clear_Again = 0xA2, + KB_CrSel_Props = 0xA3, + KB_ExSel = 0xA4, + + KB_LeftControl = 0xE0, + KB_LeftShift = 0xE1, + KB_LeftAlt = 0xE2, + KB_LeftGUI = 0xE3, + KB_RightControl = 0xE4, + KB_RightShift = 0xE5, + KB_RightAlt = 0xE6, + KB_RightGUI = 0xE7, + +} KEY_USAGE_ID; + +static T_USER_CMD_PARSE_RESULT cmd_key(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t keycount = 0; + uint16_t usage_id = p_parse_value->dw_param[1]; + uint8_t keyboard_data[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t keyboard_release[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + /********Normal Keys**********/ + if (usage_id <= 0xA4) + { + if (keycount < 6) + { + keyboard_data[2 + keycount] = usage_id; + keycount++; + } + } + /*********Modifier Keys********/ + else if ((usage_id >= 0xE0) && (usage_id <= 0xE7)) + { + keyboard_data[0] |= 1 << (usage_id & 0x07); + } + + server_send_data(conn_id, hid_srv_id, GATT_SVC_HID_REPORT_INPUT_INDEX, + keyboard_data, sizeof(keyboard_data), GATT_PDU_TYPE_NOTIFICATION); + server_send_data(conn_id, hid_srv_id, GATT_SVC_HID_REPORT_INPUT_INDEX, + keyboard_release, sizeof(keyboard_release), GATT_PDU_TYPE_NOTIFICATION); + return (RESULT_SUCESS); +} + +#endif + +static T_USER_CMD_PARSE_RESULT cmd_reset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#ifdef AMEBAD_BOARD + u32 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_BOOT_CFG); + Temp |= BIT_SOC_BOOT_PATCH_KM4_RUN; + HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_LP_BOOT_CFG, Temp); + NVIC_SystemReset(); +#endif + return (RESULT_SUCESS); +} +static T_USER_CMD_PARSE_RESULT cmd_vendor(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t param[2]; + param[0] = 3; + param[1] = 1; + + gap_vendor_cmd_req(0xFD83, 2, param); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_reg(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + gap_test_case = (T_GAP_TEST_CASE)p_parse_value->dw_param[0]; + switch (gap_test_case) + { + case GAP_TC_00_NORMAL: //normal mode + break; + +#if F_BT_ANCS_CLIENT_SUPPORT + case GAP_TC_01_ANCS: //test ancs + { + uint8_t link_num; + uint8_t auth_sec_req_enable = true; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + link_num = le_get_max_link_num(); + ancs_init(link_num); + } + break; +#endif +#if F_BT_GAPS_CHAR_WRITEABLE + case GAP_TC_02_GAPS_WRITEABLE: //test gap service write + { + uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; + uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; + T_LOCAL_APPEARANCE appearance_local; + T_LOCAL_NAME local_device_name; + if (flash_load_local_appearance(&appearance_local) == 0) + { + gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance); + } + + if (flash_load_local_name(&local_device_name) == 0) + { + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name); + } + gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop); + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop); + gatt_register_callback((void *)gap_service_callback); + } + break; +#endif + +#if F_BT_LE_PRIVACY_SUPPORT + case GAP_TC_03_PRIVACY://privacy + { + uint8_t auth_sec_req_enable = true; + uint8_t irk_auto = true; + uint16_t privacy_timeout = 0x384; + uint8_t central_address_resolution = 1; + if (p_parse_value->param_count == 2) + { + privacy_timeout = p_parse_value->dw_param[1]; + } + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_GEN_LOCAL_IRK_AUTO, sizeof(uint8_t), &irk_auto); + le_privacy_set_param(GAP_PARAM_PRIVACY_TIMEOUT, sizeof(uint16_t), &privacy_timeout); + le_privacy_register_cb(privacy_msg_callback); + gaps_set_parameter(GAPS_PARAM_CENTRAL_ADDRESS_RESOLUTION, sizeof(central_address_resolution), + ¢ral_address_resolution); + } + break; +#endif + case GAP_TC_04_PIN_CODE: + { + uint32_t auth_fix_passkey = 123456; /* passkey "000000"*/ + uint8_t auth_use_fix_passkey = true; + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(uint32_t), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(uint8_t), &auth_use_fix_passkey); + } + break; +#if F_BT_LE_5_0_SUPPORT + case GAP_TC_05_BT5: + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint8_t use_extended = true; + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_prefer = GAP_PHYS_PREFER_1M_BIT | GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT; + uint8_t rx_prefer = GAP_PHYS_PREFER_1M_BIT | GAP_PHYS_PREFER_CODED_BIT | + GAP_PHYS_PREFER_2M_BIT; +#if F_BT_LE_5_0_AE_ADV_SUPPORT + le_set_gap_param(GAP_PARAM_USE_EXTENDED_ADV, sizeof(use_extended), &use_extended); +#endif + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_prefer), &tx_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_prefer), &rx_prefer); + conn_req_param.scan_interval = 0x20; + conn_req_param.scan_window = 0x20; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + conn_req_param.conn_latency = 1; + le_set_conn_param(GAP_CONN_PARAM_2M, &conn_req_param); + conn_req_param.conn_latency = 2; + le_set_conn_param(GAP_CONN_PARAM_CODED, &conn_req_param); + + { + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + + T_GAP_LE_EXT_SCAN_PARAM extended_scan_param[GAP_EXT_SCAN_MAX_PHYS_NUM]; + extended_scan_param[0].scan_type = GAP_SCAN_MODE_ACTIVE; + extended_scan_param[0].scan_interval = 400; + extended_scan_param[0].scan_window = 200; + + extended_scan_param[1].scan_type = GAP_SCAN_MODE_ACTIVE; + extended_scan_param[1].scan_interval = 440; + extended_scan_param[1].scan_window = 220; + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_phy_param(LE_SCAN_PHY_LE_1M, &extended_scan_param[0]); + le_ext_scan_set_phy_param(LE_SCAN_PHY_LE_CODED, &extended_scan_param[1]); + } +#endif + } + break; +#endif + case GAP_TC_07_CCCD: + { + uint8_t auth_sec_req_enable = true; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + } + break; +#if F_BT_LE_LOCAL_IRK_SETTING_SUPPORT + case GAP_TC_08_LOCAL_IRK: + { + T_LOCAL_IRK le_local_irk = {0, 1, 0, 5, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 9}; + le_bond_set_param(GAP_PARAM_BOND_SET_LOCAL_IRK, GAP_KEY_LEN, le_local_irk.local_irk); + } + break; +#endif + case GAP_TC_09_SLAVE_LATENCY://test slave latency + break; + +#if F_BT_LE_4_1_CBC_SUPPORT + case GAP_TC_10_BT41: + { + uint8_t chann_num = 1; + if (p_parse_value->param_count > 1) + { + chann_num = p_parse_value->dw_param[1]; + } + le_cbc_init(chann_num); + le_cbc_register_app_cb(app_credit_based_conn_callback); + } + break; +#endif +#if F_BT_LE_GAP_MSG_INFO_WAY + case GAP_TC_12_GAP_MSG_CALLBACK: + { + le_gap_msg_info_way(false); + } + break; +#endif + case GAP_TC_13_V3_V8_TX: + break; + + case GAP_TC_14_SRV_CHANGE: //test gap service write + { + uint8_t auth_sec_req_enable = true; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + //gatt_register_callback((void *)gap_service_callback); + } + break; + +#if APP_HID_TEST + case GAP_TC_15_HID_PROFILE: //test gap service write + { + hid_srv_id = hids_add_service((void *)app_profile_callback); + } + break; +#endif + + default: + break; + } + + /* Register BT Stack. */ + if (gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE)) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_dlps(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_DLPS_EN + if (p_parse_value->dw_param[0] == 0) + { + lps_mode_pause(); + data_uart_print("Active Mode\r\n"); + } + else + { + lps_mode_resume(); + data_uart_can_enter_dlps(true); + data_uart_print("LPS Mode\r\n"); + } +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_tracelevel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + if (p_parse_value->dw_param[0] == 1) + { + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 1); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 1); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 1); + data_uart_print("Log On Sucess\r\n"); + } + else if (p_parse_value->dw_param[0] == 0) + { + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 0); + data_uart_print("Log Off Sucess\r\n"); + } + else + { + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 0); + log_module_trace_set(TRACE_MODULE_GAP, TRACE_LEVEL_INFO, true); + log_module_trace_set(TRACE_MODULE_APP, TRACE_LEVEL_INFO, true); + data_uart_print("Log Test Mode\r\n"); + } + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_setlocaltype(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t local_bd_type = p_parse_value->dw_param[0]; + T_GAP_RAND_ADDR_TYPE rand_addr = (T_GAP_RAND_ADDR_TYPE)p_parse_value->dw_param[1]; + uint8_t random_addr[6] = {0}; + random_addr[0] = 0x4E; + random_addr[1] = 0xEF; + random_addr[2] = 0x3B; + random_addr[3] = 0x58; + random_addr[4] = 0xFA; + random_addr[5] = 0xFF; +#if F_BT_LE_PRIVACY_SUPPORT + if (local_bd_type > GAP_LOCAL_ADDR_LE_RAP_OR_RAND) +#else + if (local_bd_type > GAP_LOCAL_ADDR_LE_RANDOM) +#endif + { + return RESULT_CMD_ERR_PARAM; + } + + if (local_bd_type == GAP_LOCAL_ADDR_LE_RANDOM) + { + if (rand_addr != GAP_RAND_ADDR_STATIC) + { + le_gen_rand_addr((T_GAP_RAND_ADDR_TYPE)p_parse_value->dw_param[1], random_addr); + } + le_set_rand_addr(random_addr); + if (rand_addr == GAP_RAND_ADDR_STATIC) + { + le_cfg_local_identity_address(random_addr, GAP_IDENT_ADDR_RAND); + } + data_uart_print("set local random addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + random_addr[5], + random_addr[4], + random_addr[3], + random_addr[2], + random_addr[1], + random_addr[0]); + } +#if F_BT_LE_PRIVACY_SUPPORT + else if (local_bd_type == GAP_LOCAL_ADDR_LE_RAP_OR_RAND) + { + le_set_rand_addr(random_addr); + le_cfg_local_identity_address(random_addr, GAP_IDENT_ADDR_RAND); + } +#endif + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_setstatic(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + uint8_t type = p_parse_value->dw_param[0]; + uint8_t random_addr[6] = {0}; + random_addr[0] = 0x4E; + random_addr[1] = 0xEF; + random_addr[2] = 0x3B; + random_addr[3] = 0x58; + random_addr[4] = 0xFA; + random_addr[5] = 0xFF; + + if (type == 0) + { + random_addr[0] = 0x00; + } + else + { + random_addr[0] = 0x01; + } + data_uart_print("set local random addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + random_addr[5], + random_addr[4], + random_addr[3], + random_addr[2], + random_addr[1], + random_addr[0]); + le_set_rand_addr(random_addr); + le_cfg_local_identity_address(random_addr, GAP_IDENT_ADDR_RAND); + + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + return (RESULT_SUCESS); +} + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_writedefaultdatalen(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint16_t tx_octets = p_parse_value->dw_param[0]; + uint16_t tx_time = p_parse_value->dw_param[1]; + + cause = le_write_default_data_len(tx_octets, tx_time); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_rssiread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_read_rssi(conn_id); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_txpwrset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + return RESULT_SUCESS; +} + +#if F_BT_LE_READ_CHANN_MAP +static T_USER_CMD_PARSE_RESULT cmd_readchanmap(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + cause = le_read_chann_map(conn_id); + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_showcon(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t link_num; + uint8_t conn_id; + T_GAP_CONN_INFO conn_info; + link_num = le_get_max_link_num(); + for (conn_id = 0; conn_id < link_num; conn_id++) + { + if (le_get_conn_info(conn_id, &conn_info)) + { + data_uart_print("ShowCon conn_id %d state 0x%x role %d\r\n", conn_id, + conn_info.conn_state, conn_info.role); + data_uart_print("RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + conn_info.remote_bd[5], conn_info.remote_bd[4], + conn_info.remote_bd[3], conn_info.remote_bd[2], + conn_info.remote_bd[1], conn_info.remote_bd[0], + conn_info.remote_bd_type); + } + } + data_uart_print("active link num %d, idle link num %d\r\n", + le_get_active_link_num(), le_get_idle_link_num()); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_conupdreq(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t conn_interval_min = p_parse_value->dw_param[1]; + uint16_t conn_interval_max = p_parse_value->dw_param[2]; + uint16_t conn_latency = p_parse_value->dw_param[3]; + uint16_t supervision_timeout = p_parse_value->dw_param[4]; + + + cause = le_update_conn_param(conn_id, + conn_interval_min, + conn_interval_max, + conn_latency, + supervision_timeout, + 2 * (conn_interval_min - 1), + 2 * (conn_interval_max - 1) + ); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_disc(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_disconnect(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_setdatalength(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t tx_octets = p_parse_value->dw_param[1]; + uint16_t tx_time = p_parse_value->dw_param[2]; + + cause = le_set_data_len(conn_id, + tx_octets, + tx_time); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +static T_USER_CMD_PARSE_RESULT cmd_wl(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t conn_id = p_parse_value->dw_param[1]; + T_GAP_CONN_INFO conn_info; + + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list(GAP_WHITE_LIST_OP_CLEAR, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + return (T_USER_CMD_PARSE_RESULT)cause; + } + + if (le_get_conn_info(conn_id, &conn_info)) + { + cause = le_modify_white_list(op, conn_info.remote_bd, + (T_GAP_REMOTE_ADDR_TYPE)conn_info.remote_bd_type); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_CMD_ERR_PARAM; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_wldev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t dev_idx = p_parse_value->dw_param[1]; + + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list(GAP_WHITE_LIST_OP_CLEAR, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + return (T_USER_CMD_PARSE_RESULT)cause; + } + + if (dev_idx < dev_list_count) + { + cause = le_modify_white_list(op, dev_list[dev_idx].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[dev_idx].bd_type); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_authmode(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + uint8_t oob_enable = false; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + if (p_parse_value->param_count > 0) + { + auth_flags = p_parse_value->dw_param[0]; + auth_sec_req_flags = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + auth_io_cap = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + auth_sec_req_enable = p_parse_value->dw_param[2]; + } + if (p_parse_value->param_count > 3) + { + oob_enable = p_parse_value->dw_param[3]; + } + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + cause = gap_set_pairable_mode(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_setkeydis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t init_dist = p_parse_value->dw_param[0]; + uint8_t rsp_dist = p_parse_value->dw_param[1]; + le_bond_cfg_local_key_distribute(init_dist, rsp_dist); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_sauth(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_bond_pair(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_userconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT; + T_GAP_CAUSE cause; + if (p_parse_value->dw_param[1] == 0) + { + confirm = GAP_CFM_CAUSE_REJECT; + } + cause = le_bond_user_confirm(conn_id, confirm); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_authkey(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint32_t passcode = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT; + if (passcode > GAP_PASSCODE_MAX) + { + confirm = GAP_CFM_CAUSE_REJECT; + } + cause = le_bond_passkey_input_confirm(conn_id, passcode, + confirm); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_SMP_OOB_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_oob(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t oob_data[GAP_OOB_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; + oob_data[0] = p_parse_value->dw_param[1]; + oob_data[3] = p_parse_value->dw_param[2]; + oob_data[7] = p_parse_value->dw_param[3]; + oob_data[15] = p_parse_value->dw_param[4]; + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + + cause = le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_keypress(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_KEYPRESS_NOTIF_TYPE notify_type = (T_GAP_KEYPRESS_NOTIF_TYPE)p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + cause = le_bond_keypress_notify(conn_id, notify_type); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_bondclear(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_GAP_KEY_MANAGER_SUPPORT + le_bond_clear_all_keys(); +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_bondinfo(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_GAP_KEY_MANAGER_SUPPORT + uint8_t i; + T_LE_KEY_ENTRY *p_entry; + for (i = 0; i < bond_storage_num; i++) + { + p_entry = le_find_key_entry_by_idx(i); + if (p_entry != NULL) + { + data_uart_print("bond_dev[%d]: bd 0x%02x%02x%02x%02x%02x%02x, addr_type %d, flags 0x%x\r\n", + p_entry->idx, + p_entry->remote_bd.addr[5], + p_entry->remote_bd.addr[4], + p_entry->remote_bd.addr[3], + p_entry->remote_bd.addr[2], + p_entry->remote_bd.addr[1], + p_entry->remote_bd.addr[0], + p_entry->remote_bd.remote_bd_type, + p_entry->flags); + } + } +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_scan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + if (p_parse_value->param_count > 0) + { + scan_filter_policy = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + scan_filter_duplicate = p_parse_value->dw_param[1]; + } + + link_mgr_clear_device_list(); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + cause = le_scan_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_scan_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_showdev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + data_uart_print("Advertising and Scan response: filter uuid = 0xA00A dev list\r\n"); + for (i = 0; i < dev_list_count; i++) + { + data_uart_print("RemoteBd[%d] = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + i, + dev_list[i].bd_addr[5], dev_list[i].bd_addr[4], + dev_list[i].bd_addr[3], dev_list[i].bd_addr[2], + dev_list[i].bd_addr[1], dev_list[i].bd_addr[0], + dev_list[i].bd_type); + if (dev_list[i].bd_type == GAP_REMOTE_ADDR_LE_RANDOM) + { + uint8_t addr = dev_list[i].bd_addr[5] & RANDOM_ADDR_MASK; + if (addr == RANDOM_ADDR_MASK_STATIC) + { + data_uart_print("Static Random Addr\r\n"); + } + else if (addr == RANDOM_ADDR_MASK_RESOLVABLE) + { + data_uart_print("Resolv Random Addr\r\n"); + } + else if (addr == RANDOM_ADDR_MASK_NON_RESOLVABLE) + { + data_uart_print("Non-resolv Random Addr\r\n"); + } + else + { + data_uart_print("Unknown Random Addr\r\n"); + } + } + } + + return (RESULT_SUCESS); +} + +#if F_BT_LE_GAP_CENTRAL_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_con(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t addr[6] = {0}; + uint8_t addr_len; + uint8_t addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + if (p_parse_value->param_count >= 7) + { + addr_type = p_parse_value->dw_param[6]; + } + + cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, addr, (T_GAP_REMOTE_ADDR_TYPE)addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_condev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t dev_idx = p_parse_value->dw_param[0]; + if (dev_idx < dev_list_count) + { + T_GAP_CAUSE cause; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + T_GAP_LOCAL_ADDR_TYPE local_addr_type = (T_GAP_LOCAL_ADDR_TYPE)p_parse_value->dw_param[1]; + uint8_t init_phys = 0; +#if F_BT_LE_5_0_SUPPORT + uint32_t mode = p_parse_value->dw_param[2]; + + switch (mode) + { + case 0x000: + init_phys = 0; + break; + case 0x001: + init_phys = GAP_PHYS_CONN_INIT_1M_BIT; + break; + case 0x010: + init_phys = GAP_PHYS_CONN_INIT_2M_BIT; + break; + case 0x011: + init_phys = GAP_PHYS_CONN_INIT_2M_BIT | GAP_PHYS_CONN_INIT_1M_BIT; + break; + case 0x100: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT; + break; + case 0x101: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT | GAP_PHYS_CONN_INIT_1M_BIT; + break; + case 0x110: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT | GAP_PHYS_CONN_INIT_2M_BIT; + break; + case 0x111: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT | + GAP_PHYS_CONN_INIT_2M_BIT | + GAP_PHYS_CONN_INIT_1M_BIT; + break; + + default: + break; + } +#endif + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + cause = le_connect(init_phys, dev_list[dev_idx].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[dev_idx].bd_type, + local_addr_type, + 1000); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_chanclassset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t chan_map[5] = {0}; + uint8_t i; + for (i = 0; i < 5; i++) + { + chan_map[i] = (uint8_t)p_parse_value->dw_param[i]; + } + + chan_map[4] = chan_map[4] & 0x1F; + + cause = le_set_host_chann_classif(chan_map); + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_srvdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + cause = client_all_primary_srv_discovery(conn_id, CLIENT_PROFILE_GENERAL_ID); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_gapdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool ret = gaps_start_discovery(conn_id); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_gapread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAPS_READ_TYPE read_type = (T_GAPS_READ_TYPE)p_parse_value->dw_param[1]; + bool ret = gaps_read(conn_id, read_type); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool ret = simp_ble_client_start_discovery(conn_id); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char to be read. */ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool ret; + T_SIMP_READ_TYPE read_type = (T_SIMP_READ_TYPE)p_parse_value->dw_param[1]; + /* Read by handle or UUID, 1--by UUID, 0--by handle. */ + uint8_t read_pattern = (uint8_t)p_parse_value->dw_param[2]; + + if (read_pattern) + { + ret = simp_ble_client_read_by_uuid(conn_id, read_type); + } + else + { + ret = simp_ble_client_read_by_handle(conn_id, read_type); + } + + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpcccd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char CCCD command. */ + bool ret = false; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t type = p_parse_value->dw_param[1]; + /* Enable or disable, 1--enable, 0--disable. */ + uint16_t cccd_data = p_parse_value->dw_param[2]; + + switch (type) + { + case 0:/* V3 Notify char notif enable/disable. */ + ret = simp_ble_client_set_v3_notify(conn_id, cccd_data); + break; + case 1:/* V4 Indicate char indicate enable/disable. */ + ret = simp_ble_client_set_v4_ind(conn_id, cccd_data); + break; + case 2: + ret = simp_ble_client_set_v8_cccd(conn_id, cccd_data); + break; + default: + break; + } + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpwrite(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool ret = false; + uint8_t conn_id = p_parse_value->dw_param[0]; + /* Indicate which char to be written. */ + uint8_t write_type = (uint8_t)p_parse_value->dw_param[1]; + uint8_t data[270]; + uint16_t length = 270; + uint16_t i; + for (i = 0; i < 270; i++) + { + data[i] = i; + } + if (p_parse_value->param_count > 2) + { + length = p_parse_value->dw_param[2]; + if (length > 270) + { + length = 270; + } + } + + switch (write_type) + { + case 2:/* Write the V2 Writable char value on peer server. */ + { + T_GATT_WRITE_TYPE type = (T_GATT_WRITE_TYPE)p_parse_value->dw_param[3]; + if (type > GATT_WRITE_TYPE_SIGNED_CMD) + { + return (RESULT_CMD_ERR_PARAM); + } + ret = simp_ble_client_write_v2_char(conn_id, length, data, type); + } + break; + case 3: + { + ret = simp_ble_client_write_v6_char(conn_id, length, data); + } + break; + default: + break; + } + + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simphdl(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN]; + uint8_t hdl_idx; + bool ret = simp_ble_client_get_hdl_cache(conn_id, hdl_cache, + sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN); + + if (ret) + { + for (hdl_idx = HDL_SIMBLE_SRV_START; hdl_idx < HDL_SIMBLE_CACHE_LEN; hdl_idx++) + { + data_uart_print("-->Index %d -- Handle 0x%x\r\n", hdl_idx, hdl_cache[hdl_idx]); + } + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} +#endif +#if F_BT_ANCS_CLIENT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_ancsdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool ret; + uint8_t conn_id = p_parse_value->dw_param[0]; + ret = ancs_start_discovery(conn_id); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_startadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advdata(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t len = p_parse_value->dw_param[0]; + uint8_t value = p_parse_value->dw_param[1]; + uint8_t adv_data[31]; + memset(adv_data, value, len); + le_adv_set_param(GAP_PARAM_ADV_DATA, len, adv_data); + cause = le_adv_update_param(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_adv_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_adv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = 80; + uint16_t adv_int_max = 80; + + if (p_parse_value->param_count > 0) + { + adv_int_min = p_parse_value->dw_param[0]; + adv_int_max = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + adv_filter_policy = p_parse_value->dw_param[1]; + } + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advld(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_LDC_DIRECT_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint16_t adv_int_min = 300; + uint16_t adv_int_max = 320; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t addr_len; + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + adv_direct_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advhd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_HDC_DIRECT_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t addr_len; + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + adv_direct_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_SCAN_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = 300; + uint16_t adv_int_max = 320; + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advnonconn(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = 300; + uint16_t adv_int_max = 320; + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advwl(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_filter_policy = GAP_ADV_FILTER_WHITE_LIST_ALL; + uint8_t wl_addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t wl_addr[GAP_BD_ADDR_LEN] = {0}; + + //get connected device address and address type + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR_TYPE, &wl_addr_type); + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR, &wl_addr); + + le_modify_white_list(GAP_WHITE_LIST_OP_ADD, wl_addr, (T_GAP_REMOTE_ADDR_TYPE)wl_addr_type); + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_readadvpwr(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_adv_read_tx_power(); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +static T_USER_CMD_PARSE_RESULT cmd_latency(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool disable = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + + cause = le_disable_slave_latency(conn_id, disable); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_epassed(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char to be written. */ + bool enable = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + cause = le_update_passed_chann_map(enable); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_srvchange(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + gatts_service_changed_indicate(conn_id, start_handle, end_handle); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv3notify(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t notif_val[244]; + uint16_t length = p_parse_value->dw_param[1]; + uint16_t tx_num = 0; + + if (length > 244) + { + return RESULT_ERR; + } + memset(notif_val, 1, length); + + if (p_parse_value->param_count > 2) + { + tx_num = p_parse_value->dw_param[2]; + } + +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI + GPIO->DATAOUT |= BIT(18); + GPIO->DATAOUT &= ~BIT(18); +#endif + if (!simp_ble_service_send_v3_notify(conn_id, simp_srv_id, + ¬if_val, + length)) + { + return (RESULT_ERR); + } + if (tx_num > 1) + { + gap_v3_notif_test.v3_tx_idx = 2; + gap_v3_notif_test.v3_tx_num = tx_num - 1; + gap_v3_notif_test.v3_tx_conn_id = conn_id; + gap_v3_notif_test.v3_tx_len = length; + gap_v3_notif_test.v3_tx_cmp_num = 0; + gap_v3_notif_test.v3_rx_num = 0; + gap_v3_notif_test.v8_rx_num = 0; + gap_v3_notif_test.v8_tx_cnt = 0; + gap_v3_notif_test.v3_tx_cnt = 1; + + } +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI + GPIO->DATAOUT |= BIT(18); + GPIO->DATAOUT &= ~BIT(18); +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv3dump(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + data_uart_print("simpv3dump: v3_tx_idx 0x%x, v3_tx_conn_id %d, v3_tx_num %d, v3_tx_cmp_num %d, v3_tx_cnt %d, v8_tx_cnt %d\r\n", + gap_v3_notif_test.v3_tx_idx, + gap_v3_notif_test.v3_tx_conn_id, + gap_v3_notif_test.v3_tx_num, + gap_v3_notif_test.v3_tx_cmp_num, + gap_v3_notif_test.v3_tx_cnt, + gap_v3_notif_test.v8_tx_cnt); + data_uart_print("simpv3dump: v3_rx_num %d, v8_rx_num %d\r\n", + gap_v3_notif_test.v3_rx_num, + gap_v3_notif_test.v8_rx_num); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv4ind(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t ind_val[244]; + uint16_t length = p_parse_value->dw_param[1]; + uint16_t i; + + if (length > 244) + { + return RESULT_ERR; + } + for (i = 0; i < length; i++) + { + ind_val[i] = i; + } + + if (simp_ble_service_send_v4_indicate(conn_id, simp_srv_id, + &ind_val, + length)) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv8notify(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t notify_val = (uint8_t)p_parse_value->dw_param[1]; + + + if (!simp_ble_service_simple_v8_notify(conn_id, simp_srv_id, + ¬ify_val, + 1)) + { + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv8ind(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t ind_val = (uint8_t)p_parse_value->dw_param[1]; + + + if (!simp_ble_service_simple_v8_indicate(conn_id, simp_srv_id, + &ind_val, 1)) + { + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv7len(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint16_t len = p_parse_value->dw_param[0]; + uint8_t data[SIMP_READ_V7_MAX_LEN]; + uint16_t i; + if (len > SIMP_READ_V7_MAX_LEN) + { + return (RESULT_ERR); + } + for (i = 0; i < len; i++) + { + data[i] = i; + } + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V7_LEN, len, data); + + return (RESULT_SUCESS); +} + + +static T_USER_CMD_PARSE_RESULT cmd_simpv2writeconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + + + if (!server_attr_write_confirm(conn_id, + simp_srv_id, + SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX, + APP_RESULT_SUCCESS)) + { + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} + + +#if F_BT_LE_5_0_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_setphy(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + T_GAP_PHYS_OPTIONS phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S8; + T_GAP_CAUSE cause; + + if (p_parse_value->dw_param[1] == 0) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_1M_BIT; + rx_phys = GAP_PHYS_PREFER_1M_BIT; + } + else if (p_parse_value->dw_param[1] == 1) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_2M_BIT; + rx_phys = GAP_PHYS_PREFER_2M_BIT; + } + else if (p_parse_value->dw_param[1] == 2) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_CODED_BIT; + rx_phys = GAP_PHYS_PREFER_CODED_BIT; + phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S8; + } + else if (p_parse_value->dw_param[1] == 3) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_CODED_BIT; + rx_phys = GAP_PHYS_PREFER_CODED_BIT; + phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S2; + } + else + { + all_phys = GAP_PHYS_NO_PREFER_TX_BIT; + tx_phys = GAP_PHYS_PREFER_2M_BIT; + rx_phys = GAP_PHYS_PREFER_1M_BIT; + } + cause = le_set_phy(conn_id, all_phys, tx_phys, rx_phys, phy_options); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_escan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint16_t ext_scan_duration = 0; + uint16_t ext_scan_period = 0; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + uint8_t mode = p_parse_value->dw_param[0]; + + link_mgr_clear_device_list(); + if (mode == 1) + { + ext_scan_duration = 500; + } + else if (mode == 2) + { + ext_scan_duration = 500; + ext_scan_period = 8; + ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLED_RESET_FOR_EACH_PERIOD; + } + else if (mode == 3) + { + ext_scan_filter_policy = GAP_SCAN_FILTER_WHITE_LIST; + } + else if (mode == 4) + { + scan_phys = p_parse_value->dw_param[1]; + } + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_DURATION, sizeof(ext_scan_duration), + &ext_scan_duration); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PERIOD, sizeof(ext_scan_period), + &ext_scan_period); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + cause = le_ext_scan_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopescan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_ext_scan_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_seadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle = p_parse_value->dw_param[0]; + uint16_t duration = 0; + uint8_t max_num = 0; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 1) + { + duration = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + max_num = p_parse_value->dw_param[2]; + } + + cause = le_ext_adv_set_adv_enable_param(adv_handle, duration, max_num); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_ueadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + uint8_t update_flags = EXT_ADV_SET_ADV_PARAS | EXT_ADV_SET_ADV_DATA | EXT_ADV_SET_SCAN_RSP_DATA; + T_GAP_CAUSE cause; + uint8_t adv_handle; + uint16_t adv_event_prop = (uint16_t) LE_EXT_ADV_LEGACY_ADV_CONN_SCAN_UNDIRECTED; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t *p_peer_address = NULL; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_2M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + + if (p_parse_value->param_count > 1) + { + update_flags = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + own_address_type = (T_GAP_LOCAL_ADDR_TYPE)p_parse_value->dw_param[2]; + } + if (idx == 0) + { + adv_handle = le_ext_adv_create_adv_handle(); + le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_adv_data), (uint8_t *)ext_adv_data); + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_scan_response), + (uint8_t *)ext_scan_response); + } + else + { + adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_SCAN_UNDIRECTED; + switch (idx) + { + case 0x11: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + case 0x12: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x13: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + case 0x31: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + + case 0x32: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x33: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + default: + adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_SCAN_UNDIRECTED; + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + break; + } + if (p_parse_value->param_count > 3) + { + adv_event_prop = p_parse_value->dw_param[3]; + } +#if 0 + if (adv_event_prop & GAP_EXT_ADV_EVT_PROP_SCANNABLE_ADV == 0) + { + update_flags &= ~EXT_ADV_SET_SCAN_RSP_DATA; + + } + + if (adv_event_prop & GAP_EXT_ADV_EVT_PROP_CONNECTABLE_ADV == 0) + { + update_flags &= ~EXT_ADV_SET_ADV_DATA; + } +#endif + adv_handle = le_ext_adv_create_adv_handle(); + le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + } + if (own_address_type == GAP_LOCAL_ADDR_LE_RANDOM) + { + uint8_t rand_addr[6]; + le_gen_rand_addr(GAP_RAND_ADDR_STATIC, rand_addr); + cause = le_ext_adv_set_random(adv_handle, rand_addr); + } + else if (own_address_type == GAP_LOCAL_ADDR_LE_RAP_OR_RAND) + { + uint8_t rand_addr[6]; + rand_addr[0] = 0x4E; + rand_addr[1] = 0x11; + rand_addr[2] = 0x22; + rand_addr[3] = 0x33; + rand_addr[4] = 0x44; + rand_addr[5] = adv_handle; + cause = le_ext_adv_set_random(adv_handle, rand_addr); + le_cfg_local_identity_address(rand_addr, GAP_IDENT_ADDR_RAND); + } + cause = le_ext_adv_start_setting(adv_handle, update_flags); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_uedadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[6]; + T_GAP_CAUSE cause; + uint8_t adv_handle; + uint16_t adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_NON_SCAN_NON_CONN_DIRECTED; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t peer_address[GAP_BD_ADDR_LEN] = {0}; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_1M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + uint8_t peer_address_len; + + for (peer_address_len = 0; peer_address_len < GAP_BD_ADDR_LEN; peer_address_len++) + { + peer_address[peer_address_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - peer_address_len - 1]; + } + + if (p_parse_value->param_count > 7) + { + adv_event_prop = p_parse_value->dw_param[7]; + + } + switch (idx) + { + case 0x11: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + case 0x12: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x13: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + case 0x31: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + + case 0x32: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x33: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + default: + adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_SCAN_UNDIRECTED; + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + break; + } + + adv_handle = le_ext_adv_create_adv_handle(); + le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + cause = le_ext_adv_start_setting(adv_handle, EXT_ADV_SET_AUTO); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_eadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle[4] = {0}; + uint8_t num_of_sets = 1; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 0) + { + adv_handle[0] = p_parse_value->dw_param[0]; + num_of_sets = 1; + } + if (p_parse_value->param_count > 1) + { + adv_handle[1] = p_parse_value->dw_param[1]; + num_of_sets = 2; + } + if (p_parse_value->param_count > 2) + { + adv_handle[2] = p_parse_value->dw_param[2]; + num_of_sets = 3; + } + if (p_parse_value->param_count > 3) + { + adv_handle[3] = p_parse_value->dw_param[3]; + num_of_sets = 4; + } + cause = le_ext_adv_enable(num_of_sets, adv_handle); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopeadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle[4] = {0}; + uint8_t num_of_sets = 1; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 0) + { + adv_handle[0] = p_parse_value->dw_param[0]; + num_of_sets = 1; + } + if (p_parse_value->param_count > 1) + { + adv_handle[1] = p_parse_value->dw_param[1]; + num_of_sets = 2; + } + if (p_parse_value->param_count > 2) + { + adv_handle[2] = p_parse_value->dw_param[2]; + num_of_sets = 3; + } + if (p_parse_value->param_count > 3) + { + adv_handle[3] = p_parse_value->dw_param[3]; + num_of_sets = 4; + } + cause = le_ext_adv_disable(num_of_sets, adv_handle); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_ceadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_ext_adv_clear_set(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_readv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle = 0; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 0) + { + adv_handle = p_parse_value->dw_param[0]; + } + cause = le_ext_adv_remove_set(adv_handle); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_advrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + T_GAP_CAUSE cause; + + if (p_parse_value->param_count > 0) + { + adv_evt_type = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + adv_filter_policy = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + uint8_t idx = p_parse_value->dw_param[2]; + if (privacy_table[idx].is_used == true) + { + adv_direct_type = privacy_table[idx].remote_bd_type; + memcpy(adv_direct_addr, privacy_table[idx].addr, 6); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + } + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_readlra(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + if (privacy_table[idx].is_used) + { + cause = le_privacy_read_local_resolv_addr((T_GAP_IDENT_ADDR_TYPE)privacy_table[idx].remote_bd_type, + privacy_table[idx].addr); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_readpra(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + if (privacy_table[idx].is_used) + { + cause = le_privacy_read_peer_resolv_addr(privacy_table[idx].remote_bd_type, + privacy_table[idx].addr); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_setrae(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool enable = true; + T_GAP_CAUSE cause; + if (p_parse_value->dw_param[0] == 0) + { + enable = false; + } + cause = le_privacy_set_addr_resolution(enable); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_showrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + data_uart_print("show resolved list\r\n"); + + for (i = 0; i < PRIVACY_ENTRY_SIZE; i++) + { + if (privacy_table[i].is_used) + { + data_uart_print("rel[%d] RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d is_add_to_list=%d pending=%d\r\n", + i, + privacy_table[i].addr[5], privacy_table[i].addr[4], + privacy_table[i].addr[3], privacy_table[i].addr[2], + privacy_table[i].addr[1], privacy_table[i].addr[0], + privacy_table[i].remote_bd_type, + privacy_table[i].is_add_to_list, + privacy_table[i].pending); + } + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_setprivacy(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + uint8_t mode = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + if (privacy_table[idx].is_used) + { + cause = le_privacy_set_mode((T_GAP_IDENT_ADDR_TYPE)privacy_table[idx].remote_bd_type, + privacy_table[idx].addr, + (T_GAP_PRIVACY_MODE)mode); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_CMD_ERR_PARAM; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_wlrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t idx = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list(op, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + } + else + { + if (privacy_table[idx].is_used) + { + cause = le_modify_white_list(op, privacy_table[idx].addr, + (T_GAP_REMOTE_ADDR_TYPE)privacy_table[idx].remote_bd_type); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + } + return (T_USER_CMD_PARSE_RESULT)cause; + +} + +static T_USER_CMD_PARSE_RESULT cmd_conrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + if (privacy_table[idx].is_used) + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + cause = le_connect(0, privacy_table[idx].addr, + (T_GAP_REMOTE_ADDR_TYPE)privacy_table[idx].remote_bd_type, + (T_GAP_LOCAL_ADDR_TYPE)p_parse_value->dw_param[1], + 1000); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_lepsm(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_reg_psm(p_parse_value->dw_param[0], p_parse_value->dw_param[1]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_lesec(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_set_psm_security(p_parse_value->dw_param[0], p_parse_value->dw_param[1], + (T_LE_CBC_SECURITY_MODE)p_parse_value->dw_param[2], p_parse_value->dw_param[3]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_conle(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_create(p_parse_value->dw_param[0], p_parse_value->dw_param[1]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_discle(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_disc(p_parse_value->dw_param[0]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_ledata(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + void *p_buffer; + uint16_t cid = p_parse_value->dw_param[0]; + uint16_t length = p_parse_value->dw_param[1]; + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, 2, length); + + cause = le_cbc_send_data(cid, p_buffer, length); + os_mem_free(p_buffer); + } + else + { + return RESULT_GAP_CAUSE_NO_RESOURCE; + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +#if F_BT_CONTROLLER_POWER_CONTROL +static T_USER_CMD_PARSE_RESULT cmd_poweron(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = gap_bt_power_on(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_poweroff(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = gap_bt_power_off(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +static T_USER_CMD_PARSE_RESULT cmd_taskadd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + test_task_init(); + + return RESULT_SUCESS; +} + +static T_USER_CMD_PARSE_RESULT cmd_taskdel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + test_task_deinit(); + + return RESULT_SUCESS; +} + +static T_USER_CMD_PARSE_RESULT cmd_stackadd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + upper_task_init(); + app_init(); + return RESULT_SUCESS; +} + +static T_USER_CMD_PARSE_RESULT cmd_stackdel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + app_deinit(); + upper_task_deinit(); + return RESULT_SUCESS; +} + +static T_USER_CMD_PARSE_RESULT cmd_tc(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + test_case_id = (T_CUR_TEST_CASE)p_parse_value->dw_param[0]; + test_max_count = p_parse_value->dw_param[1]; + test_cur_count = 0; + app_send_msg_to_uart_app(TC_START, 0); + return RESULT_SUCESS; +} + +static T_USER_CMD_PARSE_RESULT cmd_dump(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint16_t type = p_parse_value->dw_param[0]; + if (type == 0) + { + APP_PRINT_INFO1("os_mem_peek: %d", os_mem_peek(RAM_TYPE_DATA_ON)); + } + else if (type == 1) + { + //vHeapUsageDump(); + + /* Dump task stack usage */ + //extern void vTaskStackDump(void); + //vTaskStackDump(); + + extern void bte_pool_dump(uint8_t handle); + bte_pool_dump(0xFF); + + extern void hci_dump(void); + hci_dump(); + } + else + { + } + + return RESULT_SUCESS; +} + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const T_USER_CMD_TABLE_ENTRY user_cmd_table[] = +{ + /************************** Common cmd *************************************/ + { + "reset", + "reset\n\r", + "reset system\n\r", + cmd_reset + }, + { + "vendor", + "vendor\n\r", + "vendor cmd\n\r", + cmd_vendor + }, + { + "reg", + "reg [test_case]\n\r", + "Init stack, reg test case\n\r", + cmd_reg + }, + { + "dlps", + "dlps [mode]\n\r", + "dlps\n\r", + cmd_dlps + }, + { + "tracelevel", + "tracelevel [0/1: off/on]\n\r", + "Set trace level\n\r", + cmd_tracelevel + }, + { + "setlocaltype", + "setlocaltype [type]\n\r", + "set local address type: 0-public, 1-random, 2-resolved or public 3- resolved or random\n\r", + cmd_setlocaltype + }, + { + "setstatic", + "setstatic [type]\n\r", + "set static address type: 0-, 1-\n\r", + cmd_setstatic + }, + { + "txpwrset", + "txpwrset [type] [tx gain]\n\r", + "Set the TX Power of BLE RF\n\r", + cmd_txpwrset + }, +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + { + "wrdefaultdatalen", + "wrdefaultdatalen [tx octests] [tx time]\n\r", + "Specify suggested data length\n\r", + cmd_writedefaultdatalen + }, +#endif + { + "rssiread", + "rssiread [conn_id]\n\r", + "Read the RSSI value\n\r", + cmd_rssiread + }, +#if F_BT_LE_READ_CHANN_MAP + { + "readchanmap", + "readchanmap [conn_id]\n\r", + "read channel map\n\r", + cmd_readchanmap + }, +#endif + { + "conupdreq", + "conupdreq [conn_id] [interval_min] [interval_max] [latency] [supervision_timeout]\n\r", + "LE connection param update request\r\n\ + sample: conupdreq 0 0x30 0x40 0 500\n\r", + cmd_conupdreq + }, + { + "showcon", + "showcon\n\r", + "Show all devices connecting status\n\r", + cmd_showcon + }, + { + "disc", + "disc [conn_id]\n\r", + "Disconnect to remote device\n\r", + cmd_disc + }, +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + { + "setdatalength", + "setdatalength [conn_id] [tx octests] [tx time]\n\r", + "set data length\n\r", + cmd_setdatalength + }, +#endif + { + "wl", + "wl [op] [conn_id]\n\r", + "modify remote BD to whitelist\n\r", + cmd_wl + }, + { + "wldev", + "wldev [op] [dev idx]\n\r", + "modify remote BD to whitelist\n\r", + cmd_wldev + }, + /**************************Auth Common cmd *************************************/ + { + "authmode", + "authmode [auth_flags] [io_cap] [sec_enable] [oob_enable]\n\r", + "Config authentication mode\r\n\ + [auth_flags]:authentication req bit field: bit0-(bonding), bit2-(MITM), bit3-(SC)\r\n\ + [io_cap]:set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\ + [sec_enable]:Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\ + [oob_enable]:Enable oob flag: 0-(disable), 1-(enable)\r\n\ + sample: authmode 0x5 2 1 0\n\r", + cmd_authmode + }, + { + "setkeydis", + "setkeydis [init] [resp]\n\r", + "set key distribute\n\r", + cmd_setkeydis + }, + { + "sauth", + "sauth [conn_id]\n\r", + "Send authentication request\n\r", + cmd_sauth + }, + { + "userconf", + "userconf [conn_id] [conf]\n\r", + "Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION\r\n\ + [conf]: 0-(Reject), 1-(Accept)\r\n\ + sample: userconf 0 1\n\r", + cmd_userconf + }, + { + "authkey", + "authkey [conn_id] [passkey]\n\r", + "Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT\r\n\ + [passkey]: 0 - 999999\r\n\ + sample: authkey 0 123456\n\r", + cmd_authkey + }, +#if F_BT_LE_SMP_OOB_SUPPORT + { + "oob", + "oob [conn_id] [oob0] [oob3] [oob7] [oob15]\n\r", + "input oob data\n\r", + cmd_oob + }, +#endif +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + { + "keypress", + "keypress [conn_id] [type]\n\r", + "keypress notification\n\r", + cmd_keypress + }, +#endif + { + "bondinfo", + "bondinfo\n\r", + "Get all Bonded devices information\n\r", + cmd_bondinfo + }, + { + "bondclear", + "bondclear\n\r", + "Clear all bonded devices information\n\r", + cmd_bondclear + }, + /************************** Central only *************************************/ + { + "scan", + "scan [filter_policy] [filter_duplicate]\n\r", + "Start scan\r\n\ + [filter_policy]: 0-(any), 1-(whitelist), 2-(any RPA), 3-(whitelist RPA) \r\n\ + [filter_duplicate]: 0-(disable), 1-(enable) \n\r", + cmd_scan + }, + { + "stopscan", + "stopscan\n\r", + "Stop scan\n\r", + cmd_stopscan + }, + { + "showdev", + "showdev\n\r", + "Show scan dev list: filter simple ble service\n\r", + cmd_showdev + }, +#if F_BT_LE_GAP_CENTRAL_SUPPORT + { + "con", + "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [addr_type]\n\r", + "Connect to remote device: use address\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: remote device address\r\n\ + [addr_type]: 0-(public), 1-(random)\r\n\ + sample: con x11 x22 x33 x44 x55 x66 0 \n\r", + cmd_con + }, + { + "condev", + "condev [idx]\n\r", + "Connect to remote device: use showdev to show idx\r\n\ + [idx]: use cmd showdev to show idx before use this cmd\r\n\ + sample: condev 0\n\r", + cmd_condev + }, + { + "chanclassset", + "chanclassset [idx0] [idx1] [idx2] [idx3] [idx4]\n\r", + "Set Host Channel Classification\r\n\ + [idx0] [idx1] [idx2] [idx3] [idx4]: channel bit map\r\n\ + sample: chanclassset xff xff x3f xff x00\n\r", + cmd_chanclassset + }, +#endif + /************************** GATT client *************************************/ +#if F_BT_LE_GATT_CLIENT_SUPPORT + { + "srvdis", + "srvdis [conn_id]\n\r", + "Service discovery, discover all primary services\n\r", + cmd_srvdis + }, + /*GAPS client*/ + { + "gapdis", + "gapdis [conn_id]\n\r", + "Start discovery gap service\n\r", + cmd_gapdis + }, + { + "gapread", + "gapread [conn_id] [type]\n\r", + "Read GAP service characteristic value\r\n\ + [type]: 0-(read device name), 1-(read appearance)\r\n\ + simple: gapread 0 0\n\r", + cmd_gapread + }, + { + "simpdis", + "simpdis [conn_id]\n\r", + "Start discovery simple ble service\n\r", + cmd_simpdis + }, + { + "simpread", + "simpread [conn_id] [type] [pattern]\n\r", + "Read simple ble service characteristic and descriptor value\r\n\ + [type]: 0-(read v1), 1-(v3 cccd), 2-(v4 cccd)\r\n\ + [pattern]: 0-(read by handle), 1-(read by uuid)\r\n\ + sample: simpread 0 1 0 \n\r", + cmd_simpread + }, + { + "simpcccd", + "simpcccd [conn_id] [type] [enable]\n\r", + "Config simple ble service client characteristic configuration descriptor value\r\n\ + [type]: 0-(v3 notify), 1-(v4 indication) 2-(v8 notify and indication)\r\n\ + [enable](type!=2): 0-(disable), 1-(enable) \r\n\ + [enable](type==2): 0-(disable), 0x01-(notify), 0x10-(indicate), 0x11-(notify and indicate) \r\n\ + sample: simpcccd 0 1 1\n\r", + cmd_simpcccd + }, + { + "simpwrite", + "simpwrite [conn_id] [char] [value]\n\r", + "Write all related chars by user input\n\r", + cmd_simpwrite + }, + { + "simphdl", + "simphdl [conn_id]\n\r", + "List simple ble service handle cache\n\r", + cmd_simphdl + }, +#endif +#if F_BT_ANCS_CLIENT_SUPPORT + { + "ancsdis", + "ancsdis [conn_id]\n\r", + "Start discovery ancs service\n\r", + cmd_ancsdis + }, +#endif + /***************peripheral*******************/ + { + "startadv", + "startadv\n\r", + "start advertising without setting advertising parameters\n\r", + cmd_startadv + }, + { + "advdata", + "advdata [len] [value]\n\r", // len: 1-31 + "Modify advertising data\n\r", // value: 0x00, ff + cmd_advdata + }, + { + "stopadv", + "stopadv\n\r", + "Stop advertising\n\r", + cmd_stopadv + }, + { + "adv", + "adv [adv_interval] [filter_policy]\n\r", + "Start Undirected advertising\r\n\ + [adv_interval]: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step)\r\n\ + [filter_policy]: 0-(all), 1-(whitelist scan), 2-(whitelist conn), 3-(whitelist all)\r\n\ + sample: adv x40 0 \n\r", + cmd_adv + }, + { + "advld", + "advld [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r", + "Start lower duty directed advertising\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\ + sample: advld x11 x22 x33 x44 x55 x66\n\r", + cmd_advld + }, + { + "advhd", + "advhd [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r", + "Start high duty directed advertising\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\ + sample: advhd x11 x22 x33 x44 x55 x66\n\r", + cmd_advhd + }, + { + "advscan", + "advscan\n\r", + "Start scannable undirected advertising\n\r", + cmd_advscan + }, + { + "advnonconn", + "advnonconn\n\r", + "Start non_connectable undirected advertising\n\r", + cmd_advnonconn + }, + { + "advwl", + "advwl\n\r", + "Start undirected advertising with white list\n\r", + cmd_advwl + }, +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + { + "readadvpwr", + "readadvpwr\n\r", + "Read adv channel tx power\n\r", + cmd_readadvpwr + }, +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + { + "latency", + "latency [conn_id] [on_off]\n\r", + "On off slave latency\r\n\ + [on_off]: 0-(turn on the latency), 1-(turn off the latency)\r\n\ + sample: latency 0 1\n\r", + cmd_latency + }, + { + "epassed", + "epassed [enable]\n\r", + "Update instant passed channel map\r\n\ + [enable]: 0 - (disable), 1-(enable)\r\n\ + sample: epassed 1\n\r", + cmd_epassed + }, +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + { + "vadv", + "vadv [enable] \n\r", + "Each adv channel with diff data\r\n\ + [enable]: 0-(disable), 1-(enable)\r\n\ + sample: vadv 1 \n\r", + cmd_vadv + }, + { + "vadvdata", + "vadvdata [type] [len] [value]\n\r", + "Set adv channel adv data and scan response data\r\n\ + [type]: 0-(adv 38 data), 1-(adv 39 data), 2-(scan response 38 data), 3-(scan response 39 data)\r\n\ + [len]: 0-31\r\n\ + [value]: adv data value\r\n\ + sample: vadvdata 1 5 5 \n\r", + cmd_vadvdata + }, +#endif + /********************************Profile Server*********************************/ + { + "srvchange", + "srvchange [conn_id] [start_handle] [end_handle] \n\r", + "Send service change indication\r\n\ + [start_handle]: 1 - 0xFFFF\r\n\ + [end_handle]: 1 - 0xFFFF\n\r", + cmd_srvchange + }, + { + "simpv3notify", + "simpv3notify [conn_id] [len] \n\r", + "Send V3 notification\r\n\ + [len]: 0 - (mtu-3)\n\r", + cmd_simpv3notify + }, + { + "simpv3dump", + "simpv3dump\n\r", + "Dump v3 result\n\r", + cmd_simpv3dump + }, + { + "simpv4ind", + "simpv4ind [conn_id] [len]\n\r", + "Send V4 indication\r\n\ + [len]: 0 - (mtu-3)\n\r", + cmd_simpv4ind + }, + { + "simpv8notify", + "simpv8notify [conn_id] [val]\n\r", + "Notify Characteristic V8 Notify value.\n\r", + cmd_simpv8notify + }, + { + "simpv8ind", + "simpv8ind [conn_id] [val]\n\r", + "Indicate Characteristic V8 Indicate value.\n\r", + cmd_simpv8ind + }, + { + "simpv7len", + "simpv7len [len]\n\r", + "Set V7 Characteristic value length.\n\r", + cmd_simpv7len + }, + { + "simpv2writeconf", + "simpv2writeconf [conn_id]\n\r", + "Write Response Characteristic V2 Write Request.\n\r", + cmd_simpv2writeconf + }, +#if F_BT_LE_5_0_SUPPORT + { + "setphy", + "setphy [conn_id] [phy]\n\r", + "set phy.\n\r", + cmd_setphy + }, +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + { + "escan", + "escan [0/1/2/3]\n\r", + "escan remote devices\n\r", + cmd_escan + }, + { + "stopescan", + "stopescan\n\r", + "stopescan remote device\n\r", + cmd_stopescan + }, +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + { + "ueadv", + "ueadv [adv_handle] [flags]\n\r", + "Update extend advertising param\n\r", + cmd_ueadv + }, + { + "uedadv", + "uedadv [adv_handle] [flags]\n\r", + "Update extend directed advertising param\n\r", + cmd_uedadv + }, + { + "seadv", + "seadv [adv_handle] [duration] [max_num]\n\r", + "Set extended adv enable param\n\r", + cmd_seadv + }, + { + "eadv", + "eadv [adv_handle1] [adv_handle2] [adv_handle3] [adv_handle4]\n\r", + "Start extended adv\n\r", + cmd_eadv + }, + { + "stopeadv", + "stopeadv [adv_handle1] [adv_handle2] [adv_handle3] [adv_handle4]\n\r", + "Stop extended adv\n\r", + cmd_stopeadv + }, + { + "ceadv", + "ceadv\n\r", + "clear extended adv set\n\r", + cmd_ceadv + }, + { + "readv", + "readv [adv_handle]\n\r", + "remove extended adv set\n\r", + cmd_readv + }, +#endif +#endif +#if F_BT_LE_PRIVACY_SUPPORT + { + "advrel", + "advrel\n\r", + "Start undirected advertising with local type = resolved\n\r", + cmd_advrel + }, + { + "setrae", + "setrae [enable]\n\r", + "set addr resolution enable.\n\r", + cmd_setrae + }, + { + "readlra", + "readlra [conn_id]\n\r", + "read local resolvable address.\n\r", + cmd_readlra + }, + { + "readpra", + "readlra [conn_id]\n\r", + "read peer resolvable address..\n\r", + cmd_readpra + }, + { + "showrel", + "showrel\n\r", + "show resolved list.\n\r", + cmd_showrel + }, + { + "setprivacy", + "setprivacy [rel_idx] [0/1]\n\r", + "set privacy mode.\n\r", + cmd_setprivacy + }, + { + "wlrel", + "wlrel [op] [rel_idx]\n\r", + "whitelist\n\r", + cmd_wlrel + }, + { + "conrel", + "conrel [idx]\n\r", + "connect to remote device\n\r", + cmd_conrel + }, +#endif +#if F_BT_LE_4_1_CBC_SUPPORT + { + "lepsm", + "lepsm [psm] [action]\n\r", + "set le psm\n\r", + cmd_lepsm + }, + { + "lesec", + "lesec [psm] [active] [mode] [key_size]\n\r", + "set le psm security\n\r", + cmd_lesec + }, + { + "conle", + "conle [conn_id] [psm]\n\r", + "create credit based connection\n\r", + cmd_conle + }, + { + "discle", + "discle [cid]\n\r", + "disconnect credit based connection\n\r", + cmd_discle + }, + { + "ledata", + "ledata [cid] [num] [length]\n\r", + "send data through credit based connection\n\r", + cmd_ledata + }, +#endif +#if APP_HID_TEST + { + "key", + "key [conn_id][key]\n\r", + "Set key\n\r", + cmd_key + }, +#endif +#if F_BT_CONTROLLER_POWER_CONTROL + { + "poweron", + "poweron \n\r", + "Turn power on\n\r", + cmd_poweron + }, + { + "poweroff", + "poweroff \n\r", + "Turn power off\n\r", + cmd_poweroff + }, +#endif + { + "taskadd", + "taskadd \n\r", + "Add task\n\r", + cmd_taskadd + }, + { + "taskdel", + "taskadd \n\r", + "Delete task\n\r", + cmd_taskdel + }, + { + "stackadd", + "stackadd \n\r", + "Add stack task\n\r", + cmd_stackadd + }, + { + "stackdel", + "stackdel \n\r", + "Delete stack task\n\r", + cmd_stackdel + }, + { + "dump", + "dump [type] \n\r", + "Dump information\n\r", + cmd_dump + }, + { + "tc", + "tc [case] [count]\n\r", + "auto test case\n\r", + cmd_tc + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; diff --git a/component/common/bluetooth/realtek/sdk/src/app/deinit_test/user_cmd.h b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/user_cmd.h new file mode 100644 index 00000000..c1615aa2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/deinit_test/user_cmd.h @@ -0,0 +1,31 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file user_cmd.h +* @brief Define user command. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _USER_CMD_H_ +#define _USER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[]; +extern T_USER_CMD_IF user_cmd_if; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/ancs.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/ancs.c new file mode 100644 index 00000000..4c470bb5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/ancs.c @@ -0,0 +1,662 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ancs.c + * @brief This file handles ANCS Client routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#if F_BT_ANCS_CLIENT_SUPPORT +#include +#include +#include +#include +#include +#include + +/** @defgroup PERIPH_ANCS Peripheral ANCS + * @brief Apple ANCS service modulization + * @{ + */ +/*============================================================================* + * Types + *============================================================================*/ +typedef struct +{ + uint8_t m_parse_state; + uint8_t app_type; + uint16_t current_len; + void *ancs_queue_handle; + uint8_t *ptr; + T_DS_NOTIFICATION_ATTR notification_attr; +#if F_BT_ANCS_GET_APP_ATTR + T_DS_APP_ATTR app_attr; +#endif +} T_APP_ANCS_LINK; + +/*============================================================================* + * Variables + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Variables ANCS Exported Variables + * @brief app register ancs client to upperstack, and return ancs client id + * @{ + */ +T_CLIENT_ID ancs_client; /**< ancs client id*/ + +T_APP_ANCS_LINK *ancs_link_table; +uint8_t ancs_link_number; + +/** End of PERIPH_ANCS_Exported_Variables + * @} + */ +extern void *evt_queue_handle; //!< Event queue handle +extern void *io_queue_handle; //!< IO queue handle +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Functions ANCS Exported Functions + * @{ + */ +void ancs_send_msg_to_app(uint8_t conn_id) +{ + T_IO_MSG io_msg; + uint8_t event = EVENT_IO_TO_APP; + io_msg.type = IO_MSG_TYPE_ANCS; + io_msg.subtype = 0; + io_msg.u.param = conn_id; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail1"); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + GAP_PRINT_ERROR0("ancs_send_msg_to_app fail2"); + } +} + +void app_handle_notification_attribute_data(T_APP_ANCS_LINK *p_ancs_link) +{ + if (p_ancs_link->notification_attr.attribute_id != DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + uint8_t *p_value = p_ancs_link->notification_attr.data; + +#if F_BT_ANCS_APP_FILTER + //filter QQ , wechat , short message and incomming call + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: app identifiter %s", TRACE_STRING(p_value)); +#endif + //wechat + if (0 == memcmp(p_value, "com.tencent.xin", 16)) + { + p_ancs_link->app_type = 1; + } + else if (0 == memcmp(p_value, "com.apple.MobileSMS", 20)) + { + p_ancs_link->app_type = 2; + } + else if (0 == memcmp(p_value, "com.apple.mobilephone", 22)) + { + p_ancs_link->app_type = 3; + } + else if (0 == memcmp(p_value, "com.tencent.mqq", 16)) + { + p_ancs_link->app_type = 4; + } + else if (0 == memcmp(p_value, "com.tencent.qq", 15)) + { + p_ancs_link->app_type = 5; + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_MESSAGE) + { + if (p_ancs_link->app_type == 2) + { + APP_PRINT_INFO1("MobileSMS: message %s", TRACE_STRING(p_value)); + } + else if (p_ancs_link->app_type == 5) + { + APP_PRINT_INFO1("QQ: message %s", TRACE_STRING(p_value)); + } + } + if (p_ancs_link->notification_attr.attribute_id == DS_NOTIFICATION_ATTR_ID_DATE) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: date %s", TRACE_STRING(p_value)); +#endif + } +#endif + } + else/* All attributes has been parased*/ + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO0("parse notify attr: parse done"); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } +} + +void app_parse_notification_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_NOTIFICATION_COMMAND_ID: + p_ancs_link->notification_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID1; + break; + + case DS_PARSE_UID1: + p_ancs_link->notification_attr.notification_uid[0] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID2; + break; + + case DS_PARSE_UID2: + p_ancs_link->notification_attr.notification_uid[1] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID3; + break; + + case DS_PARSE_UID3: + p_ancs_link->notification_attr.notification_uid[2] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_UID4; + break; + + case DS_PARSE_UID4: + p_ancs_link->notification_attr.notification_uid[3] = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + break; + + case DS_PARSE_ATTRIBUTE_ID: + p_ancs_link->notification_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_ATTRIBUTE_LEN1: + p_ancs_link->notification_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_ATTRIBUTE_LEN2: + p_ancs_link->notification_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->notification_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse notify attr: attribute_id %d, attribute_len %d", + p_ancs_link->notification_attr.attribute_id, + p_ancs_link->notification_attr.attribute_len + ); +#endif + if (p_ancs_link->notification_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_ATTRIBUTE_ID; + } + if (p_ancs_link->notification_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse notify attr: error, attribute_len %d > max length %d", + p_ancs_link->notification_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + memset(&p_ancs_link->notification_attr, 0, sizeof(T_DS_NOTIFICATION_ATTR)); + } + break; + + case DS_PARSE_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->notification_attr.attribute_len) + { + /*An attribute is always a string whose length in bytes is provided in the tuple but that is not NULL-terminated.*/ + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("parse notify attr: data %b", + TRACE_BINARY(p_ancs_link->notification_attr.attribute_len, + p_ancs_link->notification_attr.data)); +#endif + app_handle_notification_attribute_data(p_ancs_link); + } + break; + } + } +} + +#if F_BT_ANCS_GET_APP_ATTR +void app_parse_app_attribute(T_APP_ANCS_LINK *p_ancs_link, uint8_t *p_data, uint8_t len) +{ + int i; + for (i = 0; i < len; i++) + { + switch (p_ancs_link->m_parse_state) + { + case DS_PARSE_GET_APP_COMMAND_ID: + p_ancs_link->app_attr.command_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_START; + break; + + case DS_PARSE_APP_IDENTIFIER_START: + if (p_data[i] == 0x00) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_IDENTIFIER_END; + + if (i + 1 == len) + { + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + else + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + } + + } + break; + + case DS_PARSE_APP_ATTRIBUTE_ID: + p_ancs_link->app_attr.attribute_id = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN1; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN1: + p_ancs_link->app_attr.attribute_len = p_data[i]; + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_LEN2; + break; + + case DS_PARSE_APP_ATTRIBUTE_LEN2: + p_ancs_link->app_attr.attribute_len |= (p_data[i] << 8); + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_READY; + p_ancs_link->ptr = p_ancs_link->app_attr.data; + p_ancs_link->current_len = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO2("parse app attr: attribute_id %d, attribute_len %d", + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len + ); +#endif + if (p_ancs_link->app_attr.attribute_len == 0) + { + p_ancs_link->m_parse_state = DS_PARSE_APP_ATTRIBUTE_ID; + + } + if (p_ancs_link->app_attr.attribute_len > ANCS_MAX_ATTR_LEN) + { +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_ERROR2("parse app attr: error, attribute_len %d > max length %d", + p_ancs_link->app_attr.attribute_len, + ANCS_MAX_ATTR_LEN + ); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + } + break; + + case DS_PARSE_APP_ATTRIBUTE_READY: + *p_ancs_link->ptr++ = p_data[i]; + p_ancs_link->current_len++; + + if (p_ancs_link->current_len == p_ancs_link->app_attr.attribute_len) + { + *p_ancs_link->ptr++ = 0; +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO4("parse app attr: command_id 0x%x, attribute_id 0x%x, attribute_len %d, data %s", + p_ancs_link->app_attr.command_id, + p_ancs_link->app_attr.attribute_id, + p_ancs_link->app_attr.attribute_len, + TRACE_STRING(p_ancs_link->app_attr.data)); +#endif + p_ancs_link->m_parse_state = DS_PARSE_NOT_START; + + } + break; + } + } +} +#endif + +/** + * @brief Parse ancs data source notification + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @param[in] len data length + * @return void + */ +void app_parse_data_soucre_notifications(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + APP_PRINT_INFO2("ANCS_FROM_DATA_SOURCE: conn_id %d, len =%d", conn_id, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("data = %b", TRACE_BINARY(len, p_data)); +#endif + T_APP_ANCS_LINK *p_ancs_link = &ancs_link_table[conn_id]; + +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("m_parse_state %d", p_ancs_link->m_parse_state); +#endif + if (p_ancs_link->m_parse_state == DS_PARSE_NOT_START) + { + if (len >= 1 && p_data[0] == CP_CMD_ID_GET_NOTIFICATION_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_NOTIFICATION_COMMAND_ID; + } +#if F_BT_ANCS_GET_APP_ATTR + else if (len >= 1 && p_data[0] == CP_CMD_ID_GET_APP_ATTR) + { + p_ancs_link->m_parse_state = DS_PARSE_GET_APP_COMMAND_ID; + } +#endif + } + + if (p_ancs_link->m_parse_state < DS_PARSE_GET_APP_COMMAND_ID) + { + app_parse_notification_attribute(p_ancs_link, p_data, len); + } +#if F_BT_ANCS_GET_APP_ATTR + else + { + app_parse_app_attribute(p_ancs_link, p_data, len); + } +#endif +} + +void app_parse_notification_source_data(uint8_t conn_id, uint8_t *p_data, uint8_t len) +{ + if (8 == len) + { + T_NS_DATA ns_data; + + memcpy(&ns_data, p_data, len); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO5("app_parse_notification_source_data: event_id %d, event_flags 0x%02x, category_id %d, category_count %d, notification_uid 0x%08x", + ns_data.event_id, + ns_data.event_flags, + ns_data.category_id, + ns_data.category_count, + ns_data.notification_uid + ); + APP_PRINT_INFO5("event_flags: slient %d, important %d, pre existing %d, positive action %d, negative action %d ", + ns_data.event_flags & NS_EVENT_FLAG_SILENT, + ns_data.event_flags & NS_EVENT_FLAG_IMPORTANT, + ns_data.event_flags & NS_EVENT_FLAG_PRE_EXISTING, + ns_data.event_flags & NS_EVENT_FLAG_POSITIVE_ACTION, + ns_data.event_flags & NS_EVENT_FLAG_NEGATIVE_ACTION + ); +#endif + //you can filter by category_id here, for demo purpose, we didn't filter any CategoryID here. +#if F_BT_ANCS_APP_FILTER + //filter social and other category & phone category & email category + if (ns_data.category_id == NS_CATEGORY_ID_SOCIAL || + ns_data.category_id == NS_CATEGORY_ID_OTHER || + ns_data.category_id == NS_CATEGORY_ID_INCOMING_CALL || + ns_data.category_id == NS_CATEGORY_ID_EMAIL) + { +#endif + if (ns_data.event_id != NS_EVENT_ID_NOTIFICATION_REMOVED) + { + uint32_t msg_num; + T_ANCS_MSG ancs_msg; + uint8_t attr_id_list[14]; + uint8_t cur_index = 0; + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_APP_IDENTIFIER; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_SUB_TITLE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE; + attr_id_list[cur_index++] = LO_WORD(ANCS_MAX_ATTR_LEN); + attr_id_list[cur_index++] = HI_WORD(ANCS_MAX_ATTR_LEN); + + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_MESSAGE_SIZE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_DATE; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_POSITIVE_ACTION_LABEL; + attr_id_list[cur_index++] = DS_NOTIFICATION_ATTR_ID_NEGATIVE_ACTION_LABEL; + + os_msg_queue_peek(ancs_link_table[conn_id].ancs_queue_handle, &msg_num); +#if F_BT_ANCS_CLIENT_DEBUG + APP_PRINT_INFO1("app_parse_notification_source_data: msg_num %d", msg_num); +#endif + if (msg_num == 0) + { + if (ancs_get_notification_attr(conn_id, ns_data.notification_uid, attr_id_list, + cur_index) == true) + { + return; + } + } + + ancs_msg.type = ANCS_MSG_TYPE_GET_NOTIFI_ATTR; + ancs_msg.data.notifi_attr.conn_id = conn_id; + ancs_msg.data.notifi_attr.notification_uid = ns_data.notification_uid; + ancs_msg.data.notifi_attr.attribute_ids_len = cur_index; + memcpy(ancs_msg.data.notifi_attr.attribute_ids, attr_id_list, cur_index); + if (os_msg_send(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_ERROR0("app_parse_notification_source_data: discard, msg queue is full"); + } + } +#if F_BT_ANCS_APP_FILTER + } +#endif + } +} + +/** + * @brief Ancs clinet callback handle message from upperstack + * @param[in] client_id client identifier + * @param[in] conn_id connection identifier + * @param[in] *p_data point to data buffer + * @return @ref T_APP_RESULT + */ +T_APP_RESULT ancs_client_cb(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_ANCS_CB_DATA *p_cb_data = (T_ANCS_CB_DATA *)p_data; + + switch (p_cb_data->cb_type) + { + case ANCS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_cb_data->cb_content.disc_state) + { + case DISC_ANCS_DONE: + APP_PRINT_INFO0("ANCS BLE Client CB: discover procedure done."); + ancs_set_data_source_notify(conn_id, true); + break; + case DISC_ANCS_FAILED: + APP_PRINT_ERROR0("ANCS BLE Client CB: discover request failed."); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (p_cb_data->cb_content.notify_data.type) + { + case ANCS_FROM_DATA_SOURCE:; + app_parse_data_soucre_notifications(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + case ANCS_FROM_NOTIFICATION_SOURCE: + APP_PRINT_INFO2("ANCS_FROM_NOTIFICATION_SOURCE: conn_id %d, length %d", + conn_id, p_cb_data->cb_content.notify_data.value_size); + app_parse_notification_source_data(conn_id, p_cb_data->cb_content.notify_data.p_value, + p_cb_data->cb_content.notify_data.value_size); + break; + default: + break; + } + break; + + case ANCS_CLIENT_CB_TYPE_WRITE_RESULT: + { + if (p_cb_data->cb_content.write_result.cause != ATT_SUCCESS) + { + APP_PRINT_ERROR1("ANCS_CLIENT_CB_TYPE_WRITE_RESULT: Failed, cause 0x%x", + p_cb_data->cb_content.write_result.cause); + } + switch (p_cb_data->cb_content.write_result.type) + { + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_ENABLE"); + break; + + case ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_NOTIFICATION_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_ENABLE"); + ancs_set_notification_source_notify(conn_id, true); + break; + case ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE: + APP_PRINT_INFO0("ANCS_WRITE_DATA_SOURCE_NOTIFY_DISABLE"); + break; + + case ANCS_WRITE_CONTROL_POINT: + APP_PRINT_INFO0("ANCS_WRITE_CONTROL_POINT"); +#if F_BT_ANCS_CLIENT_DEBUG + if (p_cb_data->cb_content.write_result.cause == 0x4A0) + { + APP_PRINT_ERROR0("The commandID was not recognized by the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A1) + { + APP_PRINT_ERROR0("The command was improperly formatted."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A2) + { + APP_PRINT_ERROR0("One of the parameters (for example, the NotificationUID) does not refer to an existing object on the NP."); + } + else if (p_cb_data->cb_content.write_result.cause == 0x4A3) + { + APP_PRINT_ERROR0("The action was not performed."); + } +#endif + ancs_send_msg_to_app(conn_id); + break; + + default: + break; + } + } + break; + + case ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: + { + T_ANCS_MSG ancs_msg; + void *ancs_queue_handle = ancs_link_table[conn_id].ancs_queue_handle; + APP_PRINT_INFO1("ANCS_CLIENT_CB_TYPE_DISCONNECT_INFO: conn_id = 0x%x", conn_id); + memset(&ancs_link_table[conn_id], 0, sizeof(T_APP_ANCS_LINK)); + ancs_link_table[conn_id].ancs_queue_handle = ancs_queue_handle; + /*release msg queue*/ + while (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0)); + } + break; + + default: + break; + } + return result; +} + +void ancs_handle_msg(T_IO_MSG *p_io_msg) +{ + uint8_t conn_id = p_io_msg->u.param; + T_ANCS_MSG ancs_msg; + if (os_msg_recv(ancs_link_table[conn_id].ancs_queue_handle, &ancs_msg, 0) == false) + { + APP_PRINT_INFO1("ancs_handle_msg: conn_id 0x%x os_msg_recv failed", conn_id); + return; + } + if (ancs_msg.type == ANCS_MSG_TYPE_GET_NOTIFI_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: notification_uid 0x%x", + ancs_msg.data.notifi_attr.notification_uid); + if (ancs_get_notification_attr(ancs_msg.data.notifi_attr.conn_id, + ancs_msg.data.notifi_attr.notification_uid, + ancs_msg.data.notifi_attr.attribute_ids, ancs_msg.data.notifi_attr.attribute_ids_len + ) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_NOTIFI_ATTR: Failed"); + } + + } + else if (ancs_msg.type == ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: notification_uid 0x%x", + ancs_msg.data.perform_action.notification_uid); + if (ancs_perform_notification_action(ancs_msg.data.perform_action.conn_id, + ancs_msg.data.perform_action.notification_uid, + ancs_msg.data.perform_action.action_id) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_PERFORM_NOTIFI_ACTION: Failed"); + } + + } +#if F_BT_ANCS_GET_APP_ATTR + else if (ancs_msg.type == ANCS_MSG_TYPE_GET_APP_ATTR) + { + APP_PRINT_INFO1("ANCS_MSG_TYPE_GET_APP_ATTR: app_identifier %s", + TRACE_STRING(ancs_msg.data.app_attr.app_identifier)); + if (ancs_get_app_attr(ancs_msg.data.app_attr.conn_id, + ancs_msg.data.app_attr.app_identifier, + ancs_msg.data.app_attr.attribute_ids, + ancs_msg.data.app_attr.attribute_ids_len) == false) + { + APP_PRINT_ERROR0("ANCS_MSG_TYPE_GET_APP_ATTR: Failed"); + } + + } +#endif +} + +/** + * @brief App register ancs client to upperstack. + * This ancs_client_cb callback function will handle message. + * @param[in] link_num Initialize link number + * @return void + */ +void ancs_init(uint8_t link_num) +{ + uint8_t i; + ancs_link_number = link_num; + ancs_link_table = os_mem_zalloc(RAM_TYPE_DATA_ON, ancs_link_number * sizeof(T_APP_ANCS_LINK)); + if (ancs_link_table == NULL) + { + APP_PRINT_ERROR0("ancs_init: allocate buffer failed"); + } + for (i = 0; i < ancs_link_number; i++) + { + if (os_msg_queue_create(&(ancs_link_table[i].ancs_queue_handle), ANCS_MSG_QUEUE_NUM, + sizeof(T_ANCS_MSG)) == false) + { + APP_PRINT_ERROR2("ancs_init: link_num %d, i 0x%x create queue failed", link_num, i); + } + } + ancs_client = ancs_add_client(ancs_client_cb, link_num); +} +/** @} */ /* End of group PERIPH_ANCS_Exported_Functions */ +/** @} */ /* End of group PERIPH_ANCS */ +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/ancs.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/ancs.h new file mode 100644 index 00000000..939fd6ef --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/ancs.h @@ -0,0 +1,260 @@ +/** +********************************************************************************************************* +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file ancs.h +* @brief ancs +* @details ancs +* @author ranhui +* @date 2015-03-27 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _ANCS_H__ +#define _ANCS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include + +/** @addtogroup PERIPH_ANCS + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup PERIPH_ANCS_Exported_Macros ANCS Exported Macros + * @{ + */ +#define ANCS_MAX_ATTR_LEN 256 //!< Max ancs attribute length + +#if F_BT_ANCS_GET_APP_ATTR +#define ANCS_APP_INDENTIFIER_MAX_LEN 30 //!< Max app indentifier length +#endif + +#define ANCS_MSG_QUEUE_NUM 5 //!< ANCS message queue size + + +/** @brief ANCS event flag */ +#define NS_EVENT_FLAG_SILENT (1 << 0) +#define NS_EVENT_FLAG_IMPORTANT (1 << 1) +#define NS_EVENT_FLAG_PRE_EXISTING (1 << 2) +#define NS_EVENT_FLAG_POSITIVE_ACTION (1 << 3) //!
© COPYRIGHT 2017 Realtek Semiconductor Corporation
+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include + +/*============================================================================* + * Macros + *============================================================================*/ +//! Task priorities +#define APP_TASK_PRIORITY 1 +//!Task stack size +#define APP_TASK_STACK_SIZE 256 * 8 + +//!IO message queue size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 +//!Event message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_GAP_MESSAGE + MAX_NUMBER_OF_IO_MESSAGE) + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +void app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +/** + * @brief App task to handle events & messages + * @param[in] p_params Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + data_uart_init(evt_queue_handle, io_queue_handle); + user_cmd_init(&user_cmd_if, "gap_test"); + + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + else + { + gap_handle_msg(event); + } + } + } +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/app_task.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/app_task.h new file mode 100644 index 00000000..0300a3cd --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/app_task.h @@ -0,0 +1,29 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +#define MAX_NUMBER_OF_GAP_MESSAGE 0x20 + +extern void *evt_queue_handle; +extern void *io_queue_handle; +/** + * @brief Initialize App task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/ble_app_main.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/ble_app_main.c new file mode 100644 index 00000000..e644a4ab --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/ble_app_main.c @@ -0,0 +1,281 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE scatternet project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#include +#include +#if APP_GENERAL_CLIENT_TEST +#include +#endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "trace_uart.h" + +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Default scan interval (units of 0.625ms) */ +#define DEFAULT_SCAN_INTERVAL 400 +/** @brief Default scan window (units of 0.625ms) */ +#define DEFAULT_SCAN_WINDOW 200 + +/** @brief Default minimum advertising interval when device is discoverable (units of 625us, 160=100ms) */ +#define DEFAULT_ADVERTISING_INTERVAL_MIN 320 +/** @brief Default Maximum advertising interval */ +#define DEFAULT_ADVERTISING_INTERVAL_MAX 320 + +/** @brief GAP - scan response data (max size = 31 bytes) */ +static const uint8_t scan_rsp_data[] = +{ + 0x03, + GAP_ADTYPE_APPEARANCE, +#if 0 + LO_WORD(GAP_GATT_APPEARANCE_KEYBOARD), + HI_WORD(GAP_GATT_APPEARANCE_KEYBOARD), +#else + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +#endif +}; + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ +static const uint8_t adv_data[] = +{ + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, +#if 0 + 0x12, + 0x18, +#else + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), +#endif + 0x0C, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'B', '3', '_', 'G', 'a', 'p', 'T', 'e', 's', 't' +}; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); +} + +/** + * @brief Initialize gap related parameters + * @return void + */ +void app_le_gap_init(void) +{ + /* Device name and device appearance */ + uint8_t device_name[GAP_DEVICE_NAME_LEN] = "BB3_GapTest"; + uint16_t appearance = GAP_GATT_APPEARANCE_UNKNOWN; + uint8_t slave_init_gatt_mtu_req = false; + + /* Scan parameters */ + uint8_t scan_mode = GAP_SCAN_MODE_ACTIVE; + uint16_t scan_interval = DEFAULT_SCAN_INTERVAL; + uint16_t scan_window = DEFAULT_SCAN_WINDOW; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + /* advertising parameters */ + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = DEFAULT_ADVERTISING_INTERVAL_MIN; + uint16_t adv_int_max = DEFAULT_ADVERTISING_INTERVAL_MIN; + + /* GAP Bond Manager parameters */ + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t auth_oob = false; +#endif + uint8_t auth_use_fix_passkey = false; + uint32_t auth_fix_passkey = 0; + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + /* Set device name and device appearance */ + le_set_gap_param(GAP_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, device_name); + le_set_gap_param(GAP_PARAM_APPEARANCE, sizeof(appearance), &appearance); + le_set_gap_param(GAP_PARAM_SLAVE_INIT_GATT_MTU_REQ, sizeof(slave_init_gatt_mtu_req), + &slave_init_gatt_mtu_req); + + /* Set scan parameters */ + le_scan_set_param(GAP_PARAM_SCAN_MODE, sizeof(scan_mode), &scan_mode); + le_scan_set_param(GAP_PARAM_SCAN_INTERVAL, sizeof(scan_interval), &scan_interval); + le_scan_set_param(GAP_PARAM_SCAN_WINDOW, sizeof(scan_window), &scan_window); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + + + /* Set advertising parameters */ + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + le_adv_set_param(GAP_PARAM_ADV_DATA, sizeof(adv_data), (void *)adv_data); + le_adv_set_param(GAP_PARAM_SCAN_RSP_DATA, sizeof(scan_rsp_data), (void *)scan_rsp_data); + + /* Setup the GAP Bond Manager */ + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(auth_oob), &auth_oob); +#endif + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(auth_fix_passkey), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(auth_use_fix_passkey), + &auth_use_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + + /* register gap message callback */ + le_register_app_cb(app_gap_callback); + gap_register_app_cb(app_gap_common_callback); + //gap_register_vendor_cb(app_gap_vendor_callback); +} + +/** + * @brief Add GATT services, clients and register callbacks + * @return void + */ +void app_le_profile_init(void) +{ + server_init(7); + simp_srv_id = simp_ble_service_add_service((void *)app_profile_callback); + server_register_app_cb(app_profile_callback); +#if F_BT_LE_GATT_CLIENT_SUPPORT + client_init(4); + gaps_client_id = gaps_add_client(app_client_callback, APP_MAX_LINKS); + simple_ble_client_id = simp_ble_add_client(app_client_callback, APP_MAX_LINKS); +#if APP_GENERAL_CLIENT_TEST + gcs_client_id = gcs_add_client(gcs_client_callback, APP_MAX_LINKS, 20); +#endif +#endif +} + +/** + * @brief Contains the initialization of pinmux settings and pad settings + * @note All the pinmux settings and pad settings shall be initiated in this function, + * but if legacy driver is used, the initialization of pinmux setting and pad setting + * should be peformed with the IO initializing. + * @return void + */ +#if F_BT_TASK_SCHEDULE_DEBUG +#include "test_os_schedule.c" +#endif + +void board_init(void) +{ +#if F_BT_TASK_SCHEDULE_DEBUG + test_os_schedule_main(); +#endif +} + +/** + * @brief Contains the initialization of peripherals + * @note Both new architecture driver and legacy driver initialization method can be used + * @return void + */ +void driver_init(void) +{ + +} + +/** + * @brief Contains the power mode settings + * @return void + */ +void pwr_mgr_init(void) +{ +#if F_BT_DLPS_EN + data_uart_dlps_init(); + lps_mode_set(LPM_DLPS_MODE); + lps_mode_pause(); +#endif +} + +/** + * @brief Contains the initialization of all tasks + * @note There is only one task in BLE Scatternet APP, thus only one APP task is init here + * @return void + */ +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int ble_app_main(void) +{ + bt_trace_init(); + bt_stack_config_init(); + bte_init(); + board_init(); + driver_init(); + le_gap_init(APP_MAX_LINKS); + app_le_gap_init(); + app_le_profile_init(); + pwr_mgr_init(); + task_init(); + + return 0; +} diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_client.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_client.c new file mode 100644 index 00000000..059755c8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_client.c @@ -0,0 +1,797 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_client.c + * @brief Complete Simple BLE client source file. + * @details + * @author jane + * @date 2016-02-18 + * @version v1.0 + ****************************************************************************** + */ + +/** Add Includes here **/ +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include +#include +#include + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ + +typedef struct +{ + T_SIMP_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN]; +} T_SIMP_LINK, *P_SIMP_LINK; + +static P_SIMP_LINK simp_table; +static uint8_t simp_link_num; + +/**< Simple BLE client ID. */ +static T_CLIENT_ID simp_client = CLIENT_PROFILE_GENERAL_ID; +/**< Callback used to send data to app from Simple BLE client layer. */ +static P_FUN_GENERAL_APP_CB simp_client_cb = NULL; + + +bool simp_ble_client_start_discovery(uint8_t conn_id) +{ + APP_PRINT_INFO0("simp_ble_client_start_discovery"); + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + /* First clear handle cache. */ + memset(&simp_table[conn_id], 0, sizeof(T_SIMP_LINK)); + simp_table[conn_id].disc_state = DISC_SIMP_START; + if (client_by_uuid_srv_discovery(conn_id, simp_client, + GATT_UUID_SIMPLE_PROFILE) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +bool simp_ble_client_read_by_handle(uint8_t conn_id, T_SIMP_READ_TYPE read_type) +{ + bool hdl_valid = false; + uint16_t handle; + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case SIMP_READ_V1_READ: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V1_READ]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V1_READ]; + hdl_valid = true; + } + break; + case SIMP_READ_V3_NOTIFY_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]; + hdl_valid = true; + } + break; + case SIMP_READ_V4_INDICATE_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]; + hdl_valid = true; + } + break; + + case SIMP_READ_V7_READ_LONG: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V7_READ_LONG]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V7_READ_LONG]; + hdl_valid = true; + } + break; + case SIMP_READ_V8_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + hdl_valid = true; + } + break; + + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, simp_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_read_by_handle: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_read_by_uuid(uint8_t conn_id, T_SIMP_READ_TYPE read_type) +{ + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_read_by_uuid: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case SIMP_READ_V1_READ: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_SIMPLE_V1_READ; + break; + case SIMP_READ_V3_NOTIFY_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case SIMP_READ_V4_INDICATE_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case SIMP_READ_V7_READ_LONG: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_SIMPLE_V7_READ_LONG; + break; + case SIMP_READ_V8_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + default: + return false; + } + + if (client_attr_read_using_uuid(conn_id, simp_client, start_handle, end_handle, + uuid16, NULL) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +bool simp_ble_client_set_v3_notify(uint8_t conn_id, bool notify) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v3_notify: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = notify ? 1 : 0; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_set_v3_notify: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_set_v4_ind(uint8_t conn_id, bool ind) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v4_ind: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = ind ? 2 : 0; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_set_v4_ind: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_set_v8_cccd(uint8_t conn_id, uint16_t cccd_bits) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v8_cccd: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + uint16_t length = sizeof(uint16_t); + uint8_t *p_data = (uint8_t *)&cccd_bits; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, p_data) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + APP_PRINT_WARN0("simp_ble_client_set_v8_cccd: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_write_v2_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_write_v2_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V2_WRITE]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V2_WRITE]; + if (client_attr_write(conn_id, simp_client, type, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_write_v2_char: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_write_v6_char(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_write_v6_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + APP_PRINT_WARN0("simp_ble_client_write_v6_char: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (simp_table[conn_id].disc_state != DISC_SIMP_DONE) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid state %d", + simp_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, simp_table[conn_id].hdl_cache, len); + return true; +} + +bool simp_ble_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (simp_table[conn_id].disc_state != DISC_SIMP_IDLE) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid state %d", + simp_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(simp_table[conn_id].hdl_cache, p_hdl_cache, len); + simp_table[conn_id].disc_state = DISC_SIMP_DONE; + return true; +} + +static bool simp_ble_client_start_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("simp_ble_client_start_simp_char_discovery"); + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + if (client_all_char_discovery(conn_id, simp_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +static bool simp_ble_client_start_char_descriptor_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("simp_ble_client_start_char_descriptor_discovery"); + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + if (client_all_char_descriptor_discovery(conn_id, simp_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} +static void simp_ble_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + bool cb_flag = false; + T_SIMP_CLIENT_CB_DATA cb_data; + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_DISC_STATE; + + APP_PRINT_INFO1("simp_ble_client_discover_state_cb: discovery_state %d", discovery_state); + if (simp_table[conn_id].disc_state == DISC_SIMP_START) + { + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + switch (discovery_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((hdl_cache[HDL_SIMBLE_SRV_START] != 0) + || (hdl_cache[HDL_SIMBLE_SRV_END] != 0)) + { + if (simp_ble_client_start_char_discovery(conn_id) == false) + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + } + /* No Simple BLE service handle found. Discover procedure complete. */ + else + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + if (hdl_cache[HDL_SIMBLE_V3_NOTIFY] != 0) + { + if (simp_ble_client_start_char_descriptor_discovery(conn_id) == false) + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + } + else + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + simp_table[conn_id].disc_state = DISC_SIMP_DONE; + cb_flag = true; + break; + case DISC_STATE_FAILED: + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + break; + default: + APP_PRINT_ERROR0("simp_handle_discover_state: Invalid Discovery State!"); + break; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && simp_client_cb) + { + cb_data.cb_content.disc_state = simp_table[conn_id].disc_state; + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + return; +} + +/** + * @brief Called by profile client layer, when discover result fetched. + * @param conn_id: connection ID. + * @param result_type: indicate which type of value discovered in service discovery procedure. + * @param result_data: value discovered. + * @retval None + */ +static void simp_ble_client_discover_result_cb(uint8_t conn_id, + T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + APP_PRINT_INFO1("simp_ble_client_discover_result_cb: result_type %d", result_type); + if (simp_table[conn_id].disc_state == DISC_SIMP_START) + { + uint16_t handle; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + hdl_cache[HDL_SIMBLE_SRV_START] = result_data.p_srv_disc_data->att_handle; + hdl_cache[HDL_SIMBLE_SRV_END] = result_data.p_srv_disc_data->end_group_handle; + break; + + case DISC_RESULT_CHAR_UUID16: + handle = result_data.p_char_uuid16_disc_data->value_handle; + switch (result_data.p_char_uuid16_disc_data->uuid16) + { + case GATT_UUID_CHAR_SIMPLE_V1_READ: + hdl_cache[HDL_SIMBLE_V1_READ] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V2_WRITE: + hdl_cache[HDL_SIMBLE_V2_WRITE] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V3_NOTIFY: + hdl_cache[HDL_SIMBLE_V3_NOTIFY] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V4_INDICATE: + hdl_cache[HDL_SIMBLE_V4_INDICATE] = handle; + break; + + + case GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG: + hdl_cache[HDL_SIMBLE_V6_WRITE_LONG] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V7_READ_LONG: + hdl_cache[HDL_SIMBLE_V7_READ_LONG] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V8: + hdl_cache[HDL_SIMBLE_V8] = handle; + break; + + default: + /* have no intrest on this handle. */ + break; + } + + break; + + case DISC_RESULT_CHAR_DESC_UUID16: + /* When use client_all_char_descriptor_discovery. */ + if (result_data.p_char_desc_uuid16_disc_data->uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) + { + handle = result_data.p_char_desc_uuid16_disc_data->handle; + if ((handle > hdl_cache[HDL_SIMBLE_V3_NOTIFY]) + && (handle < hdl_cache[HDL_SIMBLE_V4_INDICATE])) + { + hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_SIMBLE_V4_INDICATE]) && + (handle < hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) && + (hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD] == 0)) + { + hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_SIMBLE_V8]) + && (hdl_cache[HDL_SIMBLE_V8_CCCD] == 0)) + { + hdl_cache[HDL_SIMBLE_V8_CCCD] = handle; + } + } + break; + + default: + APP_PRINT_ERROR0("simp_handle_discover_result: Invalid Discovery Result Type!"); + break; + } + } + + return; +} + +static void simp_ble_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_READ_RESULT; + + APP_PRINT_INFO2("simp_ble_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + + if (handle == hdl_cache[HDL_SIMBLE_V1_READ]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V1_READ; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.v1_read.p_value = p_value; + cb_data.cb_content.read_result.data.v1_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.v1_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V3_NOTIFY_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + cb_data.cb_content.read_result.data.v3_notify_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.v3_notify_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V4_INDICATE_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + cb_data.cb_content.read_result.data.v4_indicate_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.v4_indicate_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V7_READ_LONG]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V7_READ_LONG; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.v7_read.p_value = p_value; + cb_data.cb_content.read_result.data.v7_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.v7_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V8_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + cb_data.cb_content.read_result.data.v8_notify_ind_cccd = ccc_bit; + } + } + else + { + return; + } + /* Inform application the read result. */ + if (simp_client_cb) + { + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return; +} + +/** + * @brief Called by profile client layer, when write request complete. + * @param conn_id: connection ID. + * @param result: write request send success or not. + * @retval None + */ +static void simp_ble_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_WRITE_RESULT; + + APP_PRINT_INFO2("simp_ble_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.write_result.cause = cause; + + if (handle == hdl_cache[HDL_SIMBLE_V2_WRITE]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V2_WRITE; + } + else if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V3_NOTIFY_CCCD; + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V4_INDICATE_CCCD; + } + else if (handle == hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V6_WRITE_LONG; + } + else if (handle == hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V8_CCCD; + } + else + { + return; + } + /* Inform application the write result. */ + if (simp_client_cb) + { + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return; +} + +static T_APP_RESULT simp_ble_client_notif_ind_result_cb(uint8_t conn_id, bool notify, + uint16_t handle, + uint16_t value_size, uint8_t *p_value) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + + if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY]) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V3_NOTIFY; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE]) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V4_INDICATE; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_SIMBLE_V8]) + { + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + if (notify) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V8_NOTIFY; + + } + else + { + cb_data.cb_content.notif_ind_data.type = SIMP_V8_INDICATE; + } + } + else + { + return app_result; + } + /* Inform application the notif/ind result. */ + if (simp_client_cb) + { + app_result = (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return app_result; +} + +static void simp_ble_client_disconnect_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("simp_ble_client_disconnect_cb."); + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_disconnect_cb: failed invalid conn_id %d", conn_id); + return; + } + memset(&simp_table[conn_id], 0, sizeof(T_SIMP_LINK)); + return; +} + +/** + * @brief Simple BLE Client Callbacks. +*/ +const T_FUN_CLIENT_CBS simp_ble_client_cbs = +{ + simp_ble_client_discover_state_cb, //!< Discovery State callback function pointer + simp_ble_client_discover_result_cb, //!< Discovery result callback function pointer + simp_ble_client_read_result_cb, //!< Read response callback function pointer + simp_ble_client_write_result_cb, //!< Write result callback function pointer + simp_ble_client_notif_ind_result_cb, //!< Notify Indicate callback function pointer + simp_ble_client_disconnect_cb //!< Link disconnection callback function pointer +}; + +T_CLIENT_ID simp_ble_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > SIMP_MAX_LINKS) + { + APP_PRINT_ERROR1("simp_ble_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&simp_client, &simp_ble_client_cbs)) + { + simp_client = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("simp_ble_add_client failed"); + return simp_client; + } + APP_PRINT_INFO1("simp_ble_add_client: simp_client %d", simp_client); + + /* register callback for profile to inform application that some events happened. */ + simp_client_cb = app_cb; + simp_link_num = link_num; + size = simp_link_num * sizeof(T_SIMP_LINK); + simp_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + return simp_client; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_client.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_client.h new file mode 100644 index 00000000..10a72381 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_client.h @@ -0,0 +1,332 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_client.h + * @brief Head file for using Simple BLE Client. + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _COMPLETE_BLE_CLIENT_H_ +#define _COMPLETE_BLE_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include + +/** @addtogroup PROFILE_API Profile APIs + * @{ + */ + +/** @addtogroup Bluetooth_Clients Bluetooth Clients + * @{ + */ + +/** @defgroup SIMP_Client Simple Ble service client + * @brief Simple BLE service client + * @details + Simple BLE Profile is a customized BLE-based Profile. Simple ble service please refer to @ref SIMP_Service . + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Client_Exported_Macros SIMP Client Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_UUIDs1 SIMP UUIDs + * @brief Simple BLE Profile UUID definitions + * @{ + */ +#define GATT_UUID_SIMPLE_PROFILE 0xA00A +#define GATT_UUID_CHAR_SIMPLE_V1_READ 0xB001 +#define GATT_UUID_CHAR_SIMPLE_V2_WRITE 0xB002 +#define GATT_UUID_CHAR_SIMPLE_V3_NOTIFY 0xB003 +#define GATT_UUID_CHAR_SIMPLE_V4_INDICATE 0xB004 +#define GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG 0xB006 +#define GATT_UUID_CHAR_SIMPLE_V7_READ_LONG 0xB007 +#define GATT_UUID_CHAR_SIMPLE_V8 0xB008 +/** @} End of SIMP_UUIDs */ + +/** @brief Define links number. range: 0-4 */ +#define SIMP_MAX_LINKS 4 +/** End of SIMP_Client_Exported_Macros + * @} + */ + + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Client_Exported_Types SIMP Client Exported Types + * @brief + * @{ + */ + +/** @brief SIMP client handle type*/ +typedef enum +{ + HDL_SIMBLE_SRV_START, //!< start handle of simple ble service + HDL_SIMBLE_SRV_END, //!< end handle of simple ble service + HDL_SIMBLE_V1_READ, //!< V1 read characteristic value handle + HDL_SIMBLE_V2_WRITE, //!< V2 write characteristic value handle + HDL_SIMBLE_V3_NOTIFY, //!< V3 notify characteristic value handle + HDL_SIMBLE_V3_NOTIFY_CCCD, //!< V3 notify characteristic CCCD handle + HDL_SIMBLE_V4_INDICATE, //!< V4 indicate characteristic value handle + HDL_SIMBLE_V4_INDICATE_CCCD, //!< V4 indicate characteristic CCCD handle + HDL_SIMBLE_V6_WRITE_LONG, // V6 write long value handle + HDL_SIMBLE_V7_READ_LONG, // V7 read long value handle + HDL_SIMBLE_V8, // V3 notify value handle + HDL_SIMBLE_V8_CCCD, // V3 notify CCCD handle + HDL_SIMBLE_CACHE_LEN //!< handle cache length +} T_SIMP_HANDLE_TYPE; + +/** @brief SIMP client discovery state*/ +typedef enum +{ + DISC_SIMP_IDLE, + DISC_SIMP_START, + DISC_SIMP_DONE, + DISC_SIMP_FAILED +} T_SIMP_DISC_STATE; + +/** @brief SIMP client read type*/ +typedef enum +{ + SIMP_READ_V1_READ, + SIMP_READ_V3_NOTIFY_CCCD, + SIMP_READ_V4_INDICATE_CCCD, + SIMP_READ_V7_READ_LONG = 4, + SIMP_READ_V8_CCCD = 5, +} T_SIMP_READ_TYPE; + +/** @brief SIMP client read value*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_SIMP_READ_VALUE; + +/** @brief SIMP client read data*/ +typedef union +{ + T_SIMP_READ_VALUE v1_read; + bool v3_notify_cccd; + bool v4_indicate_cccd; + uint16_t v8_notify_ind_cccd; + T_SIMP_READ_VALUE v7_read; +} T_SIMP_READ_DATA; + +/** @brief SIMP client read result*/ +typedef struct +{ + T_SIMP_READ_TYPE type; + T_SIMP_READ_DATA data; + uint16_t cause; +} T_SIMP_READ_RESULT; + + +/** @brief SIMP client write type*/ +typedef enum +{ + SIMP_WRITE_V2_WRITE, + SIMP_WRITE_V3_NOTIFY_CCCD, + SIMP_WRITE_V4_INDICATE_CCCD, + SIMP_WRITE_V6_WRITE_LONG, + SIMP_WRITE_V8_CCCD, +} T_SIMP_WRTIE_TYPE; + +/** @brief SIMP client write result*/ +typedef struct +{ + T_SIMP_WRTIE_TYPE type; + uint16_t cause; +} T_SIMP_WRITE_RESULT; + +/** @brief SIMP client notif/ind receive type*/ +typedef enum +{ + SIMP_V3_NOTIFY, + SIMP_V4_INDICATE, + SIMP_V8_NOTIFY, + SIMP_V8_INDICATE, +} T_SIMP_NOTIF_IND_TYPE; + +/** @brief SIMP client notif/ind receive data*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_SIMP_NOTIF_IND_VALUE; + +/** @brief SIMP client notif/ind receive content*/ +typedef struct +{ + T_SIMP_NOTIF_IND_TYPE type; + T_SIMP_NOTIF_IND_VALUE data; +} T_SIMP_NOTIF_IND_DATA; + +/** @brief SIMP client callback type*/ +typedef enum +{ + SIMP_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + SIMP_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + SIMP_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + SIMP_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_SIMP_CLIENT_CB_TYPE; + +/** @brief SIMP client callback content*/ +typedef union +{ + T_SIMP_DISC_STATE disc_state; + T_SIMP_READ_RESULT read_result; + T_SIMP_WRITE_RESULT write_result; + T_SIMP_NOTIF_IND_DATA notif_ind_data; +} T_SIMP_CLIENT_CB_CONTENT; + +/** @brief SIMP client callback data*/ +typedef struct +{ + T_SIMP_CLIENT_CB_TYPE cb_type; + T_SIMP_CLIENT_CB_CONTENT cb_content; +} T_SIMP_CLIENT_CB_DATA; + +/** End of SIMP_Client_Exported_Types * @} */ + +/** @defgroup SIMP_Client_Exported_Functions SIMP Client Exported Functions + * @{ + */ + +/** + * @brief Add simple ble service client to application. + * @param[in] app_cb pointer of app callback function to handle specific client module data. + * @param[in] link_num initialize link num. + * @return Client ID of the specific client module. + * @retval 0xff failed. + * @retval other success. + * + * Example usage + * \code{.c} + void app_le_profile_init(void) + { + client_init(1); + simple_ble_client_id = simp_ble_add_client(app_client_callback, APP_MAX_LINKS); + } + * \endcode + */ +T_CLIENT_ID simp_ble_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num); + +/** + * @brief Used by application, to start the discovery procedure of Simple BLE server. + * @param[in] conn_id connection ID. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_start_discovery(uint8_t conn_id); + +/** + * @brief Used by application, to read data from server by using handles. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_read_by_handle(uint8_t conn_id, T_SIMP_READ_TYPE read_type); + +/** + * @brief Used by application, to read data from server by using UUIDs. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_read_by_uuid(uint8_t conn_id, T_SIMP_READ_TYPE read_type); + +/** + * @brief Used by application, to write data of V2 write Characteristic. + * @param[in] conn_id connection ID. + * @param[in] length write data length + * @param[in] p_value point the value to write + * @param[in] type write type. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_write_v2_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type); + +/** + * @brief Used by application, to send write request to peer server's V6 Long Write Characteristic. + * @param conn_id: connection ID. + * @param length: value length. + * @param p_value: value point. + * @retval true--send request to upper stack success. + * false--send request to upper stack failed. + */ +bool simp_ble_client_write_v6_char(uint8_t conn_id, uint16_t length, uint8_t *p_value); +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param[in] conn_id connection ID. + * @param[in] notify 0--disable the notification, 1--enable the notification. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_set_v3_notify(uint8_t conn_id, bool notify); + +/** + * @brief Used by application, to enable or disable the indication of peer server's V4 Indicate Characteristic. + * @param[in] conn_id connection ID. + * @param[in] ind 0--disable the indication, 1--enable the indication. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_set_v4_ind(uint8_t conn_id, bool ind); + +bool simp_ble_client_set_v8_cccd(uint8_t conn_id, uint16_t cccd_bits); + + + + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool simp_ble_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief Used by application, to set handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool simp_ble_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** @} End of SIMP_Client_Exported_Functions */ + +/** @} End of SIMP_Client */ + +/** @} End of Bluetooth_Clients */ + +/** @} End of PROFILE_API */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SIMPLE_BLE_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_service.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_service.c new file mode 100644 index 00000000..36ee786c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_service.c @@ -0,0 +1,609 @@ +/** +********************************************************************************************************* +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file simple_ble_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date +* @version +********************************************************************************************************* +*/ + +#include +#include +#include +#include + +#define GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG 0xB006 +#define GATT_UUID_CHAR_SIMPLE_V7_READ_LONG 0xB007 +#define GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE 0xB008 + +T_SERVER_ID simp_service_id; +/**< Function pointer used to send event to application from simple profile. Initiated in simp_ble_service_add_service. */ +static P_FUN_SERVER_GENERAL_CB pfn_simp_ble_service_cb = NULL; + +/**< Value of simple read characteristic. */ +static uint8_t simple_v1_read_value = 0xf0; +uint8_t v7_char_value[SIMP_READ_V7_MAX_LEN] = {0}; +uint16_t v7_char_value_len = SIMP_READ_V7_MAX_LEN; +char v1_user_descr[] = "V1 read characteristic"; + +/**< @brief profile/service definition. */ +const T_ATTRIB_APPL simple_ble_service_tbl[] = +{ + /* <>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_SIMPLE_PROFILE), /* service UUID */ + HI_WORD(GATT_UUID_SIMPLE_PROFILE) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + /* <> demo for read */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_USER_DESCR), + HI_WORD(GATT_UUID_CHAR_USER_DESCR), + }, + (sizeof(v1_user_descr) - 1), /* bValueLen */ + (void *)v1_user_descr, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for write */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE_AUTHEN_SIGNED) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <>, demo for notify */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for write Long*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <> demo for read Long*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V7_READ_LONG), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V7_READ_LONG) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE | GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, +}; + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value) +{ + bool ret = true; + + switch (param_type) + { + default: + ret = false; + break; + case SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL: + if (len == 1) + { + simple_v1_read_value = *(uint8_t *)p_value; + } + else + { + ret = false; + } + break; + + case SIMPLE_BLE_SERVICE_PARAM_V7_LEN: + if (len <= SIMP_READ_V7_MAX_LEN) + { + memcpy(v7_char_value, p_value, len); + v7_char_value_len = len; + } + else + { + ret = false; + } + break; + } + + if (!ret) + { + APP_PRINT_ERROR0("simp_ble_service_set_parameter failed"); + } + + return ret; +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param attrib_index Attribute index of getting characteristic data. + * @param offset Used for Blob Read. + * @param p_length length of getting characteristic data. + * @param pp_value data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT simp_ble_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + default: + APP_PRINT_ERROR1("simp_ble_service_attr_read_cb, Attr not found, index %d", attrib_index); + cause = APP_RESULT_ATTR_NOT_FOUND; + break; + case SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = SIMP_READ_V1; + callback_data.conn_id = conn_id; + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = &simple_v1_read_value; + *p_length = sizeof(simple_v1_read_value); + } + break; + case SIMPLE_BLE_SERVICE_CHAR_V7_READ_LONG_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = SIMP_READ_V7; + callback_data.conn_id = conn_id; + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = v7_char_value; + *p_length = v7_char_value_len; + } + break; + } + + return (cause); +} + + +void simple_write_post_callback(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t length, uint8_t *p_value) +{ + APP_PRINT_INFO4("simple_write_post_callback: conn_id %d, service_id %d, attrib_index 0x%x, length %d", + conn_id, service_id, attrib_index, length); +} +/** + * @brief write characteristic data from service. + * + * @param conn_id + * @param service_id ServiceID to be written. + * @param attrib_index Attribute index of characteristic. + * @param length length of value to be written. + * @param p_value value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT simp_ble_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + TSIMP_CALLBACK_DATA callback_data; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("simp_ble_service_attr_write_cb write_type = 0x%x", write_type); + *p_write_ind_post_proc = simple_write_post_callback; + if (SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX == attrib_index) + { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = SIMP_WRITE_V2; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + } + else if (SIMPLE_BLE_SERVICE_CHAR_V6_WRITE_INDEX == attrib_index) + { + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = SIMP_WRITE_V6; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(simp_service_id, (void *)&callback_data); + } + } + else + { + APP_PRINT_ERROR2("simp_ble_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, + length); + cause = APP_RESULT_ATTR_NOT_FOUND; + } + return cause; +} + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("simp_ble_service_send_v3_notify"); + // send notification to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX, p_value, + length, + GATT_PDU_TYPE_ANY); +} + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("simp_ble_service_send_v4_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX, p_value, + length, GATT_PDU_TYPE_ANY); +} + +bool simp_ble_service_simple_v8_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("<-- simp_ble_service_simple_v8_notify"); + // send notification to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX, + p_value, length, GATT_PDU_TYPE_NOTIFICATION); +} + +bool simp_ble_service_simple_v8_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("<-- simp_ble_service_simple_v8_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX, + p_value, + length, GATT_PDU_TYPE_INDICATION); +} + + +void simp_ble_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index, + uint16_t cccbits) +{ + TSIMP_CALLBACK_DATA callback_data; + bool is_handled = false; + callback_data.conn_id = conn_id; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + APP_PRINT_INFO2("simp_ble_service_cccd_update_cb: index = %d, cccbits 0x%x", index, cccbits); + switch (index) + { + case SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V3_ENABLE; + } + else + { + // Disable Notification + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V3_DISABLE; + } + is_handled = true; + } + break; + case SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V4_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V4_DISABLE; + } + is_handled = true; + } + break; + + case SIMPLE_BLE_SERVICE_CHAR_V8_CCCD_INDEX: + { + if (cccbits == GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE; + } + else if (cccbits == GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE; + } + else if (cccbits == GATT_CLIENT_CHAR_CONFIG_NOTIFY_INDICATE) + { + // Disable Indication + callback_data.msg_data.notification_indification_index = + SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_DISABLE; + } + + is_handled = true; + } + break; + default: + break; + } + /* Notify Application. */ + if (pfn_simp_ble_service_cb && (is_handled == true)) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } +} + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS simp_ble_service_cbs = +{ + simp_ble_service_attr_read_cb, // Read callback function pointer + simp_ble_service_attr_write_cb, // Write callback function pointer + simp_ble_service_cccd_update_cb // CCCD update callback function pointer +}; + +/** + * @brief add Simple BLE service to application. + * + * @param[in] p_func pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + */ +T_SERVER_ID simp_ble_service_add_service(void *p_func) +{ + if (false == server_add_service(&simp_service_id, + (uint8_t *)simple_ble_service_tbl, + sizeof(simple_ble_service_tbl), + simp_ble_service_cbs)) + { + APP_PRINT_ERROR0("simp_ble_service_add_service: fail"); + simp_service_id = 0xff; + return simp_service_id; + } + + pfn_simp_ble_service_cb = (P_FUN_SERVER_GENERAL_CB)p_func; + return simp_service_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_service.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_service.h new file mode 100644 index 00000000..d9c3644f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/complete_ble_service.h @@ -0,0 +1,255 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _COMPLETE_BLE_SERVICE_H_ +#define _COMPLETE_BLE_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include +#include + +/** @addtogroup PROFILE_API Profile APIs + * @{ + */ + + +/** @addtogroup Bluetooth_Services Bluetooth Services + * @{ + */ + +/** @defgroup SIMP_Service Simple Ble Service + * @brief Simple BLE service + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Macros SIMP Service Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +typedef enum +{ + SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL = 0x01, + SIMPLE_BLE_SERVICE_PARAM_V7_LEN = 0x02, +} T_SIMP_PARAM_TYPE; + +/** @} */ + + + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ +/** @brief Index of each characteristic in Demo Profile service database. */ +#define SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX 0x02 +#define SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX 0x05 +#define SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX 0x07 +#define SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX 0x0a +#define SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX + 1) +#define SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX + 1) +#define SIMPLE_BLE_SERVICE_CHAR_V6_WRITE_INDEX 0xd +#define SIMPLE_BLE_SERVICE_CHAR_V7_READ_LONG_INDEX 0xf +#define SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX 0x11 +#define SIMPLE_BLE_SERVICE_CHAR_V8_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX + 1) + +/** @defgroup SIMP_Service_Read_Info SIMP Service Read Info + * @brief Parameter for reading characteristic value. + * @{ + */ +#define SIMP_READ_V1 1 +#define SIMP_READ_V7 2 +/** @} */ + +/** @defgroup SIMP_Service_Write_Info SIMP Service Write Info + * @brief Parameter for writing characteristic value. + * @{ + */ +#define SIMP_WRITE_V2 1 +#define SIMP_WRITE_V6 2 +/** @} */ + +/** @defgroup SIMP_Service_Notify_Indicate_Info SIMP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define SIMP_NOTIFY_INDICATE_V3_ENABLE 1 +#define SIMP_NOTIFY_INDICATE_V3_DISABLE 2 +#define SIMP_NOTIFY_INDICATE_V4_ENABLE 3 +#define SIMP_NOTIFY_INDICATE_V4_DISABLE 4 +#define SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE 7 +#define SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE 8 +#define SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE 9 +#define SIMP_NOTIFY_INDICATE_V8_DISABLE 10 +/** @} */ + +#define SIMP_READ_V7_MAX_LEN 300 + +/** @} End of SIMP_Service_Upstream_Message */ + + + +/** @} End of SIMP_Service_Exported_Macros */ +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +typedef struct +{ + uint8_t opcode; //!< ref: @ref SIMP_Control_Point_OpCodes, @ref SIMP_Service_Write_Info + T_WRITE_TYPE write_type; + uint16_t len; + uint8_t *p_value; +} TSIMP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + TSIMP_WRITE_MSG write; +} TSIMP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct +{ + uint8_t conn_id; + T_SERVICE_CALLBACK_TYPE msg_type; + TSIMP_UPSTREAM_MSG_DATA msg_data; +} TSIMP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief + * @{ + */ + +/** + * @brief add Simple BLE service to application. + * + * @param[in] p_func pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + */ +T_SERVER_ID simp_ble_service_add_service(void *p_func); + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value); + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_simple_v8_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, + uint16_t length); + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_simple_v8_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +/** @} End of Bluetooth_Services */ + +/** @} End of PROFILE_API */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/gap_test_app.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/gap_test_app.c new file mode 100644 index 00000000..3fe7f59f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/gap_test_app.c @@ -0,0 +1,1963 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_test_app.c + * @brief Gap roles test application implementation. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif +#if F_BT_LE_PRIVACY_SUPPORT +#include +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#include +#endif +#if F_BT_ANCS_CLIENT_SUPPORT +#include +#include +#endif +#include +#if APP_GENERAL_CLIENT_TEST +#include +#endif +/*============================================================================* + * Variables + *============================================================================*/ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_CLIENT_ID simple_ble_client_id = 0xf0; /**< Simple ble service client id*/ +T_CLIENT_ID gaps_client_id = 0xf0; /**< gap service client id*/ +#if APP_GENERAL_CLIENT_TEST +T_CLIENT_ID gcs_client_id = 0xf0; +#endif +#endif +T_SERVER_ID simp_srv_id = 0xff; /**< Simple ble service id*/ +T_SERVER_ID hid_srv_id = 0xff; + +T_GAP_TEST_CASE gap_test_case = GAP_TC_00_NORMAL; +T_GAP_V3_NOTIF_TEST gap_v3_notif_test; + +T_GAP_DEV_STATE gap_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +#if F_BT_LE_PRIVACY_SUPPORT +T_PRIVACY_STATE app_privacy_state = PRIVACY_STATE_INIT; +T_PRIVACY_ADDR_RESOLUTION_STATE app_privacy_resolution_state = PRIVACY_ADDR_RESOLUTION_DISABLED; +#endif +/*============================================================================* + * Functions + *============================================================================*/ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg); +void app_handle_bond_modify_msg(T_LE_BOND_MODIFY_TYPE type, T_LE_KEY_ENTRY *p_entry); +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + uint8_t rx_char; + + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + { + app_handle_gap_msg(&io_msg); + } + break; + case IO_MSG_TYPE_UART: + /* We handle user command informations from Data UART in this branch. */ + rx_char = (uint8_t)io_msg.subtype; + user_cmd_collect(&user_cmd_if, &rx_char, sizeof(rx_char), user_cmd_table); + break; +#if F_BT_ANCS_CLIENT_SUPPORT + case IO_MSG_TYPE_ANCS: + { + ancs_handle_msg(&io_msg); + } + break; +#endif + default: + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_DEV_STATE_CHANGE + * @note All the gap device state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] new_state New gap device state + * @param[in] cause GAP device state change cause + * @return void + */ +void app_handle_dev_state_evt(T_GAP_DEV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO5("app_handle_dev_state_evt: init state %d, adv state %d, scan state %d, conn state %d, cause 0x%x", + new_state.gap_init_state, new_state.gap_adv_state, + new_state.gap_scan_state, new_state.gap_conn_state, cause); +#if F_BT_LE_PRIVACY_SUPPORT + if (gap_test_case == GAP_TC_03_PRIVACY) + { + if ((new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + && (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + && (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + && (new_state.gap_conn_state == GAP_CONN_DEV_STATE_IDLE)) + { + privacy_handle_resolv_list(); + } + } +#endif + if (gap_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + uint8_t bt_addr[6]; + data_uart_print("GAP stack ready\r\n"); + gap_get_param(GAP_PARAM_BD_ADDR, bt_addr); + data_uart_print("local bd addr: 0x%2x:%2x:%2x:%2x:%2x:%2x\r\n", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); + } + } + + if (gap_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + data_uart_print("GAP scan stop\r\n"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + data_uart_print("GAP scan start\r\n"); + } + } + + if (gap_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + data_uart_print("GAP adv stoped:because conn\r\n"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + data_uart_print("GAP adv stoped\r\n"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + data_uart_print("GAP adv start\r\n"); + } + } + + if (gap_dev_state.gap_conn_state != new_state.gap_conn_state) + { + APP_PRINT_INFO2("conn state: %d -> %d", + gap_dev_state.gap_conn_state, + new_state.gap_conn_state); + } + + gap_dev_state = new_state; +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_STATE_CHANGE + * @note All the gap conn state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New gap connection state + * @param[in] cause Use this cause when new_state is GAP_CONN_STATE_DISCONNECTED + * @return void + */ +void app_handle_conn_state_evt(uint8_t conn_id, T_GAP_CONN_STATE new_state, uint16_t disc_cause) +{ + if (conn_id >= APP_MAX_LINKS) + { + return; + } + + APP_PRINT_INFO4("app_handle_conn_state_evt: conn_id %d, conn_state(%d -> %d), disc_cause 0x%x", + conn_id, app_link_table[conn_id].conn_state, new_state, disc_cause); + + app_link_table[conn_id].conn_state = new_state; + switch (new_state) + { + case GAP_CONN_STATE_DISCONNECTED: + { + if ((disc_cause != (HCI_ERR | HCI_ERR_REMOTE_USER_TERMINATE)) + && (disc_cause != (HCI_ERR | HCI_ERR_LOCAL_HOST_TERMINATE))) + { + APP_PRINT_ERROR2("app_handle_conn_state_evt: connection lost, conn_id %d, cause 0x%x", conn_id, + disc_cause); + } + + data_uart_print("Disconnect conn_id %d, cause 0x%x\r\n", conn_id, disc_cause); + memset(&app_link_table[conn_id], 0, sizeof(T_APP_LINK)); + if (gap_v3_notif_test.v3_tx_num != 0 && gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + memset(&gap_v3_notif_test, 0, sizeof(T_GAP_V3_NOTIF_TEST)); + } + } + break; + + case GAP_CONN_STATE_CONNECTED: + { + uint8_t local_bd_type; + uint8_t features[8]; + uint8_t remote_bd_type; + le_get_conn_param(GAP_PARAM_CONN_LOCAL_BD_TYPE, &local_bd_type, conn_id); + le_get_conn_param(GAP_PARAM_CONN_BD_ADDR_TYPE, &remote_bd_type, conn_id); + APP_PRINT_INFO3("GAP_CONN_STATE_CONNECTED: conn_id %d, local_bd_type %d, remote_bd_type %d", + conn_id, local_bd_type, remote_bd_type); +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + { + uint8_t tx_phy; + uint8_t rx_phy; + le_get_conn_param(GAP_PARAM_CONN_RX_PHY_TYPE, &rx_phy, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TX_PHY_TYPE, &tx_phy, conn_id); + APP_PRINT_INFO2("GAP_CONN_STATE_CONNECTED: tx_phy %d, rx_phy %d", tx_phy, rx_phy); + } +#endif +#if F_BT_LE_READ_REMOTE_FEATS + le_get_conn_param(GAP_PARAM_CONN_REMOTE_FEATURES, &features, conn_id); +#endif +#if F_BT_LE_5_0_CSA2_SUPPORT + { + uint8_t csa; + le_get_conn_param(GAP_PARAM_CONN_CHANN_ALGORITHM, &csa, conn_id); + APP_PRINT_INFO1("GAP_CONN_STATE_CONNECTED: csa %d", csa); + } +#endif + data_uart_print("connected success conn_id = %d, local_bd_type %d\r\n", conn_id, + local_bd_type); + if (gap_test_case == GAP_TC_09_SLAVE_LATENCY) + { + le_update_conn_param(conn_id, 10, 10, 50, 500, 19, 19); + } + } + break; + + default: + break; + + } +} + +/** + * @brief Handle msg GAP_MSG_LE_AUTHEN_STATE_CHANGE + * @note All the gap authentication state events are pre-handled in this function. + * Then the event handling function shall be called according to the new_state + * @param[in] conn_id Connection ID + * @param[in] new_state New authentication state + * @param[in] cause Use this cause when new_state is GAP_AUTHEN_STATE_COMPLETE + * @return void + */ +void app_handle_authen_state_evt(uint8_t conn_id, uint8_t new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_authen_state_evt:conn_id %d, cause 0x%x", conn_id, cause); + + switch (new_state) + { + case GAP_AUTHEN_STATE_STARTED: + { + data_uart_print("pair start\r\n"); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_STARTED"); + } + break; + + case GAP_AUTHEN_STATE_COMPLETE: + { + if (cause == GAP_SUCCESS) + { + data_uart_print("Pair success\r\n"); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair success"); + { + uint8_t addr[6]; + T_GAP_REMOTE_ADDR_TYPE bd_type; + uint8_t resolved_addr[6]; + T_GAP_IDENT_ADDR_TYPE resolved_bd_type; + le_get_conn_addr(conn_id, addr, &bd_type); + if (bd_type == GAP_REMOTE_ADDR_LE_RANDOM) + { + if (le_resolve_random_address(addr, resolved_addr, &resolved_bd_type)) + { + APP_PRINT_INFO2("GAP_AUTHEN_STATE_COMPLETE: resolved_addr %s, resolved_addr_type %d", + TRACE_BDADDR(resolved_addr), resolved_bd_type); + } + else + { + APP_PRINT_INFO0("GAP_AUTHEN_STATE_COMPLETE: resolved addr failed"); + } + } + } + } + else + { + data_uart_print("Pair failed: cause 0x%x\r\n", cause); + APP_PRINT_INFO0("app_handle_authen_state_evt: GAP_AUTHEN_STATE_COMPLETE pair failed"); + } + } + break; + + default: + { + APP_PRINT_ERROR1("app_handle_authen_state_evt: unknown newstate %d", new_state); + } + break; + } +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_MTU_INFO + * @note This msg is used to inform APP that exchange mtu procedure is completed. + * @param[in] conn_id Connection ID + * @param[in] mtu_size New mtu size + * @return void + */ +void app_handle_conn_mtu_info_evt(uint8_t conn_id, uint16_t mtu_size) +{ + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", conn_id, mtu_size); +} + +/** + * @brief Handle msg GAP_MSG_LE_CONN_PARAM_UPDATE + * @note All the connection parameter update change events are pre-handled in this function. + * @param[in] conn_id Connection ID + * @param[in] status New update state + * @param[in] cause Use this cause when status is GAP_CONN_PARAM_UPDATE_STATUS_FAIL + * @return void + */ +void app_handle_conn_param_update_evt(uint8_t conn_id, uint8_t status, uint16_t cause) +{ + switch (status) + { + case GAP_CONN_PARAM_UPDATE_STATUS_SUCCESS: + { + uint16_t conn_interval; + uint16_t conn_slave_latency; + uint16_t conn_supervision_timeout; + + le_get_conn_param(GAP_PARAM_CONN_INTERVAL, &conn_interval, conn_id); + le_get_conn_param(GAP_PARAM_CONN_LATENCY, &conn_slave_latency, conn_id); + le_get_conn_param(GAP_PARAM_CONN_TIMEOUT, &conn_supervision_timeout, conn_id); + data_uart_print("conn param update success\r\n"); + APP_PRINT_INFO4("app_handle_conn_param_update_evt update success:conn_id %d, conn_interval 0x%x, conn_slave_latency 0x%x, conn_supervision_timeout 0x%x", + conn_id, conn_interval, conn_slave_latency, conn_supervision_timeout); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_FAIL: + { + data_uart_print("conn param update fail\r\n"); + APP_PRINT_ERROR2("app_handle_conn_param_update_evt update failed: conn_id %d, cause 0x%x", + conn_id, cause); + } + break; + + case GAP_CONN_PARAM_UPDATE_STATUS_PENDING: + { + APP_PRINT_INFO1("app_handle_conn_param_update_evt update pending: conn_id %d", conn_id); + } + break; + default: + break; + } +} + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void app_handle_ext_adv_state_evt(uint8_t adv_handle, T_GAP_EXT_ADV_STATE new_state, uint16_t cause) +{ + APP_PRINT_INFO2("app_handle_ext_adv_state_evt: adv_handle = %d newState = %d", + adv_handle, new_state); + switch (new_state) + { + /*device is disconnected.*/ + case EXT_ADV_STATE_IDLE: + { + APP_PRINT_INFO2("EXT_ADV_STATE_IDLE: adv_handle %d, cause 0x%x", + adv_handle, cause); + } + break; + + /*device is connected*/ + case EXT_ADV_STATE_ADVERTISING: + { + APP_PRINT_INFO2("EXT_ADV_STATE_ADVERTISING: adv_handle %d, cause 0x%x", + adv_handle, cause); + } + break; + + /*error comes here*/ + default: + break; + } +} +#endif +/** + * @brief All the BT GAP MSG are pre-handled in this function. + * @note Then the event handling function shall be called according to the + * subtype of T_IO_MSG + * @param[in] p_gap_msg Pointer to GAP msg + * @return void + */ +void app_handle_gap_msg(T_IO_MSG *p_gap_msg) +{ + T_LE_GAP_MSG gap_msg; + uint8_t conn_id; + memcpy(&gap_msg, &p_gap_msg->u.param, sizeof(p_gap_msg->u.param)); + + APP_PRINT_TRACE1("app_handle_gap_msg: subtype %d", p_gap_msg->subtype); + switch (p_gap_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + app_handle_dev_state_evt(gap_msg.msg_data.gap_dev_state_change.new_state, + gap_msg.msg_data.gap_dev_state_change.cause); + } + break; + + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + app_handle_conn_state_evt(gap_msg.msg_data.gap_conn_state_change.conn_id, + (T_GAP_CONN_STATE)gap_msg.msg_data.gap_conn_state_change.new_state, + gap_msg.msg_data.gap_conn_state_change.disc_cause); + } + break; + + case GAP_MSG_LE_CONN_MTU_INFO: + { + app_handle_conn_mtu_info_evt(gap_msg.msg_data.gap_conn_mtu_info.conn_id, + gap_msg.msg_data.gap_conn_mtu_info.mtu_size); + } + break; + + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + app_handle_conn_param_update_evt(gap_msg.msg_data.gap_conn_param_update.conn_id, + gap_msg.msg_data.gap_conn_param_update.status, + gap_msg.msg_data.gap_conn_param_update.cause); + } + break; + + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + app_handle_authen_state_evt(gap_msg.msg_data.gap_authen_state.conn_id, + gap_msg.msg_data.gap_authen_state.new_state, + gap_msg.msg_data.gap_authen_state.status); + } + break; + + case GAP_MSG_LE_BOND_JUST_WORK: + { + conn_id = gap_msg.msg_data.gap_bond_just_work_conf.conn_id; + le_bond_just_work_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + APP_PRINT_INFO0("GAP_MSG_LE_BOND_JUST_WORK"); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_passkey_display.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d", + conn_id, display_value); + le_bond_passkey_display_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + } + break; + + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + uint32_t display_value = 0; + conn_id = gap_msg.msg_data.gap_bond_user_conf.conn_id; + le_bond_get_display_key(conn_id, &display_value); + APP_PRINT_INFO2("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d", + conn_id, display_value); + data_uart_print("GAP_MSG_LE_BOND_USER_CONFIRMATION: conn_id %d, passkey %d\r\n", + conn_id, + display_value); + //le_bond_user_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + //uint32_t passkey = 888888; + conn_id = gap_msg.msg_data.gap_bond_passkey_input.conn_id; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d, key_press %d", + conn_id, gap_msg.msg_data.gap_bond_passkey_input.key_press); + data_uart_print("GAP_MSG_LE_BOND_PASSKEY_INPUT: conn_id %d\r\n", conn_id); + //le_bond_passkey_input_confirm(conn_id, passkey, GAP_CFM_CAUSE_ACCEPT); + } + break; +#if F_BT_LE_SMP_OOB_SUPPORT + case GAP_MSG_LE_BOND_OOB_INPUT: + { + conn_id = gap_msg.msg_data.gap_bond_oob_input.conn_id; + APP_PRINT_INFO1("GAP_MSG_LE_BOND_OOB_INPUT: conn_id %d", conn_id); + data_uart_print("GAP_MSG_LE_BOND_OOB_INPUT conn id=%d\r\n", conn_id); + //uint8_t oob_data[GAP_OOB_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + //le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + //le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + } + break; +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case GAP_MSG_LE_EXT_ADV_STATE_CHANGE: + { + app_handle_ext_adv_state_evt(gap_msg.msg_data.gap_ext_adv_state_change.adv_handle, + (T_GAP_EXT_ADV_STATE)gap_msg.msg_data.gap_ext_adv_state_change.new_state, + gap_msg.msg_data.gap_ext_adv_state_change.cause); + } + break; +#endif + default: + APP_PRINT_ERROR1("app_handle_gap_msg: unknown subtype %d", p_gap_msg->subtype); + break; + } +} + +/** + * @brief Use 16 bit uuid to filter scan information + * @param[in] uuid 16 bit UUID. + * @param[in] scan_info point to scan information data. + * @return filter result + * @retval true found success + * @retval false not found + */ +bool filter_scan_info_by_uuid(uint16_t uuid, T_LE_SCAN_INFO *scan_info) +{ + uint8_t buffer[32]; + uint8_t pos = 0; + + while (pos < scan_info->data_len) + { + /* Length of the AD structure. */ + uint8_t length = scan_info->data[pos++]; + uint8_t type; + + if ((length > 0x01) && ((pos + length) <= 31)) + { + /* Copy the AD Data to buffer. */ + memcpy(buffer, scan_info->data + pos + 1, length - 1); + /* AD Type, one octet. */ + type = scan_info->data[pos]; + + switch (type) + { + case GAP_ADTYPE_16BIT_MORE: + case GAP_ADTYPE_16BIT_COMPLETE: + case GAP_ADTYPE_SERVICES_LIST_16BIT: + { + uint16_t *p_uuid = (uint16_t *)(buffer); + uint8_t i = length - 1; + + while (i >= 2) + { + APP_PRINT_INFO2(" AD Data: UUID16 List Item %d = 0x%x", i / 2, *p_uuid); + if (*p_uuid == uuid) + { + return true; + } + p_uuid++; + i -= 2; + } + } + break; + + default: + break; + } + } + + pos += length; + } + return false; +} + +#if F_BT_LE_APP_KEY_MANAGER +void app_handle_authen_result_ind(T_LE_AUTHEN_RESULT_IND *auth_ind) +{ + APP_PRINT_INFO5("app_handle_authen_result_ind: bd_addr %s, remote_addr_type %d, key_len %d, key_type %d, cause 0x%x", + TRACE_BDADDR(auth_ind->bd_addr), + auth_ind->remote_addr_type, + auth_ind->key_len, + auth_ind->key_type, + auth_ind->cause); + le_bond_authen_result_confirm(auth_ind->bd_addr, auth_ind->remote_addr_type, + auth_ind->key_type, GAP_CFM_CAUSE_ACCEPT); +} +void app_handle_authen_key_req_ind(T_LE_AUTHEN_KEY_REQ_IND *key_req_ind) +{ + APP_PRINT_INFO3("app_handle_authen_key_req_ind: bd_addr %s, remote_addr_type %d, key_type %d", + TRACE_BDADDR(key_req_ind->bd_addr), + key_req_ind->remote_addr_type, + key_req_ind->key_type); + le_bond_authen_key_req_confirm(key_req_ind->bd_addr, + key_req_ind->remote_addr_type, + 0, + NULL, + key_req_ind->key_type, + GAP_CFM_CAUSE_REJECT + ); +} +void app_handle_gatt_server_store_ind(T_LE_GATT_SERVER_STORE_IND *store_ind) +{ + APP_PRINT_INFO4("app_handle_gatt_server_store_ind: bd_addr %s, remote_addr_type %d, op %d, data_len %d", + TRACE_BDADDR(store_ind->bd_addr), + store_ind->remote_addr_type, + store_ind->op, + store_ind->data_len); + le_bond_gatt_server_store_confirm(store_ind->op, + store_ind->bd_addr, + store_ind->remote_addr_type, + 0, + NULL, + GAP_CFM_CAUSE_REJECT + ); +} +#endif + +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CB_DATA *p_data = (T_LE_CB_DATA *)p_cb_data; + + switch (cb_type) + { + /* common msg*/ + case GAP_MSG_LE_READ_RSSI: + APP_PRINT_INFO3("GAP_MSG_LE_READ_RSSI:conn_id 0x%x cause 0x%x rssi %d", + p_data->p_le_read_rssi_rsp->conn_id, + p_data->p_le_read_rssi_rsp->cause, + p_data->p_le_read_rssi_rsp->rssi); + break; +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_WRITE_DEFAULT_DATA_LEN: + APP_PRINT_INFO1("GAP_MSG_LE_WRITE_DEFAULT_DATA_LEN: cause 0x%x", + p_data->le_cause.cause); + break; + + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_DATA_LEN_CHANGE_INFO: conn_id %d, max_tx_octets 0x%x, max_tx_time 0x%x, max_rx_octets 0x%x, max_rx_time 0x%x", + p_data->p_le_data_len_change_info->conn_id, + p_data->p_le_data_len_change_info->max_tx_octets, + p_data->p_le_data_len_change_info->max_tx_time, + p_data->p_le_data_len_change_info->max_rx_octets, + p_data->p_le_data_len_change_info->max_rx_time); + break; + + case GAP_MSG_LE_SET_DATA_LEN: + APP_PRINT_INFO2("GAP_MSG_LE_SET_DATA_LEN: conn_id 0x%x, cause 0x%x", + p_data->p_le_set_data_len_rsp->conn_id, + p_data->p_le_set_data_len_rsp->cause); + break; +#endif + case GAP_MSG_LE_MODIFY_WHITE_LIST: + APP_PRINT_INFO2("GAP_MSG_LE_MODIFY_WHITE_LIST: operation %d, cause 0x%x", + p_data->p_le_modify_white_list_rsp->operation, + p_data->p_le_modify_white_list_rsp->cause); + break; + + case GAP_MSG_LE_SCAN_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_SCAN_INFO:adv_type 0x%x, bd_addr %s, remote_addr_type %d, rssi %d, data_len %d", + p_data->p_le_scan_info->adv_type, + TRACE_BDADDR(p_data->p_le_scan_info->bd_addr), + p_data->p_le_scan_info->remote_addr_type, + p_data->p_le_scan_info->rssi, + p_data->p_le_scan_info->data_len); + + /* User can split interested information by using the function as follow. */ + if (filter_scan_info_by_uuid(GATT_UUID_SIMPLE_PROFILE, p_data->p_le_scan_info)) + { + APP_PRINT_INFO0("Found simple ble service"); + link_mgr_add_device(p_data->p_le_scan_info->bd_addr, p_data->p_le_scan_info->remote_addr_type); + } + /* If you want to parse the scan info, please reference function app_parse_scan_info in observer app. */ + break; +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + APP_PRINT_INFO5("GAP_MSG_LE_CONN_UPDATE_IND: conn_id %d, conn_interval_max 0x%x, conn_interval_min 0x%x, conn_latency 0x%x,supervision_timeout 0x%x", + p_data->p_le_conn_update_ind->conn_id, + p_data->p_le_conn_update_ind->conn_interval_max, + p_data->p_le_conn_update_ind->conn_interval_min, + p_data->p_le_conn_update_ind->conn_latency, + p_data->p_le_conn_update_ind->supervision_timeout); + /* if reject the proposed connection parameter from peer device, use APP_RESULT_REJECT. */ + if (p_data->p_le_conn_update_ind->conn_latency > 60)//only used for test + { + result = APP_RESULT_REJECT; + } + else + { + result = APP_RESULT_ACCEPT; + } + break; + + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + APP_PRINT_INFO1("GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: cause 0x%x", + p_data->p_le_set_host_chann_classif_rsp->cause); + break; +#endif +#if F_BT_LE_READ_CHANN_MAP + case GAP_MSG_LE_READ_CHANN_MAP: + APP_PRINT_INFO7("GAP_MSG_LE_READ_CHANN_MAP: conn_id 0x%x, cause 0x%x, map[0x%x:0x%x:0x%x:0x%x:0x%x]", + p_data->p_le_read_chann_map_rsp->conn_id, + p_data->p_le_read_chann_map_rsp->cause, + p_data->p_le_read_chann_map_rsp->channel_map[0], + p_data->p_le_read_chann_map_rsp->channel_map[1], + p_data->p_le_read_chann_map_rsp->channel_map[2], + p_data->p_le_read_chann_map_rsp->channel_map[3], + p_data->p_le_read_chann_map_rsp->channel_map[4]); + break; +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + case GAP_MSG_LE_ADV_READ_TX_POWER: + APP_PRINT_INFO2("GAP_MSG_LE_ADV_READ_TX_POWER: cause 0x%x, tx_power_level 0x%x", + p_data->p_le_adv_read_tx_power_rsp->cause, + p_data->p_le_adv_read_tx_power_rsp->tx_power_level); + break; +#endif + + case GAP_MSG_LE_SET_RAND_ADDR: + APP_PRINT_INFO1("GAP_MSG_LE_SET_RAND_ADDR: cause 0x%x", + p_data->p_le_set_rand_addr_rsp->cause); + break; + + case GAP_MSG_LE_ADV_UPDATE_PARAM: + APP_PRINT_INFO1("GAP_MSG_LE_ADV_UPDATE_PARAM: cause 0x%x", + p_data->p_le_adv_update_param_rsp->cause); + break; +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + APP_PRINT_INFO1("GAP_MSG_LE_DISABLE_SLAVE_LATENCY: cause 0x%x", + p_data->p_le_disable_slave_latency_rsp->cause); + break; +#endif + case GAP_MSG_LE_CREATE_CONN_IND: + APP_PRINT_INFO0("GAP_MSG_LE_CREATE_CONN_IND"); + result = APP_RESULT_ACCEPT; + break; +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + case GAP_MSG_LE_KEYPRESS_NOTIFY: + APP_PRINT_INFO2("GAP_MSG_LE_KEYPRESS_NOTIFY:conn %d, cause 0x%x", + p_data->p_le_keypress_notify_rsp->conn_id, p_data->p_le_keypress_notify_rsp->cause); + break; + + case GAP_MSG_LE_KEYPRESS_NOTIFY_INFO: + APP_PRINT_INFO2("GAP_MSG_LE_KEYPRESS_NOTIFY_INFO:conn %d, type 0x%x", + p_data->p_le_keypress_notify_info->conn_id, p_data->p_le_keypress_notify_info->event_type); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + APP_PRINT_INFO1("GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP:cause 0x%x", + p_data->p_le_update_passed_chann_map_rsp->cause); + break; +#endif +#if F_BT_LE_READ_REMOTE_FEATS + case GAP_MSG_LE_REMOTE_FEATS_INFO: + { + uint8_t remote_feats[8]; + APP_PRINT_INFO3("GAP_MSG_LE_REMOTE_FEATS_INFO: conn id %d, cause 0x%x, remote_feats %b", + p_data->p_le_remote_feats_info->conn_id, + p_data->p_le_remote_feats_info->cause, + TRACE_BINARY(8, p_data->p_le_remote_feats_info->remote_feats)); + if (p_data->p_le_remote_feats_info->cause == GAP_SUCCESS) + { + memcpy(remote_feats, p_data->p_le_remote_feats_info->remote_feats, 8); + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + } + } + break; +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + APP_PRINT_INFO4("GAP_MSG_LE_PHY_UPDATE_INFO:conn_id %d, cause 0x%x, rx_phy %d, tx_phy %d", + p_data->p_le_phy_update_info->conn_id, + p_data->p_le_phy_update_info->cause, + p_data->p_le_phy_update_info->rx_phy, + p_data->p_le_phy_update_info->tx_phy); + break; +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + case GAP_MSG_LE_EXT_ADV_REPORT_INFO: + APP_PRINT_INFO6("GAP_MSG_LE_EXT_ADV_REPORT_INFO:connectable %d, scannable %d, direct %d, scan response %d, legacy %d, data status 0x%x", + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_CONNECTABLE_ADV, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_SCANNABLE_ADV, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_DIRECTED_ADV, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_SCAN_RESPONSE, + p_data->p_le_ext_adv_report_info->event_type & GAP_EXT_ADV_REPORT_BIT_USE_LEGACY_ADV, + p_data->p_le_ext_adv_report_info->data_status); + APP_PRINT_INFO5("GAP_MSG_LE_EXT_ADV_REPORT_INFO:event_type 0x%x, bd_addr %s, addr_type %d, rssi %d, data_len %d", + p_data->p_le_ext_adv_report_info->event_type, + TRACE_BDADDR(p_data->p_le_ext_adv_report_info->bd_addr), + p_data->p_le_ext_adv_report_info->addr_type, + p_data->p_le_ext_adv_report_info->rssi, + p_data->p_le_ext_adv_report_info->data_len); + APP_PRINT_INFO5("GAP_MSG_LE_EXT_ADV_REPORT_INFO:primary_phy %d, secondary_phy %d, adv_sid %d, tx_power %d, peri_adv_interval %d", + p_data->p_le_ext_adv_report_info->primary_phy, + p_data->p_le_ext_adv_report_info->secondary_phy, + p_data->p_le_ext_adv_report_info->adv_sid, + p_data->p_le_ext_adv_report_info->tx_power, + p_data->p_le_ext_adv_report_info->peri_adv_interval); + APP_PRINT_INFO2("GAP_MSG_LE_EXT_ADV_REPORT_INFO:direct_addr_type 0x%x, direct_addr %s", + p_data->p_le_ext_adv_report_info->direct_addr_type, + TRACE_BDADDR(p_data->p_le_ext_adv_report_info->direct_addr)); + link_mgr_add_device(p_data->p_le_ext_adv_report_info->bd_addr, + p_data->p_le_ext_adv_report_info->addr_type); + break; +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case GAP_MSG_LE_EXT_ADV_START_SETTING: + APP_PRINT_INFO3("GAP_MSG_LE_EXT_ADV_START_SETTING:cause 0x%x, flag 0x%x, adv_handle %d", + p_data->p_le_ext_adv_start_setting_rsp->cause, + p_data->p_le_ext_adv_start_setting_rsp->flag, + p_data->p_le_ext_adv_start_setting_rsp->adv_handle); + break; + case GAP_MSG_LE_EXT_ADV_REMOVE_SET: + APP_PRINT_INFO2("GAP_MSG_LE_EXT_ADV_REMOVE_SET:cause 0x%x, adv_handle %d", + p_data->p_le_ext_adv_remove_set_rsp->cause, + p_data->p_le_ext_adv_remove_set_rsp->adv_handle); + break; + case GAP_MSG_LE_EXT_ADV_CLEAR_SET: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_CLEAR_SET:cause 0x%x", + p_data->p_le_ext_adv_clear_set_rsp->cause); + break; + case GAP_MSG_LE_EXT_ADV_ENABLE: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_ENABLE:cause 0x%x", + p_data->le_cause.cause); + break; + case GAP_MSG_LE_EXT_ADV_DISABLE: + APP_PRINT_INFO1("GAP_MSG_LE_EXT_ADV_DISABLE:cause 0x%x", + p_data->le_cause.cause); + break; + case GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO: + APP_PRINT_INFO3("GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO:adv_handle %d, scanner_addr_type 0x%x, scanner_addr %s", + p_data->p_le_scan_req_received_info->adv_handle, + p_data->p_le_scan_req_received_info->scanner_addr_type, + TRACE_BDADDR(p_data->p_le_scan_req_received_info->scanner_addr)); + break; +#endif + case GAP_MSG_LE_BOND_MODIFY_INFO: + APP_PRINT_INFO2("GAP_MSG_LE_BOND_MODIFY_INFO: 0x%x, p_entry %p", + p_data->p_le_bond_modify_info->type, p_data->p_le_bond_modify_info->p_entry); +#if F_BT_LE_PRIVACY_SUPPORT + if (gap_test_case == GAP_TC_03_PRIVACY) + { + privacy_handle_bond_modify_msg(p_data->p_le_bond_modify_info->type, + p_data->p_le_bond_modify_info->p_entry, true); + } +#endif + break; +#if F_BT_LE_ATT_SIGNED_WRITE_SUPPORT + case GAP_MSG_LE_GATT_SIGNED_STATUS_INFO: + APP_PRINT_INFO5("GAP_MSG_LE_GATT_SIGNED_STATUS_INFO:conn_id %d, cause 0x%x, update_local %d, local_sign_count %d,remote_sign_count %d", + p_data->p_le_gatt_signed_status_info->conn_id, + p_data->p_le_gatt_signed_status_info->cause, + p_data->p_le_gatt_signed_status_info->update_local, + p_data->p_le_gatt_signed_status_info->local_sign_count, + p_data->p_le_gatt_signed_status_info->remote_sign_count); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE: + APP_PRINT_INFO1("GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE: cause 0x%x", + p_data->le_cause.cause); + break; + case GAP_MSG_LE_VENDOR_ADV_3_DATA_SET: + APP_PRINT_INFO2("GAP_MSG_LE_VENDOR_ADV_3_DATA_SET: type %d, cause 0x%x", + p_data->p_le_vendor_adv_3_data_set_rsp->type, + p_data->p_le_vendor_adv_3_data_set_rsp->cause); + break; +#endif +#if F_BT_LE_GAP_MSG_INFO_WAY + case GAP_MSG_LE_GAP_STATE_MSG: + APP_PRINT_INFO0("GAP_MSG_LE_GAP_STATE_MSG"); + app_handle_gap_msg(p_data->p_gap_state_msg); + break; +#endif +#if F_BT_LE_APP_KEY_MANAGER + case GAP_MSG_LE_AUTHEN_RESULT_IND: + app_handle_authen_result_ind(p_data->p_le_authen_result_ind); + break; + case GAP_MSG_LE_AUTHEN_KEY_REQ_IND: + app_handle_authen_key_req_ind(p_data->p_le_authen_key_req_ind); + break; + case GAP_MSG_LE_GATT_SERVER_STORE_IND: + app_handle_gatt_server_store_ind(p_data->p_le_gatt_server_store_ind); + break; +#endif + default: + APP_PRINT_ERROR1("app_gap_callback: unhandled cb_type 0x%x", cb_type); + break; + } + return result; +} + + +/** + * @brief Callback for gap common module to notify app + * @param[in] cb_type callback msy type @ref GAP_COMMON_MSG_TYPE. + * @param[in] p_cb_data point to callback data @ref T_GAP_CB_DATA. + * @retval void + */ +void app_gap_common_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_CB_DATA)); + APP_PRINT_INFO1("app_gap_common_callback: cb_type = %d", cb_type); + switch (cb_type) + { +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_WRITE_AIRPLAN_MODE: + APP_PRINT_INFO1("GAP_MSG_WRITE_AIRPLAN_MODE: cause 0x%x", + cb_data.p_gap_write_airplan_mode_rsp->cause); + break; + case GAP_MSG_READ_AIRPLAN_MODE: + APP_PRINT_INFO2("GAP_MSG_READ_AIRPLAN_MODE: cause 0x%x, mode %d", + cb_data.p_gap_read_airplan_mode_rsp->cause, + cb_data.p_gap_read_airplan_mode_rsp->mode); + break; +#endif +#if F_BT_CONTROLLER_POWER_CONTROL + case GAP_MSG_BT_POWER_ON_RSP: + APP_PRINT_INFO1("GAP_MSG_BT_POWER_ON_RSP: cause 0x%x", + cb_data.p_gap_bt_power_on_rsp->cause); + break; + case GAP_MSG_BT_POWER_OFF_RSP: + APP_PRINT_INFO1("GAP_MSG_BT_POWER_OFF_RSP: cause 0x%x", + cb_data.p_gap_bt_power_off_rsp->cause); + break; +#endif + default: + break; + } + return; +} +#if 0 +void app_gap_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("app_gap_common_callback: cb_type = %d", cb_type); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + APP_PRINT_INFO4("GAP_MSG_VENDOR_CMD_RSP: command 0x%x, cause 0x%x, is_cmpl_evt %d, param_len %d", + cb_data.p_gap_vendor_cmd_rsp->command, + cb_data.p_gap_vendor_cmd_rsp->cause, + cb_data.p_gap_vendor_cmd_rsp->is_cmpl_evt, + cb_data.p_gap_vendor_cmd_rsp->param_len); + break; + case GAP_MSG_VENDOR_EVT_INFO: + APP_PRINT_INFO1("GAP_MSG_VENDOR_EVT_INFO: param_len %d", + cb_data.p_gap_vendor_evt_info->param_len); + break; + default: + break; + } + return; +} +#endif + +/** + * @brief All the BT GAP service callback events are handled in this function + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_GAPS_CALLBACK_DATA *p_gap_data = (T_GAPS_CALLBACK_DATA *)p_para; + APP_PRINT_INFO2("gap_service_callback conn_id = %d msg_type = %d\n", p_gap_data->conn_id, + p_gap_data->msg_type); +#if F_BT_GAPS_CHAR_WRITEABLE + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE) + { + switch (p_gap_data->msg_data.opcode) + { + case GAPS_WRITE_DEVICE_NAME: + { + T_LOCAL_NAME device_name; + memcpy(device_name.local_name, p_gap_data->msg_data.p_value, p_gap_data->msg_data.len); + device_name.local_name[p_gap_data->msg_data.len] = 0; + flash_save_local_name(&device_name); + } + break; + + case GAPS_WRITE_APPEARANCE: + { + uint16_t appearance_val; + T_LOCAL_APPEARANCE appearance; + + LE_ARRAY_TO_UINT16(appearance_val, p_gap_data->msg_data.p_value); + appearance.local_appearance = appearance_val; + flash_save_local_appearance(&appearance); + } + break; + + default: + break; + } + } +#endif + if (p_gap_data->msg_type == SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION) + { + if (p_gap_data->msg_data.opcode == GATT_SERVICE_CHANGE_CCCD_ENABLE) + { + APP_PRINT_INFO0("GATT_SERVICE_CHANGE_CCCD_ENABLE"); + } + else if (p_gap_data->msg_data.opcode == GATT_SERVICE_CHANGE_CCCD_DISABLE) + { + APP_PRINT_INFO0("GATT_SERVICE_CHANGE_CCCD_DISABLE"); + } + } + return result; +} + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + break; + default: + break; + } + + } + else if (client_id == gaps_client_id) + { + T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data; + switch (p_gaps_cb_data->cb_type) + { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + switch (p_gaps_cb_data->cb_content.disc_state) + { + case DISC_GAPS_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("app_client_callback: discover gaps procedure done."); + break; + case DISC_GAPS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("app_client_callback: discover gaps request failed."); + break; + default: + break; + } + break; + case GAPS_CLIENT_CB_TYPE_READ_RESULT: + switch (p_gaps_cb_data->cb_content.read_result.type) + { + case GAPS_READ_DEVICE_NAME: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.", + TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value)); + } + else + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_APPEARANCE: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance %d", + p_gaps_cb_data->cb_content.read_result.data.appearance); + } + else + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + case GAPS_READ_CENTRAL_ADDR_RESOLUTION: + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d", + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + } + else + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + break; + default: + break; + } + break; + + default: + break; + } + } + else if (client_id == simple_ble_client_id) + { + T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data = (T_SIMP_CLIENT_CB_DATA *)p_data; + uint16_t value_size; + uint8_t *p_value; + switch (p_simp_client_cb_data->cb_type) + { + case SIMP_CLIENT_CB_TYPE_DISC_STATE: + switch (p_simp_client_cb_data->cb_content.disc_state) + { + case DISC_SIMP_DONE: + APP_PRINT_INFO0("app_client_callback: discover simp procedure done."); + break; + case DISC_SIMP_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("app_client_callback: discover simp request failed."); + break; + default: + break; + } + break; + case SIMP_CLIENT_CB_TYPE_READ_RESULT: + switch (p_simp_client_cb_data->cb_content.read_result.type) + { + case SIMP_READ_V1_READ: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_simp_client_cb_data->cb_content.read_result.data.v1_read.value_size; + p_value = p_simp_client_cb_data->cb_content.read_result.data.v1_read.p_value; + APP_PRINT_INFO2("SIMP_READ_V1_READ: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V1_READ: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + break; + case SIMP_READ_V3_NOTIFY_CCCD: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V3_NOTIFY_CCCD: notify %d", + p_simp_client_cb_data->cb_content.read_result.data.v3_notify_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V3_NOTIFY_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + }; + break; + case SIMP_READ_V4_INDICATE_CCCD: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V4_INDICATE_CCCD: indicate %d", + p_simp_client_cb_data->cb_content.read_result.data.v4_indicate_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V4_INDICATE_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + }; + break; + + case SIMP_READ_V8_CCCD: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V8_CCCD: cccd 0x%x", + p_simp_client_cb_data->cb_content.read_result.data.v8_notify_ind_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V8_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + }; + break; + + case SIMP_READ_V7_READ_LONG: + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_simp_client_cb_data->cb_content.read_result.data.v7_read.value_size; + p_value = p_simp_client_cb_data->cb_content.read_result.data.v7_read.p_value; + APP_PRINT_INFO2("SIMP_READ_V7_READ_LONG: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V7_READ_LONG: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + break; + + default: + break; + } + break; + + case SIMP_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_simp_client_cb_data->cb_content.write_result.type) + { + case SIMP_WRITE_V2_WRITE: + APP_PRINT_INFO1("SIMP_WRITE_V2_WRITE: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V3_NOTIFY_CCCD: + APP_PRINT_INFO1("SIMP_WRITE_V3_NOTIFY_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V4_INDICATE_CCCD: + APP_PRINT_INFO1("SIMP_WRITE_V4_INDICATE_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V6_WRITE_LONG: + APP_PRINT_INFO1("SIMP_WRITE_V6_WRITE_LONG: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + case SIMP_WRITE_V8_CCCD: + APP_PRINT_INFO1("SIMP_WRITE_V8_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + break; + default: + break; + } + break; + + case SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + value_size = p_simp_client_cb_data->cb_content.notif_ind_data.data.value_size; + p_value = p_simp_client_cb_data->cb_content.notif_ind_data.data.p_value; + switch (p_simp_client_cb_data->cb_content.notif_ind_data.type) + { + case SIMP_V3_NOTIFY: + APP_PRINT_INFO2("SIMP_V3_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + if (gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + gap_v3_notif_test.v3_rx_num++; + } + break; + case SIMP_V4_INDICATE: + APP_PRINT_INFO2("SIMP_V4_INDICATE: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + case SIMP_V8_INDICATE: + APP_PRINT_INFO2("SIMP_V8_INDICATE: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + case SIMP_V8_NOTIFY: + if (gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + gap_v3_notif_test.v8_rx_num++; + } + APP_PRINT_INFO2("SIMP_V8_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + break; + default: + break; + } + break; + + default: + break; + } + } + + return result; +} + +#if APP_GENERAL_CLIENT_TEST +void gcs_handle_discovery_result(uint8_t conn_id, T_GCS_DISCOVERY_RESULT discov_result) +{ + uint16_t i; + uint32_t uuid_128[4]; + T_GCS_DISCOV_RESULT *p_result_table; + uint16_t properties; + switch (discov_result.discov_type) + { + case GCS_ALL_PRIMARY_SRV_DISCOV: + data_uart_print("conn_id %d, GCS_ALL_PRIMARY_SRV_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_ALL_SRV_UUID16: + data_uart_print("ALL SRV UUID16[%d]: service range: 0x%4x-0x%4x, uuid16 0x%4x\r\n", + i, p_result_table->result_data.srv_uuid16_disc_data.att_handle, + p_result_table->result_data.srv_uuid16_disc_data.end_group_handle, + p_result_table->result_data.srv_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_ALL_SRV_UUID128: + memcpy(uuid_128, &p_result_table->result_data.srv_uuid128_disc_data.uuid128[0], sizeof(uuid_128)); + data_uart_print("ALL SRV UUID128[%d]: service range: 0x%4x-0x%4x, service=<0x%8x%8x%8x%8x>\r\n", + i, p_result_table->result_data.srv_uuid128_disc_data.att_handle, + p_result_table->result_data.srv_uuid128_disc_data.end_group_handle, + uuid_128[3], uuid_128[2], uuid_128[1], uuid_128[0]); + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_SRV_DISCOV: + data_uart_print("conn_id %d, GCS_BY_UUID128_SRV_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + data_uart_print("SRV DATA[%d]: service range: 0x%4x-0x%4x\r\n", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID_SRV_DISCOV: + data_uart_print("conn_id %d, GCS_BY_UUID_SRV_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_SRV_DATA: + data_uart_print("SRV DATA[%d]: service range: 0x%4x-0x%4x\r\n", + i, p_result_table->result_data.srv_disc_data.att_handle, + p_result_table->result_data.srv_disc_data.end_group_handle); + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_ALL_CHAR_DISCOV: + data_uart_print("conn_id %d, GCS_ALL_CHAR_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_UUID16: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + data_uart_print("CHAR UUID16[%d]: decl_handle 0x%4x, properties 0x%4x, value_handle 0x%4x, uuid16 0x%4x\r\n", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY); + + break; + + case DISC_RESULT_CHAR_UUID128: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + memcpy(uuid_128, &p_result_table->result_data.char_uuid128_disc_data.uuid128[0], sizeof(uuid_128)); + data_uart_print("CHAR UUID128[%d]: decl hndl=0x%4x, prop=0x%4x, value hndl=0x%4x, uuid128=<0x%8x%8x%8x%8x>\r\n", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + uuid_128[3], uuid_128[2], uuid_128[1], uuid_128[0]); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID_CHAR_DISCOV: + data_uart_print("conn_id %d, GCS_BY_UUID_CHAR_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID16_CHAR: + properties = p_result_table->result_data.char_uuid16_disc_data.properties; + data_uart_print("UUID16 CHAR[%d]: Characteristics by uuid16, decl hndl=0x%4x, prop=0x%4x, value hndl=0x%4x, uuid16=<0x%4x>\r\n", + i, p_result_table->result_data.char_uuid16_disc_data.decl_handle, + p_result_table->result_data.char_uuid16_disc_data.properties, + p_result_table->result_data.char_uuid16_disc_data.value_handle, + p_result_table->result_data.char_uuid16_disc_data.uuid16); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_BY_UUID128_CHAR_DISCOV: + data_uart_print("conn_id %d, GCS_BY_UUID128_CHAR_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_BY_UUID128_CHAR: + properties = p_result_table->result_data.char_uuid128_disc_data.properties; + memcpy(uuid_128, &p_result_table->result_data.char_uuid128_disc_data.uuid128[0], sizeof(uuid_128)); + data_uart_print("UUID128 CHAR[%d]: Characteristics by uuid128, decl hndl=0x%4x, prop=0x%4x, value hndl=0x%4x, uuid128=<0x%8x%8x%8x%8x>\r\n", + i, p_result_table->result_data.char_uuid128_disc_data.decl_handle, + p_result_table->result_data.char_uuid128_disc_data.properties, + p_result_table->result_data.char_uuid128_disc_data.value_handle, + uuid_128[3], uuid_128[2], uuid_128[1], uuid_128[0]); + data_uart_print("properties:indicate %d, read %d, write cmd %d, write %d, notify %d\r\n", + properties & GATT_CHAR_PROP_INDICATE, + properties & GATT_CHAR_PROP_READ, + properties & GATT_CHAR_PROP_WRITE_NO_RSP, + properties & GATT_CHAR_PROP_WRITE, + properties & GATT_CHAR_PROP_NOTIFY + ); + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + case GCS_ALL_CHAR_DESC_DISCOV: + data_uart_print("conn_id %d, GCS_ALL_CHAR_DESC_DISCOV, is_success %d\r\n", + conn_id, discov_result.is_success); + for (i = 0; i < discov_result.result_num; i++) + { + p_result_table = &(discov_result.p_result_table[i]); + switch (p_result_table->result_type) + { + case DISC_RESULT_CHAR_DESC_UUID16: + data_uart_print("DESC UUID16[%d]: Descriptors handle=0x%4x, uuid16=<0x%4x>\r\n", + i, p_result_table->result_data.char_desc_uuid16_disc_data.handle, + p_result_table->result_data.char_desc_uuid16_disc_data.uuid16); + break; + case DISC_RESULT_CHAR_DESC_UUID128: + memcpy(uuid_128, &p_result_table->result_data.char_desc_uuid128_disc_data.uuid128[0], + sizeof(uuid_128)); + data_uart_print("DESC UUID128[%d]: Descriptors handle=0x%4x, uuid128=<0x%8x%8x%8x%8x>\r\n", + i, p_result_table->result_data.char_desc_uuid128_disc_data.handle, + uuid_128[3], uuid_128[2], uuid_128[1], uuid_128[0]); + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + break; + + default: + data_uart_print("Invalid disc type: conn_id %d, state %d\r\n", + conn_id, discov_result.discov_type); + break; + } +} + +T_APP_RESULT gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("gcs_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + + if (client_id == gcs_client_id) + { + T_GCS_CLIENT_CB_DATA *p_gcs_cb_data = (T_GCS_CLIENT_CB_DATA *)p_data; + switch (p_gcs_cb_data->cb_type) + { + case GCS_CLIENT_CB_TYPE_DISC_RESULT: + gcs_handle_discovery_result(conn_id, p_gcs_cb_data->cb_content.discov_result); + break; + case GCS_CLIENT_CB_TYPE_READ_RESULT: + data_uart_print("READ RESULT: cause 0x%4x, handle 0x%4x, value_len %d\r\n", + p_gcs_cb_data->cb_content.read_result.cause, + p_gcs_cb_data->cb_content.read_result.handle, + p_gcs_cb_data->cb_content.read_result.value_size); + APP_PRINT_INFO1("READ VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.read_result.value_size, + p_gcs_cb_data->cb_content.read_result.p_value)); + break; + case GCS_CLIENT_CB_TYPE_WRITE_RESULT: + data_uart_print("WRITE RESULT: cause 0x%4x ,handle 0x%4x, type %d\r\n", + p_gcs_cb_data->cb_content.write_result.cause, + p_gcs_cb_data->cb_content.write_result.handle, + p_gcs_cb_data->cb_content.write_result.type); + break; + case GCS_CLIENT_CB_TYPE_NOTIF_IND: + if (p_gcs_cb_data->cb_content.notif_ind.notify == false) + { + data_uart_print("INDICATION: handle 0x%4x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("INDICATION VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + } + else + { + data_uart_print("NOTIFICATION: handle 0x%4x, value_size %d\r\n", + p_gcs_cb_data->cb_content.notif_ind.handle, + p_gcs_cb_data->cb_content.notif_ind.value_size); + APP_PRINT_INFO1("NOTIFICATION VALUE: %b", + TRACE_BINARY(p_gcs_cb_data->cb_content.notif_ind.value_size, + p_gcs_cb_data->cb_content.notif_ind.p_value)); + } + break; + default: + break; + } + } + + return result; +} +#endif +#endif +/** + * @brief All the BT Profile service callback events are handled in this function + * @note Then the event handling function shall be called according to the + * service_id. + * @param[in] service_id Profile service ID + * @param[in] p_data Pointer to callback data + * @return Indicates the function call is successful or not + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + if (gap_v3_notif_test.v3_tx_conn_id == p_param->event_data.send_data_result.conn_id) + { + uint8_t credit = p_param->event_data.send_data_result.credits; + uint8_t notif_val[244]; + gap_v3_notif_test.v3_tx_cmp_num++; + + for (; credit > 0; credit--) + { + if (gap_v3_notif_test.v3_tx_num == 0) + { + break; + } + memset(notif_val, gap_v3_notif_test.v3_tx_idx, gap_v3_notif_test.v3_tx_len); + if (gap_v3_notif_test.v3_tx_num % 2 == 0 || gap_test_case != GAP_TC_13_V3_V8_TX) + { + + if (simp_ble_service_send_v3_notify(gap_v3_notif_test.v3_tx_conn_id, simp_srv_id, + ¬if_val, + gap_v3_notif_test.v3_tx_len)) + { + gap_v3_notif_test.v3_tx_idx++; + gap_v3_notif_test.v3_tx_num--; + gap_v3_notif_test.v3_tx_cnt++; + } + else + { + break; + } + } + else + { + + if (simp_ble_service_simple_v8_notify(gap_v3_notif_test.v3_tx_conn_id, simp_srv_id, + ¬if_val, + gap_v3_notif_test.v3_tx_len)) + { + gap_v3_notif_test.v3_tx_idx++; + gap_v3_notif_test.v3_tx_num--; + gap_v3_notif_test.v8_tx_cnt++; + } + else + { + break; + } + } + } + } + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_DISABLE"); + } + break; + } + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value = 0x88; + APP_PRINT_INFO1("SIMP_READ_V1: 0x%x", value); + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 1, &value); + } + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + + case SIMP_WRITE_V6: + { + APP_PRINT_INFO1("SIMP_WRITE_V6: len = 0x%x", p_simp_cb_data->msg_data.write.len); + data_uart_print("V6 len = %d\r\n", p_simp_cb_data->msg_data.write.len); + } + break; + default: + break; + } + } + break; + + default: + break; + } + } +#if APP_HID_TEST + else if (service_id == hid_srv_id) + { + T_HID_CALLBACK_DATA *p_hid_cb_data = (T_HID_CALLBACK_DATA *)p_data; + + switch (p_hid_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + APP_PRINT_INFO2("SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: index %d, value %d", + p_hid_cb_data->msg_data.not_ind_data.index, + p_hid_cb_data->msg_data.not_ind_data.value); + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_hid_cb_data->msg_data.read_value_index) + { + case GATT_SVC_HID_PROTOCOL_MODE_INDEX: + { + APP_PRINT_INFO1("HID_WRITE_PROTOCOL MODE %d\n", + p_hid_cb_data->msg_data.write_msg.write_parameter.protocol_mode); + break; + } + case GATT_SVC_HID_REPORT_OUTPUT_INDEX: + { + //callback data definition need to modify. + APP_PRINT_INFO1("HID_OUTPUT value %d\n", p_hid_cb_data->msg_data.write_msg.write_parameter.output); + break; + } + default: + break; + } + } + break; + default: + break; + } + } +#endif + return app_result; +} + + +#if F_BT_LE_PRIVACY_SUPPORT +void app_privacy_callback(T_PRIVACY_CB_TYPE type, T_PRIVACY_CB_DATA cb_data) +{ + APP_PRINT_INFO1("app_privacy_callback: type %d", type); + switch (type) + { + case PRIVACY_STATE_MSGTYPE: + app_privacy_state = cb_data.privacy_state; + APP_PRINT_INFO1("PRIVACY_STATE_MSGTYPE: status %d", app_privacy_state); + break; + + case PRIVACY_RESOLUTION_STATUS_MSGTYPE: + app_privacy_resolution_state = cb_data.resolution_state; + APP_PRINT_INFO1("PRIVACY_RESOLUTION_STATUS_MSGTYPE: status %d", app_privacy_resolution_state); + break; + + case PRIVACY_READ_PEER_RESOLV_ADDR_MSGTYPE: + APP_PRINT_INFO2("PRIVACY_READ_PEER_RESOLV_ADDR_MSGTYPE: cause 0x%x, addr %b", + cb_data.p_privacy_read_resolv_addr_rsp->cause, + TRACE_BDADDR(cb_data.p_privacy_read_resolv_addr_rsp->resolv_addr)); + break; + + case PRIVACY_READ_LOCAL_RESOLV_ADDR_MSGTYPE: + APP_PRINT_INFO2("PRIVACY_READ_LOCAL_RESOLV_ADDR_MSGTYPE: cause 0x%x, addr %b", + cb_data.p_privacy_read_resolv_addr_rsp->cause, + TRACE_BDADDR(cb_data.p_privacy_read_resolv_addr_rsp->resolv_addr)); + break; + + case PRIVACY_GEN_PRIV_ADDR_INTERVAL_MSGTYPE: + APP_PRINT_INFO1("PRIVACY_GEN_PRIV_ADDR_INTERVAL_MSGTYPE: cause 0x%x", cb_data.cause); + break; + + case PRIVACY_SET_PEER_MODE_MSGTYPE: + APP_PRINT_INFO1("PRIVACY_SET_PEER_MODE_MSGTYPE: cause 0x%x", cb_data.cause); + break; + + default: + break; + } +} +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CBC_DATA cb_data; + memcpy(&cb_data, p_cbc_data, sizeof(T_LE_CBC_DATA)); + APP_PRINT_TRACE1("app_credit_based_conn_callback: cbc_type = %d", cbc_type); + switch (cbc_type) + { + case GAP_CBC_MSG_LE_CHANN_STATE: + APP_PRINT_INFO4("GAP_CBC_MSG_LE_CHANN_STATE: conn_id %d, cid 0x%x, conn_state %d, cause 0x%x", + cb_data.p_le_chann_state->conn_id, + cb_data.p_le_chann_state->cid, + cb_data.p_le_chann_state->conn_state, + cb_data.p_le_chann_state->cause); + if (cb_data.p_le_chann_state->conn_state == GAP_CHANN_STATE_CONNECTED) + { + uint16_t mtu; + le_cbc_get_chann_param(CBC_CHANN_PARAM_MTU, &mtu, cb_data.p_le_chann_state->cid); + APP_PRINT_INFO1("GAP_CHANN_STATE_CONNECTED: mtu %d", mtu); + } + break; + + case GAP_CBC_MSG_LE_REG_PSM: + APP_PRINT_INFO2("GAP_CBC_MSG_LE_REG_PSM: le_psm 0x%x, cause 0x%x", + cb_data.p_le_reg_psm_rsp->le_psm, + cb_data.p_le_reg_psm_rsp->cause); + break; + + case GAP_CBC_MSG_LE_SET_PSM_SECURITY: + APP_PRINT_INFO1("GAP_CBC_MSG_LE_SET_PSM_SECURITY: cause 0x%x", + cb_data.p_le_set_psm_security_rsp->cause); + break; + + case GAP_CBC_MSG_LE_SEND_DATA: + APP_PRINT_INFO4("GAP_CBC_MSG_LE_SEND_DATA: conn_id %d, cid 0x%x, cause 0x%x, credit %d", + cb_data.p_le_send_data->conn_id, + cb_data.p_le_send_data->cid, + cb_data.p_le_send_data->cause, + cb_data.p_le_send_data->credit); + break; + + case GAP_CBC_MSG_LE_RECEIVE_DATA: + APP_PRINT_INFO3("GAP_CBC_MSG_LE_RECEIVE_DATA: conn_id %d, cid 0x%x, value_len %d", + cb_data.p_le_receive_data->conn_id, + cb_data.p_le_receive_data->cid, + cb_data.p_le_receive_data->value_len); + break; + + default: + break; + } + return result; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/gap_test_app.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/gap_test_app.h new file mode 100644 index 00000000..1602c48e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/gap_test_app.h @@ -0,0 +1,139 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file gap_test_app.h + * @brief GAP roles test application implementation + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _GAP_TEST_APP_H_ +#define _GAP_TEST_APP_H_ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include "app_flags.h" +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +#include +#include +#if F_BT_LE_PRIVACY_SUPPORT +#include +#endif + +typedef enum +{ + GAP_TC_00_NORMAL = 0, + GAP_TC_01_ANCS = 1, + GAP_TC_02_GAPS_WRITEABLE = 2, + GAP_TC_03_PRIVACY = 3, + GAP_TC_04_PIN_CODE = 4, + GAP_TC_05_BT5 = 5, + GAP_TC_07_CCCD = 7, + GAP_TC_08_LOCAL_IRK = 8, + GAP_TC_09_SLAVE_LATENCY = 9, + GAP_TC_10_BT41 = 10, + GAP_TC_11_MIN_REM_SCA = 11, + GAP_TC_12_GAP_MSG_CALLBACK = 12, + GAP_TC_13_V3_V8_TX = 13, + GAP_TC_14_SRV_CHANGE = 14, + GAP_TC_15_HID_PROFILE = 15, +} T_GAP_TEST_CASE; + +typedef struct +{ + uint8_t v3_tx_idx; + uint8_t v3_tx_conn_id; + uint8_t v3_tx_len; + uint16_t v3_tx_num; + uint16_t v3_tx_cmp_num; + uint16_t v3_rx_num; + uint16_t v3_tx_cnt; + uint16_t v8_tx_cnt; + uint16_t v8_rx_num; +} T_GAP_V3_NOTIF_TEST; + +/*============================================================================* + * Variables + *============================================================================*/ +extern T_GAP_TEST_CASE gap_test_case; +extern T_GAP_V3_NOTIF_TEST gap_v3_notif_test; +#if F_BT_LE_GATT_CLIENT_SUPPORT +extern T_CLIENT_ID gaps_client_id; /**< Simple ble service client id*/ +extern T_CLIENT_ID simple_ble_client_id; /**< gap service client id*/ +#if APP_GENERAL_CLIENT_TEST +extern T_CLIENT_ID gcs_client_id; +#endif +#endif +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_SERVER_ID hid_srv_id; +#if F_BT_LE_PRIVACY_SUPPORT +extern T_PRIVACY_ADDR_RESOLUTION_STATE app_privacy_resolution_state; +#endif +/*============================================================================* + * Functions + *============================================================================*/ + +/** + * @brief All the application messages are pre-handled in this function + * @note All the IO MSGs are sent to this function, then the event handling + * function shall be called according to the MSG type. + * @param[in] io_msg IO message data + * @return void + */ +void app_handle_io_msg(T_IO_MSG io_msg); +/** + * @brief Callback for gap le to notify app + * @param[in] cb_type callback msy type @ref GAP_LE_MSG_Types. + * @param[in] p_cb_data point to callback data @ref T_LE_CB_DATA. + * @retval result @ref T_APP_RESULT + */ +T_APP_RESULT app_gap_callback(uint8_t cb_type, void *p_cb_data); + +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT app_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#if APP_GENERAL_CLIENT_TEST +T_APP_RESULT gcs_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); +#endif +#endif +T_APP_RESULT app_profile_callback(T_SERVER_ID service_id, void *p_data); + +void app_gap_common_callback(uint8_t cb_type, void *p_cb_data); +void app_gap_vendor_callback(uint8_t cb_type, void *p_cb_data); + +#if F_BT_GAPS_CHAR_WRITEABLE +T_APP_RESULT gap_service_callback(T_SERVER_ID service_id, void *p_para); +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +void app_privacy_callback(T_PRIVACY_CB_TYPE type, T_PRIVACY_CB_DATA cb_data); +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT app_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/link_mgr.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/link_mgr.c new file mode 100644 index 00000000..5ada60a2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/link_mgr.c @@ -0,0 +1,77 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.c + * @brief Multilink manager functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include + +/*============================================================================* + * Variables + *============================================================================*/ +T_APP_LINK app_link_table[APP_MAX_LINKS]; +T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +uint8_t dev_list_count = 0; + +/*============================================================================* + * Functions + *============================================================================*/ +/** + * @brief Add device information to device list. + * + * @param[in] bd_addr Peer device address. + * @param[in] bd_type Peer device address type. + * @retval true Success. + * @retval false Failed, device list is full. + */ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type) +{ + /* If result count not at max */ + if (dev_list_count < APP_MAX_DEVICE_INFO) + { + uint8_t i; + /* Check if device is already in device list*/ + for (i = 0; i < dev_list_count; i++) + { + if (memcmp(bd_addr, dev_list[i].bd_addr, GAP_BD_ADDR_LEN) == 0) + { + return true; + } + } + + /*Add addr to device list list*/ + memcpy(dev_list[dev_list_count].bd_addr, bd_addr, GAP_BD_ADDR_LEN); + dev_list[dev_list_count].bd_type = bd_type; + + /*Increment device list count*/ + dev_list_count++; + } + else + { + return false; + } + return true; +} + +/** + * @brief Clear device list. + * @retval None. + */ +void link_mgr_clear_device_list(void) +{ + dev_list_count = 0; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/link_mgr.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/link_mgr.h new file mode 100644 index 00000000..4813dd64 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/link_mgr.h @@ -0,0 +1,79 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file link_mgr.h + * @brief Define multilink manager struct and functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _LINK_MANAGER_H_ +#define _LINK_MANAGER_H_ +/*============================================================================* + * Header Files + *============================================================================*/ +#include "app_flags.h" +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#endif +/*============================================================================* + * Constants + *============================================================================*/ +/** @brief Define links number. range: 0-4 */ +#define APP_HDL_CACHE_LEN 24/** @brief Define device list table size. */ +#define APP_MAX_DEVICE_INFO 15 +typedef struct +{ + uint16_t uuid16; + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ + uint8_t reserved[3]; /**< used to T_GATT_SERVER_DATABASE_INFO four byte alignment*/ + uint16_t hdl_cache[APP_HDL_CACHE_LEN]; +} T_GATT_SERVER_DATABASE_INFO; +/** + * @brief Application Link control block defination. + */ +typedef struct +{ + T_GAP_CONN_STATE conn_state; /**< Connection state. */ +#if F_BT_LE_GATT_CLIENT_SUPPORT + T_CLIENT_ID client_id; +#endif + uint8_t end_handle_idx; + uint8_t disc_state; + uint8_t state; + T_GATT_SERVER_DATABASE_INFO server_info; +} T_APP_LINK; +/** + * @brief Device list block defination. + */ +typedef struct +{ + uint8_t bd_addr[GAP_BD_ADDR_LEN]; /**< remote BD */ + uint8_t bd_type; /**< remote BD type*/ +} T_DEV_INFO; +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief App link table */ +extern T_APP_LINK app_link_table[APP_MAX_LINKS]; +/** @brief Device list table, used to save discovered device informations. */ +extern T_DEV_INFO dev_list[APP_MAX_DEVICE_INFO]; +/** @brief The number of device informations saved in dev_list. */ +extern uint8_t dev_list_count; + +/*============================================================================* + * Functions + *============================================================================*/ +bool link_mgr_add_device(uint8_t *bd_addr, uint8_t bd_type); +void link_mgr_clear_device_list(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/user_cmd.c b/component/common/bluetooth/realtek/sdk/src/app/gap_test/user_cmd.c new file mode 100644 index 00000000..ff6e532f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/user_cmd.c @@ -0,0 +1,3539 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file user_cmd.c + * @brief User defined test commands. + * @details User command interfaces. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +#include +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "profile_client.h" +#include +#include +#if APP_GENERAL_CLIENT_TEST +#include +#endif +#endif +#include +#include +#include +#include +#include +#include +#if F_BT_ANCS_CLIENT_SUPPORT +#include +#include +#endif +#if F_BT_LE_PRIVACY_SUPPORT +#include +#endif +#if F_BT_DLPS_EN +#include +#include +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#include +#endif +#if APP_HID_TEST +#include +#endif +#if F_BT_LE_6_0_AOA_AOD_SUPPORT +#include +#endif +/*common*/ +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI +//#include +#endif + +#ifdef AMEBAD_BOARD +#include "ameba_soc.h" +#endif +#if APP_HID_TEST +#include +#endif +#include "vendor_cmd_bt.h" +#include "ftl.h" +#include "ftl_app.h" + +/*============================================================================* + * Variables + *============================================================================*/ +/** @brief User command interface data, used to parse the commands from Data UART. */ +T_USER_CMD_IF user_cmd_if; + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +// GAP - SCAN RSP data (max size = 31 bytes) +static const uint8_t ext_scan_response[] = +{ + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + 0x03, + GAP_ADTYPE_APPEARANCE, + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), +}; + +// GAP - Advertisement data (max size = 31 bytes, though this is +// best kept short to conserve power while advertisting) +static const uint8_t ext_adv_data[] = +{ + 0x02, + GAP_ADTYPE_FLAGS, + GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED, + + 0x03, + GAP_ADTYPE_16BIT_COMPLETE, + LO_WORD(GATT_UUID_SIMPLE_PROFILE), + HI_WORD(GATT_UUID_SIMPLE_PROFILE), + + 0x03, + GAP_ADTYPE_APPEARANCE, + LO_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + HI_WORD(GAP_GATT_APPEARANCE_UNKNOWN), + + 0x0C, + GAP_ADTYPE_LOCAL_NAME_COMPLETE, + 'B', 'B', '3', '_', 'G', 'a', 'p', 'T', 'e', 's', 't' +}; + +static const uint8_t ext_large_adv_data[] = +{ + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4 +}; + +/* Reduce length of ext_large_scan_data to 247 for testing two advertising sets simultaneously. + + Because another advertising set of connectable and scannable undirected advertisement with + scan response data and advertising data will use three adv tasks. So only three adv tasks could + be used by scannable undirected advertisement with extended advertising PDUs. */ +static const uint8_t ext_large_scan_data[] = +{ + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 7 +}; +#if 0 +, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1, +5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +1, 1, 1, 1, 1, 1, 1 +}; +#endif +#endif + +/*============================================================================* + * Functions + *============================================================================*/ + +#if APP_HID_TEST +typedef enum +{ + /****Keyboard*******/ + NO_EVENT = 0x00, + KB_ErrorRollOver = 0x01, + KB_POSTFail = 0x02, + KB_ErrorUndefined = 0x03, + KB_a_A = 0x04, + KB_b_B = 0x05, + KB_c_C = 0x06, + KB_d_D = 0x07, + KB_e_E = 0x08, + KB_f_F = 0x09, + KB_g_G = 0x0A, + KB_h_H = 0x0B, + KB_i_I = 0x0C, + KB_j_J = 0x0D, + KB_k_K = 0x0E, + KB_l_L = 0x0F, + KB_m_M = 0x10, + KB_n_N = 0x11, + KB_o_O = 0x12, + KB_p_P = 0x13, + KB_q_Q = 0x14, + KB_r_R = 0x15, + KB_s_S = 0x16, + KB_t_T = 0x17, + KB_u_U = 0x18, + KB_v_V = 0x19, + KB_w_W = 0x1A, + KB_x_X = 0x1B, + KB_y_Y = 0x1C, + KB_z_Z = 0x1D, + KB_1 = 0x1E, + KB_2 = 0x1F, + KB_3 = 0x20, + KB_4 = 0x21, + KB_5 = 0x22, + KB_6 = 0x23, + KB_7 = 0x24, + KB_8 = 0x25, + KB_9 = 0x26, + KB_0 = 0x27, + KB_Return_ENTER = 0x28, + KB_ESCAPE = 0x29, + KB_DELETE_Backspace = 0x2A, + KB_Tab = 0x2B, + KB_Spacebar = 0x2C, + KB_Minus_Underscore = 0x2D, + KB_Equal_Plus = 0x2E, + KB_LeftBracket_LeftBrace = 0x2F, + KB_RightBracket_RightBrace = 0x30, + KB_BackSlash_VerticalBar = 0x31, + KB_NON_US_Pound = 0x32, + KB_Semicolon_Colon = 0x33, + KB_QuotationMark = 0x34, + KB_GraveAccent_Tilde = 0x35, + KB_Comma_LessThan = 0x36, + KB_Dot_LargerThan = 0x37, + KB_Slash_QuestionMark = 0x38, + KB_CapsLock = 0x39, + KB_F1 = 0x3A, + KB_F2 = 0x3B, + KB_F3 = 0x3C, + KB_F4 = 0x3D, + KB_F5 = 0x3E, + KB_F6 = 0x3F, + KB_F7 = 0x40, + KB_F8 = 0x41, + KB_F9 = 0x42, + KB_F10 = 0x43, + KB_F11 = 0x44, + KB_F12 = 0x45, + KB_PrintScreen = 0x46, + KB_ScrollLock = 0x47, + KB_Pause = 0x48, + KB_Insert = 0x49, + KB_Home = 0x4A, + KB_PageUp = 0x4B, + KB_DeleteForward = 0x4C, + KB_End = 0x4D, + KB_PageDown = 0x4E, + KB_RightArrow = 0x4F, + KB_LeftArrow = 0x50, + KB_DownArrow = 0x51, + KB_UpArrow = 0x52, + + /****Keypad*******/ + KP_NumLock_Clear = 0x53, + KP_Divide = 0x54, + KP_Multiply = 0x55, + KP_Minus = 0x56, + KP_Plus = 0x57, + KP_Enter = 0x58, + KP_1_End = 0x59, + KP_2_DownArrow = 0x5A, + KP_3_PageDn = 0x5B, + KP_4_LeftArrow = 0x5C, + KP_5 = 0x5D, + KP_6_RightArrow = 0x5E, + KP_7_Home = 0x5F, + KP_8_UpArrow = 0x60, + KP_9_PageUp = 0x61, + KP_0_Insert = 0x62, + KP_Dot_Delete = 0x63, + + /****Keyboard*******/ + KB_NON_US_BackSlash = 0x64, + KB_Application = 0x65, + KB_Power = 0x66, + + /****Keypad*******/ + KP_Equal = 0x67, + + /****Keyboard*******/ + KB_F13 = 0x68, + KB_F14 = 0x69, + KB_F15 = 0x6A, + KB_F16 = 0x6B, + KB_F17 = 0x6C, + KB_F18 = 0x6D, + KB_F19 = 0x6E, + KB_F20 = 0x6F, + KB_F21 = 0x70, + KB_F22 = 0x71, + KB_F23 = 0x72, + KB_F24 = 0x73, + KB_Execute = 0x74, + KB_Help = 0x75, + KB_Menu = 0x76, + KB_Select = 0x77, + KB_Stop = 0x78, + KB_Again = 0x79, + KB_Undo = 0x7A, + KB_Cut = 0x7B, + KB_Copy = 0x7C, + KB_Paste = 0x7D, + KB_Find = 0x7E, + KB_Mute = 0x7F, + KB_VolumeUp = 0x80, + KB_VolumeDown = 0x81, + KB_LockingCapsLock = 0x82, + KB_LockingNumLock = 0x83, + KB_LockingScrollLock = 0x84, + KB_Comma = 0x85, + KB_EqualSign = 0x86, + KB_International1 = 0x87, + KB_International2 = 0x88, + KB_International3 = 0x89, + KB_International4 = 0x8A, + KB_International5 = 0x8B, + KB_International6 = 0x8C, + KB_International7 = 0x8D, + KB_International8 = 0x8E, + KB_International9 = 0x8F, + KB_LANG1 = 0x90, + KB_LANG2 = 0x91, + KB_LANG3 = 0x92, + KB_LANG4 = 0x93, + KB_LANG5 = 0x94, + KB_LANG6 = 0x95, + KB_LANG7 = 0x96, + KB_LANG8 = 0x97, + KB_LANG9 = 0x98, + KB_AlternateErase = 0x99, + KB_SysReq_Attention = 0x9A, + KB_Cancel = 0x9B, + KB_Clear = 0x9C, + KB_Prior = 0x9D, + KB_Return = 0x9E, + KB_Separator = 0x9F, + KB_Out = 0xA0, + KB_Oper = 0xA1, + KB_Clear_Again = 0xA2, + KB_CrSel_Props = 0xA3, + KB_ExSel = 0xA4, + + KB_LeftControl = 0xE0, + KB_LeftShift = 0xE1, + KB_LeftAlt = 0xE2, + KB_LeftGUI = 0xE3, + KB_RightControl = 0xE4, + KB_RightShift = 0xE5, + KB_RightAlt = 0xE6, + KB_RightGUI = 0xE7, + +} KEY_USAGE_ID; + +static T_USER_CMD_PARSE_RESULT cmd_key(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t keycount = 0; + uint16_t usage_id = p_parse_value->dw_param[1]; + uint8_t keyboard_data[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t keyboard_release[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + /********Normal Keys**********/ + if (usage_id <= 0xA4) + { + if (keycount < 6) + { + keyboard_data[2 + keycount] = usage_id; + keycount++; + } + } + /*********Modifier Keys********/ + else if ((usage_id >= 0xE0) && (usage_id <= 0xE7)) + { + keyboard_data[0] |= 1 << (usage_id & 0x07); + } + + server_send_data(conn_id, hid_srv_id, GATT_SVC_HID_REPORT_INPUT_INDEX, + keyboard_data, sizeof(keyboard_data), GATT_PDU_TYPE_NOTIFICATION); + server_send_data(conn_id, hid_srv_id, GATT_SVC_HID_REPORT_INPUT_INDEX, + keyboard_release, sizeof(keyboard_release), GATT_PDU_TYPE_NOTIFICATION); + return (RESULT_SUCESS); +} + +#endif + +static T_USER_CMD_PARSE_RESULT cmd_reset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#ifdef AMEBAD_BOARD + u32 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_BOOT_CFG); + Temp |= BIT_SOC_BOOT_PATCH_KM4_RUN; + HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_LP_BOOT_CFG, Temp); + NVIC_SystemReset(); +#endif + return (RESULT_SUCESS); +} + +void app_vendor_callback(uint8_t cb_type, void *p_cb_data) +{ + T_GAP_VENDOR_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_GAP_VENDOR_CB_DATA)); + APP_PRINT_INFO1("app_vendor_callback: command 0x%x", cb_data.p_gap_vendor_cmd_rsp->command); + switch (cb_type) + { + case GAP_MSG_VENDOR_CMD_RSP: + switch(cb_data.p_gap_vendor_cmd_rsp->command) + { +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + case HCI_LE_VENDOR_EXTENSION_FEATURE2: + //if(cb_data.p_gap_vendor_cmd_rsp->param[0] == HCI_EXT_SUB_ONE_SHOT_ADV) + { + APP_PRINT_INFO1("One shot adv resp: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + } + break; +#endif + case HCI_LE_VENDOR_EXTENSION_FEATURE: + switch(cb_data.p_gap_vendor_cmd_rsp->param[0]) + { +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_ADV_TX_POWER: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_ADV_TX_POWER: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + case HCI_EXT_SUB_SET_LINK_TX_POW: + APP_PRINT_INFO1("HCI_EXT_SUB_SET_LINK_TX_POW: cause 0x%x", cb_data.p_gap_vendor_cmd_rsp->cause); + break; +#endif + } + break; + default: + break; + } + break; + + default: + break; + } + + return; +} + +static T_USER_CMD_PARSE_RESULT cmd_vendor(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + vendor_cmd_init(app_vendor_callback); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_oneshot(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; +#if BT_VENDOR_CMD_ONE_SHOT_SUPPORT + cause = le_vendor_one_shot_adv(); +#endif + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_txpwrset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; +#if BT_VENDOR_CMD_ADV_TX_POWER_SUPPORT + uint8_t option = p_parse_value->dw_param[0]; + uint8_t tx_gain = p_parse_value->dw_param[1]; + cause = le_adv_set_tx_power(option, tx_gain); +#endif + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_linkpwrset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; +#if BT_VENDOR_CMD_CONN_TX_POWER_SUPPORT + uint8_t conn_id = p_parse_value->dw_param[0]; + bool reset = p_parse_value->dw_param[1]; + uint8_t tx_pwr = p_parse_value->dw_param[2]; + + cause = le_set_conn_tx_power(conn_id, reset, tx_pwr); +#endif + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_reg(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + gap_test_case = (T_GAP_TEST_CASE)p_parse_value->dw_param[0]; + switch (gap_test_case) + { + case GAP_TC_00_NORMAL: //normal mode + break; + +#if F_BT_ANCS_CLIENT_SUPPORT + case GAP_TC_01_ANCS: //test ancs + { + uint8_t link_num; + uint8_t auth_sec_req_enable = true; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + link_num = le_get_max_link_num(); + ancs_init(link_num); + } + break; +#endif +#if F_BT_GAPS_CHAR_WRITEABLE + case GAP_TC_02_GAPS_WRITEABLE: //test gap service write + { + uint8_t appearance_prop = GAPS_PROPERTY_WRITE_ENABLE; + uint8_t device_name_prop = GAPS_PROPERTY_WRITE_ENABLE; + T_LOCAL_APPEARANCE appearance_local; + T_LOCAL_NAME local_device_name; + if (flash_load_local_appearance(&appearance_local) == 0) + { + gaps_set_parameter(GAPS_PARAM_APPEARANCE, sizeof(uint16_t), &appearance_local.local_appearance); + } + + if (flash_load_local_name(&local_device_name) == 0) + { + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME, GAP_DEVICE_NAME_LEN, local_device_name.local_name); + } + gaps_set_parameter(GAPS_PARAM_APPEARANCE_PROPERTY, sizeof(appearance_prop), &appearance_prop); + gaps_set_parameter(GAPS_PARAM_DEVICE_NAME_PROPERTY, sizeof(device_name_prop), &device_name_prop); + gatt_register_callback((void *)gap_service_callback); + } + break; +#endif + +#if F_BT_LE_PRIVACY_SUPPORT + case GAP_TC_03_PRIVACY://privacy + { + uint8_t auth_sec_req_enable = true; + uint8_t irk_auto = true; + uint16_t privacy_timeout = 0x384; + uint8_t central_address_resolution = 1; + if (p_parse_value->param_count == 2) + { + privacy_timeout = p_parse_value->dw_param[1]; + } + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_GEN_LOCAL_IRK_AUTO, sizeof(uint8_t), &irk_auto); + gaps_set_parameter(GAPS_PARAM_CENTRAL_ADDRESS_RESOLUTION, sizeof(central_address_resolution), + ¢ral_address_resolution); + privacy_manage_mode(false); + privacy_set_gen_priv_addr_interval(privacy_timeout); + privacy_init(app_privacy_callback, false); + } + break; +#endif + case GAP_TC_04_PIN_CODE: + { + uint32_t auth_fix_passkey = 123456; /* passkey "000000"*/ + uint8_t auth_use_fix_passkey = true; + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY, sizeof(uint32_t), &auth_fix_passkey); + le_bond_set_param(GAP_PARAM_BOND_FIXED_PASSKEY_ENABLE, sizeof(uint8_t), &auth_use_fix_passkey); + } + break; +#if F_BT_LE_5_0_SUPPORT + case GAP_TC_05_BT5: + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + uint8_t use_extended = true; + uint8_t phys_prefer = GAP_PHYS_PREFER_ALL; + uint8_t tx_prefer = GAP_PHYS_PREFER_1M_BIT | GAP_PHYS_PREFER_2M_BIT | + GAP_PHYS_PREFER_CODED_BIT; + uint8_t rx_prefer = GAP_PHYS_PREFER_1M_BIT | GAP_PHYS_PREFER_CODED_BIT | + GAP_PHYS_PREFER_2M_BIT; +#if F_BT_LE_5_0_AE_ADV_SUPPORT + le_set_gap_param(GAP_PARAM_USE_EXTENDED_ADV, sizeof(use_extended), &use_extended); +#endif + le_set_gap_param(GAP_PARAM_DEFAULT_PHYS_PREFER, sizeof(phys_prefer), &phys_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_TX_PHYS_PREFER, sizeof(tx_prefer), &tx_prefer); + le_set_gap_param(GAP_PARAM_DEFAULT_RX_PHYS_PREFER, sizeof(rx_prefer), &rx_prefer); + conn_req_param.scan_interval = 0x20; + conn_req_param.scan_window = 0x20; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + conn_req_param.conn_latency = 1; + le_set_conn_param(GAP_CONN_PARAM_2M, &conn_req_param); + conn_req_param.conn_latency = 2; + le_set_conn_param(GAP_CONN_PARAM_CODED, &conn_req_param); + + { + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + + T_GAP_LE_EXT_SCAN_PARAM extended_scan_param[GAP_EXT_SCAN_MAX_PHYS_NUM]; + extended_scan_param[0].scan_type = GAP_SCAN_MODE_ACTIVE; + extended_scan_param[0].scan_interval = 400; + extended_scan_param[0].scan_window = 200; + + extended_scan_param[1].scan_type = GAP_SCAN_MODE_ACTIVE; + extended_scan_param[1].scan_interval = 440; + extended_scan_param[1].scan_window = 220; + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_phy_param(LE_SCAN_PHY_LE_1M, &extended_scan_param[0]); + le_ext_scan_set_phy_param(LE_SCAN_PHY_LE_CODED, &extended_scan_param[1]); + } +#endif + } + break; +#endif + case GAP_TC_07_CCCD: + { + uint8_t auth_sec_req_enable = true; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + simp_ble_service_add_service((void *)app_profile_callback); + } + break; +#if F_BT_LE_LOCAL_IRK_SETTING_SUPPORT + case GAP_TC_08_LOCAL_IRK: + { + T_LOCAL_IRK le_local_irk = {0, 1, 0, 5, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 9}; + le_bond_set_param(GAP_PARAM_BOND_SET_LOCAL_IRK, GAP_KEY_LEN, le_local_irk.local_irk); + } + break; +#endif + case GAP_TC_09_SLAVE_LATENCY://test slave latency + break; + +#if F_BT_LE_4_1_CBC_SUPPORT + case GAP_TC_10_BT41: + { + uint8_t chann_num = 1; + if (p_parse_value->param_count > 1) + { + chann_num = p_parse_value->dw_param[1]; + } + le_cbc_init(chann_num); + le_cbc_register_app_cb(app_credit_based_conn_callback); + } + break; +#endif +#if F_BT_LE_GAP_MSG_INFO_WAY + case GAP_TC_12_GAP_MSG_CALLBACK: + { + le_gap_msg_info_way(false); + } + break; +#endif + case GAP_TC_13_V3_V8_TX: + break; + + case GAP_TC_14_SRV_CHANGE: //test gap service write + { + uint8_t auth_sec_req_enable = true; + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(uint8_t), &auth_sec_req_enable); + //gatt_register_callback((void *)gap_service_callback); + } + break; + +#if APP_HID_TEST + case GAP_TC_15_HID_PROFILE: //test gap service write + { + hid_srv_id = hids_add_service((void *)app_profile_callback); + } + break; +#endif + + default: + break; + } + + /* Register BT Stack. */ + if (gap_start_bt_stack(evt_queue_handle, io_queue_handle, MAX_NUMBER_OF_GAP_MESSAGE)) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_dlps(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_DLPS_EN + if (p_parse_value->dw_param[0] == 0) + { + lps_mode_pause(); + data_uart_print("Active Mode\r\n"); + } + else + { + lps_mode_resume(); + data_uart_can_enter_dlps(true); + data_uart_print("LPS Mode\r\n"); + } +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_tracelevel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + if (p_parse_value->dw_param[0] == 1) + { + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 1); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 1); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 1); + data_uart_print("Log On Sucess\r\n"); + } + else if (p_parse_value->dw_param[0] == 0) + { + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 0); + data_uart_print("Log Off Sucess\r\n"); + } + else + { + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_TRACE, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_INFO, 0); + log_module_bitmap_trace_set(0xFFFFFFFFFFFFFFFF, TRACE_LEVEL_WARN, 0); + log_module_trace_set(TRACE_MODULE_GAP, TRACE_LEVEL_INFO, true); + log_module_trace_set(TRACE_MODULE_APP, TRACE_LEVEL_INFO, true); + data_uart_print("Log Test Mode\r\n"); + } + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_setlocaltype(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t local_bd_type = p_parse_value->dw_param[0]; + T_GAP_RAND_ADDR_TYPE rand_addr = (T_GAP_RAND_ADDR_TYPE)p_parse_value->dw_param[1]; + uint8_t random_addr[6] = {0}; + random_addr[0] = 0x4E; + random_addr[1] = 0xEF; + random_addr[2] = 0x3B; + random_addr[3] = 0x58; + random_addr[4] = 0xFA; + random_addr[5] = 0xFF; +#if F_BT_LE_PRIVACY_SUPPORT + if (local_bd_type > GAP_LOCAL_ADDR_LE_RAP_OR_RAND) +#else + if (local_bd_type > GAP_LOCAL_ADDR_LE_RANDOM) +#endif + { + return RESULT_CMD_ERR_PARAM; + } + + if (local_bd_type == GAP_LOCAL_ADDR_LE_RANDOM) + { + if (rand_addr != GAP_RAND_ADDR_STATIC) + { + le_gen_rand_addr((T_GAP_RAND_ADDR_TYPE)p_parse_value->dw_param[1], random_addr); + } + le_set_rand_addr(random_addr); + if (rand_addr == GAP_RAND_ADDR_STATIC) + { + le_cfg_local_identity_address(random_addr, GAP_IDENT_ADDR_RAND); + } + data_uart_print("set local random addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + random_addr[5], + random_addr[4], + random_addr[3], + random_addr[2], + random_addr[1], + random_addr[0]); + } +#if F_BT_LE_PRIVACY_SUPPORT + else if (local_bd_type == GAP_LOCAL_ADDR_LE_RAP_OR_RAND) + { + le_set_rand_addr(random_addr); + le_cfg_local_identity_address(random_addr, GAP_IDENT_ADDR_RAND); + } +#endif + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_setstatic(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t local_bd_type = GAP_LOCAL_ADDR_LE_RANDOM; + uint8_t type = p_parse_value->dw_param[0]; + uint8_t random_addr[6] = {0}; + random_addr[0] = 0x4E; + random_addr[1] = 0xEF; + random_addr[2] = 0x3B; + random_addr[3] = 0x58; + random_addr[4] = 0xFA; + random_addr[5] = 0xFF; + + if (type == 0) + { + random_addr[0] = 0x00; + } + else + { + random_addr[0] = 0x01; + } + data_uart_print("set local random addr:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + random_addr[5], + random_addr[4], + random_addr[3], + random_addr[2], + random_addr[1], + random_addr[0]); + le_set_rand_addr(random_addr); + le_cfg_local_identity_address(random_addr, GAP_IDENT_ADDR_RAND); + + le_adv_set_param(GAP_PARAM_ADV_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + le_scan_set_param(GAP_PARAM_SCAN_LOCAL_ADDR_TYPE, sizeof(local_bd_type), &local_bd_type); + return (RESULT_SUCESS); +} + +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_writedefaultdatalen(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint16_t tx_octets = p_parse_value->dw_param[0]; + uint16_t tx_time = p_parse_value->dw_param[1]; + + cause = le_write_default_data_len(tx_octets, tx_time); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_rssiread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_read_rssi(conn_id); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_READ_CHANN_MAP +static T_USER_CMD_PARSE_RESULT cmd_readchanmap(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + cause = le_read_chann_map(conn_id); + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_showcon(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t link_num; + uint8_t conn_id; + T_GAP_CONN_INFO conn_info; + link_num = le_get_max_link_num(); + for (conn_id = 0; conn_id < link_num; conn_id++) + { + if (le_get_conn_info(conn_id, &conn_info)) + { + data_uart_print("ShowCon conn_id %d state 0x%x role %d\r\n", conn_id, + conn_info.conn_state, conn_info.role); + data_uart_print("RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + conn_info.remote_bd[5], conn_info.remote_bd[4], + conn_info.remote_bd[3], conn_info.remote_bd[2], + conn_info.remote_bd[1], conn_info.remote_bd[0], + conn_info.remote_bd_type); + } + } + data_uart_print("active link num %d, idle link num %d\r\n", + le_get_active_link_num(), le_get_idle_link_num()); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_conupdreq(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t conn_interval_min = p_parse_value->dw_param[1]; + uint16_t conn_interval_max = p_parse_value->dw_param[2]; + uint16_t conn_latency = p_parse_value->dw_param[3]; + uint16_t supervision_timeout = p_parse_value->dw_param[4]; + + + cause = le_update_conn_param(conn_id, + conn_interval_min, + conn_interval_max, + conn_latency, + supervision_timeout, + 2 * (conn_interval_min - 1), + 2 * (conn_interval_max - 1) + ); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_disc(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_disconnect(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_setdatalength(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t tx_octets = p_parse_value->dw_param[1]; + uint16_t tx_time = p_parse_value->dw_param[2]; + + cause = le_set_data_len(conn_id, + tx_octets, + tx_time); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +static T_USER_CMD_PARSE_RESULT cmd_wl(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t conn_id = p_parse_value->dw_param[1]; + T_GAP_CONN_INFO conn_info; + + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list(GAP_WHITE_LIST_OP_CLEAR, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + return (T_USER_CMD_PARSE_RESULT)cause; + } + + if (le_get_conn_info(conn_id, &conn_info)) + { + cause = le_modify_white_list(op, conn_info.remote_bd, + (T_GAP_REMOTE_ADDR_TYPE)conn_info.remote_bd_type); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_CMD_ERR_PARAM; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_wldev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t dev_idx = p_parse_value->dw_param[1]; + + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list(GAP_WHITE_LIST_OP_CLEAR, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + return (T_USER_CMD_PARSE_RESULT)cause; + } + + if (dev_idx < dev_list_count) + { + cause = le_modify_white_list(op, dev_list[dev_idx].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[dev_idx].bd_type); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_authmode(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t auth_pair_mode = GAP_PAIRING_MODE_PAIRABLE; + uint16_t auth_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + uint8_t auth_io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; +#if F_BT_LE_SMP_OOB_SUPPORT + uint8_t oob_enable = false; +#endif + uint8_t auth_sec_req_enable = false; + uint16_t auth_sec_req_flags = GAP_AUTHEN_BIT_BONDING_FLAG; + + if (p_parse_value->param_count > 0) + { + auth_flags = p_parse_value->dw_param[0]; + auth_sec_req_flags = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + auth_io_cap = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + auth_sec_req_enable = p_parse_value->dw_param[2]; + } +#if F_BT_LE_SMP_OOB_SUPPORT + if (p_parse_value->param_count > 3) + { + oob_enable = p_parse_value->dw_param[3]; + } +#endif + gap_set_param(GAP_PARAM_BOND_PAIRING_MODE, sizeof(auth_pair_mode), &auth_pair_mode); + gap_set_param(GAP_PARAM_BOND_AUTHEN_REQUIREMENTS_FLAGS, sizeof(auth_flags), &auth_flags); + gap_set_param(GAP_PARAM_BOND_IO_CAPABILITIES, sizeof(auth_io_cap), &auth_io_cap); +#if F_BT_LE_SMP_OOB_SUPPORT + gap_set_param(GAP_PARAM_BOND_OOB_ENABLED, sizeof(uint8_t), &oob_enable); +#endif + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_ENABLE, sizeof(auth_sec_req_enable), &auth_sec_req_enable); + le_bond_set_param(GAP_PARAM_BOND_SEC_REQ_REQUIREMENT, sizeof(auth_sec_req_flags), + &auth_sec_req_flags); + cause = gap_set_pairable_mode(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_setkeydis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t init_dist = p_parse_value->dw_param[0]; + uint8_t rsp_dist = p_parse_value->dw_param[1]; + le_bond_cfg_local_key_distribute(init_dist, rsp_dist); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_sauth(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + cause = le_bond_pair(conn_id); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_userconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT; + T_GAP_CAUSE cause; + if (p_parse_value->dw_param[1] == 0) + { + confirm = GAP_CFM_CAUSE_REJECT; + } + cause = le_bond_user_confirm(conn_id, confirm); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_authkey(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint32_t passcode = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + T_GAP_CFM_CAUSE confirm = GAP_CFM_CAUSE_ACCEPT; + if (passcode > GAP_PASSCODE_MAX) + { + confirm = GAP_CFM_CAUSE_REJECT; + } + cause = le_bond_passkey_input_confirm(conn_id, passcode, + confirm); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_SMP_OOB_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_oob(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t oob_data[GAP_OOB_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5}; + oob_data[0] = p_parse_value->dw_param[1]; + oob_data[3] = p_parse_value->dw_param[2]; + oob_data[7] = p_parse_value->dw_param[3]; + oob_data[15] = p_parse_value->dw_param[4]; + le_bond_set_param(GAP_PARAM_BOND_OOB_DATA, GAP_OOB_LEN, oob_data); + + cause = le_bond_oob_input_confirm(conn_id, GAP_CFM_CAUSE_ACCEPT); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_keypress(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_KEYPRESS_NOTIF_TYPE notify_type = (T_GAP_KEYPRESS_NOTIF_TYPE)p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + cause = le_bond_keypress_notify(conn_id, notify_type); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_bondclear(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_GAP_KEY_MANAGER_SUPPORT + le_bond_clear_all_keys(); +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_seclevel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + T_GAP_SEC_LEVEL sec_level; + uint8_t conn_id = p_parse_value->dw_param[0]; + + cause = le_bond_get_sec_level(conn_id, &sec_level); + if (sec_level == GAP_SEC_LEVEL_NO) + { + data_uart_print("GAP_SEC_LEVEL_NO\r\n"); + } + else if (sec_level == GAP_SEC_LEVEL_UNAUTHEN) + { + data_uart_print("GAP_SEC_LEVEL_UNAUTHEN\r\n"); + } + else if (sec_level == GAP_SEC_LEVEL_AUTHEN) + { + data_uart_print("GAP_SEC_LEVEL_AUTHEN\r\n"); + } + else if (sec_level == GAP_SEC_LEVEL_SC_UNAUTHEN) + { + data_uart_print("GAP_SEC_LEVEL_SC_UNAUTHEN\r\n"); + } + else if (sec_level == GAP_SEC_LEVEL_SC_AUTHEN) + { + data_uart_print("GAP_SEC_LEVEL_SC_AUTHEN\r\n"); + } + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_bondinfo(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ +#if F_BT_GAP_KEY_MANAGER_SUPPORT + uint8_t i; + T_LE_KEY_ENTRY *p_entry; + for (i = 0; i < bond_storage_num; i++) + { + p_entry = le_find_key_entry_by_idx(i); + if (p_entry != NULL) + { + data_uart_print("bond_dev[%d]: bd 0x%02x%02x%02x%02x%02x%02x, addr_type %d, flags 0x%x\r\n", + p_entry->idx, + p_entry->remote_bd.addr[5], + p_entry->remote_bd.addr[4], + p_entry->remote_bd.addr[3], + p_entry->remote_bd.addr[2], + p_entry->remote_bd.addr[1], + p_entry->remote_bd.addr[0], + p_entry->remote_bd.remote_bd_type, + p_entry->flags); + } + } +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_scan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + + if (p_parse_value->param_count > 0) + { + scan_filter_policy = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + scan_filter_duplicate = p_parse_value->dw_param[1]; + } + + link_mgr_clear_device_list(); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_POLICY, sizeof(scan_filter_policy), + &scan_filter_policy); + le_scan_set_param(GAP_PARAM_SCAN_FILTER_DUPLICATES, sizeof(scan_filter_duplicate), + &scan_filter_duplicate); + cause = le_scan_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_scan_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_showdev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + data_uart_print("Advertising and Scan response: filter uuid = 0xA00A dev list\r\n"); + for (i = 0; i < dev_list_count; i++) + { + data_uart_print("RemoteBd[%d] = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d\r\n", + i, + dev_list[i].bd_addr[5], dev_list[i].bd_addr[4], + dev_list[i].bd_addr[3], dev_list[i].bd_addr[2], + dev_list[i].bd_addr[1], dev_list[i].bd_addr[0], + dev_list[i].bd_type); + if (dev_list[i].bd_type == GAP_REMOTE_ADDR_LE_RANDOM) + { + uint8_t addr = dev_list[i].bd_addr[5] & RANDOM_ADDR_MASK; + if (addr == RANDOM_ADDR_MASK_STATIC) + { + data_uart_print("Static Random Addr\r\n"); + } + else if (addr == RANDOM_ADDR_MASK_RESOLVABLE) + { + data_uart_print("Resolv Random Addr\r\n"); + } + else if (addr == RANDOM_ADDR_MASK_NON_RESOLVABLE) + { + data_uart_print("Non-resolv Random Addr\r\n"); + } + else + { + data_uart_print("Unknown Random Addr\r\n"); + } + } + } + + return (RESULT_SUCESS); +} + +#if F_BT_LE_GAP_CENTRAL_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_con(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t addr[6] = {0}; + uint8_t addr_len; + uint8_t addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + if (p_parse_value->param_count >= 7) + { + addr_type = p_parse_value->dw_param[6]; + } + + cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, addr, (T_GAP_REMOTE_ADDR_TYPE)addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, + 1000); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_condev(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t dev_idx = p_parse_value->dw_param[0]; + if (dev_idx < dev_list_count) + { + T_GAP_CAUSE cause; + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + T_GAP_LOCAL_ADDR_TYPE local_addr_type = (T_GAP_LOCAL_ADDR_TYPE)p_parse_value->dw_param[1]; + uint8_t init_phys = 0; +#if F_BT_LE_5_0_SUPPORT + uint32_t mode = p_parse_value->dw_param[2]; + + switch (mode) + { + case 0x000: + init_phys = 0; + break; + case 0x001: + init_phys = GAP_PHYS_CONN_INIT_1M_BIT; + break; + case 0x010: + init_phys = GAP_PHYS_CONN_INIT_2M_BIT; + break; + case 0x011: + init_phys = GAP_PHYS_CONN_INIT_2M_BIT | GAP_PHYS_CONN_INIT_1M_BIT; + break; + case 0x100: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT; + break; + case 0x101: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT | GAP_PHYS_CONN_INIT_1M_BIT; + break; + case 0x110: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT | GAP_PHYS_CONN_INIT_2M_BIT; + break; + case 0x111: + init_phys = GAP_PHYS_CONN_INIT_CODED_BIT | + GAP_PHYS_CONN_INIT_2M_BIT | + GAP_PHYS_CONN_INIT_1M_BIT; + break; + + default: + break; + } +#endif + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + cause = le_connect(init_phys, dev_list[dev_idx].bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)dev_list[dev_idx].bd_type, + local_addr_type, + 1000); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_chanclassset(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t chan_map[5] = {0}; + uint8_t i; + for (i = 0; i < 5; i++) + { + chan_map[i] = (uint8_t)p_parse_value->dw_param[i]; + } + + chan_map[4] = chan_map[4] & 0x1F; + + cause = le_set_host_chann_classif(chan_map); + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#if F_BT_LE_GATT_CLIENT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_srvdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + cause = client_all_primary_srv_discovery(conn_id, CLIENT_PROFILE_GENERAL_ID); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_gapdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool ret = gaps_start_discovery(conn_id); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_gapread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAPS_READ_TYPE read_type = (T_GAPS_READ_TYPE)p_parse_value->dw_param[1]; + bool ret = gaps_read(conn_id, read_type); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool ret = simp_ble_client_start_discovery(conn_id); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpread(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char to be read. */ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool ret; + T_SIMP_READ_TYPE read_type = (T_SIMP_READ_TYPE)p_parse_value->dw_param[1]; + /* Read by handle or UUID, 1--by UUID, 0--by handle. */ + uint8_t read_pattern = (uint8_t)p_parse_value->dw_param[2]; + + if (read_pattern) + { + ret = simp_ble_client_read_by_uuid(conn_id, read_type); + } + else + { + ret = simp_ble_client_read_by_handle(conn_id, read_type); + } + + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpcccd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char CCCD command. */ + bool ret = false; + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t type = p_parse_value->dw_param[1]; + /* Enable or disable, 1--enable, 0--disable. */ + uint16_t cccd_data = p_parse_value->dw_param[2]; + + switch (type) + { + case 0:/* V3 Notify char notif enable/disable. */ + ret = simp_ble_client_set_v3_notify(conn_id, cccd_data); + break; + case 1:/* V4 Indicate char indicate enable/disable. */ + ret = simp_ble_client_set_v4_ind(conn_id, cccd_data); + break; + case 2: + ret = simp_ble_client_set_v8_cccd(conn_id, cccd_data); + break; + default: + break; + } + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpwrite(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool ret = false; + uint8_t conn_id = p_parse_value->dw_param[0]; + /* Indicate which char to be written. */ + uint8_t write_type = (uint8_t)p_parse_value->dw_param[1]; + uint8_t data[270]; + uint16_t length = 270; + uint16_t i; + for (i = 0; i < 270; i++) + { + data[i] = i; + } + if (p_parse_value->param_count > 2) + { + length = p_parse_value->dw_param[2]; + if (length > 270) + { + length = 270; + } + } + + switch (write_type) + { + case 2:/* Write the V2 Writable char value on peer server. */ + { + T_GATT_WRITE_TYPE type = (T_GATT_WRITE_TYPE)p_parse_value->dw_param[3]; + if (type > GATT_WRITE_TYPE_SIGNED_CMD) + { + return (RESULT_CMD_ERR_PARAM); + } + ret = simp_ble_client_write_v2_char(conn_id, length, data, type); + } + break; + case 3: + { + ret = simp_ble_client_write_v6_char(conn_id, length, data); + } + break; + default: + break; + } + + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simphdl(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN]; + uint8_t hdl_idx; + bool ret = simp_ble_client_get_hdl_cache(conn_id, hdl_cache, + sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN); + + if (ret) + { + for (hdl_idx = HDL_SIMBLE_SRV_START; hdl_idx < HDL_SIMBLE_CACHE_LEN; hdl_idx++) + { + data_uart_print("-->Index %d -- Handle 0x%x\r\n", hdl_idx, hdl_cache[hdl_idx]); + } + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} +#endif +#if F_BT_ANCS_CLIENT_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_ancsdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool ret; + uint8_t conn_id = p_parse_value->dw_param[0]; + ret = ancs_start_discovery(conn_id); + if (ret) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_startadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advdata(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t len = p_parse_value->dw_param[0]; + uint8_t value = p_parse_value->dw_param[1]; + uint8_t adv_data[31]; + memset(adv_data, value, len); + le_adv_set_param(GAP_PARAM_ADV_DATA, len, adv_data); + cause = le_adv_update_param(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_adv_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_adv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = 80; + uint16_t adv_int_max = 80; + + if (p_parse_value->param_count > 0) + { + adv_int_min = p_parse_value->dw_param[0]; + adv_int_max = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + adv_filter_policy = p_parse_value->dw_param[1]; + } + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advld(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_LDC_DIRECT_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint16_t adv_int_min = 300; + uint16_t adv_int_max = 320; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t addr_len; + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + adv_direct_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advhd(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_HDC_DIRECT_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t addr_len; + + for (addr_len = 0; addr_len < GAP_BD_ADDR_LEN; addr_len++) + { + adv_direct_addr[addr_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - addr_len - 1]; + } + + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advscan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_SCAN_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = 300; + uint16_t adv_int_max = 320; + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advnonconn(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_NONCONN_IND; + uint8_t adv_chann_map = GAP_ADVCHAN_ALL; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + uint16_t adv_int_min = 300; + uint16_t adv_int_max = 320; + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_CHANNEL_MAP, sizeof(adv_chann_map), &adv_chann_map); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MIN, sizeof(adv_int_min), &adv_int_min); + le_adv_set_param(GAP_PARAM_ADV_INTERVAL_MAX, sizeof(adv_int_max), &adv_int_max); + + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_advwl(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + //advertising parameters + T_GAP_CAUSE cause; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_filter_policy = GAP_ADV_FILTER_WHITE_LIST_ALL; + uint8_t wl_addr_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t wl_addr[GAP_BD_ADDR_LEN] = {0}; + + //get connected device address and address type + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR_TYPE, &wl_addr_type); + le_get_gap_param(GAP_PARAM_LATEST_CONN_BD_ADDR, &wl_addr); + + le_modify_white_list(GAP_WHITE_LIST_OP_ADD, wl_addr, (T_GAP_REMOTE_ADDR_TYPE)wl_addr_type); + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + + cause = le_adv_start(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_readadvpwr(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_adv_read_tx_power(); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +static T_USER_CMD_PARSE_RESULT cmd_latency(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + bool disable = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause; + + cause = le_disable_slave_latency(conn_id, disable); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_epassed(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + /* Indicate which char to be written. */ + bool enable = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + + cause = le_update_passed_chann_map(enable); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +static T_USER_CMD_PARSE_RESULT cmd_srvchange(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + gatts_service_changed_indicate(conn_id, start_handle, end_handle); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv3notify(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t notif_val[244]; + uint16_t length = p_parse_value->dw_param[1]; + uint16_t tx_num = 0; + + if (length > 244) + { + return RESULT_ERR; + } + memset(notif_val, 1, length); + + if (p_parse_value->param_count > 2) + { + tx_num = p_parse_value->dw_param[2]; + } + +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI + GPIO->DATAOUT |= BIT(18); + GPIO->DATAOUT &= ~BIT(18); +#endif + if (!simp_ble_service_send_v3_notify(conn_id, simp_srv_id, + ¬if_val, + length)) + { + return (RESULT_ERR); + } + if (tx_num > 1) + { + gap_v3_notif_test.v3_tx_idx = 2; + gap_v3_notif_test.v3_tx_num = tx_num - 1; + gap_v3_notif_test.v3_tx_conn_id = conn_id; + gap_v3_notif_test.v3_tx_len = length; + gap_v3_notif_test.v3_tx_cmp_num = 0; + gap_v3_notif_test.v3_rx_num = 0; + gap_v3_notif_test.v8_rx_num = 0; + gap_v3_notif_test.v8_tx_cnt = 0; + gap_v3_notif_test.v3_tx_cnt = 1; + + } +#if F_BT_UPPER_STACK_USE_VIRTUAL_HCI + GPIO->DATAOUT |= BIT(18); + GPIO->DATAOUT &= ~BIT(18); +#endif + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv3dump(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + data_uart_print("simpv3dump: v3_tx_idx 0x%x, v3_tx_conn_id %d, v3_tx_num %d, v3_tx_cmp_num %d, v3_tx_cnt %d, v8_tx_cnt %d\r\n", + gap_v3_notif_test.v3_tx_idx, + gap_v3_notif_test.v3_tx_conn_id, + gap_v3_notif_test.v3_tx_num, + gap_v3_notif_test.v3_tx_cmp_num, + gap_v3_notif_test.v3_tx_cnt, + gap_v3_notif_test.v8_tx_cnt); + data_uart_print("simpv3dump: v3_rx_num %d, v8_rx_num %d\r\n", + gap_v3_notif_test.v3_rx_num, + gap_v3_notif_test.v8_rx_num); + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv4ind(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t ind_val[244]; + uint16_t length = p_parse_value->dw_param[1]; + uint16_t i; + + if (length > 244) + { + return RESULT_ERR; + } + for (i = 0; i < length; i++) + { + ind_val[i] = i; + } + + if (simp_ble_service_send_v4_indicate(conn_id, simp_srv_id, + &ind_val, + length)) + { + return (RESULT_SUCESS); + } + else + { + return (RESULT_ERR); + } +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv8notify(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t notify_val = (uint8_t)p_parse_value->dw_param[1]; + + + if (!simp_ble_service_simple_v8_notify(conn_id, simp_srv_id, + ¬ify_val, + 1)) + { + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv8ind(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t ind_val = (uint8_t)p_parse_value->dw_param[1]; + + + if (!simp_ble_service_simple_v8_indicate(conn_id, simp_srv_id, + &ind_val, 1)) + { + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_simpv7len(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint16_t len = p_parse_value->dw_param[0]; + uint8_t data[SIMP_READ_V7_MAX_LEN]; + uint16_t i; + if (len > SIMP_READ_V7_MAX_LEN) + { + return (RESULT_ERR); + } + for (i = 0; i < len; i++) + { + data[i] = i; + } + simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V7_LEN, len, data); + + return (RESULT_SUCESS); +} + + +static T_USER_CMD_PARSE_RESULT cmd_simpv2writeconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + + + if (!server_attr_write_confirm(conn_id, + simp_srv_id, + SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX, + APP_RESULT_SUCCESS)) + { + return (RESULT_ERR); + } + + return (RESULT_SUCESS); +} + + +#if F_BT_LE_5_0_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_setphy(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + T_GAP_PHYS_OPTIONS phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S8; + T_GAP_CAUSE cause; + + if (p_parse_value->dw_param[1] == 0) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_1M_BIT; + rx_phys = GAP_PHYS_PREFER_1M_BIT; + } + else if (p_parse_value->dw_param[1] == 1) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_2M_BIT; + rx_phys = GAP_PHYS_PREFER_2M_BIT; + } + else if (p_parse_value->dw_param[1] == 2) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_CODED_BIT; + rx_phys = GAP_PHYS_PREFER_CODED_BIT; + phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S8; + } + else if (p_parse_value->dw_param[1] == 3) + { + all_phys = GAP_PHYS_PREFER_ALL; + tx_phys = GAP_PHYS_PREFER_CODED_BIT; + rx_phys = GAP_PHYS_PREFER_CODED_BIT; + phy_options = GAP_PHYS_OPTIONS_CODED_PREFER_S2; + } + else + { + all_phys = GAP_PHYS_NO_PREFER_TX_BIT; + tx_phys = GAP_PHYS_PREFER_2M_BIT; + rx_phys = GAP_PHYS_PREFER_1M_BIT; + } + cause = le_set_phy(conn_id, all_phys, tx_phys, rx_phys, phy_options); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_escan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + uint8_t ext_scan_filter_policy = GAP_SCAN_FILTER_ANY; + uint8_t ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLE; + uint16_t ext_scan_duration = 0; + uint16_t ext_scan_period = 0; + uint8_t scan_phys = GAP_EXT_SCAN_PHYS_1M_BIT | GAP_EXT_SCAN_PHYS_CODED_BIT; + uint8_t mode = p_parse_value->dw_param[0]; + + link_mgr_clear_device_list(); + if (mode == 1) + { + ext_scan_duration = 500; + } + else if (mode == 2) + { + ext_scan_duration = 500; + ext_scan_period = 8; + ext_scan_filter_duplicate = GAP_SCAN_FILTER_DUPLICATE_ENABLED_RESET_FOR_EACH_PERIOD; + } + else if (mode == 3) + { + ext_scan_filter_policy = GAP_SCAN_FILTER_WHITE_LIST; + } + else if (mode == 4) + { + scan_phys = p_parse_value->dw_param[1]; + } + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PHYS, sizeof(scan_phys), + &scan_phys); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_DURATION, sizeof(ext_scan_duration), + &ext_scan_duration); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_PERIOD, sizeof(ext_scan_period), + &ext_scan_period); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_POLICY, sizeof(ext_scan_filter_policy), + &ext_scan_filter_policy); + le_ext_scan_set_param(GAP_PARAM_EXT_SCAN_FILTER_DUPLICATES, sizeof(ext_scan_filter_duplicate), + &ext_scan_filter_duplicate); + cause = le_ext_scan_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopescan(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_ext_scan_stop(); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_seadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle = p_parse_value->dw_param[0]; + uint16_t duration = 0; + uint8_t max_num = 0; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 1) + { + duration = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + max_num = p_parse_value->dw_param[2]; + } + + cause = le_ext_adv_set_adv_enable_param(adv_handle, duration, max_num); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_ueadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + uint8_t update_flags = EXT_ADV_SET_ADV_PARAS | EXT_ADV_SET_ADV_DATA | EXT_ADV_SET_SCAN_RSP_DATA; + T_GAP_CAUSE cause; + uint8_t adv_handle; + uint16_t adv_event_prop = (uint16_t) LE_EXT_ADV_LEGACY_ADV_CONN_SCAN_UNDIRECTED; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t *p_peer_address = NULL; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_2M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + + if (p_parse_value->param_count > 1) + { + update_flags = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + own_address_type = (T_GAP_LOCAL_ADDR_TYPE)p_parse_value->dw_param[2]; + } + if (idx == 0) + { + adv_handle = le_ext_adv_create_adv_handle(); + le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_adv_data), (uint8_t *)ext_adv_data); + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_scan_response), + (uint8_t *)ext_scan_response); + } + else + { + adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_SCAN_UNDIRECTED; + switch (idx) + { + case 0x11: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + case 0x12: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x13: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + case 0x31: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + + case 0x32: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x33: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + default: + adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_SCAN_UNDIRECTED; + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + break; + } + if (p_parse_value->param_count > 3) + { + adv_event_prop = p_parse_value->dw_param[3]; + } +#if 0 + if (adv_event_prop & GAP_EXT_ADV_EVT_PROP_SCANNABLE_ADV == 0) + { + update_flags &= ~EXT_ADV_SET_SCAN_RSP_DATA; + + } + + if (adv_event_prop & GAP_EXT_ADV_EVT_PROP_CONNECTABLE_ADV == 0) + { + update_flags &= ~EXT_ADV_SET_ADV_DATA; + } +#endif + adv_handle = le_ext_adv_create_adv_handle(); + le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + } + if (own_address_type == GAP_LOCAL_ADDR_LE_RANDOM) + { + uint8_t rand_addr[6]; + le_gen_rand_addr(GAP_RAND_ADDR_STATIC, rand_addr); + cause = le_ext_adv_set_random(adv_handle, rand_addr); + } + else if (own_address_type == GAP_LOCAL_ADDR_LE_RAP_OR_RAND) + { + uint8_t rand_addr[6]; + rand_addr[0] = 0x4E; + rand_addr[1] = 0x11; + rand_addr[2] = 0x22; + rand_addr[3] = 0x33; + rand_addr[4] = 0x44; + rand_addr[5] = adv_handle; + cause = le_ext_adv_set_random(adv_handle, rand_addr); + le_cfg_local_identity_address(rand_addr, GAP_IDENT_ADDR_RAND); + } + cause = le_ext_adv_start_setting(adv_handle, update_flags); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_uedadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[6]; + T_GAP_CAUSE cause; + uint8_t adv_handle; + uint16_t adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_NON_SCAN_NON_CONN_DIRECTED; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + T_GAP_LOCAL_ADDR_TYPE own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + T_GAP_REMOTE_ADDR_TYPE peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t peer_address[GAP_BD_ADDR_LEN] = {0}; + uint8_t filter_policy = 0; + uint8_t tx_power = 127; + T_GAP_PHYS_PRIM_ADV_TYPE primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + uint8_t secondary_adv_max_skip = 0x00; + T_GAP_PHYS_TYPE secondary_adv_phy = GAP_PHYS_1M; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + uint8_t peer_address_len; + + for (peer_address_len = 0; peer_address_len < GAP_BD_ADDR_LEN; peer_address_len++) + { + peer_address[peer_address_len] = p_parse_value->dw_param[GAP_BD_ADDR_LEN - peer_address_len - 1]; + } + + if (p_parse_value->param_count > 7) + { + adv_event_prop = p_parse_value->dw_param[7]; + + } + switch (idx) + { + case 0x11: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + case 0x12: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x13: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_1M; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + case 0x31: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_1M; + } + break; + + case 0x32: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_2M; + } + break; + + case 0x33: + { + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + secondary_adv_phy = GAP_PHYS_CODED; + } + break; + + default: + adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_SCAN_UNDIRECTED; + primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + break; + } + + adv_handle = le_ext_adv_create_adv_handle(); + le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + own_address_type, + peer_address_type, + peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + primary_adv_phy, + secondary_adv_max_skip, + secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + le_ext_adv_set_adv_data(adv_handle, sizeof(ext_large_adv_data), (uint8_t *)ext_large_adv_data); + le_ext_adv_set_scan_response_data(adv_handle, sizeof(ext_large_scan_data), + (uint8_t *)ext_large_scan_data); + cause = le_ext_adv_start_setting(adv_handle, EXT_ADV_SET_AUTO); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_eadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle[4] = {0}; + uint8_t num_of_sets = 1; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 0) + { + adv_handle[0] = p_parse_value->dw_param[0]; + num_of_sets = 1; + } + if (p_parse_value->param_count > 1) + { + adv_handle[1] = p_parse_value->dw_param[1]; + num_of_sets = 2; + } + if (p_parse_value->param_count > 2) + { + adv_handle[2] = p_parse_value->dw_param[2]; + num_of_sets = 3; + } + if (p_parse_value->param_count > 3) + { + adv_handle[3] = p_parse_value->dw_param[3]; + num_of_sets = 4; + } + cause = le_ext_adv_enable(num_of_sets, adv_handle); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_stopeadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle[4] = {0}; + uint8_t num_of_sets = 1; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 0) + { + adv_handle[0] = p_parse_value->dw_param[0]; + num_of_sets = 1; + } + if (p_parse_value->param_count > 1) + { + adv_handle[1] = p_parse_value->dw_param[1]; + num_of_sets = 2; + } + if (p_parse_value->param_count > 2) + { + adv_handle[2] = p_parse_value->dw_param[2]; + num_of_sets = 3; + } + if (p_parse_value->param_count > 3) + { + adv_handle[3] = p_parse_value->dw_param[3]; + num_of_sets = 4; + } + cause = le_ext_adv_disable(num_of_sets, adv_handle); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_ceadv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_ext_adv_clear_set(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_readv(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_handle = 0; + T_GAP_CAUSE cause; + if (p_parse_value->param_count > 0) + { + adv_handle = p_parse_value->dw_param[0]; + } + cause = le_ext_adv_remove_set(adv_handle); + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_advrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + uint8_t adv_evt_type = GAP_ADTYPE_ADV_IND; + uint8_t adv_filter_policy = GAP_ADV_FILTER_ANY; + T_GAP_CAUSE cause; + + if (p_parse_value->param_count > 0) + { + adv_evt_type = p_parse_value->dw_param[0]; + } + if (p_parse_value->param_count > 1) + { + adv_filter_policy = p_parse_value->dw_param[1]; + } + if (p_parse_value->param_count > 2) + { + uint8_t idx = p_parse_value->dw_param[2]; + T_LE_KEY_ENTRY *p_entry; + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + adv_direct_type = p_entry->resolved_remote_bd.remote_bd_type; + memcpy(adv_direct_addr, p_entry->resolved_remote_bd.addr, 6); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + } + + le_adv_set_param(GAP_PARAM_ADV_EVENT_TYPE, sizeof(adv_evt_type), &adv_evt_type); + le_adv_set_param(GAP_PARAM_ADV_FILTER_POLICY, sizeof(adv_filter_policy), &adv_filter_policy); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + + cause = le_adv_start(); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_readlra(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + T_LE_KEY_ENTRY *p_entry; + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + cause = privacy_read_local_resolv_addr((T_GAP_REMOTE_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_readpra(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + T_LE_KEY_ENTRY *p_entry; + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + cause = privacy_read_peer_resolv_addr((T_GAP_REMOTE_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_setrae(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + bool enable = true; + T_GAP_CAUSE cause; + if (p_parse_value->dw_param[0] == 0) + { + enable = false; + } + cause = privacy_set_addr_resolution(enable); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_showrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t i; + T_LE_KEY_ENTRY *p_entry; + data_uart_print("show resolved list\r\n"); + for (i = 0; i < bond_storage_num; i++) + { + p_entry = le_find_key_entry_by_idx(i); + if (p_entry != NULL) + { + data_uart_print("rel[%d] RemoteBd = [%02x:%02x:%02x:%02x:%02x:%02x] type = %d flags = 0x%x\r\n", + i, + p_entry->resolved_remote_bd.addr[5], p_entry->resolved_remote_bd.addr[4], + p_entry->resolved_remote_bd.addr[3], p_entry->resolved_remote_bd.addr[2], + p_entry->resolved_remote_bd.addr[1], p_entry->resolved_remote_bd.addr[0], + p_entry->resolved_remote_bd.remote_bd_type, + p_entry->flags); + } + + } + + return (RESULT_SUCESS); +} + +static T_USER_CMD_PARSE_RESULT cmd_setprivacy(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + bool mode = p_parse_value->dw_param[1]; + T_LE_KEY_ENTRY *p_entry; + T_GAP_CAUSE cause; + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry != NULL) + { + cause = privacy_set_peer_mode((T_GAP_REMOTE_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr, + mode); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_CMD_ERR_PARAM; + } +} + +static T_USER_CMD_PARSE_RESULT cmd_wlrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_WHITE_LIST_OP op = (T_GAP_WHITE_LIST_OP)p_parse_value->dw_param[0]; + uint8_t idx = p_parse_value->dw_param[1]; + T_LE_KEY_ENTRY *p_entry; + T_GAP_CAUSE cause; + if (op == GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list(op, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + } + else + { + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + cause = le_modify_white_list(op, p_entry->resolved_remote_bd.addr, + (T_GAP_REMOTE_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type); + } + else + { + return RESULT_CMD_ERR_PARAM; + } + } + return (T_USER_CMD_PARSE_RESULT)cause; + +} + +static T_USER_CMD_PARSE_RESULT cmd_conrel(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t idx = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause; + T_LE_KEY_ENTRY *p_entry; + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 80; + conn_req_param.conn_interval_max = 80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + cause = le_connect(0, p_entry->resolved_remote_bd.addr, + (T_GAP_REMOTE_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type, + (T_GAP_LOCAL_ADDR_TYPE)p_parse_value->dw_param[1], + 1000); + return (T_USER_CMD_PARSE_RESULT)cause; + } + else + { + return RESULT_ERR; + } +} +#endif + +#if F_BT_LE_4_1_CBC_SUPPORT +static T_USER_CMD_PARSE_RESULT cmd_lepsm(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_reg_psm(p_parse_value->dw_param[0], p_parse_value->dw_param[1]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_lesec(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_set_psm_security(p_parse_value->dw_param[0], p_parse_value->dw_param[1], + (T_LE_CBC_SECURITY_MODE)p_parse_value->dw_param[2], p_parse_value->dw_param[3]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_conle(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_create(p_parse_value->dw_param[0], p_parse_value->dw_param[1]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_discle(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + cause = le_cbc_disc(p_parse_value->dw_param[0]); + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_ledata(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause; + void *p_buffer; + uint16_t cid = p_parse_value->dw_param[0]; + uint16_t length = p_parse_value->dw_param[1]; + p_buffer = os_mem_zalloc(RAM_TYPE_DATA_ON, length); + if (p_buffer != NULL) + { + memset(p_buffer, 2, length); + + cause = le_cbc_send_data(cid, p_buffer, length); + os_mem_free(p_buffer); + } + else + { + return RESULT_GAP_CAUSE_NO_RESOURCE; + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +#if F_BT_CONTROLLER_POWER_CONTROL +static T_USER_CMD_PARSE_RESULT cmd_poweron(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = gap_bt_power_on(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +static T_USER_CMD_PARSE_RESULT cmd_poweroff(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE cause = gap_bt_power_off(); + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +#if APP_GENERAL_CLIENT_TEST +T_USER_CMD_PARSE_RESULT cmd_indconf(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + T_GAP_CAUSE ret; + uint8_t conn_id = p_parse_value->dw_param[0]; + ret = gcs_attr_ind_confirm(conn_id); + return (T_USER_CMD_PARSE_RESULT)ret; +} + +T_USER_CMD_PARSE_RESULT cmd_write(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint8_t write_type = p_parse_value->dw_param[1]; + uint16_t handle = p_parse_value->dw_param[2]; + uint16_t length = p_parse_value->dw_param[3]; + uint8_t data[512] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + if (p_parse_value->param_count > 4) + { + for (uint8_t i = 0; i < p_parse_value->param_count - 4; ++i) + { + data[i] = p_parse_value->dw_param[i + 4]; + } + } + + T_GAP_CAUSE ret = gcs_attr_write(conn_id, (T_GATT_WRITE_TYPE)write_type, handle, + length, data); + return (T_USER_CMD_PARSE_RESULT)ret; +} + +T_USER_CMD_PARSE_RESULT cmd_gsrvdis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause = gcs_all_primary_srv_discovery(conn_id); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +T_USER_CMD_PARSE_RESULT cmd_srvuuid(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->dw_param[1] == 0) + { + uint16_t uuid16 = p_parse_value->dw_param[2]; + cause = gcs_by_uuid_srv_discovery(conn_id, uuid16); + } + else if (p_parse_value->dw_param[1] == 1) + { + uint32_t u0 = p_parse_value->dw_param[2]; + uint32_t u1 = p_parse_value->dw_param[3]; + uint32_t u2 = p_parse_value->dw_param[4]; + uint32_t u3 = p_parse_value->dw_param[5]; + uint8_t uuid128[16] = + { + (uint8_t)u3, (uint8_t)(u3 >> 8), (uint8_t)(u3 >> 16), (uint8_t)(u3 >> 24), + (uint8_t)u2, (uint8_t)(u2 >> 8), (uint8_t)(u2 >> 16), (uint8_t)(u2 >> 24), + (uint8_t)u1, (uint8_t)(u1 >> 8), (uint8_t)(u1 >> 16), (uint8_t)(u1 >> 24), + (uint8_t)u0, (uint8_t)(u0 >> 8), (uint8_t)(u0 >> 16), (uint8_t)(u0 >> 24) + }; + cause = gcs_by_uuid128_srv_discovery(conn_id, uuid128); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +T_USER_CMD_PARSE_RESULT cmd_chardis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + + T_GAP_CAUSE cause = gcs_all_char_discovery(conn_id, start_handle, end_handle); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +T_USER_CMD_PARSE_RESULT cmd_charuuid(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->dw_param[3] == 0) + { + uint16_t uuid16 = p_parse_value->dw_param[4]; + T_GAP_CAUSE cause = gcs_by_uuid_char_discovery(conn_id, start_handle, end_handle, + uuid16); + } + else if (p_parse_value->dw_param[3] == 1) + { + uint32_t u0 = p_parse_value->dw_param[4]; + uint32_t u1 = p_parse_value->dw_param[5]; + uint32_t u2 = p_parse_value->dw_param[6]; + uint32_t u3 = p_parse_value->dw_param[7]; + uint8_t uuid128[16] = + { + (uint8_t)u3, (uint8_t)(u3 >> 8), (uint8_t)(u3 >> 16), (uint8_t)(u3 >> 24), + (uint8_t)u2, (uint8_t)(u2 >> 8), (uint8_t)(u2 >> 16), (uint8_t)(u2 >> 24), + (uint8_t)u1, (uint8_t)(u1 >> 8), (uint8_t)(u1 >> 16), (uint8_t)(u1 >> 24), + (uint8_t)u0, (uint8_t)(u0 >> 8), (uint8_t)(u0 >> 16), (uint8_t)(u0 >> 24) + }; + T_GAP_CAUSE cause = gcs_by_uuid128_char_discovery(conn_id, start_handle, + end_handle, + uuid128); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +T_USER_CMD_PARSE_RESULT cmd_charddis(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + + T_GAP_CAUSE cause = gcs_all_char_descriptor_discovery(conn_id, start_handle, + end_handle); + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +T_USER_CMD_PARSE_RESULT cmd_read(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t handle = p_parse_value->dw_param[1]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->param_count <= 2) + { + cause = gcs_attr_read(conn_id, handle); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} + +T_USER_CMD_PARSE_RESULT cmd_readu(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t conn_id = p_parse_value->dw_param[0]; + uint16_t start_handle = p_parse_value->dw_param[1]; + uint16_t end_handle = p_parse_value->dw_param[2]; + T_GAP_CAUSE cause = GAP_CAUSE_SUCCESS; + + if (p_parse_value->dw_param[3] == 0) + { + uint16_t uuid16 = p_parse_value->dw_param[4]; + cause = gcs_attr_read_using_uuid16(conn_id, start_handle, end_handle, uuid16); + } + else if (p_parse_value->dw_param[3] == 1) + { + uint32_t u0 = p_parse_value->dw_param[4]; + uint32_t u1 = p_parse_value->dw_param[5]; + uint32_t u2 = p_parse_value->dw_param[6]; + uint32_t u3 = p_parse_value->dw_param[7]; + uint8_t uuid128[16] = + { + (uint8_t)u3, (uint8_t)(u3 >> 8), (uint8_t)(u3 >> 16), (uint8_t)(u3 >> 24), + (uint8_t)u2, (uint8_t)(u2 >> 8), (uint8_t)(u2 >> 16), (uint8_t)(u2 >> 24), + (uint8_t)u1, (uint8_t)(u1 >> 8), (uint8_t)(u1 >> 16), (uint8_t)(u1 >> 24), + (uint8_t)u0, (uint8_t)(u0 >> 8), (uint8_t)(u0 >> 16), (uint8_t)(u0 >> 24) + }; + cause = gcs_attr_read_using_uuid128(conn_id, start_handle, end_handle, uuid128); + } + + return (T_USER_CMD_PARSE_RESULT)cause; +} +#endif + +T_USER_CMD_PARSE_RESULT cmd_ftltest(T_USER_CMD_PARSED_VALUE *p_parse_value) +{ + uint8_t data[80]; + uint8_t data_load[80]; + uint32_t ret; + memset(data, 0x34, 80); + ftl_load(data_load, 16, 80); + ret = ftl_save(data, 16, 80); + if(ret == 0) + { + ftl_load(data_load, 16, 80); + if(memcmp(data, data_load, 80) == 0) + { + return RESULT_SUCESS; + } + } + return RESULT_GAP_CAUSE_INVALID_PARAM; +} + +/*---------------------------------------------------- + * command table + * --------------------------------------------------*/ +const T_USER_CMD_TABLE_ENTRY user_cmd_table[] = +{ + /************************** Common cmd *************************************/ + { + "reset", + "reset\n\r", + "reset system\n\r", + cmd_reset + }, + { + "vendor", + "vendor\n\r", + "vendor cmd\n\r", + cmd_vendor + }, + { + "ftltest", + "ftltest\n\r", + "ftltest\n\r", + cmd_ftltest + }, + { + "reg", + "reg [test_case]\n\r", + "Init stack, reg test case\n\r", + cmd_reg + }, + { + "dlps", + "dlps [mode]\n\r", + "dlps\n\r", + cmd_dlps + }, + { + "tracelevel", + "tracelevel [0/1: off/on]\n\r", + "Set trace level\n\r", + cmd_tracelevel + }, + { + "setlocaltype", + "setlocaltype [type]\n\r", + "set local address type: 0-public, 1-random, 2-resolved or public 3- resolved or random\n\r", + cmd_setlocaltype + }, + { + "setstatic", + "setstatic [type]\n\r", + "set static address type: 0-, 1-\n\r", + cmd_setstatic + }, +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + { + "wrdefaultdatalen", + "wrdefaultdatalen [tx octests] [tx time]\n\r", + "Specify suggested data length\n\r", + cmd_writedefaultdatalen + }, +#endif + { + "rssiread", + "rssiread [conn_id]\n\r", + "Read the RSSI value\n\r", + cmd_rssiread + }, +#if F_BT_LE_READ_CHANN_MAP + { + "readchanmap", + "readchanmap [conn_id]\n\r", + "read channel map\n\r", + cmd_readchanmap + }, +#endif + { + "conupdreq", + "conupdreq [conn_id] [interval_min] [interval_max] [latency] [supervision_timeout]\n\r", + "LE connection param update request\r\n\ + sample: conupdreq 0 0x30 0x40 0 500\n\r", + cmd_conupdreq + }, + { + "showcon", + "showcon\n\r", + "Show all devices connecting status\n\r", + cmd_showcon + }, + { + "disc", + "disc [conn_id]\n\r", + "Disconnect to remote device\n\r", + cmd_disc + }, +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + { + "setdatalength", + "setdatalength [conn_id] [tx octests] [tx time]\n\r", + "set data length\n\r", + cmd_setdatalength + }, +#endif + { + "wl", + "wl [op] [conn_id]\n\r", + "modify remote BD to whitelist\n\r", + cmd_wl + }, + { + "wldev", + "wldev [op] [dev idx]\n\r", + "modify remote BD to whitelist\n\r", + cmd_wldev + }, + /**************************Auth Common cmd *************************************/ + { + "authmode", + "authmode [auth_flags] [io_cap] [sec_enable] [oob_enable]\n\r", + "Config authentication mode\r\n\ + [auth_flags]:authentication req bit field: bit0-(bonding), bit2-(MITM), bit3-(SC)\r\n\ + [io_cap]:set io Capabilities: 0-(display only), 1-(display yes/no), 2-(keyboard noly), 3-(no IO), 4-(keyboard display)\r\n\ + [sec_enable]:Start smp pairing procedure when connected: 0-(disable), 1-(enable)\r\n\ + [oob_enable]:Enable oob flag: 0-(disable), 1-(enable)\r\n\ + sample: authmode 0x5 2 1 0\n\r", + cmd_authmode + }, + { + "setkeydis", + "setkeydis [init] [resp]\n\r", + "set key distribute\n\r", + cmd_setkeydis + }, + { + "sauth", + "sauth [conn_id]\n\r", + "Send authentication request\n\r", + cmd_sauth + }, + { + "userconf", + "userconf [conn_id] [conf]\n\r", + "Send user confirmation when show GAP_MSG_LE_BOND_USER_CONFIRMATION\r\n\ + [conf]: 0-(Reject), 1-(Accept)\r\n\ + sample: userconf 0 1\n\r", + cmd_userconf + }, + { + "authkey", + "authkey [conn_id] [passkey]\n\r", + "Input passkey when show GAP_MSG_LE_BOND_PASSKEY_INPUT\r\n\ + [passkey]: 0 - 999999\r\n\ + sample: authkey 0 123456\n\r", + cmd_authkey + }, +#if F_BT_LE_SMP_OOB_SUPPORT + { + "oob", + "oob [conn_id] [oob0] [oob3] [oob7] [oob15]\n\r", + "input oob data\n\r", + cmd_oob + }, +#endif +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + { + "keypress", + "keypress [conn_id] [type]\n\r", + "keypress notification\n\r", + cmd_keypress + }, +#endif + { + "bondinfo", + "bondinfo\n\r", + "Get all Bonded devices information\n\r", + cmd_bondinfo + }, + { + "bondclear", + "bondclear\n\r", + "Clear all bonded devices information\n\r", + cmd_bondclear + }, + { + "seclevel", + "seclevel [conn_id]\n\r", + "Get security level\n\r", + cmd_seclevel + }, + /************************** Central only *************************************/ + { + "scan", + "scan [filter_policy] [filter_duplicate]\n\r", + "Start scan\r\n\ + [filter_policy]: 0-(any), 1-(whitelist), 2-(any RPA), 3-(whitelist RPA) \r\n\ + [filter_duplicate]: 0-(disable), 1-(enable) \n\r", + cmd_scan + }, + { + "stopscan", + "stopscan\n\r", + "Stop scan\n\r", + cmd_stopscan + }, + { + "showdev", + "showdev\n\r", + "Show scan dev list: filter simple ble service\n\r", + cmd_showdev + }, +#if F_BT_LE_GAP_CENTRAL_SUPPORT + { + "con", + "con [BD0] [BD1] [BD2] [BD3] [BD4] [BD5] [addr_type]\n\r", + "Connect to remote device: use address\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: remote device address\r\n\ + [addr_type]: 0-(public), 1-(random)\r\n\ + sample: con x11 x22 x33 x44 x55 x66 0 \n\r", + cmd_con + }, + { + "condev", + "condev [idx]\n\r", + "Connect to remote device: use showdev to show idx\r\n\ + [idx]: use cmd showdev to show idx before use this cmd\r\n\ + sample: condev 0\n\r", + cmd_condev + }, + { + "chanclassset", + "chanclassset [idx0] [idx1] [idx2] [idx3] [idx4]\n\r", + "Set Host Channel Classification\r\n\ + [idx0] [idx1] [idx2] [idx3] [idx4]: channel bit map\r\n\ + sample: chanclassset xff xff x3f xff x00\n\r", + cmd_chanclassset + }, +#endif + /************************** GATT client *************************************/ +#if F_BT_LE_GATT_CLIENT_SUPPORT + { + "srvdis", + "srvdis [conn_id]\n\r", + "Service discovery, discover all primary services\n\r", + cmd_srvdis + }, + /*GAPS client*/ + { + "gapdis", + "gapdis [conn_id]\n\r", + "Start discovery gap service\n\r", + cmd_gapdis + }, + { + "gapread", + "gapread [conn_id] [type]\n\r", + "Read GAP service characteristic value\r\n\ + [type]: 0-(read device name), 1-(read appearance)\r\n\ + simple: gapread 0 0\n\r", + cmd_gapread + }, + { + "simpdis", + "simpdis [conn_id]\n\r", + "Start discovery simple ble service\n\r", + cmd_simpdis + }, + { + "simpread", + "simpread [conn_id] [type] [pattern]\n\r", + "Read simple ble service characteristic and descriptor value\r\n\ + [type]: 0-(read v1), 1-(v3 cccd), 2-(v4 cccd)\r\n\ + [pattern]: 0-(read by handle), 1-(read by uuid)\r\n\ + sample: simpread 0 1 0 \n\r", + cmd_simpread + }, + { + "simpcccd", + "simpcccd [conn_id] [type] [enable]\n\r", + "Config simple ble service client characteristic configuration descriptor value\r\n\ + [type]: 0-(v3 notify), 1-(v4 indication) 2-(v8 notify and indication)\r\n\ + [enable](type!=2): 0-(disable), 1-(enable) \r\n\ + [enable](type==2): 0-(disable), 0x01-(notify), 0x10-(indicate), 0x11-(notify and indicate) \r\n\ + sample: simpcccd 0 1 1\n\r", + cmd_simpcccd + }, + { + "simpwrite", + "simpwrite [conn_id] [char] [value]\n\r", + "Write all related chars by user input\n\r", + cmd_simpwrite + }, + { + "simphdl", + "simphdl [conn_id]\n\r", + "List simple ble service handle cache\n\r", + cmd_simphdl + }, +#endif +#if F_BT_ANCS_CLIENT_SUPPORT + { + "ancsdis", + "ancsdis [conn_id]\n\r", + "Start discovery ancs service\n\r", + cmd_ancsdis + }, +#endif + /***************peripheral*******************/ + { + "startadv", + "startadv\n\r", + "start advertising without setting advertising parameters\n\r", + cmd_startadv + }, + { + "advdata", + "advdata [len] [value]\n\r", // len: 1-31 + "Modify advertising data\n\r", // value: 0x00, ff + cmd_advdata + }, + { + "stopadv", + "stopadv\n\r", + "Stop advertising\n\r", + cmd_stopadv + }, + { + "adv", + "adv [adv_interval] [filter_policy]\n\r", + "Start Undirected advertising\r\n\ + [adv_interval]: 0x0020 - 0x4000 (20ms - 10240ms, 0.625ms/step)\r\n\ + [filter_policy]: 0-(all), 1-(whitelist scan), 2-(whitelist conn), 3-(whitelist all)\r\n\ + sample: adv x40 0 \n\r", + cmd_adv + }, + { + "advld", + "advld [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r", + "Start lower duty directed advertising\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\ + sample: advld x11 x22 x33 x44 x55 x66\n\r", + cmd_advld + }, + { + "advhd", + "advhd [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]\n\r", + "Start high duty directed advertising\r\n\ + [BD0] [BD1] [BD2] [BD3] [BD4] [BD5]: peer address\r\n\ + sample: advhd x11 x22 x33 x44 x55 x66\n\r", + cmd_advhd + }, + { + "advscan", + "advscan\n\r", + "Start scannable undirected advertising\n\r", + cmd_advscan + }, + { + "advnonconn", + "advnonconn\n\r", + "Start non_connectable undirected advertising\n\r", + cmd_advnonconn + }, + { + "advwl", + "advwl\n\r", + "Start undirected advertising with white list\n\r", + cmd_advwl + }, +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + { + "readadvpwr", + "readadvpwr\n\r", + "Read adv channel tx power\n\r", + cmd_readadvpwr + }, +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + { + "latency", + "latency [conn_id] [on_off]\n\r", + "On off slave latency\r\n\ + [on_off]: 0-(turn on the latency), 1-(turn off the latency)\r\n\ + sample: latency 0 1\n\r", + cmd_latency + }, + { + "epassed", + "epassed [enable]\n\r", + "Update instant passed channel map\r\n\ + [enable]: 0 - (disable), 1-(enable)\r\n\ + sample: epassed 1\n\r", + cmd_epassed + }, +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + { + "vadv", + "vadv [enable] \n\r", + "Each adv channel with diff data\r\n\ + [enable]: 0-(disable), 1-(enable)\r\n\ + sample: vadv 1 \n\r", + cmd_vadv + }, + { + "vadvdata", + "vadvdata [type] [len] [value]\n\r", + "Set adv channel adv data and scan response data\r\n\ + [type]: 0-(adv 38 data), 1-(adv 39 data), 2-(scan response 38 data), 3-(scan response 39 data)\r\n\ + [len]: 0-31\r\n\ + [value]: adv data value\r\n\ + sample: vadvdata 1 5 5 \n\r", + cmd_vadvdata + }, +#endif + /********************************Profile Server*********************************/ + { + "srvchange", + "srvchange [conn_id] [start_handle] [end_handle] \n\r", + "Send service change indication\r\n\ + [start_handle]: 1 - 0xFFFF\r\n\ + [end_handle]: 1 - 0xFFFF\n\r", + cmd_srvchange + }, + { + "simpv3notify", + "simpv3notify [conn_id] [len] \n\r", + "Send V3 notification\r\n\ + [len]: 0 - (mtu-3)\n\r", + cmd_simpv3notify + }, + { + "simpv3dump", + "simpv3dump\n\r", + "Dump v3 result\n\r", + cmd_simpv3dump + }, + { + "simpv4ind", + "simpv4ind [conn_id] [len]\n\r", + "Send V4 indication\r\n\ + [len]: 0 - (mtu-3)\n\r", + cmd_simpv4ind + }, + { + "simpv8notify", + "simpv8notify [conn_id] [val]\n\r", + "Notify Characteristic V8 Notify value.\n\r", + cmd_simpv8notify + }, + { + "simpv8ind", + "simpv8ind [conn_id] [val]\n\r", + "Indicate Characteristic V8 Indicate value.\n\r", + cmd_simpv8ind + }, + { + "simpv7len", + "simpv7len [len]\n\r", + "Set V7 Characteristic value length.\n\r", + cmd_simpv7len + }, + { + "simpv2writeconf", + "simpv2writeconf [conn_id]\n\r", + "Write Response Characteristic V2 Write Request.\n\r", + cmd_simpv2writeconf + }, +#if F_BT_LE_5_0_SUPPORT + { + "setphy", + "setphy [conn_id] [phy]\n\r", + "set phy.\n\r", + cmd_setphy + }, +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + { + "escan", + "escan [0/1/2/3]\n\r", + "escan remote devices\n\r", + cmd_escan + }, + { + "stopescan", + "stopescan\n\r", + "stopescan remote device\n\r", + cmd_stopescan + }, +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT + { + "ueadv", + "ueadv [adv_handle] [flags]\n\r", + "Update extend advertising param\n\r", + cmd_ueadv + }, + { + "uedadv", + "uedadv [adv_handle] [flags]\n\r", + "Update extend directed advertising param\n\r", + cmd_uedadv + }, + { + "seadv", + "seadv [adv_handle] [duration] [max_num]\n\r", + "Set extended adv enable param\n\r", + cmd_seadv + }, + { + "eadv", + "eadv [adv_handle1] [adv_handle2] [adv_handle3] [adv_handle4]\n\r", + "Start extended adv\n\r", + cmd_eadv + }, + { + "stopeadv", + "stopeadv [adv_handle1] [adv_handle2] [adv_handle3] [adv_handle4]\n\r", + "Stop extended adv\n\r", + cmd_stopeadv + }, + { + "ceadv", + "ceadv\n\r", + "clear extended adv set\n\r", + cmd_ceadv + }, + { + "readv", + "readv [adv_handle]\n\r", + "remove extended adv set\n\r", + cmd_readv + }, +#endif +#endif +#if F_BT_LE_PRIVACY_SUPPORT + { + "advrel", + "advrel\n\r", + "Start undirected advertising with local type = resolved\n\r", + cmd_advrel + }, + { + "setrae", + "setrae [enable]\n\r", + "set addr resolution enable.\n\r", + cmd_setrae + }, + { + "readlra", + "readlra [conn_id]\n\r", + "read local resolvable address.\n\r", + cmd_readlra + }, + { + "readpra", + "readlra [conn_id]\n\r", + "read peer resolvable address..\n\r", + cmd_readpra + }, + { + "showrel", + "showrel\n\r", + "show resolved list.\n\r", + cmd_showrel + }, + { + "setprivacy", + "setprivacy [rel_idx] [0/1]\n\r", + "set privacy mode.\n\r", + cmd_setprivacy + }, + { + "wlrel", + "wlrel [op] [rel_idx]\n\r", + "whitelist\n\r", + cmd_wlrel + }, + { + "conrel", + "conrel [idx]\n\r", + "connect to remote device\n\r", + cmd_conrel + }, +#endif +#if F_BT_LE_4_1_CBC_SUPPORT + { + "lepsm", + "lepsm [psm] [action]\n\r", + "set le psm\n\r", + cmd_lepsm + }, + { + "lesec", + "lesec [psm] [active] [mode] [key_size]\n\r", + "set le psm security\n\r", + cmd_lesec + }, + { + "conle", + "conle [conn_id] [psm]\n\r", + "create credit based connection\n\r", + cmd_conle + }, + { + "discle", + "discle [cid]\n\r", + "disconnect credit based connection\n\r", + cmd_discle + }, + { + "ledata", + "ledata [cid] [num] [length]\n\r", + "send data through credit based connection\n\r", + cmd_ledata + }, +#endif +#if APP_HID_TEST + { + "key", + "key [conn_id][key]\n\r", + "Set key\n\r", + cmd_key + }, +#endif +#if F_BT_CONTROLLER_POWER_CONTROL + { + "poweron", + "poweron \n\r", + "Turn power on\n\r", + cmd_poweron + }, + { + "poweroff", + "poweroff \n\r", + "Turn power off\n\r", + cmd_poweroff + }, +#endif +#if APP_GENERAL_CLIENT_TEST + { + "indconf", + "indconf [conn_id]\n\r", + "Indication confimation\n\r", + cmd_indconf + }, + { + "write", + "write [conn_id] [type] [handle] [length] [value1] [...]\n\r", + "write to client\n\r\ + [type] 1 - write request, 2 - write command, 4 - signed write command\n\r", + cmd_write + }, + { + "gsrvdis", + "gsrvdis [conn_id]\n\r", + "discover all primary services\n\r", + cmd_gsrvdis + }, + { + "srvuuid", + "srvdis [conn_id] [type] [uuid]\n\r", + "discover services by uuid\n\r", + cmd_srvuuid + }, + { + "chardis", + "chardis [conn_id] [start handle] [end handle]\n\r", + "discover characterristic\n\r", + cmd_chardis + }, + { + "charuuid", + "charuuid [conn_id] [start handle] [end handle] [type] [uuid]\n\r", + "discover characterristic by uuid\n\r", + cmd_charuuid + }, + { + "charddis", + "charddis [conn_id] [start handle] [end handle]\n\r", + "discover characteristic descriptor\n\r", + cmd_charddis + }, + { + "read", + "read [conn_id] [handle]\n\r", + "read characteristic\n\r", + cmd_read + }, + { + "readu", + "readu [conn_id] [start handle] [end handle] [type] [uuid]\n\r", + "read characterristic by uuid\n\r", + cmd_readu + }, +#endif + { + "txpwrset", + "txpwrset [type] [tx gain]\n\r", + "Set the TX Power of BLE RF\n\r", + cmd_txpwrset + }, + { + "linkpwrset", + "linkpwrset [conn_id] [reset] [tx_pwr]\n\r", + "Set the link TX Power of BLE RF\n\r", + cmd_linkpwrset + }, + { + "oneshot", + "oneshot [guard_slot] [guard_usec] [wait_usec]\n\r", + "enable one shot adv\n\r", + cmd_oneshot + }, + /* MUST be at the end: */ + { + 0, + 0, + 0, + 0 + } +}; diff --git a/component/common/bluetooth/realtek/sdk/src/app/gap_test/user_cmd.h b/component/common/bluetooth/realtek/sdk/src/app/gap_test/user_cmd.h new file mode 100644 index 00000000..c1615aa2 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/gap_test/user_cmd.h @@ -0,0 +1,31 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file user_cmd.h +* @brief Define user command. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _USER_CMD_H_ +#define _USER_CMD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +extern const T_USER_CMD_TABLE_ENTRY user_cmd_table[]; +extern T_USER_CMD_IF user_cmd_if; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/ble_app_main.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/ble_app_main.c new file mode 100644 index 00000000..9976e4a5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/ble_app_main.c @@ -0,0 +1,61 @@ + +#include +#include +#include +#include +#include +#include +#include +#include "trace_uart.h" + +/* +#include +#include +#include + +#include +extern void ltp_TimerCallBack(void *xtimer); + + +void BtStack_Init_Gap(void) +{ + +#ifdef TEST_PROFILE + module_bredr_profile_Init_Gap(); +#endif + +} + +void Profile_Init(void) +{ + +#ifdef TEST_PROFILE + module_bredr_profile_Profile_Init(); +#endif + +} +*/ +/** + * @brief Config bt stack related feature + * + * NOTE: This function shall be called before @ref bte_init is invoked. + * @return void + */ +void bt_stack_config_init(void) +{ + gap_config_max_le_link_num(APP_MAX_LINKS); +} + +void ble_app_main(void) +{ + bt_trace_init(); + bt_stack_config_init(); + bte_init(); + hrp_init(); + hrp_task_init(); + + return; +} + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp.h new file mode 100644 index 00000000..5861faa0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp.h @@ -0,0 +1,289 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file aci_if.h +* @brief some macro/struct/functions declaration of aci interface +* @details none. +* @author tifnan +* @date 2014-10-17 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _HRP_H_ +#define _HRP_H_ + +/**************************************************************************** + * includes + ****************************************************************************/ + +#include +#include +#include + +#define HRP_SUB_TYPE 1 /* 0:sdk-v0,acut,bb3-dev; 1:sdk-v1,bcut */ +#define ACI_EN 0 + +#ifdef TEST_PROFILE +/* select which profiles to be tested */ + +#define LTP_TEST_APP 1 +#if LTP_TEST_APP +#define LTP_TEST_AVRCP 1 // 1 -- built success +#define LTP_TEST_A2DP 1 +#define LTP_TEST_HFP 1 +#define LTP_TEST_KEY_MGR 1 +#define LTP_TEST_GAP 1 +#define LTP_TEST_SPP 1 + +#define LE_SUPPORT 1 + +#else +#define LTP_TEST_AVRCP 0 // 1 -- built success +#define LTP_TEST_A2DP 0 +#define LTP_TEST_HFP 0 +#define LTP_TEST_KEY_MGR 0 +#define LTP_TEST_GAP 0 +#define LTP_TEST_SPP 0 +#endif +#endif + +/* buffer size */ +#define RX_BUFFER_SIZE 0x800 //must be 2^n,because {x&(RX_BUFFER_SIZE-1)} +#define RX_DISABLE_COUNT 0x200 +#define TX_BUFFER_SIZE1 0x400 //lorna change 0x200 --> 0x400 8K +#define RX_HANDLE_BUFFER_SIZE 0x400 + +#define BTLTP_DEFAULT_COPMSK 0x80 /* enable CRC */ + +#define BTHRP_ACTION_POOL_SIZE (2) /* enough */ +#define BT_GATT_SERVER_MAX_SERVICES_COUNT 8 +#define BTIF_MDL_COUNT 4 + +#define LTP_ACT_INFO_FLAG_ACT_INFO 0x01 +#define LTP_ACT_INFO_FLAG_GAP_REG 0x02 + +#ifdef TEST_PROFILE +#define LTP_ACT_INFO_FLAG_ALL (LTP_ACT_INFO_FLAG_ACT_INFO) +#else +#define LTP_ACT_INFO_FLAG_ALL (LTP_ACT_INFO_FLAG_ACT_INFO|LTP_ACT_INFO_FLAG_GAP_REG) +#endif + +#define BTIF_L2C_COUNT 6 +#define BT_MAX_MTU_SIZE 1021 //lorna change 335-->672-->1021 +#define BTLTP_US_BUFFER_SIZE (BT_MAX_MTU_SIZE + 32) +#define BTLTP_MAX_MSG_SIZE 1021 //lornachange 361-->672-->1021 + +#define BTHRP_QUEUE_ELEMENT_COUNT 10 + +#define LTP_TRACE_NONE 0 +#define LTP_TRACE_ERROR 1 +#define LTP_TRACE_INFO 2 +#define LTP_TRACE_DEBUG 3 +#define LTP_TRACE_ALL 4 + +/******************************** the define of events ltp used **********************************/ +#define LTP_EVENT_BTIF_MESSAGE 0x10 /* BTIF message */ +#define LTP_EVENT_UART_RX 0x21 /* data available */ +#define LTP_EVENT_UART_TX 0x12 /* transmit request */ +#define LTP_EVENT_UART_TX_COMPLETED 0x13 /* transmit completed */ +#define LTP_EVENT_PROFILE_MESSAGE 0x14 /* spp tx innner data event */ +#define LTP_EVENT_BTIF_L2C_DATA_RSP 0x15 /* l2cap tx innner data event */ +#define LTP_EVENT_MPA_L2C_DATA_RSP 0x16 /* l2cap tx innner data event */ + +/****************************************************************************/ +/* state */ +/****************************************************************************/ +typedef enum _TBTHrpState +{ + btltpStateInit, + btltpStateRegistering, + btltpStateIdle, + btltpStateReleasing, + btltpStateCount +} T_BT_HRP_STATE; + +/****************************************************************************/ +/* Tx Buffer callback handling */ +/****************************************************************************/ + +typedef enum +{ + btltpActionNotUsed, + btltpActionExit, + btltpActionReset, + btltpActionSendDataConf, + btltpActionSendDIDDeviceConf, + btltpActionSendSDPEndpointConf, + btltpActionReleaseBuffer +} TBTLtpActionCommand; + +typedef enum +{ + LTPProfileSppTxData +} TProfileEvent; + +typedef struct +{ + void *pBuffer; + uint32_t p_srv_handle; +} TBTLtpServiceAction; + +typedef union +{ + uint8_t *pReleaseBuffer; + uint16_t MDL_ID; + TBTLtpServiceAction serviceAction; +} TBTLtpActionData; + +typedef struct +{ + TBTLtpActionCommand Action; + TBTLtpActionData p; +} T_BT_HRP_ACTION; +typedef T_BT_HRP_ACTION *P_BT_HRP_ACTION; + +#define API_TYPE_GATT_SEND_VENDOR_HCI_CMD 3 +typedef struct _TApiBufVendorCmd +{ + uint16_t op; + uint8_t len; + uint8_t *para; +} TApiBufVendorCmd; + +typedef struct _TApiBufUserDefined +{ + uint16_t Type; + union + { + TApiBufVendorCmd ApiBufVendorCmd; + } p; +} TApiBufUserDefined; + + +/* Ltp data struct */ +typedef struct _TData +{ + uint8_t *pBuffer; + uint32_t Length; +} T_HRP_DATA; + + +/** @brief tcb to manage tx buffer */ +typedef struct +{ + uint16_t + tx_blk_idx; /* sending block index [0 -- TX_BUFFER_SIZE_MASK](block is sending now ) */ + uint16_t tx_free_blk_idx; /* free tx block index [0----TX_BUFFER_SIZE_MASK] */ + uint16_t tx_un_used_size; /* size of block which is discarded */ + uint16_t free_size; /* bytes can be used */ +} TxMemTCB, *PTxMemTCB; + +/** @brief aci control struct */ +typedef struct _ACI_TCB +{ + T_HRP_DATA TxData; + void *Handle; /* task handle */ + void *UarthandleEvent; /* task queue */ + void *QueueHandleEvent; /* task queue */ + void *QueueHandleMessage; /* message queue */ + void *QueueHandleTxData; /* Tx queue */ + void *QueueHandleRxData; /* Rx queue */ + void *QueueHandleTxRel; /* tx buffer release queue */ + uint32_t RxDataIndication; /* pending responses */ + uint32_t RxDataLength; + uint32_t RxOffset; + uint16_t RxReadIndex; + uint16_t RxWriteIndex; + uint8_t *p_rx_buf; /* pointer to the rx buffer allocated dynamically */ + uint8_t *p_tx_buf; /* pointer to the tx buffer allocated dynamically */ + uint8_t *p_rx_handle_buf; /* buffer address, handle uart rx data */ + uint8_t *P_RxBuffer; /* for rx */ + TxMemTCB tx_mem_tcb; /* manage tx bufer */ + + bool RxDisabled; + bool TxDisabled; +} ACI_TCB, *P_ACI_TCB; + +typedef struct _TBTHrp +{ + uint8_t *p_send_buffer; /* for saving the address of tx buffer */ + HRP_QUEUE_T FreeElementQueue; + + T_BT_HRP_STATE State; + +#if 0 + T_BT_HRP_MDL_CONTEXT MDLContextPool[BTIF_MDL_COUNT]; + + T_BT_HRP_L2C_CONTEXT L2cContextPool[BTIF_L2C_COUNT]; + uint16_t current_trx_cid; /* added for br/edr l2cap throughput test*/ + uint16_t current_trx_data_len; /* added for br/edr l2cap throughput test*/ +#endif + + void *QueueHandleProfileMessage; + + /* Buffer callback Action Handling */ + T_BT_HRP_ACTION ActionPool[BTHRP_ACTION_POOL_SIZE]; + P_BT_HRP_ACTION pBufferAction; + /* LTP re-assemble */ + uint8_t *pMsgBuffer; + T_HRP_LIB HRPLib; + T_HRP_ELEMENT ElementPool[BTHRP_QUEUE_ELEMENT_COUNT]; + /* COM interface */ + uint8_t ActInfoFlags; + uint8_t ownBDAddress[6]; + + uint8_t service_register_idx; + // TGattServiceTable gattServiceTable[BT_GATT_SERVER_MAX_SERVICES_COUNT]; //use for ACI + void *gattServiceHandle[BT_GATT_SERVER_MAX_SERVICES_COUNT];//use for LTP + + P_ACI_TCB p_aci_tcb; + uint16_t le_ds_pool_id; + uint16_t le_ds_data_offset; + uint8_t le_ds_credits; +} T_BT_HRP; +typedef T_BT_HRP *P_BT_HRP; + +typedef struct _TAciConfig +{ + uint8_t ltp_interface : 2; + uint8_t ltp_wake_up_pin_en : 1; + uint8_t ltp_trace_level: 3; + uint8_t reserved: 2; + + uint8_t uart_flow_control_en: 1; + uint8_t uart_word_len: 1; + uint8_t uart_parity: 2; + uint8_t reserved2: 4; + + /* ltp uart pin configuration */ + uint8_t uart_tx_pin_index; + uint8_t uart_rx_pin_index; + uint8_t uart_cts_pin_index; + uint8_t uart_rts_pin_index; + uint8_t gpio_h_pin_index; + uint8_t gpio_b_pin_index; + + uint32_t uart_baudrate; + + /* ltp spi pin configuration */ + uint8_t spi_mosi_pin_index; + uint8_t spi_miso_pin_index; + uint8_t spi_cs_pin_index; + uint8_t spi_clk_pin_index; + uint8_t spi_int_pin_index; /* used to notify master to read data drom bee */ + + uint8_t reserved3[7]; + +} TAciConfig; +typedef TAciConfig *PAciConfig; +extern PAciConfig P_AciConfig; +extern P_BT_HRP P_BtHrp; + +/* hrp_application.c */ +extern void hrp_buffer_release(void *pBuffer); +extern void hrp_write(uint8_t *p_buf, uint32_t buf_len); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_app_flags.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_app_flags.h new file mode 100644 index 00000000..9eed223e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_app_flags.h @@ -0,0 +1,22 @@ +#ifndef _HRP_APP_FLAGS_H_ +#define _HRP_APP_FLAGS_H_ + +#include "bt_flags.h" + +/** @brief Config APP LE link number */ +#define APP_MAX_LINKS 3 + +#define F_BT_DLPS_EN 0 +#define F_BT_LE_BTIF_SUPPORT (F_BT_LE_SUPPORT && 1) + +#define F_BT_CONFIG_INTERNAL_API 1 + +//add for compile error +#define B_ADDR_LEN 6 +#define REMOTE_FEATURES_LEN 8 + +#define F_BT_PATCH_CHANGE_BOND_INFO 1 +#define F_BT_PATCH_SRV_CHANGE_IND 1 +#define F_BT_PATCH_ADD_PRIVACY_API 1 + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_application.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_application.c new file mode 100644 index 00000000..1dbe7d7e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_application.c @@ -0,0 +1,552 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file btltp_FreeRTOS.c +* @brief aci iterface implementation. +* @details none. +* @author Tifnan +* @date 2014-10-17 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "wdt_reset.h" +#include +#include +#include +#include +#include "gap.h" + + + +/* task */ +#define LTP_PRIORITY (0 + 2) /* Task priorities. tskIDLE_PRIORITY + 2*/ +#define LTP_TASK_STACK_SIZE 0x800 +#define TX_TASK_STACK_SIZE 0x200 + +void *hEventQueueHandle; +void *hrp_hTimerQueueHandle; +void *hIoQueueHandle; + +P_BT_HRP P_BtHrp = NULL; + +TAciConfig AciConfig; +PAciConfig P_AciConfig = &AciConfig; + +T_HRP_STATUS system_status = HRP_STATUS_RESET; +HRP_MODULE_ID active_module = HRP_MODULE_RESERVED; + +extern uint8_t btif_get_up_data_len(T_BTIF_UP_MSG *p_msg); + +void *LTPTaskHandle = NULL; +void *LTPTxAssistHandle = NULL; +void hrp_task(void *pParameters); + +/** + * @brief send event to ltp task. + * + * @param pEvent, pointer to the event to be sent. + * @return send result. + * @retval true--send successfully. + * false-- queue is full. +*/ +bool hrp_send_event(const unsigned char *pEvent) +{ + bool ReturnValue; + + ReturnValue = os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleEvent, (void *)pEvent, 0); + return (ReturnValue); +} + +/** + * @brief callback function, upper stack will call it to send message to ltp. + * + * @param pMsg --message pointer from upper stack. + * @return none. + * @retal void +*/ +/* //move to individual module +void hrp_btif_callback(T_BTIF_UP_MSG *pMsg) +{ + unsigned char Event = LTP_EVENT_BTIF_MESSAGE; + + if (os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleMessage, &pMsg, 0) == false) + { + btif_buffer_put(pMsg); + } + else + { + hrp_send_event(&Event); + } +} +*/ + +/** + * @brief call this fucntion will start to send data through ltp. + * @param p_buf pointer to the buffer start address. + * @param buf_len the length of the buffer. + * @return none. + * @retal void. +*/ +void hrp_write(uint8_t *p_buf, uint32_t buf_len) +{ + T_HRP_DATA tx_data; + unsigned char ltpEvent = LTP_EVENT_UART_TX; + tx_data.pBuffer = p_buf; + tx_data.Length = buf_len; + + //APP_PRINT_INFO2("hrp_write: value_size %d, value %b", + //tx_data.Length, TRACE_BINARY(tx_data.Length, tx_data.pBuffer)); + if (os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleTxData, &tx_data, 0xffffffff) == false) + { + APP_PRINT_ERROR0("hrp_write: No queue"); + } + else + { + hrp_send_event(<pEvent); + } + + return; +} + + +/** + * @brief release ltp buffer when ltp command has executed completely. + * + * @param p_buf the buffer start address to release, not used now!! + * @return none. + * @retal void. +*/ +void hrp_buffer_release(void *p_buf) +{ + T_HRP_DATA RxData; + + if (os_msg_recv(P_BtHrp->p_aci_tcb->QueueHandleRxData, &RxData, 0) == true) + { + if (RxData.pBuffer == &P_BtHrp->p_aci_tcb->p_rx_buf[P_BtHrp->p_aci_tcb->RxReadIndex]) + { + uint32_t RxDataLength; + uint32_t s; + + s = os_lock(); + P_BtHrp->p_aci_tcb->RxDataLength -= RxData.Length; + RxDataLength = P_BtHrp->p_aci_tcb->RxDataLength; + os_unlock(s); + + P_BtHrp->p_aci_tcb->RxReadIndex += RxData.Length; + P_BtHrp->p_aci_tcb->RxReadIndex &= (RX_BUFFER_SIZE - 1); + + if (P_BtHrp->p_aci_tcb->RxDataIndication) /* waiting for response */ + { + P_BtHrp->p_aci_tcb->RxDataIndication -= RxData.Length; + } + + if (P_BtHrp->p_aci_tcb->RxDataIndication == 0 && /* no response pending and */ + RxDataLength != 0) /* still data available */ + { + uint8_t event = LTP_EVENT_UART_RX; + if (false == hrp_send_event(&event)) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("hrp_send_event fail"); + } + } + } + + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("hrp_buffer_release: Wrong buffer"); + } + } + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_INFO) + { + APP_PRINT_INFO0("hrp_buffer_release: No RxData"); + } + } + + return; +} + +void aci_config_default(void) +{ + P_AciConfig->ltp_trace_level = LTP_TRACE_ALL; +} + +/** + * @brief init ltp module, call this function before calling other ltp functions . + * + * @param none. + * @return the init result. + * @retal 0 -- init ltp failed. + 1 -- init ltp successfully. +*/ + +// 1. init uart +// 2. init trace +// 3. init hrp related struction +// all stack related init please move to individual modules , +// for example when the state is idle and received the first command + +uint8_t hrp_init(void) +{ +#if LTP_TEST_LOG_CLOSE + for (uint8_t i = 0; i < MODULE_NUM; i++) + { + log_module_trace_set((T_MODULE_ID)i, LEVEL_TRACE, false); + log_module_trace_set((T_MODULE_ID)i, LEVEL_INFO, false); + } + log_module_trace_set(MODULE_SNOOP, LEVEL_INFO, false); + log_module_trace_set(MODULE_SNOOP, LEVEL_TRACE, false); + log_module_trace_set(MODULE_SNOOP, LEVEL_ERROR, false); + log_module_trace_set(MODULE_SNOOP, LEVEL_WARN, false); +#endif + + aci_config_default(); +// APP_PRINT_TRACE2("memory before alloc DATA ON:%d DATA OFF:%d", +// os_mem_peek(RAM_TYPE_DATA_ON), os_mem_peek(RAM_TYPE_DATA_ON)); + APP_PRINT_TRACE2("memory before alloc DATA ON:%d DATA OFF:%d", + os_mem_peek(RAM_TYPE_DATA_ON), os_mem_peek(RAM_TYPE_DATA_ON)); + + P_BtHrp = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(T_BT_HRP));//&BtLtp; + P_BtHrp->p_aci_tcb = os_mem_zalloc(RAM_TYPE_DATA_ON, sizeof(ACI_TCB));// & AciTcb; + + P_BtHrp->p_aci_tcb->p_rx_buf = os_mem_zalloc(RAM_TYPE_DATA_ON, RX_BUFFER_SIZE); + P_BtHrp->p_aci_tcb->p_tx_buf = os_mem_zalloc(RAM_TYPE_DATA_ON, TX_BUFFER_SIZE1); + P_BtHrp->p_aci_tcb->p_rx_handle_buf = os_mem_zalloc(RAM_TYPE_DATA_ON, RX_HANDLE_BUFFER_SIZE); + + APP_PRINT_TRACE2("memory after alloc DATA ON:%d DATA OFF:%d", + os_mem_peek(RAM_TYPE_DATA_ON), os_mem_peek(RAM_TYPE_DATA_ON)); + + /* allocate failed */ + if (NULL == P_BtHrp + || NULL == P_BtHrp->p_aci_tcb + || NULL == P_BtHrp->p_aci_tcb->p_rx_buf + || NULL == P_BtHrp->p_aci_tcb->p_tx_buf + || NULL == P_BtHrp->p_aci_tcb->p_rx_handle_buf) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("Ltp ram allocated failed!"); + } + + return 0; + } + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_INFO) + { + APP_PRINT_INFO0("Ltp ram allocated successfully!"); + } + + memset(&(P_BtHrp->p_aci_tcb->tx_mem_tcb), 0, sizeof(TxMemTCB)); + P_BtHrp->p_aci_tcb->tx_mem_tcb.free_size = TX_BUFFER_SIZE1; + + /* tasks and queues */ + P_BtHrp->p_aci_tcb->Handle = LTPTaskHandle; + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + os_msg_queue_create(&(P_BtHrp->p_aci_tcb->QueueHandleEvent), MAX_NUMBER_OF_RX_EVENT, + sizeof(unsigned char)); + os_msg_queue_create(&(P_BtHrp->p_aci_tcb->QueueHandleTxData), MAX_NUMBER_OF_TX_DATA, + sizeof(T_HRP_DATA)); + os_msg_queue_create(&(P_BtHrp->p_aci_tcb->QueueHandleRxData), MAX_NUMBER_OF_RX_DATA, + sizeof(T_HRP_DATA)); + os_msg_queue_create(&(P_BtHrp->p_aci_tcb->QueueHandleTxRel), MAX_NUMBER_OF_TX_REL, + sizeof(T_HRP_DATA)); /* tx release */ + os_msg_queue_create(&(P_BtHrp->p_aci_tcb->QueueHandleMessage), MAX_NUMBER_OF_MESSAGE, + sizeof(T_BTIF_UP_MSG *)); + + os_msg_queue_create(&hIoQueueHandle, BLT_MAX_NUMBER_OF_IO_EVENT, sizeof(T_IO_MSG)); + + os_msg_queue_create(&(P_BtHrp->QueueHandleProfileMessage), MAX_NUMBER_OF_PROFILE_MSG, + sizeof(TProfileEvent)); + + os_sem_create(&(P_BtHrp->p_aci_tcb->UarthandleEvent), 1, 1); + +//move to individual modle when received reset command + /* le_key_init(); + + legacy_key_init(); + */ + + return 1; +} + + +/** + * @brief Callback function should be register to upper stack to send message to application. + * @param[in] pMsg message sent from upper stack. + * @retval None + */ +/* +void aci_btif_callback(T_BTIF_UP_MSG *pMsg) +{ + unsigned char event = LTP_EVENT_BTIF_MESSAGE; + + if (os_msg_send(hMessageQueueHandle, &pMsg, 0) == false) + { + btif_buffer_put(pMsg); + } + else if (os_msg_send(hEventQueueHandle, &event, 0) == false) + { + + } +} +*/ +uint8_t hrp_task_init(void) +{ + uint8_t ret = false; + ret = os_task_create(<PTaskHandle, "BTLTP", hrp_task, NULL, LTP_TASK_STACK_SIZE, LTP_PRIORITY); + + if (ret == false) + { + APP_PRINT_ERROR0("BTlTP task create fail: "); + } +#ifndef PLATFORM_STO + ret = os_task_create(<PTxAssistHandle, "TxAssist", TxAssistTask, NULL, TX_TASK_STACK_SIZE, + LTP_PRIORITY - 1); + + if (ret == false) + { + APP_PRINT_ERROR0("BTlTP task create fail: "); + } +#endif + + return 1; +} + +/** + * @brief ltp task implementation . + * + * @param pParameters --task parameters, no used in ltp task. + * @return none. + * @retal void +*/ +void hrp_task(void *p_parameters) +{ + int loop; + char event; + + /*step1: init uart or spi */ + ltpPeripheralInit(); + P_BtHrp->State = btltpStateInit; + + for (loop = 0; loop < BTHRP_QUEUE_ELEMENT_COUNT; loop++) + { + hrp_queue_in(&P_BtHrp->FreeElementQueue, &P_BtHrp->ElementPool[loop]); + } + + for (loop = 0; loop < BTHRP_ACTION_POOL_SIZE; loop++) + { + P_BtHrp->ActionPool[loop].Action = btltpActionNotUsed; + } + P_BtHrp->pBufferAction = NULL; /* no action pending */ + hrp_lib_initialize(&P_BtHrp->HRPLib, + (HRP_TGT_APPHANDLE)P_BtHrp, + 0, + BTLTP_MAX_MSG_SIZE, + 0 + ); + + /*step2: regist callback to stack*/ + /* //move to individual modules + #ifdef TEST_PROFILE + gap_start_bt_stack(aci_btif_callback); + #else + btif_register_req(aci_gap_btif_callback); + #endif + */ + P_BtHrp->State = btltpStateIdle; /* not use !!*/ + + APP_PRINT_TRACE0("ltp_task start "); + + /*step3: process events*/ + while (true) + { + if (os_msg_recv(P_BtHrp->p_aci_tcb->QueueHandleEvent, &event, 0xFFFFFFFF) == true) + { + switch (event) + { + case LTP_EVENT_UART_RX: /* RxData available */ + { + uint32_t RxDataLength; + uint16_t RxReadIndex; + uint32_t s; + + s = os_lock(); + /* skip data filed in handling */ + RxDataLength = P_BtHrp->p_aci_tcb->RxDataLength - P_BtHrp->p_aci_tcb->RxDataIndication; + os_unlock(s); + RxReadIndex = P_BtHrp->p_aci_tcb->RxReadIndex + P_BtHrp->p_aci_tcb->RxDataIndication; + RxReadIndex &= (RX_BUFFER_SIZE - 1); + + while (RxDataLength) + { + T_HRP_DATA RxData; + + /* exceed rx buffer tail */ + if ((RxReadIndex + RxDataLength) > RX_BUFFER_SIZE) + { + RxData.Length = RX_BUFFER_SIZE - RxReadIndex; + } + else + { + RxData.Length = RxDataLength; + } + RxData.pBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[RxReadIndex]; + + if (os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleRxData, &RxData, 0) == true) + { + P_BtHrp->p_aci_tcb->RxDataIndication += RxData.Length; + /* hrp_lib_handle_receive_data return when all data in RxData has been copied */ + if (!hrp_lib_handle_receive_data(&P_BtHrp->HRPLib, RxData.pBuffer, RxData.Length, 0)) + { + hrp_buffer_release(RxData.pBuffer); + } + + RxDataLength -= RxData.Length; + RxReadIndex += RxData.Length; + RxReadIndex &= (RX_BUFFER_SIZE - 1); + } + else + { + break; + } + } + break; + } + + case LTP_EVENT_UART_TX: /* transmit data */ + ltpStartTransmit(); + break; + + case LTP_EVENT_UART_TX_COMPLETED: /* transmit completed */ + { + T_HRP_DATA data; + + if (os_msg_recv(P_BtHrp->p_aci_tcb->QueueHandleTxRel, &data, 0) == true) + { + P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx += data.Length; + P_BtHrp->p_aci_tcb->tx_mem_tcb.free_size += data.Length; + + if (P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx > TX_BUFFER_SIZE1) + { + P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx = data.Length; + P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size = 0; + } + else if (P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx == TX_BUFFER_SIZE1) + { + P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx = 0; + P_BtHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size = 0; + } + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_INFO) + { + APP_PRINT_ERROR0("QueueHandleTxRel recieve fail: "); + } + } + + if (P_BtHrp->pBufferAction) + { + if (P_BtHrp->pBufferAction->Action >= btltpActionReset && + P_BtHrp->pBufferAction->Action < btltpActionReleaseBuffer) + { + void *Handle = (void *)P_BtHrp->pBufferAction; + bt_hrp_buffer_callback(Handle); + P_BtHrp->pBufferAction->Action = btltpActionNotUsed; + P_BtHrp->pBufferAction = NULL; + } + } + + ltpStartTransmit(); + break; + } + + case LTP_EVENT_BTIF_MESSAGE: /* BTIF */ + { + T_BTIF_UP_MSG *pMsg; + + while (os_msg_recv(P_BtHrp->p_aci_tcb->QueueHandleMessage, &pMsg, 0) == true) + { +#if F_BT_LE_BTIF_SUPPORT + hrp_btif_handle_msg(pMsg); +#endif + } + break; + } +#ifdef TEST_PROFILE + case LTP_EVENT_PROFILE_MESSAGE: /* spp tx innner data event */ + { + TProfileEvent profile_event; + while (os_msg_recv(P_BtHrp->QueueHandleProfileMessage, &profile_event, 0) == true) + { + profiles_handle_profile_message(profile_event); + } + break; + } +#endif + case EVENT_GAP_MSG: + case EVENT_GAP_TIMER: + gap_handle_msg(event); + break; + case EVENT_IO_TO_APP: + { + T_IO_MSG io_msg; + if (os_msg_recv(hIoQueueHandle, &io_msg, 0) == true) + { + hrp_gap_le_handle_io_msg(io_msg); + } + } + break; + + default: + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR1("hrp_task: Unknown event (%d)", event); + } + break; + } + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("hrp_task: os_msg_recv fail"); + } + } + } +} + + + +void hrp_system_reset() +{ + APP_PRINT_INFO1("system_status= %d", system_status); + if (system_status == HRP_STATUS_RESET) + { + return; + } + else + { + APP_PRINT_INFO0("HRP: reset (wait for WD to kick in)"); + + /* wait for last char of ResetRsp (buffercallback is executed on txempty, NOT on txcomplete) */ + os_delay(20); /* 20 ms delay */ + wdt_reset(); + } +} diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_application.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_application.h new file mode 100644 index 00000000..b15212a5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_application.h @@ -0,0 +1,46 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file aci_service_handle.h +* @brief low power handle when using ACI. +* @details none. +* @author tifnan +* @date 2014-11-19 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _LTPLIB_APPLICATION_H_ +#define _LTPLIB_APPLICATION_H_ +#include + +#define MAX_NUMBER_OF_RX_EVENT 0x40 +#define MAX_NUMBER_OF_MESSAGE 0x20 +#define MAX_NUMBER_OF_TX_DATA 12 +#define MAX_NUMBER_OF_TX_REL MAX_NUMBER_OF_TX_DATA +#define MAX_NUMBER_OF_RX_DATA 12 +#define MAX_NUMBER_OF_GAP_TIMER 0x10 +#define BLT_MAX_NUMBER_OF_RX_EVENT 0x20 +#define BLT_MAX_NUMBER_OF_IO_EVENT 0x20 +#define MAX_NUMBER_OF_PROFILE_MSG 0x10 + +typedef enum +{ + HRP_STATUS_IDLE = 0, + HRP_STATUS_RESET = 1, + HRP_STATUS_ACTIVE = 2, +} T_HRP_STATUS; + + +uint8_t hrp_init(void); +uint8_t hrp_task_init(void); +void hrp_system_reset(void); +void hrp_timer_cb(void *xtimer); + +extern T_HRP_STATUS system_status; +extern HRP_MODULE_ID active_module; +extern P_BT_HRP P_BtHrp; +bool hrp_send_event(const unsigned char *pEvent); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_module_id.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_module_id.h new file mode 100644 index 00000000..804db690 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_module_id.h @@ -0,0 +1,47 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file aci_service_handle.h +* @brief low power handle when using ACI. +* @details none. +* @author tifnan +* @date 2014-11-19 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _LTPLIB_MODULE_ID_H_ +#define _LTPLIB_MODULE_ID_H_ + +typedef enum _HRP_MODULE_ID +{ + HRP_MODULE_RESERVED = 0, + HRP_MODULE_LOWER_STACK = 1, + HRP_MODULE_UPPER_STACK = 2, + HRP_MODULE_PROFILE = 3, + HRP_MODULE_RESERVED1, + + HRP_MODULE_AUDIO = 16, + HRP_MODULE_BLE_AUTO_TEST = 17, + + +} HRP_MODULE_ID; + +/************************************************/ +typedef enum +{ + HRP_BTIF_CMD_GROUP_STACK = 0, + HRP_BTIF_CMD_GROUP_SYSTEM = 1, +} HRP_BTIF_CMD_GROUP; + + + +/************************************************/ + + + + + + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_utils.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_utils.c new file mode 100644 index 00000000..9b38a88e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_utils.c @@ -0,0 +1,998 @@ +#include +#include +#include "trace_app.h" +#include +#include +#include +#include +#include +#include +#include "wdt_reset.h" + +#define LTP_SOURCE_FILE_ID 0x83 + +bool LTPLibHandleUnkownCommand(P_HRP_LIB pLTPLib, uint8_t cmd); + + +/*--------------------------------------------------------------------------*/ +/* FCS lookup table. */ +/* generator polynomial: x**8 + x**2 + x + 1 */ +/* -------------------------------------------------------------------------*/ +static const uint8_t crc8EtsTable[256] = +{ + 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, + 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B, + 0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, + 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67, + 0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, + 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43, + 0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, + 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F, + 0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, + 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B, + 0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, + 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17, + 0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, + 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33, + 0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, + 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F, + 0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, + 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B, + 0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, + 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87, + 0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, + 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3, + 0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, + 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF, + 0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, + 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB, + 0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, + 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7, + 0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, + 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3, + 0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, + 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF +}; +static const uint16_t crc16EtsTable[256] = +{ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; + +P_BT_HRP_ACTION BTLTPAllocateAction(P_BT_HRP pBTLtp) +{ + uint16_t loop; + + for (loop = 0; loop < BTHRP_ACTION_POOL_SIZE; loop++) + { + if (pBTLtp->ActionPool[loop].Action == btltpActionNotUsed) + { + return &pBTLtp->ActionPool[loop]; + } + } + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("LTP: out of action queue elements"); + } + + return NULL; +} + +extern P_BT_HRP P_BtHrp; + + +void bt_hrp_buffer_callback(void *Handle) +{ + P_BT_HRP_ACTION pAction = (P_BT_HRP_ACTION)Handle; + TBTLtpActionCommand thisAction = pAction->Action; + + pAction->Action = btltpActionNotUsed; + + switch (thisAction) + { + case btltpActionReset: /*---------------------------------------------*/ + + APP_PRINT_INFO0("LTP: reset (wait for WD to kick in)"); + /* wait for last char of ResetRsp (buffercallback is executed on txempty, NOT on txcomplete) */ + os_delay(20); /* 20 ms delay */ + wdt_reset(); + break; +#if 0 + case btltpActionSendDataConf: /*--------------------------------------*/ + { + PBTLtpMDLContext pMDLContext = BTLTPFindMDLContext(P_BtHrp, pAction->p.MDL_ID); //&BtLtp + //bool ret; + + if (pMDLContext != NULL) + { + pMDLContext->pendingDataConfs++; + while (pMDLContext->pendingDataConfs > 0) + { +#if 0 + ret = btif_DataConf(//NULL, + //tBTLtp.BTIFHandle, + pAction->p.MDL_ID, + BTIF_CAUSE_SUCCESS + ); + + /* if msg fails, keep number of failed dataConfs and retry later */ + if (ret == false) + { + DBG_BUFFER(MODULE_LTP, LEVEL_ERROR, "!!LTP: failed to send [%d] COM_DataConf(s)", 1, + pMDLContext->pendingDataConfs + ); + break; + } +#endif + pMDLContext->pendingDataConfs--; + } + } + // hrp_lib_trigger_hrp_proccess(&P_BtHrp->HRPLib); + // to do + } + break; +#endif + + default: /*-----------------------------------------------------------*/ + break; + } +} + + +/****************************************************************************/ +/* bool bt_hrp_tgt_send_hrp_message */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identity Application Context */ +/* uint8_t * pMsg : pointer to of LTP msg buffer to be send */ +/* uint16_t offset */ +/* uint16_t dataLen */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* false in case the message could be send successfully, */ +/* true in case the message could not be send but was dumped */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function is used to send an LTP message to an Application with the */ +/* BT_LTP_Sendxxx functions of this library */ +/****************************************************************************/ +bool bt_hrp_tgt_send_hrp_message(HRP_TGT_APPHANDLE AppHandle, uint8_t *p_buffer, uint16_t offset, + uint16_t data_len) +{ + P_BT_HRP pBTHrp = (P_BT_HRP)P_BtHrp; + + if (pBTHrp->State == btltpStateIdle) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_INFO) + { + // APP_PRINT_INFO3("bt_hrp_tgt_send_hrp_message: 0x%x(%s) dataLen = %d", *pBuffer, + // LTPLIB_Message(*pBuffer), dataLen); + } + + /* put real buffer address and buffer callback in front of message */ + hrp_write((uint8_t *)(p_buffer + offset), data_len); + return (true); + } + else + { + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx = pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx = 0; + + if (pBTHrp->pBufferAction) + { + void *Handle = (void *)pBTHrp->pBufferAction; + + pBTHrp->pBufferAction = NULL; + bt_hrp_buffer_callback(Handle); + } + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("bt_hrp_tgt_send_hrp_message: did not send message (configurator active)"); + } + + return true; + } +} + +/****************************************************************************/ +/* uint8_t * BTLTPTgtSendBfferAlloc */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identity Application Context */ +/* uint16_t len : size of buffer to be allocated (bytes) */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* pointer to allocated memory in case of success */ +/* NULL pointer in case of an error */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to allocate buffers for LTP */ +/* messages that are send to an Application with the BT_LTP_Sendxxx */ +/* functions of this library. */ +/****************************************************************************/ +uint8_t *bt_hrp_tgt_send_buffer_alloc(HRP_TGT_APPHANDLE AppHandle, uint16_t len) +{ + uint8_t *p_buf = NULL; + P_BT_HRP pBTHrp = (P_BT_HRP)P_BtHrp; + + if (NULL == pBTHrp->p_aci_tcb) + { + return NULL; + } + + /* free index > tx index */ + if ((pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx >= pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx) + && (pBTHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size != pBTHrp->p_aci_tcb->tx_mem_tcb.free_size)) + { + /* [A---tx_idx----free_idx----B], have enough serial ram in [free_idx----B] */ + if ((pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx + len) <= TX_BUFFER_SIZE1) + + { + p_buf = pBTHrp->p_aci_tcb->p_tx_buf + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx += len; + pBTHrp->p_aci_tcb->tx_mem_tcb.free_size -= len; + /* if reach tx buffer size, return to index 0 */ + // pBTLtp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx &= (TX_BUFFER_SIZE1 - 1); + if (pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx >= TX_BUFFER_SIZE1) + { + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx -= TX_BUFFER_SIZE1; + } + } + /* [A---tx_idx----free_idx----B], have enough serial ram in [A---tx_idx], + discard [free_idx----B] */ + else if ((pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx + len) > TX_BUFFER_SIZE1 + && pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx >= len) + { + p_buf = pBTHrp->p_aci_tcb->p_tx_buf; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size = + TX_BUFFER_SIZE1 - pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx = len; + pBTHrp->p_aci_tcb->tx_mem_tcb.free_size -= len; + } + //Lorna: There have one case: when tx_blk_idx ==tx_free_blk_idx, as long as len<= TX_BUFFER_SIZE1, ram can be allocated + else if ((len <= TX_BUFFER_SIZE1) && (pBTHrp->p_aci_tcb->tx_mem_tcb.free_size == TX_BUFFER_SIZE1) + && (pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx == pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx)) + { + p_buf = pBTHrp->p_aci_tcb->p_tx_buf; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size = 0; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx = len; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx = 0; + pBTHrp->p_aci_tcb->tx_mem_tcb.free_size -= len; + /* if reach tx buffer size, return to index 0 */ + // pBTLtp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx &= (TX_BUFFER_SIZE1 - 1); + if (pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx >= TX_BUFFER_SIZE1) + { + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx -= TX_BUFFER_SIZE1; + } + } + else + { + p_buf = NULL; /* no enough free size */ + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR5("Have no serial ram 1,free index:0x%x, tx index:0x%x, unused size:0x%x, free size:0x%x, len:0x%x", + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx, pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx, \ + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size, pBTHrp->p_aci_tcb->tx_mem_tcb.free_size, len); + } + } + } + /* free index < tx index */ + else if (pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx < pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx) + { + /* [A---free_idx----tx_idx----B], have enough ram in [free_idx----tx_idx] */ + if ((pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx + len) < + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx) + + { + p_buf = pBTHrp->p_aci_tcb->p_tx_buf + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx; + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx += len; + pBTHrp->p_aci_tcb->tx_mem_tcb.free_size -= len; + } + else + { + p_buf = NULL; /* no enough free size */ + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR5("Have no serial ram 2,free index:0x%x, tx index:0x%x, unused size:0x%x, free size:0x%x, len:0x%x", + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_free_blk_idx, pBTHrp->p_aci_tcb->tx_mem_tcb.tx_blk_idx, \ + pBTHrp->p_aci_tcb->tx_mem_tcb.tx_un_used_size, pBTHrp->p_aci_tcb->tx_mem_tcb.free_size, len); + } + } + } + else /* no possiable */ + { + p_buf = NULL; /* no enough free size */ + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("Have no serial ram 3"); + } + } + + return p_buf; +} + +/****************************************************************************/ +/* void bt_hrp_tgt_receive_buffer_release */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identity Application Context */ +/* uint8_t * pBuffer : pointer to receive buffer to be released*/ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* non */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to released buffers for LTP */ +/* messages that are received and consumed by the 'LTPLibHandleReceiveData' */ +/* function of this library. */ +/****************************************************************************/ + +void bt_hrp_tgt_receive_buffer_release(HRP_TGT_APPHANDLE AppHandle, uint8_t *pBuffer) +{ + hrp_buffer_release((void *)pBuffer); +} + +/****************************************************************************/ +/* uint8_t * bt_hrp_tgt_assembly_buffer_alloc */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identity Application Context */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* pointer to allocated memory in case of success */ +/* NULL pointer in case of an error */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to allocate buffers for LTP- */ +/* message assembly that is processed by functions of this library. */ +/****************************************************************************/ +uint8_t *bt_hrp_tgt_assembly_buffer_alloc(HRP_TGT_APPHANDLE AppHandle) +{ + P_BT_HRP p_bt_hrp = (P_BT_HRP)AppHandle; + + return p_bt_hrp->p_aci_tcb->p_rx_handle_buf; +} + +/****************************************************************************/ +/* PLTPElement bt_hrp_tgt_queue_element_alloc */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identity Application Context */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* pointer to allocated queue element in case of success */ +/* NULL pointer in case of an error */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to allocate queue elements for LTP-*/ +/* message assembly that is processed by functions of this library. */ +/****************************************************************************/ +P_HRP_ElEMENT bt_hrp_tgt_queue_element_alloc(HRP_TGT_APPHANDLE AppHandle) +{ + P_BT_HRP p_bt_hrp = (P_BT_HRP)AppHandle; + P_HRP_ElEMENT pElement; + + pElement = hrp_queue_out(&p_bt_hrp->FreeElementQueue); + + if (!pElement) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("bt_hrp_tgt_queue_element_alloc: no element in BTLTPTgtQueueElementAlloc"); + } + } + + return pElement; +} + +/****************************************************************************/ +/* void bt_hrp_tgt_queue_element_release */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identity Application Context */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* non */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to release queue elements for LTP- */ +/* message assembly that is processed by functions of this library. */ +/****************************************************************************/ +void bt_hrp_tgt_queue_element_release(HRP_TGT_APPHANDLE AppHandle, P_HRP_ElEMENT pHRPElement) +{ + P_BT_HRP pBTLtp = (P_BT_HRP)AppHandle; + + hrp_queue_in(&pBTLtp->FreeElementQueue, pHRPElement); +} + + +uint8_t bt_hrp_tgt_do_crc8(HRP_TGT_APPHANDLE AppHandle, uint8_t *pStart, uint16_t length) +{ + uint8_t fcs = 0xff; + + while (length--) + { + fcs = crc8EtsTable[fcs ^ *pStart++]; + } + return 0xff - fcs; +} +unsigned short bt_hrp_tgt_do_crc16(unsigned char *q, int len) +{ + unsigned short crc = 0; + + while (len-- > 0) + { + crc = crc16EtsTable[(crc >> 8 ^ *q++) & 0xff] ^ (crc << 8); + } + return crc; +} + +void hrp_queue_in(HRP_QUEUE_P QueuePtr, void *pQueueElement) +{ + P_HRP_ELEMENT QueueElementPtr = (P_HRP_ELEMENT)pQueueElement; + P_HRP_ELEMENT LastPtr; + + if ((LastPtr = QueuePtr->Last) == (P_HRP_ELEMENT)0) /* if queue is empty, */ + { + QueuePtr->First = QueueElementPtr; /* q->first = q->last = new entry */ + } + else /* if it is not empty, new entry */ + { + LastPtr->Next = QueueElementPtr; /* is next from last entry */ + } + QueuePtr->Last = QueueElementPtr; + QueueElementPtr->Next = (P_HRP_ELEMENT)0; + QueuePtr->ElementCount++; /* increment element count */ +} + +void *hrp_queue_out(HRP_QUEUE_P QueuePtr) +{ + P_HRP_ELEMENT FirstPtr; + + if ((FirstPtr = QueuePtr->First) != (P_HRP_ELEMENT)0) + { + /* if queue not empty and */ + /* it is the last entry */ + if ((QueuePtr->First = FirstPtr->Next) == (P_HRP_ELEMENT)0) + { + QueuePtr->Last = (P_HRP_ELEMENT)0; /* set queue empty */ + } + QueuePtr->ElementCount--; /* decrement element count */ + } + return (FirstPtr); +} + + +static void bt_hrp_init_hrp_assembly(P_HRP_LIB pHRPLib, bool reUseBuffer) +{ + if (reUseBuffer) + { + pHRPLib->HRPMsgStart = pHRPLib->ReceiveOffset; + pHRPLib->HRPMsgPos = pHRPLib->ReceiveOffset; + pHRPLib->HRPDataCollected = 0; + pHRPLib->HRPMsgLength = 0; /* not known */ + } + else + { + pHRPLib->pHRPMsg = NULL; + } +} + +bool hrp_lib_initialize(P_HRP_LIB pHRPLib, HRP_TGT_APPHANDLE AppHandle, uint16_t ReceiveOffset, + uint16_t ReceiveMaxLen, uint16_t SendOffset) +{ + /* first of all, clear context data */ + memset(pHRPLib, 0, sizeof(T_HRP_LIB)); + + /* initialize context */ + pHRPLib->AppHandle = AppHandle; + pHRPLib->ReceiveOffset = ReceiveOffset; + pHRPLib->ReceiveMaxLength = ReceiveMaxLen; + pHRPLib->SendOffset = SendOffset; + + /* initialize message assembly */ + bt_hrp_init_hrp_assembly(pHRPLib, true); + + /* ready to rock... */ + pHRPLib->Status = HRPLibStatusIdle; + + return true; /* OK */ +} + + +bool hrp_lib_shutdown(P_HRP_LIB pHRPLib) +{ + if (pHRPLib == NULL) + { + return false; + } + + if (pHRPLib->pHRPMsg != NULL) + { + pHRPLib->pHRPMsg = NULL; + } + + if (pHRPLib->pActiveElement != NULL) + { + bt_hrp_tgt_queue_element_release(pHRPLib->AppHandle, pHRPLib->pActiveElement); + pHRPLib->pActiveElement = NULL; + } + + return true; +} + +bool hrp_lib_handle_receive_data(P_HRP_LIB p_hrp_lib, uint8_t *p_rx_buffer, uint16_t rx_length, + uint16_t rx_offset) +{ + //to do: process downstream commands + P_HRP_ElEMENT p_hrp_element; + + /* try to get new storage element */ + p_hrp_element = bt_hrp_tgt_queue_element_alloc(p_hrp_lib->AppHandle); + if (p_hrp_element) + { + /* store information */ + p_hrp_element->DataCB.BufferAddress = p_rx_buffer; + p_hrp_element->DataCB.Length = rx_length; + p_hrp_element->DataCB.Offset = rx_offset; + + hrp_queue_in(&p_hrp_lib->UsedElementQueue, p_hrp_element); + //DBG_BUFFER(MODULE_LTP, LEVEL_TRACE, "hrp_lib_handle_receive_data: Alloc new element: len = %d ", 1, rxLength); + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("hrp_lib_handle_receive_data: Alloc new element failed!!!"); + } + } + + if (!p_hrp_element) + { + return false; /* data could not be handled, please re-try later... */ + } + + /* trigger HRP statemachine */ + hrp_lib_trigger_hrp_proccess(p_hrp_lib); + + return true; +} +void hrp_lib_trigger_hrp_proccess(P_HRP_LIB p_hrp_lib) +{ + if (p_hrp_lib->Status >= HRPLibStatusBusy) /* off-sync or re-entrant */ + { + return; + } + else /* now we are busy */ + { + p_hrp_lib->Status = HRPLibStatusBusy; + } + + while (hrp_lib_trigger(p_hrp_lib)); + + if (p_hrp_lib->Status == HRPLibStatusBusy) /* might be off-sync */ + { + p_hrp_lib->Status = HRPLibStatusIdle; + } +} +static bool hrp_lib_trigger(P_HRP_LIB p_hrp_lib) +{ + uint16_t len_field; + uint32_t info_field; + uint16_t opt_len; + uint16_t crc16; + uint8_t module_id; + uint8_t cmd_group; + uint16_t cmd_entry; + uint16_t param_len; + uint8_t *p_param; + /* if we have no assembly buffer => try to get one */ + if (!p_hrp_lib->HRPDataCollected && !p_hrp_lib->HRPMsgLength) + { + p_hrp_lib->pHRPMsg = bt_hrp_tgt_assembly_buffer_alloc(p_hrp_lib->AppHandle); + + if (!p_hrp_lib->pHRPMsg) + { + return false; /* no re-trigger */ + } + } + /* if we have no LTP data element to work with => try to get one */ + if (!p_hrp_lib->pActiveElement) + { + p_hrp_lib->pActiveElement = (P_HRP_ElEMENT)hrp_queue_out(&p_hrp_lib->UsedElementQueue); + + if (!p_hrp_lib->pActiveElement) + { + return false; /* no re-trigger */ + } + } + /* if we don't know how long the LTP msg is we try to assemble */ + /* ==> try to determine LTP msg length */ + if (!p_hrp_lib->HRPMsgLength) + { + uint16_t copy_length; + if (p_hrp_lib->HRPDataCollected < HRP_DATA_MIN_HEADER_LENGTH) //header length is 7 + { + copy_length = HRP_DATA_MIN_HEADER_LENGTH - p_hrp_lib->HRPDataCollected; + if (bt_hrp_transfer_hrp_element_data(p_hrp_lib, copy_length)) + { + return true; /* not enough data => re-trigger*/ + } + } + //lenfield, inforfield + LE_ARRAY_TO_UINT16(len_field, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + 1 ]); + LE_ARRAY_TO_UINT32(info_field, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + 3]); + opt_len = len_field - 4; + if (p_hrp_lib->HRPDataCollected < (HRP_DATA_MIN_HEADER_LENGTH + opt_len)) + { + copy_length = (HRP_DATA_MIN_HEADER_LENGTH + opt_len) - p_hrp_lib->HRPDataCollected; + if (bt_hrp_transfer_hrp_element_data(p_hrp_lib, copy_length)) + { + return true; // not enough data => re-trigger + } + } + switch (info_field & HRP_OPT_MASK_HEADER_CRC) + { + case 0x03: //crc16 &crc 8 + { + LE_ARRAY_TO_UINT16(crc16, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + HRP_DATA_MIN_HEADER_LENGTH + + opt_len - 2]); + if (bt_hrp_tgt_do_crc8(p_hrp_lib, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart], 7) + != p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + HRP_DATA_MIN_HEADER_LENGTH ] || + bt_hrp_tgt_do_crc16(&p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart], opt_len + 5) + != crc16) + { + //hrp_lib_send_internal_event_info(p_hrp_lib, 0, NULL, HRP_CAUSE_CONNECTION_LOST, + // HRP_INTERNAL_EVENT_COMMUNICATION_OUT_OF_SYNC, HRP_GENERATE_EVENT_ID); + bt_hrp_crc_error(p_hrp_lib); + return true; + } + } + break; + case 0x02: //crc16 + { + LE_ARRAY_TO_UINT16(crc16, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + HRP_DATA_MIN_HEADER_LENGTH + + opt_len - 2]); + if (bt_hrp_tgt_do_crc16(&p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart], opt_len + 5) != crc16) + { + //hrp_lib_send_internal_event_info(p_hrp_lib, 0, NULL, HRP_CAUSE_CONNECTION_LOST, + // HRP_INTERNAL_EVENT_COMMUNICATION_OUT_OF_SYNC, HRP_GENERATE_EVENT_ID); + bt_hrp_crc_error(p_hrp_lib); + return true; + } + } + break; + case 0x01: //crc8 + { + if (bt_hrp_tgt_do_crc8(p_hrp_lib, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart], 7) + != p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + HRP_DATA_MIN_HEADER_LENGTH ]) + { + //hrp_lib_send_internal_event_info(p_hrp_lib, 0, NULL, HRP_CAUSE_CONNECTION_LOST, + // HRP_INTERNAL_EVENT_COMMUNICATION_OUT_OF_SYNC, HRP_GENERATE_EVENT_ID); + bt_hrp_crc_error(p_hrp_lib); + return true; + } + } + break; + default: + break; + } + p_hrp_lib->HRPMsgLength = opt_len + HRP_DATA_MIN_HEADER_LENGTH; + } + /* wait for message completed */ + if (p_hrp_lib->HRPMsgLength > p_hrp_lib->HRPDataCollected) + { + /* try to complete LTP message */ + if (bt_hrp_transfer_hrp_element_data(p_hrp_lib, + p_hrp_lib->HRPMsgLength - p_hrp_lib->HRPDataCollected)) + { + return true; /* not enough data => re-trigger */ + } + } + /*------------------------------------------------------------------------*/ + /* message is completed => process it */ + /*------------------------------------------------------------------------*/ + LE_ARRAY_TO_UINT16(len_field, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + 1 ]); + LE_ARRAY_TO_UINT32(info_field, &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + 3]); + + module_id = info_field >> 8; + module_id &= 0x3f; + + switch (info_field & HRP_OPT_MASK_HEADER_CRC8) + { + + case 0x01: //crc8 + { + p_param = &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + 7 + 1]; + } + break; + default: //no crc8 + { + p_param = &p_hrp_lib->pHRPMsg[p_hrp_lib->HRPMsgStart + 7]; + } + break; + } + LE_ARRAY_TO_UINT8(cmd_group, p_param); + p_param += 1; + LE_ARRAY_TO_UINT16(cmd_entry, p_param); + p_param += 2; + LE_ARRAY_TO_UINT16(param_len, p_param); + p_param += 2; + + hrp_handle_downstream_req((HRP_MODULE_ID)module_id, cmd_group, cmd_entry, param_len, p_param); + + bt_hrp_init_hrp_assembly(p_hrp_lib, true); + return true; +} +bool hrp_lib_send_internal_event_info(P_HRP_LIB p_hrp_lib, uint8_t copmsk, uint8_t *p_opt, + uint8_t cause, + uint8_t event_type, uint32_t event_info) +{ + uint16_t pos = 0; + uint8_t *p_buffer = bt_hrp_tgt_send_buffer_alloc(p_hrp_lib->AppHandle, 4); + + if (!p_buffer) + { + return true; + } + + p_buffer[pos++] = (uint8_t)cause; + p_buffer[pos++] = (uint8_t)event_type; + NETLONG2CHAR(&p_buffer[pos], event_info); + pos += 4; + + return bt_hrp_tgt_send_hrp_message(p_hrp_lib->AppHandle, p_buffer, 0, + pos); + +} +static void bt_hrp_crc_error(P_HRP_LIB pLTPLib) +{ + uint16_t invalidCount = 1; + APP_PRINT_ERROR1("bt_hrp_crc_error cut 0x%x", pLTPLib->pHRPMsg[pLTPLib->HRPMsgStart]); + while (pLTPLib->pHRPMsg[pLTPLib->HRPMsgStart + invalidCount] != 0x5A && + invalidCount < pLTPLib->HRPDataCollected) + { + //APP_PRINT_ERROR1("bt_hrp_crc_error cut 0x%x", pLTPLib->pHRPMsg[pLTPLib->HRPMsgStart + invalidCount]); + invalidCount++; + } + APP_PRINT_ERROR1("bt_hrp_crc_error cut %d byte", invalidCount); + pLTPLib->HRPMsgStart += invalidCount; + pLTPLib->HRPDataCollected -= invalidCount; + + pLTPLib->HRPMsgLength = 0; +} + +static bool bt_hrp_transfer_hrp_element_data(P_HRP_LIB pHRPLib, uint16_t copyLength) +{ + bool retVal = false; /* ==> all requested data copied */ + P_HRP_ElEMENT pActiveElement = pHRPLib->pActiveElement; + + if (pActiveElement == NULL) + { + return true; /* ==> new queue element required */ + } + + if (copyLength > pActiveElement->DataCB.Length) + { + copyLength = pActiveElement->DataCB.Length; + retVal = true; /* ==> not enough data in element!!!!!! */ + } + /*find the sync data*/ + + if (pHRPLib->HRPDataCollected) + { + while (0x5A != pHRPLib->pHRPMsg[pHRPLib->HRPMsgStart] && pHRPLib->HRPDataCollected) + { + pHRPLib->HRPMsgStart += 1; + pHRPLib->HRPDataCollected -= 1; + } + if (0 == pHRPLib->HRPDataCollected) + { + pHRPLib->HRPMsgStart = 0; + } + } + if (!pHRPLib->HRPDataCollected) + { + while (0x5A != pActiveElement->DataCB.BufferAddress[pActiveElement->DataCB.Offset] && + pActiveElement->DataCB.Length) + { + pActiveElement->DataCB.Offset++; + pActiveElement->DataCB.Length--; + } + } + + if (pActiveElement->DataCB.Length) + { + /* copy element data to msg buffer */ + memcpy(&pHRPLib->pHRPMsg[pHRPLib->HRPMsgPos], + &pActiveElement->DataCB.BufferAddress[pActiveElement->DataCB.Offset], + copyLength + ); + + /* updata data structures for element and msg buffer */ + pHRPLib->HRPDataCollected += copyLength; + pHRPLib->HRPMsgPos += copyLength; + + pActiveElement->DataCB.Offset += copyLength; + pActiveElement->DataCB.Length -= copyLength; + } + + /* check if element is consumed completely */ + else + { + bt_hrp_tgt_receive_buffer_release(pHRPLib->AppHandle, pActiveElement->DataCB.BufferAddress); + + bt_hrp_tgt_queue_element_release(pHRPLib->AppHandle, pActiveElement); + + pHRPLib->pActiveElement = NULL; + } + + return retVal; +} + +bool hrp_handle_downstream_req(HRP_MODULE_ID module_id, uint8_t cmd_group, + uint16_t cmd_index, uint16_t param_list_len, uint8_t *p_param_list) +{ + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_DEBUG) + { + APP_PRINT_INFO4("hrp downstream: module %d cmd_group 0x%x cmd_index 0x%x param_len %d", + module_id, cmd_group, cmd_index, param_list_len); + } + + switch (module_id) + { + case HRP_MODULE_LOWER_STACK: + break; + + case HRP_MODULE_UPPER_STACK: +#if F_BT_LE_BTIF_SUPPORT + hrp_btif_handle_req(cmd_group, cmd_index, param_list_len, p_param_list); +#endif + break; + + case HRP_MODULE_PROFILE: + hrp_profile_handle_req(cmd_group, cmd_index, param_list_len, p_param_list); + break; + + case HRP_MODULE_AUDIO: + break; + + case HRP_MODULE_BLE_AUTO_TEST: + hrp_gap_ble_handle_req(cmd_group, cmd_index, param_list_len, p_param_list); + break; + + default: + break; + } + return true; +} + +HRP_SEQ_ID g_hrp_seq_id = {0}; +bool hrp_handle_upperstream_events(HRP_MODULE_ID module_id, uint8_t cmd_group, + uint16_t cmd_index, uint16_t param_list_len, uint8_t *p_param_list) +{ + //add hrp header + uint8_t *p_buffer; + uint16_t pos = 0; + uint8_t sync = 0x5A; + uint16_t len_field; + uint32_t info_rfield; + uint16_t buffer_Len; + + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_DEBUG) + { + APP_PRINT_INFO4("hrp upstream: module %d cmd_group 0x%x cmd_index 0x%x param_len %d", + module_id, cmd_group, cmd_index, param_list_len); + } + + info_rfield = g_hrp_seq_id.crc8 | g_hrp_seq_id.crc16 << 1 | g_hrp_seq_id.seq_id << 2 | module_id << + 8; + //crc8 &crc16 + if (g_hrp_seq_id.crc8 && g_hrp_seq_id.crc16) + { + buffer_Len = HRP_DATA_MIN_HEADER_LENGTH + 3 + 5 + param_list_len; + len_field = 4 + 1 + 2 + 5 + param_list_len; + } + //crc8 + else if (g_hrp_seq_id.crc8 && !g_hrp_seq_id.crc16) + { + buffer_Len = HRP_DATA_MIN_HEADER_LENGTH + 1 + 5 + param_list_len; + len_field = 4 + 1 + 5 + param_list_len; + + } + //crc16 + else if (!g_hrp_seq_id.crc8 && g_hrp_seq_id.crc16) + { + buffer_Len = HRP_DATA_MIN_HEADER_LENGTH + 2 + 5 + param_list_len; + len_field = 4 + 2 + 5 + param_list_len; + + } + //no crc + else + { + buffer_Len = HRP_DATA_MIN_HEADER_LENGTH + 5 + param_list_len; + len_field = 4 + 5 + param_list_len; + } + + p_buffer = bt_hrp_tgt_send_buffer_alloc(0, buffer_Len); + if (!p_buffer) + { + APP_PRINT_ERROR0("hrp_handle_upperstream_events: buffer allocated failed"); + return false; + } + + p_buffer[pos++] = sync; + + LE_UINT16_TO_ARRAY(&p_buffer[pos], len_field); + pos += 2; + + LE_UINT32_TO_ARRAY(&p_buffer[pos], info_rfield); + pos += 4; + + g_hrp_seq_id.seq_id += 1; + if (g_hrp_seq_id.seq_id >= 32) + { + g_hrp_seq_id.seq_id = 0; + } + if (g_hrp_seq_id.crc8) + { + p_buffer[pos++] = bt_hrp_tgt_do_crc8(0, &p_buffer[0], HRP_DATA_MIN_HEADER_LENGTH); + } + p_buffer[pos++] = cmd_group; + + LE_UINT16_TO_ARRAY(&p_buffer[pos], cmd_index); + pos += 2; + LE_UINT16_TO_ARRAY(&p_buffer[pos], param_list_len); + pos += 2; + + memcpy(&p_buffer[pos], p_param_list, param_list_len); + pos += param_list_len; + + + if (g_hrp_seq_id.crc16) + { + if (g_hrp_seq_id.crc8) + { + LE_UINT16_TO_ARRAY(&p_buffer[pos], bt_hrp_tgt_do_crc16(&p_buffer[0], + HRP_DATA_MIN_HEADER_LENGTH + 1 + 5 + param_list_len)); + } + else + { + LE_UINT16_TO_ARRAY(&p_buffer[pos], bt_hrp_tgt_do_crc16(&p_buffer[0], + HRP_DATA_MIN_HEADER_LENGTH + 5 + param_list_len)); + } + pos += 2; + } + + return (bt_hrp_tgt_send_hrp_message(0, p_buffer, 0, pos)); +} + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_utils.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_utils.h new file mode 100644 index 00000000..14b1db54 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/application/hrp_utils.h @@ -0,0 +1,505 @@ +#ifndef _LTPLIB_UTILS_H_ +#define _LTPLIB_UTILS_H_ + +#include +#include + + + + +typedef enum _HRP_MODULE_ID +{ + HRP_MODULE_RESERVED = 0, + HRP_MODULE_LOWER_STACK = 1, + HRP_MODULE_UPPER_STACK = 2, + HRP_MODULE_PROFILE = 3, + HRP_MODULE_RESERVED1, + + HRP_MODULE_AUDIO = 16, + HRP_MODULE_BLE_AUTO_TEST = 17, + + +} HRP_MODULE_ID; + +bool hrp_handle_downstream_req(HRP_MODULE_ID module_id, uint8_t cmd_group, + uint16_t cmd_index, uint16_t param_list_len, uint8_t *p_param_list); + +bool hrp_handle_upperstream_events(HRP_MODULE_ID module_id, uint8_t cmd_group, + uint16_t cmd_index, uint16_t param_list_len, uint8_t *p_param_list); + + + +/****************************************************************************/ +/* target specific application context to be handed over to the application */ +/* this constand is used by the BTLTPTgtxxx function calls of this library */ +#define HRP_TGT_APPHANDLE void * + + +/* definition of valid LTP response causes */ +#define HRP_CAUSE_SUCCESS 0x00 +#define HRP_CAUSE_ACCEPT 0x01 +#define HRP_CAUSE_REJECT 0x02 +#define HRP_CAUSE_RESOURCE_ERROR 0x03 +#define HRP_CAUSE_INVALID_PARAMETER 0x04 +#define HRP_CAUSE_INVALID_STATE 0x05 +#define HRP_CAUSE_CONNECTION_DISCONNECT 0x06 +#define HRP_CAUSE_CONNECTION_DISCONNECTED LTP_CAUSE_CONNECTION_DISCONNECT +#define HRP_CAUSE_CONNECTION_LOST 0x07 +#define HRP_CAUSE_AUTHENTICATION_FAILED 0x08 +#define HRP_CAUSE_INIT_TIMEOUT 0x09 +#define HRP_CAUSE_INIT_OUT_OF_SYNC 0x0A +#define HRP_CAUSE_INIT_HARDWARE_fAILURE 0x0B +#define HRP_CAUSE_CONNECTION_PAUSED 0x30 +#define HRP_CAUSE_FLOWCONTROL_VIOLATION 0x31 +#define HRP_CAUSE_UNSPECIFIED 0xFD +#define HRP_CAUSE_NOT_SUPPORTED 0xFE + +/* definition of locally generated internal Event types */ +#define HRP_INTERNAL_EVENT_COMMUNICATION_OUT_OF_SYNC 0x40 +#define HRP_INTERNAL_EVENT_MALFORMED_MSG_RECEIVED 0x41 +#define HRP_INTERNAL_EVENT_INVALID_DATA_RECEIVED 0x42 + + + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** 3) Internal functionality used by the LTP-Lib **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +/* macro definition for read/write uint16_t from/to uint8_t memory */ +#define NETSHORT2CHAR(p,w) \ + *((p)+1) = (uint8_t)((w) & 0xff); \ + *(p) = /*lint -e(572,778)*/ (uint8_t)(((w)>>8) & 0xff) + +#define NETCHAR2SHORT(p) ((*((p)+1)) & 0xff) + ((*(p)) << 8) + +#define NETCHAR2LONG(p) ((uint32_t)(*((p)+3)) & 0xff) + ((uint32_t)(*((p)+2)) << 8) \ + + ((uint32_t)(*((p)+1)) << 16) + ((uint32_t)(*((p)+0)) << 24) + +#define NET24BIT2CHAR(p,w) \ + *((p)+2) = (uint8_t)((w) & 0xff); \ + *((p)+1) = /*lint -e(572,778)*/ (uint8_t)(((w)>>8) & 0xff); \ + *((p)+0) = /*lint -e(572,778)*/ (uint8_t)(((w)>>16) & 0xff); \ + +#define NETLONG2CHAR(p,w) \ + *((p)+3) = (uint8_t)((w) & 0xff); \ + *((p)+2) = /*lint -e(572,778)*/ (uint8_t)(((w)>>8) & 0xff); \ + *((p)+1) = /*lint -e(572,778)*/ (uint8_t)(((w)>>16) & 0xff); \ + *((p)+0) = /*lint -e(572,778)*/ (uint8_t)(((w)>>24) & 0xff) + + +/* macro definition to identity internal event location */ +#define HRP_GENERATE_EVENT_ID ((0x00)<<24 | (((LTP_SOURCE_FILE_ID) & 0xFF)<<16) | ((__LINE__) & 0xFFFF)) + +/* message definitions */ +#define HRP_DATA_MIN_HEADER_LENGTH 7 +#define HRP_OPT_MASK_HEADER_CRC 0x03 +#define HRP_OPT_MASK_HEADER_CRC8 0x01 + +#define HRP_OPCODE_RESERVED 0x00 + +/* definitions of message properties */ +#define LTP_MDC_MSG 0x01 +#define LTP_MDH_MSG 0x02 +#define LTP_VAR_LEN_MSG 0x04 +#define LTP_CNF_MSG 0x08 + + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* needed message structures */ + +/* data structure to describe message properties */ +typedef struct +{ + uint8_t opcode; + uint8_t length; + uint8_t properties; +} LTPCmdInfo; +typedef LTPCmdInfo *PLTPCmdInfo; + +/* internal Status definition for LTP-Lib */ +typedef enum +{ + HRPLibStatusIdle, /* ready to be called with 'LTPLibxxx' call*/ + HRPLibStatusResync, /* Lib is ready for re-sync */ + HRPLibStatusBusy, /* busy with 'LTPLibxxx' call (re-entrant) */ + HRPLibStatusOffSync /* Lib detected sync loss in receive data */ +} T_ENUM_HRP_STATUS; + +/* internal data container definition for LTP-Lib */ +typedef struct +{ + uint16_t Offset; /* offset to data in data buffer */ + uint16_t Length; /* length of data */ + uint8_t *BufferAddress; /* buffer address */ +} T_HRP_DATA_CB; +typedef T_HRP_DATA_CB *LTP_DATA_CB_P; + +/* internal data container definition for queue elements */ +struct hrpQueueElement /* dummy definition */ +{ + struct hrpQueueElement *Next; /* point to next element */ + uint8_t data[2]; /* user data */ +}; +typedef struct hrpQueueElement T_HRP_QUEUE_ELEMENT; +typedef T_HRP_QUEUE_ELEMENT *P_HRP_ELEMENT; + +/* internal data container definition for queue elements */ +typedef struct +{ + P_HRP_ELEMENT First; /* first element */ + P_HRP_ELEMENT Last; /* last element */ + uint16_t ElementCount; /* element count */ +} HRP_QUEUE_T, *HRP_QUEUE_P; + +void hrp_queue_in(HRP_QUEUE_P QueuePtr, void *pQueueElement); +void *hrp_queue_out(HRP_QUEUE_P QueuePtr); + +/* internal queue-element for LTP-Lib for data container */ +typedef struct +{ + /* This MUST be the FIRST structure element ! */ + T_HRP_QUEUE_ELEMENT QueueElement; + /* the 'real' data... */ + T_HRP_DATA_CB DataCB; +} T_HRP_ELEMENT; +typedef T_HRP_ELEMENT *P_HRP_ElEMENT; + + + +/* internal context definition for LTP-Lib. When ever a LTP-Lib function is */ +/* called, a pointer to this context must be provided */ +typedef struct +{ + HRP_TGT_APPHANDLE AppHandle; + T_ENUM_HRP_STATUS Status; + uint16_t ReceiveOffset; + uint16_t ReceiveMaxLength; + uint16_t SendOffset; + uint16_t HRPMsgStart; + P_HRP_ElEMENT pActiveElement; + uint8_t *pHRPMsg; + uint16_t HRPMsgPos; + uint16_t HRPMsgLength; + + HRP_QUEUE_T UsedElementQueue; + uint16_t HRPDataCollected; +} T_HRP_LIB; +typedef T_HRP_LIB *P_HRP_LIB; +typedef struct +{ + uint8_t seq_id; + bool crc8; + bool crc16; +} HRP_SEQ_ID; + +void hrp_lib_trigger_hrp_proccess(P_HRP_LIB p_hrp_lib); +static bool hrp_lib_trigger(P_HRP_LIB p_hrp_lib); +static bool bt_hrp_transfer_hrp_element_data(P_HRP_LIB p_hrp_lib, uint16_t copy_length); +static void bt_hrp_crc_error(P_HRP_LIB p_hrp_lib); +bool hrp_lib_send_internal_event_info(P_HRP_LIB p_hrp_lib, uint8_t copmsk, uint8_t *p_opt, + uint8_t cause, + uint8_t event_type, uint32_t event_info); + + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** 4) Target specifics that must be implemented by the user of the LTP-Lib**/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +/****************************************************************************/ +/* uint8_t * bt_hrp_tgt_send_buffer_alloc */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* uint16_t len : size of buffer to be allocated (bytes) */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* pointer to allocated memory in case of success */ +/* NULL pointer in case of an error */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to allocate buffers for LTP */ +/* messages that are send to an application with the BT_LTP_Sendxxx */ +/* functions of this library. */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +uint8_t *bt_hrp_tgt_send_buffer_alloc(HRP_TGT_APPHANDLE app_handle, uint16_t len); + +/****************************************************************************/ +/* uint8_t * BTLTPTgtAssemblyBfferAlloc */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* pointer to allocated memory in case of success */ +/* NULL pointer in case of no buffer available (this is no error condition) */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to allocate buffers for LTP- */ +/* message assembly that is processed by functions of this library. */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +uint8_t *bt_hrp_tgt_assembly_buffer_alloc(HRP_TGT_APPHANDLE app_handle); + +void bt_hrp_buffer_callback(void *Handle); + +/****************************************************************************/ +/* void bt_hrp_tgt_receive_buffer_release */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* uint8_t * pBuffer : pointer to receive buffer to be released*/ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* non */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to released buffers for LTP */ +/* messages that are received and consumed by the 'hrp_lib_handle_receive_data' */ +/* function of this library. */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +void bt_hrp_tgt_receive_buffer_release(HRP_TGT_APPHANDLE app_handle, uint8_t *pBuffer); + +/****************************************************************************/ +/* bool bt_hrp_tgt_send_hrp_message */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* uint8_t * pMsg : pointer to of LTP msg buffer to be send */ +/* uint16_t offset */ +/* uint16_t dataLen */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* true in case the message could be send successfully, */ +/* false in case the message could not be send but was dumped */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function is used to send an LTP message to an application with the */ +/* BT_LTP_Sendxxx functions of this library */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +bool bt_hrp_tgt_send_hrp_message(HRP_TGT_APPHANDLE app_handle, uint8_t *pMsg, uint16_t offset, + uint16_t data_len); + +/****************************************************************************/ +/* bool bt_hrp_tgt_handle_hrp_message */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* uint8_t * pMsgBuffer: pointer to message buffer */ +/* uint8_t cmd : identifier for LTP-command to be handled*/ +/* uint8_t copmsk : copmsk of LPT-command to be handled */ +/* uint8_t * pOpt : pointer to optional parameters of LTP- */ +/* command to be handled, or NULL in case */ +/* of no optional parameters included */ +/* uint16_t lenPara : length of mandatory parameters of LTP- */ +/* command to be handled */ +/* uint8_t * pPara : pointer to mandatory parameters of LTP- */ +/* command to be handled, or NULL in case */ +/* of no mandatory parameters included */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* false in case the message buffer shall not be re-used for LTP-msg */ +/* assembly by the LTP-Lib, otherwise true */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function is called by the LTP-Lib if a complete LTP message is */ +/* assembled and is ready to be consumed by the application */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +bool bt_hrp_tgt_handle_hrp_message(HRP_TGT_APPHANDLE app_handle, uint8_t *p_msg_buffer, uint8_t cmd, + uint8_t copmsk, uint8_t *p_opt, uint16_t len_para, uint8_t *p_para); + +/****************************************************************************/ +/* PLTPElement BTLTPTgtQueueElementAlloc */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* pointer to allocated queue element in case of success */ +/* NULL pointer in case of no queue element available (this is no error */ +/* condition) */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to allocate queue elements for LTP-*/ +/* message assembly that is processed by functions of this library. */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +P_HRP_ElEMENT bt_hrp_tgt_queue_element_alloc(HRP_TGT_APPHANDLE app_handle); + +/****************************************************************************/ +/* void bt_hrp_tgt_queue_element_release */ +/* ( */ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* non */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This target specific function is used to release queue elements for LTP- */ +/* message assembly that is processed by functions of this library. */ +/* */ +/* TODO: please implement this function for your target */ +/* */ +/****************************************************************************/ +void bt_hrp_tgt_queue_element_release(HRP_TGT_APPHANDLE app_handle, P_HRP_ElEMENT p_hrp_element); + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** 5) Utility fuctions that have to be integrated for using the LTP-Lib **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + +/****************************************************************************/ +/* bool hrp_lib_initialize */ +/* ( */ +/* P_HRP_LIB pLTPLib : pointer to LTP context to be initialized*/ +/* HRP_TGT_APPHANDLE AppHandle : Handle to identify application context */ +/* uint16_t receiveOffset : offset for assembled LTP-messages */ +/* uint16_t receiveMaxLen : max len for assembled LTP-messages */ +/* uint16_t sendOffset : offset for LTP-messages to be send */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* false if an internal error occured and the lib is not functional, */ +/* true otherwise (in case of success) */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function has to be called to initialize the LTP-Lib at system */ +/* startup and/or reset */ +/* */ +/* TODO: please integrate this function into the target implementation */ +/* */ +/****************************************************************************/ +bool hrp_lib_initialize(P_HRP_LIB p_hrp_lib, HRP_TGT_APPHANDLE app_handle, uint16_t receive_offset, + uint16_t receive_max_len, uint16_t send_offset); + +/****************************************************************************/ +/* bool hrp_lib_shutdown */ +/* ( */ +/* P_HRP_LIB pLTPLib : pointer to LTP context to be initialized*/ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* false if an internal error occured and the lib is not functional, */ +/* true otherwise (in case of success) */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function may be called to free all resources used by LTP-Lib */ +/* */ +/* TODO: please integrate this function into the target implementation */ +/* */ +/****************************************************************************/ +bool hrp_lib_shutdown(P_HRP_LIB p_hrp_lib); + +//void hrp_lib_trigger_hrp_proccess(P_HRP_LIB pLTPLib); + +#if F_LTPLIB_ASYNC_ASSEMBLY_SUPPORT +/****************************************************************************/ +/* void LTPLibHandleTimeout */ +/* ( */ +/* P_HRP_LIB pLTPLib : pointer to LTP context to be used */ +/* TLTPTimerID timerID : timer that timed out */ +/* ) */ +/****************************************************************************/ +void hrp_lib_handle_receive_data(P_HRP_LIB p_hrp_lib, TLTPTimerID timerID); +#endif + +/****************************************************************************/ +/* bool LTPLibHandleReceiveData */ +/* ( */ +/* P_HRP_LIB pLTPLib : pointer to LTP context to be used */ +/* uint8_t * pRxBuffer : pointer to buffer that contains new data */ +/* uint16_t rxLength : length of new data received */ +/* uint16_t rxOffset : offset of new data in buffer */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* false data could NOT be handled properly, */ +/* true otherwise */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function has to be called to introduce new rx data received into */ +/* the LTP-Lib statemachine when ever new data is received */ +/* */ +/* TODO: please integrate this function into the target implementation */ +/* */ +/****************************************************************************/ +bool hrp_lib_handle_receive_data(P_HRP_LIB p_hrp_lib, uint8_t *p_rx_buffer, uint16_t rx_length, + uint16_t rx_offset); + +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/** **/ +/** 6) Utility functions that can be used by the user of the LTP-Lib **/ +/** **/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ +/****************************************************************************/ + + + +/****************************************************************************/ +/* uint16_t hrp_lib_insert_header */ +/* ( */ +/* P_HRP_LIB pLTPLib : pointer to LTP context to be used */ +/* uint8_t * pBuffer : pointer to data buffer containing payload */ +/* uint16_t* offset : pointer to the offset of the payload */ +/* after call: offset of the message in buffer */ +/* uint16_t dataLen : payload length in buffer */ +/* uint8_t cmd : ltp command */ +/* uint8_t copmsk : bitmask defining content of optional parameter */ +/* uint8_t * pOpt : pointer to optional parameter structure */ +/* uint16_t* posParam : after call: offset of the first parameter */ +/* ) */ +/* return:------------------------------------------------------------------*/ +/* length of the ltp message in pBuffer beginning from *offset */ +/* if length is 0, the header could not be inserted */ +/* */ +/* Description:-------------------------------------------------------------*/ +/* This function can be used to insert a LTP message header with optional */ +/* parameters infront of a given message buffer with payload */ +/* */ +/****************************************************************************/ + + +#ifdef __cplusplus +} +#endif + +#endif /* LTPLIB_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif.h new file mode 100644 index 00000000..1a0a9351 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif.h @@ -0,0 +1,7708 @@ +/** + * Copyright (c) 2017, Realsil Semiconductor Corporation. All rights reserved. + */ + +#ifndef _BTIF_H_ +#define _BTIF_H_ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup STACK STACK + * \defgroup BTIF BTIF + * + * \brief Define parameters and structures used in Bluetooth stack APIs or messages. + * \details The BTIF module provide parameters and structure definitions that + * can be used in Bluetooth stack APIs and upstream messages that Bluetooth + * stack sent to APP. APIs such as release btif message buffers are also + * provided here.\n + * + * \ingroup STACK + */ + +/** + * + * \ingroup BTIF + */ +#define BTIF_NAME_LENGTH 40 /**< Max length of device name. */ + +/** + * btif.h + * + * \name BTIF_AUTHEN_FLAGS + * \brief Btif authentication support flags. + * \anchor BTIF_AUTHEN_FLAGS + */ +/** + * \ingroup BTIF + */ +#define BTIF_AUTHEN_BONDING 0x0001 /**< Dedicated bonding support. */ +#define BTIF_AUTHEN_GENERAL_BONDING 0x0002 /**< General bonding support. */ +#define BTIF_AUTHEN_MITM 0x0004 /**< MITM support. */ +#define BTIF_AUTHEN_SC 0x0008 /**< LE secure connections support. */ +#define BTIF_AUTHEN_KEY_PRESS 0x0010 /**< Keypress support. */ +#define BTIF_AUTHEN_FORCE_BONDING 0x0100 /**< Always force bonding. */ +#define BTIF_AUTHEN_SC_ONLY 0x0200 /**< Secure connections only mode support. */ +#define BTIF_AUTHEN_SC_BR 0x0400 /**< BR/EDR secure connections support. */ + +#define BTIF_LE_MAX_EXTENDED_SCAN_PHY_NUM 2 +#define BTIF_LE_MAX_EXTENDED_ADV_SETS_NUM 4//max is 63 by core spec +#define BTIF_LE_MAX_INIT_PHYS_NUM 3 + +#define LE_ADV_CHANNEL_37 0x01 /**< Enable channel 37 */ +#define LE_ADV_CHANNEL_38 0x02 /**< Enable channel 38 */ +#define LE_ADV_CHANNEL_39 0x04 /**< Enable channel 39 */ +#define LE_ADV_CHANNEL_ALL 0x07 /**< Enable all channels */ + +/* PairingReq / PairingRsp initKeyDist/respKeyDist */ +#define BTIF_LE_SMP_DIST_ENC_KEY 0x01 +#define BTIF_LE_SMP_DIST_ID_KEY 0x02 +#define BTIF_LE_SMP_DIST_SIGN_KEY 0x04 +#define BTIF_LE_SMP_DIST_LINK_KEY 0x08 + +#define BTIF_LE_CONN_INIT_PHY_1M 0x01 +#define BTIF_LE_CONN_INIT_PHY_2M 0x02 +#define BTIF_LE_CONN_INIT_PHY_CODED 0x04 + +#define BTIF_LE_TX_POWER_UNKNOWN 127 +#define BTIF_USE_LE_FIXED_DISPLAY_VALUE 0x80000000 + +/** +If extended advertising PDU types are being used (bit 4 = 0) then: +1. The advertisement shall not be both connectable and scannable. +2. High duty cycle directed connectable advertising shall not be used (bit 3 = 0). +*/ +#define BTIF_ADV_EVENT_PROP_CONNECTABLE_ADV 0x01 +#define BTIF_ADV_EVENT_PROP_SCANNABLE_ADV 0x02 +#define BTIF_ADV_EVENT_PROP_DIRECTED_ADV 0x04 +#define BTIF_ADV_EVENT_PROP_HDC_DIRECTED_ADV 0x08 +#define BTIF_ADV_EVENT_PROP_USE_LEGACY_ADV 0x10 +#define BTIF_ADV_EVENT_PROP_OMIT_ADV_ADDR 0x20 +#define BTIF_ADV_EVENT_PROP_INCLUDE_TX_POWER 0x40 + +#define BTIF_EXT_ADV_REPORT_CONNECTABLE_ADV 0x01 +#define BTIF_EXT_ADV_REPORT_SCANNABLE_ADV 0x02 +#define BTIF_EXT_ADV_REPORT_DIRECTED_ADV 0x04 +#define BTIF_EXT_ADV_REPORT_SCAN_RESPONSE 0x08 +#define BTIF_EXT_ADV_REPORT_USE_LEGACY_ADV 0x10 + +#define BTIF_LE_SCAN_PHY_LE_1M 0x01 +#define BTIF_LE_SCAN_PHY_LE_CODED 0x04 + +#define BTIF_LE_ALL_PHY_NO_PREFERENCE_TX 0x01 +#define BTIF_LE_ALL_PHY_NO_PREFERENCE_RX 0x02 + +#define BTIF_LE_TX_PHY_PREFERENCE_1M 0x01 +#define BTIF_LE_TX_PHY_PREFERENCE_2M 0x02 +#define BTIF_LE_TX_PHY_PREFERENCE_CODED 0x04 + +#define BTIF_LE_RX_PHY_PREFERENCE_1M 0x01 +#define BTIF_LE_RX_PHY_PREFERENCE_2M 0x02 +#define BTIF_LE_RX_PHY_PREFERENCE_CODED 0x04 + +/** + * btif.h + * + * \name BTIF_BR_SEC + * \brief Btif BR/EDR security requirement flags. + * \anchor BTIF_BR_SEC + */ +/** + * \ingroup BTIF + */ +#define BTIF_BR_SEC_OUTGOING 0x01 /**< Request for outgoing connection. */ +#define BTIF_BR_SEC_AUTHEN 0x02 /**< Authentication is required. */ +#define BTIF_BR_SEC_MITM 0x04 /**< MITM authentication is required, only possible if authentication is set. */ +#define BTIF_BR_SEC_AUTHOR 0x08 /**< User level authorization is required. */ +#define BTIF_BR_SEC_ENCRYPT 0x10 /**< Encryption on link is required, only possible if authentication is set. */ +#define BTIF_BR_SEC_SECURE_CONNECTIONS 0x20 /**< Secure connections is required. */ + +/** + * btif.h + * + * \name BTIF_BR_LINK_POLICY + * \brief Btif BR/EDR link policy. + * \anchor BTIF_BR_LINK_POLICY + */ +/** + * \ingroup BTIF + */ +#define BTIF_BR_LINK_POLICY_DISABLE_ALL 0x00 /**< Disable all link policies for BR/EDR link. */ +#define BTIF_BR_LINK_POLICY_ENABLE_ROLE_SWITCH 0x01 /**< Only enable role switch for BR/EDR link. */ +#define BTIF_BR_LINK_POLICY_ENABLE_SNIFF_MODE 0x04 /**< Only enable sniff mode for BR/EDR link. */ + +/** + * btif.h + * + * \name BTIF_BR_ACL_PKT_TYPE + * \brief Btif BR/EDR ACL link packet type. + * \anchor BTIF_BR_ACL_PKT_TYPE + */ +/** + * \ingroup BTIF + */ +#define BTIF_PKT_TYPE_NO_2DH1 0x0002 /**< Packet type 2DH1 shall not be used. */ +#define BTIF_PKT_TYPE_NO_3DH1 0x0004 /**< Packet type 3DH1 shall not be used. */ +#define BTIF_PKT_TYPE_DM1 0x0008 /**< Packet type DM1 may be used. */ +#define BTIF_PKT_TYPE_DH1 0x0010 /**< Packet type DH1 may be used. */ +#define BTIF_PKT_TYPE_NO_2DH3 0x0100 /**< Packet type 2DH3 shall not be used. */ +#define BTIF_PKT_TYPE_NO_3DH3 0x0200 /**< Packet type 3DH3 shall not be used. */ +#define BTIF_PKT_TYPE_DM3 0x0400 /**< Packet type DM3 may be used. */ +#define BTIF_PKT_TYPE_DH3 0x0800 /**< Packet type DH3 may be used. */ +#define BTIF_PKT_TYPE_NO_2DH5 0x1000 /**< Packet type 2DH5 shall not be used. */ +#define BTIF_PKT_TYPE_NO_3DH5 0x2000 /**< Packet type 3DH5 shall not be used. */ +#define BTIF_PKT_TYPE_DM5 0x4000 /**< Packet type DM5 may be used. */ +#define BTIF_PKT_TYPE_DH5 0x8000 /**< Packet type DH5 may be used. */ + +/** + * btif.h + * + * \name BTIF_BR_SCO_PKT_TYPE + * \brief Btif BR/EDR SCO link packet type. + * \anchor BTIF_BR_SCO_PKT_TYPE + */ +/** + * \ingroup BTIF + */ +#define BTIF_PKT_TYPE_HV1 0x0001 /**< Packet type HV1 may be used. */ +#define BTIF_PKT_TYPE_HV2 0x0002 /**< Packet type HV2 may be used. */ +#define BTIF_PKT_TYPE_HV3 0x0004 /**< Packet type HV3 may be used. */ +#define BTIF_PKT_TYPE_EV3 0x0008 /**< Packet type EV3 may be used. */ +#define BTIF_PKT_TYPE_EV4 0x0010 /**< Packet type EV4 may be used. */ +#define BTIF_PKT_TYPE_EV5 0x0020 /**< Packet type EV5 may be used. */ +#define BTIF_PKT_TYPE_NO_2EV3 0x0040 /**< Packet type 2EV3 shall not be used. */ +#define BTIF_PKT_TYPE_NO_3EV3 0x0080 /**< Packet type 3EV3 shall not be used. */ +#define BTIF_PKT_TYPE_NO_2EV5 0x0100 /**< Packet type 2EV5 shall not be used. */ +#define BTIF_PKT_TYPE_NO_3EV5 0x0200 /**< Packet type 3EV5 shall not be used. */ + +/** + * btif.h + * + * \name BTIF_BR_L2CAP_MODE + * \brief Btif BR/EDR L2CAP mode. + * \anchor BTIF_BR_L2CAP_MODE + */ +/** + * \ingroup BTIF + */ +#define BTIF_L2C_MODE_BASIC (1 << 0x00) /**< L2CAP channel mode: basic mode. */ +#define BTIF_L2C_MODE_ERTM (1 << 0x03) /**< L2CAP channel mode: enhanced retransmission mode. */ + +/** + * btif.h + * + * \name BTIF_BR_L2CAP_REJ_MODE + * \brief Btif BR/EDR L2CAP rej mode in ERTM. + * \anchor BTIF_BR_L2CAP_REJ_MODE + */ +/** + * \ingroup BTIF + */ +#define BTIF_L2C_ERTM_REJ 0x00 /**< Use REJ for L2CAP ERTM mode. */ +#define BTIF_L2C_ERTM_SREJ 0x01 /**< Use SREJ for L2CAP ERTM mode. */ + +/** + * btif.h + * + * \name BTIF_BR_AIR_MODE + * \brief Btif transmit air coding format on SCO/eSCO link. + * \anchor BTIF_BR_AIR_MODE + */ +/** + * \ingroup BTIF + */ +/**@{*/ +#define BTIF_AIR_MODE_U_LAW 0 /**< Air mode u-law log. */ +#define BTIF_AIR_MODE_A_LAW 1 /**< Air mode A-law log. */ +#define BTIF_AIR_MODE_CVSD 2 /**< Air mode CVSD. */ +#define BTIF_AIR_MODE_TRANSPARENT 3 /**< Air mode transparent data. */ +/**@}*/ + +/** + * btif.h + * + * \brief Btif cause used for response messages to tell results of request. + * Also used in some confirmation APIs to answer indications. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_CAUSE_SUCCESS = BTIF_SUCCESS, /**< Success. */ + BTIF_CAUSE_ACCEPT = (BTIF_ERR | BTIF_ACCEPT), /**< Accept for indication, only used when confirmation. */ + BTIF_CAUSE_REJECT = (BTIF_ERR | BTIF_ERR_REJECT), /**< Reject for indication, only used when confirmation. */ + BTIF_CAUSE_RESOURCE_ERROR = (BTIF_ERR | BTIF_ERR_NO_RESOURCE), /**< Error happened because of resource limitation. */ + BTIF_CAUSE_INVALID_PARAM = (BTIF_ERR | BTIF_ERR_INVALID_PARAM), /**< Error happened because of invalid parameters. */ + BTIF_CAUSE_INVALID_STATE = (BTIF_ERR | BTIF_ERR_INVALID_STATE), /**< Error happened because of invalid states. */ + BTIF_CAUSE_CONN_DISCONNECT = (BTIF_ERR | BTIF_ERR_CONN_DISCONNECT), /**< Connection disconnected. */ + BTIF_CAUSE_CONN_LOST = (BTIF_ERR | BTIF_ERR_CONN_LOST), /**< Connection lost. */ + BTIF_CAUSE_AUTHEN_FAIL = (BTIF_ERR | BTIF_ERR_AUTHEN_FAIL), /**< Authentication failed. */ + BTIF_CAUSE_INIT_TOUT = (BTIF_ERR | BTIF_ERR_INIT_TOUT), /**< Timeout when stack initialize. */ + BTIF_CAUSE_INIT_OUT_OF_SYNC = (BTIF_ERR | BTIF_ERR_INIT_OUT_OF_SYNC), /**< Out if sync with controllor when stack initialize. */ + BTIF_CAUSE_INIT_HARDWARE_ERROR = (BTIF_ERR | BTIF_ERR_INIT_HARDWARE_ERROR),/**< Hardware error happened when stack initialize. */ + BTIF_CAUSE_LOWER_LAYER_ERROR = (BTIF_ERR | BTIF_ERR_LOWER_LAYER_ERROR), /**< Error happended in lower layer. */ + BTIF_CAUSE_ADDR_NOT_RESOLVED = (BTIF_ERR | BTIF_ERR_ADDR_NOT_RESOLVED), /**< Address type is not resolved. */ + BTIF_CAUSE_TOUT = (BTIF_ERR | BTIF_ERR_TOUT), /**< Error happened because of timeout. */ + + BTIF_CAUSE_UNSPECIFIED = (BTIF_ERR | BTIF_ERR_UNSPECIFIED), /**< Unspecified error reason. */ + BTIF_CAUSE_NOT_SUPPORTED = (BTIF_ERR | BTIF_ERR_NOT_SUPPORTED), /**< Request not support. */ +} T_BTIF_CAUSE; + +/** + * btif.h + * + * \brief Btif key type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_KEY_COMBINATION = 0x00, /**< Combination key. */ + BTIF_KEY_LOCAL_UNIT = 0x01, /**< Local unit key. */ + BTIF_KEY_REMOTE_UNIT = 0x02, /**< Remote unit key. */ + BTIF_KEY_DEBUG_COMBINATION = 0x03, /**< Debug combination key. */ + BTIF_KEY_UNAUTHEN = 0x04, /**< SSP generated link key without MITM protection. */ + BTIF_KEY_AUTHEN = 0x05, /**< SSP generated link key with MITM protection. */ + BTIF_KEY_CHANGED_COMBINATION = 0x06, /**< Changed combination key. */ + BTIF_KEY_UNAUTHEN_P256 = 0x07, /**< Security Connections generated link key without MITM protection. */ + BTIF_KEY_AUTHEN_P256 = 0x08, /**< Security Connections link key with MITM protection. */ + BTIF_KEY_LE_LOCAL_LTK = 0x11, /**< BLE Long Term Key Blob. */ + BTIF_KEY_LE_REMOTE_LTK = 0x12, /**< BLE Long Term Key Blob. */ + BTIF_KEY_LE_LOCAL_IRK = 0x13, /**< BLE Identity Resolving Key. */ + BTIF_KEY_LE_REMOTE_IRK = 0x14, /**< BLE Identity Resolving Key. */ + BTIF_KEY_LE_LOCAL_CSRK = 0x15, /**< BLE Local CSR Key. */ + BTIF_KEY_LE_REMOTE_CSRK = 0x16, /**< BLE Remote CSR Key. */ + BTIF_KEY_REQ_BR = 0x80, /**< Only used to request a BR/EDR link key. */ + BTIF_KEY_DELETE = 0xFF /**< Link key is no longer valid and should be deleted. */ +} T_BTIF_KEY_TYPE; + +typedef enum +{ + BTIF_REMOTE_ADDR_LE_PUBLIC = 0x00, + BTIF_REMOTE_ADDR_LE_RANDOM = 0x01, +#if F_BT_LE_PRIVACY_SUPPORT + BTIF_REMOTE_ADDR_LE_PUBLIC_IDENTITY = 0x02, + BTIF_REMOTE_ADDR_LE_RANDOM_IDENTITY = 0x03, +#endif + BTIF_REMOTE_ADDR_CLASSIC = 0x10, + BTIF_REMOTE_ADDR_ANY = 0x20, + BTIF_REMOTE_ADDR_LE_ANONYMOUS = 0xff, +} T_BTIF_REMOTE_ADDR_TYPE; + +/** + * btif.h + * + * \brief Btif operation code used to configure local device. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_DEV_CFG_OP_NAME = 0x10, /**< Configure local name and class of device. */ + BTIF_DEV_CFG_OP_DID_EIR, /**< Configure DID infomation in EIR. */ + BTIF_DEV_CFG_OP_EXT_EIR, /**< Configure extra data in EIR. */ + BTIF_DEV_CFG_OP_PAGE_SCAN, /**< Configure page scan parameters. */ + BTIF_DEV_CFG_OP_INQUIRY_SCAN, /**< Configure inquiry scan parameters. */ + BTIF_DEV_CFG_OP_INQUIRY_MODE, /**< Configure inquiry mode. */ + BTIF_DEV_CFG_OP_LINK_POLICY, /**< Configure default link policy used when connection established. */ + BTIF_DEV_CFG_OP_BT_MODE, /**< Configure Bluetooth mode. */ + BTIF_DEV_CFG_OP_ACCEPT_CONN_ROLE /**< Configure prefered link role when accept connection request. */ +} T_BTIF_DEV_CFG_OPCODE; + +/** + * btif.h + * + * \brief Btif ACL status used in ACL status information message. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_ACL_CONN_ACTIVE = 0x01, /**< ACL link in active mode. */ + BTIF_ACL_CONN_SNIFF = 0x02, /**< ACL link in sniff mode. */ + BTIF_ACL_AUTHEN_START = 0x03, /**< ACL link authentication start. */ + BTIF_ACL_AUTHEN_SUCCESS = 0x04, /**< ACL link authentication success. */ + BTIF_ACL_AUTHEN_FAIL = 0x05, /**< ACL link authentication fail. */ + BTIF_ACL_CONN_ENCRYPTED = 0x06, /**< ACL link encrypted. */ + BTIF_ACL_CONN_DISCONN = 0x07, /**< ACL link disconnected. */ + BTIF_ACL_CONN_NOT_ENCRYPTED = 0x08, /**< ACL link not encrypted. */ + BTIF_ACL_ADDR_RESOLVED = 0x09, /**< Address is resolved. */ + BTIF_ACL_ROLE_MASTER = 0x0A, /**< ACL link role is master. */ + BTIF_ACL_ROLE_SLAVE = 0x0B, /**< ACL link role is slave. */ + BTIF_ACL_CONN_SNIFF_SUBRATE = 0x0C, /**< ACL link in sniff subrate mode. */ + BTIF_ACL_CONN_FAIL = 0x0D, /**< ACL link is failed to connect. */ + BTIF_ACL_CONN_SUCCESS = 0x0E, /**< ACL link is connected successfully. */ + BTIF_ACL_CONN_READY = 0x0F, /**< ACL link is ready to be configured. */ + BTIF_ACL_CONN_BR_SC_START = 0x10, /**< BR/EDR Secure Connections information exchange is started. */ + BTIF_ACL_CONN_BR_SC_CMPL = 0x11 /**< BR/EDR Secure Connections information exchange is finished. */ +} T_BTIF_ACL_STATUS; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_AUTHEN_START or \ref BTIF_ACL_AUTHEN_SUCCESS or \ref + * BTIF_ACL_AUTHEN_FAIL or \ref BTIF_ACL_CONN_ENCRYPTED or \ref BTIF_ACL_CONN_NOT_ENCRYPTED. + * + * \ingroup BTIF + */ +typedef struct +{ + T_BTIF_KEY_TYPE key_type; /**< Key type of the link. */ + uint8_t key_size; /**< Key size of the link. */ + uint8_t encrypt_type; /**< Encryption type of the link. */ + uint16_t cause; /**< Authentication result. */ +} T_BTIF_ACL_STATUS_PARAM_AUTHEN; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_BR_SC_CMPL. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< BR/EDR Secure Connections information exchange result. */ +} T_BTIF_ACL_STATUS_PARAM_BR_SC_CMPL; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_ADDR_RESOLVED. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; +} T_BTIF_ACL_STATUS_PARAM_RESOLVE; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_SNIFF. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t interval; /**< Sniff interval of the ACL link. */ +} T_BTIF_ACL_STATUS_PARAM_SNIFF; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_SNIFF_SUBRATE. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t max_tx_latency; /**< Maximum latency for data transmitted to remote device. */ + uint16_t max_rx_latency; /**< Maximum latency for data received from remote device. */ + uint16_t min_remote_tout; /**< Base sniff subrate timeout remote device shall use. */ + uint16_t min_local_tout; /**< Base sniff subrate timeout local device will use. */ +} T_BTIF_ACL_STATUS_PARAM_SNIFF_SUBRATE; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_DISCONN. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< ACL link disconnect reason. */ +} T_BTIF_ACL_CONNECTION_DISCONNECT; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_FAIL. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< ACL link establish fail reason. */ +} T_BTIF_ACL_CONNECTION_FAIL; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_SUCCESS. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t handle; /**< ACL link handle. */ +} T_BTIF_ACL_CONNECTION_SUCCESS; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message when status is + * \ref BTIF_ACL_CONN_READY. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t handle; /**< ACL link handle. */ +} T_BTIF_ACL_CONNECTION_READY; + +/** + * btif.h + * + * \brief Parameters used in ACL status information message. + * + * \ingroup BTIF + */ +typedef union +{ + T_BTIF_ACL_CONNECTION_SUCCESS conn_success; /**< Parameter for link success to establish. */ + T_BTIF_ACL_CONNECTION_READY conn_ready; /**< Parameter for link ready to be used. */ + T_BTIF_ACL_CONNECTION_FAIL conn_fail; /**< Parameter for link fail to establish. */ + T_BTIF_ACL_CONNECTION_DISCONNECT conn_disconn; /**< Parameter for link disconnected. */ + T_BTIF_ACL_STATUS_PARAM_AUTHEN authen; /**< Parameter for authentication status. */ + T_BTIF_ACL_STATUS_PARAM_RESOLVE resolve; /**< Address resolvable paramter. */ + T_BTIF_ACL_STATUS_PARAM_SNIFF sniff; /**< Parameter for ACL link sniff mode. */ + T_BTIF_ACL_STATUS_PARAM_SNIFF_SUBRATE sniff_subrate;/**< Parameter for ACL link sniff subrate. */ + T_BTIF_ACL_STATUS_PARAM_BR_SC_CMPL br_sc_cmpl; /**< Parameter for BR SC complete. */ +} T_BTIF_ACL_STATUS_PARAM; + +/** + * btif.h + * + * \brief Keypress notification type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_PASSKEY_ENTRY_STARTED, /**< The passkey key entry protocol procedure is started. */ + BTIF_PASSKEY_DIGIT_ENTERED, /**< A digit is entered by the remote user. */ + BTIF_PASSKEY_DIGIT_ERASED, /**< A digit is erased by the remote user. */ + BTIF_PASSKEY_CLEARED, /**< The display is cleared by the remote user. */ + BTIF_PASSKEY_ENTRY_CMPL, /**< The passkey key entry protocol procedure is completed. */ +} T_BTIF_KEYPRESS_NOTIF_TYPE; + +/** @brief define indentify address type */ +typedef enum +{ + BTIF_IDENT_ADDR_PUBLIC = 0x00, /* low energy public address. */ + BTIF_IDENT_ADDR_RAND = 0x01, /* low energy random address. */ +} T_BTIF_IDENT_ADDR_TYPE; + +/** @brief define local adress type */ +typedef enum +{ + BTIF_LOCAL_ADDR_LE_PUBLIC = 0x00, /**< Bluetooth low energy public address. */ + BTIF_LOCAL_ADDR_LE_RANDOM = 0x01, /**< Bluetooth low energy random address. */ +#if F_BT_LE_PRIVACY_SUPPORT + BTIF_LOCAL_ADDR_LE_RAP_OR_PUBLIC = 0x02, /**< Bluetooth low energy random address. */ + BTIF_LOCAL_ADDR_LE_RAP_OR_RAND = 0x03 /**< Bluetooth low energy random address. */ +#endif +} T_BTIF_LOCAL_ADDR_TYPE; + +typedef enum +{ + BTIF_ADDR_LE_RAND_STATIC = 0x00, + BTIF_ADDR_LE_RAND_NON_RESOLVABLE = 0x01, + BTIF_ADDR_LE_RAND_RESOLVABLE = 0x02 +} T_BTIF_ADDR_RAND; + +typedef enum +{ + BTIF_PDU_TYPE_ANY = 0x00, + BTIF_PDU_TYPE_NOTIFICATION = 0x01, + BTIF_PDU_TYPE_INDICATION = 0x02 +} T_BTIF_GATT_PDU_TYPE; + +typedef enum +{ + BTIF_GATT_DISCOVERY_SERVICE = 0x01, /**< all primary services */ + BTIF_GATT_DISCOVERY_SERVICE_BY_UUID, /**< service by UUID */ + BTIF_GATT_DISCOVERY_CHARACTER, /**< all characteristics */ + BTIF_GATT_DISCOVERY_CHARACTER_DESC, /**< all characteristic descriptors */ + BTIF_GATT_DISCOVERY_RELATIONSHIP /**< relationship (included services) */ +} T_BTIF_GATT_DISCOVERY_TYPE; + +typedef struct +{ + uint16_t att_handle; + uint16_t end_group_handle; + uint16_t uuid16; +} T_BTIF_GATT_GENERIC_ELEM16; + +typedef struct +{ + uint16_t att_handle; + uint16_t end_group_handle; + uint8_t uuid128[16]; +} T_BTIF_GATT_GENERIC_ELEM128; + +typedef T_BTIF_GATT_GENERIC_ELEM16 T_BTIF_GATT_SERVICE_ELEM16; +typedef T_BTIF_GATT_GENERIC_ELEM128 T_BTIF_GATT_SERVICE_ELEM128; + +typedef struct +{ + uint16_t att_handle; + uint16_t end_group_handle; +} T_BTIF_GATT_SERVICE_BY_UUID_ELEM; + +typedef struct +{ + uint16_t decl_handle; + uint16_t properties; /**< high nibble is reserved */ + uint16_t value_handle; + uint16_t uuid16; +} T_BTIF_GATT_CHARACT_ELEM16; + +typedef struct +{ + uint16_t decl_handle; + uint16_t properties; /**< high nibble is reserved */ + uint16_t value_handle; + uint8_t uuid128[16]; +} T_BTIF_GATT_CHARACT_ELEM128; + +typedef struct +{ + uint16_t handle; + uint16_t uuid16; +} T_BTIF_GATT_CHARACT_DESC_ELEM16; + +typedef struct +{ + uint16_t handle; + uint8_t uuid128[16]; +} T_BTIF_GATT_CHARACT_DESC_ELEM128; + +typedef struct +{ + uint16_t decl_handle; + uint16_t att_handle; + uint16_t end_group_handle; + uint16_t uuid16; +} T_BTIF_GATT_RELATION_ELEM16; + +typedef struct +{ + uint16_t decl_handle; + uint16_t att_handle; + uint16_t end_group_handle; + uint8_t uuid128[16]; +} T_BTIF_GATT_RELATION_ELEM128; + +typedef enum +{ + BTIF_GATT_READ_TYPE_BASIC = 0x01, /**< ATT "Read (Blob) Request" */ + BTIF_GATT_READ_TYPE_BY_UUID /**< ATT "Read By Type Request" */ +} T_BTIF_GATT_READ_TYPE; + +typedef enum +{ + BTIF_GATT_WRITE_TYPE_REQ = 0x01, /**< ATT "Write Request" */ + BTIF_GATT_WRITE_TYPE_CMD, /**< ATT "Write Command" */ + BTIF_GATT_WRITE_TYPE_PREP, /**< ATT "Prepare Write Request" */ + BTIF_GATT_WRITE_TYPE_SIGNED_CMD /**< ATT "Signed Write Command" */ +} T_BTIF_GATT_WRITE_TYPE; + +typedef enum +{ + BTIF_GATT_STORE_OP_GET_CCC_BITS, /**< get CCC Bits for one */ + BTIF_GATT_STORE_OP_SET_CCC_BITS, /**< set CCC Bits for one */ + BTIF_GATT_STORE_OP_DELETE_ALL_CCC_BITS, /**< delete all CCC Bits for all peers */ +} T_BTIF_GATT_STORE_OPCODE; + +typedef enum +{ + BTIF_LE_ADV_MODE_DISABLED = 0, + BTIF_LE_ADV_MODE_ENABLED +} T_BTIF_LE_ADV_MODE; + +typedef enum +{ + BTIF_LE_EXT_ADV_MODE_DISABLED = 0, + BTIF_LE_EXT_ADV_MODE_ENABLED +} T_BTIF_LE_EXT_ADV_MODE; + +typedef enum +{ + BTIF_LE_PERIODIC_ADV_MODE_DISABLED = 0, + BTIF_LE_PERIODIC_ADV_MODE_ENABLED +} T_BTIF_LE_PERIODIC_ADV_MODE; + +typedef enum +{ + BTIF_LE_AE_LEGACY_ADV_CONN_N_SCAN_UNDIRECTED = 0x13, + BTIF_LE_AE_LEGACY_ADV_CONN_LOW_DUTY_DIRECTED = 0x15, + BTIF_LE_AE_LEGACY_ADV_CONN_HIGH_DUTY_DIRECTED = 0x1D, + BTIF_LE_AE_LEGACY_ADV_SCAN_UNDIRECTED = 0x12, + BTIF_LE_AE_LEGACY_ADV_NON_SCAN_NON_CONN = 0x10, +} T_BTIF_LE_AE_LEGACY_ADV_PROPERTY; + +typedef enum +{ + BTIF_LE_PRIM_ADV_PHY_LE_1M = 1, + BTIF_LE_PRIM_ADV_PHY_LE_CODED = 3 +} T_BTIF_LE_PRIM_ADV_PHY_TYPE; + +typedef enum +{ + BTIF_LE_ADV_TYPE_UNDIRECTED = 0, + BTIF_LE_ADV_TYPE_DIRECTED_HIGH_DUTY, + BTIF_LE_ADV_TYPE_SCANNABLE, + BTIF_LE_ADV_TYPE_NON_CONNECTABLE, + BTIF_LE_ADV_TYPE_DIRECTED_LOW_DUTY +} T_BTIF_LE_ADV_TYPE; + +typedef enum +{ + BTIF_LE_SCAN_REQ_NOTIFY_DISABLE = 0, + BTIF_LE_SCAN_REQ_NOTIFY_ENABLE = 1 +} T_BTIF_LE_SCAN_REQ_NOTIFY_TYPE; + +/** This enum type describes adv type for BTIF_MSG_LE_SCAN_INFO. */ +typedef enum +{ + BTIF_LE_ADV_EVT_TYPE_UNDIRECTED = 0, /**< Connectable undirected advertising. */ + BTIF_LE_ADV_EVT_TYPE_DIRECTED = 1, /**< Connectable directed advertising. */ + BTIF_LE_ADV_EVT_TYPE_SCANNABLE = 2, /**< Scanable undirected advertising. */ + BTIF_LE_ADV_EVT_TYPE_NON_CONNECTABLE, /**< Nonconnectable undirected advertising. */ + BTIF_LE_ADV_EVT_TYPE_SCAN_RSP /**< scan response. */ +} T_BTIF_LE_ADV_EVT_TYPE; + +typedef enum +{ + BTIF_LE_ADV_EVT_TYPE_CONNECTABLE_DIRECTED = 0x01, /* Connectable undirected advertising */ +} T_BTIF_LE_DIRECT_ADV_EVT_TYPE; + +typedef enum +{ + BTIF_LE_ADV_FILTER_ANY = 0, + BTIF_LE_ADV_FILTER_WHITE_LIST_SCAN, + BTIF_LE_ADV_FILTER_WHITE_LIST_CONN, + BTIF_LE_ADV_FILTER_WHITE_LIST_ALL, +} T_BTIF_LE_ADV_FILTER_POLICY; + +typedef enum +{ + BTIF_LE_SCAN_FILTER_ANY = 0, + BTIF_LE_SCAN_FILTER_WHITE_LIST, + BTIF_LE_SCAN_FILTER_ANY_RPA, + BTIF_LE_SCAN_FILTER_WHITE_LIST_RPA, +} T_BTIF_LE_SCAN_FILTER_POLICY; + +typedef enum +{ + BTIF_LE_DATA_TYPE_ADV = 0, + BTIF_LE_DATA_TYPE_SCAN_RSP +} T_BTIF_LE_ADV_DATA_TYPE; + +typedef enum +{ + BTIF_LE_DATA_TYPE_EXT_ADV = 0, + BTIF_LE_DATA_TYPE_EXT_SCAN_RSP +} T_BTIF_LE_EXT_ADV_DATA_TYPE; + +typedef enum +{ + BTIF_LE_ADV_FRAG_OP_INTERMEDIATE_FRAG = 0, + BTIF_LE_ADV_FRAG_OP_FIRST_FRAG = 1, + BTIF_LE_ADV_FRAG_OP_LAST_FRAG = 2, + BTIF_LE_ADV_FRAG_OP_CMPL_ADV_DATA = 3, + BTIF_LE_ADV_FRAG_OP_UNCHANGE_UPDATE_DID = 4, +} T_BTIF_LE_ADV_FRAG_OP_TYPE; + +typedef enum +{ + BTIF_LE_ADV_FRAG_PREFER_MAY_FRAG_ALL = 0, + BTIF_LE_ADV_FRAG_PREFER_NOT_OR_MIN_FRAG = 1 +} T_BTIF_LE_ADV_FRAG_PREFERENCE_TYPE; + +typedef enum +{ + BTIF_LE_SCAN_MODE_DISABLED = 0, + BTIF_LE_SCAN_MODE_ENABLED = 1, +} T_BTIF_LE_SCAN_MODE; + +typedef enum +{ + BTIF_LE_SCAN_DUPLICATE_FILTER_DISABLED = 0, + BTIF_LE_SCAN_DUPLICATE_FILTER_ENABLED = 1, + BTIF_LE_SCAN_DUPLICATE_FILTER_ENABLED_RESET_FOR_EACH_PERIOD = 2, +} T_BTIF_LE_SCAN_FILTER_DUPLICATES; + +typedef enum +{ + BTIF_LE_SCAN_TYPE_PASSIVE, + BTIF_LE_SCAN_TYPE_ACTIVE +} T_BTIF_LE_SCAN_TYPE; + +typedef enum +{ + BTIF_LE_WHITE_LIST_OP_CLEAR = 0, + BTIF_LE_WHITE_LIST_OP_ADD, + BTIF_LE_WHITE_LIST_OP_REMOVE +} T_BTIF_LE_WHITE_LIST_OP; + +typedef enum +{ + BTIF_LE_ADV_SET_OP_CLEAR = 0, + BTIF_LE_ADV_SET_OP_ADD, + BTIF_LE_ADV_SET_OP_REMOVE +} T_BTIF_LE_ADV_SET_OP; + +typedef enum +{ + BTIF_DIRECT_ADDR_LE_PUBLIC = 0x00, + BTIF_DIRECT_ADDR_LE_RAND = 0x01, + BTIF_DIRECT_ADDR_LE_PUBLIC_IDENT = 0x02, + BTIF_DIRECT_ADDR_LE_RAND_IDENT = 0x03, + BTIF_DIRECT_ADDR_LE_RAND_UNABLE_RESOLV = 0xFE +} T_BTIF_DIRECT_ADDR_TYPE; + +typedef struct +{ + T_BTIF_LE_SCAN_TYPE scan_type; + uint16_t scan_interval; + uint16_t scan_window; +} T_BTIF_LE_EXT_SCAN_PARAM; + +typedef struct +{ + uint8_t adv_handle; + uint16_t duration; + uint8_t max_ext_adv_evt; +} T_BTIF_LE_EXT_ADV_SET_PARAM; + +typedef enum +{ + BTIF_LE_PERIODIC_ADV_LIST_OP_CLEAR = 0, + BTIF_LE_PERIODIC_ADV_LIST_OP_ADD, + BTIF_LE_PERIODIC_ADV_LIST_OP_REMOVE +} T_BTIF_LE_PERIODIC_ADV_LIST_OP; + +typedef enum +{ + BTIF_LE_RESOLVING_LIST_OP_CLEAR = 0, + BTIF_LE_RESOLVING_LIST_OP_ADD, + BTIF_LE_RESOLVING_LIST_OP_REMOVE +} T_BTIF_LE_RESOLVING_LIST_OP; + +typedef enum +{ + BTIF_LE_NETWORK_PRIVACY = 0, + BTIF_LE_DEVICE_PRIVACY +} T_BTIF_LE_PRIVACY_MODE; + +typedef enum +{ + BTIF_LE_PHY_1M = 0x01, + BTIF_LE_PHY_2M = 0x02, + BTIF_LE_PHY_CODED = 0x03 +} T_BTIF_LE_PHY_TYPE; + +typedef enum +{ + BTIF_LE_PHY_OPTIONS_LE_CODED_PREFERENCE_NO = 0, + BTIF_LE_PHY_OPTIONS_LE_CODED_PREFERENCE_S2 = 1, + BTIF_LE_PHY_OPTIONS_LE_CODED_PREFERENCE_S8 = 2 +} T_BTIF_LE_PHY_OPTIONS; + +typedef struct +{ + uint16_t scan_interval; + uint16_t scan_window; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supv_tout; + uint16_t ce_len_min; + uint16_t ce_len_max; +} T_BTIF_LE_CONN_REQ_PARAM; + +typedef enum +{ + T_BTIF_SERVICE_APP_DEF = 0, /**< application provides services */ +} T_BTIF_GATT_SERVICE_ID; + +typedef enum +{ + BTIF_L2C_LE_CONN_ACCEPT = L2C_LE_CREDIT_CONN_SUCCESS, + BTIF_L2C_LE_CONN_PSM_NOT_SUPPORTED = (L2C_ERR | L2C_LE_CREDIT_RSP_PSM_NOT_SUPPORTED), + BTIF_L2C_LE_CONN_NO_RESOURCES = (L2C_ERR | L2C_LE_CREDIT_RSP_NO_RESOURCES), + BTIF_L2C_LE_CONN_INSUFFICIENT_AUTHEN = (L2C_ERR | L2C_LE_CREDIT_RSP_INSUFFICIENT_AUTHEN), + BTIF_L2C_LE_CONN_INSUFFICIENT_AUTHOR = (L2C_ERR | L2C_LE_CREDIT_RSP_INSUFFICIENT_AUTHOR), + BTIF_L2C_LE_CONN_INSUFFICIENT_ENCRYP_KEY_SIZE = (L2C_ERR | L2C_LE_CREDIT_RSP_INSUFFICIENT_ENCRYP_KEY_SIZE), + BTIF_L2C_LE_CONN_INSUFFICIENT_ENCRYP = (L2C_ERR | L2C_LE_CREDIT_RSP_INSUFFICIENT_ENCRYP), + BTIF_L2C_LE_CONN_INVAlID_SOURCE_CID = (L2C_ERR | L2C_LE_CREDIT_RSP_INVALID_SOURCE_CID), + BTIF_L2C_LE_CONN_SOURCE_CID_ALREADY_ALLOC = (L2C_ERR | L2C_LE_CREDIT_RSP_SOURCE_CID_ALREADY_ALLOC) +} T_BTIF_L2C_LE_CONN_STATUS; + +typedef enum +{ + BTIF_LE_SECURITY_NONE, + BTIF_LE_SECURITY_UNAUTHEN_ENCRYT, + BTIF_LE_SECURITY_AUTHEN_ENCRYT, + BTIF_LE_SECURITY_UNAUTHEN_DATA_SIGN, + BTIF_LE_SECURITY_AUTHEN_DATA_SIGN, + BTIF_LE_SECURITY_AUTHOR +} T_BTIF_LE_SECURITY_MODE; + +/** + * btif.h + * + * \brief Definition of input/output capabilities. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_IOCAP_DISPLAY_ONLY, /**< Only a Display present, no Keyboard or Yes/No Keys. */ + BTIF_IOCAP_DISPLAY_YES_NO, /**< Display and Yes/No Keys present. */ + BTIF_IOCAP_KEYBOARD_ONLY, /**< only a Keyboard present, no Display. */ + BTIF_IOCAP_NO_IO, /**< No input/output capabilities. */ + BTIF_IOCAP_KEYBOARD_DISPLAY /**< Keyboard and Display present, used in BLE only. */ +} T_BTIF_IOCAP; + +/** + * btif.h + * + * \brief BR/EDR bluetooth mode. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_BT_MODE21_DISABLED, /**< Disable all Bluetooth 2.1 functionality. */ + BTIF_BT_MODE21_ENABLED /**< Enable Bluetooth 2.1 functionality. */ +} T_BTIF_BT_MODE; + +/** + * btif.h + * + * \brief BR/EDR radio mode. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_RADIO_VISIBLE_CONNECTABLE = 0x01, /**< Enable both inquiry scan and page scan. */ + BTIF_RADIO_VISIBLE = 0x02, /**< Only enable inquiry scan. */ + BTIF_RADIO_CONNECTABLE = 0x03, /**< Only enable page scan. */ + BTIF_RADIO_NON_DISCVBL = 0x04, /**< Disable both inquiry scan and page scan. */ + BTIF_RADIO_OFF = 0x06 /**< Radio off mode. */ +} T_BTIF_RADIO_MODE; + +/** + * btif.h + * + * \brief BR/EDR page scan type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_BR_PAGE_SCAN_STANDARD = 0, /**< BR/EDR page scan type standard. */ + BTIF_BR_PAGE_SCAN_INTERLACED, /**< BR/EDR page scan type interlaced. */ +} T_BTIF_BR_PAGE_SCAN_TYPE; + +/** + * btif.h + * + * \brief BR/EDR inquiry scan type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_BR_INQUIRY_SCAN_STANDARD = 0, /**< BR/EDR inquiry scan type standard. */ + BTIF_BR_INQUIRY_SCAN_INTERLACED, /**< BR/EDR inquiry scan type interlaced. */ +} T_BTIF_BR_INQUIRY_SCAN_TYPE; + +/** + * btif.h + * + * \brief BR/EDR inquiry inquiry result type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_BR_STANDARD_INQUIRY_RESULT = 0, /**< Inquiry reusult standard format. */ + BTIF_BR_INQUIRY_RESULT_WITH_RSSI, /**< Inquiry result format with RSSI. */ + BTIF_BR_EXTENDED_INQUIRY_RESULT, /**< Inquiry result with RSSI format or Extended inquiry result format. */ +} T_BTIF_BR_INQUIRY_MODE; + +/** + * btif.h + * + * \brief BR/EDR link policy. + * + * \ingroup BTIF + */ +typedef uint8_t T_BTIF_BR_LINK_POLICY; + +/** + * btif.h + * + * \brief BR/EDR link role. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_BR_LINK_ROLE_MASTER, /**< BR/EDR link role master. */ + BTIF_BR_LINK_ROLE_SLAVE /**< BR/EDR link role slave. */ +} T_BTIF_BR_LINK_ROLE; + +/** + * btif.h + * + * \brief Operation code used to configure ACL link. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_ACL_CFG_LINK_POLICY, /**< Configure ACL link policy. */ + BTIF_ACL_CFG_LINK_SUPV_TOUT, /**< Configure ACL link supervision timeout value. */ + BTIF_ACL_CFG_LINK_ROLE, /**< Configure ACL link role. */ + BTIF_ACL_CFG_PKT_TYPE, /**< Configure ACL link packet type. */ + BTIF_ACL_CFG_ENTER_SNIFF_MODE, /**< Configure ACL to enter sniff mode. */ + BTIF_ACL_CFG_EXIT_SNIFF_MODE, /**< Configure ACL to exit sniff mode. */ +} T_BTIF_ACL_CFG_OPCODE; + +/** + * btif.h + * + * \brief Parameters used to configure ACL link when operation code is \ref BTIF_ACL_CFG_LINK_POLICY. + * + * \ingroup BTIF + */ +typedef struct +{ + T_BTIF_BR_LINK_POLICY policy; /**< ACL link policy paramter to be configured. */ +} T_BTIF_ACL_CFG_PARAM_LINK_POLICY; + +/** + * btif.h + * + * \brief Parameters used to configure ACL link when operation code is \ref BTIF_ACL_CFG_LINK_SUPV_TOUT. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t tout; /**< ACL link supervision timeout value to be configured. */ +} T_BTIF_ACL_CFG_PARAM_LINK_SUPV_TOUT; + +/** + * btif.h + * + * \brief Parameters used to configure ACL link when operation code is \ref BTIF_ACL_CFG_LINK_ROLE. + * + * \ingroup BTIF + */ +typedef struct +{ + T_BTIF_BR_LINK_ROLE role; /**< ACL link role to be configured. */ +} T_BTIF_ACL_CFG_PARAM_LINK_ROLE; + +/** + * btif.h + * + * \brief Parameters used to configure ACL link when operation code is \ref BTIF_ACL_CFG_ENTER_SNIFF_MODE. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t min_interval; /**< Min sniff interval, only even values between 0x0002 and 0xFFFE are valid. */ + uint16_t max_interval; /**< Max sniff interval, only even values between 0x0002 and 0xFFFE are valid, should be larger than min_interval. */ + uint16_t sniff_attempt; /**< Number of baseband receive slots for sniff attempt. */ + uint16_t sniff_tout; /**< Number of baseband receive slots for sniff timeout. */ + uint16_t max_latency; /**< Max allowed sniff subrate of the remote device. Set to 0 if do not want to configure sniff subrate. */ + uint16_t min_remote_tout; /**< Min base sniff subrate timeout the remote device may use. */ + uint16_t min_local_tout; /**< Min base sniff subrate timeout the local device may use. */ +} T_BTIF_ACL_CFG_PARAM_SNIFF_MODE; + +/** + * btif.h + * + * \brief Parameters used to configure ACL link when operation code is \ref BTIF_ACL_CFG_PKT_TYPE. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t type; /**< ACL link packet type to be configured. */ +} T_BTIF_ACL_CFG_PKT_TYPE; + +/** + * btif.h + * + * \brief Parameters used to configure ACL link. + * + * \ingroup BTIF + */ +typedef union +{ + T_BTIF_ACL_CFG_PARAM_LINK_POLICY link_policy; /**< Parameter for link policy. */ + T_BTIF_ACL_CFG_PARAM_LINK_SUPV_TOUT supv_tout; /**< Parameter for supervision timeout. */ + T_BTIF_ACL_CFG_PARAM_LINK_ROLE link_role; /**< Parameter for link role. */ + T_BTIF_ACL_CFG_PARAM_SNIFF_MODE sniff_mode; /**< Parameter for sniff mode. */ + T_BTIF_ACL_CFG_PKT_TYPE pkt_type; /**< Parameter for link packet type. */ +} T_BTIF_ACL_CFG_PARAM; + +/** + * btif.h + * + * \brief SDP UUID type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_UUID16, /**< UUID type 16 bits */ + BTIF_UUID32, /**< UUID type 32 bits */ + BTIF_UUID128 /**< UUID type 128 bits */ +} T_BTIF_UUID_TYPE; + +/** + * btif.h + * + * \brief SDP UUID data. + * + * \ingroup BTIF + */ +typedef union +{ + uint16_t uuid_16; /**< UUID data in 16 bits */ + uint32_t uuid_32; /**< UUID data in 32 bits */ + uint8_t uuid_128[16]; /**< UUID data in 128 bits */ +} T_BTIF_UUID_DATA; + +/** + * btif.h + * + * \brief SDP discovery type. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_SDP_DISCOV_TYPE_BR, /**< Discover normal SDP information */ + BTIF_SDP_DISCOV_TYPE_DID /**< Discover DID information */ +} T_BTIF_SDP_DISCOV_TYPE; + +/** + * btif.h + * + * \brief L2CAP cause used in L2CAP connection confirm API. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_L2C_CONN_ACCEPT = L2C_CONN_ACCEPT, /**< L2CAP connection accept */ + BTIF_L2C_CONN_PENDING = (L2C_ERR | L2C_ERR_PENDING), /**< L2CAP connection pending */ + BTIF_L2C_CONN_INVALID_PSM = (L2C_ERR | L2C_ERR_INVALID_PSM), /**< L2CAP connection reject because of PSM not support */ + BTIF_L2C_CONN_SECURITY_BLOCK = (L2C_ERR | L2C_ERR_SECURITY_BLOCK), /**< L2CAP connection reject because of security block */ + BTIF_L2C_CONN_NO_RESOURCE = (L2C_ERR | L2C_ERR_NO_RESOURCE), /**< L2CAP connection reject because of no resources available */ + BTIF_L2C_CONN_INVALID_PARAM = (L2C_ERR | L2C_ERR_INVALID_PARAM), /**< L2CAP connection reject because of invalid parameter */ + BTIF_L2C_CONN_INVALID_SOURCE_CID = (L2C_ERR | L2C_ERR_INVALID_SOURCE_CID), /**< L2CAP connection reject because of invalid source CID */ + BTIF_L2C_CONN_SOURCE_CID_ALLOCATED = (L2C_ERR | L2C_ERR_SOURCE_CID_ALLOCATED)/**< L2CAP connection reject because of source CID already allocated */ +} T_BTIF_L2C_CONN_CAUSE; + +/** + * btif.h + * + * \brief SCO packet status. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_SCO_PKT_STATUS_OK = 0, /**< SCO packet status for correctly received data */ + BTIF_SCO_PKT_STATUS_INVALID = 1, /**< SCO packet status for invalid data */ + BTIF_SCO_PKT_STATUS_NO_DATA = 2, /**< SCO packet status for no data received */ + BTIF_SCO_PKT_STATUS_PARTIAL_LOST = 3 /**< SCO packet status for data partially lost */ +} T_BTIF_SCO_PKT_STATUS; + +/** + * btif.h + * + * \brief Btif message types. + * + * \ingroup BTIF + */ +typedef enum +{ + BTIF_MSG_REGISTER_REQ = 0x01, + BTIF_MSG_REGISTER_RSP, /**< Response of registering callback function. */ + BTIF_MSG_RELEASE_REQ, + BTIF_MSG_RELEASE_RSP, /**< Response of releasing callback function. */ + BTIF_MSG_ACT_INFO, /**< Information of Bluetooth stack initialization. */ + BTIF_MSG_DEV_CFG_REQ, + BTIF_MSG_DEV_CFG_RSP, /**< Response of configuring local device. */ + + BTIF_MSG_ACL_STATUS_INFO, /**< Information of ACL link status. */ + BTIF_MSG_ACL_PRIORITY_SET_REQ, + BTIF_MSG_ACL_PRIORITY_SET_RSP, /**< Response of setting acl priority. */ + + BTIF_MSG_READ_RSSI_REQ, + BTIF_MSG_READ_RSSI_RSP, /**< Response of reading RSSI information. */ + BTIF_MSG_VENDOR_CMD_REQ, + BTIF_MSG_VENDOR_CMD_RSP, /**< Response of vendor command. */ + BTIF_MSG_VENDOR_EVT_INFO, /**< Information of vendor event. */ + + BTIF_MSG_PAIRABLE_MODE_SET_REQ, + BTIF_MSG_PAIRABLE_MODE_SET_RSP, /**< Response of setting radio mode. */ + BTIF_MSG_USER_PASSKEY_REQ_IND, /**< Indication of user passkey request. */ + BTIF_MSG_USER_PASSKEY_REQ_CFM, + BTIF_MSG_USER_PASSKEY_REQ_REPLY_REQ, + BTIF_MSG_USER_PASSKEY_REQ_REPLY_RSP, /**< Response of user passkey request reply. */ + BTIF_MSG_USER_PASSKEY_NOTIF_INFO, /**< Information of user passkey notification. */ + BTIF_MSG_AUTHEN_RESULT_IND, /**< Indication of authentication result. */ + BTIF_MSG_AUTHEN_RESULT_CFM, + BTIF_MSG_AUTHEN_KEY_REQ_IND, /**< Indication of authentication key request. */ + BTIF_MSG_AUTHEN_KEY_REQ_CFM, + BTIF_MSG_USER_CFM_REQ_IND, /**< Indication of user confirm request. */ + BTIF_MSG_USER_CFM_REQ_CFM, + BTIF_MSG_KEYPRESS_NOTIF_REQ, + BTIF_MSG_KEYPRESS_NOTIF_RSP, /**< Response of keypress notification. */ + BTIF_MSG_KEYPRESS_NOTIF_INFO, /**< Information of remote keypress notification. */ + BTIF_MSG_HW_ERROR_INFO, /**< Indication of hardware error. */ + + BTIF_MSG_REMOTE_OOB_REQ_IND = 0x0100, /**< Indication of remote OOB data request. */ + BTIF_MSG_REMOTE_OOB_REQ_CFM, + + // GATT + // server + BTIF_MSG_GATT_SRV_REG_REQ, + BTIF_MSG_GATT_SRV_REG_RSP, + BTIF_MSG_GATT_ATTR_UPDATE_REQ, + BTIF_MSG_GATT_ATTR_UPDATE_RSP, + BTIF_MSG_GATT_ATTR_UPDATE_STATUS_IND, + BTIF_MSG_GATT_ATTR_UPDATE_STATUS_CFM, + BTIF_MSG_GATT_ATTR_READ_IND, + BTIF_MSG_GATT_ATTR_READ_CFM, + BTIF_MSG_GATT_ATTR_WRITE_REQ_IND, + BTIF_MSG_GATT_ATTR_WRITE_REQ_CFM, + BTIF_MSG_GATT_ATTR_PREP_WRITE_IND, + BTIF_MSG_GATT_ATTR_PREP_WRITE_CFM, + BTIF_MSG_GATT_ATTR_EXEC_WRITE_IND, + BTIF_MSG_GATT_ATTR_EXEC_WRITE_CFM, + BTIF_MSG_GATT_ATTR_WRITE_CMD_INFO,//0x110 + BTIF_MSG_GATT_ATTR_CCCD_INFO, + // client + BTIF_MSG_GATT_DISCOVERY_REQ, + BTIF_MSG_GATT_DISCOVERY_RSP, + BTIF_MSG_GATT_DISCOVERY_IND, + BTIF_MSG_GATT_DISCOVERY_CFM, + BTIF_MSG_GATT_ATTR_READ_REQ, + BTIF_MSG_GATT_ATTR_READ_RSP, + BTIF_MSG_GATT_ATTR_READ_MULTI_REQ, + BTIF_MSG_GATT_ATTR_READ_MULTI_RSP, + BTIF_MSG_GATT_ATTR_WRITE_REQ, + BTIF_MSG_GATT_ATTR_WRITE_RSP, + BTIF_MSG_GATT_ATTR_PREP_WRITE_REQ, + BTIF_MSG_GATT_ATTR_PREP_WRITE_RSP, + BTIF_MSG_GATT_ATTR_EXEC_WRITE_REQ, + BTIF_MSG_GATT_ATTR_EXEC_WRITE_RSP, + + BTIF_MSG_GATT_ATTR_IND,//0x120 + BTIF_MSG_GATT_ATTR_CFM, + BTIF_MSG_GATT_ATTR_NOTIF_INFO, + + // common + BTIF_MSG_GATT_SECURITY_REQ, + BTIF_MSG_GATT_SECURITY_RSP, + BTIF_MSG_GATT_SERVER_STORE_IND, + BTIF_MSG_GATT_SERVER_STORE_CFM, + BTIF_MSG_GATT_MTU_SIZE_INFO, + // end of GATT + + BTIF_MSG_LE_CONN_REQ, + BTIF_MSG_LE_CONN_RSP, + BTIF_MSG_LE_CONN_IND, + BTIF_MSG_LE_CONN_CFM, + BTIF_MSG_LE_CONN_CMPL_INFO, + BTIF_MSG_LE_DISCONN_REQ, + BTIF_MSG_LE_DISCONN_RSP, + BTIF_MSG_LE_DISCONN_IND, + BTIF_MSG_LE_DISCONN_CFM,//0x130 + + BTIF_MSG_LE_ADV_REQ, + BTIF_MSG_LE_ADV_RSP, + BTIF_MSG_LE_ADV_PARAM_SET_REQ, + BTIF_MSG_LE_ADV_PARAM_SET_RSP, + BTIF_MSG_LE_ADV_DATA_SET_REQ, + BTIF_MSG_LE_ADV_DATA_SET_RSP, + BTIF_MSG_LE_SCAN_REQ, + BTIF_MSG_LE_SCAN_RSP, + BTIF_MSG_LE_SCAN_PARAM_SET_REQ, + BTIF_MSG_LE_SCAN_PARAM_SET_RSP, + BTIF_MSG_LE_SCAN_INFO, + BTIF_MSG_LE_MODIFY_WHITE_LIST_REQ, + BTIF_MSG_LE_MODIFY_WHITE_LIST_RSP, + BTIF_MSG_LE_CONN_UPDATE_REQ, + BTIF_MSG_LE_CONN_UPDATE_RSP, + BTIF_MSG_LE_CONN_UPDATE_IND,//0x140 + BTIF_MSG_LE_CONN_UPDATE_CFM, + BTIF_MSG_LE_CONN_PARAM_INFO, + BTIF_MSG_LE_CONN_PARAM_REQ_EVT_INFO, + BTIF_MSG_LE_CONN_PARAM_REQ_REPLY_REQ, + BTIF_MSG_LE_CONN_PARAM_REQ_REPLY_RSP, + BTIF_MSG_LE_CONN_PARAM_REQ_NEG_REPLY_REQ, + BTIF_MSG_LE_CONN_PARAM_REQ_NEG_REPLY_RSP, + + BTIF_MSG_LE_CREDIT_BASED_CONN_REQ, + BTIF_MSG_LE_CREDIT_BASED_CONN_RSP, + BTIF_MSG_LE_CREDIT_BASED_CONN_IND, + BTIF_MSG_LE_CREDIT_BASED_CONN_CFM, + BTIF_MSG_LE_CREDIT_BASED_DISCONN_REQ, + BTIF_MSG_LE_CREDIT_BASED_DISCONN_RSP, + BTIF_MSG_LE_CREDIT_BASED_DISCONN_IND, + BTIF_MSG_LE_CREDIT_BASED_DISCONN_CFM, + BTIF_MSG_LE_SEND_CREDIT_REQ,//0x150 + BTIF_MSG_LE_SEND_CREDIT_RSP, + BTIF_MSG_LE_CREDIT_BASED_DATA_REQ, + BTIF_MSG_LE_CREDIT_BASED_DATA_RSP, + BTIF_MSG_LE_CREDIT_BASED_DATA_IND, + BTIF_MSG_LE_CREDIT_BASED_DATA_CFM, + BTIF_MSG_LE_CREDIT_BASED_CONN_CMPL_INFO, + BTIF_MSG_LE_CREDIT_BASED_CONN_CREDIT_INFO, + BTIF_MSG_LE_CREDIT_BASED_SECURITY_REG_REQ, + BTIF_MSG_LE_CREDIT_BASED_SECURITY_REG_RSP, + BTIF_MSG_LE_CREDIT_BASED_PSM_REG_REQ, + BTIF_MSG_LE_CREDIT_BASED_PSM_REG_RSP, + BTIF_MSG_LE_SET_CHANN_CLASSIF_REQ, + BTIF_MSG_LE_SET_CHANN_CLASSIF_RSP, + BTIF_MSG_LE_READ_CHANN_MAP_REQ, + BTIF_MSG_LE_READ_CHANN_MAP_RSP, + BTIF_MSG_LE_RECEIVER_TEST_REQ, + BTIF_MSG_LE_RECEIVER_TEST_RSP, + BTIF_MSG_LE_TRANSMITTER_TEST_REQ,//0x162 + BTIF_MSG_LE_TRANSMITTER_TEST_RSP, + BTIF_MSG_LE_TEST_END_REQ, + BTIF_MSG_LE_TEST_END_RSP, + BTIF_MSG_LE_READ_ADV_TX_POWER_REQ, + BTIF_MSG_LE_READ_ADV_TX_POWER_RSP, + BTIF_MSG_LE_SET_RAND_ADDR_REQ, + BTIF_MSG_LE_SET_RAND_ADDR_RSP, + BTIF_MSG_LE_READ_MAX_DATA_LEN_REQ, + BTIF_MSG_LE_READ_MAX_DATA_LEN_RSP, + BTIF_MSG_LE_READ_DEFAULT_DATA_LEN_REQ, + BTIF_MSG_LE_READ_DEFAULT_DATA_LEN_RSP, + BTIF_MSG_LE_WRITE_DEFAULT_DATA_LEN_REQ, + BTIF_MSG_LE_WRITE_DEFAULT_DATA_LEN_RSP, + BTIF_MSG_LE_SET_DATA_LEN_REQ,//0x172 + BTIF_MSG_LE_SET_DATA_LEN_RSP, + BTIF_MSG_LE_DATA_LEN_CHANGE_INFO, + BTIF_MSG_LE_MODIFY_RESOLV_LIST_REQ, + BTIF_MSG_LE_MODIFY_RESOLV_LIST_RSP, + BTIF_MSG_LE_READ_PEER_RESOLV_ADDR_REQ, + BTIF_MSG_LE_READ_PEER_RESOLV_ADDR_RSP, + BTIF_MSG_LE_READ_LOCAL_RESOLV_ADDR_REQ, + BTIF_MSG_LE_READ_LOCAL_RESOLV_ADDR_RSP, + BTIF_MSG_LE_SET_RESOLUTION_ENABLE_REQ, + BTIF_MSG_LE_SET_RESOLUTION_ENABLE_RSP, + BTIF_MSG_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ, + BTIF_MSG_LE_SET_RESOLV_PRIV_ADDR_TOUT_RSP, + BTIF_MSG_LE_CONFIG_LOCAL_IRK_REQ, + BTIF_MSG_LE_CONFIG_LOCAL_IRK_RSP, + BTIF_MSG_LE_SET_PRIVACY_MODE_REQ, + BTIF_MSG_LE_SET_PRIVACY_MODE_RSP,//0x182 + BTIF_MSG_LE_DIRECT_ADV_INFO, + BTIF_MSG_LE_HIGH_DUTY_ADV_TOUT_INFO, + + BTIF_MSG_LE_SET_ADV_SET_RAND_ADDR_REQ, + BTIF_MSG_LE_SET_ADV_SET_RAND_ADDR_RSP, + + BTIF_MSG_LE_EXT_ADV_PARAM_SET_REQ, + BTIF_MSG_LE_EXT_ADV_PARAM_SET_RSP, + BTIF_MSG_LE_EXT_ADV_DATA_SET_REQ, + BTIF_MSG_LE_EXT_ADV_DATA_SET_RSP, + BTIF_MSG_LE_EXT_ADV_ENABLE_REQ, + BTIF_MSG_LE_EXT_ADV_ENABLE_RSP, + + BTIF_MSG_LE_EXT_SCAN_PARAM_SET_REQ, + BTIF_MSG_LE_EXT_SCAN_PARAM_SET_RSP, + BTIF_MSG_LE_EXT_SCAN_REQ, + BTIF_MSG_LE_EXT_SCAN_RSP,//0x190 + + BTIF_MSG_LE_SET_DEFAULT_PHY_REQ, + BTIF_MSG_LE_SET_DEFAULT_PHY_RSP, + + BTIF_MSG_LE_SET_PHY_REQ, + BTIF_MSG_LE_SET_PHY_RSP, + + BTIF_MSG_LE_ENHANCED_RECEIVER_TEST_REQ, + BTIF_MSG_LE_ENHANCED_RECEIVER_TEST_RSP, + BTIF_MSG_LE_ENHANCED_TRANSMITTER_TEST_REQ, + BTIF_MSG_LE_ENHANCED_TRANSMITTER_TEST_RSP, + + BTIF_MSG_LE_MODIFY_PERIODIC_ADV_LIST_REQ, + BTIF_MSG_LE_MODIFY_PERIODIC_ADV_LIST_RSP, + + BTIF_MSG_LE_READ_RF_PATH_COMPENSATION_REQ, + BTIF_MSG_LE_READ_RF_PATH_COMPENSATION_RSP, + + BTIF_MSG_LE_WRITE_RF_PATH_COMPENSATION_REQ, + BTIF_MSG_LE_WRITE_RF_PATH_COMPENSATION_RSP, + + BTIF_MSG_LE_MODIFY_ADV_SET_REQ, + BTIF_MSG_LE_MODIFY_ADV_SET_RSP,//0x1A0 + + BTIF_MSG_LE_SET_PERIODIC_ADV_PARAM_REQ, + BTIF_MSG_LE_SET_PERIODIC_ADV_PARAM_RSP, + BTIF_MSG_LE_SET_PERIODIC_ADV_DATA_REQ, + BTIF_MSG_LE_SET_PERIODIC_ADV_DATA_RSP, + BTIF_MSG_LE_SET_PERIODIC_ADV_ENABLE_REQ, + BTIF_MSG_LE_SET_PERIODIC_ADV_ENABLE_RSP, + BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_REQ, + BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_RSP, + BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_REQ, + BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_RSP, + BTIF_MSG_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ, + BTIF_MSG_LE_PERIODIC_ADV_TERMINATE_SYNC_RSP, + + BTIF_MSG_LE_PHY_UPDATE_INFO, + BTIF_MSG_LE_EXT_ADV_REPORT_INFO, + BTIF_MSG_LE_PERIODIC_ADV_SYNC_ESTABLISHED_INFO, + BTIF_MSG_LE_PERIODIC_ADV_REPORT_INFO,//0x1B0 + BTIF_MSG_LE_PERIODIC_ADV_SYNC_LOST_INFO, + BTIF_MSG_LE_SCAN_TIMEOUT_INFO, + BTIF_MSG_LE_ADV_SET_TERMINATED_INFO, + BTIF_MSG_LE_SCAN_REQ_RECEIVED_INFO, + BTIF_MSG_LE_LOCAL_DEV_INFO, + BTIF_MSG_LE_ENABLE_EXT_ADV_MODE_REQ, + BTIF_MSG_LE_ENABLE_EXT_ADV_MODE_RSP, + BTIF_MSG_LE_REMOTE_FEATS_INFO, + BTIF_MSG_GATT_ATTR_WRITE_CMD_SIGNED_INFO, + BTIF_MSG_LE_SIGNED_STATUS_INFO, + + BTIF_MSG_JUST_WORK_REQ_IND, + BTIF_MSG_JUST_WORK_REQ_CFM, + + BTIF_MSG_USER_PASSKEY_NOTIF_IND, + BTIF_MSG_USER_PASSKEY_NOTIF_CFM, + + BTIF_MSG_GATT_SRV2_REG_REQ, + + BTIF_MSG_LE_SET_SUPPL_TEST_PARAMS_REQ = 0x0300, + BTIF_MSG_LE_SET_SUPPL_TEST_PARAMS_RSP, + BTIF_MSG_LE_SET_CONNLESS_SUPPL_TRANSMIT_PARAMS_REQ, + BTIF_MSG_LE_SET_CONNLESS_SUPPL_TRANSMIT_PARAMS_RSP, + BTIF_MSG_LE_SET_CONNLESS_SUPPL_TRANSMIT_ENABLE_REQ, + BTIF_MSG_LE_SET_CONNLESS_SUPPL_TRANSMIT_ENABLE_RSP, + BTIF_MSG_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE_REQ, + BTIF_MSG_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE_RSP, + BTIF_MSG_LE_SET_CONN_SUPPL_PARAMS_REQ, + BTIF_MSG_LE_SET_CONN_SUPPL_PARAMS_RSP, + BTIF_MSG_LE_CONN_SUPPL_REQUEST_ENABLE_REQ, + BTIF_MSG_LE_CONN_SUPPL_REQUEST_ENABLE_RSP, + BTIF_MSG_LE_CONN_SUPPL_RESPONSE_ENABLE_REQ, + BTIF_MSG_LE_CONN_SUPPL_RESPONSE_ENABLE_RSP, + BTIF_MSG_LE_READ_ANTENNA_INFORMATION_REQ, + BTIF_MSG_LE_READ_ANTENNA_INFORMATION_RSP, + + BTIF_MSG_LE_CONNLESS_IQ_REPORT_INFO, + BTIF_MSG_LE_CONN_IQ_REPORT_INFO, + BTIF_MSG_LE_SUPPL_REQUEST_FAILED_INFO, + + BTIF_MSG_RADIO_MODE_SET_REQ = 0x1000, + BTIF_MSG_RADIO_MODE_SET_RSP, /**< Response of setting radio mode. */ + + BTIF_MSG_INQUIRY_REQ, + BTIF_MSG_INQUIRY_RSP, /**< Response of starting inquiry. */ + BTIF_MSG_INQUIRY_RESULT_INFO, /**< Information of device found during inquiry. */ + BTIF_MSG_INQUIRY_CMPL_INFO, /**< Information of inquiry complete. */ + BTIF_MSG_INQUIRY_CANCEL_REQ, + BTIF_MSG_INQUIRY_CANCEL_RSP, /**< Response of canceling inquiry. */ + + BTIF_MSG_REMOTE_NAME_REQ, + BTIF_MSG_REMOTE_NAME_RSP, /**< Response of getting remote name. */ + + BTIF_MSG_SDP_DISCOV_REQ, + BTIF_MSG_SDP_DISCOV_RSP, /**< Response of starting SDP discovery. */ + BTIF_MSG_SDP_ATTR_IND, /**< Indication of attributes found during SDP discovery. */ + BTIF_MSG_SDP_ATTR_CFM, + BTIF_MSG_DID_ATTR_IND, /**< Indication of attributes found during DID discovery. */ + BTIF_MSG_DID_ATTR_CFM, + BTIF_MSG_SDP_DISCOV_CMPL_INFO, /**< Information of SDP discovery complete. */ + BTIF_MSG_STOP_SDP_DISCOV_REQ, + BTIF_MSG_STOP_SDP_DISCOV_RSP, /**< Response of stopping SDP discovery. */ + + BTIF_MSG_AUTHEN_REQ, + BTIF_MSG_AUTHEN_RSP, /**< Response of BR/EDR authentication. */ + BTIF_MSG_AUTHOR_REQ_IND, /**< Indication of authorization. */ + BTIF_MSG_AUTHOR_REQ_CFM, + BTIF_MSG_PIN_CODE_REQ_IND, /**< Indication of PIN code request. */ + BTIF_MSG_PIN_CODE_REQ_CFM, + BTIF_MSG_LEGACY_REMOTE_OOB_REQ_IND, /**< Indication of legacy remote OOB data request. */ + BTIF_MSG_LEGACY_REMOTE_OOB_REQ_CFM, + BTIF_MSG_LOCAL_OOB_REQ, + BTIF_MSG_LOCAL_OOB_RSP, /**< Response of getting local OOB data. */ + + BTIF_MSG_ACL_CFG_REQ, + BTIF_MSG_ACL_CFG_RSP, /**< Response of configuring ACL link. */ + + BTIF_MSG_SDP_REG_REQ, + BTIF_MSG_SDP_REG_RSP, /**< Response of registering SDP record to Bluetooth stack. */ + BTIF_MSG_L2C_PROTO_REG_REQ, + BTIF_MSG_L2C_PROTO_REG_RSP, /**< Response of registering protocol over L2CAP. */ + BTIF_MSG_L2C_CONN_REQ, + BTIF_MSG_L2C_CONN_RSP, /**< Response of L2CAP connection request. */ + BTIF_MSG_L2C_CONN_IND, /**< Indication of L2CAP connection request from remote device. */ + BTIF_MSG_L2C_CONN_CFM, + BTIF_MSG_L2C_CONN_CMPL_INFO, /**< Information of L2CAP channel establish result. */ + BTIF_MSG_L2C_DATA_REQ, + BTIF_MSG_L2C_DATA_RSP, /**< Response of L2CAP data. */ + BTIF_MSG_L2C_DATA_IND, /**< Indication of received L2CAP data from remote device. */ + BTIF_MSG_L2C_DATA_CFM, + BTIF_MSG_L2C_DISCONN_REQ, + BTIF_MSG_L2C_DISCONN_RSP, /**< Response of disconnecting L2CAP channel. */ + BTIF_MSG_L2C_DISCONN_IND, /**< Indication of L2CAP disconnection from remote device. */ + BTIF_MSG_L2C_DISCONN_CFM, + BTIF_MSG_L2C_SET_LOCAL_BUSY_REQ, + BTIF_MSG_L2C_SET_LOCAL_BUSY_RSP, /**< Response of setting local busy state in ERTM mode. */ + + BTIF_MSG_L2C_SEC_REG_REQ, + BTIF_MSG_L2C_SEC_REG_RSP, /**< Response of registering L2CAP security entry. */ + BTIF_MSG_RFC_AUTHEN_REQ, + BTIF_MSG_RFC_AUTHEN_RSP, /**< Response of authencation over RFCOMM channel. */ + + BTIF_MSG_SCO_CONN_REQ, + BTIF_MSG_SCO_CONN_RSP, /**< Response of creating SCO/eSCO connection. */ + BTIF_MSG_SCO_CONN_IND, /**< Indication of SCO/eSCO connection request from remote device. */ + BTIF_MSG_SCO_CONN_CFM, + BTIF_MSG_SCO_CONN_CMPL_INFO, /**< Information of SCO/eSCO connection establish result. */ + BTIF_MSG_SCO_DATA_REQ, + BTIF_MSG_SCO_DATA_RSP, /**< Response of setting SCO data to remote device. */ + BTIF_MSG_SCO_DATA_IND, /**< Indication of SCO data received from remote device. */ + BTIF_MSG_SCO_DATA_CFM, + BTIF_MSG_SCO_DISCONN_REQ, + BTIF_MSG_SCO_DISCONN_RSP, /**< Response of disconnecting SCO/eSCO link. */ + BTIF_MSG_SCO_DISCONN_IND, /**< Indication of SCO/eSCO disconnection from remote device. */ + BTIF_MSG_SCO_DISCONN_CFM, + + BTIF_MSG_ACL_DISCONN_REQ, + BTIF_MSG_ACL_DISCONN_RSP, /**< Response of disconnecting ACL link. */ + + BTIF_MSG_SETUP_QOS_REQ, + BTIF_MSG_SETUP_QOS_RSP, /**< Response of setting QOS for an ACL link. */ + + /*connectionless slave broadcast*/ + BTIF_MSG_LT_ADDR_SET_REQ, + BTIF_MSG_LT_ADDR_SET_RSP, + BTIF_MSG_LT_ADDR_DEL_REQ, + BTIF_MSG_LT_ADDR_DEL_RSP, + BTIF_MSG_SYNC_TRAIN_PARAM_SET_REQ, + BTIF_MSG_SYNC_TRAIN_PARAM_SET_RSP, + BTIF_MSG_SYNC_TRAIN_REQ, + BTIF_MSG_SYNC_TRAIN_RSP, + BTIF_MSG_SYNC_TRAIN_CMPL_INFO, + BTIF_MSG_SYNC_TRAIN_RCV_REQ, + BTIF_MSG_SYNC_TRAIN_RCV_RSP, + BTIF_MSG_SYNC_TRAIN_RCV_CMPL_INFO, + BTIF_MSG_CSB_SET_REQ, + BTIF_MSG_CSB_SET_RSP, + BTIF_MSG_CSB_RCV_SET_REQ, + BTIF_MSG_CSB_RCV_SET_RSP, + BTIF_MSG_CSB_TOUT_INFO, + BTIF_MSG_CSB_DATA_REQ, + BTIF_MSG_CSB_DATA_RSP, + BTIF_MSG_CSB_DATA_IND, + BTIF_MSG_CSB_DATA_CFM, + + BTIF_MSG_IDLE, +} T_BTIF_MSG_TYPE; + +/** + * btif.h + * + * \brief Response of registering callback function. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_REGISTER_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint32_t version; /**< Bluetooth stack software version. */ + uint16_t cause; /**< Result of register callback function. */ +} T_BTIF_REGISTER_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_RELEASE_RSP; + +/** + * btif.h + * + * \brief Local device information. It will be received in the callback function + * registered by \ref btif_register_req with message type as \ref + * BTIF_MSG_ACT_INFO. This message will be received right after register + * response \ref BTIF_MSG_REGISTER_RSP if register successfully. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t local_addr[6]; /**< Local bluetooth address. */ + uint16_t cause; /**< Result of bluetooth stack initialization. */ +} T_BTIF_ACT_INFO; + +/** + * btif.h + * + * \brief Response of configuring local device. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_DEV_CFG_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + T_BTIF_DEV_CFG_OPCODE op; /**< Operation code for device configuration. */ + uint16_t cause; /**< Device configuration result. */ +} T_BTIF_DEV_CFG_RSP; + +/** + * btif.h + * + * \brief ACL status information. It will be received in the callback function + * registered by \ref btif_register_req with message type as \ref + * BTIF_MSG_ACL_STATUS_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + T_BTIF_ACL_STATUS status; /**< ACL status information type. */ + T_BTIF_ACL_STATUS_PARAM p; /**< ACL status information parameter. */ +} T_BTIF_ACL_STATUS_INFO; + +/** + * btif.h + * + * \brief Response of setting link proirity. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_ACL_PRIORITY_SET_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + uint8_t conn_type; /**< Connection type, 0:BR/EDR ACL link, + 1:SCO/ESCO link, 2:LE link. */ + bool is_high_priority; /**< Set the link to high priority or not. */ + uint16_t cause; /**< Result of setting priority of the link. */ +} T_BTIF_ACL_PRIORITY_SET_RSP; + +/** + * btif.h + * + * \brief Response of reading RSSI. It will be received in the callback function + * registered by \ref btif_register_req with message type as \ref BTIF_MSG_READ_RSSI_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + uint16_t cause; /**< Result of reading RSSI. */ + int8_t rssi; /**< RSSI value read if success. */ +} T_BTIF_READ_RSSI_RSP; + +/** + * btif.h + * + * \brief Response of vendor command. It will be received in the callback function + * registered by \ref btif_register_req with message type as \ref BTIF_MSG_VENDOR_CMD_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t command; /**< Vendor command. Shoule be the same as that in request. */ + uint16_t cause; /**< Result of executing command. */ + bool is_cmpl_evt; /**< Whether the response is generated from command complete event. */ + uint8_t param_len; /**< Response parameter length. */ + uint8_t param[1]; /**< Response parameter buffer. */ +} T_BTIF_VENDOR_CMD_RSP; + +/** + * btif.h + * + * \brief Vendor event infomation. It will be received in the callback function + * registered by \ref btif_register_req with message type as \ref BTIF_MSG_VENDOR_EVT_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t param_len; /**< Information parameter length. */ + uint8_t param[1]; /**< Information parameter buffer. */ +} T_BTIF_VENDOR_EVT_INFO; + +/** + * btif.h + * + * \brief Response of setting pairable mode. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_PAIRABLE_MODE_SET_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of set pairable mode. */ +} T_BTIF_PAIRABLE_MODE_SET_RSP; + +/** + * btif.h + * + * \brief Indication to request user to input passkey. It will be received in + * the callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_USER_PASSKEY_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + bool key_press; /**< Whether keypress is needed. */ +} T_BTIF_USER_PASSKEY_REQ_IND; + +/** + * btif.h + * + * \brief Response of user passkey request reply. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_USER_PASSKEY_REQ_REPLY_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of user passkey request reply. */ +} T_BTIF_USER_PASSKEY_REQ_REPLY_RSP; + +/** + * btif.h + * + * \brief Information of user passkey notification. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_USER_PASSKEY_NOTIF_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + uint32_t display_value; /**< Passkey value. */ +} T_BTIF_USER_PASSKEY_NOTIF_INFO; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint32_t display_value; +} T_BTIF_USER_PASSKEY_NOTIF_IND; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; +} T_BTIF_JUST_WORK_REQ_IND; + +/** + * btif.h + * + * \brief Indication of authentication result. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_AUTHEN_RESULT_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + uint8_t key_len; /**< Key length. */ + T_BTIF_KEY_TYPE key_type; /**< Key type. */ + uint8_t link_key[28]; /**< Key value. */ + uint16_t cause; /**< Authentication result. */ +} T_BTIF_AUTHEN_RESULT_IND; + +/** + * btif.h + * + * \brief Indication to request key during authentication. It will be received + * in the callback function registered by \ref btif_register_req with + * message type as \ref BTIF_MSG_AUTHEN_KEY_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + T_BTIF_KEY_TYPE key_type; /**< Requested Key type. */ +} T_BTIF_AUTHEN_KEY_REQ_IND; + +/** + * btif.h + * + * \brief Indication to request user confirmation when pairing. It will be received + * in the callback function registered by \ref btif_register_req with + * message type as \ref BTIF_MSG_USER_CFM_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + uint32_t display_value; /**< Numeric value to be displayed. */ +} T_BTIF_USER_CFM_REQ_IND; + +/** + * btif.h + * + * \brief Response of keypress notification request. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_KEYPRESS_NOTIF_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Keypress notification result. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ +} T_BTIF_KEYPRESS_NOTIF_RSP; + +/** + * btif.h + * + * \brief Information of remote keypress notification. It will be received in + * the callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_KEYPRESS_NOTIF_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; /**< Address type of remote device. */ + T_BTIF_KEYPRESS_NOTIF_TYPE event_type; /**< Keypress notification type. */ +} T_BTIF_KEYPRESS_NOTIF_INFO; + +/** + * btif.h + * + * \brief Information of hardware error. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_HW_ERROR_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t hw_code; /**< Hardware error code. */ +} T_BTIF_HW_ERROR_INFO; + +/** + * btif.h + * + * \brief Indication to request remote LE OOB data. It will be received in + * the callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_REMOTE_OOB_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + T_BTIF_REMOTE_ADDR_TYPE addr_type; /**< Address type of remote device */ +} T_BTIF_REMOTE_OOB_REQ_IND; + +typedef struct +{ + void *p_srv_handle; + uint16_t cause; +} T_BTIF_GATT_SRV_REG_RSP; + +typedef struct +{ + void *p_srv_handle; + void *p_req_handle; + uint16_t link_id; + uint16_t attr_index; + uint16_t cause; +} T_BTIF_GATT_ATTR_UPDATE_RSP; + +typedef struct +{ + void *p_srv_handle; + void *p_req_handle; + uint16_t link_id; + uint16_t attr_index; + uint16_t cause; + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; +} T_BTIF_GATT_ATTR_UPDATE_STATUS_IND; + +typedef struct +{ + uint16_t link_id; + void *p_srv_handle; + uint16_t attr_index; + uint16_t read_offset; +} T_BTIF_GATT_ATTR_READ_IND; + +typedef struct +{ + uint16_t link_id; + void *p_srv_handle; + uint16_t attr_index; + uint16_t attr_len; + uint16_t handle; + uint16_t write_offset; + uint16_t gap; + uint8_t data[1]; +} T_BTIF_GATT_ATTR_WRITE_IND; + +typedef struct +{ + uint16_t link_id; + uint8_t flags; /**< 0x00-Cancel all writes, 0x01-write all values */ +} T_BTIF_GATT_ATTR_EXEC_WRITE_IND; + +typedef struct +{ + uint16_t link_id; + void *p_srv_handle; + uint16_t count; /**< nbr. of attr_index/CCCD value pairs */ + uint16_t gap; /**< offset of first pair in data[] */ + uint8_t data[1]; +} T_BTIF_GATT_ATTR_CCCD_INFO; + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_DISCOVERY_TYPE type; + uint16_t cause; +} T_BTIF_GATT_DISCOVERY_RSP; + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_DISCOVERY_TYPE type; + uint16_t cause; + uint16_t elem_cnt; + uint16_t elem_len; + uint16_t gap; + uint8_t list[1]; +} T_BTIF_GATT_DISCOVERY_IND; + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_READ_TYPE read_type; + uint16_t cause; + uint16_t read_offset; + uint16_t total_len; + uint16_t attr_len; + uint16_t num_handle; + uint16_t gap; + uint8_t handles[1]; +} T_BTIF_GATT_ATTR_READ_RSP; + +#if F_BT_LE_ATT_READ_MULTI_SUPPORT +typedef struct +{ + uint16_t link_id; /**< local link ID. */ + uint16_t cause; /**< More detailed result information. */ + uint16_t total_len; /**< Total number of bytes stored in the value[] array. */ + uint16_t gap; /**< offset of first handle in value[] */ + uint8_t value[1]; /**< Array of attribute values read. */ +} T_BTIF_GATT_ATTR_READ_MULTI_RSP; +#endif + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_WRITE_TYPE write_type; + uint16_t attr_handle; + uint16_t cause; + uint16_t attr_len; /**< attrib. value length */ + uint16_t gap; /**< offset of attrib. value in data[] */ + uint8_t data[1]; +} T_BTIF_GATT_ATTR_WRITE_RSP; + +typedef struct +{ + uint16_t link_id; /**< local link ID. */ + uint16_t cause; /**< More detailed result information. */ + uint16_t write_offset; /**< The offset of the first octet to be written. */ + uint16_t attr_len; /**< attrib. value length. */ + uint16_t gap; /**< offset of attrib. value in data[]. */ + uint8_t data[1]; /**< attrib. value in data[]. */ +} T_BTIF_GATT_ATTR_PREP_WRITE_RSP; + +typedef struct +{ + uint16_t link_id; /**< local link ID. */ + uint16_t cause; /**< More detailed result information. */ +} T_BTIF_GATT_ATTR_EXEC_WRITE_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t attr_handle; + uint16_t attr_len; /**< attrib. value length */ + uint16_t gap; /**< offset of attrib. value in data[] */ + uint8_t data[1]; +} T_BTIF_GATT_ATTR_IND; + +typedef T_BTIF_GATT_ATTR_IND T_BTIF_GATT_ATTR_NOTIF_INFO; + +typedef struct +{ + uint16_t link_id; + T_BTIF_KEY_TYPE key_type; + uint8_t key_size; + uint16_t cause; +} T_BTIF_GATT_SECURITY_RSP; + +typedef struct +{ + T_BTIF_GATT_STORE_OPCODE op; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint8_t bd_addr[6]; + uint8_t data_len; + uint8_t *p_data; +} T_BTIF_GATT_SERVER_STORE_IND; + +typedef struct +{ + uint16_t link_id; + uint16_t mtu_size; +} T_BTIF_GATT_MTU_SIZE_INFO; + +typedef struct +{ + uint16_t link_id; + uint16_t cause; + bool update_local; + uint32_t local_sign_count; + uint32_t remote_sign_count; +} T_BTIF_LE_SIGNED_STATUS_INFO; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint16_t link_id; + uint16_t cause; +} T_BTIF_LE_CONN_RSP; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; +} T_BTIF_LE_CONN_IND; + +typedef struct +{ + uint16_t cause; + uint16_t link_id; + uint16_t mtu_size; + uint8_t ds_credits; + T_BTIF_LOCAL_ADDR_TYPE own_addr_type; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint8_t bd_addr[6]; + uint16_t interval; + uint16_t latency; + uint16_t supv_tout; + T_BTIF_LE_PHY_TYPE tx_phy; + T_BTIF_LE_PHY_TYPE rx_phy; + uint8_t csa; +} T_BTIF_LE_CONN_CMPL_INFO; + +#if F_BT_LE_READ_REMOTE_FEATS +typedef struct +{ + uint16_t cause; + uint16_t link_id; + uint8_t remote_feats[8]; +} T_BTIF_LE_REMOTE_FEATS_INFO; +#endif + +typedef struct +{ + uint16_t link_id; + uint16_t cause; + uint16_t reason; +} T_BTIF_LE_DISCONN_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t cause; +} T_BTIF_LE_DISCONN_IND; + +typedef struct +{ + T_BTIF_LE_ADV_MODE adv_mode; + uint16_t cause; +} T_BTIF_LE_ADV_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_ADV_PARAM_SET_RSP; + +typedef struct +{ + T_BTIF_LE_ADV_DATA_TYPE data_type; + uint16_t cause; +} T_BTIF_LE_ADV_DATA_SET_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SCAN_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SCAN_PARAM_SET_RSP; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_LE_ADV_EVT_TYPE adv_type; + int8_t rssi; + uint8_t data_len; + uint8_t data[31]; +} T_BTIF_LE_SCAN_INFO; + +typedef struct +{ + T_BTIF_LE_WHITE_LIST_OP operation; + uint16_t cause; +} T_BTIF_LE_MODIFY_WHITE_LIST_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t cause; +} T_BTIF_LE_CONN_UPDATE_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t supv_tout; +} T_BTIF_LE_CONN_UPDATE_IND; + +typedef struct +{ + uint16_t link_id; + uint16_t interval; + uint16_t latency; + uint16_t supv_tout; +} T_BTIF_LE_CONN_PARAM_INFO; + +typedef struct +{ + uint16_t link_id; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t supv_tout; +} T_BTIF_LE_CONN_PARAM_REQ_EVT_INFO; + +typedef struct +{ + uint16_t cause; + uint16_t link_id; +} T_BTIF_LE_CONN_PARAM_REQ_REPLY_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t link_id; +} T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t cause; +} T_BTIF_LE_CREDIT_BASED_CONN_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; +} T_BTIF_LE_CREDIT_BASED_CONN_IND; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t cause; +} T_BTIF_LE_CREDIT_BASED_DISCONN_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t cause; +} T_BTIF_LE_CREDIT_BASED_DISCONN_IND; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t cause; +} T_BTIF_LE_SEND_CREDIT_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t cause; +} T_BTIF_LE_CREDIT_BASED_DATA_RSP; + +typedef struct +{ + uint16_t link_id; /**< local link ID. */ + uint16_t channel; /**< channel ID */ + uint16_t value_len; /**< value length */ + uint16_t gap; /**< offset of value in data[]. */ + uint8_t data[1]; /**< value. */ +} T_BTIF_LE_CREDIT_BASED_DATA_IND; + +typedef struct +{ + uint16_t cause; + uint16_t link_id; /**< local link ID. */ + uint16_t channel; /**< channel ID */ + uint16_t remote_mtu; /**< remote Maximum Transmission Unit */ + uint16_t remote_credits; /**< remote initial credits*/ + uint16_t max_ds_credits; /**< max downstream credits */ +} T_BTIF_LE_CREDIT_BASED_CONN_CMPL_INFO; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; +} T_BTIF_LE_CREDIT_BASED_CONN_CREDIT_INFO; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_CREDIT_BASED_SECURITY_REG_RSP; + +typedef struct +{ + uint16_t le_psm; + uint16_t cause; +} T_BTIF_LE_CREDIT_BASED_PSM_REG_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_CHANN_CLASSIF_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t cause; + uint8_t chann_map[5]; +} T_BTIF_LE_READ_CHANN_MAP_RSP; +#if F_BT_LE_4_0_DTM_SUPPORT +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_RECEIVER_TEST_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_TRANSMITTER_TEST_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t num_pkts; +} T_BTIF_LE_TEST_END_RSP; +#endif +typedef struct +{ + uint16_t cause; + uint8_t tx_power_level; +} T_BTIF_LE_READ_ADV_TX_POWER_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_RAND_ADDR_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t max_tx_oct; + uint16_t max_tx_time; + uint16_t max_rx_oct; + uint16_t max_rx_time; +} T_BTIF_LE_READ_MAX_DATA_LEN_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t max_tx_oct; + uint16_t max_tx_time; +} T_BTIF_LE_READ_DEFAULT_DATA_LEN_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t link_id; +} T_BTIF_LE_SET_DATA_LEN_RSP; + +typedef struct +{ + uint16_t link_id; + uint16_t max_tx_oct; + uint16_t max_tx_time; + uint16_t max_rx_oct; + uint16_t max_rx_time; +} T_BTIF_LE_DATA_LEN_CHANGE_INFO; + +typedef struct +{ + T_BTIF_LE_RESOLVING_LIST_OP operation; + uint16_t cause; +} T_BTIF_LE_MODIFY_RESOLV_LIST_RSP; + +typedef struct +{ + uint16_t cause; + uint8_t peer_resolv_addr[6]; +} T_BTIF_LE_READ_PEER_RESOLV_ADDR_RSP; + +typedef struct +{ + uint16_t cause; + uint8_t local_resolv_addr[6]; +} T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_RESOLUTION_ENABLE_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_RSP; + +//#if F_BT_LE_LOCAL_IRK_SETTING_SUPPORT +typedef struct +{ + uint16_t cause; + bool generate; + uint8_t local_irk[16]; +} T_BTIF_LE_CONFIG_LOCAL_IRK_RSP; +//#endif + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_PRIVACY_MODE_RSP; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint8_t direct_bd_addr[6]; + T_BTIF_DIRECT_ADDR_TYPE direct_addr_type; + T_BTIF_LE_DIRECT_ADV_EVT_TYPE direct_adv_type; + int8_t rssi; +} T_BTIF_LE_DIRECT_ADV_INFO; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_HIGH_DUTY_ADV_TIMEOUT_INFO; + +#if F_BT_LE_5_0_SUPPORT + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +typedef struct +{ + uint16_t cause; + uint8_t adv_handle; + uint8_t rand_addr[6]; +} T_BTIF_LE_SET_ADV_SET_RAND_ADDR_RSP; + +typedef struct +{ + int8_t selected_tx_power; + uint16_t cause; +} T_BTIF_LE_EXT_ADV_PARAM_SET_RSP; + +typedef struct +{ + T_BTIF_LE_EXT_ADV_DATA_TYPE data_type; + uint16_t cause; +} T_BTIF_LE_EXT_ADV_DATA_SET_RSP; + +typedef struct +{ + T_BTIF_LE_EXT_ADV_MODE mode; + uint16_t cause; +} T_BTIF_LE_EXT_ADV_ENABLE_RSP; +#endif + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_EXT_SCAN_PARAM_SET_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_EXT_SCAN_RSP; +#endif + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_DEFAULT_PHY_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t link_id; +} T_BTIF_LE_SET_PHY_RSP; +#endif + +#if F_BT_LE_5_0_DTM_SUPPORT +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_ENHANCED_RECEIVER_TEST_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_RSP; +#endif +typedef struct +{ + T_BTIF_LE_PERIODIC_ADV_LIST_OP op; + uint16_t cause; +} T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_RSP; + +typedef struct +{ + uint16_t cause; + int8_t rf_tx_path_compensation; + int8_t rf_rx_path_compensation; +} T_BTIF_LE_READ_RF_PATH_COMPENSATION_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_RSP; + +typedef struct +{ + T_BTIF_LE_ADV_SET_OP op; + uint16_t cause; +} T_BTIF_LE_MODIFY_ADV_SET_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_PERIODIC_ADV_PARAM_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_PERIODIC_ADV_DATA_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_RSP; + +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +typedef struct +{ + uint16_t cause; + uint16_t link_id; + T_BTIF_LE_PHY_TYPE tx_phy; + T_BTIF_LE_PHY_TYPE rx_phy; +} T_BTIF_LE_PHY_UPDATE_INFO; +#endif +typedef enum +{ + BTIF_ADV_EVENT_TYPE_DATA_STATUS_COMPLETE = 0x00, + BTIF_ADV_EVENT_TYPE_DATA_STATUS_MORE = 0x01, + BTIF_ADV_EVENT_TYPE_DATA_STATUS_TRUNCATED = 0x02, + BTIF_ADV_EVENT_TYPE_DATA_STATUS_RFU = 0x03 +} T_BTIF_EXT_ADV_EVT_TYPE_DATA_STATUS; + +typedef struct +{ + uint16_t event_type; + T_BTIF_EXT_ADV_EVT_TYPE_DATA_STATUS data_status; + T_BTIF_REMOTE_ADDR_TYPE addr_type; + uint8_t bd_addr[6]; + T_BTIF_LE_PRIM_ADV_PHY_TYPE primary_phy; + uint8_t secondary_phy; + uint8_t adv_sid; + int8_t tx_power; + int8_t rssi; + uint16_t peri_adv_interval; + T_BTIF_DIRECT_ADDR_TYPE direct_addr_type; + uint8_t direct_addr[6]; + uint8_t data_len; + uint8_t *p_data; //max 229 bytes +} T_BTIF_LE_EXT_ADV_REPORT_INFO; + +typedef struct +{ + uint16_t cause; + uint8_t sync_handle; + uint8_t advertising_sid; + uint8_t advertiser_address_type; + uint8_t advertiser_address[6]; + T_BTIF_LE_PHY_TYPE advertiser_phy; + uint8_t periodic_advertising_interval; + uint8_t advertiser_clock_accuracy; +} T_BTIF_LE_PERIODIC_ADV_SYNC_ESTABLISHED_INFO; + +typedef struct +{ + uint16_t sync_handle; + int8_t tx_power; + int8_t rssi; + uint8_t rfu; + uint8_t data_status; + uint8_t data_len; + uint8_t *p_data; +} T_BTIF_LE_PERIODIC_ADV_REPORT_INFO; + +typedef struct +{ + uint8_t sync_handle; +} T_BTIF_LE_PERIODIC_ADV_SYNC_LOST_INFO; + +typedef struct +{ + uint16_t cause; + uint8_t adv_handle; + uint16_t conn_handle; + uint8_t num_cmpl_ext_adv_evt; +} T_BTIF_LE_ADV_SET_TERMINATED_INFO; + +typedef struct +{ + uint8_t adv_handle; + uint8_t scanner_addr_type; + uint8_t scanner_addr[6]; +} T_BTIF_LE_SCAN_REQ_RECEIVED_INFO; + +typedef struct +{ + uint16_t cause; + uint16_t le_max_ext_adv_len; + uint8_t le_max_num_of_adv_sets; + uint8_t le_periodic_adv_list_size; +} T_BTIF_LE_ENABLE_EXT_ADV_MODE_RSP; +#endif +typedef struct +{ + uint8_t le_local_feats[8]; + uint16_t le_ds_pool_id; + uint16_t le_ds_data_offset; + uint8_t le_ds_credits; + uint8_t le_max_wl_size; + uint8_t le_resolvable_list_size; + int8_t le_min_tx_power; + int8_t le_max_tx_power; +} T_BTIF_LE_LOCAL_DEV_INFO; + +/** + * btif.h + * + * \brief Response of setting radio mode. It will be received in the callback + * function registered by \ref btif_register_req with message type + * as \ref BTIF_MSG_RADIO_MODE_SET_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of set radio mode */ +} T_BTIF_RADIO_MODE_SET_RSP; + +/** + * btif.h + * + * \brief Response of starting inquiry. It will be received in the callback + * function registered by \ref btif_register_req with message type + * as \ref BTIF_MSG_INQUIRY_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of start inquiry */ +} T_BTIF_INQUIRY_RSP; + +/** + * btif.h + * + * \brief Information of devices which is found duing inquiry. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_INQUIRY_RESULT_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of device found when inquiry */ + uint32_t cod; /**< Class of device of device found when inquiry */ + int8_t rssi; /**< RSSI of device found when inquiry */ + uint8_t name[BTIF_NAME_LENGTH]; /**< Name of device found when inquiry */ +} T_BTIF_INQUIRY_RESULT_INFO; + +/** + * btif.h + * + * \brief Information of inquiry procedure complete. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_INQUIRY_CMPL_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Status of inquiry procedure */ +} T_BTIF_INQUIRY_CMPL_INFO; + +/** + * btif.h + * + * \brief Response of canceling inquiry. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_INQUIRY_CANCEL_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of cancel inquiry */ +} T_BTIF_INQUIRY_CANCEL_RSP; + +/** + * btif.h + * + * \brief Response of getting name of remote device. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_REMOTE_NAME_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of getting remote device's name */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint8_t name[BTIF_NAME_LENGTH]; /**< Name of remote device */ +} T_BTIF_REMOTE_NAME_RSP; + +/** + * btif.h + * + * \brief Response of starting SDP discovery. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_SDP_DISCOV_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint16_t cause; /**< Result of starting SDP discovery */ +} T_BTIF_SDP_DISCOV_RSP; + +/** + * btif.h + * + * \brief Indication of attributes found during SDP discovery. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SDP_ATTR_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint8_t server_channel; /**< Server channel number */ + uint8_t supported_repos; /**< Supported repositories */ + uint16_t l2c_psm; /**< L2CAP PSM value */ + T_BTIF_UUID_TYPE srv_class_uuid_type; /**< Service class UUID type */ + T_BTIF_UUID_DATA srv_class_uuid_data; /**< Service class UUID data */ + uint16_t remote_version; /**< Remote profile version */ + uint16_t supported_feat; /**< Supported features */ + uint8_t *p_ext_data; /**< Address of extra data if used */ +} T_BTIF_SDP_ATTR_IND; + +/** + * btif.h + * + * \brief Indication of DID information found during SDP discovery. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_DID_ATTR_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t specific_id; /**< Specific ID of remote device */ + uint16_t vendor_id; /**< Vendor ID of remote device */ + uint16_t vendor_src; /**< Verndor source of remote device */ + uint16_t product_id; /**< Product ID of remote device */ + uint16_t version; /**< Version of remote device */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ +} T_BTIF_DID_ATTR_IND; + +/** + * btif.h + * + * \brief Information of SDP discovery complete. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_SDP_DISCOV_CMPL_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint16_t cause; /**< Status of SDP discovery procedure */ +} T_BTIF_SDP_DISCOV_CMPL_INFO; + +/** + * btif.h + * + * \brief Response of stopping SDP discovery. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_STOP_SDP_DISCOV_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint16_t cause; /**< Result of stop SDP discovey */ +} T_BTIF_STOP_SDP_DISCOV_RSP; + +/** + * btif.h + * + * \brief Response of BR/EDR authentication request. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_AUTHEN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint16_t cause; /**< Result of authentication procedure */ +} T_BTIF_AUTHEN_RSP; + +/** + * btif.h + * + * \brief Indication to request user's authorization for service connection + * establish. It will be received in the callback function registered by + * \ref btif_register_req with message type as \ref BTIF_MSG_AUTHOR_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t psm; /**< PSM of protocol which the service is based on */ + uint16_t server_chann; /**< Server channel number when PSM is RFCOMM, otherwise is 0 */ + uint16_t uuid; /**< UUID of the service */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ + uint8_t outgoing; /**< Direction of the service, 1 for outgoing and 0 for incoming. */ +} T_BTIF_AUTHOR_REQ_IND; + +/** + * btif.h + * + * \brief Indication to request PIN code. It will be received in the callback + * function registered by \ref btif_register_req with message type + * as \ref BTIF_MSG_PIN_CODE_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ +} T_BTIF_PIN_CODE_REQ_IND; + +/** + * btif.h + * + * \brief Indication to request BR/EDR OOB data of remote device. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_LEGACY_REMOTE_OOB_REQ_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device */ +} T_BTIF_LEGACY_REMOTE_OOB_REQ_IND; + +/** + * btif.h + * + * \brief Response of getting local BR/EDR OOB data. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_LOCAL_OOB_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t data_c[16]; /**< OOB data simple pairing hash C. */ + uint8_t data_r[16]; /**< OOB data simple pairing randonizer R. */ + uint16_t cause; /**< Result of getting local OOB data. */ +} T_BTIF_LOCAL_OOB_RSP; + +/** + * btif.h + * + * \brief Response of configuring ACL link. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_ACL_CFG_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + T_BTIF_ACL_CFG_OPCODE op; /**< Operation code used to configure ACL link. */ + uint16_t cause; /**< Result of configuring ACL link. */ +} T_BTIF_ACL_CFG_RSP; + +/** + * btif.h + * + * \brief Response of registering SDP record. It will be received in the callback + * function registered by \ref btif_register_req with message type as + * \ref BTIF_MSG_SDP_REG_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of registering SDP record to Bluetooth stack. */ +} T_BTIF_SDP_REG_RSP; + +/** + * btif.h + * + * \brief Response of registering protocol over L2CAP. It will be received in + * the callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_L2C_PROTO_REG_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t psm; /**< PSM of the protocol. */ + uint16_t proto_id; /**< Protocol ID assigned by upper layer. Should be the same as request. */ + uint16_t cause; /**< Result of registering protocol to Bluetooth stack. */ +} T_BTIF_L2C_PROTO_REG_RSP; + +/** + * btif.h + * + * \brief Response of starting L2CAP connection request. It will be received in + * the callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_L2C_CONN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cid; /**< Local CID assigned by Bluetooth stack. */ + uint16_t proto_id; /**< Protocol ID assigned by upper layer. Should be the same as request. */ + uint16_t cause; /**< Result of executing L2CAP connection request from upper layer. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_L2C_CONN_RSP; + +/** + * btif.h + * + * \brief Indication of remote L2CAP connection request. It will be received in + * the callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_L2C_CONN_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cid; /**< Local CID assigned by Bluetooth stack. */ + uint16_t proto_id; /**< Protocol ID which is assigned by upper layer. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_L2C_CONN_IND; + +/** + * btif.h + * + * \brief Information of L2CAP connection establish result. It will be received + * in the callback function registered by \ref btif_register_req with + * message type as \ref BTIF_MSG_L2C_CONN_CMPL_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of establishing a L2CAP channel with remote device. */ + uint16_t cid; /**< Local CID assigned by Bluetooth stack. */ + uint16_t remote_mtu; /**< Remote MTU value. */ + uint16_t proto_id; /**< Protocol ID assigned by upper layer. */ + uint16_t ds_data_offset; /**< Offset used to fill user data when sending L2CAP data to remote. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_L2C_CONN_CMPL_INFO; + +/** + * btif.h + * + * \brief Indication of L2CAP data received from remote side. It will be received + * in the callback function registered by \ref btif_register_req with + * message type as \ref BTIF_MSG_L2C_DATA_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t proto_id; /**< Protocol ID assigned by upper layer. */ + uint16_t cid; /**< Local CID assigned by Bluetooth stack. */ + uint16_t length; /**< Length of L2CAP data. */ + uint16_t gap; /**< Offset from data parameter to the real L2CAP data. */ + uint8_t data[1]; /**< The rest of message which contains real L2CAP data at offset of gap. */ +} T_BTIF_L2C_DATA_IND; + +/** + * btif.h + * + * \brief Response of L2CAP disconnection request from upper layer. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_L2C_DISCONN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cid; /**< Local CID assigned by Bluetooth stack. */ + uint16_t proto_id; /**< Protocol ID assigned by upper layer. */ + uint16_t cause; /**< Result of disconnecting L2CAP channel with remote device. */ +} T_BTIF_L2C_DISCONN_RSP; + +/** + * btif.h + * + * \brief Indication of L2CAP disconnection request from remote side. It will + * be received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_L2C_DISCONN_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cid; /**< Local CID assigned by Bluetooth stack. */ + uint16_t proto_id; /**< Protocol ID assigned by upper layer. */ + uint16_t cause; /**< L2CAP channel disconnect reason. */ +} T_BTIF_L2C_DISCONN_IND; + +/** + * btif.h + * + * \brief Response of setting local device into busy state in ERTM mode. It will + * be received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_L2C_SET_LOCAL_BUSY_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of setting local busy state in ERTM mode. */ +} T_BTIF_L2C_SET_LOCAL_BUSY_RSP; + +/** + * btif.h + * + * \brief Response of registering L2CAP security entry. It will be received + * in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_L2C_SEC_REG_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t psm; /**< PSM of the protocol. */ + uint16_t server_chann; /**< Server channel when PSM is RFCOMM, otherwise is 0. */ + uint8_t active; /**< Active/Deactive the security entry. */ + uint16_t uuid; /**< UUID of the service the security entry registered for. */ + uint16_t cause; /**< Result of registering L2CAP level security entry. */ +} T_BTIF_L2C_SEC_REG_RSP; + +/** + * btif.h + * + * \brief Result of authenticaion on profile over RFCOMM channel. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_RFC_AUTHEN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t chann; /**< Local CID assigned by Bluetooth stack. */ + uint16_t dlci; /**< DCLI value of the RFCOMM channel. */ + uint16_t cause; /**< Result of authentication on the RFCOMM channel. */ + uint8_t outgoing; /**< Direction of the service, 1 for outgoing and 0 for incoming. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_RFC_AUTHEN_RSP; + +/** + * btif.h + * + * \brief Response of SCO/eSCO connection request from upper layer. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SCO_CONN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of starting a SCO/eSCO connection. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_SCO_CONN_RSP; + +/** + * btif.h + * + * \brief Indication of SCO/eSCO connection request from remote side. It will be + * received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SCO_CONN_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ + uint8_t is_esco; /**< Connection type remote device want to create. 1 for eSCO and 0 for SCO. */ +} T_BTIF_SCO_CONN_IND; + +/** + * btif.h + * + * \brief Result of SCO/eSCO connection establish procedure. It will be received + * in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SCO_CONN_CMPL_INFO. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t handle; /**< Connection handle of the SCO/eSCO link. */ + uint16_t cause; /**< Result of establishing the SCO/eSCO link. */ + uint8_t is_esco; /**< Whether this link is a SCO/eSCO link. 1 for eSCO and 0 for SCO. */ + uint8_t air_mode; /**< Air mode of the SCO/eSCO link. */ + uint16_t tx_length; /**< Length of the eSCO payload in transmit direction. 0 for SCO links. */ + uint16_t rx_length; /**< Length of the eSCO payload in receive direction. 0 for SCO links. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_SCO_CONN_CMPL_INFO; + +/** + * btif.h + * + * \brief Indication of SCO/eSCO data from remote side. It will be received + * in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SCO_DATA_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t handle; /**< Connection handle of the SCO/eSCO link. */ + T_BTIF_SCO_PKT_STATUS status; /**< Status of the SCO/eSCO data. */ + void *p_buf; /**< Address of the SCO/eSCO data. */ + uint16_t len; /**< Length of the SCO/eSCO data. */ +} T_BTIF_SCO_DATA_IND; + +/** + * btif.h + * + * \brief Response of SCO/eSCO disconnect request from upper layer. It will + * be received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SCO_DISCONN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t handle; /**< Connection handle of the SCO/eSCO link. */ + uint16_t cause; /**< Result of disconnecting the SCO/eSCO link. */ + uint16_t reason; /**< Disconnect reason for the SCO/eSCO link. */ +} T_BTIF_SCO_DISCONN_RSP; + +/** + * btif.h + * + * \brief Indication of SCO/eSCO disconnect request from remote side. It will + * be received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_SCO_DISCONN_IND. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t handle; /**< Connection handle of the SCO/eSCO link. */ + uint16_t cause; /**< Disconnect reason for the SCO/eSCO link. */ +} T_BTIF_SCO_DISCONN_IND; + +/** + * btif.h + * + * \brief Response of ACL disconnect request from upper layer. It will + * be received in the callback function registered by \ref btif_register_req + * with message type as \ref BTIF_MSG_ACL_DISCONN_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of disconnecting ACL link. */ + uint16_t reason; /**< Disconnect reason for the ACL link. */ + uint8_t bd_addr[6]; /**< Bluetooth address of remote device. */ +} T_BTIF_ACL_DISCONN_RSP; + +/** + * btif.h + * + * \brief Response of setup QOS for an ACL link. It will be received in the + * callback function registered by \ref btif_register_req with message + * type as \ref BTIF_MSG_SETUP_QOS_RSP. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t cause; /**< Result of setup QOS for the ACL link. */ + uint16_t handle; /**< Connection handle of the ACL link. */ +} T_BTIF_SETUP_QOS_RSP; + +typedef enum +{ + SMP_OOB_INVALID_TYPE, + SMP_OOB_PEER, + SMP_OOB_LOCAL, + SMP_OOB_BOTH +} T_BTIF_OOB_DATA_TYPE; + +typedef struct +{ + uint8_t present; + uint8_t rand[16]; + uint8_t confirm[16]; + uint8_t bd_addr_to[6]; + uint8_t local_sk[32]; + uint8_t local_pk[64]; +} T_BTIF_LOCAL_OOB_DATA; + +typedef struct +{ + uint8_t present; + uint8_t rand[16]; + uint8_t confirm[16]; + uint8_t bd_addr_from[6]; +} T_BTIF_PEER_OOB_DATA; + +typedef struct +{ + T_BTIF_LOCAL_OOB_DATA loc_oob_data; + T_BTIF_PEER_OOB_DATA peer_oob_data; +} T_SMP_SC_OOB_DATA; + +#if F_BT_LE_6_0_AOA_AOD_SUPPORT + +typedef struct +{ + uint16_t cause; + bool is_receiver; +} T_BTIF_LE_SET_SUPPL_TEST_PARAMS_RSP; + +#if F_BT_LE_6_0_AOX_CONNLESS_SUPPORT +typedef struct +{ + uint16_t cause; + uint16_t sync_handle; +} T_BTIF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE_RSP; +#endif +typedef struct +{ + uint16_t cause; + bool is_receiver; +} T_BTIF_LE_SET_CONN_SUPPL_PARAMS_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_CONN_SUPPL_REQUEST_ENABLE_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_LE_CONN_SUPPL_RESPONSE_ENABLE_RSP; + +typedef struct +{ + uint16_t cause; + uint8_t supported_sampling_rates; + uint8_t num_of_antennae; + uint8_t max_suppl_length; +} T_BTIF_LE_READ_ANTENNA_INFO_RSP; + + + +typedef struct +{ + uint16_t sync_handle; + uint8_t channel_index; + uint8_t suppl_type; + uint8_t slot_durations; + uint8_t packet_status; + uint8_t sample_count; //0x09 ?C 0x52 + uint8_t iq_sample[82 + 82]; +} T_BTIF_LE_CONNLESS_IQ_REPORT_INFO; + +typedef struct +{ + uint16_t conn_handle; + uint8_t rx_phy; + uint8_t data_chan_index; + uint8_t rssi; + uint8_t suppl_type; + uint8_t slot_durations; + uint8_t packet_status; + uint8_t sample_count;//0x09 ?C 0x52 + uint8_t iq_sample[82 + 82]; +} T_BTIF_LE_CONN_IQ_REPORT_INFO; + +typedef struct +{ + uint8_t status; + uint16_t conn_handle; + +} T_BTIF_LE_SUPPL_REQUEST_FAILED_INFO; +#endif + +typedef struct +{ + uint16_t cause; + uint8_t lt_addr; +} T_BTIF_LT_ADDR_SET_RSP; + +typedef struct +{ + uint16_t cause; + uint8_t lt_addr; +} T_BTIF_LT_ADDR_DEL_RSP; + +typedef struct +{ + uint16_t cause; + uint16_t interval; +} T_BTIF_SYNC_TRAIN_PARAM_SET_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_SYNC_TRAIN_RSP; + +typedef struct +{ + uint16_t cause; +} T_BTIF_SYNC_TRAIN_CMPL_INFO; + +typedef struct +{ + uint16_t cause; +} T_BTIF_SYNC_TRAIN_RCV_RSP; + +typedef struct +{ + uint16_t cause; + uint8_t bd_addr[6]; + uint32_t clk_offset; + uint8_t afh_chann_map[10]; + uint8_t lt_addr; + uint8_t srv_data; + uint32_t next_broadcast_inst; + uint16_t csb_interval; +} T_BTIF_SYNC_TRAIN_RCV_CMPL_INFO; + +typedef struct +{ + uint16_t cause; + uint8_t lt_addr; + uint16_t interval; +} T_BTIF_CSB_SET_RSP; + +typedef struct +{ + uint16_t cause; + uint8_t bd_addr[6]; + uint8_t lt_addr; +} T_BTIF_CSB_RCV_SET_RSP; + +typedef struct +{ + uint8_t bd_addr[6]; + uint8_t lt_addr; +} T_BTIF_CSB_TOUT_INFO; + +typedef struct +{ + uint16_t cause; + uint8_t lt_addr; +} T_BTIF_CSB_DATA_RSP; + +typedef struct +{ + uint8_t bd_addr[6]; + uint8_t lt_addr; + uint32_t clk; + uint32_t offset; + uint8_t rcv_status; + uint8_t fragment; + uint16_t data_len; + uint8_t data[1]; +} T_BTIF_CSB_DATA_IND; + +/** + * btif.h + * + * \brief Message data in upstream message from Bluetooth stack to APP. The + * specific value of the data is depeneded on message type . + * + * \ingroup BTIF + */ +typedef union +{ + T_BTIF_REGISTER_RSP register_rsp; + T_BTIF_RELEASE_RSP release_rsp; + T_BTIF_ACT_INFO act_info; + T_BTIF_DEV_CFG_RSP dev_cfg_rsp; + T_BTIF_ACL_STATUS_INFO acl_status_info; + T_BTIF_ACL_PRIORITY_SET_RSP acl_priority_set_rsp; + T_BTIF_READ_RSSI_RSP read_rssi_rsp; + T_BTIF_VENDOR_CMD_RSP vendor_cmd_rsp; + T_BTIF_VENDOR_EVT_INFO vendor_evt_info; + T_BTIF_PAIRABLE_MODE_SET_RSP pairable_mode_set_rsp; + T_BTIF_USER_PASSKEY_REQ_IND user_passkey_req_ind; + T_BTIF_JUST_WORK_REQ_IND just_work_req_ind; + T_BTIF_USER_PASSKEY_REQ_REPLY_RSP user_passkey_req_reply_rsp; + T_BTIF_USER_PASSKEY_NOTIF_INFO user_passkey_notif_info; + T_BTIF_USER_PASSKEY_NOTIF_IND user_passkey_notif_ind; + T_BTIF_AUTHEN_RESULT_IND authen_result_ind; + T_BTIF_AUTHEN_KEY_REQ_IND authen_key_req_ind; + T_BTIF_USER_CFM_REQ_IND user_cfm_req_ind; +#if F_BT_KEY_PRESS_SUPPORT + T_BTIF_KEYPRESS_NOTIF_RSP keypress_notif_rsp; + T_BTIF_KEYPRESS_NOTIF_INFO keypress_notif_info; +#endif + T_BTIF_HW_ERROR_INFO hw_error_info; + + T_BTIF_REMOTE_OOB_REQ_IND remote_ood_req_ind; + T_BTIF_GATT_SRV_REG_RSP gatt_srv_reg_rsp; + T_BTIF_GATT_ATTR_UPDATE_RSP gatt_attr_update_rsp; + T_BTIF_GATT_ATTR_UPDATE_STATUS_IND gatt_attr_update_status_ind; + T_BTIF_GATT_ATTR_READ_IND gatt_attr_read_ind; + T_BTIF_GATT_ATTR_WRITE_IND gatt_attr_write_ind; + T_BTIF_GATT_ATTR_EXEC_WRITE_IND gatt_attr_exec_write_ind; + T_BTIF_GATT_ATTR_CCCD_INFO gatt_attr_cccd_info; + T_BTIF_GATT_DISCOVERY_RSP gatt_discovery_rsp; + T_BTIF_GATT_DISCOVERY_IND gatt_discovery_ind; + T_BTIF_GATT_ATTR_READ_RSP gatt_attr_read_rsp; +#if F_BT_LE_ATT_READ_MULTI_SUPPORT + T_BTIF_GATT_ATTR_READ_MULTI_RSP gatt_attr_read_multi_rsp; +#endif + T_BTIF_GATT_ATTR_WRITE_RSP gatt_attr_write_rsp; + T_BTIF_GATT_ATTR_PREP_WRITE_RSP gatt_attr_prep_write_rsp; + T_BTIF_GATT_ATTR_EXEC_WRITE_RSP gatt_attr_exec_write_rsp; + T_BTIF_GATT_ATTR_IND gatt_attr_ind; + T_BTIF_GATT_ATTR_NOTIF_INFO gatt_attr_notif_info; + T_BTIF_GATT_SECURITY_RSP gatt_security_rsp; + T_BTIF_GATT_SERVER_STORE_IND gatt_server_store_ind; + T_BTIF_GATT_MTU_SIZE_INFO gatt_mtu_size_info; + + T_BTIF_LE_CONN_RSP le_conn_rsp; + T_BTIF_LE_CONN_IND le_conn_ind; + T_BTIF_LE_CONN_CMPL_INFO le_conn_cmpl_info; +#if F_BT_LE_READ_REMOTE_FEATS + T_BTIF_LE_REMOTE_FEATS_INFO le_remote_feats_info; +#endif + T_BTIF_LE_DISCONN_RSP le_disconn_rsp; + T_BTIF_LE_DISCONN_IND le_disconn_ind; + T_BTIF_LE_ADV_RSP le_adv_rsp; + T_BTIF_LE_ADV_PARAM_SET_RSP le_adv_param_set_rsp; + T_BTIF_LE_ADV_DATA_SET_RSP le_adv_data_set_rsp; + T_BTIF_LE_SCAN_RSP le_scan_rsp; + T_BTIF_LE_SCAN_PARAM_SET_RSP le_scan_param_set_rsp; + T_BTIF_LE_SCAN_INFO le_scan_info; + T_BTIF_LE_MODIFY_WHITE_LIST_RSP le_modify_white_list_rsp; + T_BTIF_LE_CONN_UPDATE_RSP le_conn_update_rsp; + T_BTIF_LE_CONN_UPDATE_IND le_conn_update_ind; + T_BTIF_LE_CONN_PARAM_INFO le_conn_param_info; +#if F_BT_LE_4_2_SUPPORT +#if F_BT_LE_4_2_CONN_PARAM_UPDATE_SUPPORT + T_BTIF_LE_CONN_PARAM_REQ_EVT_INFO le_conn_param_req_evt_info; + T_BTIF_LE_CONN_PARAM_REQ_REPLY_RSP le_conn_param_req_reply_rsp; + T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_RSP le_conn_param_req_neg_reply_rsp; +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + T_BTIF_LE_READ_MAX_DATA_LEN_RSP le_read_max_data_len_rsp; + T_BTIF_LE_READ_DEFAULT_DATA_LEN_RSP le_read_default_data_len_rsp; + T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_RSP le_write_default_data_len_rsp; + T_BTIF_LE_SET_DATA_LEN_RSP le_set_data_len_rsp; + T_BTIF_LE_DATA_LEN_CHANGE_INFO le_data_len_change_info; +#endif +#endif +#if F_BT_LE_4_1_CBC_SUPPORT + T_BTIF_LE_CREDIT_BASED_CONN_RSP le_credit_based_conn_rsp; + T_BTIF_LE_CREDIT_BASED_CONN_IND le_credit_based_conn_ind; + T_BTIF_LE_CREDIT_BASED_DISCONN_RSP le_credit_based_disconn_rsp; + T_BTIF_LE_CREDIT_BASED_DISCONN_IND le_credit_based_disconn_ind; + T_BTIF_LE_SEND_CREDIT_RSP le_send_credit_rsp; + T_BTIF_LE_CREDIT_BASED_DATA_RSP le_credit_based_data_rsp; + T_BTIF_LE_CREDIT_BASED_DATA_IND le_credit_based_data_ind; + T_BTIF_LE_CREDIT_BASED_CONN_CMPL_INFO le_credit_based_conn_cmpl_info; + T_BTIF_LE_CREDIT_BASED_CONN_CREDIT_INFO le_credit_based_conn_credit_info; + T_BTIF_LE_CREDIT_BASED_SECURITY_REG_RSP le_credit_based_security_reg_rsp; + T_BTIF_LE_CREDIT_BASED_PSM_REG_RSP le_credit_based_psm_reg_rsp; +#endif + T_BTIF_LE_SET_CHANN_CLASSIF_RSP le_set_chann_classif_rsp; + T_BTIF_LE_READ_CHANN_MAP_RSP le_read_chann_map_rsp; +#if F_BT_LE_4_0_DTM_SUPPORT + T_BTIF_LE_RECEIVER_TEST_RSP le_receiver_test_rsp; + T_BTIF_LE_TRANSMITTER_TEST_RSP le_transmitter_test_rsp; + T_BTIF_LE_TEST_END_RSP le_test_end_rsp; +#endif + T_BTIF_LE_READ_ADV_TX_POWER_RSP le_read_adv_tx_power_rsp; + T_BTIF_LE_SET_RAND_ADDR_RSP le_set_rand_addr_rsp; + T_BTIF_LE_CONFIG_LOCAL_IRK_RSP le_config_local_irk_rsp; +#if F_BT_LE_PRIVACY_SUPPORT + T_BTIF_LE_MODIFY_RESOLV_LIST_RSP le_modify_resolv_list_rsp; + T_BTIF_LE_READ_PEER_RESOLV_ADDR_RSP le_read_peer_resolv_addr_rsp; + T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_RSP le_read_local_resolv_addr_rsp; + T_BTIF_LE_SET_RESOLUTION_ENABLE_RSP le_set_resolution_enable_rsp; + T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_RSP le_set_resolv_priv_addr_tout_rsp; + T_BTIF_LE_SET_PRIVACY_MODE_RSP le_set_privacy_mode_rsp; + T_BTIF_LE_DIRECT_ADV_INFO le_direct_adv_info; +#endif + T_BTIF_LE_HIGH_DUTY_ADV_TIMEOUT_INFO le_high_duty_adv_timeout_info; +#if F_BT_LE_5_0_SUPPORT +#if F_BT_LE_5_0_AE_ADV_SUPPORT + T_BTIF_LE_SET_ADV_SET_RAND_ADDR_RSP le_set_adv_set_rand_addr_rsp; + T_BTIF_LE_EXT_ADV_PARAM_SET_RSP le_ext_adv_param_set_rsp; + T_BTIF_LE_EXT_ADV_DATA_SET_RSP le_ext_adv_data_set_rsp; + T_BTIF_LE_EXT_ADV_ENABLE_RSP le_ext_adv_enable_rsp; + T_BTIF_LE_ADV_SET_TERMINATED_INFO le_adv_set_terminated_info; + T_BTIF_LE_SCAN_REQ_RECEIVED_INFO le_scan_req_received_info; + T_BTIF_LE_ENABLE_EXT_ADV_MODE_RSP le_enable_ext_adv_mode_rsp; + T_BTIF_LE_MODIFY_ADV_SET_RSP le_modify_adv_set_rsp; +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + T_BTIF_LE_EXT_SCAN_PARAM_SET_RSP le_ext_scan_param_set_rsp; + T_BTIF_LE_EXT_SCAN_RSP le_ext_scan_rsp; + T_BTIF_LE_EXT_ADV_REPORT_INFO le_ext_adv_report_info; +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + T_BTIF_LE_SET_DEFAULT_PHY_RSP le_set_default_phy_rsp; + T_BTIF_LE_SET_PHY_RSP le_set_phy_rsp; + T_BTIF_LE_PHY_UPDATE_INFO le_phy_update_info; +#endif +#if F_BT_LE_5_0_DTM_SUPPORT + T_BTIF_LE_ENHANCED_RECEIVER_TEST_RSP le_enhanced_receiver_test_rsp; + T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_RSP le_enhanced_transmitter_test_rsp; +#endif +#if F_BT_LE_5_0_RF_PATH_SUPPORT + T_BTIF_LE_READ_RF_PATH_COMPENSATION_RSP le_read_rf_path_compensation_rsp; + T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_RSP le_write_rf_path_compensation_rsp; +#endif +#if F_BT_LE_5_0_PERIODIC_ADV_SUPPORT + T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_RSP le_modify_periodic_adv_list_rsp; + T_BTIF_LE_SET_PERIODIC_ADV_PARAM_RSP le_set_periodic_adv_param_rsp; + T_BTIF_LE_SET_PERIODIC_ADV_DATA_RSP le_set_periodic_adv_data_rsp; + T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_RSP le_set_periodic_adv_enable_rsp; + T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_RSP le_periodic_adv_create_sync_rsp; + T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_RSP le_periodic_adv_create_sync_cancel_rsp; + T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_RSP le_periodic_adv_terminate_sync_rsp; + T_BTIF_LE_PERIODIC_ADV_SYNC_ESTABLISHED_INFO le_periodic_adv_sync_established_info; + T_BTIF_LE_PERIODIC_ADV_REPORT_INFO le_periodic_adv_report_info; + T_BTIF_LE_PERIODIC_ADV_SYNC_LOST_INFO le_periodic_adv_sync_lost_info; +#endif +#endif + T_BTIF_LE_LOCAL_DEV_INFO le_local_dev_info; +#if F_BT_LE_ATT_SIGNED_WRITE_SUPPORT + T_BTIF_LE_SIGNED_STATUS_INFO le_signed_status_info; +#endif +#if F_BT_LE_6_0_AOA_AOD_SUPPORT + T_BTIF_LE_SET_SUPPL_TEST_PARAMS_RSP le_set_suppl_test_params_rsp; +#if F_BT_LE_6_0_AOX_CONNLESS_SUPPORT + T_BTIF_LE_SET_CONNLESS_IQ_SAMPLING_ENABLE_RSP le_set_connless_iq_sampling_enable_rsp; + T_BTIF_LE_CONNLESS_IQ_REPORT_INFO le_connless_iq_report_info; +#endif + T_BTIF_LE_SET_CONN_SUPPL_PARAMS_RSP le_set_conn_suppl_params_rsp; + T_BTIF_LE_CONN_SUPPL_REQUEST_ENABLE_RSP le_conn_suppl_request_enable_rsp; + T_BTIF_LE_CONN_SUPPL_RESPONSE_ENABLE_RSP le_conn_suppl_response_enable_rsp; + T_BTIF_LE_READ_ANTENNA_INFO_RSP le_read_antenna_info_rsp; + T_BTIF_LE_CONN_IQ_REPORT_INFO le_conn_iq_report_info; + T_BTIF_LE_SUPPL_REQUEST_FAILED_INFO le_suppl_request_failed_info; +#endif + +#if F_BT_BREDR_SUPPORT + T_BTIF_RADIO_MODE_SET_RSP radio_mode_set_rsp; + T_BTIF_INQUIRY_RSP inquiry_rsp; + T_BTIF_INQUIRY_RESULT_INFO inquiry_result_info; + T_BTIF_INQUIRY_CMPL_INFO inquiry_cmpl_info; + T_BTIF_INQUIRY_CANCEL_RSP inquiry_cancel_rsp; + T_BTIF_REMOTE_NAME_RSP remote_name_rsp; + T_BTIF_SDP_DISCOV_RSP sdp_discov_rsp; + T_BTIF_SDP_ATTR_IND sdp_attr_ind; + T_BTIF_DID_ATTR_IND did_attr_ind; + T_BTIF_SDP_DISCOV_CMPL_INFO sdp_discov_cmpl_info; + T_BTIF_STOP_SDP_DISCOV_RSP stop_sdp_discov_rsp; + T_BTIF_AUTHEN_RSP authen_rsp; + T_BTIF_AUTHOR_REQ_IND author_req_ind; + T_BTIF_PIN_CODE_REQ_IND pin_code_req_ind; + T_BTIF_LEGACY_REMOTE_OOB_REQ_IND legacy_remote_oob_req_ind; + T_BTIF_LOCAL_OOB_RSP local_oob_rsp; + T_BTIF_ACL_CFG_RSP acl_cfg_rsp; + T_BTIF_SDP_REG_RSP sdp_reg_rsp; + T_BTIF_L2C_PROTO_REG_RSP l2c_proto_reg_rsp; + T_BTIF_L2C_CONN_RSP l2c_conn_rsp; + T_BTIF_L2C_CONN_IND l2c_conn_ind; + T_BTIF_L2C_CONN_CMPL_INFO l2c_conn_cmpl_info; + T_BTIF_L2C_DATA_IND l2c_data_ind; + T_BTIF_L2C_DISCONN_RSP l2c_disconn_rsp; + T_BTIF_L2C_DISCONN_IND l2c_disconn_ind; + T_BTIF_L2C_SET_LOCAL_BUSY_RSP l2c_set_local_busy_rsp; + T_BTIF_L2C_SEC_REG_RSP l2c_sec_reg_rsp; + T_BTIF_RFC_AUTHEN_RSP rfc_authen_rsp; + T_BTIF_SCO_CONN_RSP sco_conn_rsp; + T_BTIF_SCO_CONN_IND sco_conn_ind; + T_BTIF_SCO_CONN_CMPL_INFO sco_conn_cmpl_info; + T_BTIF_SCO_DATA_IND sco_data_ind; + T_BTIF_SCO_DISCONN_RSP sco_disconn_rsp; + T_BTIF_SCO_DISCONN_IND sco_disconn_ind; + T_BTIF_ACL_DISCONN_RSP acl_disconn_rsp; + T_BTIF_SETUP_QOS_RSP setup_qos_rsp; + + T_BTIF_LT_ADDR_SET_RSP lt_addr_set_rsp; + T_BTIF_LT_ADDR_DEL_RSP lt_addr_del_rsp; + T_BTIF_SYNC_TRAIN_PARAM_SET_RSP sync_train_param_set_rsp; + T_BTIF_SYNC_TRAIN_RSP sync_train_rsp; + T_BTIF_SYNC_TRAIN_CMPL_INFO sync_train_cmpl_info; + T_BTIF_SYNC_TRAIN_RCV_RSP sync_train_rcv_rsp; + T_BTIF_SYNC_TRAIN_RCV_CMPL_INFO sync_train_rcv_cmpl_info; + T_BTIF_CSB_SET_RSP csb_set_rsp; + T_BTIF_CSB_RCV_SET_RSP csb_rcv_set_rsp; + T_BTIF_CSB_TOUT_INFO csb_tout_info; + T_BTIF_CSB_DATA_RSP csb_data_rsp; + T_BTIF_CSB_DATA_IND csb_data_ind; +#endif +} T_BTIF_UP_MSG_DATA; + +/** + * btif.h + * + * \brief Upstream message from Bluetooth stack to APP. It will be received + * in the callback function registered by \ref btif_register_req. + * + * \ingroup BTIF + */ +typedef struct +{ + uint16_t reserved; /**< Reserved for future use. */ + uint16_t command; /**< Message type defined as \ref T_BTIF_MSG_TYPE. */ + T_BTIF_UP_MSG_DATA p; /**< Message data defined as \ref T_BTIF_UP_MSG_DATA. */ +} T_BTIF_UP_MSG; + +/** + * btif.h + * + * \brief Prototype of callback function to handle btif messages from Bluetooth + * stack to upper layer. + * \details The callback function should be registered by \ref btif_register_req. + * Upstream messages will be handled in this function. Message types are + * defined in \ref T_BTIF_UP_MSG. Sending messages to APP task is + * highly recommended.\n + * + * \ingroup BTIF + */ +typedef void (* P_BTIF_CALLBACK)(T_BTIF_UP_MSG *p_msg); + +/** + * btif.h + * + * \brief Allocate a buffer from the specified pool in Bluetooth stack. This + * function is mainly used when sending LE ACL data to remote side. + * \c pool_id parameter should be the same as the one in upstream messages + * with message type as \ref BTIF_MSG_LE_LOCAL_DEV_INFO. + * + * \param[in] pool_id ID of the specified pool to allocate buffer from. + * \param[in] size Pool buffer size in bytes. + * \param[in] offset Offset in bytes. User data will be put start from the offset in the buffer. + * + * \return The address of the allocated pool buffer. If the address is NULL, + * the buffer allocation was failed. + * + * Example usage + \code{.c} + uint16_t ds_data_offset; + uint16_t ds_pool_id; + + // ... + // Assign ds_data_offset and ds_pool_id value by btif message. + // ... + + void test_send_notification(uint8_t *p_data, uint16_t data_len) + { + uint16_t length = data_len; + + if (data_len != 0 && p_data != NULL) + { + + uint8_t *p_buf = NULL; + uint16_t offset = ds_data_offset + 3; + + p_buf = btif_buffer_get(ds_pool_id, length, offset); + if (p_buf != NULL) + { + memcpy(p_buf + offset, p_data, length); + } + else + { + return; + } + + //local_mdl_id, p_service_handle, p_request_handle was get from btif message. + if (btif_gatt_attr_update_req(p_buf, local_mdl_id, p_service_handle, + p_request_handle, 4, length, offset, 0)) + { + + } + else + { + if (p_buf != NULL) + { + btif_buffer_put(p_buf); + } + } + } + } + \endcode + * + * \ingroup BTIF + */ +void *btif_buffer_get(uint16_t pool_id, uint16_t size, uint16_t offset); + +/** + * btif.h + * + * \brief Free a buffer from Bluetooth stack. The buffer can either be allocated + * by APP by \ref btif_buffer_get or allocated by Bluetooth stack and + * send to APP by callback function registered by \ref btif_register_req. + * + * \param[in] p_buf The address of the buffer. + * + * \return The status of the buffer freeing. + * \retval true Buffer was freed successfully. + * \retval false Buffer was failed to free. + * + * Example usage + \code{.c} + #define BTIF_MSG_EVENT 0x01 + + #define MAX_NUMBER_OF_RX_EVENT 0x10 + #define MAX_NUMBER_OF_MESSAGE 0x10 + + void *evt_q_handle; + void *msg_q_handle; + + // APP btif message callback function. + void app_btif_msg_cb(T_BTIF_UP_MSG *p_msg) + { + unsigned char event = BTIF_MSG_EVENT; + + if (os_msg_send(msg_q_handle, &p_msg, 0) == false) + { + APP_PRINT_WARN0("app_btif_msg_cb: Message Queue is full"); + btif_buffer_put(p_msg); + } + else if (os_msg_send(evt_q_handle, &event, 0) == false) + { + APP_PRINT_WARN0("app_btif_msg_cb: Event Queue is full"); + } + } + + void app_task(void *p_param) + { + char event; + + os_msg_queue_create(&evt_q_handle, MAX_NUMBER_OF_RX_EVENT, sizeof(unsigned char)); + os_msg_queue_create(&msg_q_handle, MAX_NUMBER_OF_MESSAGE, sizeof(T_BTIF_UP_MSG *)); + + //Register callback function + btif_register_req(app_btif_msg_cb); + + while (true) + { + if (os_msg_recv(evt_q_handle, &event, 0xFFFFFFFF) == true) + { + if (event == BTIF_MSG_EVENT) + { + T_BTIF_UP_MSG *p_msg; + + if (os_msg_recv(msg_q_handle, &p_msg, 0) == true) + { + // ... + // Handle btif message. + // ... + + btif_buffer_put(p_msg); + } + } + } + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_buffer_put(void *p_buf); + +/** + * btif.h + * + * \brief Send a request to register a callback function to handle btif + * upsteam messages from Bluetooth stack to APP. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_REGISTER_RSP + * and data is \ref T_BTIF_REGISTER_RSP will be received in the callback + * function. If the function was successfully registered, another message + * whose type is \ref BTIF_MSG_ACT_INFO and data is \ref T_BTIF_ACT_INFO + * will also be received after that. Sending messages to APP task + * in the callback function is highly recommended. Btif message + * buffer should be released after the message is truely handled. + * + * \param[in] p_callback Callback function to handle btif message. The function + * must has prototype as \ref P_BTIF_CALLBACK. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + #define BTIF_MSG_EVENT 0x01 + + #define MAX_NUMBER_OF_RX_EVENT 0x10 + #define MAX_NUMBER_OF_MESSAGE 0x10 + + void *evt_q_handle; + void *msg_q_handle; + + // APP btif message callback function. + void app_btif_msg_cb(T_BTIF_UP_MSG *p_msg) + { + unsigned char event = BTIF_MSG_EVENT; + + if (os_msg_send(msg_q_handle, &p_msg, 0) == false) + { + APP_PRINT_WARN0("app_btif_msg_cb: message queue is full"); + btif_buffer_put(p_msg); + } + else if (os_msg_send(evt_q_handle, &event, 0) == false) + { + APP_PRINT_WARN0("app_btif_msg_cb: event queue is full"); + } + } + + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_REGISTER_RSP: + APP_PRINT_TRACE1("register response cause: 0x%04x", p_msg->p.register_rsp.cause); + break; + + case BTIF_MSG_ACT_INFO: + APP_PRINT_TRACE1("local address: %s", TRACE_BDADDR(p_msg->p.act_info.local_addr)); + break; + + default: + break; + } + } + + void app_task(void *p_param) + { + char event; + + os_msg_queue_create(&evt_q_handle, MAX_NUMBER_OF_RX_EVENT, sizeof(unsigned char)); + os_msg_queue_create(&msg_q_handle, MAX_NUMBER_OF_MESSAGE, sizeof(T_BTIF_UP_MSG *)); + + //Register callback function + btif_register_req(app_btif_msg_cb); + + while (true) + { + if (os_msg_recv(evt_q_handle, &event, 0xFFFFFFFF) == true) + { + if (event == BTIF_MSG_EVENT) + { + T_BTIF_UP_MSG *p_msg; + + if (os_msg_recv(msg_q_handle, &p_msg, 0) == true) + { + app_handle_btif_msg(p_msg); + btif_buffer_put(p_msg); + } + } + } + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_register_req(P_BTIF_CALLBACK p_callback); + +/** + * btif.h + * + * \brief Send a request to read RSSI of remote device. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_READ_RSSI_RSP + * and data is \ref T_BTIF_READ_RSSI_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_READ_RSSI_RSP: + { + T_BTIF_READ_RSSI_RSP *p_rsp = &p_msg->p.read_rssi_rsp; + + if (!p_rsp->cause) + { + APP_PRINT_TRACE1("RSSI value is %d", p_rsp->rssi); + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + btif_read_rssi_req(bd_addr, BTIF_REMOTE_ADDR_CLASSIC); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_read_rssi_req(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type); + +/** + * btif.h + * + * \brief Send a request to set priority for an ACL link. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_ACL_PRIORITY_SET_RSP + * and data is \ref T_BTIF_ACL_PRIORITY_SET_RSP will be received in the callback + * function registered by \ref btif_register_req. To set priority for + * an ACL link, it must be connected and ready to be configured, which + * can be sure by receiving \ref BTIF_MSG_ACL_STATUS_INFO message with + * ACL status as \ref BTIF_ACL_CONN_READY. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] conn_type Connection type for the link. + * \param[in] is_high_priority Priority to set. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_READY: + btif_acl_priority_set_req(p_info->bd_addr, 0, true); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_PRIORITY_SET_RSP: + { + T_BTIF_ACL_PRIORITY_SET_RSP *p_rsp = &p_msg->p.acl_priority_set_rsp; + APP_PRINT_TRACE1("Configure ACL link priority response: cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_priority_set_req(uint8_t *bd_addr, uint8_t conn_type, bool is_high_priority); + +/** + * btif.h + * + * \brief Send a request to send vendor command to controller. If the request + * was successfully sent, a message whose type is \ref BTIF_MSG_VENDOR_CMD_RSP + * and data is \ref T_BTIF_VENDOR_CMD_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param[in] op Operation code of the command. + * \param[in] len Length of parameters of the command. + * \param[in] p_param Address of parameters of the command. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_VENDOR_CMD_RSP: + { + T_BTIF_VENDOR_CMD_RSP *p_rsp = &p_msg->p.vendor_cmd_rsp; + + if (p_rsp->command == 0xFC11) + { + APP_PRINT_TRACE1("vendor command response: cause 0x%04x", p_rsp->cause); + } + + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_vendor_cmd_req(0xFC11, 0, NULL); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_vendor_cmd_req(uint16_t op, uint8_t len, uint8_t *p_param); + +/** + * btif.h + * + * \brief Send a request to set pairable mode. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_PAIRABLE_MODE_SET_RSP + * and data is \ref T_BTIF_PAIRABLE_MODE_SET_RSP will be received in + * the callback function registered by \ref btif_register_req. + * + * \param[in] le_enable Whether to enable le pairing or not. + * \param[in] br_enable Whether to enable br pairing or not. + * \param[in] requirements Authentication requirement of the device. Valid values are the combination of \ref BTIF_AUTHEN_FLAGS. + * \param[in] io_caps Input/Output capabilities. Valid values is \ref T_BTIF_IOCAP. + * \param[in] oob_present Whether OOB data can be used or not. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_PAIRABLE_MODE_SET_RSP: + { + T_BTIF_PAIRABLE_MODE_SET_RSP *p_rsp = &p_msg->p.vendor_cmd_rsp; + + APP_PRINT_TRACE1("pairable mode set response: cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_pairable_mode_set_req(true, true, BTIF_AUTHEN_BONDING | BTIF_AUTHEN_MITM, BTIF_IOCAP_NO_IO, false); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_pairable_mode_set_req(bool le_enable, bool br_enable, uint16_t requirements, + T_BTIF_IOCAP io_caps, bool oob_present); + +/** + * btif.h + * + * \brief Send a confirmation for user passkey request indication. The function + * should be used when receiving message with type as \ref BTIF_MSG_USER_PASSKEY_REQ_IND + * in the callback function registered by \ref btif_register_req. If + * confirm with cause as \ref BTIF_CAUSE_ACCEPT, passkey should be input + * later using \ref btif_user_passkey_req_reply_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * \param[in] cause Confirm result of user passkey request indication. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_USER_PASSKEY_REQ_IND: + { + T_BTIF_USER_PASSKEY_REQ_IND *p_ind = &p_msg->p.user_passkey_req_ind; + + btif_user_passkey_req_cfm(p_ind->bd_addr, p_ind->remote_addr_type, BTIF_CAUSE_ACCEPT); + btif_user_passkey_req_reply_req(p_ind->bd_addr, p_ind->remote_addr_type, 888888, BTIF_CAUSE_ACCEPT); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_user_passkey_req_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a request to input user passkey. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_USER_PASSKEY_REQ_REPLY_RSP + * and data is \ref T_BTIF_USER_PASSKEY_REQ_REPLY_RSP will be received in + * the callback function registered by \ref btif_register_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * \param[in] passkey User passkey. Only valid when \c cause is \ref BTIF_CAUSE_ACCEPT. + * \param[in] cause Status of input user passkey. \ref BTIF_CAUSE_ACCEPT to input passkey, otherwise reject. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_USER_PASSKEY_REQ_IND: + { + T_BTIF_USER_PASSKEY_REQ_IND *p_ind = &p_msg->p.user_passkey_req_ind; + + btif_user_passkey_req_cfm(p_ind->bd_addr, p_ind->remote_addr_type, BTIF_CAUSE_ACCEPT); + btif_user_passkey_req_reply_req(p_ind->bd_addr, p_ind->remote_addr_type, 888888, BTIF_CAUSE_ACCEPT); + } + break; + + case BTIF_MSG_USER_PASSKEY_REQ_REPLY_RSP: + { + T_BTIF_USER_PASSKEY_REQ_REPLY_RSP *p_rsp = &p_msg->p.user_passkey_req_reply_rsp; + APP_PRINT_TRACE1("input user passkey result 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_user_passkey_req_reply_req(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + uint32_t passkey, T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a confirmation for authentication result indication. The function + * should be used when receiving message with type as \ref BTIF_MSG_AUTHEN_RESULT_IND + * in the callback function registered by \ref btif_register_req. User + * should save authetication information or delete old one according to + * key type in the indication message. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * \param[in] cause Confirm result of authentication result indication. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_AUTHEN_RESULT_IND: + { + T_BTIF_AUTHEN_RESULT_IND *p_ind = &p_msg->p.authen_result_ind; + + if (p_ind->key_type == BTIF_KEY_DELETE) + { + //Delete link key saved before. + } + else + { + //Save link key information. + } + + btif_authen_result_cfm(p_ind->bd_addr, p_ind->remote_addr_type, BTIF_CAUSE_SUCCESS); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_authen_result_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + T_BTIF_KEY_TYPE key_type, T_BTIF_CAUSE cause); + + +/** + * btif.h + * + * \brief Send a confirmation for authentication key request indication. + * The function should be used when receiving message with type as + * \ref BTIF_MSG_AUTHEN_KEY_REQ_IND in the callback function registered + * by \ref btif_register_req. After receiving the indication, user should + * try to find key information and then use this function to confirm. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * \param[in] key_len Length of the authenticaion key found. + * \param[in] p_key Address of the authenticaion key found. + * \param[in] key_type Type of the authenticaion key found. + * \param[in] cause Confirmation status for authentication key request indication. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_AUTHEN_KEY_REQ_IND: + { + T_BTIF_AUTHEN_KEY_REQ_IND *p_ind = &p_msg->p.authen_key_req_ind; + + if (p_ind->remote_addr_type == BTIF_REMOTE_ADDR_CLASSIC) + { + if (p_ind->key_type == BTIF_KEY_REQ_BR) + { + uint8_t link_key[16]; + uint8_t key_type; + + //Find BR/EDR link key for the address. + if (legacy_get_bond(p_ind->bd_addr, link_key, &key_type) == true) + { + btif_authen_key_req_cfm(p_ind->bd_addr, p_ind->remote_addr_type, 16, link_key, + (T_BTIF_KEY_TYPE)key_type, BTIF_CAUSE_ACCEPT); + } + else + { + btif_authen_key_req_cfm(p_ind->bd_addr, p_ind->remote_addr_type, 0, NULL, + p_ind->key_type, BTIF_CAUSE_REJECT); + } + } + } + else + { + //Handle indication for LE key request. + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_authen_key_req_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + uint8_t key_len, uint8_t *p_key, T_BTIF_KEY_TYPE key_type, + T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a confirmation for user confirm request indication. The + * function should be used when receiving message with type as \ref + * BTIF_MSG_USER_CFM_REQ_IND and specific numeric value in message + * data in the callback function registered by \ref btif_register_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * \param[in] cause Confirmation status for user confirm request indication. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_USER_CFM_REQ_IND: + { + T_BTIF_USER_CFM_REQ_IND *p_ind = &p_msg->p.user_cfm_req_ind; + + btif_user_cfm_req_cfm(p_ind->bd_addr, p_ind->remote_addr_type, BTIF_CAUSE_ACCEPT); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_user_cfm_req_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a request to send keypress event to remote device. If the + * request was successfully sent, a message whose type is \ref + * BTIF_MSG_KEYPRESS_NOTIF_RSP and data is \ref T_BTIF_KEYPRESS_NOTIF_RSP + * will be received in the callback function registered by \ref btif_register_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] remote_addr_type Address type of remote device. + * \param[in] event_type Keypress event type. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_KEYPRESS_NOTIF_RSP: + { + T_BTIF_KEYPRESS_NOTIF_RSP *p_rsp = &p_msg->p.keypress_notif_rsp; + APP_PRINT_TRACE1("keypress response cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + btif_keypress_notif_req(bd_addr, BTIF_REMOTE_ADDR_LE_PUBLIC, BTIF_PASSKEY_ENTRY_STARTED); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_keypress_notif_req(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + T_BTIF_KEYPRESS_NOTIF_TYPE event_type); + +bool btif_just_work_req_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + T_BTIF_CAUSE cause); + +bool btif_user_passkey_notif_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + T_BTIF_CAUSE cause); + +bool btif_set_link_key_convert(bool is_support); + +bool btif_user_defined(void *p_buf); + +T_BTIF_IDENT_ADDR_TYPE btif_convert_addr_type(T_BTIF_REMOTE_ADDR_TYPE type); + +bool btif_le_cfg_passkey_value(uint32_t value); + +void btif_le_cfg_slave_init_mtu(bool enable); + +void btif_le_cfg_local_key_distribute(uint8_t init_dist, uint8_t rsp_dist); + +bool btif_le_cfg_local_identity_address(uint8_t *addr, T_BTIF_IDENT_ADDR_TYPE type); + +bool btif_le_conn_req(bool use_extended_conn, uint8_t bd_addr[6], + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, T_BTIF_LOCAL_ADDR_TYPE local_addr_type, + uint8_t init_phys, uint16_t scan_timeout, T_BTIF_LE_CONN_REQ_PARAM *p_conn_req_param); + +bool btif_le_conn_cfm(uint8_t *bd_addr, T_BTIF_CAUSE cause); + +bool btif_le_disconn_req(uint16_t link_id, T_BTIF_CAUSE cause); + +bool btif_le_disconn_cfm(uint16_t link_id); + +bool btif_gatt_srv_reg_req(uint16_t num_attr, void *p_srv); + +bool btif_gatt_srv2_reg_req(uint16_t num_attr, void *p_srv, uint16_t start_handle); + +bool btif_gatt_attr_update_req(void *p_buf, uint16_t link_id, void *p_srv_handle, + void *p_req_handle, uint16_t attr_index, uint16_t attr_len, + uint16_t offset, T_BTIF_GATT_PDU_TYPE type); + +bool btif_gatt_attr_update_status_cfm(uint16_t link_id, void *p_srv_handle, + void *p_req_handle, uint16_t attr_index); + +bool btif_gatt_attr_read_cfm(void *p_buf, uint16_t link_id, void *p_srv_handle, uint16_t cause, + uint16_t attr_index, uint16_t attr_len, uint16_t offset); + +bool btif_gatt_attr_write_req_cfm(uint16_t link_id, void *p_srv_handle, + uint16_t cause, uint16_t attr_index); + +bool btif_gatt_attr_prep_write_cfm(void *p_buf, uint16_t link_id, void *p_srv_handle, + uint16_t cause, uint16_t attr_index, uint16_t attr_len, uint16_t offset); + +bool btif_gatt_attr_exec_write_cfm(uint16_t link_id, uint16_t cause, uint16_t handle); + +bool btif_gatt_attr_prep_write_req(void *p_buf, uint16_t link_id, uint16_t attr_handle, + uint16_t attr_len, uint16_t write_offset, uint16_t offset); + +bool btif_gatt_attr_exec_write_req(uint16_t link_id, uint8_t flags); + +bool btif_gatt_discovery_req(uint16_t link_id, T_BTIF_GATT_DISCOVERY_TYPE type, + uint16_t start_handle, uint16_t end_handle, uint16_t uuid16, uint8_t *p_uuid128); + +bool btif_gatt_discovery_cfm(uint16_t link_id, T_BTIF_GATT_DISCOVERY_TYPE type, + uint16_t start_handle, uint16_t end_handle); + +bool btif_gatt_attr_read_req(uint16_t link_id, T_BTIF_GATT_READ_TYPE read_type, + uint16_t read_offset, uint16_t start_handle, uint16_t end_handle, + uint16_t uuid16, uint8_t *p_uuid128); + +bool btif_gatt_attr_read_multi_req(uint16_t link_id, uint16_t num_handle, uint16_t *p_handle); + +bool btif_gatt_attr_write_req(void *p_buf, uint16_t link_id, T_BTIF_GATT_WRITE_TYPE write_type, + uint16_t attr_handle, uint16_t attr_len, uint16_t offset); + +bool btif_gatt_attr_cfm(uint16_t link_id); + +bool btif_gatt_security_req(uint16_t link_id, uint16_t requirements, uint8_t min_key_size); + +bool btif_gatt_server_store_cfm(T_BTIF_GATT_STORE_OPCODE op, uint8_t *bd_addr, + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, + uint8_t data_len, uint8_t *data, T_BTIF_CAUSE cause); + +#if F_BT_LE_SMP_OOB_SUPPORT +bool btif_remote_oob_req_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE addr_type, + uint8_t *p_data_c, T_BTIF_CAUSE cause); +#endif + +bool btif_le_adv_req(T_BTIF_LE_ADV_MODE adv_mode); + +bool btif_le_adv_param_set_req(T_BTIF_LE_ADV_TYPE adv_type, + T_BTIF_LE_ADV_FILTER_POLICY filter_policy, + uint16_t min_interval, uint16_t max_interval, + T_BTIF_LOCAL_ADDR_TYPE local_addr_type, uint8_t *bd_addr, + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type, uint8_t chann_map); + +bool btif_le_adv_data_set_req(T_BTIF_LE_ADV_DATA_TYPE data_type, uint8_t data_len, uint8_t *p_data); + +bool btif_le_scan_req(T_BTIF_LE_SCAN_MODE mode, T_BTIF_LE_SCAN_FILTER_DUPLICATES filter_duplicates); + +bool btif_le_scan_param_set_req(T_BTIF_LE_SCAN_TYPE type, uint16_t interval, uint16_t window, + T_BTIF_LE_SCAN_FILTER_POLICY filter_policy, T_BTIF_LOCAL_ADDR_TYPE local_addr_type); + +bool btif_le_ext_scan_req(T_BTIF_LE_SCAN_MODE mode, + T_BTIF_LE_SCAN_FILTER_DUPLICATES filter_duplicates, + uint16_t duration, uint16_t period); + +bool btif_le_ext_scan_param_set_req(T_BTIF_LOCAL_ADDR_TYPE local_addr_type, + T_BTIF_LE_SCAN_FILTER_POLICY filter_policy, + uint8_t scan_phys, + T_BTIF_LE_EXT_SCAN_PARAM *p_extended_scan_param); + +bool btif_le_modify_adv_set_req(T_BTIF_LE_ADV_SET_OP op, uint8_t adv_handle); + +bool btif_le_modify_white_list_req(T_BTIF_LE_WHITE_LIST_OP op, uint8_t *bd_addr, + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type); + +bool btif_le_conn_update_req(uint16_t link_id, uint16_t min_interval, uint16_t max_interval, + uint16_t conn_latency, uint16_t supv_tout, uint16_t min_ce_len, + uint16_t max_ce_len); + +bool btif_le_conn_update_cfm(uint16_t link_id, T_BTIF_CAUSE cause); + +bool btif_le_set_rand_addr_req(uint8_t *random_addr); + +bool btif_le_enable_ext_adv_mode_req(void); + +bool btif_le_set_adv_set_rand_addr_req(uint8_t *random_addr, uint8_t adv_handle); + +bool btif_le_credit_based_conn_req(uint16_t link_id, uint16_t le_psm, uint16_t mtu, + uint16_t initial_credits, uint16_t credits_threshold); + +bool btif_le_credit_based_conn_cfm(uint16_t link_id, uint16_t channel, uint16_t mtu, + uint16_t initial_credits, uint16_t credits_threshold, + T_BTIF_L2C_LE_CONN_STATUS cause); + +bool btif_le_credit_based_disconn_req(uint16_t link_id, uint16_t channel); + +bool btif_le_credit_based_disconn_cfm(uint16_t link_id, uint16_t channel); + +bool btif_le_send_credit_req(uint16_t link_id, uint16_t channel, uint16_t credits); + +bool btif_le_credit_based_data_req(void *p_buf, uint16_t link_id, uint16_t channel, + uint16_t length, uint16_t offset); + +bool btif_le_credit_based_data_cfm(uint16_t link_id, uint16_t channel, T_BTIF_CAUSE cause); + +bool btif_le_credit_based_security_reg_req(uint16_t le_psm, bool active, + T_BTIF_LE_SECURITY_MODE mode, uint8_t key_size); + +bool btif_le_credit_based_psm_reg_req(uint16_t le_psm, uint8_t action); + +bool btif_le_set_data_len_req(uint16_t link_id, uint16_t tx_oct, uint16_t tx_time); + +bool btif_le_conn_param_req_reply_req(uint16_t link_id, uint16_t min_interval, + uint16_t max_interval, uint16_t latency, uint16_t supv_tout, + uint16_t min_ce_len, uint16_t max_ce_len); + +bool btif_le_conn_param_req_neg_reply_req(uint16_t link_id, uint8_t reason); + +bool btif_le_config_local_irk_req(uint8_t *p_local_irk); + +bool btif_le_gen_rand_addr(T_BTIF_ADDR_RAND rand_addr_type, uint8_t *p_addr); + +bool btif_le_modify_resolv_list_req(T_BTIF_LE_RESOLVING_LIST_OP operation, + T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type, uint8_t *peer_ident_addr, + uint8_t *peer_irk, uint8_t *local_irk); + +bool btif_le_read_peer_resolv_addr_req(T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type, + uint8_t *peer_ident_addr); + +bool btif_le_read_local_resolv_addr_req(T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type, + uint8_t *peer_ident_addr); + +bool btif_le_set_resolution_enable_req(uint8_t enable); + +bool btif_le_set_resolv_priv_addr_tout_req(uint16_t timeout); + +bool btif_le_set_privacy_mode_req(T_BTIF_IDENT_ADDR_TYPE peer_identity_address_type, + uint8_t *peer_identity_address, T_BTIF_LE_PRIVACY_MODE privacy_mode); + +bool btif_le_set_chann_classif_req(uint8_t *p_chann_map); + +bool btif_le_read_chann_map_req(uint16_t link_id); + +bool btif_le_receiver_test_req(uint8_t rx_chann); + +bool btif_le_transmitter_test_req(uint8_t tx_chann, uint8_t data_len, uint8_t pkt_pl); + +bool btif_le_test_end_req(void); + +bool btif_le_read_adv_tx_power_req(void); + +bool btif_le_set_default_phy_req(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys); + +bool btif_le_set_phy_req(uint16_t link_id, uint8_t all_phys, uint8_t tx_phys, + uint8_t rx_phys, T_BTIF_LE_PHY_OPTIONS phy_options); + +bool btif_le_ext_adv_enable_req(T_BTIF_LE_EXT_ADV_MODE adv_mode, uint8_t num_of_sets, + T_BTIF_LE_EXT_ADV_SET_PARAM *p_adv_set_param); + +bool btif_le_ext_adv_param_set_req(uint8_t adv_handle, uint16_t adv_event_prop, + uint32_t primary_adv_interval_min, uint32_t primary_adv_interval_max, + uint8_t primary_adv_channel_map, T_BTIF_LOCAL_ADDR_TYPE own_address_type, + T_BTIF_REMOTE_ADDR_TYPE peer_address_type, uint8_t *p_peer_address, + T_BTIF_LE_ADV_FILTER_POLICY filter_policy, uint8_t tx_power, + T_BTIF_LE_PRIM_ADV_PHY_TYPE primary_adv_phy, uint8_t secondary_adv_max_skip, + T_BTIF_LE_PHY_TYPE secondary_adv_phy, uint8_t adv_sid, + T_BTIF_LE_SCAN_REQ_NOTIFY_TYPE scan_req_notification_enable); + +bool btif_le_ext_adv_data_set_req(T_BTIF_LE_EXT_ADV_DATA_TYPE data_type, + uint8_t adv_handle, T_BTIF_LE_ADV_FRAG_OP_TYPE op, + T_BTIF_LE_ADV_FRAG_PREFERENCE_TYPE frag_preference, + uint8_t data_len, uint8_t *p_data); + +bool btif_le_enhanced_receiver_test_req(uint8_t rx_chann, uint8_t phy, uint8_t modulation_index); + +bool btif_le_enhanced_transmitter_test_req(uint8_t tx_chann, uint8_t data_len, + uint8_t pkt_pl, uint8_t phy); + +bool btif_le_modify_periodic_adv_list_req(T_BTIF_LE_PERIODIC_ADV_LIST_OP op, uint8_t adv_addr_type, + uint8_t *adv_addr, uint8_t adv_sid); + +bool btif_le_read_rf_path_compensation_req(void); + +bool btif_le_write_rf_path_compensation_req(int8_t rf_tx_path_compensation, + int8_t rf_rx_path_compensation); + +bool btif_le_set_periodic_adv_param_req(uint8_t adv_handle, uint16_t adv_interval_min, + uint16_t adv_interval_max, uint16_t adv_prop); + +bool btif_le_set_periodic_adv_data_req(uint8_t adv_handle, T_BTIF_LE_ADV_FRAG_OP_TYPE op, + uint8_t data_len, uint8_t *p_data); + +bool btif_le_set_periodic_adv_enable_req(T_BTIF_LE_PERIODIC_ADV_MODE mode, uint8_t adv_handle); + +bool btif_le_periodic_adv_create_sync_req(uint8_t filter_policy, uint8_t adv_sid, + uint8_t adv_addr_type, uint8_t adv_add[6], uint16_t skip, + uint16_t sync_timeout, uint16_t unused); + +bool btif_le_periodic_adv_create_sync_cancel_req(void); + +bool btif_le_periodic_adv_terminate_sync_req(uint16_t sync_handle); + +bool btif_remote_oob_req_cfm(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE addr_type, + uint8_t *p_data_c, T_BTIF_CAUSE cause); + +bool btif_le_sc_local_oob_init(uint64_t *p_ecc_rand_in, uint8_t *local_rand, + T_BTIF_LOCAL_OOB_DATA *p_local_oob_data); + +bool btif_le_sc_peer_oob_init(T_BTIF_PEER_OOB_DATA *p_peer_oob_data); + +#if F_BT_LE_6_0_AOA_AOD_SUPPORT +bool btif_le_set_suppl_test_params_req(bool is_receiver, uint8_t suppl_len, uint8_t suppl_slot_type, + uint8_t num_antena_ids, uint8_t antenna_switching_pattern); +#if F_BT_LE_6_0_AOX_CONNLESS_SUPPORT +bool btif_le_set_connless_suppl_transmit_params_req(uint8_t adv_handle, uint8_t suppl_type, + uint8_t suppl_len, + uint8_t num_antena_ids, uint8_t *p_antenna_id_list); +bool btif_le_set_connless_suppl_transmit_enable_req(uint8_t adv_handle, uint8_t enable); +bool btif_le_set_connless_iq_sample_enable_req(uint16_t sync_handle, uint8_t enable, + uint8_t slot_duration, + uint8_t num_antena_ids, uint8_t *p_antenna_id_list); +#endif +bool btif_le_set_conn_suppl_params_req(bool is_receiver, uint16_t link_id, uint8_t slot_duration, + uint8_t num_antena_ids, uint8_t *p_antenna_id_list); + +bool btif_le_conn_suppl_request_enable_req(uint16_t link_id, uint8_t enable, + uint16_t suppl_interval, + uint8_t suppl_len, uint8_t suppl_type); +bool btif_le_conn_suppl_response_enable_req(uint16_t link_id, uint8_t enable); +bool btif_le_read_antenna_info_req(void); +#endif + +/** + * btif.h + * + * \brief Send a request to configure name and class of device of local + * device. If the request was successfully sent, a message whose type + * is \ref BTIF_MSG_DEV_CFG_RSP and data is \ref T_BTIF_DEV_CFG_RSP + * will be received in the callback function registered by \ref + * btif_register_req. The operation code in \ref T_BTIF_DEV_CFG_RSP + * is \ref BTIF_DEV_CFG_OP_NAME. + * + * \param[in] cod Class of device to be configured. + * \param[in] p_name Address of name to be configured. The length of name should not be larger than \ref BTIF_NAME_LENGTH. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_NAME: + APP_PRINT_TRACE1("Configure local name result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_dev_cfg_name_req(0x000900, "New Name"); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_cfg_name_req(uint32_t cod, uint8_t *p_name); + +/** + * btif.h + * + * \brief Send a request to configure DID information in EIR data. If the + * request was successfully sent, a message whose type is \ref + * BTIF_MSG_DEV_CFG_RSP and data is \ref T_BTIF_DEV_CFG_RSP will be + * received in the callback function registered by \ref btif_register_req. + * The operation code in \ref T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_DID_EIR. + * + * \param[in] vendor_id Vendor ID. + * \param[in] vendor_id_src Vendor ID source. + * \param[in] product_id Product ID. + * \param[in] product_version Product version. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_DID_EIR: + APP_PRINT_TRACE1("Configure DID information result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_dev_did_eir_cfg_req(0x005D, 0x0001, 0x223B, 0x0100); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_did_eir_cfg_req(uint16_t vendor_id, uint16_t vendor_id_src, + uint16_t product_id, uint16_t product_version); + +/** + * btif.h + * + * \brief Send a request to configure extra information other than local + * name, service UUID and DID in EIR data. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_DEV_CFG_RSP and data is + * \ref T_BTIF_DEV_CFG_RSP will be received in the callback function + * registered by \ref btif_register_req. The operation code in \ref + * T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_EXT_EIR. + * + * \param[in] p_data Address of extra EIR data.The buffer should not be freed until receiving the response message. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + uint8_t *p_ext = NULL; + + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_EXT_EIR: + APP_PRINT_TRACE1("Configure extra eir data result 0x%04x", p_rsp->cause); + os_mem_free(p_ext); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + p_ext = os_mem_zalloc(30); + if (p_ext != NULL) + { + // ... + // Fill in extra EIR data. + // ... + btif_dev_ext_eir_cfg_req(p_ext); + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_ext_eir_cfg_req(uint8_t *p_data); + +/** + * btif.h + * + * \brief Send a request to configure page scan parameters and page timeout + * value. If the request was successfully sent, a message whose type is + * \ref BTIF_MSG_DEV_CFG_RSP and data is \ref T_BTIF_DEV_CFG_RSP will be + * received in the callback function registered by \ref btif_register_req. + * The operation code in \ref T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_PAGE_SCAN. + * + * \param[in] scan_type Page scan type. + * \param[in] interval Page scan interval. Only even values from 0x12 to 0x1000 are valid. + * \param[in] window Page scan window. Only values from 0x11 to 0x1000 are valid. Should be less than or equal to interval. + * \param[in] page_tout Page timeout value. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_PAGE_SCAN: + APP_PRINT_TRACE1("Configure page scan parameters result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_dev_page_scan_cfg_req(BTIF_BR_PAGE_SCAN_STANDARD, 0x800, 0x12, 0x2000); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_page_scan_cfg_req(T_BTIF_BR_PAGE_SCAN_TYPE scan_type, + uint16_t interval, uint16_t window, uint16_t page_tout); + +/** + * btif.h + * + * \brief Send a request to configure inquiry scan parameters. If the request + * was successfully sent, a message whose type is \ref BTIF_MSG_DEV_CFG_RSP + * and data is \ref T_BTIF_DEV_CFG_RSP will be received in the callback + * function registered by \ref btif_register_req. The operation code in + * \ref T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_INQUIRY_SCAN. + * + * \param[in] scan_type Inquiry scan type. + * \param[in] interval Inquiry scan interval. Only even values from 0x12 to 0x1000 are valid. + * \param[in] window Inquiry scan window. Only values from 0x11 to 0x1000 are valid. Should be less than or equal to interval. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_INQUIRY_SCAN: + APP_PRINT_TRACE1("Configure inquiry scan parameters result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_dev_inquiry_scan_cfg_req(BTIF_BR_INQUIRY_SCAN_STANDARD, 0x1000, 0x12); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_inquiry_scan_cfg_req(T_BTIF_BR_INQUIRY_SCAN_TYPE scan_type, + uint16_t interval, uint16_t window); + +/** + * btif.h + * + * \brief Send a request to configure inquiry mode. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_DEV_CFG_RSP + * and data is \ref T_BTIF_DEV_CFG_RSP will be received in the callback + * function registered by \ref btif_register_req. The operation code in + * \ref T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_INQUIRY_MODE. + * + * \param[in] mode Inquiry mode. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_INQUIRY_MODE: + APP_PRINT_TRACE1("Configure inquiry mode result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_dev_inquiry_mode_cfg_req(BTIF_BR_EXTENDED_INQUIRY_RESULT); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_inquiry_mode_cfg_req(T_BTIF_BR_INQUIRY_MODE mode); + +/** + * btif.h + * + * \brief Send a request to configure default link policy to use after ACL + * connection is established and default page timeout value if local is + * master. If the request was successfully sent, a message whose type + * is \ref BTIF_MSG_DEV_CFG_RSP and data is \ref T_BTIF_DEV_CFG_RSP + * will be received in the callback function registered by \ref btif_register_req. + * The operation code in \ref T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_LINK_POLICY. + * + * \param[in] policy Default link policy to use after ACL link established. Valid values are combination of \ref BTIF_BR_LINK_POLICY. + * \param[in] supv_tout Default supervision timeout value to use if local is master. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_LINK_POLICY: + APP_PRINT_TRACE1("Configure link policy result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_dev_link_policy_cfg_req(BTIF_BR_LINK_POLICY_ENABLE_ROLE_SWITCH | BTIF_BR_LINK_POLICY_ENABLE_SNIFF_MODE, 0x7D00); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_link_policy_cfg_req(T_BTIF_BR_LINK_POLICY policy, uint16_t supv_tout); + +/** + * btif.h + * + * \brief Send a request to configure Bluetooth mode. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_DEV_CFG_RSP + * and data is \ref T_BTIF_DEV_CFG_RSP will be received in the + * callback function registered by \ref btif_register_req. The operation + * code in \ref T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_BT_MODE. + * Default value of Bluetooth mode is \ref BTIF_BT_MODE21_DISABLED. + * Bluetooth mode can only be configured from \ref BTIF_BT_MODE21_DISABLED + * to \ref BTIF_BT_MODE21_ENABLED, not the other way around. + * + * \param[in] mode Bluetooth mode. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_BT_MODE: + APP_PRINT_TRACE1("Configure Bluetooth mode result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_dev_bt_mode_cfg_req(BTIF_BT_MODE21_ENABLED); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_bt_mode_cfg_req(T_BTIF_BT_MODE mode); + +/** + * btif.h + * + * \brief Send a request to configure accept role to use when accepting + * connection request from remote device. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_DEV_CFG_RSP and data is + * \ref T_BTIF_DEV_CFG_RSP will be received in the callback function + * registered by \ref btif_register_req. The operation code in \ref + * T_BTIF_DEV_CFG_RSP is \ref BTIF_DEV_CFG_OP_ACCEPT_CONN_ROLE. + * + * \param[in] role Accept role to use. + * \arg \c 0 Become the Master for this connection. + * \arg \c 1 Remain the Slave for this connection. This is the default value. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_DEV_CFG_RSP: + { + T_BTIF_DEV_CFG_RSP *p_rsp = &p_msg->p.dev_cfg_rsp; + + switch (p_rsp->op) + { + case BTIF_DEV_CFG_OP_ACCEPT_CONN_ROLE: + APP_PRINT_TRACE1("Configure accept role result 0x%04x", p_rsp->cause); + break; + + default: + break; + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_dev_accept_role_cfg_req(0); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_dev_accept_role_cfg_req(uint8_t role); + +/** + * btif.h + * + * \brief Send a request to set radio mode of local device. If the request + * was successfully sent, a message whose type is \ref BTIF_MSG_RADIO_MODE_SET_RSP + * and data is \ref T_BTIF_RADIO_MODE_SET_RSP will be received in the + * callback function registered by \ref btif_register_req. + * + * \param[in] mode Radio mode of local device. + * \param[in] limited Whether enable limited discoverable mode. Only valid when inquiry scan was enabled in mode. + * \param[in] limited_time Limited discoverable timeout value. Only valid when limited discoverable was enabled. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_RADIO_MODE_SET_RSP: + { + T_BTIF_RADIO_MODE_SET_RSP *p_rsp = &p_msg->p.radio_mode_set_rsp; + APP_PRINT_TRACE1("Set radio mode response: status 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + btif_radio_mode_set_req(BTIF_RADIO_VISIBLE_CONNECTABLE, false, 0); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_radio_mode_set_req(T_BTIF_RADIO_MODE mode, bool limited, uint8_t limited_time); + +/** + * btif.h + * + * \brief Send a request to start BR/EDR inquiry. If the request was successfully + * sent, multiple messages will be received in the callback function + * registered by \ref btif_register_req. The first one has message type + * as \ref BTIF_MSG_INQUIRY_RSP and data as \ref T_BTIF_INQUIRY_RSP, + * this message indicates whether inquiry was started successfully. If + * inquiry was started successfully, one or more messages whose type is + * \ref BTIF_MSG_INQUIRY_RESULT_INFO and data is \ref T_BTIF_INQUIRY_RESULT_INFO + * may be received, each message represents a remote device information. + * After inquiry procedure is done, a message whose type is \ref BTIF_MSG_INQUIRY_CMPL_INFO + * and data is \ref T_BTIF_INQUIRY_CMPL_INFO will be received. + * + * \param[in] limited_inquiry Start a limited inquiry or not. + * \arg \c true Start a limited inquiry. + * \arg \c false Start a general inquiry. + * \param[in] timeout Inquiry duration in 1.28s. The real inquiry time is timeout*1.28s. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_INQUIRY_RSP: + { + T_BTIF_INQUIRY_RSP *p_rsp = &p_msg->p.inquiry_rsp; + APP_PRINT_TRACE1("Inquiry response: status 0x%04x", p_rsp->cause); + } + break; + + case BTIF_MSG_INQUIRY_RESULT_INFO: + { + T_BTIF_INQUIRY_RESULT_INFO *p_info = &p_msg->p.inquiry_result_info; + APP_PRINT_TRACE2("Inqury result: remote addr %s, name %s", + TRACE_BDADDR(p_info->bd_addr), TRACE_STRING(p_info->name)); + } + break; + + case BTIF_MSG_INQUIRY_CMPL_INFO: + { + T_BTIF_INQUIRY_CMPL_INFO *p_info = &p_msg->p.inquiry_cmpl_info; + APP_PRINT_TRACE1("Inquiry complete: status 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_inquiry_req(false, 8); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_inquiry_req(bool limited_inquiry, uint8_t timeout); + +/** + * btif.h + * + * \brief Send a request to stop BR/EDR inquiry. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_INQUIRY_CANCEL_RSP and + * data is \ref T_BTIF_INQUIRY_CANCEL_RSP will be received in the callback + * function registered by \ref btif_register_req to indicates whether + * inquiry was stoped successfully. If inquiry was successfully stopped, + * no \ref BTIF_MSG_INQUIRY_CMPL_INFO will be received. + * + * \param[in] None. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_INQUIRY_RSP: + { + T_BTIF_INQUIRY_RSP *p_rsp = &p_msg->p.inquiry_rsp; + + if (!p_rsp->cause) + { + btif_inquiry_cancel_req; + } + } + break; + + case BTIF_MSG_INQUIRY_CANCEL_RSP: + { + T_BTIF_INQUIRY_CANCEL_RSP *p_rsp = &p_msg->p.inquiry_cancel_rsp; + APP_PRINT_TRACE1("Stop inquiry response: status 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_inquiry_req(false, 8); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_inquiry_cancel_req(void); + +/** + * btif.h + * + * \brief Send a request to get remote device's name. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_REMOTE_NAME_RSP and + * data is \ref T_BTIF_REMOTE_NAME_RSP will be received in the callback + * function registered by \ref btif_register_req to indicate the result + * of the procedure. If success, remote name will also be contained in + * the message data. + * + * \param[in] bd_addr Bluetooth address of remote device. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_REMOTE_NAME_RSP: + { + T_BTIF_REMOTE_NAME_RSP *p_rsp = &p_msg->p.remote_name_rsp; + + if (!p_rsp->cause) + { + APP_PRINT_TRACE1("Get remote name response: name is %s", + TRACE_STRING(p_rsp->name)); + } + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + btif_remote_name_req(bd_addr); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_remote_name_req(uint8_t *bd_addr); + +/** + * btif.h + * + * \brief Send a request to start SDP discovery. If the request was successfully + * sent, multiple messages will be received in the callback function + * registered by \ref btif_register_req. The first one has message type + * as \ref BTIF_MSG_SDP_DISCOV_RSP and data as \ref T_BTIF_SDP_DISCOV_RSP + * which indicates whether SDP discovery was started successfully. If + * SDP discovery was started successfully and discovery type is \ref + * BTIF_SDP_DISCOV_TYPE_BR, one or more messages whos type is \ref + * BTIF_MSG_SDP_ATTR_IND and data is \ref T_BTIF_SDP_ATTR_IND may be + * received. If discovery type is \ref BTIF_SDP_DISCOV_TYPE_DID, one + * message whose type is \ref BTIF_MSG_DID_ATTR_IND and data is \ref + * T_BTIF_DID_ATTR_IND may be received. After inquiry procedure is done, + * \ref BTIF_MSG_SDP_DISCOV_CMPL_INFO will be received. Only one + * SDP/DID discovery can be executed at the same time. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] type SDP discovery type. + * \arg \c \ref BTIF_SDP_DISCOV_TYPE_BR Normal SDP discovery. + * \arg \c \ref BTIF_SDP_DISCOV_TYPE_DID DID discovery. + * \param[in] uuid_type Type of UUID to discovery. Only valid when discovery type is \ref BTIF_SDP_DISCOV_TYPE_BR. + * \arg \c BTIF_UUID16 UUID in 16 bits. + * \arg \c BTIF_UUID32 UUID in 32 bits. + * \arg \c BTIF_UUID128 UUID in 128 bits. + * \param[in] uuid_data Discovery UUID data corresponding to uuid_type. Only valid when discovery type is \ref BTIF_SDP_DISCOV_TYPE_BR. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SDP_DISCOV_RSP: + { + T_BTIF_SDP_DISCOV_RSP *p_rsp = &p_msg->p.sdp_discov_rsp; + APP_PRINT_TRACE1("SDP discovery response: status 0x%04x", p_rsp->cause); + } + break; + + case BTIF_MSG_SDP_ATTR_IND: + { + T_BTIF_SDP_ATTR_IND *p_ind = &p_msg->p.sdp_attr_ind; + APP_PRINT_TRACE2("SDP discovery attribute: remote addr %s, remote version 0x%04x", + TRACE_BDADDR(p_ind->bd_addr), p_ind->remote_version); + btif_sdp_attr_cfm(BTIF_CAUSE_SUCCESS); + } + break; + + case BTIF_MSG_SDP_DISCOV_CMPL_INFO: + { + T_BTIF_SDP_DISCOV_CMPL_INFO *p_info = &p_msg->p.sdp_discov_cmpl_info; + APP_PRINT_TRACE1("SDP discovery complete: status 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + T_BTIF_UUID_DATA uuid_data; + + uuid_data.uuid_16 = UUID_HANDSFREE; + btif_sdp_discov_req(bd_addr, BTIF_SDP_DISCOV_TYPE_BR, BTIF_UUID16, uuid_data); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sdp_discov_req(uint8_t *bd_addr, T_BTIF_SDP_DISCOV_TYPE type, + T_BTIF_UUID_TYPE uuid_type, T_BTIF_UUID_DATA uuid_data); + +/** + * btif.h + * + * \brief Send a confirmation for normal SDP attribute indication. This function + * is used when receiving a message whose type is \ref BTIF_MSG_SDP_ATTR_IND + * and data is \ref T_BTIF_SDP_ATTR_IND in the callback function + * registered by \ref btif_register_req. If the confirmation was + * successfully sent, Bluetooth stack will start next SDP attribute + * request procedure. + * + * \param[in] cause Confirmation cause of the SDP attribute indication. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SDP_DISCOV_RSP: + { + T_BTIF_SDP_DISCOV_RSP *p_rsp = &p_msg->p.sdp_discov_rsp; + APP_PRINT_TRACE1("SDP discovery response: status 0x%04x", p_rsp->cause); + } + break; + + case BTIF_MSG_SDP_ATTR_IND: + { + T_BTIF_SDP_ATTR_IND *p_ind = &p_msg->p.sdp_attr_ind; + APP_PRINT_TRACE2("SDP discovery attribute: remote addr %s, remote version 0x%04x", + TRACE_BDADDR(p_ind->bd_addr), p_ind->remote_version); + btif_sdp_attr_cfm(BTIF_CAUSE_SUCCESS); + } + break; + + case BTIF_MSG_SDP_DISCOV_CMPL_INFO: + { + T_BTIF_SDP_DISCOV_CMPL_INFO *p_info = &p_msg->p.sdp_discov_cmpl_info; + APP_PRINT_TRACE1("SDP discovery complete: status 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + T_BTIF_UUID_DATA uuid_data; + + uuid_data.uuid_16 = UUID_HANDSFREE; + btif_sdp_discov_req(bd_addr, BTIF_SDP_DISCOV_TYPE_BR, BTIF_UUID16, uuid_data); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sdp_attr_cfm(T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a confirmation for DID attribute indication. This function is + * used when receiving a message whose type is \ref BTIF_MSG_DID_ATTR_IND + * and data is \ref T_BTIF_DID_ATTR_IND in the callback function registered + * by \ref btif_register_req. If the confirmation was successfully sent, + * Bluetooth stack will start next DID attribute request procedure. + * + * \param[in] cause Confirmation cause of the DID attribute indication. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SDP_DISCOV_RSP: + { + T_BTIF_SDP_DISCOV_RSP *p_rsp = &p_msg->p.sdp_discov_rsp; + APP_PRINT_TRACE1("SDP discovery response: status 0x%04x", p_rsp->cause); + } + break; + + case BTIF_MSG_DID_ATTR_IND: + { + T_BTIF_DID_ATTR_IND *p_ind = &p_msg->p.did_attr_ind; + APP_PRINT_TRACE2("DID discovery attribute: remote addr %s, product ID 0x%04x", + TRACE_BDADDR(p_ind->bd_addr), p_ind->product_id); + btif_did_attr_cfm(BTIF_CAUSE_SUCCESS); + } + break; + + case BTIF_MSG_SDP_DISCOV_CMPL_INFO: + { + T_BTIF_SDP_DISCOV_CMPL_INFO *p_info = &p_msg->p.sdp_discov_cmpl_info; + APP_PRINT_TRACE1("SDP discovery complete: status 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + T_BTIF_UUID_DATA uuid_data = {0}; + + btif_sdp_discov_req(bd_addr, BTIF_SDP_DISCOV_TYPE_DID, (T_BTIF_UUID_TYPE)0, uuid_data); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_did_attr_cfm(T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a request to stop SDP discovery. If the request was successfully + * sent, a message whose type is \ref BTIF_MSG_STOP_SDP_DISCOV_RSP and + * data is \ref T_BTIF_STOP_SDP_DISCOV_RSP will be received in the callback + * function registered by \ref btif_register_req. If SDP discovery was + * successfully stopped, no \ref BTIF_MSG_SDP_DISCOV_CMPL_INFO message + * will be received. + * + * \param[in] bd_addr Bluetooth address of remote device. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SDP_DISCOV_RSP: + { + T_BTIF_SDP_DISCOV_RSP *p_rsp = &p_msg->p.sdp_discov_rsp; + APP_PRINT_TRACE1("SDP discovery response: status 0x%04x", p_rsp->cause); + + if (!p_rsp->cause) + { + btif_stop_sdp_discov_req(p_rsp->bd_addr); + } + } + break; + + case BTIF_MSG_STOP_SDP_DISCOV_RSP: + { + T_BTIF_STOP_SDP_DISCOV_RSP *p_rsp = &p_msg->p.stop_sdp_discov_rsp; + APP_PRINT_TRACE1("Stop SDP discovery reponse: status 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + T_BTIF_UUID_DATA uuid_data; + + uuid_data.uuid_16 = UUID_HANDSFREE; + btif_sdp_discov_req(bd_addr, BTIF_SDP_DISCOV_TYPE_BR, BTIF_UUID16, uuid_data); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_stop_sdp_discov_req(uint8_t *bd_addr); + +/** + * btif.h + * + * \brief Send a request to start BR/EDR pairing with remote device. If the + * request was successfully sent, a message whose type is \ref BTIF_MSG_AUTHEN_RSP + * and data is \ref T_BTIF_AUTHEN_RSP will be received in the callback + * function registered by \ref btif_register_req when the pairing procedure + * is complete. + * + * \param[in] bd_addr Bluetooth address of remote device. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_AUTHEN_RSP: + { + T_BTIF_AUTHEN_RSP *p_rsp = &p_msg->p.authen_rsp; + APP_PRINT_TRACE1("BR/EDR pairing response: status 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + + btif_authen_req(bd_addr); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_authen_req(uint8_t *bd_addr); + +/** + * btif.h + * + * \brief Send a confirmation for authorization request indication. This function + * is used when receiving a message whose type is \ref BTIF_MSG_AUTHOR_REQ_IND + * and data is \ref T_BTIF_AUTHOR_REQ_IND in the callback function registered + * by \ref btif_register_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] cause Confirmation cause of authorization. \ref BTIF_CAUSE_ACCEPT for accept and others for reject. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_AUTHOR_REQ_IND: + { + T_BTIF_AUTHOR_REQ_IND *p_ind = &p_msg->p.author_req_ind; + btif_author_req_cfm(p_ind->bd_addr, BTIF_CAUSE_ACCEPT); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_author_req_cfm(uint8_t *bd_addr, T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a confirmation for PIN code request indication. This function + * is used when receiving a message whose type is \ref BTIF_MSG_PIN_CODE_REQ_IND + * and data is \ref T_BTIF_PIN_CODE_REQ_IND in the callback function + * registered by \ref btif_register_req. User can input PIN code by + * using this function. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] pin_code_len Length of PIN code. Should not be larger than 16. + * \param[in] pin_code Address of PIN code. + * \param[in] cause Confirmation cause. Pin code is only valid when cause is \ref BTIF_CAUSE_ACCEPT. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_PIN_CODE_REQ_IND: + { + T_BTIF_PIN_CODE_REQ_IND *p_ind = &p_msg->p.pin_code_req_ind; + btif_pin_code_req_cfm(p_ind->bd_addr, 4, "0000", BTIF_CAUSE_ACCEPT); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_pin_code_req_cfm(uint8_t *bd_addr, uint8_t pin_code_len, + uint8_t *pin_code, T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a confirmation for remote legacy OOB data request indication. + * This function is used when receiving a message whose type is \ref + * BTIF_MSG_LEGACY_REMOTE_OOB_REQ_IND and data is \ref + * T_BTIF_LEGACY_REMOTE_OOB_REQ_IND in the callback function + * registered by \ref btif_register_req. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] p_data_c Address of BR/EDR OOB data simple pairing hash C. + * \param[in] p_data_r Address of BR/EDR OOB data simple pairing randonizer R. + * \param[in] cause Confirmation cause. OOB data are only valid when cause is \ref BTIF_CAUSE_ACCEPT. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_LEGACY_REMOTE_OOB_REQ_IND: + { + T_BTIF_LEGACY_REMOTE_OOB_REQ_IND *p_ind = &p_msg->p.legacy_remote_oob_req_ind; + uint8_t oob_r[KEY_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t oob_c[KEY_LEN] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + btif_legacy_remote_oob_req_cfm(p_ind->bd_addr, oob_c, oob_r, BTIF_CAUSE_ACCEPT); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_legacy_remote_oob_req_cfm(uint8_t *bd_addr, uint8_t *p_data_c, + uint8_t *p_data_r, T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Send a request to get local BR/EDR OOB data. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_LOCAL_OOB_RSP + * and data is \ref T_BTIF_LOCAL_OOB_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param[in] None. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_LOCAL_OOB_RSP: + { + T_BTIF_LOCAL_OOB_RSP *p_rsp = &p_msg->p.local_oob_rsp; + APP_PRINT_TRACE2("Local OOB data response: data c %b, data r %b", + TRACE_BINARY(16, p_rsp->data_c), TRACE_BINARY(16, p_rsp->data_r)); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_local_oob_req(); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_local_oob_req(void); + +/** + * btif.h + * + * \brief Send a request to configure link policy for an ACL link. If the + * request was successfully sent, a message whose type is \ref BTIF_MSG_ACL_CFG_RSP + * and data is \ref T_BTIF_ACL_CFG_RSP will be received in the callback + * function registered by \ref btif_register_req. Operation code in \ref + * T_BTIF_ACL_CFG_RSP should be \ref BTIF_ACL_CFG_LINK_POLICY. Bluetooth + * stack will automatically set link policy after ACL link is connected. + * To change the default link policy that Bluetooth stack will set, + * \ref btif_dev_link_policy_cfg_req can be used.\ref btif_acl_link_policy_cfg_req + * is used to change link policy after that. In order to avoid collision, + * user should set link policy after receiving \ref BTIF_MSG_ACL_STATUS_INFO + * message with ACL status as \ref BTIF_ACL_CONN_READY. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] policy Link policy to set. Valid values are combinations of \ref BTIF_BR_LINK_POLICY. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_READY: + btif_acl_link_policy_cfg_req(p_info->bd_addr, BTIF_BR_LINK_POLICY_DISABLE_ALL); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_CFG_RSP: + { + T_BTIF_ACL_CFG_RSP *p_rsp = &p_msg->p.acl_cfg_rsp; + + if (p_rsp->op == BTIF_ACL_CFG_LINK_POLICY) + { + APP_PRINT_TRACE1("Configure ACL link policy response: cause 0x%04x", p_rsp->cause); + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_link_policy_cfg_req(uint8_t *bd_addr, T_BTIF_BR_LINK_POLICY policy); + +/** + * btif.h + * + * \brief Send a request to configure link supervision timeout value for an + * ACL link. If the request was successfully sent, a message whose type + * is \ref BTIF_MSG_ACL_CFG_RSP and data is \ref T_BTIF_ACL_CFG_RSP + * will be received in the callback function registered by \ref btif_register_req. + * Operation code in \ref T_BTIF_ACL_CFG_RSP should be \ref BTIF_ACL_CFG_LINK_SUPV_TOUT. + * The function is only useful when local is master of the ACL link. + * Bluetooth stack will automatically set link supervision timeout value + * after ACL link is connected as master. To change the default link + * supervision timeout value that Bluetooth stack will set, \ref btif_dev_link_policy_cfg_req + * can be used.\ref btif_acl_link_supv_tout_cfg_req is used to change + * link supervision timeout value after that. In order to avoid collision, + * user should set link policy after receiving \ref BTIF_MSG_ACL_STATUS_INFO + * message with ACL status as \ref BTIF_ACL_CONN_READY. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] supv_tout Supervision timeout value to set. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_READY: + btif_acl_link_supv_tout_cfg_req(p_info->bd_addr, 0x7D00); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_CFG_RSP: + { + T_BTIF_ACL_CFG_RSP *p_rsp = &p_msg->p.acl_cfg_rsp; + + if (p_rsp->op == BTIF_ACL_CFG_LINK_SUPV_TOUT) + { + APP_PRINT_TRACE1("Configure ACL link supervision timeout response: cause 0x%04x", p_rsp->cause); + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_link_supv_tout_cfg_req(uint8_t *bd_addr, uint16_t supv_tout); + +/** + * btif.h + * + * \brief Send a request to switch link role for an ACL link. If the request + * was successfully sent, a message whose type is \ref BTIF_MSG_ACL_CFG_RSP + * and data is \ref T_BTIF_ACL_CFG_RSP will be received in the callback + * function registered by \ref btif_register_req. Operation code in \ref + * T_BTIF_ACL_CFG_RSP should be \ref BTIF_ACL_CFG_LINK_ROLE. If switch + * role procedure was successful, \ref BTIF_MSG_ACL_STATUS_INFO message + * will also be received with ACL status as \ref BTIF_ACL_ROLE_MASTER + * or \ref BTIF_ACL_ROLE_SLAVE depending on the switch request. If BR/EDR + * secure connections is supported, role change during SMP exchange is + * forbidden. Recommended timing to switch is after receiving \ref + * BTIF_MSG_ACL_STATUS_INFO message with ACL status as \ref BTIF_ACL_CONN_ENCRYPTED + * or ACL status as \ref BTIF_ACL_CONN_BR_SC_CMPL if \ref BTIF_ACL_CONN_BR_SC_START + * was received before. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] role Device role to configure. + * \arg \c 0 Switch to master role. + * \arg \c 1 Switch to slave role. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + uint8_t local_role = 0; + + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_ENCRYPTED: + if (local_role == 1) + { + legacy_cfg_acl_link_role(p_info->bd_addr, 0); + } + break; + + case BTIF_ACL_ROLE_MASTER: + local_role = 0; + break; + + case BTIF_ACL_ROLE_SLAVE: + local_role = 1; + break; + + default: + break; + + } + } + break; + + case BTIF_MSG_ACL_CFG_RSP: + { + T_BTIF_ACL_CFG_RSP *p_rsp = &p_msg->p.acl_cfg_rsp; + + if (p_rsp->op == BTIF_ACL_CFG_LINK_ROLE) + { + APP_PRINT_TRACE1("Configure ACL link role response: cause 0x%04x", p_rsp->cause); + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_link_role_cfg_req(uint8_t *bd_addr, T_BTIF_BR_LINK_ROLE role); + +/** + * btif.h + * + * \brief Send a request to change packet type for an ACL link. If the request + * was successfully sent, a message whose type is \ref BTIF_MSG_ACL_CFG_RSP + * and data is \ref T_BTIF_ACL_CFG_RSP will be received in the callback + * function registered by \ref btif_register_req. Operation code in \ref + * T_BTIF_ACL_CFG_RSP should be \ref BTIF_ACL_CFG_PKT_TYPE. BT stack + * will automatically set link packet type after ACL link is connected. + * In order to avoid collision, user should set link policy after + * receiving \ref BTIF_MSG_ACL_STATUS_INFO message with ACL status as + * \ref BTIF_ACL_CONN_READY. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] pkt_type Packet type to use. Valid values are combinations of \ref BTIF_BR_ACL_PKT_TYPE. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_READY: + btif_acl_pkt_type_cfg_req(p_info->bd_addr, + BTIF_PKT_TYPE_NO_3DH1 | BTIF_PKT_TYPE_DM1 | + BTIF_PKT_TYPE_DH1 | BTIF_PKT_TYPE_NO_3DH3 | + BTIF_PKT_TYPE_DM3 | BTIF_PKT_TYPE_DH3 | + BTIF_PKT_TYPE_NO_3DH5); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_CFG_RSP: + { + T_BTIF_ACL_CFG_RSP *p_rsp = &p_msg->p.acl_cfg_rsp; + + if (p_rsp->op == BTIF_ACL_CFG_PKT_TYPE) + { + APP_PRINT_TRACE1("Configure packet type response: cause 0x%04x", p_rsp->cause); + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_pkt_type_cfg_req(uint8_t *bd_addr, uint16_t pkt_type); + +/** + * btif.h + * + * \brief Send a request to configure ACL link with remote device into sniff + * mode. If the request was successfully sent, a message whose type is + * \ref BTIF_MSG_ACL_CFG_RSP and data is \ref T_BTIF_ACL_CFG_RSP will + * be received in the callback function registered by \ref btif_register_req. + * Operation code in \ref T_BTIF_ACL_CFG_RSP should be \ref BTIF_ACL_CFG_ENTER_SNIFF_MODE. + * If the link enters sniff mode successfully, \ref BTIF_MSG_ACL_STATUS_INFO + * message will also be received with ACL status as \ref BTIF_ACL_CONN_SNIFF, + * the actual sniff interval will also be contained in the message data. + * To configure an ACL link into sniff mode, the link must be connected + * and ready to be configured, which can be sure by receiving \ref + * BTIF_MSG_ACL_STATUS_INFO message with ACL status as \ref BTIF_ACL_CONN_READY. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] min_interval Min sniff interval, only even values between 0x0002 and 0xFFFE are valid. + * \param[in] max_interval Max sniff interval, only even values between 0x0002 and 0xFFFE are valid, should be larger than min_interval. + * \param[in] sniff_attempt Number of baseband receive slots for sniff attempt. + * \param[in] sniff_tout Number of baseband receive slots for sniff timeout. + * \param[in] max_latency Max allowed sniff subrate of the remote device. Set to 0 if do not want to configure sniff subrate. + * \param[in] min_remote_tout Min base sniff subrate timeout the remote device may use. + * \param[in] min_local_tout Min base sniff subrate timeout the local device may use. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_READY: + btif_acl_sniff_mode_enter_req(p_info->bd_addr, 192, 800, 4, 2, 0, 0, 0); + break; + + case BTIF_ACL_CONN_SNIFF: + APP_PRINT_TRACE1("ACL link into sniff mode: interval 0x%04x", p_info->p.sniff.interval); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_CFG_RSP: + { + T_BTIF_ACL_CFG_RSP *p_rsp = &p_msg->p.acl_cfg_rsp; + + if (p_rsp->op == BTIF_ACL_CFG_ENTER_SNIFF_MODE) + { + APP_PRINT_TRACE1("Configure sniff mode response: cause 0x%04x", p_rsp->cause); + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_sniff_mode_enter_req(uint8_t *bd_addr, uint16_t min_interval, uint16_t max_interval, + uint16_t sniff_attempt, uint16_t sniff_tout, uint16_t max_latency, + uint16_t min_remote_tout, uint16_t min_local_tout); + +/** + * btif.h + * + * \brief Send a request to configure ACL link with remote device to exit sniff + * mode. If the request was successfully sent, a message whose type is + * \ref BTIF_MSG_ACL_CFG_RSP and data is \ref T_BTIF_ACL_CFG_RSP will + * be received in the callback function registered by \ref btif_register_req. + * Operation code in \ref T_BTIF_ACL_CFG_RSP should be \ref BTIF_ACL_CFG_EXIT_SNIFF_MODE. + * If the link exits sniff mode successfully, \ref BTIF_MSG_ACL_STATUS_INFO + * message will also be received with ACL status as \ref BTIF_ACL_CONN_ACTIVE. + * To configure an ACL link to exit sniff mode, the link must be in sniff + * mode, which can be sure by receiving \ref BTIF_MSG_ACL_STATUS_INFO + * message with ACL status as \ref BTIF_ACL_CONN_SNIFF. + * + * \param[in] bd_addr Bluetooth address of remote device. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_SNIFF: + APP_PRINT_TRACE1("ACL link into sniff mode: interval 0x%04x", p_info->p.sniff.interval); + btif_acl_sniff_mode_exit_req(p_info->bd_addr); + break; + + case BTIF_ACL_CONN_ACTIVE: + APP_PRINT_TRACE0("ACL link into active mode"); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_CFG_RSP: + { + T_BTIF_ACL_CFG_RSP *p_rsp = &p_msg->p.acl_cfg_rsp; + + if (p_rsp->op == BTIF_ACL_CFG_EXIT_SNIFF_MODE) + { + APP_PRINT_TRACE1("EXIT sniff mode response: cause 0x%04x", p_rsp->cause); + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_sniff_mode_exit_req(uint8_t *bd_addr); + +/** + * btif.h + * + * \brief Send a request to register a SDP record into Bluetooth stack. If the + * request was successfully sent, a message whose type is \ref BTIF_MSG_SDP_REG_RSP + * and data is \ref T_BTIF_SDP_REG_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param[in] p_buf Address of SDP record buffer. The buffer shall not + * be released since Bluetooth stack will record the buffer + * address instead of copy the whole buffer. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + //DID SDP record buffer + const uint8_t did_sdp_record[] = + { + SDP_DATA_ELEM_SEQ_HDR, + 0x4D, + //attribute SDP_ATTR_SRV_CLASS_ID_LIST + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_SRV_CLASS_ID_LIST >> 8), + (uint8_t)SDP_ATTR_SRV_CLASS_ID_LIST, + SDP_DATA_ELEM_SEQ_HDR, + 0x03, + SDP_UUID16_HDR, + (uint8_t)(UUID_PNP_INFORMATION >> 8), + (uint8_t)(UUID_PNP_INFORMATION), + + //attribute SDP_ATTR_BROWSE_GROUP_LIST + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_BROWSE_GROUP_LIST >> 8), + (uint8_t)SDP_ATTR_BROWSE_GROUP_LIST, + SDP_DATA_ELEM_SEQ_HDR, + 0x03, + SDP_UUID16_HDR, + (uint8_t)(UUID_PUBLIC_BROWSE_GROUP >> 8), + (uint8_t)UUID_PUBLIC_BROWSE_GROUP, + + //attribute SDP_ATTR_LANG_BASE_ATTR_ID_LIST + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_LANG_BASE_ATTR_ID_LIST >> 8), + (uint8_t)SDP_ATTR_LANG_BASE_ATTR_ID_LIST, + SDP_DATA_ELEM_SEQ_HDR, + 0x09, + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_LANG_ENGLISH >> 8), + (uint8_t)SDP_LANG_ENGLISH, + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_CHARACTER_UTF8 >> 8), + (uint8_t)SDP_CHARACTER_UTF8, + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_BASE_LANG_OFFSET >> 8), + (uint8_t)SDP_BASE_LANG_OFFSET, + + //attribute SDP_ATTR_PROFILE_DESC_LIST + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_PROFILE_DESC_LIST >> 8), + (uint8_t)SDP_ATTR_PROFILE_DESC_LIST, + SDP_DATA_ELEM_SEQ_HDR, + 0x08, + SDP_DATA_ELEM_SEQ_HDR, + 0x06, + SDP_UUID16_HDR, + (uint8_t)(UUID_PNP_INFORMATION >> 8), + (uint8_t)UUID_PNP_INFORMATION, + SDP_UNSIGNED_TWO_BYTE, + 0x01,//version 1.3 + 0x03, + + //attribute SDP_ATTR_DIP_SPECIFICATION_ID + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_DIP_SPECIFICATION_ID >> 8), + (uint8_t)SDP_ATTR_DIP_SPECIFICATION_ID, + SDP_UNSIGNED_TWO_BYTE, + 0x01, + 0x03, + + //attribute SDP_ATTR_DIP_VENDOR_ID + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_DIP_VENDOR_ID >> 8), + (uint8_t)SDP_ATTR_DIP_VENDOR_ID, + SDP_UNSIGNED_TWO_BYTE, + //0x00,//0x005D : RealTek + //0x5D, + (uint8_t)(RTK_COMPANY_ID >> 8), + (uint8_t)RTK_COMPANY_ID, + + //attribute SDP_ATTR_DIP_PRODUCT_ID + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_DIP_PRODUCT_ID >> 8), + (uint8_t)SDP_ATTR_DIP_PRODUCT_ID, + SDP_UNSIGNED_TWO_BYTE, + 0x22,//8763 + 0x3B, + + //attribute SDP_ATTR_DIP_PRODUCT_VERSION + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_DIP_PRODUCT_VERSION >> 8), + (uint8_t)SDP_ATTR_DIP_PRODUCT_VERSION, + SDP_UNSIGNED_TWO_BYTE, + 0x01,// 1.0.0 + 0x00, + + //attribute SDP_ATTR_DIP_PRIMARY_RECORD + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_DIP_PRIMARY_RECORD >> 8), + (uint8_t)SDP_ATTR_DIP_PRIMARY_RECORD, + SDP_BOOL_ONE_BYTE, + true, + + //attribute SDP_ATTR_DIP_VENDOR_ID_SOURCE + SDP_UNSIGNED_TWO_BYTE, + (uint8_t)(SDP_ATTR_DIP_VENDOR_ID_SOURCE >> 8), + (uint8_t)SDP_ATTR_DIP_VENDOR_ID_SOURCE, + SDP_UNSIGNED_TWO_BYTE, + 0x00,//Bluetooth SIG + 0x01 + }; + + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SDP_REG_RSP: + { + T_BTIF_SDP_REG_RSP *p_rsp = &p_msg->p.sdp_reg_rsp; + APP_PRINT_TRACE1("Register SDP record response: cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_sdp_reg_req(did_sdp_record); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sdp_reg_req(void *p_buf); + +/** + * btif.h + * + * \brief Send a request to register/deregister a protocol over L2CAP in Bluetooth + * stack. If the request was successfully sent, a message whose type is \ref + * BTIF_MSG_L2C_PROTO_REG_RSP and data is \ref T_BTIF_L2C_PROTO_REG_RSP + * will be received in the callback function registered by \ref btif_register_req. + * The protocol must be registered before creating a L2CAP connection + * or accepting a L2CAP connection request from other devices. + * + * \param[in] psm PSM value of the protocol. + * \param[in] proto_id Protocol ID assigned by upper layer. The protocol ID must be less than 0x10. + * \param[in] action Requested action for the protocol. + * \arg \c 0 Register the protocol into Bluetooth stack. + * \arg \c 1 Deregister the protocol from Bluetoth stack. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_PROTO_REG_RSP: + { + T_BTIF_L2C_PROTO_REG_RSP *p_rsp = &p_msg->p.l2c_proto_reg_rsp; + APP_PRINT_TRACE1("Register protocol response: cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_l2c_proto_reg_req(0x17, 0x01, 1); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_proto_reg_req(uint16_t psm, uint16_t proto_id, uint8_t action); + +/** + * btif.h + * + * \brief Send a request to connect a L2CAP channel with remote device. If the + * request was successfully sent, a message whose type is \ref BTIF_MSG_L2C_CONN_RSP + * and data is \ref T_BTIF_L2C_CONN_RSP will be received in the callback + * function registered by \ref btif_register_req to indicate whether + * the procedure was started successfully. If the procedure was started, + * another message whose type is \ref BTIF_MSG_L2C_CONN_CMPL_INFO and + * data is \ref T_BTIF_L2C_CONN_CMPL_INFO will also be received to tell + * the result of connection establishment. + * + * \param[in] psm PSM value of protocol on the L2CAP channel. The protocol ID and PSM must be registered by \ref btif_l2c_proto_reg_req. + * \param[in] uuid UUID of the protocol on the L2CAP channel. + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] proto_id Protocol ID assigned by upper layer. The protocol ID and PSM must be registered by \ref btif_l2c_proto_reg_req. + * \param[in] mtu_size MTU size of L2CAP channel. + * \param[in] mode_bits L2CAP modes that the channel can be used. Valid values are combinations of \ref BTIF_BR_L2CAP_MODE. + * \param[in] flush_tout Flush timeout value to use for data transmitted on the channel. 0xFFFF for no flush. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_PROTO_REG_RSP: + { + T_BTIF_L2C_PROTO_REG_RSP *p_rsp = &p_msg->p.l2c_proto_reg_rsp; + + if (!p_rsp->cause) + { + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + btif_l2c_conn_req(0x17, 0x0017, 0x01, 672, bd_addr, BTIF_L2C_MODE_BASIC, 0xFFFF); + } + } + break; + + case BTIF_MSG_L2C_CONN_RSP: + { + T_BTIF_L2C_CONN_RSP *p_rsp = &p_msg->p.l2c_conn_rsp; + APP_PRINT_TRACE("L2CAP connect reponse: cause 0x%04x", p_rsp->cause); + } + break; + + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + APP_PRINT_TRACE1("L2CAP channel establish result: cause 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_l2c_proto_reg_req(0x17, 0x01, 1); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_conn_req(uint16_t psm, uint16_t uuid, uint8_t *bd_addr, uint16_t proto_id, + uint16_t mtu_size, uint8_t mode_bits, uint16_t flush_tout); + +/** + * btif.h + * + * \brief Send a confirmation for L2CAP channel connect indication. If the + * confirmation was successfully sent and confirm cause is \ref BTIF_L2C_CONN_ACCEPT, + * a message whose type is \ref BTIF_MSG_L2C_CONN_CMPL_INFO and data is + * \ref T_BTIF_L2C_CONN_CMPL_INFO will be received in the callback + * function registered by \ref btif_register_req to tell the channel + * establish result. The function can only be used when receive \ref + * BTIF_MSG_L2C_CONN_IND message in the callback function. + * + * \param[in] cause Confirm cause for L2CAP channel connection request. \ref BTIF_L2C_CONN_ACCEPT to accept the connection, otherwise reject. + * \param[in] cid Local CID received in \ref BTIF_MSG_L2C_CONN_IND. + * \param[in] mtu_size MTU size of L2CAP channel. + * \param[in] mode_bits L2CAP modes that the channel can be used. Valid values are combinations of \ref BTIF_BR_L2CAP_MODE. + * \param[in] flush_tout Flush timeout value to use for data transmitted on the channel. 0xFFFF for no flush. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_IND: + { + T_BTIF_L2C_CONN_IND *p_ind = &p_msg->p.l2c_conn_ind; + + btif_l2c_conn_cfm(BTIF_L2C_CONN_ACCEPT, p_ind->cid, 672, BTIF_L2C_MODE_BASIC, 0xFFFF); + } + break; + + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + APP_PRINT_TRACE1("L2CAP channel establish result: cause 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_conn_cfm(T_BTIF_L2C_CONN_CAUSE cause, uint16_t cid, uint16_t mtu_size, + uint8_t mode_bits, uint16_t flush_tout); + +/** + * btif.h + * + * \brief Get buffer from Bluetooth stack to put in L2CAP data which will be sent to remote device. + * + * \param[in] size Length of L2CAP data. + * \param[in] offset Offset of real L2CAP data in the buffer. Offset value can be get from \ref BTIF_MSG_L2C_CONN_CMPL_INFO message. + * \param[in] ack Whether need an ack when the buffer was released. If set to true, \ref BTIF_MSG_L2C_DATA_RSP message will be + * received in the callback function registered by \ref btif_register_req. + * + * \return The address of the allocated buffer. If the address in NULL, the buffer was get failed. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + + if (!p_info->cause) + { + uint8_t *p_buffer = btif_get_l2c_buf(330, p_info->ds_data_offset, false); + + if (p_buffer) + { + // ... + // Fill in the buffer with SCO data + // ... + + btif_l2c_data_req(p_buffer, p_info->ds_data_offset, p_info->cid, 330, false); + } + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +void *btif_get_l2c_buf(uint16_t size, uint16_t offset, bool ack); + +/** + * btif.h + * + * \brief Send a request to send L2CAP data to remote device. + * + * \param[in] p_buf Address of L2CAP data buffer which is allocated by \ref btif_get_l2c_buf. + * \param[in] offset Offset of real L2CAP data in the buffer. Offset value can be get from \ref BTIF_MSG_L2C_CONN_CMPL_INFO message. + * \param[in] cid Local CID. The value can be get from \ref BTIF_MSG_L2C_CONN_CMPL_INFO message. + * \param[in] length Length of real L2CAP data. + * \param[in] auto_flush Whether the L2CAP data can be flushed or not. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + + if (!p_info->cause) + { + uint8_t *p_buffer = btif_get_l2c_buf(330, p_info->ds_data_offset, false); + + if (p_buffer) + { + // ... + // Fill in the buffer with SCO data + // ... + + btif_l2c_data_req(p_buffer, p_info->ds_data_offset, p_info->cid, 330, false); + } + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_data_req(void *p_buf, uint16_t offset, uint16_t cid, + uint16_t length, bool auto_flush); + +/** + * btif.h + * + * \brief Send a request to disconnect a L2CAP channel. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_L2C_DISCONN_RSP + * and data is \ref T_BTIF_L2C_DISCONN_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param[in] cid Local CID. The value can be get from \ref BTIF_MSG_L2C_CONN_CMPL_INFO message. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + + if (!p_info->cause) + { + btif_l2c_disconn_req(p_info->cid); + } + } + break; + + case BTIF_MSG_L2C_DISCONN_RSP: + { + T_BTIF_L2C_DISCONN_RSP *p_rsp = &p_msg->p.l2c_disconn_rsp; + + APP_PRINT_TRACE1("L2CAP channel disconnect response: status 0x%04x", + p_rsp->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_disconn_req(uint16_t cid); + +/** + * btif.h + * + * \brief Send a confirmation for L2CAP channel disconnect indication. The + * function can only be used when receive \ref BTIF_MSG_L2C_DISCONN_IND + * message in the callback function registered by \ref btif_register_req. + * + * \param[in] cid Local CID. The value can be get from \ref BTIF_MSG_L2C_DISCONN_IND message. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_DISCONN_IND: + { + T_BTIF_L2C_DISCONN_IND *p_ind = &p_msg->p.l2c_disconn_ind; + btif_l2c_disconn_cfm(p_ind->cid); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_disconn_cfm(uint16_t cid); + +/** + * btif.h + * + * \brief Send a request to register/deregister a security entry over L2CAP. + * The security will be used when establishing a L2CAP channel. If the + * request was successfully sent, a message whose type is \ref BTIF_MSG_L2C_SEC_REG_RSP + * and data is \ref T_BTIF_L2C_SEC_REG_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param active Register/Deregister the security entry. + * \param psm PSM value for protocol. + * \param server_chann Local server channel number for RFCOMM, for other protocols set to 0. + * \param uuid UUID for profiles over rfcomm or UUID for other protocols except RFCOMM. + * \param requirement Security requirement of the entry. Valid values are combinations of \ref BTIF_BR_SEC. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_SEC_REG_RSP: + { + T_BTIF_L2C_SEC_REG_RSP *p_rsp = &p_msg->p.l2c_sec_reg_rsp; + APP_PRINT_TRACE1("Register L2CAP security entry response: cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + btif_l2c_sec_reg_req(1, 0x17, 0, 0x17, BTIF_BR_SEC_AUTHEN | BTIF_BR_SEC_MITM | BTIF_BR_SEC_ENCRYPT); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_l2c_sec_reg_req(uint8_t active, uint16_t psm, uint16_t server_chann, + uint16_t uuid, uint8_t requirement); + +/** + * btif.h + * + * \brief Send a request to start authentication for a profile on RFCOMM channel. + * If the request was successfully sent, a message whose type is \ref + * BTIF_MSG_RFC_AUTHEN_RSP and data is \ref T_BTIF_RFC_AUTHEN_RSP will + * be received in the callback function registered by \ref btif_register_req. + * + * \param bd_addr Bluetooth address of remote device. + * \param cid L2CAP local CID. + * \param dlci DLCI value for the RFCOMM channel. + * \param uuid UUID for profiles over rfcomm. + * \param outgoing Direction of the profile over rfcomm channel. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_RFC_AUTHEN_RSP: + { + T_BTIF_RFC_AUTHEN_RSP *p_rsp = &p_msg->p.rfc_authen_rsp; + APP_PRINT_TRACE1("RFCOMM authentication response: cause 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // Connect profile over RFCOMM. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + btif_rfc_authen_req(bd_addr, 0x40, 0x12, 0x111E, 0); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_rfc_authen_req(uint8_t *bd_addr, uint16_t cid, uint16_t dlci, + uint16_t uuid, uint8_t outgoing); + +/** + * btif.h + * + * \brief Send a request to create a SCO/eSCO connection. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_SCO_CONN_RSP + * and data is \ref T_BTIF_SCO_CONN_RSP will be received in the callback + * function registered by \ref btif_register_req to indicate whether + * the procedure was started successfully. If the procedure was started, + * another message whose type is \ref BTIF_MSG_SCO_CONN_CMPL_INFO and + * data is \ref T_BTIF_SCO_CONN_CMPL_INFO will also be received to tell + * the result of connection establishment. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] tx_bandwidth Transmit bandwidth in octets per second. + * \param[in] rx_bandwidth Receive bandwidth in octets per second. + * \param[in] max_latency A value in milliseconds representing upper limit of the sum of the synchronous interval. Valid between 0x0004 to 0xFFFE. + * \param[in] voice_setting Voice setting bitmap. + * \param[in] retrans_effort Retransmit effort. + * \arg \c 0x00 No retransmissions. + * \arg \c 0x01 At least one retransmission, optimize for power consumption. + * \arg \c 0x02 At least one retransmission, optimize for link quality. + * \arg \c 0xFF Don't care. + * \param[in] packet_type Transmit packet type. Valid values are combinations of \ref BTIF_BR_SCO_PKT_TYPE. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_CONN_RSP: + { + T_BTIF_SCO_CONN_RSP *p_rsp = &p_msg->p.sco_conn_rsp; + APP_PRINT_TRACE1("SCO connect response: cause 0x%04x", p_rsp->cause); + } + break; + + case BTIF_MSG_SCO_CONN_CMPL_INFO: + { + T_BTIF_SCO_CONN_CMPL_INFO *p_info = &p_msg->p.sco_conn_cmpl_info; + APP_PRINT_TRACE1("SCO connection establish result: cause 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + uint8_t bd_addr[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; + btif_sco_conn_req(bd_addr, 8000, 8000, 7, 0x0360, 0, BTIF_PKT_TYPE_EV3 | BTIF_PKT_TYPE_EV4 | BTIF_PKT_TYPE_EV5); + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sco_conn_req(uint8_t *bd_addr, uint32_t tx_bandwidth, uint32_t rx_bandwidth, + uint16_t max_latency, uint16_t voice_setting, uint8_t retrans_effort, uint16_t packet_type); + +/** + * btif.h + * + * \brief Send a confirmation for SCO/eSCO connect indication. If the confirmation + * was successfully sent and confirm cause is \ref BTIF_CAUSE_ACCEPT, + * a message whose type is \ref BTIF_MSG_SCO_CONN_CMPL_INFO and data is + * \ref T_BTIF_SCO_CONN_CMPL_INFO will be received in the callback + * function registered by \ref btif_register_req to tell the connection + * establish result. The function can only be used when receive \ref + * BTIF_MSG_SCO_CONN_IND message in the callback function. + * + * \param[in] bd_addr Bluetooth address of remote device. + * \param[in] tx_bandwidth Transmit bandwidth in octets per second. + * \param[in] rx_bandwidth Receive bandwidth in octets per second. + * \param[in] max_latency A value in milliseconds representing upper limit of the sum of the synchronous interval. Valid between 0x0004 to 0xFFFE. + * \param[in] voice_setting Voice setting bitmap. + * \param[in] retrans_effort Retransmit effort. + * \arg \c 0x00 No retransmissions. + * \arg \c 0x01 At least one retransmission, optimize for power consumption. + * \arg \c 0x02 At least one retransmission, optimize for link quality. + * \arg \c 0xFF Don't care. + * \param[in] packet_type Transmit packet type. Valid values are combinations of \ref BTIF_BR_SCO_PKT_TYPE. + * \param[in] cause Confirm cause for SCO connection request. \ref BTIF_CAUSE_ACCEPT to accept the connection, otherwise reject. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_CONN_IND: + { + T_BTIF_SCO_CONN_IND *p_ind = &p_msg->p.sco_conn_ind; + + btif_sco_conn_cfm(p_ind->bd_addr, 8000, 8000, 13, 0x0363, 1, + BTIF_PKT_TYPE_EV3 | BTIF_PKT_TYPE_EV4 | BTIF_PKT_TYPE_EV5, + BTIF_CAUSE_ACCEPT); + } + break; + + case BTIF_MSG_SCO_CONN_CMPL_INFO: + { + T_BTIF_SCO_CONN_CMPL_INFO *p_info = &p_msg->p.sco_conn_cmpl_info; + APP_PRINT_TRACE1("SCO connection establish result: cause 0x%04x", p_info->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sco_conn_cfm(uint8_t *bd_addr, uint32_t tx_bandwidth, uint32_t rx_bandwidth, + uint16_t max_latency, uint16_t voice_setting, uint8_t retrans_effort, + uint16_t packet_type, T_BTIF_CAUSE cause); + +/** + * btif.h + * + * \brief Get buffer from Bluetooth stack to put in SCO data which will be sent to remote device. + * + * \param[in] len Length of SCO data to put into the buffer. + * + * \return The address of the allocated buffer. If the address in NULL, the + * buffer was get failed. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_CONN_CMPL_INFO: + { + T_BTIF_SCO_CONN_CMPL_INFO *p_info = &p_msg->p.sco_conn_cmpl_info; + + if (!p_info->cause) + { + uint8_t *p_buffer = btif_sco_buffer_get(60); + + if (p_buffer) + { + // ... + // Fill in the buffer with SCO data + // ... + + btif_sco_data_req(p_info->handle, p_buffer, 60); + } + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +void *btif_sco_buffer_get(uint8_t len); + +/** + * btif.h + * + * \brief Send a request to send SCO data to remote device. + * + * \param[in] handle Connection handle of the SCO/eSCO link. + * \param[in] p_buf Address of SCO data buffer which is get by \ref btif_sco_buffer_get. + * \param[in] len Length of SCO data buffer. Must match the one in \ref btif_sco_buffer_get. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_CONN_CMPL_INFO: + { + T_BTIF_SCO_CONN_CMPL_INFO *p_info = &p_msg->p.sco_conn_cmpl_info; + + if (!p_info->cause) + { + uint8_t *p_buffer = btif_sco_buffer_get(60); + + if (p_buffer) + { + // ... + // Fill in the buffer with SCO data + // ... + + btif_sco_data_req(p_info->handle, p_buffer, 60); + } + } + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sco_data_req(uint16_t handle, void *p_buf, uint8_t len); + +/** + * btif.h + * + * \brief Send a confirmation for SCO data indication. The function can + * only be used when receive \ref BTIF_MSG_SCO_DATA_IND message in the + * callback function registered by \ref btif_register_req. + * + * \param[in] p_buf Address of SCO data buffer. Must be same as that in \ref BTIF_MSG_SCO_DATA_IND message. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_DATA_IND: + { + T_BTIF_SCO_DATA_IND *p_ind = &p_msg->p.sco_data_ind; + btif_sco_data_cfm(p_ind->p_buf); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sco_data_cfm(uint8_t *p_buf); + +/** + * btif.h + * + * \brief Send a request to disconnect a SCO/eSCO connection. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_SCO_DISCONN_RSP + * and data is \ref T_BTIF_SCO_DISCONN_RSP will be received in the callback + * function registered by \ref btif_register_req. + * + * \param[in] handle Connection handle of the SCO/eSCO link. The handle can be get in \ref T_BTIF_SCO_CONN_CMPL_INFO message. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_CONN_CMPL_INFO: + { + T_BTIF_SCO_CONN_CMPL_INFO *p_info = &p_msg->p.sco_conn_cmpl_info; + + if (!p_info->cause) + { + btif_sco_disconn_req(p_info->handle); + } + } + break; + + case BTIF_MSG_SCO_DISCONN_RSP: + { + T_BTIF_SCO_DISCONN_RSP *p_rsp = &p_msg->p.sco_disconn_rsp; + + APP_PRINT_TRACE2("SCO disconnect response: status 0x%04x, reason 0x%04x", + p_rsp->cause, p_rsp->reason); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sco_disconn_req(uint16_t handle); + +/** + * btif.h + * + * \brief Send a confirmation for SCO/eSCO disconnect indication. The function + * can only be used when receive \ref BTIF_MSG_SCO_DISCONN_IND message + * in the callback function registered by \ref btif_register_req. + * + * \param[in] handle Connection handle of the SCO/eSCO link. + * + * \return The status of sending the confirmation. + * \retval true The confirmation was successfully sent. + * \retval false The confirmation was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_SCO_DISCONN_IND: + { + T_BTIF_SCO_DISCONN_IND *p_ind = &p_msg->p.sco_disconn_ind; + btif_sco_disconn_cfm(p_ind->handle); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_sco_disconn_cfm(uint16_t handle); + +/** + * btif.h + * + * \brief Send a request to disconnect an ACL link. If the request was + * successfully sent, a message whose type is \ref BTIF_MSG_ACL_DISCONN_RSP + * and data is \ref T_BTIF_ACL_DISCONN_RSP will be received in the callback + * function registered by \ref btif_register_req. If the ACL link was + * successfully disconnected, \ref BTIF_MSG_ACL_STATUS_INFO message will + * also be received with ACL status as \ref BTIF_ACL_CONN_DISCONN in the + * message data. To disconnect an ACL link, it must be connected, + * which can be sure by receiving \ref BTIF_MSG_ACL_STATUS_INFO message + * with ACL status as \ref BTIF_ACL_CONN_SUCCESS in the message data. + * + * \param[in] bd_addr Bluetooth address of remote device. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_SUCCESS: + btif_acl_disconn_req(p_info->bd_addr); + break; + + case BTIF_ACL_CONN_DISCONN: + APP_PRINT_TRACE0("ACL link disconnected"); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_ACL_DISCONN_RSP: + { + T_BTIF_ACL_DISCONN_RSP *p_rsp = &p_msg->p.acl_disconn_rsp; + APP_PRINT_TRACE2("ACL link disconnect response: status 0x%04x, reason 0x%04x", + p_rsp->cause, p_rsp->reason); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_acl_disconn_req(uint8_t *bd_addr); + +/** + * btif.h + * + * \brief Send a request to specify Quality of Service parameters for an ACL + * link. If the request was successfully sent, a message whose type is + * \ref BTIF_MSG_SETUP_QOS_RSP and data is \ref T_BTIF_SETUP_QOS_RSP + * will be received in the callback function registered by \ref btif_register_req. + * To set the QOS of an ACL link, the link must be connected, which + * can be sure by receiving \ref BTIF_MSG_ACL_STATUS_INFO message + * with ACL status as \ref BTIF_ACL_CONN_SUCCESS in the message data. + * + * \param[in] handle Connection handle of the link, which can be get by \ref BTIF_MSG_ACL_STATUS_INFO message with ACL status as \ref BTIF_ACL_CONN_SUCCESS. + * \param[in] flags Reserved for feature use. + * \param[in] type Service type. + * \arg \c 0 No traffic. + * \arg \c 1 Best effort. + * \arg \c 2 Guaranteed. + * \param[in] token_rate Token rate in octets per second. + * \param[in] peak_bandwdith Peak bandwidth in octets per second. + * \param[in] latency Latency in microseconds. + * \param[in] delay_variation Delay variation in microseconds. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_ACL_STATUS_INFO: + { + T_BTIF_ACL_STATUS_INFO *p_info = &p_msg->p.acl_status_info; + + switch (p_info->status) + { + case BTIF_ACL_CONN_SUCCESS: + legacy_send_setup_qos_req(p_info->p.conn_success.handle, 0, + QOS_GUARANTEED, 11250, 0, 10000 * 2, 0); + break; + + default: + break; + } + } + break; + + case BTIF_MSG_SETUP_QOS_RSP: + { + T_BTIF_SETUP_QOS_RSP *p_rsp = &p_msg->p.setup_qos_rsp; + APP_PRINT_TRACE1("Setup QOS response: status 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_setup_qos_req(uint16_t handle, uint8_t flags, uint8_t type, uint32_t token_rate, + uint32_t peak_bandwdith, uint32_t latency, uint32_t delay_variation); + +/** + * btif.h + * + * \brief Send a request to set local channel into busy/idle state in L2CAP + * ERTM mode. If the request was successfully sent, a message whose type + * is \ref BTIF_MSG_L2C_SET_LOCAL_BUSY_RSP and data is \ref T_BTIF_L2C_SET_LOCAL_BUSY_RSP + * will be received in the callback function registered by \ref btif_register_req. + * + * \param[in] cid Local CID. The value can be get from \ref BTIF_MSG_L2C_CONN_CMPL_INFO message. + * \param[in] busy Set local to busy state or not. + * \arg \c true Set local to busy state. + * \arg \c false Set local to idle state. + * + * \return The status of sending the request. + * \retval true The request was successfully sent. + * \retval false The request was failed to sent. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + + if (!p_info->cause) + { + btif_set_l2c_local_busy_req(p_info->cid, true); + } + + } + break; + + case BTIF_MSG_L2C_SET_LOCAL_BUSY_RSP: + { + T_BTIF_L2C_SET_LOCAL_BUSY_RSP *p_rsp = &p_msg->p.l2c_set_local_busy_rsp; + APP_PRINT_TRACE1("Set local busy state response: status 0x%04x", p_rsp->cause); + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_set_l2c_local_busy_req(uint16_t cid, bool busy); + +/** + * btif.h + * + * \brief Select reject mode used in L2CAP ERTM mode. + * + * \param[in] mode Reject mode used in L2CAP ERTM mode. Valid values are \ref BTIF_BR_L2CAP_REJ_MODE. + * + * \return The status of selecting reject mode. + * \retval true Reject mode was successfully set. + * \retval false Reject mode was failed to set. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + + if (!p_info->cause) + { + btif_set_l2c_rej_mode(BTIF_L2C_ERTM_REJ); + } + + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_set_l2c_rej_mode(uint8_t mode); + +/** + * btif.h + * + * \brief Enable/Disable FCS usage in L2CAP ERTM mode. + * + * \param[in] flag FCS usage flag in L2CAP ERTM mode. + * \arg \c 1 Prefer to use FCS in L2CAP ERTM mode. + * \arg \c 0 Do not use FCS in L2CAP ERTM mode. + * + * \return The status of setting FCS usage. + * \retval true FCS usage was successfully set. + * \retval false RFCS usage was failed to set. + * + * Example usage + \code{.c} + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + + if (!p_info->cause) + { + btif_set_l2c_fcs(1); + } + + } + break; + + default: + break; + } + } + \endcode + * + * \ingroup BTIF + */ +bool btif_set_l2c_fcs(uint8_t flag); + +/** + * btif.h + * + * \brief Get total number for L2CAP buffer which will send \ref BTIF_MSG_L2C_DATA_RSP + * when released. This is mainly used for data flow control from upper + * layer to Bluetooth stack. + * + * \param[in] None. + * + * \return Total number for L2CAP buffer which will send \ref BTIF_MSG_L2C_DATA_RSP when released. + * + * Example usage + \code{.c} + uint8_t data_quota; + + void app_handle_btif_msg(T_BTIF_UP_MSG *p_msg) + { + switch (p_msg->command) + { + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + T_BTIF_L2C_CONN_CMPL_INFO *p_info = &p_msg->p.l2c_conn_cmpl_info; + uint8_t i; + + if (!p_info->cause) + { + for (i = 0; i < data_quota; i++) + { + // ... + // Get a L2CAP buffer with ack flag set to true. + // Fill the buffer and send it. + // ... + } + } + + } + break; + + case BTIF_MSG_L2C_CONN_CMPL_INFO: + { + // ... + // Get a L2CAP buffer with ack flag set to true. + // Fill the buffer and send it. + // ... + } + break; + + default: + break; + } + } + + void test(void) + { + // ... + // Create app task. + // Register callback function. + // ... + + data_quota = btif_get_l2c_data_quota(); + } + \endcode + * + * \ingroup BTIF + */ +uint8_t btif_get_l2c_data_quota(void); + +bool btif_lt_addr_set_req(uint8_t lt_addr); + +bool btif_lt_addr_del_req(uint8_t lt_addr); + +bool btif_sync_train_param_set_req(uint16_t min_interval, uint16_t max_interval, + uint32_t sync_train_tout, uint8_t srv_data); + +bool btif_sync_train_req(void); + +bool btif_sync_train_rcv_req(uint8_t *bd_addr, uint16_t sync_scan_tout, + uint16_t sync_scan_window, uint16_t sync_scan_interval); + +bool btif_csb_set_req(uint8_t enable, uint8_t lt_addr, uint8_t lpo_allowed, uint16_t pkt_type, + uint16_t min_interval, uint16_t max_interval, uint16_t csb_supv_tout); + +bool btif_csb_rcv_set_req(uint8_t enable, uint8_t *bd_addr, uint8_t lt_addr, uint16_t interval, + uint32_t clk_offset, uint32_t next_broadcast_clk, uint16_t csb_supv_tout, + uint8_t remote_timing_acc, uint8_t skip, uint16_t pkt_type, uint8_t *afh_chann_map); + +bool btif_csb_data_req(uint8_t lt_addr, void *p_data, uint16_t length); + +#ifdef __cplusplus +} +#endif + +#endif /* _BTIF_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_common_api.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_common_api.c new file mode 100644 index 00000000..40e69a00 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_common_api.c @@ -0,0 +1,209 @@ +#include +#include + +#if F_BT_LE_BTIF_SUPPORT + +void hrp_register_req(uint16_t len, uint8_t *p_param_list) +{ +// btif_register_req() +} + +void hrp_release_req(uint16_t len, uint8_t *p_param_list) +{ + //btif_release_req() +} +void hrp_dev_cfg_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_DEV_CFG_OPCODE cfg_op = (T_BTIF_DEV_CFG_OPCODE)p_param_list[0]; + //uint8_t *reqParam = &p_param_list[1]; + APP_PRINT_INFO1("hrp_dev_cfg_req op= %d", cfg_op); + switch (cfg_op) + { + /* + case BTIF_DEV_CFG_OP_NAME : + { + T_BTIF_DEV_CFG_DEV *p_name = (T_BTIF_DEV_CFG_DEV *)reqParam; + btif_dev_cfg_name_req(p_name->cod, p_name->name); + break; + } + + case BTIF_DEV_CFG_OP_DID_EIR: + { + T_BTIF_DEV_CFG_DID_EIR *p_did_eir = (T_BTIF_DEV_CFG_DID_EIR *)reqParam; + btif_dev_did_eir_cfg_req(p_did_eir->vendor_id, p_did_eir->vendor_id_src, + p_did_eir->product_id, p_did_eir->product_version); + break; + } + + case BTIF_DEV_CFG_OP_EXT_EIR: + { + T_BTIF_DEV_CFG_EXT_EIR *p_ext_eir = (T_BTIF_DEV_CFG_EXT_EIR *)reqParam; + btif_dev_ext_eir_cfg_req(p_ext_eir->p_data); + break; + } + + case BTIF_DEV_CFG_OP_PAGE_SCAN: + { + T_BTIF_DEV_CFG_PAGE_SCAN *p_page_scan = (T_BTIF_DEV_CFG_PAGE_SCAN *)reqParam; + btif_dev_page_scan_cfg_req(p_page_scan->scan_type, p_page_scan->interval, + p_page_scan->window, p_page_scan->page_tout); + break; + } + case BTIF_DEV_CFG_OP_INQUIRY_SCAN: + { + T_BTIF_DEV_CFG_INQUIRY_SCAN *p_inquiry_scan = (T_BTIF_DEV_CFG_INQUIRY_SCAN *)reqParam; + btif_dev_inquiry_scan_cfg_req(p_inquiry_scan->scan_type, p_inquiry_scan->interval, + p_inquiry_scan->window); + break; + } + case BTIF_DEV_CFG_OP_INQUIRY_MODE: + { + T_BTIF_DEV_CFG_INQUIRY_MODE *p_inquiry_mode = (T_BTIF_DEV_CFG_INQUIRY_MODE *)reqParam; + btif_dev_inquiry_mode_cfg_req(p_inquiry_mode->mode); + break; + } + case BTIF_DEV_CFG_OP_LINK_POLICY: + { + T_BTIF_DEV_CFG_LINK_POLICY *p_link_policy = (T_BTIF_DEV_CFG_LINK_POLICY *)reqParam; + btif_dev_link_policy_cfg_req(p_link_policy->policy, p_link_policy->supv_tout); + break; + } + case BTIF_DEV_CFG_OP_BT_MODE: + { + T_BTIF_DEV_CFG_BT_MODE *p_bt_mode = (T_BTIF_DEV_CFG_BT_MODE *)reqParam; + btif_dev_bt_mode_cfg_req(p_bt_mode->mode); + break; + } + + case BTIF_DEV_CFG_OP_ACCEPT_CONN_ROLE: + { + T_BTIF_DEV_CFG_ACCEPT_ROLE *p_accept_role = (T_BTIF_DEV_CFG_ACCEPT_ROLE *)reqParam; + btif_dev_accept_role_cfg_req(p_accept_role->role); + break; + } + */ + default: + break; + } + + +} + +void hrp_read_rssi_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_READ_RSSI_REQ *p_req = (T_BTIF_READ_RSSI_REQ *)p_param_list; + if (len != sizeof(T_BTIF_READ_RSSI_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_READ_RSSI_REQ) = %d", + len, sizeof(T_BTIF_READ_RSSI_REQ)); + return; + } + btif_read_rssi_req(p_req->bd_addr, p_req->remote_addr_type); +} +void hrp_vendor_cmd_req(uint16_t len, uint8_t *p_param_list) +{ + +} + +void hrp_pairable_mode_set_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_PAIRABLE_MODE_SET_REQ *p_req = (T_BTIF_PAIRABLE_MODE_SET_REQ *)p_param_list; + if (len != sizeof(T_BTIF_PAIRABLE_MODE_SET_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_PAIRABLE_MODE_SET_REQ) = %d", + len, sizeof(T_BTIF_PAIRABLE_MODE_SET_REQ)); + return; + } + btif_pairable_mode_set_req(p_req->enable, p_req->enable, p_req->requirements, + p_req->io_capabilities, + p_req->oob_present); +} + +void hrp_user_passkey_req_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_USER_PASSKEY_REQ_CFM *p_cfm = (T_BTIF_USER_PASSKEY_REQ_CFM *)p_param_list; + if (len != sizeof(T_BTIF_USER_PASSKEY_REQ_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_USER_PASSKEY_REQ_CFM) = %d", + len, sizeof(T_BTIF_USER_PASSKEY_REQ_CFM)); + return; + } + APP_PRINT_TRACE0("hrp_user_passkey_req_cfm"); + btif_user_passkey_req_cfm(p_cfm->bd_addr, p_cfm->remote_addr_type, p_cfm->cause); +} + +void hrp_user_passkey_req_reply_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_USER_PASSKEY_REQ_REPLY_REQ *p_req = (T_BTIF_USER_PASSKEY_REQ_REPLY_REQ *)p_param_list; + if (len != sizeof(T_BTIF_USER_PASSKEY_REQ_REPLY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_USER_PASSKEY_REQ_REPLY_REQ) = %d", + len, sizeof(T_BTIF_USER_PASSKEY_REQ_REPLY_REQ)); + return; + } + btif_user_passkey_req_reply_req(p_req->bd_addr, p_req->remote_addr_type, p_req->passkey, + p_req->cause); +} + +void hrp_authen_result_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_AUTHEN_RESULT_CFM *p_cfm = (T_BTIF_AUTHEN_RESULT_CFM *)p_param_list; + if (len != sizeof(T_BTIF_AUTHEN_RESULT_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_AUTHEN_RESULT_CFM) = %d", + len, sizeof(T_BTIF_AUTHEN_RESULT_CFM)); + return; + } + btif_authen_result_cfm(p_cfm->bd_addr, p_cfm->remote_addr_type, + p_cfm->key_type, + p_cfm->cause); +} + +void hrp_authen_key_req_cfm(uint16_t len, uint8_t *p_param_list) +{ + uint8_t bd_addr[6]; + uint8_t remote_addr_type; + uint8_t key_len; + uint8_t link_key[28]; + uint8_t key_type; + uint8_t cause; + uint8_t pos = 0; + + memcpy(bd_addr, p_param_list + pos, 6); pos += 6; + LE_ARRAY_TO_UINT8(remote_addr_type, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(key_len, p_param_list + pos); pos++; + memcpy(link_key, p_param_list + pos, 28); pos += 28; + LE_ARRAY_TO_UINT8(key_type, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos++; + + btif_authen_key_req_cfm(bd_addr, (T_BTIF_REMOTE_ADDR_TYPE)remote_addr_type, key_len, link_key, + (T_BTIF_KEY_TYPE)key_type, (T_BTIF_CAUSE)cause); +} + +void hrp_user_cfm_req_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_USER_CFM_REQ_CFM *p_cfm = (T_BTIF_USER_CFM_REQ_CFM *)p_param_list; + if (len != sizeof(T_BTIF_USER_CFM_REQ_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_USER_CFM_REQ_CFM) = %d", + len, sizeof(T_BTIF_USER_CFM_REQ_CFM)); + return; + } + btif_user_cfm_req_cfm(p_cfm->bd_addr, p_cfm->remote_addr_type, p_cfm->cause); +} +#if F_BT_KEY_PRESS_SUPPORT +void hrp_keypress_notif_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_KEYPRESS_NOTIF_REQ *p_req = (T_BTIF_KEYPRESS_NOTIF_REQ *)p_param_list; + if (len != sizeof(T_BTIF_KEYPRESS_NOTIF_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_KEYPRESS_NOTIF_REQ) = %d", + len, sizeof(T_BTIF_KEYPRESS_NOTIF_REQ)); + return; + } + btif_keypress_notif_req(p_req->bd_addr, p_req->remote_addr_type, p_req->event_type); +} + + +#endif +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_common_api.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_common_api.h new file mode 100644 index 00000000..c3c2ae59 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_common_api.h @@ -0,0 +1,190 @@ +#ifndef _HRP_BTIF_COMMON_API_H_ +#define _HRP_BTIF_COMMON_API_H_ + +#include +#include +#include + +typedef struct +{ + uint32_t cod; + uint8_t name[BTIF_NAME_LENGTH]; +} T_BTIF_DEV_CFG_DEV; + +typedef struct +{ + uint16_t vendor_id; + uint16_t vendor_id_src; + uint16_t product_id; + uint16_t product_version; +} T_BTIF_DEV_CFG_DID_EIR; + +typedef struct +{ + uint8_t *p_data; +} T_BTIF_DEV_CFG_EXT_EIR; + +typedef struct +{ + T_BTIF_BR_PAGE_SCAN_TYPE scan_type; + uint16_t interval; + uint16_t window; + uint16_t page_tout; +} T_BTIF_DEV_CFG_PAGE_SCAN; + +typedef struct +{ + T_BTIF_BR_INQUIRY_SCAN_TYPE scan_type; + uint16_t interval; + uint16_t window; +} T_BTIF_DEV_CFG_INQUIRY_SCAN; + +typedef struct +{ + T_BTIF_BR_INQUIRY_MODE mode; +} T_BTIF_DEV_CFG_INQUIRY_MODE; + +typedef struct +{ + uint16_t policy; + uint16_t supv_tout; +} T_BTIF_DEV_CFG_LINK_POLICY; + +typedef struct +{ + int16_t tx_power; +} T_BTIF_DEV_CFG_MAX_TX_POWER; + +typedef struct +{ + T_BTIF_BT_MODE mode; +} T_BTIF_DEV_CFG_BT_MODE; + +typedef struct +{ + uint8_t role; +} T_BTIF_DEV_CFG_ACCEPT_ROLE; + +typedef struct +{ + uint32_t fixed_value; +} T_BTIF_DEV_CFG_PASSKEY_VALUE; + +typedef struct +{ + T_BTIF_DEV_CFG_OPCODE op; + union + { + T_BTIF_DEV_CFG_DEV dev; + T_BTIF_DEV_CFG_DID_EIR did; + T_BTIF_DEV_CFG_EXT_EIR ext_eir; + T_BTIF_DEV_CFG_PAGE_SCAN page_scan; + T_BTIF_DEV_CFG_INQUIRY_SCAN inquiry_scan; + T_BTIF_DEV_CFG_INQUIRY_MODE inquiry_mode; + T_BTIF_DEV_CFG_LINK_POLICY link_policy; + + T_BTIF_DEV_CFG_BT_MODE bt_mode; + T_BTIF_DEV_CFG_ACCEPT_ROLE accept_role; + } p; +} T_BTIF_DEV_CFG_SET_REQ; + +typedef struct +{ + uint8_t bd_addr[6]; + uint8_t conn_type; /* 0: BREDR ACL; 1: SCO; 2: LE */ + bool is_high_priority; +} T_BTIF_ACL_PRIORITY_SET_REQ; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; +} T_BTIF_READ_RSSI_REQ; + +typedef struct +{ + uint16_t command; + uint8_t param_len; + uint8_t param[1]; +} T_BTIF_VENDOR_CMD_REQ; + +typedef struct +{ + bool enable; + uint16_t requirements; + T_BTIF_IOCAP io_capabilities; + bool oob_present; +} T_BTIF_PAIRABLE_MODE_SET_REQ; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_CAUSE cause; +} T_BTIF_USER_PASSKEY_REQ_CFM; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint32_t passkey; + T_BTIF_CAUSE cause; +} T_BTIF_USER_PASSKEY_REQ_REPLY_REQ; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_KEY_TYPE key_type; + T_BTIF_CAUSE cause; +} T_BTIF_AUTHEN_RESULT_CFM; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint8_t key_len; + uint8_t link_key[28]; + T_BTIF_KEY_TYPE key_type; + T_BTIF_CAUSE cause; +} T_BTIF_AUTHEN_KEY_REQ_CFM; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_CAUSE cause; +} T_BTIF_USER_CFM_REQ_CFM; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_KEYPRESS_NOTIF_TYPE event_type; +} T_BTIF_KEYPRESS_NOTIF_REQ; + +void hrp_register_req(uint16_t len, uint8_t *p_param_list); + +void hrp_release_req(uint16_t len, uint8_t *p_param_list); + +void hrp_dev_cfg_req(uint16_t len, uint8_t *p_param_list); + + +void hrp_read_rssi_req(uint16_t len, uint8_t *p_param_list); + +void hrp_vendor_cmd_req(uint16_t len, uint8_t *p_param_list); + +void hrp_pairable_mode_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_user_passkey_req_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_user_passkey_req_reply_req(uint16_t len, uint8_t *p_param_list); + +void hrp_authen_result_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_authen_key_req_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_user_cfm_req_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_keypress_notif_req(uint16_t len, uint8_t *p_param_list); +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_entry.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_entry.c new file mode 100644 index 00000000..15240f69 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_entry.c @@ -0,0 +1,919 @@ +#include +#include +#include +#include +#include +#include +#include +#if F_BT_DLPS_EN +#include +#endif + +#if F_BT_LE_BTIF_SUPPORT + +extern uint8_t btif_get_up_data_len(T_BTIF_UP_MSG *p_msg); +extern T_L2C_DATA_TRANS l2c_data_trans; +T_GATT_DEV_INFO t_gatt_dev_info = {0}; +T_GATT_SRV_TABLE t_srv_table = {0}; + +const P_HRP_BTIF_HANDLER hrp_btif_handle_system[] = +{ + hrp_btif_system_reset, /* 0x00, HRP_SYSTEM_RESET_REQ */ + NULL, /* 0x01, HRP_SYSTEM_RESET_RSP*/ + hrp_btif_system_init, /* 0x02, HRP_SYSTEM_INIT_REQ*/ + NULL, /* 0x03, HRP_SYSTEM_INIT_RSP*/ + NULL, /* 0x04, HRP_SYSTEM_L2C_DATA_TEST_REQ*/ + NULL, /* 0x05, HRP_SYSTEM_L2C_DATA_TEST_CMPL_INFO*/ + hrp_btif_system_le_cfg_passkey_value, /* 0x06, HRP_SYSTEM_LE_CFG_PASSKEY_VALUE_REQ*/ + NULL, /* 0x07, HRP_SYSTEM_LE_CFG_PASSKEY_VALUE_RSP*/ + hrp_btif_system_event_ack, /* 0x08, HRP_SYSTEM_EVENT_ACK*/ + NULL, /* 0x09, HRP_SYSTEM_CMD_ACK*/ + hrp_btif_system_enable_dlps_req, /* 0x0A, HRP_SYSTEM_ENABLE_DLPS_REQ*/ + NULL, /* 0x0B, HRP_SYSTEM_ENABLE_DLPS_RSP*/ + hrp_btif_system_read_dlps_count_req,/* 0x0C, HRP_SYSTEM_READ_DLPS_COUNT_REQ*/ + NULL, /* 0x0D, HRP_SYSTEM_READ_DLPS_COUNT_RSP*/ + +}; + +const P_HRP_BTIF_HANDLER hrp_btif_handle_common[] = +{ + NULL, /* 0x00 */ + hrp_register_req, /* BTIF_MSG_REGISTER_REQ = 0x01, */ + NULL, /* BTIF_MSG_REGISTER_RSP, */ + hrp_release_req, /* BTIF_MSG_RELEASE_REQ, */ + NULL, /* BTIF_MSG_RELEASE_RSP, */ + NULL, /* BTIF_MSG_ACT_INFO, */ + hrp_dev_cfg_req, /* BTIF_MSG_DEV_CFG_REQ, */ + NULL, /* BTIF_MSG_DEV_CFG_RSP, */ + + NULL, /* BTIF_MSG_ACL_STATUS_INFO, */ + NULL, /* BTIF_MSG_ACL_PRIORITY_SET_REQ, */ + NULL, /* BTIF_MSG_ACL_PRIORITY_SET_RSP, */ + + hrp_read_rssi_req, /* BTIF_MSG_READ_RSSI_REQ, */ + NULL, /* BTIF_MSG_READ_RSSI_RSP, */ + hrp_vendor_cmd_req, /* BTIF_MSG_VENDOR_CMD_REQ, */ + NULL, /* BTIF_MSG_VENDOR_CMD_RSP, */ + NULL, /* BTIF_MSG_VENDOR_EVT_INFO, */ + + hrp_pairable_mode_set_req, /* BTIF_MSG_PAIRABLE_MODE_SET_REQ, */ + NULL, /* BTIF_MSG_PAIRABLE_MODE_SET_RSP, */ + NULL, /* BTIF_MSG_USER_PASSKEY_REQ_IND, */ + hrp_user_passkey_req_cfm, /* BTIF_MSG_USER_PASSKEY_REQ_CFM, */ + hrp_user_passkey_req_reply_req, /* BTIF_MSG_USER_PASSKEY_REQ_REPLY_REQ, */ + NULL, /* BTIF_MSG_USER_PASSKEY_REQ_REPLY_RSP, */ + NULL, /* BTIF_MSG_USER_PASSKEY_NOTIF_INFO, */ + NULL, /* BTIF_MSG_AUTHEN_RESULT_IND, */ + hrp_authen_result_cfm, /* BTIF_MSG_AUTHEN_RESULT_CFM, */ + NULL, /* BTIF_MSG_AUTHEN_KEY_REQ_IND, */ + hrp_authen_key_req_cfm, /* BTIF_MSG_AUTHEN_KEY_REQ_CFM, */ + NULL, /* BTIF_MSG_USER_CFM_REQ_IND, */ + hrp_user_cfm_req_cfm, /* BTIF_MSG_USER_CFM_REQ_CFM, */ +#if F_BT_KEY_PRESS_SUPPORT + hrp_keypress_notif_req, /* BTIF_MSG_KEYPRESS_NOTIF_REQ, */ +#else + NULL, +#endif + NULL, /* BTIF_MSG_KEYPRESS_NOTIF_RSP, */ + NULL, /* BTIF_MSG_KEYPRESS_NOTIF_INFO, */ + NULL, /* BTIF_MSG_HW_ERROR_INFO, */ +}; + +const P_HRP_BTIF_HANDLER hrp_btif_handle_ble[] = +{ + NULL, //BTIF_MSG_REMOTE_OOB_REQ_IND = 0x0100, +#if F_BT_LE_SMP_OOB_SUPPORT + hrp_remote_oob_req_cfm, // BTIF_MSG_REMOTE_OOB_REQ_CFM, +#else + NULL, +#endif + hrp_gatt_srv_reg_req, // BTIF_MSG_GATT_SRV_REG_REQ, + NULL, // BTIF_MSG_GATT_SRV_REG_RSP, + hrp_gatt_attr_update_req, // BTIF_MSG_GATT_ATTR_UPDATE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_UPDATE_RSP, + NULL, // BTIF_MSG_GATT_ATTR_UPDATE_STATUS_IND, + hrp_gatt_attr_update_status_cfm, // BTIF_MSG_GATT_ATTR_UPDATE_STATUS_CFM, + NULL, // BTIF_MSG_GATT_ATTR_READ_IND, + hrp_gatt_attr_read_cfm, // BTIF_MSG_GATT_ATTR_READ_CFM, + NULL, // BTIF_MSG_GATT_ATTR_WRITE_REQ_IND, + hrp_gatt_attr_write_req_cfm, // BTIF_MSG_GATT_ATTR_WRITE_REQ_CFM, + NULL, // BTIF_MSG_GATT_ATTR_PREP_WRITE_IND, + hrp_gatt_attr_prep_write_cfm, // BTIF_MSG_GATT_ATTR_PREP_WRITE_CFM, + NULL, // BTIF_MSG_GATT_ATTR_EXEC_WRITE_IND, + hrp_gatt_attr_exec_write_cfm, // BTIF_MSG_GATT_ATTR_EXEC_WRITE_CFM, + NULL, // BTIF_MSG_GATT_ATTR_WRITE_CMD_INFO,//0x110 + NULL, // BTIF_MSG_GATT_ATTR_CCCD_INFO, +#if F_BT_LE_GATT_CLIENT_SUPPORT + hrp_gatt_discovery_req, // BTIF_MSG_GATT_DISCOVERY_REQ, + NULL, // BTIF_MSG_GATT_DISCOVERY_RSP, + NULL, // BTIF_MSG_GATT_DISCOVERY_IND, + hrp_gatt_discovery_cfm, // BTIF_MSG_GATT_DISCOVERY_CFM, + hrp_gatt_attr_read_req, // BTIF_MSG_GATT_ATTR_READ_REQ, + NULL, // BTIF_MSG_GATT_ATTR_READ_RSP, +#if F_BT_LE_ATT_READ_MULTI_SUPPORT + hrp_gatt_attr_read_multi_req, // BTIF_MSG_GATT_ATTR_READ_MULTI_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_GATT_ATTR_READ_MULTI_RSP, + hrp_gatt_attr_write_req, // BTIF_MSG_GATT_ATTR_WRITE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_WRITE_RSP, + hrp_gatt_attr_prep_write_req, // BTIF_MSG_GATT_ATTR_PREP_WRITE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_PREP_WRITE_RSP, + hrp_gatt_attr_exec_write_req, // BTIF_MSG_GATT_ATTR_EXEC_WRITE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_EXEC_WRITE_RSP, + + NULL, // BTIF_MSG_GATT_ATTR_IND,//0x120 + hrp_gatt_attr_cfm, // BTIF_MSG_GATT_ATTR_CFM, + NULL, // BTIF_MSG_GATT_ATTR_NOTIF_INFO, +#else + NULL, // BTIF_MSG_GATT_DISCOVERY_REQ, + NULL, // BTIF_MSG_GATT_DISCOVERY_RSP, + NULL, // BTIF_MSG_GATT_DISCOVERY_IND, + NULL, // BTIF_MSG_GATT_DISCOVERY_CFM, + NULL, // BTIF_MSG_GATT_ATTR_READ_REQ, + NULL, // BTIF_MSG_GATT_ATTR_READ_RSP, +#if F_BT_LE_ATT_READ_MULTI_SUPPORT + NULL, // BTIF_MSG_GATT_ATTR_READ_MULTI_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_GATT_ATTR_READ_MULTI_RSP, + NULL, // BTIF_MSG_GATT_ATTR_WRITE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_WRITE_RSP, + NULL, // BTIF_MSG_GATT_ATTR_PREP_WRITE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_PREP_WRITE_RSP, + NULL, // BTIF_MSG_GATT_ATTR_EXEC_WRITE_REQ, + NULL, // BTIF_MSG_GATT_ATTR_EXEC_WRITE_RSP, + + NULL, // BTIF_MSG_GATT_ATTR_IND,//0x120 + NULL, // BTIF_MSG_GATT_ATTR_CFM, + NULL, // BTIF_MSG_GATT_ATTR_NOTIF_INFO, +#endif + hrp_gatt_security_req, // BTIF_MSG_GATT_SECURITY_REQ, + NULL, // BTIF_MSG_GATT_SECURITY_RSP, + NULL, // BTIF_MSG_GATT_SERVER_STORE_IND, + hrp_gatt_server_store_cfm, // BTIF_MSG_GATT_SERVER_STORE_CFM, + NULL, // BTIF_MSG_GATT_MTU_SIZE_INFO, +#if F_BT_LE_GAP_CENTRAL_SUPPORT + hrp_le_conn_req, // BTIF_MSG_LE_CONN_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_CONN_RSP, + NULL, // BTIF_MSG_LE_CONN_IND, + hrp_le_conn_cfm, // BTIF_MSG_LE_CONN_CFM, + NULL, // BTIF_MSG_LE_CONN_CMPL_INFO, + hrp_le_disconn_req, // BTIF_MSG_LE_DISCONN_REQ, + NULL, // BTIF_MSG_LE_DISCONN_RSP, + NULL, // BTIF_MSG_LE_DISCONN_IND, + hrp_le_disconn_cfm, // BTIF_MSG_LE_DISCONN_CFM,//0x130 + + hrp_le_adv_req, // BTIF_MSG_LE_ADV_REQ, + NULL, // BTIF_MSG_LE_ADV_RSP, + hrp_le_adv_param_set_req, // BTIF_MSG_LE_ADV_PARAM_SET_REQ, + NULL, // BTIF_MSG_LE_ADV_PARAM_SET_RSP, + hrp_le_adv_data_set_req, // BTIF_MSG_LE_ADV_DATA_SET_REQ, + NULL, // BTIF_MSG_LE_ADV_DATA_SET_RSP, + hrp_le_scan_req, // BTIF_MSG_LE_SCAN_REQ, + NULL, // BTIF_MSG_LE_SCAN_RSP, + hrp_le_scan_param_set_req, // BTIF_MSG_LE_SCAN_PARAM_SET_REQ, + NULL, // BTIF_MSG_LE_SCAN_PARAM_SET_RSP, + NULL, // BTIF_MSG_LE_SCAN_INFO, + hrp_le_modify_white_list_req, // BTIF_MSG_LE_MODIFY_WHITE_LIST_REQ, + NULL, // BTIF_MSG_LE_MODIFY_WHITE_LIST_RSP, + hrp_le_conn_update_req, // BTIF_MSG_LE_CONN_UPDATE_REQ, + NULL, // BTIF_MSG_LE_CONN_UPDATE_RSP, + NULL, // BTIF_MSG_LE_CONN_UPDATE_IND,//0x140 +#if F_BT_LE_GAP_CENTRAL_SUPPORT + hrp_le_conn_update_cfm, // BTIF_MSG_LE_CONN_UPDATE_CFM, +#else + NULL, // BTIF_MSG_LE_CONN_UPDATE_CFM, +#endif + NULL, // BTIF_MSG_LE_CONN_PARAM_INFO, + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_EVT_INFO, +#if F_BT_LE_4_2_CONN_PARAM_UPDATE_SUPPORT + hrp_le_conn_param_req_reply_req, // BTIF_MSG_LE_CONN_PARAM_REQ_REPLY_REQ, + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_REPLY_RSP, + hrp_le_conn_param_req_neg_reply_req, // BTIF_MSG_LE_CONN_PARAM_REQ_NEG_REPLY_REQ, + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_NEG_REPLY_RSP, +#else + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_REPLY_REQ, + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_REPLY_RSP, + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_NEG_REPLY_REQ, + NULL, // BTIF_MSG_LE_CONN_PARAM_REQ_NEG_REPLY_RSP, +#endif +#if F_BT_LE_4_1_CBC_SUPPORT + hrp_le_credit_based_conn_req, // BTIF_MSG_LE_CREDIT_BASED_CONN_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_IND, + hrp_le_credit_based_conn_cfm, // BTIF_MSG_LE_CREDIT_BASED_CONN_CFM, + hrp_le_credit_based_disconn_req, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_IND, + hrp_le_credit_based_disconn_cfm, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_CFM, + hrp_le_send_credit_req, // BTIF_MSG_LE_SEND_CREDIT_REQ,//0x150 + NULL, // BTIF_MSG_LE_SEND_CREDIT_RSP, + hrp_le_credit_based_data_req, // BTIF_MSG_LE_CREDIT_BASED_DATA_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DATA_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DATA_IND, + hrp_le_credit_based_data_cfm, // BTIF_MSG_LE_CREDIT_BASED_DATA_CFM, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_CMPL_INFO, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_CREDIT_INFO, + hrp_le_credit_based_security_reg_req, // BTIF_MSG_LE_CREDIT_BASED_SECURITY_REG_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_SECURITY_REG_RSP, + hrp_le_credit_based_psm_reg_req, // BTIF_MSG_LE_CREDIT_BASED_PSM_REG_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_PSM_REG_RSP, +#else + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_IND, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_CFM, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_IND, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DISCONN_CFM, + NULL, // BTIF_MSG_LE_SEND_CREDIT_REQ,//0x150 + NULL, // BTIF_MSG_LE_SEND_CREDIT_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DATA_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DATA_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DATA_IND, + NULL, // BTIF_MSG_LE_CREDIT_BASED_DATA_CFM, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_CMPL_INFO, + NULL, // BTIF_MSG_LE_CREDIT_BASED_CONN_CREDIT_INFO, + NULL, // BTIF_MSG_LE_CREDIT_BASED_SECURITY_REG_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_SECURITY_REG_RSP, + NULL, // BTIF_MSG_LE_CREDIT_BASED_PSM_REG_REQ, + NULL, // BTIF_MSG_LE_CREDIT_BASED_PSM_REG_RSP, +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT + hrp_le_set_chann_classif_req, // BTIF_MSG_LE_SET_CHANN_CLASSIF_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_SET_CHANN_CLASSIF_RSP, +#if F_BT_LE_READ_CHANN_MAP + hrp_le_read_chann_map_req, // BTIF_MSG_LE_READ_CHANN_MAP_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_READ_CHANN_MAP_RSP, +#if F_BT_LE_4_0_DTM_SUPPORT + hrp_le_receiver_test_req, // BTIF_MSG_LE_RECEIVER_TEST_REQ, + NULL, // BTIF_MSG_LE_RECEIVER_TEST_RSP, + hrp_le_transmitter_test_req, // BTIF_MSG_LE_TRANSMITTER_TEST_REQ,//0x162 + NULL, // BTIF_MSG_LE_TRANSMITTER_TEST_RSP, + hrp_le_test_end_req, // BTIF_MSG_LE_TEST_END_REQ, + NULL, // BTIF_MSG_LE_TEST_END_RSP, +#else + NULL, // BTIF_MSG_LE_RECEIVER_TEST_REQ, + NULL, // BTIF_MSG_LE_RECEIVER_TEST_RSP, + NULL, // BTIF_MSG_LE_TRANSMITTER_TEST_REQ,//0x162 + NULL, // BTIF_MSG_LE_TRANSMITTER_TEST_RSP, + NULL, // BTIF_MSG_LE_TEST_END_REQ, + NULL, // BTIF_MSG_LE_TEST_END_RSP, +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + hrp_le_read_adv_tx_power_req, // BTIF_MSG_LE_READ_ADV_TX_POWER_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_READ_ADV_TX_POWER_RSP, + hrp_le_set_rand_addr_req, // BTIF_MSG_LE_SET_RAND_ADDR_REQ, + NULL, // BTIF_MSG_LE_SET_RAND_ADDR_RSP, +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + hrp_le_read_max_data_len_req, // BTIF_MSG_LE_READ_MAX_DATA_LEN_REQ, + NULL, // BTIF_MSG_LE_READ_MAX_DATA_LEN_RSP, + hrp_le_read_default_data_len_req, // BTIF_MSG_LE_READ_DEFAULT_DATA_LEN_REQ, + NULL, // BTIF_MSG_LE_READ_DEFAULT_DATA_LEN_RSP, + hrp_le_write_default_data_len_req, // BTIF_MSG_LE_WRITE_DEFAULT_DATA_LEN_REQ, + NULL, // BTIF_MSG_LE_WRITE_DEFAULT_DATA_LEN_RSP, + hrp_le_set_data_len_req, // BTIF_MSG_LE_SET_DATA_LEN_REQ,//0x172 +#else + NULL, // BTIF_MSG_LE_READ_MAX_DATA_LEN_REQ, + NULL, // BTIF_MSG_LE_READ_MAX_DATA_LEN_RSP, + NULL, // BTIF_MSG_LE_READ_DEFAULT_DATA_LEN_REQ, + NULL, // BTIF_MSG_LE_READ_DEFAULT_DATA_LEN_RSP, + NULL, // BTIF_MSG_LE_WRITE_DEFAULT_DATA_LEN_REQ, + NULL, // BTIF_MSG_LE_WRITE_DEFAULT_DATA_LEN_RSP, + NULL, // BTIF_MSG_LE_SET_DATA_LEN_REQ,//0x172 +#endif + NULL, // BTIF_MSG_LE_SET_DATA_LEN_RSP, + NULL, // BTIF_MSG_LE_DATA_LEN_CHANGE_INFO, +#if F_BT_LE_PRIVACY_SUPPORT + hrp_le_modify_resolv_list_req, // BTIF_MSG_LE_MODIFY_RESOLV_LIST_REQ, + NULL, // BTIF_MSG_LE_MODIFY_RESOLV_LIST_RSP, + hrp_le_read_peer_resolv_addr_req, // BTIF_MSG_LE_READ_PEER_RESOLV_ADDR_REQ, + NULL, // BTIF_MSG_LE_READ_PEER_RESOLV_ADDR_RSP, + hrp_le_read_local_resolv_addr_req, // BTIF_MSG_LE_READ_LOCAL_RESOLV_ADDR_REQ, + NULL, // BTIF_MSG_LE_READ_LOCAL_RESOLV_ADDR_RSP, + hrp_le_set_resolution_enable_req, // BTIF_MSG_LE_SET_RESOLUTION_ENABLE_REQ, + NULL, // BTIF_MSG_LE_SET_RESOLUTION_ENABLE_RSP, + hrp_le_set_resolv_priv_addr_tout_req, // BTIF_MSG_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ, + NULL, // BTIF_MSG_LE_SET_RESOLV_PRIV_ADDR_TOUT_RSP, +#else + NULL, // BTIF_MSG_LE_MODIFY_RESOLV_LIST_REQ, + NULL, // BTIF_MSG_LE_MODIFY_RESOLV_LIST_RSP, + NULL, // BTIF_MSG_LE_READ_PEER_RESOLV_ADDR_REQ, + NULL, // BTIF_MSG_LE_READ_PEER_RESOLV_ADDR_RSP, + NULL, // BTIF_MSG_LE_READ_LOCAL_RESOLV_ADDR_REQ, + NULL, // BTIF_MSG_LE_READ_LOCAL_RESOLV_ADDR_RSP, + NULL, // BTIF_MSG_LE_SET_RESOLUTION_ENABLE_REQ, + NULL, // BTIF_MSG_LE_SET_RESOLUTION_ENABLE_RSP, + NULL, // BTIF_MSG_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ, + NULL, // BTIF_MSG_LE_SET_RESOLV_PRIV_ADDR_TOUT_RSP, +#endif +#if F_BT_LE_LOCAL_IRK_SETTING_SUPPORT + hrp_le_config_local_irk_req, // BTIF_MSG_LE_CONFIG_LOCAL_IRK_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_CONFIG_LOCAL_IRK_RSP, +#if F_BT_LE_PRIVACY_SUPPORT + hrp_le_set_privacy_mode_req, // BTIF_MSG_LE_SET_PRIVACY_MODE_REQ, +#else + NULL, // BTIF_MSG_LE_SET_PRIVACY_MODE_REQ, +#endif + NULL, // BTIF_MSG_LE_SET_PRIVACY_MODE_RSP,//0x182 + NULL, // BTIF_MSG_LE_DIRECT_ADV_INFO, + NULL, // BTIF_MSG_LE_HIGH_DUTY_ADV_TOUT_INFO, +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_le_set_adv_set_rand_addr_req, // BTIF_MSG_LE_SET_ADV_SET_RAND_ADDR_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_SET_ADV_SET_RAND_ADDR_RSP, +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_le_ext_adv_param_set_req, // BTIF_MSG_LE_EXT_ADV_PARAM_SET_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_EXT_ADV_PARAM_SET_RSP, +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_le_ext_adv_data_set_req, // BTIF_MSG_LE_EXT_ADV_DATA_SET_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_EXT_ADV_DATA_SET_RSP, +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_le_ext_adv_enable_req, // BTIF_MSG_LE_EXT_ADV_ENABLE_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_EXT_ADV_ENABLE_RSP, +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + hrp_le_ext_scan_param_set_req, // BTIF_MSG_LE_EXT_SCAN_PARAM_SET_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_EXT_SCAN_PARAM_SET_RSP, +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + hrp_le_ext_scan_req, // BTIF_MSG_LE_EXT_SCAN_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_EXT_SCAN_RSP,//0x190 +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + hrp_le_set_default_phy_req, // BTIF_MSG_LE_SET_DEFAULT_PHY_REQ, + NULL, // BTIF_MSG_LE_SET_DEFAULT_PHY_RSP, + hrp_le_set_phy_req, // BTIF_MSG_LE_SET_PHY_REQ, + NULL, // BTIF_MSG_LE_SET_PHY_RSP, +#else + NULL, // BTIF_MSG_LE_SET_DEFAULT_PHY_REQ, + NULL, // BTIF_MSG_LE_SET_DEFAULT_PHY_RSP, + NULL, // BTIF_MSG_LE_SET_PHY_REQ, + NULL, // BTIF_MSG_LE_SET_PHY_RSP, +#endif +#if F_BT_LE_5_0_DTM_SUPPORT + hrp_le_enhanced_receiver_test_req, // BTIF_MSG_LE_ENHANCED_RECEIVER_TEST_REQ, + NULL, // BTIF_MSG_LE_ENHANCED_RECEIVER_TEST_RSP, + hrp_le_enhanced_transmitter_test_req, // BTIF_MSG_LE_ENHANCED_TRANSMITTER_TEST_REQ, + NULL, // BTIF_MSG_LE_ENHANCED_TRANSMITTER_TEST_RSP, +#else + NULL, // BTIF_MSG_LE_ENHANCED_RECEIVER_TEST_REQ, + NULL, // BTIF_MSG_LE_ENHANCED_RECEIVER_TEST_RSP, + NULL, // BTIF_MSG_LE_ENHANCED_TRANSMITTER_TEST_REQ, + NULL, // BTIF_MSG_LE_ENHANCED_TRANSMITTER_TEST_RSP, +#endif + hrp_le_modify_periodic_adv_list_req, // BTIF_MSG_LE_MODIFY_PERIODIC_ADV_LIST_REQ, + NULL, // BTIF_MSG_LE_MODIFY_PERIODIC_ADV_LIST_RSP, +#if F_BT_LE_5_0_RF_PATH_SUPPORT + hrp_le_read_rf_path_compensation_req, // BTIF_MSG_LE_READ_RF_PATH_COMPENSATION_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_READ_RF_PATH_COMPENSATION_RSP, +#if F_BT_LE_5_0_RF_PATH_SUPPORT + hrp_le_write_rf_path_compensation_req, // BTIF_MSG_LE_WRITE_RF_PATH_COMPENSATION_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_WRITE_RF_PATH_COMPENSATION_RSP, +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_le_modify_adv_set_req, // BTIF_MSG_LE_MODIFY_ADV_SET_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_MODIFY_ADV_SET_RSP,//0x1A0 +#if F_BT_LE_5_0_PERIODIC_ADV_SUPPORT + hrp_le_set_periodic_adv_param_req, // BTIF_MSG_LE_SET_PERIODIC_ADV_PARAM_REQ, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_PARAM_RSP, + hrp_le_set_periodic_adv_data_req, // BTIF_MSG_LE_SET_PERIODIC_ADV_DATA_REQ, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_DATA_RSP, + hrp_le_set_periodic_adv_enable_req, // BTIF_MSG_LE_SET_PERIODIC_ADV_ENABLE_REQ, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_ENABLE_RSP, + hrp_le_periodic_adv_create_sync_req, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_REQ, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_RSP, + hrp_le_periodic_adv_create_sync_cancel_req, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_REQ, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_RSP, + hrp_le_periodic_adv_terminate_sync_req, // BTIF_MSG_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_TERMINATE_SYNC_RSP, +#else + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_PARAM_REQ, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_PARAM_RSP, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_DATA_REQ, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_DATA_RSP, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_ENABLE_REQ, + NULL, // BTIF_MSG_LE_SET_PERIODIC_ADV_ENABLE_RSP, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_REQ, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_RSP, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_REQ, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL_RSP, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_TERMINATE_SYNC_RSP, +#endif + NULL, // BTIF_MSG_LE_PHY_UPDATE_INFO, + NULL, // BTIF_MSG_LE_EXT_ADV_REPORT_INFO, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_SYNC_ESTABLISHED_INFO, + NULL, // BTIF_MSG_LE_PERIODIC_ADV_REPORT_INFO,//0x1B0 + NULL, // BTIF_MSG_LE_PERIODIC_ADV_SYNC_LOST_INFO, + NULL, // BTIF_MSG_LE_SCAN_TIMEOUT_INFO, + NULL, // BTIF_MSG_LE_ADV_SET_TERMINATED_INFO, + NULL, // BTIF_MSG_LE_SCAN_REQ_RECEIVED_INFO, + NULL, // BTIF_MSG_LE_LOCAL_DEV_INFO, +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_le_enable_ext_adv_mode_req, // BTIF_MSG_LE_ENABLE_EXT_ADV_MODE_REQ, +#else + NULL, +#endif + NULL, // BTIF_MSG_LE_ENABLE_EXT_ADV_MODE_RSP, + NULL, // BTIF_MSG_LE_REMOTE_FEATS_INFO, + NULL, // BTIF_MSG_GATT_ATTR_WRITE_CMD_SIGNED_INFO, + NULL, // BTIF_MSG_LE_SIGNED_STATUS_INFO, + NULL, // BTIF_MSG_JUST_WORK_REQ_IND, + hrp_just_work_req_cfm, // BTIF_MSG_JUST_WORK_REQ_CFM, + NULL, // BTIF_MSG_USER_PASSKEY_NOTIF_IND, + hrp_user_passkey_notif_cfm, // BTIF_MSG_USER_PASSKEY_NOTIF_CFM, +}; + + + +void hrp_btif_handle_req(uint8_t cmd_group, uint16_t cmd_index, + uint16_t param_list_len, uint8_t *p_param_list) +{ + P_HRP_BTIF_HANDLER p_handle_req = NULL; + + if ((system_status == HRP_STATUS_ACTIVE) && (active_module != HRP_MODULE_UPPER_STACK)) + { + APP_PRINT_ERROR2("wrong module status: system_status= %d active_module= %d", + system_status, active_module); + return ; + } + +#if F_BT_DLPS_EN + if (hrp_dlps_status == HRP_DLPS_STATUS_ACTIVED) + { + if (!((cmd_group == HRP_BTIF_CMD_GROUP_SYSTEM) && (cmd_index == HRP_SYSTEM_EVENT_ACK))) + { + hrp_system_send_cmd_ack(cmd_group, cmd_index, HRP_SYSTEM_COMMAND_COMPLETE); + } + hrp_dlps_allow_enter(true); + APP_PRINT_INFO0("hrp_btif_handle_req allow enter dlps"); + } + +#endif + + switch (cmd_group) + { + case HRP_BTIF_CMD_GROUP_STACK: + if (cmd_index >= 0x1000) + { + APP_PRINT_ERROR1("HRP_BTIF_CMD_GROUP_STACK: wrong cmd_index! cmd_index = 0x%x", + cmd_index); + return; + } + if (cmd_index < (sizeof(hrp_btif_handle_common) / sizeof(P_HRP_BTIF_HANDLER))) + { + p_handle_req = hrp_btif_handle_common[cmd_index]; + } + else if (cmd_index >= 0x0100 && + cmd_index < (0x0100 + sizeof(hrp_btif_handle_ble) / sizeof(P_HRP_BTIF_HANDLER))) + { + p_handle_req = hrp_btif_handle_ble[cmd_index - 0x0100]; + } + break; + case HRP_BTIF_CMD_GROUP_SYSTEM: + if (cmd_index >= 0x0d) + { + APP_PRINT_ERROR1("HRP_BTIF_CMD_GROUP_SYSTEM: wrong cmd_index! cmd_index = 0x%x", + cmd_index); + return; + } + p_handle_req = hrp_btif_handle_system[cmd_index]; + break; + + default: + p_handle_req = NULL; + break; + } + + if (p_handle_req != NULL) + { + p_handle_req(param_list_len, p_param_list); + } + else + { + APP_PRINT_ERROR2("the function handle is NULL, cmd_group = 0x%x, cmd_index = 0x%x", + cmd_group, cmd_index); + } +} + +/** +@ +@ +@return : true - need send msg to uart, false - no need to send data to uart +*/ +bool hrp_btif_handle_special_msg(uint8_t *cmd_group, uint16_t *cmd_index, + T_BTIF_UP_MSG_DATA *p_param_list, uint16_t *param_list_len) +{ + uint8_t *p_param = (uint8_t *)p_param_list; + switch (*cmd_index) + { + case BTIF_MSG_SDP_ATTR_IND: + { + T_BTIF_SDP_ATTR_IND param = *((T_BTIF_SDP_ATTR_IND *)p_param_list); + uint16_t pos = 0; + + APP_PRINT_INFO1("sizeof(T_BTIF_SDP_ATTR_IND = %d", sizeof(T_BTIF_SDP_ATTR_IND)); + + memcpy(p_param, param.bd_addr, 6); pos += 6; + LE_UINT8_TO_ARRAY(p_param + pos, param.server_channel); pos ++; + LE_UINT8_TO_ARRAY(p_param + pos, param.supported_repos); pos++; + LE_UINT16_TO_ARRAY(p_param + pos, param.l2c_psm); pos += 2; + LE_UINT8_TO_ARRAY(p_param + pos, param.srv_class_uuid_type); pos++; + + switch (param.srv_class_uuid_type) + { + case BTIF_UUID16: + LE_UINT16_TO_ARRAY(p_param + pos, param.srv_class_uuid_data.uuid_16); + pos += 2; + break; + case BTIF_UUID32: + LE_UINT32_TO_ARRAY(p_param + pos, param.srv_class_uuid_data.uuid_32); + pos += 4; + break; + case BTIF_UUID128: + memcpy(p_param + pos, param.srv_class_uuid_data.uuid_128, 16); + pos += 16; + break; + default: + break; + } + + LE_UINT16_TO_ARRAY(p_param + pos, param.remote_version); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.supported_feat); pos += 2; + if (param.p_ext_data != NULL) + { + uint16_t len = sizeof(param.p_ext_data); /* Note: p_param may not enough */ + memcpy(p_param + pos, param.p_ext_data, len); pos += len; + *param_list_len = pos; + } + else + { + *param_list_len = pos; + } + } + break; + + case BTIF_MSG_L2C_DATA_IND: + { + T_BTIF_L2C_DATA_IND data_ind = *((T_BTIF_L2C_DATA_IND *)p_param_list); + + *param_list_len = offsetof(T_BTIF_L2C_DATA_IND, data) + data_ind.gap + data_ind.length; + if (l2c_data_trans.is_testing) + { + bool dataRight = true; + //check data + + + //update data + if (dataRight) + { + l2c_data_trans.rx_rcved_count++; + l2c_data_trans.rx_next_byte = ((uint8_t *)p_param_list)[*param_list_len - 1] + 1; + } + else + { + //data test cmpl info cause = wrong data + } + if (l2c_data_trans.rx_rcved_count == l2c_data_trans.rx_total_count) + { + *cmd_group = HRP_BTIF_CMD_GROUP_SYSTEM; + *cmd_index = HRP_SYSTEM_L2C_DATA_TEST_CMPL_INFO; + //uint8_t *p_buffer = p_param_list; + uint16_t pos = 0; + LE_UINT16_TO_ARRAY(p_param + pos, 0); pos += 2; /* cause */ + LE_UINT16_TO_ARRAY(p_param + pos, l2c_data_trans.rx_rcved_count); pos += 2; /* rx_count */ + LE_UINT16_TO_ARRAY(p_param + pos, l2c_data_trans.tx_sent_count); pos += 2; /* tx_count */ + *param_list_len = 6; + return true; + } + return false; + } + } + break; + + case BTIF_MSG_L2C_DATA_RSP: + { + uint8_t event = LTP_EVENT_BTIF_L2C_DATA_RSP; + + if (!l2c_data_trans.is_testing) + { + return false; + } + + l2c_data_trans.tx_available_credits++; + if (l2c_data_trans.tx_sent_count >= l2c_data_trans.tx_total_count) + { + *cmd_group = HRP_BTIF_CMD_GROUP_SYSTEM; + *cmd_index = HRP_SYSTEM_L2C_DATA_TEST_CMPL_INFO; + uint16_t pos = 0; + LE_UINT16_TO_ARRAY(p_param + pos, 0); pos += 2; /* cause */ + LE_UINT16_TO_ARRAY(p_param + pos, l2c_data_trans.rx_rcved_count); pos += 2; /* rx_count */ + LE_UINT16_TO_ARRAY(p_param + pos, l2c_data_trans.tx_sent_count); pos += 2; /* tx_count */ + *param_list_len = 6; + l2c_data_trans.is_testing = false; + return true; + } + else + { + if (os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleEvent, &event, 0) == false) + { + APP_PRINT_ERROR0("hrp_btif_handle_special_msg:BTIF_MSG_L2C_DATA_RSP Send msg error"); + } + } + return false; + } + + case BTIF_MSG_LE_SCAN_INFO: + { + T_BTIF_LE_SCAN_INFO param = *((T_BTIF_LE_SCAN_INFO *)p_param_list); + uint16_t pos = 0; + + memcpy(p_param + pos, param.bd_addr, 6); pos += 6; + LE_UINT8_TO_ARRAY(p_param + pos, param.remote_addr_type); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.adv_type); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.rssi); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.data_len); + pos += 1; + memcpy(p_param + pos, &(param.data), param.data_len); + pos += param.data_len; + *param_list_len = pos; + break; + } +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case BTIF_MSG_LE_EXT_ADV_REPORT_INFO: + { + T_BTIF_LE_EXT_ADV_REPORT_INFO param = *((T_BTIF_LE_EXT_ADV_REPORT_INFO *)p_param_list); + uint16_t pos = 0; + LE_UINT16_TO_ARRAY(p_param + pos, param.event_type); + pos += 2; + LE_UINT8_TO_ARRAY(p_param + pos, param.data_status); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.addr_type); + pos += 1; + + memcpy(p_param + pos, param.bd_addr, 6); pos += 6; + + LE_UINT8_TO_ARRAY(p_param + pos, param.primary_phy); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.secondary_phy); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.adv_sid); + pos += 1; + + LE_UINT8_TO_ARRAY(p_param + pos, param.tx_power); + pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.rssi); + pos += 1; + + LE_UINT16_TO_ARRAY(p_param + pos, param.peri_adv_interval); + pos += 2; + LE_UINT8_TO_ARRAY(p_param + pos, param.direct_addr_type); + pos += 1; + memcpy(p_param + pos, param.direct_addr, 6); pos += 6; + LE_UINT8_TO_ARRAY(p_param + pos, param.data_len); + pos += 1; + memcpy(p_param + pos, param.p_data, param.data_len); + + pos += param.data_len; + + *param_list_len = pos; + break; + } +#endif + case BTIF_MSG_GATT_ATTR_CCCD_INFO: + { + T_BTIF_GATT_ATTR_CCCD_INFO param = *((T_BTIF_GATT_ATTR_CCCD_INFO *)p_param_list); + uint16_t pos = 0; + LE_UINT16_TO_ARRAY(p_param + pos, param.link_id); pos += 2; + memcpy(p_param + pos, param.p_srv_handle, 4); + pos += 4; + LE_UINT16_TO_ARRAY(p_param + pos, param.count); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.gap); pos += 2; + pos = pos + param.gap; + memcpy(p_param + pos, param.data, 4 * param.count); + pos += (4 * param.count); + *param_list_len = pos; + break; + } + case BTIF_MSG_GATT_ATTR_UPDATE_RSP: + { + + + } + break; + case BTIF_MSG_GATT_ATTR_WRITE_RSP: + { + T_BTIF_GATT_ATTR_WRITE_RSP param = *((T_BTIF_GATT_ATTR_WRITE_RSP *)p_param_list); + + uint16_t pos = 0; + + LE_UINT16_TO_ARRAY(p_param + pos, param.link_id); pos += 2; + LE_UINT8_TO_ARRAY(p_param + pos, param.write_type); pos += 1; + LE_UINT16_TO_ARRAY(p_param + pos, param.attr_handle); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.cause); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.attr_len); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.gap); pos += 2; + + pos = pos + param.gap; + + memcpy(p_param + pos, ¶m.data, param.attr_len); pos += param.attr_len; + + *param_list_len = pos; + + //*param_list_len = offsetof(T_BTIF_GATT_ATTR_WRITE_RSP, data) + param.gap+param.attr_len; + + } + break; + + case BTIF_MSG_GATT_ATTR_IND: + { + T_BTIF_GATT_ATTR_IND param = *((T_BTIF_GATT_ATTR_IND *)p_param_list); + uint16_t pos = 0; + + LE_UINT16_TO_ARRAY(p_param + pos, param.link_id); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.attr_handle); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.attr_len); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.gap); pos += 2; + + pos = pos + param.gap; + + memcpy(p_param + pos, param.data, param.attr_len); pos += param.attr_len; + + *param_list_len = pos; + //*param_list_len = offsetof(T_BTIF_GATT_ATTR_IND, data) + param.gap + param.attr_len; + + } + break; + case BTIF_MSG_GATT_DISCOVERY_IND: + { + + T_BTIF_GATT_DISCOVERY_IND param = *((T_BTIF_GATT_DISCOVERY_IND *)p_param_list); + uint16_t pos = 0; + + LE_UINT16_TO_ARRAY(p_param + pos, param.link_id); pos += 2; + LE_UINT8_TO_ARRAY(p_param + pos, param.type); pos += 1; + LE_UINT16_TO_ARRAY(p_param + pos, param.cause); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.elem_cnt); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.elem_len); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.gap); pos += 2; + + pos = pos + param.gap; + + memcpy(p_param + pos, param.list, param.elem_cnt * param.elem_len); + pos += (param.elem_cnt * param.elem_len); + + *param_list_len = pos; + + } + break; + case BTIF_MSG_GATT_SRV_REG_RSP: + { + + T_BTIF_GATT_SRV_REG_RSP param = *((T_BTIF_GATT_SRV_REG_RSP *)p_param_list); + uint16_t pos = 0; + memcpy(p_param + pos, param.p_srv_handle, 1); pos += 4; + LE_UINT16_TO_ARRAY(p_param + pos, param.cause); pos += 2; + + t_srv_table.p_srv_handle = (uint8_t *)¶m.p_srv_handle; + *param_list_len = pos; + + } + break; + case BTIF_MSG_GATT_SERVER_STORE_IND: + { + + T_BTIF_GATT_SERVER_STORE_IND param = *((T_BTIF_GATT_SERVER_STORE_IND *)p_param_list); + uint16_t pos = 0; + + LE_UINT8_TO_ARRAY(p_param + pos, param.op); pos += 1; + LE_UINT8_TO_ARRAY(p_param + pos, param.remote_addr_type); pos += 1; + memcpy(p_param + pos, param.bd_addr, 6); pos += 6; + LE_UINT8_TO_ARRAY(p_param + pos, param.data_len); pos += 1; + memcpy(p_param + pos, param.p_data, param.data_len); pos += param.data_len; + *param_list_len = pos; + } + break; + + case BTIF_MSG_GATT_ATTR_WRITE_REQ_IND: + { + + T_BTIF_GATT_ATTR_WRITE_IND param = *((T_BTIF_GATT_ATTR_WRITE_IND *)p_param_list); + uint16_t pos = 0; + + LE_UINT16_TO_ARRAY(p_param + pos, param.link_id); pos += 2; + memcpy(p_param + pos, param.p_srv_handle, 4); pos += 4; + + LE_UINT16_TO_ARRAY(p_param + pos, param.attr_index); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.attr_len); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.handle); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.write_offset); pos += 2; + LE_UINT16_TO_ARRAY(p_param + pos, param.gap); pos += 2; + pos += param.gap; + memcpy(p_param + pos, param.data, param.attr_len); pos += param.attr_len; + *param_list_len = pos; + + } + break; + case BTIF_MSG_LE_LOCAL_DEV_INFO: + { + + T_BTIF_LE_LOCAL_DEV_INFO dev_info = *((T_BTIF_LE_LOCAL_DEV_INFO *)p_param_list); + t_gatt_dev_info.le_ds_pool_id = dev_info.le_ds_pool_id; + t_gatt_dev_info.le_ds_data_offset = dev_info.le_ds_data_offset; + t_gatt_dev_info.le_ds_credits = dev_info.le_ds_credits; + APP_PRINT_TRACE3("Dev Info: le_ds_pool_id=%d, le_ds_data_offset=%d ,le_ds_credits=%d ", + dev_info.le_ds_pool_id, + dev_info.le_ds_data_offset, dev_info.le_ds_credits); + } + break; + case BTIF_MSG_USER_PASSKEY_NOTIF_IND: + { + T_BTIF_USER_PASSKEY_NOTIF_IND param = *((T_BTIF_USER_PASSKEY_NOTIF_IND *)p_param_list); + uint16_t pos = 0; + memcpy(p_param + pos, param.bd_addr, 6); pos += 6; + LE_UINT8_TO_ARRAY(p_param + pos, param.remote_addr_type); pos += 1; + LE_UINT32_TO_ARRAY(p_param + pos, param.display_value); pos += 4; + *param_list_len = pos; + } + break; + case BTIF_MSG_LE_ADV_RSP: + { + T_BTIF_LE_ADV_RSP param = *((T_BTIF_LE_ADV_RSP *)p_param_list); + uint16_t pos = 0; + LE_UINT8_TO_ARRAY(p_param + pos, param.adv_mode); pos += 1; + LE_UINT16_TO_ARRAY(p_param + pos, param.cause); pos += 2; + *param_list_len = pos; + } + break; + default: + break; + } + return true; +} + +void hrp_btif_handle_msg(T_BTIF_UP_MSG *pMsg) +{ + // process upstream events + HRP_MODULE_ID module_id = HRP_MODULE_UPPER_STACK; + uint8_t cmd_group = HRP_BTIF_CMD_GROUP_STACK; + uint16_t cmd_index = pMsg->command; + uint16_t param_list_len = btif_get_up_data_len(pMsg); + T_BTIF_UP_MSG_DATA *p_param_list = & pMsg->p; + + /*1. handle systemMsg; 2. handle some message contains poiter, commit every parameters to p_param_list */ + if (hrp_btif_handle_special_msg(&cmd_group, &cmd_index, p_param_list, ¶m_list_len)) + { + hrp_handle_upperstream_events(module_id, cmd_group, + cmd_index, param_list_len, (uint8_t *)p_param_list); + } + + btif_buffer_put(pMsg); + +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_entry.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_entry.h new file mode 100644 index 00000000..81cc91ff --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_entry.h @@ -0,0 +1,45 @@ +#ifndef _HRP_BTIF_ENTRY_H_ +#define _HRP_BTIF_ENTRY_H_ + +#include +#include +#include + +typedef enum +{ + HRP_BTIF_CMD_GROUP_STACK = 0, + HRP_BTIF_CMD_GROUP_SYSTEM = 1, +} HRP_BTIF_CMD_GROUP; + +typedef struct _GattDevInfo +{ + uint16_t le_ds_pool_id; + uint16_t le_ds_data_offset; + uint8_t le_ds_credits; +} T_GATT_DEV_INFO; + + +typedef struct +{ + uint8_t *p_srv_handle; + void *p_service; + bool is_used; + uint8_t self_idx; + uint16_t nbr_of_attrib; + uint16_t database_length; + uint16_t receive_length; + uint32_t host_service; +} T_GATT_SRV_TABLE; + +typedef void (* P_HRP_BTIF_HANDLER)(uint16_t len, uint8_t *p_param); + +void hrp_btif_handle_req(uint8_t cmd_group, uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list); +void hrp_btif_handle_msg(T_BTIF_UP_MSG *pMsg); + +//const extern P_HRP_BTIF_HANDLER hrp_btif_handle_bredr[]; +//const extern P_HRP_BTIF_HANDLER hrp_btif_handle_ble[]; + + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_le_api.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_le_api.c new file mode 100644 index 00000000..29771a33 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_le_api.c @@ -0,0 +1,1189 @@ +#include +#include +#include +#include +#include "gattsvc_dis.h" +#include "gattsvc_cts.h" +#include "gattsvc_bas.h" +#include "gattsvc_gls.h" +#include "gattsvc_ndcs.h" +#include "gattsvc_rtus.h" + +#if F_BT_LE_BTIF_SUPPORT + +extern T_GATT_DEV_INFO t_gatt_dev_info; +extern T_GATT_SRV_TABLE t_srv_table; +extern const T_ATTRIB_APPL gatt_dfindme_profile[]; +extern const int gatt_svc_findme_nbr_of_attrib; +extern const int gatt_dfindme_profile_size; + +void *hrp_gatt_srv_get(GATT_SRV_ID service_id, uint16_t *p_nbr_of_attrib) +{ + void *p_service = NULL; + + switch (service_id) + { + default: + *p_nbr_of_attrib = 0; + break; + case BTIF_ApplicationDefined: + p_service = (void *)gatt_dfindme_profile; + *p_nbr_of_attrib = gatt_svc_findme_nbr_of_attrib; + break; + + case BTIF_ServiceBAS: + p_service = (void *)gatt_svc_bas; + *p_nbr_of_attrib = gatt_svc_bas_nbr_of_attrib; + break; + + case BTIF_ServiceDIS: + p_service = (void *)gatt_svc_dis; + *p_nbr_of_attrib = gatt_svc_dis_nbr_of_attrib; + break; + + case BTIF_ServiceRTUS: + p_service = (void *)gatt_svc_rtus; + *p_nbr_of_attrib = gatt_svc_rtus_nbr_of_attrib; + break; + + case BTIF_ServiceGLS: + p_service = (void *)gatt_svc_gls; + *p_nbr_of_attrib = gatt_svc_gls_nbr_of_attrib; + break; + + case BTIF_ServiceNDCS: + p_service = (void *)gatt_svc_ndcs; + *p_nbr_of_attrib = gatt_svc_ndcs_nbr_of_attrib; + break; + + case BTIF_ServiceCTS: + p_service = (void *)gatt_svc_cts; + *p_nbr_of_attrib = gatt_svc_cts_nbr_of_attrib; + break; + + } + + return p_service; +} + +#if F_BT_LE_SMP_OOB_SUPPORT +void hrp_remote_oob_req_cfm(uint16_t len, uint8_t *p_param_list) +{ + /*T_BTIF_REMOTE_OOB_REQ_CFM *p = (T_BTIF_REMOTE_OOB_REQ_CFM *)p_param_list; + if (len != sizeof(T_BTIF_REMOTE_OOB_REQ_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_REMOTE_OOB_REQ_CFM) = %d", + len, sizeof(T_BTIF_REMOTE_OOB_REQ_CFM)); + return; + }*/ + uint8_t bd_addr[6]; + uint8_t data_c[16]; + uint8_t cause; + uint8_t addr_type; + + uint8_t pos = 0; + memcpy(bd_addr, p_param_list + pos, 6); pos += 6; + memcpy(data_c, p_param_list + pos, 16); pos += 16; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(addr_type, p_param_list + pos); pos++; + + btif_remote_oob_req_cfm(bd_addr, (T_BTIF_REMOTE_ADDR_TYPE)addr_type, data_c, (T_BTIF_CAUSE)cause); +} +#endif +void hrp_gatt_srv_reg_req(uint16_t len, uint8_t *p_param_list) +{ + /*T_BTIF_GATT_SRV_REG_REQ *p = (T_BTIF_GATT_SRV_REG_REQ *)p_param_list; + if (len != sizeof(T_BTIF_GATT_SRV_REG_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_SRV_REG_REQ) = %d", + len, sizeof(T_BTIF_GATT_SRV_REG_REQ)); + return; + }*/ + uint8_t *p_buffer = p_param_list; + uint16_t num_attr; + LE_ARRAY_TO_UINT16(num_attr, p_buffer); p_buffer += 2; + void *p_srv = NULL; + uint8_t serviceID = 0; + p_srv = hrp_gatt_srv_get((GATT_SRV_ID)serviceID, &num_attr); + + if (p_srv != NULL) + { + btif_gatt_srv2_reg_req(num_attr, p_srv, 0); + } + +} +void hrp_gatt_attr_update_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_GATT_ATTR_UPDATE_REQ *p = (T_BTIF_GATT_ATTR_UPDATE_REQ *)p_param_list; + + uint8_t *p_buffer = p_param_list; + uint8_t *p_data = NULL; + uint16_t offset; + uint16_t pool_id; + + uint8_t *p_srv_handle; + uint8_t *p_req_handle; + uint8_t type; + + uint16_t link_id; + uint16_t attr_index; + uint16_t attr_len; + uint16_t gap; + + //memcpy(p_srv_handle, p_buffer, 4); + p_srv_handle = (uint8_t *)&t_srv_table.p_srv_handle; + p_buffer += 4; + p_req_handle = NULL; p_buffer += 4; + + LE_ARRAY_TO_UINT8(type, p_buffer); p_buffer++; + + LE_ARRAY_TO_UINT16(link_id, p_buffer); p_buffer += 2; + LE_ARRAY_TO_UINT16(attr_index, p_buffer); p_buffer += 2; + LE_ARRAY_TO_UINT16(attr_len, p_buffer); p_buffer += 2; + LE_ARRAY_TO_UINT16(gap, p_buffer); p_buffer += 2; + p_buffer += gap; + pool_id = t_gatt_dev_info.le_ds_pool_id; + offset = t_gatt_dev_info.le_ds_data_offset; + + offset += 3; + + p_data = btif_buffer_get(pool_id, attr_len, offset); + + APP_PRINT_TRACE5("hrp_gatt_attr_update_req :link_id= %d, type= %d,attr_index =%d, attr_len=%d, gap=%d", + link_id, type, attr_index, attr_len, gap); + if (p_data == NULL) + { + APP_PRINT_ERROR2("hrp_gatt_attr_update_req:fail to get buffer: pool_id = %d, offset=%d", pool_id, + offset); + return; + } + memcpy(((uint8_t *)p_data) + offset, p_buffer, attr_len); + + + btif_gatt_attr_update_req(p_data, link_id, p_srv_handle, p_req_handle, attr_index, + attr_len, offset, (T_BTIF_GATT_PDU_TYPE)type); + +} +//to do: add all the apis here +void hrp_gatt_attr_update_status_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_UPDATE_STATUS_CFM *p = (T_BTIF_GATT_ATTR_UPDATE_STATUS_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_UPDATE_STATUS_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_UPDATE_STATUS_CFM )= %d", + len, sizeof(T_BTIF_GATT_ATTR_UPDATE_STATUS_CFM)); + return; + } + btif_gatt_attr_update_status_cfm(p->link_id, p->p_srv_handle, p->p_req_handle, p->attr_index); +} +void hrp_gatt_attr_read_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_READ_CFM *p = (T_BTIF_GATT_ATTR_READ_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_READ_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_READ_CFM) = %d", + len, sizeof(T_BTIF_GATT_ATTR_READ_CFM)); + return; + } + btif_gatt_attr_read_cfm(p->data, p->link_id, p->p_srv_handle, p->cause, + p->attr_index, p->attr_len, p->gap); +} +void hrp_gatt_attr_write_req_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_WRITE_REQ_CFM *p = (T_BTIF_GATT_ATTR_WRITE_REQ_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_WRITE_REQ_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_WRITE_REQ_CFM) = %d", + len, sizeof(T_BTIF_GATT_ATTR_WRITE_REQ_CFM)); + return; + } + btif_gatt_attr_write_req_cfm(p->link_id, p->p_srv_handle, p->cause, + p->attr_index); +} +void hrp_gatt_attr_prep_write_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_PREP_WRITE_CFM *p = (T_BTIF_GATT_ATTR_PREP_WRITE_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_PREP_WRITE_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_PREP_WRITE_CFM) = %d", + len, sizeof(T_BTIF_GATT_ATTR_PREP_WRITE_CFM)); + return; + } + btif_gatt_attr_prep_write_cfm(p->data, p->link_id, p->p_srv_handle, p->cause, + p->attr_index, p->attr_len, p->gap); +} +void hrp_gatt_attr_exec_write_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_EXEC_WRITE_CFM *p = (T_BTIF_GATT_ATTR_EXEC_WRITE_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_EXEC_WRITE_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_EXEC_WRITE_CFM )= %d", + len, sizeof(T_BTIF_GATT_ATTR_EXEC_WRITE_CFM)); + return; + } + btif_gatt_attr_exec_write_cfm(p->link_id, p->cause, p->handle); +} +#if F_BT_LE_GATT_CLIENT_SUPPORT +void hrp_gatt_discovery_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_GATT_DISCOVERY_REQ *p = (T_BTIF_GATT_DISCOVERY_REQ *)p_param_list; + + uint16_t link_id; + uint8_t type; + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + uint8_t uuid128[16]; + + uint8_t pos = 0; + + LE_ARRAY_TO_UINT16(link_id, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT8(type, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT16(start_handle, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(end_handle, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(uuid16, p_param_list + pos); pos += 2; + memcpy(uuid128, p_param_list + pos, 16); + pos += 16; + /*if (len != sizeof(T_BTIF_GATT_DISCOVERY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_DISCOVERY_REQ )= %d", + len, sizeof(T_BTIF_GATT_DISCOVERY_REQ)); + return; + } + */ + + btif_gatt_discovery_req(link_id, (T_BTIF_GATT_DISCOVERY_TYPE) type, start_handle, end_handle, + uuid16, uuid128); +} +void hrp_gatt_discovery_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_DISCOVERY_CFM *p = (T_BTIF_GATT_DISCOVERY_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_DISCOVERY_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_DISCOVERY_CFM) = %d", + len, sizeof(T_BTIF_GATT_DISCOVERY_CFM)); + return; + } + btif_gatt_discovery_cfm(p->link_id, p->type, p->start_handle, p->end_handle); +} +void hrp_gatt_attr_read_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_READ_REQ *p = (T_BTIF_GATT_ATTR_READ_REQ *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_READ_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_READ_REQ) = %d", + len, sizeof(T_BTIF_GATT_ATTR_READ_REQ)); + return; + } + btif_gatt_attr_read_req(p->link_id, p->read_type, p->read_offset, p->start_handle, p->end_handle, + p->uuid16, p->uuid128); +} +#if F_BT_LE_ATT_READ_MULTI_SUPPORT +void hrp_gatt_attr_read_multi_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_READ_MULTI_REQ *p = (T_BTIF_GATT_ATTR_READ_MULTI_REQ *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_READ_MULTI_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_READ_MULTI_REQ) = %d", + len, sizeof(T_BTIF_GATT_ATTR_READ_MULTI_REQ)); + return; + } + btif_gatt_attr_read_multi_req(p->link_id, p->num_handle, p->handles); +} +#endif +void hrp_gatt_attr_write_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_GATT_ATTR_WRITE_REQ *p = (T_BTIF_GATT_ATTR_WRITE_REQ *)p_param_list; + uint8_t *p_buffer = p_param_list; + uint8_t *p_data = NULL; + uint16_t offset; + uint16_t pool_id; + + uint16_t link_id; + uint8_t write_type; + uint16_t attr_handle; + uint16_t attr_len; /**< attrib. value length */ + uint16_t write_offset; /**< write offset in attribute */ + uint16_t gap; /**< offset of attrib. value in data[] */ + + LE_ARRAY_TO_UINT16(link_id, p_buffer); p_buffer += 2; + + LE_ARRAY_TO_UINT8(write_type, p_buffer); p_buffer++; + LE_ARRAY_TO_UINT16(attr_handle, p_buffer); p_buffer += 2; + + LE_ARRAY_TO_UINT16(attr_len, p_buffer); p_buffer += 2; + LE_ARRAY_TO_UINT16(write_offset, p_buffer); p_buffer += 2; + LE_ARRAY_TO_UINT16(gap, p_buffer); p_buffer += 2; + p_buffer += gap; + + //p_data = os_mem_alloc(RAM_TYPE_DATA_ON, attr_len); + pool_id = t_gatt_dev_info.le_ds_pool_id; + offset = t_gatt_dev_info.le_ds_data_offset; + + offset += 3; + + p_data = btif_buffer_get(pool_id, attr_len, offset); + + APP_PRINT_TRACE6("hrp_gatt_attr_write_req :link_id= %d, write_type= %d,attr_handle =%d, attr_len=%d, write_offset=%d, gap=%d", + link_id, write_type, attr_handle, attr_len, write_offset, gap); + if (p_data == NULL) + { + APP_PRINT_ERROR2("hrp_gatt_attr_write_req:fail to get buffer: pool_id = %d, offset=%d", pool_id, + offset); + return; + } + memcpy(((uint8_t *)p_data) + offset, p_buffer, attr_len); + + btif_gatt_attr_write_req(p_data, link_id, (T_BTIF_GATT_WRITE_TYPE)write_type, attr_handle, + attr_len, offset); + +} +void hrp_gatt_attr_prep_write_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_WRITE_REQ *p = (T_BTIF_GATT_ATTR_WRITE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_WRITE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_WRITE_REQ) = %d", + len, sizeof(T_BTIF_GATT_ATTR_WRITE_REQ)); + return; + } + btif_gatt_attr_prep_write_req(p->data, p->link_id, p->attr_handle, p->attr_len, p->write_offset, + p->gap); +} +void hrp_gatt_attr_exec_write_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_EXEC_WRITE_REQ *p = (T_BTIF_GATT_ATTR_EXEC_WRITE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_EXEC_WRITE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_EXEC_WRITE_REQ) = %d", + len, sizeof(T_BTIF_GATT_ATTR_EXEC_WRITE_REQ)); + return; + } + btif_gatt_attr_exec_write_req(p->link_id, p->flags); +} +void hrp_gatt_attr_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_ATTR_CFM *p = (T_BTIF_GATT_ATTR_CFM *)p_param_list; + if (len != sizeof(T_BTIF_GATT_ATTR_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_ATTR_CFM) = %d", + len, sizeof(T_BTIF_GATT_ATTR_CFM)); + return; + } + btif_gatt_attr_cfm(p->link_id); +} +#endif +void hrp_gatt_security_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_GATT_SECURITY_REQ *p = (T_BTIF_GATT_SECURITY_REQ *)p_param_list; + if (len != sizeof(T_BTIF_GATT_SECURITY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_GATT_SECURITY_REQ) = %d", + len, sizeof(T_BTIF_GATT_SECURITY_REQ)); + return; + } + btif_gatt_security_req(p->link_id, p->requirements, p->min_key_size); +} +void hrp_gatt_server_store_cfm(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_GATT_SERVER_STORE_CFM *p = (T_BTIF_GATT_SERVER_STORE_CFM *)p_param_list; + + uint8_t op; + uint8_t bd_addr[6]; + uint8_t remote_addr_type; + uint8_t data_len; + uint8_t *p_data; + uint8_t cause; + + uint8_t pos = 0; + + LE_ARRAY_TO_UINT8(op, p_param_list + pos); pos++; + memcpy(bd_addr, p_param_list + pos, 6); pos += 6; + LE_ARRAY_TO_UINT8(remote_addr_type, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(data_len, p_param_list + pos); pos++; + + p_data = os_mem_alloc(RAM_TYPE_DATA_ON, data_len); + + memcpy(p_data, p_param_list + pos, data_len); + pos += data_len; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos++; + + + btif_gatt_server_store_cfm((T_BTIF_GATT_STORE_OPCODE)op, bd_addr, + (T_BTIF_REMOTE_ADDR_TYPE)remote_addr_type, + data_len, p_data, (T_BTIF_CAUSE)cause); + os_mem_free(p_data); +} +#if F_BT_LE_GAP_CENTRAL_SUPPORT +void hrp_le_conn_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONN_REQ *p = (T_BTIF_LE_CONN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONN_REQ) = %d", + len, sizeof(T_BTIF_LE_CONN_REQ)); + return; + } + btif_le_conn_req(p->use_ext_conn, p->bd_addr, p->remote_addr_type, p->local_addr_type, + p->init_phys, p->scan_timeout, p->conn_req_param); +} +#endif +void hrp_le_conn_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONN_CFM *p = (T_BTIF_LE_CONN_CFM *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONN_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONN_CFM) = %d", + len, sizeof(T_BTIF_LE_CONN_CFM)); + return; + } + btif_le_conn_cfm(p->bd_addr, p->cause); +} +void hrp_le_disconn_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_DISCONN_REQ *p = (T_BTIF_LE_DISCONN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_DISCONN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_DISCONN_REQ) = %d", + len, sizeof(T_BTIF_LE_DISCONN_REQ)); + return; + } + btif_le_disconn_req(p->link_id, p->cause); +} +void hrp_le_disconn_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_DISCONN_CFM *p = (T_BTIF_LE_DISCONN_CFM *)p_param_list; + if (len != sizeof(T_BTIF_LE_DISCONN_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_DISCONN_CFM) = %d", + len, sizeof(T_BTIF_LE_DISCONN_CFM)); + return; + } + btif_le_disconn_cfm(p->link_id); +} +void hrp_le_adv_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_ADV_REQ *p = (T_BTIF_LE_ADV_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_ADV_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_ADV_REQ) = %d", + len, sizeof(T_BTIF_LE_ADV_REQ)); + return; + } + APP_PRINT_INFO0("hrp_le_adv_req"); + btif_le_adv_req(p->adv_mode); +} +void hrp_le_adv_param_set_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_ADV_PARAM_SET_REQ *p = (T_BTIF_LE_ADV_PARAM_SET_REQ *)p_param_list; + //if (len != sizeof(T_BTIF_LE_ADV_PARAM_SET_REQ)) + // { + // APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_ADV_PARAM_SET_REQ) = %d", + // len, sizeof(T_BTIF_LE_ADV_PARAM_SET_REQ)); + // return; + //} + + btif_le_adv_param_set_req(p->adv_type, p->filter_policy, p->min_interval, p->max_interval, + p->local_addr_type, + p->bd_addr, p->remote_addr_type, p->chann_map); +} +void hrp_le_adv_data_set_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_ADV_DATA_SET_REQ *p = (T_BTIF_LE_ADV_DATA_SET_REQ *)p_param_list; + + uint8_t data_type; + uint8_t data_len; + uint8_t *p_data = NULL; + + uint8_t pos = 0; + + LE_ARRAY_TO_UINT8(data_type, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(data_len, p_param_list + pos); pos++; + p_data = os_mem_alloc(RAM_TYPE_DATA_ON, data_len); + + memcpy(p_data, p_param_list + pos, data_len); + pos += data_len; + APP_PRINT_TRACE3("hrp_le_adv_data_set_req :data_type= %d, data_len = %d,p_data= %d", + data_type, data_len, p_data); + + + btif_le_adv_data_set_req((T_BTIF_LE_ADV_DATA_TYPE)data_type, data_len, p_data); + + os_mem_free(p_data); +} +void hrp_le_scan_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SCAN_REQ *p = (T_BTIF_LE_SCAN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SCAN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SCAN_REQ) = %d", + len, sizeof(T_BTIF_LE_SCAN_REQ)); + return; + } + btif_le_scan_req(p->mode, p->filter_duplicates); +} +void hrp_le_scan_param_set_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SCAN_PARAM_SET_REQ *p = (T_BTIF_LE_SCAN_PARAM_SET_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SCAN_PARAM_SET_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SCAN_PARAM_SET_REQ) = %d", + len, sizeof(T_BTIF_LE_SCAN_PARAM_SET_REQ)); + return; + } + btif_le_scan_param_set_req(p->type, p->interval, p->window, p->filter_policy, p->local_addr_type); +} +void hrp_le_modify_white_list_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_MODIFY_WHITE_LIST_REQ *p = (T_BTIF_LE_MODIFY_WHITE_LIST_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_MODIFY_WHITE_LIST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_MODIFY_WHITE_LIST_REQ) = %d", + len, sizeof(T_BTIF_LE_MODIFY_WHITE_LIST_REQ)); + return; + } + btif_le_modify_white_list_req(p->operation, p->bd_addr, p->remote_addr_type); +} +void hrp_le_conn_update_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONN_UPDATE_REQ *p = (T_BTIF_LE_CONN_UPDATE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONN_UPDATE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONN_UPDATE_REQ) = %d", + len, sizeof(T_BTIF_LE_CONN_UPDATE_REQ)); + return; + } + btif_le_conn_update_req(p->link_id, p->min_interval, p->max_interval, p->latency, p->supv_tout, + p->min_ce_len, p->max_ce_len); +} + +#if F_BT_LE_GAP_CENTRAL_SUPPORT +void hrp_le_conn_update_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONN_UPDATE_CFM *p = (T_BTIF_LE_CONN_UPDATE_CFM *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONN_UPDATE_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONN_UPDATE_CFM) = %d", + len, sizeof(T_BTIF_LE_CONN_UPDATE_CFM)); + return; + } + btif_le_conn_update_cfm(p->link_id, p->cause); +} +#endif +#if F_BT_LE_4_2_CONN_PARAM_UPDATE_SUPPORT +void hrp_le_conn_param_req_reply_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONN_PARAM_REQ_REPLY_REQ *p = (T_BTIF_LE_CONN_PARAM_REQ_REPLY_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONN_PARAM_REQ_REPLY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONN_PARAM_REQ_REPLY_REQ) = %d", + len, sizeof(T_BTIF_LE_CONN_PARAM_REQ_REPLY_REQ)); + return; + } + btif_le_conn_param_req_reply_req(p->link_id, p->min_interval, p->max_interval, p->latency, + p->supv_tout, + p->min_ce_len, p->max_ce_len); +} +void hrp_le_conn_param_req_neg_reply_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_REQ *p = (T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_REQ) = %d", + len, sizeof(T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_REQ)); + return; + } + btif_le_conn_param_req_neg_reply_req(p->link_id, p->reason); +} +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +void hrp_le_credit_based_conn_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_CONN_REQ *p = (T_BTIF_LE_CREDIT_BASED_CONN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_CONN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_CONN_REQ) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_CONN_REQ)); + return; + } + btif_le_credit_based_conn_req(p->link_id, p->le_psm, p->mtu, p->init_credits, p->credits_threshold); +} +void hrp_le_credit_based_conn_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_CONN_CFM *p = (T_BTIF_LE_CREDIT_BASED_CONN_CFM *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_CONN_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_CONN_CFM) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_CONN_CFM)); + return; + } + btif_le_credit_based_conn_cfm(p->link_id, p->channel, p->mtu, p->init_credits, p->credits_threshold, + p->cause); +} +void hrp_le_credit_based_disconn_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_DISCONN_REQ *p = (T_BTIF_LE_CREDIT_BASED_DISCONN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_DISCONN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_DISCONN_REQ) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_DISCONN_REQ)); + return; + } + btif_le_credit_based_disconn_req(p->link_id, p->channel); +} +void hrp_le_credit_based_disconn_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_DISCONN_CFM *p = (T_BTIF_LE_CREDIT_BASED_DISCONN_CFM *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_DISCONN_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_DISCONN_CFM) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_DISCONN_CFM)); + return; + } + btif_le_credit_based_disconn_cfm(p->link_id, p->channel); +} +void hrp_le_send_credit_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SEND_CREDIT_REQ *p = (T_BTIF_LE_SEND_CREDIT_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SEND_CREDIT_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SEND_CREDIT_REQ) = %d", + len, sizeof(T_BTIF_LE_SEND_CREDIT_REQ)); + return; + } + btif_le_send_credit_req(p->link_id, p->channel, p->credits); +} +void hrp_le_credit_based_data_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_DATA_REQ *p = (T_BTIF_LE_CREDIT_BASED_DATA_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_DATA_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_DATA_REQ) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_DATA_REQ)); + return; + } + btif_le_credit_based_data_req(p->data, p->link_id, p->channel, p->len, p->gap); +} +void hrp_le_credit_based_data_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_DATA_CFM *p = (T_BTIF_LE_CREDIT_BASED_DATA_CFM *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_DATA_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_DATA_CFM) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_DATA_CFM)); + return; + } + btif_le_credit_based_data_cfm(p->link_id, p->channel, p->cause); +} +void hrp_le_credit_based_security_reg_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_SECURITY_REG_REQ *p = (T_BTIF_LE_CREDIT_BASED_SECURITY_REG_REQ *) + p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_SECURITY_REG_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_SECURITY_REG_REQ) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_SECURITY_REG_REQ)); + return; + } + btif_le_credit_based_security_reg_req(p->le_psm, p->active, p->mode, p->key_size); +} +void hrp_le_credit_based_psm_reg_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CREDIT_BASED_PSM_REG_REQ *p = (T_BTIF_LE_CREDIT_BASED_PSM_REG_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CREDIT_BASED_PSM_REG_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CREDIT_BASED_PSM_REG_REQ) = %d", + len, sizeof(T_BTIF_LE_CREDIT_BASED_PSM_REG_REQ)); + return; + } + btif_le_credit_based_psm_reg_req(p->le_psm, p->action); +} +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT +void hrp_le_set_chann_classif_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_CHANN_CLASSIF_REQ *p = (T_BTIF_LE_SET_CHANN_CLASSIF_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_CHANN_CLASSIF_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_CHANN_CLASSIF_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_CHANN_CLASSIF_REQ)); + return; + } + btif_le_set_chann_classif_req(p->channel_map); +} +#endif +#if F_BT_LE_READ_CHANN_MAP +void hrp_le_read_chann_map_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_READ_CHANN_MAP_REQ *p = (T_BTIF_LE_READ_CHANN_MAP_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_READ_CHANN_MAP_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_READ_CHANN_MAP_REQ) = %d", + len, sizeof(T_BTIF_LE_READ_CHANN_MAP_REQ)); + return; + } + btif_le_read_chann_map_req(p->link_id); +} +#endif +#if F_BT_LE_4_0_DTM_SUPPORT +void hrp_le_receiver_test_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_RECEIVER_TEST_REQ *p = (T_BTIF_LE_RECEIVER_TEST_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_RECEIVER_TEST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_RECEIVER_TEST_REQ) = %d", + len, sizeof(T_BTIF_LE_RECEIVER_TEST_REQ)); + return; + } + btif_le_receiver_test_req(p->rx_chann); +} +void hrp_le_transmitter_test_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_TRANSMITTER_TEST_REQ *p = (T_BTIF_LE_TRANSMITTER_TEST_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_TRANSMITTER_TEST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_TRANSMITTER_TEST_REQ) = %d", + len, sizeof(T_BTIF_LE_TRANSMITTER_TEST_REQ)); + return; + } + btif_le_transmitter_test_req(p->tx_chann, p->data_len, p->pkt_pl); +} +void hrp_le_test_end_req(uint16_t len, uint8_t *p_param_list) +{ + btif_le_test_end_req(); +} +#endif +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT +void hrp_le_read_adv_tx_power_req(uint16_t len, uint8_t *p_param_list) +{ + btif_le_read_adv_tx_power_req(); +} +#endif +void hrp_le_set_rand_addr_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_RAND_ADDR_REQ *p = (T_BTIF_LE_SET_RAND_ADDR_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_RAND_ADDR_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_RAND_ADDR_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_RAND_ADDR_REQ)); + return; + } + btif_le_set_rand_addr_req(p->random_addr); +} +//*********** ??????? +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT +void hrp_le_read_max_data_len_req(uint16_t len, uint8_t *p_param_list) +{ + //btif_le_read_max_data_len_req(); +} +void hrp_le_read_default_data_len_req(uint16_t len, uint8_t *p_param_list) +{ + //btif_le_read_default_data_len_req(); +} +void hrp_le_write_default_data_len_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_REQ *p = (T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_REQ) = %d", + len, sizeof(T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_REQ)); + return; + } + //btif_le_write_default_data_len_req(p->tx_oct, p->tx_time); +} +//********** +void hrp_le_set_data_len_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_DATA_LEN_REQ *p = (T_BTIF_LE_SET_DATA_LEN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_DATA_LEN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_DATA_LEN_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_DATA_LEN_REQ)); + return; + } + btif_le_set_data_len_req(p->link_id, p->tx_oct, p->tx_time); +} +#endif +#if F_BT_LE_PRIVACY_SUPPORT +void hrp_le_modify_resolv_list_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_MODIFY_RESOLV_LIST_REQ *p = (T_BTIF_LE_MODIFY_RESOLV_LIST_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_MODIFY_RESOLV_LIST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_MODIFY_RESOLV_LIST_REQ) = %d", + len, sizeof(T_BTIF_LE_MODIFY_RESOLV_LIST_REQ)); + return; + } + btif_le_modify_resolv_list_req(p->operation, p->peer_ident_addr_type, p->peer_ident_addr, + p->peer_irk, p->local_irk); +} +void hrp_le_read_peer_resolv_addr_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_READ_PEER_RESOLV_ADDR_REQ *p = (T_BTIF_LE_READ_PEER_RESOLV_ADDR_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_READ_PEER_RESOLV_ADDR_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_READ_PEER_RESOLV_ADDR_REQ) = %d", + len, sizeof(T_BTIF_LE_READ_PEER_RESOLV_ADDR_REQ)); + return; + } + btif_le_read_peer_resolv_addr_req(p->peer_ident_addr_type, p->peer_ident_addr); +} +void hrp_le_read_local_resolv_addr_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_REQ *p = (T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_REQ) = %d", + len, sizeof(T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_REQ)); + return; + } + btif_le_read_local_resolv_addr_req(p->peer_ident_addr_type, p->peer_ident_addr); +} +void hrp_le_set_resolution_enable_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_RESOLUTION_ENABLE_REQ *p = (T_BTIF_LE_SET_RESOLUTION_ENABLE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_RESOLUTION_ENABLE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_RESOLUTION_ENABLE_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_RESOLUTION_ENABLE_REQ)); + return; + } + btif_le_set_resolution_enable_req(p->enable); +} +void hrp_le_set_resolv_priv_addr_tout_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ *p = (T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ *) + p_param_list; + if (len != sizeof(T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ)); + return; + } + btif_le_set_resolv_priv_addr_tout_req(p->timeout); +} +#endif +#if F_BT_LE_LOCAL_IRK_SETTING_SUPPORT +void hrp_le_config_local_irk_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_CONFIG_LOCAL_IRK_REQ *p = (T_BTIF_LE_CONFIG_LOCAL_IRK_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_CONFIG_LOCAL_IRK_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_CONFIG_LOCAL_IRK_REQ) = %d", + len, sizeof(T_BTIF_LE_CONFIG_LOCAL_IRK_REQ)); + return; + } + btif_le_config_local_irk_req(p->local_irk); +} +#endif +#if F_BT_LE_PRIVACY_SUPPORT +void hrp_le_set_privacy_mode_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_PRIVACY_MODE_REQ *p = (T_BTIF_LE_SET_PRIVACY_MODE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_PRIVACY_MODE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_PRIVACY_MODE_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_PRIVACY_MODE_REQ)); + return; + } + btif_le_set_privacy_mode_req(p->peer_ident_addr_type, p->peer_ident_addr, p->privacy_mode); +} +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_le_set_adv_set_rand_addr_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_ADV_SET_RAND_ADDR_REQ *p = (T_BTIF_LE_SET_ADV_SET_RAND_ADDR_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_ADV_SET_RAND_ADDR_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_ADV_SET_RAND_ADDR_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_ADV_SET_RAND_ADDR_REQ)); + return; + } + btif_le_set_adv_set_rand_addr_req(p->rand_addr, p->adv_handle); +} + + +void hrp_le_ext_adv_param_set_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_EXT_ADV_PARAM_SET_REQ *p = (T_BTIF_LE_EXT_ADV_PARAM_SET_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_EXT_ADV_PARAM_SET_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_EXT_ADV_PARAM_SET_REQ) = %d", + len, sizeof(T_BTIF_LE_EXT_ADV_PARAM_SET_REQ)); + return; + } + btif_le_ext_adv_param_set_req(p->adv_handle, p->adv_event_prop, p->prim_adv_interval_min, + p->prim_adv_interval_max, + p->prim_adv_chann_map, p->own_addr_type, p->peer_addr_type, p->peer_addr, p->filter_policy, + p->tx_power, + p->prim_adv_phy, p->secondary_adv_max_skip, p->secondary_adv_phy, p->adv_sid, + p->scan_req_notif_enable); +} +void hrp_le_ext_adv_data_set_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_EXT_ADV_DATA_SET_REQ *p = (T_BTIF_LE_EXT_ADV_DATA_SET_REQ *)p_param_list; + + uint8_t data_type; + uint8_t adv_handle; + uint8_t op; + uint8_t frag_preference; + uint8_t data_len; + uint8_t *p_data; + + uint8_t pos = 0; + + LE_ARRAY_TO_UINT8(data_type, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(adv_handle, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(op, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(frag_preference, p_param_list + pos); pos++; + LE_ARRAY_TO_UINT8(data_len, p_param_list + pos); pos++; + + + p_data = os_mem_alloc(RAM_TYPE_DATA_ON, data_len); + + memcpy(p_data, p_param_list + pos, data_len); + pos += data_len; + APP_PRINT_INFO2("hrp_le_ext_adv_data_set_req:len=%d,pos=%d", len, pos); + + btif_le_ext_adv_data_set_req((T_BTIF_LE_EXT_ADV_DATA_TYPE)data_type, adv_handle, + (T_BTIF_LE_ADV_FRAG_OP_TYPE)op, (T_BTIF_LE_ADV_FRAG_PREFERENCE_TYPE)frag_preference, data_len, + p_data); + os_mem_free(p_data); + +} +void hrp_le_ext_adv_enable_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_EXT_ADV_ENABLE_REQ *p = (T_BTIF_LE_EXT_ADV_ENABLE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_EXT_ADV_ENABLE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_EXT_ADV_ENABLE_REQ) = %d", + len, sizeof(T_BTIF_LE_EXT_ADV_ENABLE_REQ)); + return; + } + btif_le_ext_adv_enable_req(p->mode, p->num_of_sets, p->adv_set_param); +} +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +void hrp_le_ext_scan_param_set_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_EXT_SCAN_PARAM_SET_REQ *p = (T_BTIF_LE_EXT_SCAN_PARAM_SET_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_EXT_SCAN_PARAM_SET_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_EXT_SCAN_PARAM_SET_REQ) = %d", + len, sizeof(T_BTIF_LE_EXT_SCAN_PARAM_SET_REQ)); + return; + } + btif_le_ext_scan_param_set_req(p->local_addr_type, p->filter_policy, p->scan_phys, p->scan_param); +} +void hrp_le_ext_scan_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_EXT_SCAN_REQ *p = (T_BTIF_LE_EXT_SCAN_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_EXT_SCAN_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_EXT_SCAN_REQ) = %d", + len, sizeof(T_BTIF_LE_EXT_SCAN_REQ)); + return; + } + btif_le_ext_scan_req(p->mode, p->filter_duplicates, p->duration, p->period); +} +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void hrp_le_set_default_phy_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_DEFAULT_PHY_REQ *p = (T_BTIF_LE_SET_DEFAULT_PHY_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_DEFAULT_PHY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_DEFAULT_PHY_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_DEFAULT_PHY_REQ)); + return; + } + btif_le_set_default_phy_req(p->all_phys, p->tx_phys, p->rx_phys); +} +void hrp_le_set_phy_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_SET_PHY_REQ *p = (T_BTIF_LE_SET_PHY_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_PHY_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_PHY_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_PHY_REQ)); + return; + } + btif_le_set_phy_req(p->link_id, p->all_phys, p->tx_phys, p->rx_phys, p->phy_options); +} +#endif +#if F_BT_LE_5_0_DTM_SUPPORT +void hrp_le_enhanced_receiver_test_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_ENHANCED_RECEIVER_TEST_REQ *p = (T_BTIF_LE_ENHANCED_RECEIVER_TEST_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_ENHANCED_RECEIVER_TEST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_ENHANCED_RECEIVER_TEST_REQ) = %d", + len, sizeof(T_BTIF_LE_ENHANCED_RECEIVER_TEST_REQ)); + return; + } + btif_le_enhanced_receiver_test_req(p->rx_chann, p->phy, p->modulation_index); +} +void hrp_le_enhanced_transmitter_test_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_REQ *p = (T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_REQ *) + p_param_list; + if (len != sizeof(T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_REQ) = %d", + len, sizeof(T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_REQ)); + return; + } + btif_le_enhanced_transmitter_test_req(p->tx_chann, p->data_len, p->pkt_pl, p->phy); +} +#endif +void hrp_le_modify_periodic_adv_list_req(uint16_t len, uint8_t *p_param_list) +{ +#if F_BT_LE_5_0_PERIODIC_ADV_SUPPORT + T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_REQ *p = (T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_REQ) = %d", + len, sizeof(T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_REQ)); + return; + } + btif_le_modify_periodic_adv_list_req(p->op, p->advertiser_addr_type, p->advertiser_addr, + p->adv_sid); +#endif + +} +#if F_BT_LE_5_0_RF_PATH_SUPPORT +void hrp_le_read_rf_path_compensation_req(uint16_t len, uint8_t *p_param_list) +{ + btif_le_read_rf_path_compensation_req(); +} + +void hrp_le_write_rf_path_compensation_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_REQ *p = (T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_REQ *) + p_param_list; + if (len != sizeof(T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_REQ) = %d", + len, sizeof(T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_REQ)); + return; + } + btif_le_write_rf_path_compensation_req(p->rf_tx_path_compensation, p->rf_rx_path_compensation); +} +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_le_modify_adv_set_req(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_LE_MODIFY_ADV_SET_REQ *p = (T_BTIF_LE_MODIFY_ADV_SET_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_MODIFY_ADV_SET_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_MODIFY_ADV_SET_REQ) = %d", + len, sizeof(T_BTIF_LE_MODIFY_ADV_SET_REQ)); + return; + } + btif_le_modify_adv_set_req(p->operation, p->adv_handle); +} +#endif +//**********???? +void hrp_le_set_periodic_adv_param_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_SET_PERIODIC_ADV_PARAM_REQ *p = (T_BTIF_LE_SET_PERIODIC_ADV_PARAM_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_PERIODIC_ADV_PARAM_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_PERIODIC_ADV_PARAM_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_PERIODIC_ADV_PARAM_REQ)); + return; + } + //btif_le_set_periodic_adv_param_req(p->adv_handle, p->adv_interval_min, p->adv_interval_max, + // p->adv_prop); +} +void hrp_le_set_periodic_adv_data_req(uint16_t len, uint8_t *p_param_list) +{ + // T_BTIF_LE_SET_PERIODIC_ADV_DATA_REQ *p = (T_BTIF_LE_SET_PERIODIC_ADV_DATA_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_PERIODIC_ADV_DATA_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_PERIODIC_ADV_DATA_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_PERIODIC_ADV_DATA_REQ)); + return; + } + //btif_le_set_periodic_adv_data_req(p->adv_handle, p->op, p->data_len, p->p_data); +} +void hrp_le_set_periodic_adv_enable_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_REQ *p = (T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_REQ) = %d", + len, sizeof(T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_REQ)); + return; + } + //btif_le_set_periodic_adv_enable_req(p->mode, p->adv_handle); +} +void hrp_le_periodic_adv_create_sync_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_REQ *p = (T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_REQ *)p_param_list; + if (len != sizeof(T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_REQ) = %d", + len, sizeof(T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_REQ)); + return; + } + //btif_le_periodic_adv_create_sync_req(p->filter_policy, p->adv_sid, p->adv_addr_type, p->adv_add, + // p->skip, + // p->sync_timeout, p->unused); +} +void hrp_le_periodic_adv_create_sync_cancel_req(uint16_t len, uint8_t *p_param_list) +{ + //btif_le_periodic_adv_create_sync_cancel_req(); +} +void hrp_le_periodic_adv_terminate_sync_req(uint16_t len, uint8_t *p_param_list) +{ + //T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ *p = (T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ *) + // p_param_list; + if (len != sizeof(T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ) = %d", + len, sizeof(T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ)); + return; + } + //btif_le_periodic_adv_terminate_sync_req(p->sync_handle); +} +//*******???? +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_le_enable_ext_adv_mode_req(uint16_t len, uint8_t *p_param_list) +{ + btif_le_enable_ext_adv_mode_req(); +} +#endif + + +void hrp_just_work_req_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_JUST_WORK_REQ_CFM *p = (T_BTIF_JUST_WORK_REQ_CFM *) p_param_list; + if (len != sizeof(T_BTIF_JUST_WORK_REQ_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_JUST_WORK_REQ_CFM) = %d", + len, sizeof(T_BTIF_JUST_WORK_REQ_CFM)); + return; + } + APP_PRINT_INFO0("hrp_just_work_req_cfm"); + btif_just_work_req_cfm(p->bd_addr, p->remote_addr_type, + p->cause); +} + +void hrp_user_passkey_notif_cfm(uint16_t len, uint8_t *p_param_list) +{ + T_BTIF_PASSKEY_NOTIF_CFM *p = (T_BTIF_PASSKEY_NOTIF_CFM *) p_param_list; + if (len != sizeof(T_BTIF_PASSKEY_NOTIF_CFM)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_BTIF_PASSKEY_NOTIF_CFM) = %d", + len, sizeof(T_BTIF_PASSKEY_NOTIF_CFM)); + return; + } + APP_PRINT_INFO0("hrp_user_passkey_notif_cfm"); + + btif_user_passkey_notif_cfm(p->bd_addr, p->remote_addr_type, + p->cause); +} + + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_le_api.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_le_api.h new file mode 100644 index 00000000..5ec0e6eb --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_le_api.h @@ -0,0 +1,758 @@ +#ifndef _HRP_BTIF_LE_API_H_ +#define _HRP_BTIF_LE_API_H_ + +#include +#include +#include + +typedef enum +{ + BTIF_ApplicationDefined = 0, /**< application provides services */ + BTIF_ServiceDIS, /**< Device Information service */ + BTIF_ServiceGLS, /**< Glucose service */ + BTIF_ServiceBAS, /**< Battery service */ + BTIF_ServiceCTS, /**< Current Time service */ + BTIF_ServiceNDCS, /**< Next DST Change service */ + BTIF_ServiceRTUS, /**< Reference Time Update service */ + BTIF_ServiceBLS, /**< Blood Pressure service */ + BTIF_ServiceHRS, /**< Heart Rate service */ + + /* the following services are not (yet) available as built-in services: */ + BTIF_ServiceCGM, /**< Continous Glucose Monitor service */ + BTIF_ServiceBMS, /**< Bond Management service */ + BTIF_ServiceQUL, /**< Qualification test service */ + BTIF_ServiceTST /**< Test service */ +} GATT_SRV_ID; + +void *hrp_gatt_srv_get(GATT_SRV_ID serviceID, uint16_t *pNbrOfAttrib); +typedef struct +{ + uint8_t bd_addr[6]; + uint8_t data_c[16]; + T_BTIF_CAUSE cause; + T_BTIF_REMOTE_ADDR_TYPE addr_type; +} T_BTIF_REMOTE_OOB_REQ_CFM; +typedef struct +{ + uint16_t num_attr; + void *p_srv; +} T_BTIF_GATT_SRV_REG_REQ; + +typedef struct +{ + void *p_srv_handle; + void *p_req_handle; + T_BTIF_GATT_PDU_TYPE type; + uint16_t link_id; + uint16_t attr_index; + uint16_t attr_len; + uint16_t gap; + uint8_t data[1]; +} T_BTIF_GATT_ATTR_UPDATE_REQ; + +typedef struct +{ + void *p_srv_handle; + void *p_req_handle; + uint16_t link_id; + uint16_t attr_index; +} T_BTIF_GATT_ATTR_UPDATE_STATUS_CFM; + +typedef struct +{ + void *p_srv_handle; + uint16_t link_id; + uint16_t cause; + uint16_t attr_index; + uint16_t attr_len; + uint16_t gap; + uint8_t data[1]; +} T_BTIF_GATT_ATTR_READ_CFM; + +typedef struct +{ + uint16_t link_id; + void *p_srv_handle; + uint16_t cause; + uint16_t attr_index; +} T_BTIF_GATT_ATTR_WRITE_REQ_CFM; + +typedef struct +{ + void *p_srv_handle; + uint16_t link_id; + uint16_t cause; + uint16_t attr_index; + uint16_t attr_len; + uint16_t gap; + uint8_t data[1]; +} T_BTIF_GATT_ATTR_PREP_WRITE_CFM; + +typedef struct +{ + uint16_t link_id; + uint16_t cause; + uint16_t handle; +} T_BTIF_GATT_ATTR_EXEC_WRITE_CFM; + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_DISCOVERY_TYPE type; + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + uint8_t uuid128[16]; +} T_BTIF_GATT_DISCOVERY_REQ; + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_DISCOVERY_TYPE type; + uint16_t start_handle; + uint16_t end_handle; +} T_BTIF_GATT_DISCOVERY_CFM; + +typedef struct +{ + uint16_t link_id; + T_BTIF_GATT_READ_TYPE read_type; + uint16_t read_offset; + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + uint8_t uuid128[16]; +} T_BTIF_GATT_ATTR_READ_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t num_handle; + uint16_t handles[11]; +} T_BTIF_GATT_ATTR_READ_MULTI_REQ; + +typedef struct +{ + uint16_t link_id; + uint8_t write_type; + uint16_t attr_handle; + uint16_t attr_len; /**< attrib. value length */ + uint16_t write_offset; /**< write offset in attribute */ + uint16_t gap; /**< offset of attrib. value in data[] */ + uint8_t data[1]; +} T_BTIF_GATT_ATTR_WRITE_REQ; +typedef struct +{ + uint16_t link_id; + uint8_t flags; +} T_BTIF_GATT_ATTR_EXEC_WRITE_REQ; + +typedef struct +{ + uint16_t link_id; +} T_BTIF_GATT_ATTR_CFM; + +typedef struct +{ + uint16_t link_id; + uint16_t requirements; + uint8_t min_key_size; +} T_BTIF_GATT_SECURITY_REQ; + +typedef struct +{ + T_BTIF_GATT_STORE_OPCODE op; + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + uint8_t data_len; + uint8_t *p_data; + T_BTIF_CAUSE cause; +} T_BTIF_GATT_SERVER_STORE_CFM; + +typedef struct +{ + bool use_ext_conn; + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_LOCAL_ADDR_TYPE local_addr_type; + uint8_t init_phys; + uint16_t scan_timeout; + T_BTIF_LE_CONN_REQ_PARAM conn_req_param[BTIF_LE_MAX_INIT_PHYS_NUM]; +} T_BTIF_LE_CONN_REQ; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_CAUSE cause; +} T_BTIF_LE_CONN_CFM; + +typedef struct +{ + uint16_t link_id; + T_BTIF_CAUSE cause; +} T_BTIF_LE_DISCONN_REQ; + +typedef struct +{ + uint16_t link_id; +} T_BTIF_LE_DISCONN_CFM; + +typedef struct +{ + T_BTIF_LE_ADV_MODE adv_mode; +} T_BTIF_LE_ADV_REQ; + +typedef struct +{ + T_BTIF_LE_ADV_TYPE adv_type; + T_BTIF_LE_ADV_FILTER_POLICY filter_policy; + uint8_t chann_map; + uint16_t min_interval; + uint16_t max_interval; + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_LOCAL_ADDR_TYPE local_addr_type; +} T_BTIF_LE_ADV_PARAM_SET_REQ; + +typedef struct +{ + T_BTIF_LE_ADV_DATA_TYPE data_type; + uint8_t data_len; + uint8_t *p_data; +} T_BTIF_LE_ADV_DATA_SET_REQ; + +typedef struct +{ + T_BTIF_LE_SCAN_MODE mode; + T_BTIF_LE_SCAN_FILTER_DUPLICATES filter_duplicates; +} T_BTIF_LE_SCAN_REQ; + +typedef struct +{ + T_BTIF_LE_SCAN_TYPE type; + uint16_t interval; + uint16_t window; + T_BTIF_LE_SCAN_FILTER_POLICY filter_policy; + T_BTIF_LOCAL_ADDR_TYPE local_addr_type; +} T_BTIF_LE_SCAN_PARAM_SET_REQ; + +typedef struct +{ + T_BTIF_LE_WHITE_LIST_OP operation; + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; +} T_BTIF_LE_MODIFY_WHITE_LIST_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t supv_tout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} T_BTIF_LE_CONN_UPDATE_REQ; + +typedef struct +{ + uint16_t link_id; + T_BTIF_CAUSE cause; +} T_BTIF_LE_CONN_UPDATE_CFM; + +typedef struct +{ + uint16_t link_id; + uint16_t min_interval; + uint16_t max_interval; + uint16_t latency; + uint16_t supv_tout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} T_BTIF_LE_CONN_PARAM_REQ_REPLY_REQ; + +typedef struct +{ + uint16_t link_id; + uint8_t reason; +} T_BTIF_LE_CONN_PARAM_REQ_NEG_REPLY_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t le_psm; + uint16_t mtu; + uint16_t init_credits; + uint16_t credits_threshold; +} T_BTIF_LE_CREDIT_BASED_CONN_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t mtu; + uint16_t init_credits; + uint16_t credits_threshold; + T_BTIF_L2C_LE_CONN_STATUS cause; +} T_BTIF_LE_CREDIT_BASED_CONN_CFM; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; +} T_BTIF_LE_CREDIT_BASED_DISCONN_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; +} T_BTIF_LE_CREDIT_BASED_DISCONN_CFM; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t credits; +} T_BTIF_LE_SEND_CREDIT_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + uint16_t len; + uint16_t gap; + uint8_t data[1]; +} T_BTIF_LE_CREDIT_BASED_DATA_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t channel; + T_BTIF_CAUSE cause; +} T_BTIF_LE_CREDIT_BASED_DATA_CFM; + +typedef struct +{ + uint16_t le_psm; + bool active; + T_BTIF_LE_SECURITY_MODE mode; + uint8_t key_size; +} T_BTIF_LE_CREDIT_BASED_SECURITY_REG_REQ; + +typedef struct +{ + uint16_t le_psm; + uint8_t action; +} T_BTIF_LE_CREDIT_BASED_PSM_REG_REQ; + +typedef struct +{ + uint8_t channel_map[5]; +} T_BTIF_LE_SET_CHANN_CLASSIF_REQ; + +typedef struct +{ + uint16_t link_id; +} T_BTIF_LE_READ_CHANN_MAP_REQ; + +typedef struct +{ + uint8_t rx_chann; +} T_BTIF_LE_RECEIVER_TEST_REQ; + +typedef struct +{ + uint8_t tx_chann; + uint8_t data_len; + uint8_t pkt_pl; +} T_BTIF_LE_TRANSMITTER_TEST_REQ; + +typedef struct +{ + uint8_t random_addr[6]; +} T_BTIF_LE_SET_RAND_ADDR_REQ; + +typedef struct +{ + uint16_t tx_oct; + uint16_t tx_time; +} T_BTIF_LE_WRITE_DEFAULT_DATA_LEN_REQ; + +typedef struct +{ + uint16_t link_id; + uint16_t tx_oct; + uint16_t tx_time; +} T_BTIF_LE_SET_DATA_LEN_REQ; + +typedef struct +{ + T_BTIF_LE_RESOLVING_LIST_OP operation; + T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type; + uint8_t peer_ident_addr[6]; + uint8_t peer_irk[16]; + uint8_t local_irk[16]; +} T_BTIF_LE_MODIFY_RESOLV_LIST_REQ; + +typedef struct +{ + T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type; + uint8_t peer_ident_addr[6]; +} T_BTIF_LE_READ_PEER_RESOLV_ADDR_REQ; + +typedef struct +{ + T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type; + uint8_t peer_ident_addr[6]; +} T_BTIF_LE_READ_LOCAL_RESOLV_ADDR_REQ; + +typedef struct +{ + uint8_t enable; +} T_BTIF_LE_SET_RESOLUTION_ENABLE_REQ; + +typedef struct +{ + uint16_t timeout; +} T_BTIF_LE_SET_RESOLV_PRIV_ADDR_TOUT_REQ; + +typedef struct +{ + bool generate; + uint8_t local_irk[16]; +} T_BTIF_LE_CONFIG_LOCAL_IRK_REQ; + +typedef struct +{ + T_BTIF_IDENT_ADDR_TYPE peer_ident_addr_type; + uint8_t peer_ident_addr[6]; + T_BTIF_LE_PRIVACY_MODE privacy_mode; +} T_BTIF_LE_SET_PRIVACY_MODE_REQ; + +typedef struct +{ + uint8_t adv_handle; + uint8_t rand_addr[6]; +} T_BTIF_LE_SET_ADV_SET_RAND_ADDR_REQ; + +typedef struct +{ + uint8_t adv_handle; + uint16_t adv_event_prop; + uint32_t prim_adv_interval_min; + uint32_t prim_adv_interval_max; + uint8_t prim_adv_chann_map; + T_BTIF_LOCAL_ADDR_TYPE own_addr_type; + T_BTIF_REMOTE_ADDR_TYPE peer_addr_type; + uint8_t peer_addr[6]; + T_BTIF_LE_ADV_FILTER_POLICY filter_policy; + uint8_t tx_power; + T_BTIF_LE_PRIM_ADV_PHY_TYPE prim_adv_phy; + uint8_t secondary_adv_max_skip; + T_BTIF_LE_PHY_TYPE secondary_adv_phy; + uint8_t adv_sid; + T_BTIF_LE_SCAN_REQ_NOTIFY_TYPE scan_req_notif_enable; +} T_BTIF_LE_EXT_ADV_PARAM_SET_REQ; + +typedef struct +{ + T_BTIF_LE_EXT_ADV_DATA_TYPE data_type; + uint8_t adv_handle; + T_BTIF_LE_ADV_FRAG_OP_TYPE op; + T_BTIF_LE_ADV_FRAG_PREFERENCE_TYPE frag_preference; + uint8_t len; + uint8_t *p_data; +} T_BTIF_LE_EXT_ADV_DATA_SET_REQ; + +typedef struct +{ + T_BTIF_LE_EXT_ADV_MODE mode; + uint8_t num_of_sets; + T_BTIF_LE_EXT_ADV_SET_PARAM adv_set_param[BTIF_LE_MAX_EXTENDED_ADV_SETS_NUM]; +} T_BTIF_LE_EXT_ADV_ENABLE_REQ; + +typedef struct +{ + T_BTIF_LOCAL_ADDR_TYPE local_addr_type; + T_BTIF_LE_SCAN_FILTER_POLICY filter_policy; + uint8_t scan_phys; + T_BTIF_LE_EXT_SCAN_PARAM scan_param[BTIF_LE_MAX_EXTENDED_SCAN_PHY_NUM]; +} T_BTIF_LE_EXT_SCAN_PARAM_SET_REQ; + +typedef struct +{ + T_BTIF_LE_SCAN_MODE mode; + T_BTIF_LE_SCAN_FILTER_DUPLICATES filter_duplicates; + uint16_t duration; + uint16_t period; +} T_BTIF_LE_EXT_SCAN_REQ; + +typedef struct +{ + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; +} T_BTIF_LE_SET_DEFAULT_PHY_REQ; + +typedef struct +{ + uint16_t link_id; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + T_BTIF_LE_PHY_OPTIONS phy_options; +} T_BTIF_LE_SET_PHY_REQ; + +typedef struct +{ + uint8_t rx_chann; + uint8_t phy; + uint8_t modulation_index; +} T_BTIF_LE_ENHANCED_RECEIVER_TEST_REQ; + +typedef struct +{ + uint8_t tx_chann; + uint8_t data_len; + uint8_t pkt_pl; + uint8_t phy; +} T_BTIF_LE_ENHANCED_TRANSMITTER_TEST_REQ; + +typedef struct +{ + T_BTIF_LE_PERIODIC_ADV_LIST_OP op; + uint8_t advertiser_addr_type; + uint8_t advertiser_addr[6]; + uint8_t adv_sid; +} T_BTIF_LE_MODIFY_PERIODIC_ADV_LIST_REQ; + +typedef struct +{ + int8_t rf_tx_path_compensation; + int8_t rf_rx_path_compensation; +} T_BTIF_LE_WRITE_RF_PATH_COMPENSATION_REQ; + +typedef struct +{ + T_BTIF_LE_ADV_SET_OP operation; + uint8_t adv_handle; +} T_BTIF_LE_MODIFY_ADV_SET_REQ; + +typedef struct +{ + uint8_t adv_handle; + uint16_t adv_interval_min; + uint16_t adv_interval_max; + uint16_t adv_prop; +} T_BTIF_LE_SET_PERIODIC_ADV_PARAM_REQ; + +typedef struct +{ + uint8_t adv_handle; + T_BTIF_LE_ADV_FRAG_OP_TYPE op; + uint8_t data_len; + uint8_t *p_data; +} T_BTIF_LE_SET_PERIODIC_ADV_DATA_REQ; + +typedef struct +{ + T_BTIF_LE_PERIODIC_ADV_MODE mode; + uint8_t adv_handle; +} T_BTIF_LE_SET_PERIODIC_ADV_ENABLE_REQ; + +typedef struct +{ + uint8_t filter_policy; + uint8_t adv_sid; + uint8_t adv_addr_type; + uint8_t adv_add[6]; + uint16_t skip; + uint16_t sync_timeout; + uint16_t unused; +} T_BTIF_LE_PERIODIC_ADV_CREATE_SYNC_REQ; + +typedef struct +{ + uint16_t sync_handle; +} T_BTIF_LE_PERIODIC_ADV_TERMINATE_SYNC_REQ; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_CAUSE cause; +} T_BTIF_JUST_WORK_REQ_CFM; + +typedef struct +{ + uint8_t bd_addr[6]; + T_BTIF_REMOTE_ADDR_TYPE remote_addr_type; + T_BTIF_CAUSE cause; +} T_BTIF_PASSKEY_NOTIF_CFM; + +void hrp_remote_oob_req_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_srv_reg_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_update_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_update_status_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_read_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_write_req_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_prep_write_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_exec_write_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_discovery_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_discovery_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_read_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_read_multi_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_write_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_prep_write_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_exec_write_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_attr_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_security_req(uint16_t len, uint8_t *p_param_list); + +void hrp_gatt_server_store_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_conn_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_conn_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_disconn_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_disconn_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_adv_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_adv_param_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_adv_data_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_scan_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_scan_param_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_modify_white_list_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_conn_update_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_conn_update_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_conn_param_req_reply_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_conn_param_req_neg_reply_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_conn_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_conn_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_disconn_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_disconn_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_send_credit_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_data_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_data_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_security_reg_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_credit_based_psm_reg_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_chann_classif_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_read_chann_map_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_receiver_test_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_transmitter_test_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_test_end_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_read_adv_tx_power_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_rand_addr_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_read_max_data_len_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_read_default_data_len_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_write_default_data_len_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_data_len_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_modify_resolv_list_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_read_peer_resolv_addr_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_read_local_resolv_addr_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_resolution_enable_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_resolv_priv_addr_tout_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_config_local_irk_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_privacy_mode_req(uint16_t len, uint8_t *p_param_list); +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_le_set_adv_set_rand_addr_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_ext_adv_param_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_ext_adv_data_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_ext_adv_enable_req(uint16_t len, uint8_t *p_param_list); +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +void hrp_le_ext_scan_param_set_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_ext_scan_req(uint16_t len, uint8_t *p_param_list); +#endif +void hrp_le_set_default_phy_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_phy_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_enhanced_receiver_test_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_enhanced_transmitter_test_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_modify_periodic_adv_list_req(uint16_t len, uint8_t *p_param_list); +#if F_BT_LE_5_0_RF_PATH_SUPPORT +void hrp_le_read_rf_path_compensation_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_write_rf_path_compensation_req(uint16_t len, uint8_t *p_param_list); +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_le_modify_adv_set_req(uint16_t len, uint8_t *p_param_list); +#endif +void hrp_le_set_periodic_adv_param_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_periodic_adv_data_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_set_periodic_adv_enable_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_periodic_adv_create_sync_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_periodic_adv_create_sync_cancel_req(uint16_t len, uint8_t *p_param_list); + +void hrp_le_periodic_adv_terminate_sync_req(uint16_t len, uint8_t *p_param_list); +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_le_enable_ext_adv_mode_req(uint16_t len, uint8_t *p_param_list); +#endif +void hrp_just_work_req_cfm(uint16_t len, uint8_t *p_param_list); + +void hrp_user_passkey_notif_cfm(uint16_t len, uint8_t *p_param_list); +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_system_api.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_system_api.c new file mode 100644 index 00000000..4735f4d5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_system_api.c @@ -0,0 +1,197 @@ +#include +#include + + +#include + +#include +#include +#include + +#if F_BT_DLPS_EN +#include +#endif + +#if F_BT_LE_BTIF_SUPPORT + +T_L2C_DATA_TRANS l2c_data_trans; + +/** + * @brief callback function, upper stack will call it to send message to ltp. + * + * @param pMsg --message pointer from upper stack. + * @return none. + * @retal void +*/ +void hrp_btif_callback(T_BTIF_UP_MSG *pMsg) +{ + unsigned char Event = LTP_EVENT_BTIF_MESSAGE; + + if (os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleMessage, &pMsg, 0) == false) + { + btif_buffer_put(pMsg); + } + else + { + hrp_send_event(&Event); /* signal event to ltp task */ + } +} + +void hrp_system_reset_rsp(uint16_t cause) +{ + + HRP_MODULE_ID module_id = HRP_MODULE_UPPER_STACK; + uint8_t cmd_group = HRP_BTIF_CMD_GROUP_SYSTEM; + uint16_t cmd_index = HRP_SYSTEM_RESET_RSP; + uint16_t param_list_len = 2; + uint16_t *p_param_list = &cause; + + hrp_handle_upperstream_events(module_id, cmd_group, + cmd_index, param_list_len, (uint8_t *)p_param_list); + +} + +void hrp_system_init_rsp(uint16_t cause) +{ + + HRP_MODULE_ID module_id = HRP_MODULE_UPPER_STACK; + uint8_t cmd_group = HRP_BTIF_CMD_GROUP_SYSTEM; + uint16_t cmd_index = HRP_SYSTEM_INIT_RSP; + uint16_t param_list_len = 3; + uint8_t param_list[3]; + uint8_t *p_param_list = ¶m_list[0]; + uint8_t pos = 0; + LE_UINT16_TO_ARRAY(p_param_list + pos, cause); pos += 2; + LE_UINT8_TO_ARRAY(p_param_list + pos, HRP_SUB_TYPE); + + hrp_handle_upperstream_events(module_id, cmd_group, + cmd_index, param_list_len, (uint8_t *)p_param_list); + +} +void hrp_system_send_cmd_ack(uint8_t cmd_group, uint16_t cmd_index, + HRP_SYSTEM_CMD_STATUS status) +{ + HRP_MODULE_ID module_id = HRP_MODULE_UPPER_STACK; + uint8_t event_group = HRP_BTIF_CMD_GROUP_SYSTEM; + uint16_t event_index = HRP_SYSTEM_CMD_ACK; + uint16_t param_list_len = 5; + uint8_t param_list[5]; + uint8_t *p_param_list = ¶m_list[0]; + uint8_t pos = 0; + uint32_t cmd_id = (((uint32_t)cmd_group) << 16) + cmd_index; + + LE_UINT32_TO_ARRAY(p_param_list + pos, cmd_id); pos += 4; + LE_UINT8_TO_ARRAY(p_param_list + pos, status); + + hrp_handle_upperstream_events(module_id, event_group, + event_index, param_list_len, p_param_list); +} +void hrp_system_enable_dlps_rsp(bool status) +{ + HRP_MODULE_ID module_id = HRP_MODULE_UPPER_STACK; + uint8_t cmd_group = HRP_BTIF_CMD_GROUP_SYSTEM; + uint16_t cmd_index = HRP_SYSTEM_ENABLE_DLPS_RSP; + uint16_t param_list_len = 1; + uint8_t param_list = status; + + hrp_handle_upperstream_events(module_id, cmd_group, + cmd_index, param_list_len, ¶m_list); +} + +void hrp_btif_system_reset(uint16_t len, uint8_t *p_param_list) +{ + APP_PRINT_INFO1("hrp_btif_system_reset system_status= %d", system_status); + hrp_system_reset_rsp(BTIF_CAUSE_SUCCESS); + hrp_system_reset(); +} + +void hrp_btif_system_init(uint16_t len, uint8_t *p_param_list) +{ + APP_PRINT_INFO1("system_status= %d", system_status); + if (system_status != HRP_STATUS_RESET) + { + APP_PRINT_ERROR0("wrong status"); + return; + } + + btif_register_req(hrp_btif_callback); + + system_status = HRP_STATUS_ACTIVE; + active_module = HRP_MODULE_UPPER_STACK; + l2c_data_trans.is_testing = false; + hrp_system_init_rsp(BTIF_CAUSE_SUCCESS); +} + + + +void hrp_btif_system_event_ack(uint16_t len, uint8_t *p_param_list) +{ +#if 0 + uint16_t pos = 0; + uint32_t event_index; + uint8_t status; + LE_ARRAY_TO_UINT32(event_index, p_param_list); pos += 4; + LE_ARRAY_TO_UINT8(status, p_param_list); pos++; + + //hrp_utils_handle_event_ack(event_index, status); +#endif +} + +void hrp_btif_system_read_dlps_count_rsp(uint16_t cause, uint32_t count) +{ + HRP_MODULE_ID module_id = HRP_MODULE_UPPER_STACK; + uint8_t cmd_group = HRP_BTIF_CMD_GROUP_SYSTEM; + uint16_t cmd_index = HRP_SYSTEM_READ_DLPS_COUNT_RSP; + uint16_t param_list_len = 6; + uint8_t p_param_list[6] = {0}; + + p_param_list[0] = cause & 0xff; + p_param_list[1] = (cause >> 8) & 0xff; + p_param_list[2] = count & 0xff; + p_param_list[3] = (count >> 8) & 0xff; + p_param_list[4] = (count >> 16) & 0xff; + p_param_list[5] = (count >> 24) & 0xff; + + hrp_handle_upperstream_events(module_id, cmd_group, + cmd_index, param_list_len, p_param_list); +} + +void hrp_btif_system_read_dlps_count_req(uint16_t len, uint8_t *p_param_list) +{ +#if F_BT_DLPS_EN + APP_PRINT_INFO1("hrp_btif_system_read_dlps_count_req count = %d", enter_dlps_count); + hrp_btif_system_read_dlps_count_rsp(0, enter_dlps_count); +#endif +} + + +void hrp_btif_system_enable_dlps_req(uint16_t len, uint8_t *p_param_list) +{ + APP_PRINT_INFO0("hrp_btif_system_enable_dlps_req"); +#if F_BT_DLPS_EN + uint16_t pos = 0; + uint8_t active; + LE_ARRAY_TO_UINT8(active, p_param_list); pos++; + + hrp_dlps_active_dlps(active); + hrp_dlps_allow_enter(false); + hrp_system_enable_dlps_rsp(true); +#else + hrp_system_enable_dlps_rsp(false); +#endif +} + +void hrp_btif_system_le_cfg_passkey_value(uint16_t len, uint8_t *p_param_list) +{ + T_LE_CFG_PASSKEY_VALUE *p = (T_LE_CFG_PASSKEY_VALUE *)p_param_list; + if (len != sizeof(T_LE_CFG_PASSKEY_VALUE)) + { + APP_PRINT_ERROR2("len= %d, sizeof(T_LE_CFG_PASSKEY_VALUE) = %d", + len, sizeof(T_LE_CFG_PASSKEY_VALUE)); + return; + } + btif_le_cfg_passkey_value(p->leFixedDisplayValue); + +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_system_api.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_system_api.h new file mode 100644 index 00000000..cb01cd98 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/btif/hrp_btif_system_api.h @@ -0,0 +1,98 @@ +#ifndef _HRP_BTIF_SYSTEM_API_H_ +#define _HRP_BTIF_SYSTEM_API_H_ + +#include +#include + +typedef enum +{ + HRP_SYSTEM_RESET_REQ = 0, + HRP_SYSTEM_RESET_RSP = 1, + + HRP_SYSTEM_INIT_RSP = 3, + HRP_SYSTEM_L2C_DATA_TEST_CMPL_INFO = 5, + HRP_SYSTEM_LE_CFG_PASSKEY_VALUE_RSP = 7, + HRP_SYSTEM_EVENT_ACK = 8, + HRP_SYSTEM_CMD_ACK = 9, + + HRP_SYSTEM_ENABLE_DLPS_RSP = 0x0B, + HRP_SYSTEM_READ_DLPS_COUNT_REQ = 0x0C, + HRP_SYSTEM_READ_DLPS_COUNT_RSP = 0x0D, + +} HRP_SYSTEM_CMD_ENTRY; + +typedef enum +{ + HRP_SYSTEM_COMMAND_COMPLETE = 0, + HRP_SYSTEM_COMMAND_DISALLOW = 1, + HRP_SYSTEM_UNKNOWN_COMMAND = 2, +} HRP_SYSTEM_CMD_STATUS; + +typedef struct +{ + uint16_t tx_cid; + uint16_t tx_data_offset; + uint16_t tx_length; + uint16_t tx_total_count; /*if tx_total_count > 0, send data*/ + uint8_t tx_next_byte; + uint16_t tx_max_credits; + + uint16_t tx_available_credits; + uint16_t tx_sent_count; + + uint16_t rx_cid; + uint16_t rx_length; + uint16_t rx_total_count; /*if rx_total_count > 0, receive data*/ + uint8_t rx_next_byte; + + uint16_t rx_rcved_count; + + bool is_testing; + + //uint32_t tx_start_timestamp; + //uint32_t tx_stop_timestamp; + //uint32_t rx_start_timestamp; + //uint32_t rx_stop_timestamp; +} T_L2C_DATA_TRANS; + +typedef struct +{ + uint16_t tx_cid; + uint16_t tx_data_offset; + uint16_t tx_length; + uint16_t tx_total_count; /*if tx_total_count > 0, send data*/ + uint16_t tx_max_credits; + + uint16_t rx_cid; + uint16_t rx_length; + uint16_t rx_total_count; /*if rx_total_count > 0, receive data*/ + + uint8_t tx_next_byte; + uint8_t rx_next_byte; + +} T_L2C_DATA_TEST_REQ; + +typedef struct +{ + uint32_t leFixedDisplayValue; + +} T_LE_CFG_PASSKEY_VALUE; + + + +void hrp_system_send_cmd_ack(uint8_t cmd_group, uint16_t cmd_index, HRP_SYSTEM_CMD_STATUS status); + +void hrp_btif_system_reset(uint16_t len, uint8_t *p_param_list); + +void hrp_btif_system_init(uint16_t len, uint8_t *p_param_list); + + +void hrp_btif_system_le_cfg_passkey_value(uint16_t len, uint8_t *p_param_list); + +void hrp_btif_system_event_ack(uint16_t len, uint8_t *p_param_list); + +void hrp_btif_system_enable_dlps_req(uint16_t len, uint8_t *p_param_list); + +void hrp_btif_system_read_dlps_count_req(uint16_t len, uint8_t *p_param_list); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_client.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_client.c new file mode 100644 index 00000000..42329444 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_client.c @@ -0,0 +1,796 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_client.c + * @brief Complete Simple BLE client source file. + * @details + * @author jane + * @date 2016-02-18 + * @version v1.0 + ****************************************************************************** + */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +/** Add Includes here **/ +#include +#include +#include +#include + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ + +typedef struct +{ + T_SIMP_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN]; +} T_SIMP_LINK, *P_SIMP_LINK; + +static P_SIMP_LINK simp_table; +static uint8_t simp_link_num; + +/**< Simple BLE client ID. */ +static T_CLIENT_ID simp_client = CLIENT_PROFILE_GENERAL_ID; +/**< Callback used to send data to app from Simple BLE client layer. */ +static P_FUN_GENERAL_APP_CB simp_client_cb = NULL; + + +bool simp_ble_client_start_discovery(uint8_t conn_id) +{ + APP_PRINT_INFO0("simp_ble_client_start_discovery"); + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + /* First clear handle cache. */ + memset(&simp_table[conn_id], 0, sizeof(T_SIMP_LINK)); + simp_table[conn_id].disc_state = DISC_SIMP_START; + if (client_by_uuid_srv_discovery(conn_id, simp_client, + GATT_UUID_SIMPLE_PROFILE) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +bool simp_ble_client_read_by_handle(uint8_t conn_id, T_SIMP_READ_TYPE read_type) +{ + bool hdl_valid = false; + uint16_t handle; + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case SIMP_READ_V1_READ: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V1_READ]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V1_READ]; + hdl_valid = true; + } + break; + case SIMP_READ_V3_NOTIFY_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]; + hdl_valid = true; + } + break; + case SIMP_READ_V4_INDICATE_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]; + hdl_valid = true; + } + break; + + case SIMP_READ_V7_READ_LONG: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V7_READ_LONG]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V7_READ_LONG]; + hdl_valid = true; + } + break; + case SIMP_READ_V8_CCCD: + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + hdl_valid = true; + } + break; + + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, simp_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_read_by_handle: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_read_by_uuid(uint8_t conn_id, T_SIMP_READ_TYPE read_type) +{ + uint16_t start_handle; + uint16_t end_handle; + uint16_t uuid16; + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_read_by_uuid: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case SIMP_READ_V1_READ: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_SIMPLE_V1_READ; + break; + case SIMP_READ_V3_NOTIFY_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case SIMP_READ_V4_INDICATE_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + case SIMP_READ_V7_READ_LONG: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_SIMPLE_V7_READ_LONG; + break; + case SIMP_READ_V8_CCCD: + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + uuid16 = GATT_UUID_CHAR_CLIENT_CONFIG; + break; + default: + return false; + } + + if (client_attr_read_using_uuid(conn_id, simp_client, start_handle, end_handle, + uuid16, NULL) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +bool simp_ble_client_set_v3_notify(uint8_t conn_id, bool notify) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v3_notify: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = notify ? 1 : 0; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_set_v3_notify: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_set_v4_ind(uint8_t conn_id, bool ind) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v4_ind: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]; + uint16_t length = sizeof(uint16_t); + uint16_t cccd_bits = ind ? 2 : 0; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, (uint8_t *)&cccd_bits) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_set_v4_ind: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_set_v8_cccd(uint8_t conn_id, uint16_t cccd_bits) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_v8_cccd: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V8_CCCD]; + uint16_t length = sizeof(uint16_t); + uint8_t *p_data = (uint8_t *)&cccd_bits; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, p_data) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + APP_PRINT_WARN0("simp_ble_client_set_v8_cccd: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_write_v2_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_write_v2_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V2_WRITE]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V2_WRITE]; + if (client_attr_write(conn_id, simp_client, type, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("simp_ble_client_write_v2_char: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_write_v6_char(uint8_t conn_id, uint16_t length, uint8_t *p_value) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_write_v6_char: failed invalid conn_id %d", conn_id); + return false; + } + + if (simp_table[conn_id].hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) + { + uint16_t handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]; + if (client_attr_write(conn_id, simp_client, GATT_WRITE_TYPE_REQ, handle, + length, p_value) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + APP_PRINT_WARN0("simp_ble_client_write_v6_char: Request fail! Please check!"); + return false; +} + +bool simp_ble_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (simp_table[conn_id].disc_state != DISC_SIMP_DONE) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid state %d", + simp_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN) + { + APP_PRINT_ERROR1("simp_ble_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, simp_table[conn_id].hdl_cache, len); + return true; +} + +bool simp_ble_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (simp_table[conn_id].disc_state != DISC_SIMP_IDLE) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid state %d", + simp_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN) + { + APP_PRINT_ERROR1("simp_ble_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(simp_table[conn_id].hdl_cache, p_hdl_cache, len); + simp_table[conn_id].disc_state = DISC_SIMP_DONE; + return true; +} + +static bool simp_ble_client_start_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("simp_ble_client_start_simp_char_discovery"); + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_START]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + if (client_all_char_discovery(conn_id, simp_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +static bool simp_ble_client_start_char_descriptor_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("simp_ble_client_start_char_descriptor_discovery"); + start_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_V3_NOTIFY]; + end_handle = simp_table[conn_id].hdl_cache[HDL_SIMBLE_SRV_END]; + if (client_all_char_descriptor_discovery(conn_id, simp_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} +static void simp_ble_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + bool cb_flag = false; + T_SIMP_CLIENT_CB_DATA cb_data; + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_DISC_STATE; + + APP_PRINT_INFO1("simp_ble_client_discover_state_cb: discovery_state %d", discovery_state); + if (simp_table[conn_id].disc_state == DISC_SIMP_START) + { + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + switch (discovery_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((hdl_cache[HDL_SIMBLE_SRV_START] != 0) + || (hdl_cache[HDL_SIMBLE_SRV_END] != 0)) + { + if (simp_ble_client_start_char_discovery(conn_id) == false) + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + } + /* No Simple BLE service handle found. Discover procedure complete. */ + else + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + if (hdl_cache[HDL_SIMBLE_V3_NOTIFY] != 0) + { + if (simp_ble_client_start_char_descriptor_discovery(conn_id) == false) + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + } + else + { + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + simp_table[conn_id].disc_state = DISC_SIMP_DONE; + cb_flag = true; + break; + case DISC_STATE_FAILED: + simp_table[conn_id].disc_state = DISC_SIMP_FAILED; + cb_flag = true; + break; + default: + APP_PRINT_ERROR0("simp_handle_discover_state: Invalid Discovery State!"); + break; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && simp_client_cb) + { + cb_data.cb_content.disc_state = simp_table[conn_id].disc_state; + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + return; +} + +/** + * @brief Called by profile client layer, when discover result fetched. + * @param conn_id: connection ID. + * @param result_type: indicate which type of value discovered in service discovery procedure. + * @param result_data: value discovered. + * @retval None + */ +static void simp_ble_client_discover_result_cb(uint8_t conn_id, + T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + APP_PRINT_INFO1("simp_ble_client_discover_result_cb: result_type %d", result_type); + if (simp_table[conn_id].disc_state == DISC_SIMP_START) + { + uint16_t handle; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + hdl_cache[HDL_SIMBLE_SRV_START] = result_data.p_srv_disc_data->att_handle; + hdl_cache[HDL_SIMBLE_SRV_END] = result_data.p_srv_disc_data->end_group_handle; + break; + + case DISC_RESULT_CHAR_UUID16: + handle = result_data.p_char_uuid16_disc_data->value_handle; + switch (result_data.p_char_uuid16_disc_data->uuid16) + { + case GATT_UUID_CHAR_SIMPLE_V1_READ: + hdl_cache[HDL_SIMBLE_V1_READ] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V2_WRITE: + hdl_cache[HDL_SIMBLE_V2_WRITE] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V3_NOTIFY: + hdl_cache[HDL_SIMBLE_V3_NOTIFY] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V4_INDICATE: + hdl_cache[HDL_SIMBLE_V4_INDICATE] = handle; + break; + + + case GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG: + hdl_cache[HDL_SIMBLE_V6_WRITE_LONG] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V7_READ_LONG: + hdl_cache[HDL_SIMBLE_V7_READ_LONG] = handle; + break; + + case GATT_UUID_CHAR_SIMPLE_V8: + hdl_cache[HDL_SIMBLE_V8] = handle; + break; + + default: + /* have no intrest on this handle. */ + break; + } + + break; + + case DISC_RESULT_CHAR_DESC_UUID16: + /* When use client_all_char_descriptor_discovery. */ + if (result_data.p_char_desc_uuid16_disc_data->uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG) + { + handle = result_data.p_char_desc_uuid16_disc_data->handle; + if ((handle > hdl_cache[HDL_SIMBLE_V3_NOTIFY]) + && (handle < hdl_cache[HDL_SIMBLE_V4_INDICATE])) + { + hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_SIMBLE_V4_INDICATE]) && + (handle < hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) && + (hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD] == 0)) + { + hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD] = handle; + } + else if ((handle > hdl_cache[HDL_SIMBLE_V8]) + && (hdl_cache[HDL_SIMBLE_V8_CCCD] == 0)) + { + hdl_cache[HDL_SIMBLE_V8_CCCD] = handle; + } + } + break; + + default: + APP_PRINT_ERROR0("simp_handle_discover_result: Invalid Discovery Result Type!"); + break; + } + } + + return; +} + +static void simp_ble_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_READ_RESULT; + + APP_PRINT_INFO2("simp_ble_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + + if (handle == hdl_cache[HDL_SIMBLE_V1_READ]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V1_READ; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.v1_read.p_value = p_value; + cb_data.cb_content.read_result.data.v1_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.v1_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V3_NOTIFY_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + cb_data.cb_content.read_result.data.v3_notify_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.v3_notify_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V4_INDICATE_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + if (ccc_bit & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + cb_data.cb_content.read_result.data.v4_indicate_cccd = true; + } + else + { + cb_data.cb_content.read_result.data.v4_indicate_cccd = false; + } + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V7_READ_LONG]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V7_READ_LONG; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.v7_read.p_value = p_value; + cb_data.cb_content.read_result.data.v7_read.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.v7_read.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + cb_data.cb_content.read_result.type = SIMP_READ_V8_CCCD; + if (cause == GAP_SUCCESS) + { + uint16_t ccc_bit; + if (value_size != 2) + { + APP_PRINT_ERROR1("simp_ble_client_read_result_cb: invalid cccd len %d", value_size); + return; + } + LE_ARRAY_TO_UINT16(ccc_bit, p_value); + + cb_data.cb_content.read_result.data.v8_notify_ind_cccd = ccc_bit; + } + } + else + { + return; + } + /* Inform application the read result. */ + if (simp_client_cb) + { + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return; +} + +/** + * @brief Called by profile client layer, when write request complete. + * @param conn_id: connection ID. + * @param result: write request send success or not. + * @retval None + */ +static void simp_ble_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, uint16_t cause, + uint8_t credits) +{ + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_WRITE_RESULT; + + APP_PRINT_INFO2("simp_ble_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.write_result.cause = cause; + + if (handle == hdl_cache[HDL_SIMBLE_V2_WRITE]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V2_WRITE; + } + else if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V3_NOTIFY_CCCD; + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V4_INDICATE_CCCD; + } + else if (handle == hdl_cache[HDL_SIMBLE_V6_WRITE_LONG]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V6_WRITE_LONG; + } + else if (handle == hdl_cache[HDL_SIMBLE_V8_CCCD]) + { + cb_data.cb_content.write_result.type = SIMP_WRITE_V8_CCCD; + } + else + { + return; + } + /* Inform application the write result. */ + if (simp_client_cb) + { + (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return; +} + +static T_APP_RESULT simp_ble_client_notif_ind_result_cb(uint8_t conn_id, bool notify, + uint16_t handle, + uint16_t value_size, uint8_t *p_value) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + T_SIMP_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = simp_table[conn_id].hdl_cache; + + cb_data.cb_type = SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + + if (handle == hdl_cache[HDL_SIMBLE_V3_NOTIFY]) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V3_NOTIFY; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_SIMBLE_V4_INDICATE]) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V4_INDICATE; + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + } + else if (handle == hdl_cache[HDL_SIMBLE_V8]) + { + cb_data.cb_content.notif_ind_data.data.value_size = value_size; + cb_data.cb_content.notif_ind_data.data.p_value = p_value; + if (notify) + { + cb_data.cb_content.notif_ind_data.type = SIMP_V8_NOTIFY; + + } + else + { + cb_data.cb_content.notif_ind_data.type = SIMP_V8_INDICATE; + } + } + else + { + return app_result; + } + /* Inform application the notif/ind result. */ + if (simp_client_cb) + { + app_result = (*simp_client_cb)(simp_client, conn_id, &cb_data); + } + + return app_result; +} + +static void simp_ble_client_disconnect_cb(uint8_t conn_id) +{ + APP_PRINT_INFO0("simp_ble_client_disconnect_cb."); + if (conn_id >= simp_link_num) + { + APP_PRINT_ERROR1("simp_ble_client_disconnect_cb: failed invalid conn_id %d", conn_id); + return; + } + memset(&simp_table[conn_id], 0, sizeof(T_SIMP_LINK)); + return; +} + +/** + * @brief Simple BLE Client Callbacks. +*/ +const T_FUN_CLIENT_CBS simp_ble_client_cbs = +{ + simp_ble_client_discover_state_cb, //!< Discovery State callback function pointer + simp_ble_client_discover_result_cb, //!< Discovery result callback function pointer + simp_ble_client_read_result_cb, //!< Read response callback function pointer + simp_ble_client_write_result_cb, //!< Write result callback function pointer + simp_ble_client_notif_ind_result_cb, //!< Notify Indicate callback function pointer + simp_ble_client_disconnect_cb //!< Link disconnection callback function pointer +}; + +T_CLIENT_ID simp_ble_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > SIMP_MAX_LINKS) + { + APP_PRINT_ERROR1("simp_ble_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&simp_client, &simp_ble_client_cbs)) + { + simp_client = CLIENT_PROFILE_GENERAL_ID; + APP_PRINT_ERROR0("simp_ble_add_client failed"); + return simp_client; + } + APP_PRINT_INFO1("simp_ble_add_client: simp_client %d", simp_client); + + /* register callback for profile to inform application that some events happened. */ + simp_client_cb = app_cb; + simp_link_num = link_num; + size = simp_link_num * sizeof(T_SIMP_LINK); + simp_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + return simp_client; +} +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_client.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_client.h new file mode 100644 index 00000000..dbb8f421 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_client.h @@ -0,0 +1,333 @@ +/** +***************************************************************************************** +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_client.h + * @brief Head file for using Simple BLE Client. + * @details Simple BLE data structs and external functions declaration. + * @author jane + * @date 2016-02-18 + * @version v0.1 + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _COMPLETE_BLE_CLIENT_H_ +#define _COMPLETE_BLE_CLIENT_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include + +/** @addtogroup PROFILE_API Profile APIs + * @{ + */ + +/** @addtogroup Bluetooth_Clients Bluetooth Clients + * @{ + */ + +/** @defgroup SIMP_Client Simple Ble service client + * @brief Simple BLE service client + * @details + Simple BLE Profile is a customized BLE-based Profile. Simple ble service please refer to @ref SIMP_Service . + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Client_Exported_Macros SIMP Client Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_UUIDs1 SIMP UUIDs + * @brief Simple BLE Profile UUID definitions + * @{ + */ +#define GATT_UUID_SIMPLE_PROFILE 0xA00A +#define GATT_UUID_CHAR_SIMPLE_V1_READ 0xB001 +#define GATT_UUID_CHAR_SIMPLE_V2_WRITE 0xB002 +#define GATT_UUID_CHAR_SIMPLE_V3_NOTIFY 0xB003 +#define GATT_UUID_CHAR_SIMPLE_V4_INDICATE 0xB004 +#define GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG 0xB006 +#define GATT_UUID_CHAR_SIMPLE_V7_READ_LONG 0xB007 +#define GATT_UUID_CHAR_SIMPLE_V8 0xB008 +/** @} End of SIMP_UUIDs */ + +/** @brief Define links number. range: 0-4 */ +#define SIMP_MAX_LINKS 4 +/** End of SIMP_Client_Exported_Macros + * @} + */ + + +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Client_Exported_Types SIMP Client Exported Types + * @brief + * @{ + */ + +/** @brief SIMP client handle type*/ +typedef enum +{ + HDL_SIMBLE_SRV_START, //!< start handle of simple ble service + HDL_SIMBLE_SRV_END, //!< end handle of simple ble service + HDL_SIMBLE_V1_READ, //!< V1 read characteristic value handle + HDL_SIMBLE_V2_WRITE, //!< V2 write characteristic value handle + HDL_SIMBLE_V3_NOTIFY, //!< V3 notify characteristic value handle + HDL_SIMBLE_V3_NOTIFY_CCCD, //!< V3 notify characteristic CCCD handle + HDL_SIMBLE_V4_INDICATE, //!< V4 indicate characteristic value handle + HDL_SIMBLE_V4_INDICATE_CCCD, //!< V4 indicate characteristic CCCD handle + HDL_SIMBLE_V6_WRITE_LONG, // V6 write long value handle + HDL_SIMBLE_V7_READ_LONG, // V7 read long value handle + HDL_SIMBLE_V8, // V3 notify value handle + HDL_SIMBLE_V8_CCCD, // V3 notify CCCD handle + HDL_SIMBLE_CACHE_LEN //!< handle cache length +} T_SIMP_HANDLE_TYPE; + +/** @brief SIMP client discovery state*/ +typedef enum +{ + DISC_SIMP_IDLE, + DISC_SIMP_START, + DISC_SIMP_DONE, + DISC_SIMP_FAILED +} T_SIMP_DISC_STATE; + +/** @brief SIMP client read type*/ +typedef enum +{ + SIMP_READ_V1_READ, + SIMP_READ_V3_NOTIFY_CCCD, + SIMP_READ_V4_INDICATE_CCCD, + SIMP_READ_V7_READ_LONG = 4, + SIMP_READ_V8_CCCD = 5, +} T_SIMP_READ_TYPE; + +/** @brief SIMP client read value*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_SIMP_READ_VALUE; + +/** @brief SIMP client read data*/ +typedef union +{ + T_SIMP_READ_VALUE v1_read; + bool v3_notify_cccd; + bool v4_indicate_cccd; + uint16_t v8_notify_ind_cccd; + T_SIMP_READ_VALUE v7_read; +} T_SIMP_READ_DATA; + +/** @brief SIMP client read result*/ +typedef struct +{ + T_SIMP_READ_TYPE type; + T_SIMP_READ_DATA data; + uint16_t cause; +} T_SIMP_READ_RESULT; + + +/** @brief SIMP client write type*/ +typedef enum +{ + SIMP_WRITE_V2_WRITE, + SIMP_WRITE_V3_NOTIFY_CCCD, + SIMP_WRITE_V4_INDICATE_CCCD, + SIMP_WRITE_V6_WRITE_LONG, + SIMP_WRITE_V8_CCCD, +} T_SIMP_WRTIE_TYPE; + +/** @brief SIMP client write result*/ +typedef struct +{ + T_SIMP_WRTIE_TYPE type; + uint16_t cause; +} T_SIMP_WRITE_RESULT; + +/** @brief SIMP client notif/ind receive type*/ +typedef enum +{ + SIMP_V3_NOTIFY, + SIMP_V4_INDICATE, + SIMP_V8_NOTIFY, + SIMP_V8_INDICATE, +} T_SIMP_NOTIF_IND_TYPE; + +/** @brief SIMP client notif/ind receive data*/ +typedef struct +{ + uint16_t value_size; + uint8_t *p_value; +} T_SIMP_NOTIF_IND_VALUE; + +/** @brief SIMP client notif/ind receive content*/ +typedef struct +{ + T_SIMP_NOTIF_IND_TYPE type; + T_SIMP_NOTIF_IND_VALUE data; +} T_SIMP_NOTIF_IND_DATA; + +/** @brief SIMP client callback type*/ +typedef enum +{ + SIMP_CLIENT_CB_TYPE_DISC_STATE, //!< Discovery procedure state, done or pending. + SIMP_CLIENT_CB_TYPE_READ_RESULT, //!< Read request's result data, responsed from server. + SIMP_CLIENT_CB_TYPE_WRITE_RESULT, //!< Write request result, success or fail. + SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT, //!< Notification or indication data received from server. + SIMP_CLIENT_CB_TYPE_INVALID //!< Invalid callback type, no practical usage. +} T_SIMP_CLIENT_CB_TYPE; + +/** @brief SIMP client callback content*/ +typedef union +{ + T_SIMP_DISC_STATE disc_state; + T_SIMP_READ_RESULT read_result; + T_SIMP_WRITE_RESULT write_result; + T_SIMP_NOTIF_IND_DATA notif_ind_data; +} T_SIMP_CLIENT_CB_CONTENT; + +/** @brief SIMP client callback data*/ +typedef struct +{ + T_SIMP_CLIENT_CB_TYPE cb_type; + T_SIMP_CLIENT_CB_CONTENT cb_content; +} T_SIMP_CLIENT_CB_DATA; + +/** End of SIMP_Client_Exported_Types * @} */ + +/** @defgroup SIMP_Client_Exported_Functions SIMP Client Exported Functions + * @{ + */ + +/** + * @brief Add simple ble service client to application. + * @param[in] app_cb pointer of app callback function to handle specific client module data. + * @param[in] link_num initialize link num. + * @return Client ID of the specific client module. + * @retval 0xff failed. + * @retval other success. + * + * Example usage + * \code{.c} + void app_le_profile_init(void) + { + client_init(1); + simple_ble_client_id = simp_ble_add_client(app_client_callback, APP_MAX_LINKS); + } + * \endcode + */ +T_CLIENT_ID simp_ble_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num); + +/** + * @brief Used by application, to start the discovery procedure of Simple BLE server. + * @param[in] conn_id connection ID. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_start_discovery(uint8_t conn_id); + +/** + * @brief Used by application, to read data from server by using handles. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_read_by_handle(uint8_t conn_id, T_SIMP_READ_TYPE read_type); + +/** + * @brief Used by application, to read data from server by using UUIDs. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_read_by_uuid(uint8_t conn_id, T_SIMP_READ_TYPE read_type); + +/** + * @brief Used by application, to write data of V2 write Characteristic. + * @param[in] conn_id connection ID. + * @param[in] length write data length + * @param[in] p_value point the value to write + * @param[in] type write type. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_write_v2_char(uint8_t conn_id, uint16_t length, uint8_t *p_value, + T_GATT_WRITE_TYPE type); + +/** + * @brief Used by application, to send write request to peer server's V6 Long Write Characteristic. + * @param conn_id: connection ID. + * @param length: value length. + * @param p_value: value point. + * @retval true--send request to upper stack success. + * false--send request to upper stack failed. + */ +bool simp_ble_client_write_v6_char(uint8_t conn_id, uint16_t length, uint8_t *p_value); +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param[in] conn_id connection ID. + * @param[in] notify 0--disable the notification, 1--enable the notification. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_set_v3_notify(uint8_t conn_id, bool notify); + +/** + * @brief Used by application, to enable or disable the indication of peer server's V4 Indicate Characteristic. + * @param[in] conn_id connection ID. + * @param[in] ind 0--disable the indication, 1--enable the indication. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool simp_ble_client_set_v4_ind(uint8_t conn_id, bool ind); + +bool simp_ble_client_set_v8_cccd(uint8_t conn_id, uint16_t cccd_bits); + + + + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool simp_ble_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); + +/** + * @brief Used by application, to set handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool simp_ble_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len); +#endif +/** @} End of SIMP_Client_Exported_Functions */ + +/** @} End of SIMP_Client */ + +/** @} End of Bluetooth_Clients */ + +/** @} End of PROFILE_API */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _SIMPLE_BLE_CLIENT_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_service.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_service.c new file mode 100644 index 00000000..36ee786c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_service.c @@ -0,0 +1,609 @@ +/** +********************************************************************************************************* +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file simple_ble_service.c +* @brief simple BLE profile source file. +* @details Demonstration of how to implement a self-definition profile. +* @author +* @date +* @version +********************************************************************************************************* +*/ + +#include +#include +#include +#include + +#define GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG 0xB006 +#define GATT_UUID_CHAR_SIMPLE_V7_READ_LONG 0xB007 +#define GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE 0xB008 + +T_SERVER_ID simp_service_id; +/**< Function pointer used to send event to application from simple profile. Initiated in simp_ble_service_add_service. */ +static P_FUN_SERVER_GENERAL_CB pfn_simp_ble_service_cb = NULL; + +/**< Value of simple read characteristic. */ +static uint8_t simple_v1_read_value = 0xf0; +uint8_t v7_char_value[SIMP_READ_V7_MAX_LEN] = {0}; +uint16_t v7_char_value_len = SIMP_READ_V7_MAX_LEN; +char v1_user_descr[] = "V1 read characteristic"; + +/**< @brief profile/service definition. */ +const T_ATTRIB_APPL simple_ble_service_tbl[] = +{ + /* <>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_SIMPLE_PROFILE), /* service UUID */ + HI_WORD(GATT_UUID_SIMPLE_PROFILE) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + /* <> demo for read */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V1_READ) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VOID | ATTRIB_FLAG_ASCII_Z, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_USER_DESCR), + HI_WORD(GATT_UUID_CHAR_USER_DESCR), + }, + (sizeof(v1_user_descr) - 1), /* bValueLen */ + (void *)v1_user_descr, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for write */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE | GATT_CHAR_PROP_WRITE_NO_RSP | GATT_CHAR_PROP_WRITE_AUTHEN_SIGNED) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V2_WRITE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <>, demo for notify */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V3_NOTIFY) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V4_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, + /* <> demo for write Long*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_WRITE) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V6_WRITE_LONG) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_WRITE /* permissions */ + }, + /* <> demo for read Long*/ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V7_READ_LONG), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V7_READ_LONG) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + /* <> demo for indicate */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_INDICATE | GATT_CHAR_PROP_NOTIFY) /* characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE), + HI_WORD(GATT_UUID_CHAR_SIMPLE_V8_NOTIFY_INDICATE) + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_NONE /* permissions */ + }, + /* client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /* permissions */ + }, +}; + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value) +{ + bool ret = true; + + switch (param_type) + { + default: + ret = false; + break; + case SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL: + if (len == 1) + { + simple_v1_read_value = *(uint8_t *)p_value; + } + else + { + ret = false; + } + break; + + case SIMPLE_BLE_SERVICE_PARAM_V7_LEN: + if (len <= SIMP_READ_V7_MAX_LEN) + { + memcpy(v7_char_value, p_value, len); + v7_char_value_len = len; + } + else + { + ret = false; + } + break; + } + + if (!ret) + { + APP_PRINT_ERROR0("simp_ble_service_set_parameter failed"); + } + + return ret; +} + +/** + * @brief read characteristic data from service. + * + * @param service_id ServiceID of characteristic data. + * @param attrib_index Attribute index of getting characteristic data. + * @param offset Used for Blob Read. + * @param p_length length of getting characteristic data. + * @param pp_value data got from service. + * @return Profile procedure result +*/ +T_APP_RESULT simp_ble_service_attr_read_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, uint16_t offset, uint16_t *p_length, uint8_t **pp_value) +{ + T_APP_RESULT cause = APP_RESULT_SUCCESS; + + switch (attrib_index) + { + default: + APP_PRINT_ERROR1("simp_ble_service_attr_read_cb, Attr not found, index %d", attrib_index); + cause = APP_RESULT_ATTR_NOT_FOUND; + break; + case SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = SIMP_READ_V1; + callback_data.conn_id = conn_id; + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = &simple_v1_read_value; + *p_length = sizeof(simple_v1_read_value); + } + break; + case SIMPLE_BLE_SERVICE_CHAR_V7_READ_LONG_INDEX: + { + TSIMP_CALLBACK_DATA callback_data; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE; + callback_data.msg_data.read_value_index = SIMP_READ_V7; + callback_data.conn_id = conn_id; + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + *pp_value = v7_char_value; + *p_length = v7_char_value_len; + } + break; + } + + return (cause); +} + + +void simple_write_post_callback(uint8_t conn_id, T_SERVER_ID service_id, uint16_t attrib_index, + uint16_t length, uint8_t *p_value) +{ + APP_PRINT_INFO4("simple_write_post_callback: conn_id %d, service_id %d, attrib_index 0x%x, length %d", + conn_id, service_id, attrib_index, length); +} +/** + * @brief write characteristic data from service. + * + * @param conn_id + * @param service_id ServiceID to be written. + * @param attrib_index Attribute index of characteristic. + * @param length length of value to be written. + * @param p_value value to be written. + * @return Profile procedure result +*/ +T_APP_RESULT simp_ble_service_attr_write_cb(uint8_t conn_id, T_SERVER_ID service_id, + uint16_t attrib_index, T_WRITE_TYPE write_type, uint16_t length, uint8_t *p_value, + P_FUN_WRITE_IND_POST_PROC *p_write_ind_post_proc) +{ + TSIMP_CALLBACK_DATA callback_data; + T_APP_RESULT cause = APP_RESULT_SUCCESS; + APP_PRINT_INFO1("simp_ble_service_attr_write_cb write_type = 0x%x", write_type); + *p_write_ind_post_proc = simple_write_post_callback; + if (SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX == attrib_index) + { + /* Notify Application. */ + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = SIMP_WRITE_V2; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } + } + else if (SIMPLE_BLE_SERVICE_CHAR_V6_WRITE_INDEX == attrib_index) + { + callback_data.msg_type = SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE; + callback_data.conn_id = conn_id; + callback_data.msg_data.write.opcode = SIMP_WRITE_V6; + callback_data.msg_data.write.write_type = write_type; + callback_data.msg_data.write.len = length; + callback_data.msg_data.write.p_value = p_value; + + if (pfn_simp_ble_service_cb) + { + pfn_simp_ble_service_cb(simp_service_id, (void *)&callback_data); + } + } + else + { + APP_PRINT_ERROR2("simp_ble_service_attr_write_cb Error: attrib_index 0x%x, length %d", + attrib_index, + length); + cause = APP_RESULT_ATTR_NOT_FOUND; + } + return cause; +} + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("simp_ble_service_send_v3_notify"); + // send notification to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX, p_value, + length, + GATT_PDU_TYPE_ANY); +} + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("simp_ble_service_send_v4_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX, p_value, + length, GATT_PDU_TYPE_ANY); +} + +bool simp_ble_service_simple_v8_notify(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("<-- simp_ble_service_simple_v8_notify"); + // send notification to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX, + p_value, length, GATT_PDU_TYPE_NOTIFICATION); +} + +bool simp_ble_service_simple_v8_indicate(uint8_t conn_id, T_SERVER_ID service_id, void *p_value, + uint16_t length) +{ + APP_PRINT_INFO0("<-- simp_ble_service_simple_v8_indicate"); + // send indication to client + return server_send_data(conn_id, service_id, SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX, + p_value, + length, GATT_PDU_TYPE_INDICATION); +} + + +void simp_ble_service_cccd_update_cb(uint8_t conn_id, T_SERVER_ID service_id, uint16_t index, + uint16_t cccbits) +{ + TSIMP_CALLBACK_DATA callback_data; + bool is_handled = false; + callback_data.conn_id = conn_id; + callback_data.msg_type = SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION; + APP_PRINT_INFO2("simp_ble_service_cccd_update_cb: index = %d, cccbits 0x%x", index, cccbits); + switch (index) + { + case SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Enable Notification + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V3_ENABLE; + } + else + { + // Disable Notification + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V3_DISABLE; + } + is_handled = true; + } + break; + case SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX: + { + if (cccbits & GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V4_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V4_DISABLE; + } + is_handled = true; + } + break; + + case SIMPLE_BLE_SERVICE_CHAR_V8_CCCD_INDEX: + { + if (cccbits == GATT_CLIENT_CHAR_CONFIG_INDICATE) + { + // Enable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE; + } + else if (cccbits == GATT_CLIENT_CHAR_CONFIG_NOTIFY) + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE; + } + else if (cccbits == GATT_CLIENT_CHAR_CONFIG_NOTIFY_INDICATE) + { + // Disable Indication + callback_data.msg_data.notification_indification_index = + SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE; + } + else + { + // Disable Indication + callback_data.msg_data.notification_indification_index = SIMP_NOTIFY_INDICATE_V8_DISABLE; + } + + is_handled = true; + } + break; + default: + break; + } + /* Notify Application. */ + if (pfn_simp_ble_service_cb && (is_handled == true)) + { + pfn_simp_ble_service_cb(service_id, (void *)&callback_data); + } +} + +/** + * @brief Simple ble Service Callbacks. +*/ +const T_FUN_GATT_SERVICE_CBS simp_ble_service_cbs = +{ + simp_ble_service_attr_read_cb, // Read callback function pointer + simp_ble_service_attr_write_cb, // Write callback function pointer + simp_ble_service_cccd_update_cb // CCCD update callback function pointer +}; + +/** + * @brief add Simple BLE service to application. + * + * @param[in] p_func pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + */ +T_SERVER_ID simp_ble_service_add_service(void *p_func) +{ + if (false == server_add_service(&simp_service_id, + (uint8_t *)simple_ble_service_tbl, + sizeof(simple_ble_service_tbl), + simp_ble_service_cbs)) + { + APP_PRINT_ERROR0("simp_ble_service_add_service: fail"); + simp_service_id = 0xff; + return simp_service_id; + } + + pfn_simp_ble_service_cb = (P_FUN_SERVER_GENERAL_CB)p_func; + return simp_service_id; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_service.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_service.h new file mode 100644 index 00000000..d9c3644f --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/complete_ble_service.h @@ -0,0 +1,255 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file complete_ble_service.h + * @brief Demonstration of how to implement a self-definition service. + * @details Demonstration of different kinds of service interfaces. + * @author + * @date + * @version + * ************************************************************************************* + */ + +/* Define to prevent recursive inclusion */ +#ifndef _COMPLETE_BLE_SERVICE_H_ +#define _COMPLETE_BLE_SERVICE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* Add Includes here */ +#include +#include + +/** @addtogroup PROFILE_API Profile APIs + * @{ + */ + + +/** @addtogroup Bluetooth_Services Bluetooth Services + * @{ + */ + +/** @defgroup SIMP_Service Simple Ble Service + * @brief Simple BLE service + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Macros SIMP Service Exported Macros + * @brief + * @{ + */ + +/** @defgroup SIMP_Service_Application_Parameters SIMP Service Application Parameters + * @brief Type of parameters set/got from application. + * @{ + */ +typedef enum +{ + SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL = 0x01, + SIMPLE_BLE_SERVICE_PARAM_V7_LEN = 0x02, +} T_SIMP_PARAM_TYPE; + +/** @} */ + + + +/** @defgroup SIMP_Service_Upstream_Message SIMP Service Upstream Message + * @brief Upstream message used to inform application. + * @{ + */ +/** @brief Index of each characteristic in Demo Profile service database. */ +#define SIMPLE_BLE_SERVICE_CHAR_V1_READ_INDEX 0x02 +#define SIMPLE_BLE_SERVICE_CHAR_V2_WRITE_INDEX 0x05 +#define SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX 0x07 +#define SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX 0x0a +#define SIMPLE_BLE_SERVICE_CHAR_NOTIFY_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V3_NOTIFY_INDEX + 1) +#define SIMPLE_BLE_SERVICE_CHAR_INDICATE_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V4_INDICATE_INDEX + 1) +#define SIMPLE_BLE_SERVICE_CHAR_V6_WRITE_INDEX 0xd +#define SIMPLE_BLE_SERVICE_CHAR_V7_READ_LONG_INDEX 0xf +#define SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX 0x11 +#define SIMPLE_BLE_SERVICE_CHAR_V8_CCCD_INDEX (SIMPLE_BLE_SERVICE_CHAR_V8_NOTIFY_INDICATE_INDEX + 1) + +/** @defgroup SIMP_Service_Read_Info SIMP Service Read Info + * @brief Parameter for reading characteristic value. + * @{ + */ +#define SIMP_READ_V1 1 +#define SIMP_READ_V7 2 +/** @} */ + +/** @defgroup SIMP_Service_Write_Info SIMP Service Write Info + * @brief Parameter for writing characteristic value. + * @{ + */ +#define SIMP_WRITE_V2 1 +#define SIMP_WRITE_V6 2 +/** @} */ + +/** @defgroup SIMP_Service_Notify_Indicate_Info SIMP Service Notify Indicate Info + * @brief Parameter for enable or disable notification or indication. + * @{ + */ +#define SIMP_NOTIFY_INDICATE_V3_ENABLE 1 +#define SIMP_NOTIFY_INDICATE_V3_DISABLE 2 +#define SIMP_NOTIFY_INDICATE_V4_ENABLE 3 +#define SIMP_NOTIFY_INDICATE_V4_DISABLE 4 +#define SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE 7 +#define SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE 8 +#define SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE 9 +#define SIMP_NOTIFY_INDICATE_V8_DISABLE 10 +/** @} */ + +#define SIMP_READ_V7_MAX_LEN 300 + +/** @} End of SIMP_Service_Upstream_Message */ + + + +/** @} End of SIMP_Service_Exported_Macros */ +/*============================================================================* + * Types + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Types SIMP Service Exported Types + * @brief + * @{ + */ + +/** @defgroup TSIMP_WRITE_MSG TSIMP_WRITE_MSG + * @brief Simple BLE service written msg to application. + * @{ + */ +typedef struct +{ + uint8_t opcode; //!< ref: @ref SIMP_Control_Point_OpCodes, @ref SIMP_Service_Write_Info + T_WRITE_TYPE write_type; + uint16_t len; + uint8_t *p_value; +} TSIMP_WRITE_MSG; +/** @} End of TSIMP_WRITE_MSG */ + + +/** @defgroup TSIMP_UPSTREAM_MSG_DATA TSIMP_UPSTREAM_MSG_DATA + * @brief Simple BLE service callback message content. + * @{ + */ +typedef union +{ + uint8_t notification_indification_index; //!< ref: @ref SIMP_Service_Notify_Indicate_Info + uint8_t read_value_index; //!< ref: @ref SIMP_Service_Read_Info + TSIMP_WRITE_MSG write; +} TSIMP_UPSTREAM_MSG_DATA; +/** @} End of TSIMP_UPSTREAM_MSG_DATA */ + +/** @defgroup TSIMP_CALLBACK_DATA TSIMP_CALLBACK_DATA + * @brief Simple BLE service data to inform application. + * @{ + */ +typedef struct +{ + uint8_t conn_id; + T_SERVICE_CALLBACK_TYPE msg_type; + TSIMP_UPSTREAM_MSG_DATA msg_data; +} TSIMP_CALLBACK_DATA; +/** @} End of TSIMP_CALLBACK_DATA */ + +/** @} End of SIMP_Service_Exported_Types */ +/*============================================================================* + * Functions + *============================================================================*/ +/** @defgroup SIMP_Service_Exported_Functions SIMP Service Exported Functions + * @brief + * @{ + */ + +/** + * @brief add Simple BLE service to application. + * + * @param[in] p_func pointer of app callback function called by profile. + * @return service ID auto generated by profile layer. + */ +T_SERVER_ID simp_ble_service_add_service(void *p_func); + +/** + * @brief Set service related data from application. + * + * @param[in] param_type parameter type to set. + * @param[in] len value length to be set. + * @param[in] p_value value to set. + * @return parameter set result. + * @retval 0 false + * @retval 1 true + */ +bool simp_ble_service_set_parameter(T_SIMP_PARAM_TYPE param_type, uint16_t len, void *p_value); + +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v3_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_send_v4_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** + * @brief send notification of simple notify characteristic value. + * + * @param[in] conn_id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_simple_v8_notify(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, + uint16_t length); + +/** + * @brief send indication of simple indicate characteristic value. + * + * @param[in] conn_id connection id + * @param[in] service_id service ID of service. + * @param[in] p_value characteristic value to notify + * @param[in] length characteristic value length to notify + * @return notification action result + * @retval 1 true + * @retval 0 false + */ +bool simp_ble_service_simple_v8_indicate(uint8_t conn_id, T_SERVER_ID service_id, + void *p_value, uint16_t length); +/** @} End of SIMP_Service_Exported_Functions */ + +/** @} End of SIMP_Service */ + +/** @} End of Bluetooth_Services */ + +/** @} End of PROFILE_API */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_gap_le.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_gap_le.c new file mode 100644 index 00000000..0ee0721b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_gap_le.c @@ -0,0 +1,3185 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file hrp_gap_le.c +* @brief +* @details none. +* @author Lorna +* @date 2017-11-24 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include "../../../../inc/bluetooth/gap/gap_callback_le.h" +#include "trace_app.h" +//#include +//#include +#include + +#include +#include +#include +#include +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#endif +#include +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +#include +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +#include +#endif +#if F_BT_LE_4_1_CBC_SUPPORT +#include "gap_credit_based_conn.h" +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +#include +#include +#endif +#include +#include +#include + +T_GAP_DEV_STATE hrp_dev_state = {0, 0, 0, 0, 0}; /**< GAP device state */ +#if F_BT_LE_PRIVACY_SUPPORT +T_PRIVACY_STATE app_privacy_state = PRIVACY_STATE_INIT; +T_PRIVACY_ADDR_RESOLUTION_STATE app_privacy_resolution_state = PRIVACY_ADDR_RESOLUTION_DISABLED; +#endif +//#define HRP_GAP_LE_PROFILE_HRS_MASK 1 /* Define le profile mask here*/ +uint8_t adv_handle = 0; +void *g_check_lps_wakeup_timer_handle = NULL; + +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_CLIENT_ID simple_ble_client_id; /**< Simple ble service client id*/ +T_CLIENT_ID gaps_client_id; /**< gap service client id*/ +#endif +T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ + +#define HRP_CHANN_NUM 3 + +#if F_BT_LE_PRIVACY_SUPPORT +bool hrp_test_privacy = false; +#endif + +extern bool gap_set_lps_bootup_active_time(uint16_t active_time); +extern void lps_get_wakeup_time(uint32_t *p_wakeup_count, uint32_t *p_wakeup_time, + uint32_t *p_total_time); + +void hrp_profile_gap_le_event(uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + uint8_t cmd_group = HRP_PROFILE_CMD_GROUP_EVENT_LE; + + hrp_profile_evet(cmd_group, cmd_index, param_list_len, p_param_list); +} +static void hrp_profile_gap_le_cmd_result(uint16_t leCause) +{ + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_RESULT, sizeof(uint16_t), (uint8_t *)&leCause); +} +#if 0 +static void hrp_profile_gap_le_check_lps_wakeup_time_result(uint16_t leCause) +{ + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CHECK_LPS_WAKEUP_TIME_RSP, sizeof(uint16_t), + (uint8_t *)&leCause); +} +#endif +static void hrp_profile_general_id_event(uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + uint8_t cmd_group = HRP_PROFILE_CMD_GROUP_EVENT_GENERAL_ID; + + hrp_profile_evet(cmd_group, cmd_index, param_list_len, p_param_list); +} + + +void hrp_gap_le_handle_io_msg(T_IO_MSG io_msg) +{ + + uint16_t msg_type = io_msg.type; + APP_PRINT_INFO1("hrp_gap_le_handle_io_msg :msg_type=%d ", msg_type); + switch (msg_type) + { + case IO_MSG_TYPE_BT_STATUS: + hrp_app_handle_gap_le_msg(&io_msg); + break; +#if F_BT_DLPS_EN + case IO_MSG_TYPE_TIMER: + hrp_gap_le_check_lps_wakeup_time_handler(&io_msg); + break; +#endif + default: + break; + + } +} + +void hrp_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state) +{ + APP_PRINT_INFO4("hrp_app_handle_dev_state_evt: init state %d scan state %d adv state %d conn state %d", + new_state.gap_init_state, + new_state.gap_scan_state, new_state.gap_adv_state, new_state.gap_conn_state); +#if F_BT_LE_PRIVACY_SUPPORT + // if (hrp_test_privacy == true) + { + if ((new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + && (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + && (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + && (new_state.gap_conn_state == GAP_CONN_DEV_STATE_IDLE)) + { + privacy_handle_resolv_list(); + } + } +#endif + if (hrp_dev_state.gap_init_state != new_state.gap_init_state) + { + if (new_state.gap_init_state == GAP_INIT_STATE_STACK_READY) + { + APP_PRINT_INFO0("GAP stack ready"); + hrp_profile_handle_initCmplete( + HRP_GAP_LE); /* must call this function after le gap initiate completed*/ + /*stack ready*/ + } + } + if (hrp_dev_state.gap_scan_state != new_state.gap_scan_state) + { + if (new_state.gap_scan_state == GAP_SCAN_STATE_IDLE) + { + APP_PRINT_INFO0("GAP scan stop"); + } + else if (new_state.gap_scan_state == GAP_SCAN_STATE_SCANNING) + { + APP_PRINT_INFO0("GAP scan start"); + } + } + + if (hrp_dev_state.gap_adv_state != new_state.gap_adv_state) + { + if (new_state.gap_adv_state == GAP_ADV_STATE_IDLE) + { + if (new_state.gap_adv_sub_state == GAP_ADV_TO_IDLE_CAUSE_CONN) + { + APP_PRINT_INFO0("GAP adv stoped: because connection created"); + } + else + { + APP_PRINT_INFO0("GAP adv stoped"); + } + } + else if (new_state.gap_adv_state == GAP_ADV_STATE_ADVERTISING) + { + APP_PRINT_INFO0("GAP adv start"); + } + } + + if (hrp_dev_state.gap_conn_state != new_state.gap_conn_state) + { + APP_PRINT_INFO2("conn state: %d -> %d", + hrp_dev_state.gap_conn_state, + new_state.gap_conn_state); + } + + hrp_dev_state = new_state; +} +void hrp_app_handle_gap_le_msg(T_IO_MSG *p_io_msg) +{ + T_LE_GAP_MSG bt_msg; + uint8_t evt_param[100]; + memcpy(&bt_msg, &p_io_msg->u.param, sizeof(p_io_msg->u.param)); + + APP_PRINT_TRACE1("hrp_app_handle_gap_le_msg: sub_type %d", p_io_msg->subtype); + + switch (p_io_msg->subtype) + { + case GAP_MSG_LE_DEV_STATE_CHANGE: + { + hrp_app_handle_dev_state_evt(bt_msg.msg_data.gap_dev_state_change.new_state); + T_GAP_DEV_STATE_CHANGE *tmpPtr = &bt_msg.msg_data.gap_dev_state_change; + uint16_t pos = 0; + hrp_app_handle_dev_state_evt(tmpPtr->new_state); + + memcpy(evt_param + pos, &(tmpPtr->new_state), sizeof(T_GAP_DEV_STATE)); + pos += sizeof(T_GAP_DEV_STATE); + + //hrp_profile_fetch_buf(evt_param, &pos, tmpPtr, sizeof(T_GAP_DEV_STATE)); + + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_DEV_STATE_CHANGE, pos, evt_param); + } + break; + case GAP_MSG_LE_CONN_STATE_CHANGE: + { + + T_GAP_CONN_STATE_CHANGE *tmpPtr = &bt_msg.msg_data.gap_conn_state_change; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->new_state); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->disc_cause); pos += 2; + APP_PRINT_INFO3("app_handle_conn_state_evt: conn_id %d, conn_state %d, disc_cause 0x%x", + tmpPtr->conn_id, tmpPtr->new_state, tmpPtr->disc_cause); + + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CONN_STATE_CHANGE, pos, evt_param); + } + break; + case GAP_MSG_LE_CONN_PARAM_UPDATE: + { + + T_GAP_CONN_PARAM_UPDATE *tmpPtr = &bt_msg.msg_data.gap_conn_param_update; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->status); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CONN_PARAM_UPDATE, pos, evt_param); + } + break; + case GAP_MSG_LE_CONN_MTU_INFO: + { + + T_GAP_CONN_MTU_INFO *tmpPtr = &bt_msg.msg_data.gap_conn_mtu_info; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->mtu_size); pos += 2; + APP_PRINT_INFO2("app_handle_conn_mtu_info_evt: conn_id %d, mtu_size %d", tmpPtr->conn_id, + tmpPtr->mtu_size); + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CONN_MTU_INFO, pos, evt_param); + } + break; + case GAP_MSG_LE_AUTHEN_STATE_CHANGE: + { + + T_GAP_AUTHEN_STATE *tmpPtr = &bt_msg.msg_data.gap_authen_state; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->new_state); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->status); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_AUTHEN_STATE_CHANGE, pos, evt_param); + } + break; + + case GAP_MSG_LE_BOND_PASSKEY_DISPLAY: + { + + T_GAP_BOND_PASSKEY_DISPLAY *tmpPtr = &bt_msg.msg_data.gap_bond_passkey_display; + int pos = 0; + uint32_t display_value = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + le_bond_get_display_key(tmpPtr->conn_id, &display_value); + LE_UINT32_TO_ARRAY(evt_param + pos, display_value); pos += 4; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_PASSKEY_DISPLAY: conn_id %d, display_value %d", tmpPtr->conn_id, + display_value); + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_BOND_PASSKEY_DISPLAY, pos, evt_param); + } + break; + case GAP_MSG_LE_BOND_PASSKEY_INPUT: + { + + T_GAP_BOND_PASSKEY_INPUT *tmpPtr = &bt_msg.msg_data.gap_bond_passkey_input; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->key_press); pos += 1; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_BOND_PASSKEY_INPUT, pos, evt_param); + } + break; + case GAP_MSG_LE_BOND_OOB_INPUT: + { + + T_GAP_BOND_OOB_INPUT *tmpPtr = &bt_msg.msg_data.gap_bond_oob_input; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_BOND_OOB_INPUT, pos, evt_param); + } + + break; + case GAP_MSG_LE_BOND_USER_CONFIRMATION: + { + + T_GAP_BOND_USER_CONF *tmpPtr = &bt_msg.msg_data.gap_bond_user_conf; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_BOND_USER_CONFIRMATION, pos, evt_param); + } + + break; + case GAP_MSG_LE_BOND_JUST_WORK: + { + + T_GAP_BOND_JUST_WORK_CONF *tmpPtr = &bt_msg.msg_data.gap_bond_just_work_conf; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_BOND_JUST_WORK, pos, evt_param); + } + + break; +#if F_BT_LE_5_0_AE_ADV_SUPPORT + case GAP_MSG_LE_EXT_ADV_STATE_CHANGE: + { + + T_GAP_EXT_ADV_STATE_CHANGE *tmpPtr = &bt_msg.msg_data.gap_ext_adv_state_change; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->adv_handle); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->new_state); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_STATE_CHANGE, pos, evt_param); + } + + break; +#endif + } +} + +#if F_BT_LE_PRIVACY_SUPPORT +void app_privacy_callback(T_PRIVACY_CB_TYPE type, T_PRIVACY_CB_DATA cb_data) +{ + APP_PRINT_INFO1("app_privacy_callback: type %d", type); + switch (type) + { + case PRIVACY_STATE_MSGTYPE: + app_privacy_state = cb_data.privacy_state; + APP_PRINT_INFO1("PRIVACY_STATE_MSGTYPE: status %d", app_privacy_state); + break; + + case PRIVACY_RESOLUTION_STATUS_MSGTYPE: + { + uint8_t param[1] = {0}; + int pos = 0; + app_privacy_resolution_state = cb_data.resolution_state; + APP_PRINT_INFO1("PRIVACY_RESOLUTION_STATUS_MSGTYPE: status %d", app_privacy_resolution_state); + LE_UINT8_TO_ARRAY(param + pos, app_privacy_resolution_state); pos += 1; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_PRIVACY_RESOLUTION_STATUS_INFO, pos, param); + } + break; + + case PRIVACY_READ_PEER_RESOLV_ADDR_MSGTYPE: + { + uint8_t param[8] = {0}; + int pos = 0; + APP_PRINT_INFO2("PRIVACY_READ_PEER_RESOLV_ADDR_MSGTYPE: cause 0x%x, addr %b", + cb_data.p_privacy_read_resolv_addr_rsp->cause, + TRACE_BDADDR(cb_data.p_privacy_read_resolv_addr_rsp->resolv_addr)); + LE_UINT16_TO_ARRAY(param + pos, cb_data.p_privacy_read_resolv_addr_rsp->cause); pos += 2; + hrp_profile_commit_buf(param, &pos, cb_data.p_privacy_read_resolv_addr_rsp->resolv_addr, 6); + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_PRIVACY_READ_PEER_RESOLV_ADDR, pos, param); + } + break; + + case PRIVACY_READ_LOCAL_RESOLV_ADDR_MSGTYPE: + { + uint8_t param[8] = {0}; + int pos = 0; + APP_PRINT_INFO2("PRIVACY_READ_LOCAL_RESOLV_ADDR_MSGTYPE: cause 0x%x, addr %b", + cb_data.p_privacy_read_resolv_addr_rsp->cause, + TRACE_BDADDR(cb_data.p_privacy_read_resolv_addr_rsp->resolv_addr)); + LE_UINT16_TO_ARRAY(param + pos, cb_data.p_privacy_read_resolv_addr_rsp->cause); pos += 2; + hrp_profile_commit_buf(param, &pos, cb_data.p_privacy_read_resolv_addr_rsp->resolv_addr, 6); + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR, pos, param); + } + break; + + case PRIVACY_GEN_PRIV_ADDR_INTERVAL_MSGTYPE: + APP_PRINT_INFO1("PRIVACY_GEN_PRIV_ADDR_INTERVAL_MSGTYPE: cause 0x%x", cb_data.cause); + break; + + case PRIVACY_SET_PEER_MODE_MSGTYPE: + { + uint8_t param[2] = {0}; + int pos = 0; + APP_PRINT_INFO1("PRIVACY_SET_PEER_MODE_MSGTYPE: cause 0x%x", cb_data.cause); + + LE_UINT16_TO_ARRAY(param + pos, cb_data.cause); pos += 2; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_PRIVACY_SET_MODE, pos, param); + } + + break; + + default: + break; + } +} +#endif +/***********************set le param**********************************/ +T_GAP_CAUSE hrp_le_set_gap_param(uint16_t type, uint8_t len, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_set_gap_param: type:%x= %b", type, TRACE_BINARY(len, p_value)); + return le_set_gap_param((T_GAP_LE_PARAM_TYPE)type, len, p_value); +} +T_GAP_CAUSE hrp_le_set_bond_param(uint16_t type, uint8_t len, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_set_bond_param: type:%x = %b", type, TRACE_BINARY(len, p_value)); + return le_bond_set_param((T_LE_BOND_PARAM_TYPE)type, len, p_value); +} +#if F_BT_LE_GAP_SCAN_SUPPORT +T_GAP_CAUSE hrp_le_set_scan_param(uint16_t type, uint8_t len, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_set_scan_param: type:%x = %b", type, TRACE_BINARY(len, p_value)); + return le_scan_set_param((T_LE_SCAN_PARAM_TYPE)type, len, p_value); +} +#endif +#if F_BT_LE_PRIVACY_SUPPORT +T_GAP_CAUSE hrp_le_set_privacy_param(uint16_t type, uint8_t len, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_set_privacy_param: type:%x = %b", type, TRACE_BINARY(len, p_value)); + return le_privacy_set_param((T_LE_PRIVACY_PARAM_TYPE)type, len, p_value); +} +#endif +T_GAP_CAUSE hrp_le_set_adv_param(uint16_t type, uint8_t len, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_set_adv_param: type:%x = %b", type, TRACE_BINARY(len, p_value)); + return le_adv_set_param((T_LE_ADV_PARAM_TYPE)type, len, p_value); +} + +/****************************get le param*********************************/ +T_GAP_CAUSE hrp_le_get_gap_param(uint16_t type, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_get_gap_param: type:%x = %b", type, TRACE_STRING(p_value)); + return le_get_gap_param((T_GAP_LE_PARAM_TYPE)type, p_value); +} + +T_GAP_CAUSE hrp_le_get_bond_param(uint16_t type, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_get_bond_param: type:%x = %b", type, TRACE_STRING(p_value)); + return le_bond_get_param((T_LE_BOND_PARAM_TYPE)type, p_value); +} +#if F_BT_LE_GAP_SCAN_SUPPORT +T_GAP_CAUSE hrp_le_get_scan_param(uint16_t type, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_get_scan_param: type:%x = %b", type, TRACE_STRING(p_value)); + return le_scan_get_param((T_LE_SCAN_PARAM_TYPE)type, p_value); +} +#endif +#if F_BT_LE_PRIVACY_SUPPORT +T_GAP_CAUSE hrp_le_get_privacy_param(uint16_t type, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_get_privacy_param: type:%x = %b", type, TRACE_STRING(p_value)); + return le_privacy_get_param((T_LE_PRIVACY_PARAM_TYPE)type, p_value); +} +#endif +T_GAP_CAUSE hrp_le_get_adv_param(uint16_t type, void *p_value) +{ + APP_PRINT_INFO2("hrp_le_get_privacy_param: type:%x = %b", type, TRACE_STRING(p_value)); + return le_adv_get_param((T_LE_ADV_PARAM_TYPE)type, p_value); +} + + + + + +/**********************start handle event fun************************************/ + + +void hrp_profile_handle_set_rand_addr(void *data) +{ + T_LE_SET_RAND_ADDR_RSP *tmpPtr = (T_LE_SET_RAND_ADDR_RSP *)data; + uint8_t evt_param[2]; + int pos = 0; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_SET_RAND_ADDR, pos, evt_param); +} +#if F_BT_LE_GAP_CENTRAL_SUPPORT +void hrp_profile_handle_set_host_chann_classif(void *data) +{ + T_LE_SET_HOST_CHANN_CLASSIF_RSP *tmpPtr = (T_LE_SET_HOST_CHANN_CLASSIF_RSP *)data; + uint8_t evt_param[2]; + int pos = 0; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_SET_HOST_CHANN_CLASSIF, pos, evt_param); +} +#endif + +void hrp_profile_handle_read_rssi(void *data) +{ + T_LE_READ_RSSI_RSP *tmpPtr = (T_LE_READ_RSSI_RSP *)data; + uint8_t evt_param[4]; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->rssi); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_READ_RSSI, pos, evt_param); +} +#if F_BT_LE_READ_CHANN_MAP +void hrp_profile_handle_read_chann_map(void *data) +{ + T_LE_READ_CHANN_MAP_RSP *tmpPtr = (T_LE_READ_CHANN_MAP_RSP *)data; + uint8_t evt_param[100]; + int pos = 0; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->channel_map, 5); + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_READ_CHANN_MAP, pos, evt_param); +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +void hrp_profile_handle_disable_slave_latency(void *data) +{ + T_LE_DISABLE_SLAVE_LATENCY_RSP *tmpPtr = (T_LE_DISABLE_SLAVE_LATENCY_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_DISABLE_SLAVE_LATENCY, pos, evt_param); +} +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT +void hrp_profile_handle_set_data_len(void *data) +{ + T_LE_SET_DATA_LEN_RSP *tmpPtr = (T_LE_SET_DATA_LEN_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_SET_DATA_LEN, pos, evt_param); +} + +void hrp_profile_handle_data_len_change_info(void *data) +{ + T_LE_DATA_LEN_CHANGE_INFO *tmpPtr = (T_LE_DATA_LEN_CHANGE_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->max_tx_octets); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->max_tx_time); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->max_rx_octets); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->max_rx_time); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_DATA_LEN_CHANGE_INFO, pos, evt_param); +} +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT +void hrp_profile_handle_conn_update_ind(void *data) +{ + T_LE_CONN_UPDATE_IND *tmpPtr = (T_LE_CONN_UPDATE_IND *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->conn_interval_min); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->conn_interval_max); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->conn_latency); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->supervision_timeout); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CONN_UPDATE_IND, pos, evt_param); +} +#endif +void hrp_profile_handle_create_conn_ind(void *data) +{ + T_LE_CREATE_CONN_IND *tmpPtr = (T_LE_CREATE_CONN_IND *)data; + int pos = 0; + uint8_t evt_param[100]; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->bd_addr, 6); + + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->remote_addr_type); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CREATE_CONN_IND, pos, evt_param); +} +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +void hrp_profile_handle_phy_update_info(void *data) +{ + T_LE_PHY_UPDATE_INFO *tmpPtr = (T_LE_PHY_UPDATE_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->tx_phy); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->rx_phy); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_PHY_UPDATE_INFO, pos, evt_param); +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +void hrp_profile_handle_update_passed_chann_map(void *data) +{ + T_LE_UPDATE_PASSED_CHANN_MAP_RSP *tmpPtr = (T_LE_UPDATE_PASSED_CHANN_MAP_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP, pos, evt_param); +} +#endif +#if F_BT_LE_READ_REMOTE_FEATS +void hrp_profile_handle_remote_feats_info(void *data) +{ + T_LE_REMOTE_FEATS_INFO *tmpPtr = (T_LE_REMOTE_FEATS_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->remote_feats, 8); + + APP_PRINT_INFO3("hrp_profile_handle_remote_feats_info: conn_id %d, cause=%d, remote_feats =%b", + tmpPtr->conn_id, tmpPtr->cause, TRACE_BINARY(8, tmpPtr->remote_feats)); + if (tmpPtr->remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & + LE_SUPPORT_FEATURES_LE_2M_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support 2M"); + } + if (tmpPtr->remote_feats[LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1] & + LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT) + { + APP_PRINT_INFO0("GAP_MSG_LE_REMOTE_FEATS_INFO: support CODED"); + } + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_REMOTE_FEATS_INFO, pos, evt_param); +} +#endif +void hrp_profile_handle_bond_modify_info(void *data) +{ + T_LE_BOND_MODIFY_INFO *tmpPtr = (T_LE_BOND_MODIFY_INFO *)data; + APP_PRINT_INFO2("GAP_MSG_LE_BOND_MODIFY_INFO: 0x%x, p_entry %p", + tmpPtr->type, tmpPtr->p_entry); +#if F_BT_LE_PRIVACY_SUPPORT + privacy_handle_bond_modify_msg(tmpPtr->type, tmpPtr->p_entry, true); +#endif + if (tmpPtr->type == LE_BOND_CLEAR) + { + return; + } + else if (tmpPtr->type == LE_BOND_KEY_MISSING) + { + le_bond_delete_by_idx(tmpPtr->p_entry->idx); + } + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->type); pos += 1; + + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->p_entry->is_used); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->p_entry->idx); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->p_entry->flags); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->p_entry->local_bd_type); pos += 1; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->p_entry->reserved, 2); + + hrp_profile_commit_buf(evt_param, &pos, &tmpPtr->p_entry->remote_bd, 8/*sizeof(T_LE_REMOTE_BD)*/); + + hrp_profile_commit_buf(evt_param, &pos, &tmpPtr->p_entry->resolved_remote_bd, + 8/* sizeof(T_LE_REMOTE_BD)*/); + + //hrp_profile_gap_le_event(HRP_GAP_MSG_LE_BOND_MODIFY_INFO, pos, evt_param); +} + +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT +void hrp_profile_handle_keypress_notify(void *data) +{ + T_LE_KEYPRESS_NOTIFY_RSP *tmpPtr = (T_LE_KEYPRESS_NOTIFY_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_KEYPRESS_NOTIFY, pos, evt_param); +} + +void hrp_profile_handle_keypress_notify_info(void *data) +{ + T_LE_KEYPRESS_NOTIFY_INFO *tmpPtr = (T_LE_KEYPRESS_NOTIFY_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->event_type); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_KEYPRESS_NOTIFY_INFO, pos, evt_param); +} +#endif +#if F_BT_LE_ATT_SIGNED_WRITE_SUPPORT +void hrp_profile_handle_gatt_signed_status_info(void *data) +{ + T_LE_GATT_SIGNED_STATUS_INFO *tmpPtr = (T_LE_GATT_SIGNED_STATUS_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->update_local); pos += 1; + LE_UINT32_TO_ARRAY(evt_param + pos, tmpPtr->local_sign_count); pos += 4; + LE_UINT32_TO_ARRAY(evt_param + pos, tmpPtr->remote_sign_count); pos += 4; + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_GATT_SIGNED_STATUS_INFO, pos, evt_param); +} +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT +void hrp_profile_handle_scan_info(void *data) +{ + T_LE_SCAN_INFO *tmpPtr = (T_LE_SCAN_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->bd_addr, 6); + + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->remote_addr_type); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->adv_type); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->rssi); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->data_len); pos += 1; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->data, 31); + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_SCAN_INFO, pos, evt_param); +} +#if F_BT_LE_PRIVACY_SUPPORT +void hrp_profile_handle_direct_adv_info(void *data) +{ + T_LE_DIRECT_ADV_INFO *tmpPtr = (T_LE_DIRECT_ADV_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->bd_addr, 6); + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->remote_addr_type); pos += 1; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->direct_bd_addr, 6); + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->direct_addr_type); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->direct_adv_type); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->rssi); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_DIRECT_ADV_INFO, pos, evt_param); +} +#endif +#endif +void hrp_profile_handle_adv_update_param(void *data) +{ + T_LE_ADV_UPDATE_PARAM_RSP *tmpPtr = (T_LE_ADV_UPDATE_PARAM_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_ADV_UPDATE_PARAM, pos, evt_param); +} +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT +void hrp_profile_handle_adv_read_tx_power(void *data) +{ + T_LE_ADV_READ_TX_POWER_RSP *tmpPtr = (T_LE_ADV_READ_TX_POWER_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->tx_power_level); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_ADV_READ_TX_POWER, pos, evt_param); +} +#endif +#if 0 +void hrp_profile_handle_dtm_receiver_test(void *data) +{ + T_LE_DTM_TEST_END_RSP *tmpPtr = (T_LE_DTM_TEST_END_RSP *)data; + int pos = 0; + + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->num_pkts); pos += 2; + + hrp_profile_gap_le_event(GAP_MSG_LE_DTM_RECEIVER_TEST, pos, evt_param); +} +void hrp_profile_handle_dtm_transmitter_test(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(GAP_MSG_LE_DTM_TRANSMITTER_TEST, pos, evt_param); +} + +void hrp_profile_handle_dtm_test_end(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(GAP_MSG_LE_DTM_TEST_END, pos, evt_param); +} +void hrp_profile_handle_dtm_enhanced_receiver_test(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(GAP_MSG_LE_DTM_ENHANCED_RECEIVER_TEST, pos, evt_param); +} +void hrp_profile_handle_dtm_enhanced_transmitter_test(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(GAP_MSG_LE_DTM_ENHANCED_TRANSMITTER_TEST, pos, evt_param); +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +void hrp_profile_handle_vendor_adv_3_data_enable(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE, pos, evt_param); +} + + +void hrp_profile_handle_vendor_adv_3_data_set(void *data) +{ + T_LE_VENDOR_ADV_3_DATA_SET_RSP *tmpPtr = (T_LE_VENDOR_ADV_3_DATA_SET_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->type); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_VENDOR_ADV_3_DATA_SET, pos, evt_param); +} + +void hrp_profile_handle_set_lps_bootup_active_time(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + uint8_t evt_param[10]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_SET_LPS_BOOTUP_ACTIVE_TIME, pos, evt_param); +} +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +void hrp_profile_handle_ext_adv_report_info(void *data) +{ + T_LE_EXT_ADV_REPORT_INFO *tmpPtr = (T_LE_EXT_ADV_REPORT_INFO *)data; + int pos = 0; + uint8_t param[500]; + + LE_UINT16_TO_ARRAY(param + pos, tmpPtr->event_type); pos += 2; + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->data_status); pos += 1; + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->addr_type); pos += 1; + hrp_profile_commit_buf(param, &pos, tmpPtr->bd_addr, 6); + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->primary_phy); pos += 1; + + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->secondary_phy); pos += 1; + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->adv_sid); pos += 1; + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->tx_power); pos += 1; + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->rssi); pos += 1; + LE_UINT16_TO_ARRAY(param + pos, tmpPtr->peri_adv_interval); pos += 2; + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->direct_addr_type); pos += 1; + hrp_profile_commit_buf(param, &pos, tmpPtr->direct_addr, 6); + LE_UINT8_TO_ARRAY(param + pos, tmpPtr->data_len); pos += 1; + hrp_profile_commit_buf(param, &pos, tmpPtr->p_data, tmpPtr->data_len); + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_REPORT_INFO, pos, param); +} +#endif +#if F_BT_LE_5_0_AE_ADV_SUPPORT +void hrp_profile_handle_ext_adv_start_setting(void *data) +{ + T_LE_EXT_ADV_START_SETTING_RSP *tmpPtr = (T_LE_EXT_ADV_START_SETTING_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->adv_handle); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->flag); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_START_SETTING, pos, evt_param); +} +void hrp_profile_handle_ext_adv_remove_set(void *data) +{ + T_LE_EXT_ADV_REMOVE_SET_RSP *tmpPtr = (T_LE_EXT_ADV_REMOVE_SET_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->adv_handle); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_REMOVE_SET, pos, evt_param); +} + +void hrp_profile_handle_ext_adv_clear_set(void *data) +{ + T_LE_EXT_ADV_CLEAR_SET_RSP *tmpPtr = (T_LE_EXT_ADV_CLEAR_SET_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_CLEAR_SET, pos, evt_param); +} +void hrp_profile_handle_ext_adv_enable(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_ENABLE, pos, evt_param); +} + +void hrp_profile_handle_ext_adv_disable(void *data) +{ + T_LE_CAUSE *tmpPtr = (T_LE_CAUSE *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_EXT_ADV_DISABLE, pos, evt_param); +} +void hrp_profile_handle_scan_req_received_info(void *data) +{ + T_LE_SCAN_REQ_RECEIVED_INFO *tmpPtr = (T_LE_SCAN_REQ_RECEIVED_INFO *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->adv_handle); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->scanner_addr_type); pos += 1; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->scanner_addr, 6); + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO, pos, evt_param); +} +#endif +void hrp_profile_handle_modify_white_list(void *data) +{ + T_LE_MODIFY_WHITE_LIST_RSP *tmpPtr = (T_LE_MODIFY_WHITE_LIST_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->operation); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_MODIFY_WHITE_LIST, pos, evt_param); +} + + + + +/*********************end handle event fun******************************/ + + + +T_APP_RESULT hrp_gap_le_cb(uint8_t cb_type, void *p_cb_data) +{ + T_LE_CB_DATA cb_data; + memcpy(&cb_data, p_cb_data, sizeof(T_LE_CB_DATA)); + APP_PRINT_INFO1("hrp_gap_le_cb: cb_type %d", cb_type); + switch (cb_type) + { +//gap_le.h + case GAP_MSG_LE_MODIFY_WHITE_LIST: + hrp_profile_handle_modify_white_list(cb_data.p_le_modify_white_list_rsp); + break; + case GAP_MSG_LE_SET_RAND_ADDR: + hrp_profile_handle_set_rand_addr(cb_data.p_le_set_rand_addr_rsp); + break; +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_SET_HOST_CHANN_CLASSIF: + hrp_profile_handle_set_host_chann_classif(cb_data.p_le_set_host_chann_classif_rsp); + break; +#endif +//gap_conn_le.h + case GAP_MSG_LE_READ_RSSI: + hrp_profile_handle_read_rssi(cb_data.p_le_read_rssi_rsp); + break; +#if F_BT_LE_READ_CHANN_MAP + case GAP_MSG_LE_READ_CHANN_MAP: + hrp_profile_handle_read_chann_map(cb_data.p_le_read_chann_map_rsp); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_DISABLE_SLAVE_LATENCY: + hrp_profile_handle_disable_slave_latency(cb_data.p_le_disable_slave_latency_rsp); + break; +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + case GAP_MSG_LE_SET_DATA_LEN: + hrp_profile_handle_set_data_len(cb_data.p_le_set_data_len_rsp); + break; + case GAP_MSG_LE_DATA_LEN_CHANGE_INFO: + hrp_profile_handle_data_len_change_info(cb_data.p_le_data_len_change_info); + break; +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_CONN_UPDATE_IND: + hrp_profile_handle_conn_update_ind(cb_data.p_le_conn_update_ind); + break; +#endif + case GAP_MSG_LE_CREATE_CONN_IND: + hrp_profile_handle_create_conn_ind(cb_data.p_le_create_conn_ind); + break; +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + case GAP_MSG_LE_PHY_UPDATE_INFO: + hrp_profile_handle_phy_update_info(cb_data.p_le_phy_update_info); + break; +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP: + hrp_profile_handle_update_passed_chann_map(cb_data.p_le_update_passed_chann_map_rsp); + break; +#endif +#if F_BT_LE_READ_REMOTE_FEATS + case GAP_MSG_LE_REMOTE_FEATS_INFO: + hrp_profile_handle_remote_feats_info(cb_data.p_le_remote_feats_info); + break; +#endif +//gap_bond_le.h + case GAP_MSG_LE_BOND_MODIFY_INFO: + hrp_profile_handle_bond_modify_info(cb_data.p_le_bond_modify_info); + break; +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + case GAP_MSG_LE_KEYPRESS_NOTIFY: + hrp_profile_handle_keypress_notify(cb_data.p_le_keypress_notify_rsp); + break; + case GAP_MSG_LE_KEYPRESS_NOTIFY_INFO: + hrp_profile_handle_keypress_notify_info(cb_data.p_le_keypress_notify_info); + break; +#endif +#if F_BT_LE_ATT_SIGNED_WRITE_SUPPORT + case GAP_MSG_LE_GATT_SIGNED_STATUS_INFO: + hrp_profile_handle_gatt_signed_status_info(cb_data.p_le_gatt_signed_status_info); + break; +#endif +//gap_scan.h +#if F_BT_LE_GAP_CENTRAL_SUPPORT + case GAP_MSG_LE_SCAN_INFO: + hrp_profile_handle_scan_info(cb_data.p_le_scan_info); + break; +#if F_BT_LE_PRIVACY_SUPPORT + case GAP_MSG_LE_DIRECT_ADV_INFO: + hrp_profile_handle_direct_adv_info(cb_data.p_le_direct_adv_info); + break; +#endif +#endif +//gap_adv.h + case GAP_MSG_LE_ADV_UPDATE_PARAM: + hrp_profile_handle_adv_update_param(cb_data.p_le_adv_update_param_rsp); + break; +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + case GAP_MSG_LE_ADV_READ_TX_POWER: + hrp_profile_handle_adv_read_tx_power(cb_data.p_le_adv_read_tx_power_rsp); + break; +#endif +//gap_dtm.h +#if 0 + case HRP_GAP_MSG_LE_DTM_RECEIVER_TEST: + hrp_profile_handle_dtm_receiver_test(p_cb_data); + break; + case HRP_GAP_MSG_LE_DTM_TRANSMITTER_TEST: + hrp_profile_handle_dtm_transmitter_test(p_cb_data); + break; + case HRP_GAP_MSG_LE_DTM_TEST_END: + hrp_profile_handle_dtm_test_end(p_cb_data); + break; + case HRP_GAP_MSG_LE_DTM_ENHANCED_RECEIVER_TEST: + hrp_profile_handle_dtm_enhanced_receiver_test(p_cb_data); + break; + case HRP_GAP_MSG_LE_DTM_ENHANCED_TRANSMITTER_TEST: + hrp_profile_handle_dtm_enhanced_transmitter_test(p_cb_data); + break; +#endif +//gap_vendor.h +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + case GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE: + hrp_profile_handle_vendor_adv_3_data_enable(&cb_data.le_cause); + break; + case GAP_MSG_LE_VENDOR_ADV_3_DATA_SET: + hrp_profile_handle_vendor_adv_3_data_set(cb_data.p_le_vendor_adv_3_data_set_rsp); + break; + case GAP_MSG_GAP_SET_LPS_BOOTUP_ACTIVE_TIME: + hrp_profile_handle_set_lps_bootup_active_time(&cb_data.le_cause); + break; +#endif +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +//gap_ext_scan.h + case GAP_MSG_LE_EXT_ADV_REPORT_INFO: + hrp_profile_handle_ext_adv_report_info(cb_data.p_le_ext_adv_report_info); + break; +#endif + +#if F_BT_LE_5_0_AE_ADV_SUPPORT +//gap_ext_adv.h + case GAP_MSG_LE_EXT_ADV_START_SETTING: + hrp_profile_handle_ext_adv_start_setting(cb_data.p_le_ext_adv_start_setting_rsp); + break; + case GAP_MSG_LE_EXT_ADV_REMOVE_SET: + hrp_profile_handle_ext_adv_remove_set(cb_data.p_le_ext_adv_remove_set_rsp); + break; + case GAP_MSG_LE_EXT_ADV_CLEAR_SET: + hrp_profile_handle_ext_adv_clear_set(cb_data.p_le_ext_adv_clear_set_rsp); + break; + case GAP_MSG_LE_EXT_ADV_ENABLE: + hrp_profile_handle_ext_adv_enable(&cb_data.le_cause); + break; + case GAP_MSG_LE_EXT_ADV_DISABLE: + hrp_profile_handle_ext_adv_disable(&cb_data.le_cause); + break; + case GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO: + hrp_profile_handle_scan_req_received_info(cb_data.p_le_scan_req_received_info); + break; +#endif + + default: + break; + } + return APP_RESULT_SUCCESS; +} + + +void hrp_profile_server_init(uint16_t le_profile_sever_mask) +{ + server_init(7); + APP_PRINT_INFO1("hrp_profile_server_init: le_profile_sever_mask %d", + le_profile_sever_mask); + + if (SIMPLE_BLE_SERVICE & le_profile_sever_mask) + { + + simp_srv_id = simp_ble_service_add_service((void *)hrp_profile_callback); + } + if (SIMPLE_BLE_ADD_SERVICE & le_profile_sever_mask) + { + for (uint8_t i = 1; i <= 6; i++) + { + simp_ble_service_add_service((void *)hrp_profile_callback); + APP_PRINT_INFO1("hrp_profile_server_init :add service %d times.", i); + } + + } + + server_register_app_cb(hrp_profile_callback); + +} + +/****************************hrp service event function **************************************/ + +void hrp_profile_handle_profile_evt_srv_reg_complete(T_SERVER_RESULT service_reg_result) +{ + int pos = 0; + uint8_t evt_param[100]; + + LE_UINT8_TO_ARRAY(evt_param + pos, service_reg_result); pos += 1; + + hrp_profile_general_id_event(HRP_PROFILE_EVT_SRV_REG_COMPLETE, pos, evt_param); +} +void hrp_profile_handle_profile_evt_send_data_complete(uint8_t conn_id, uint16_t cause, + T_SERVER_ID service_id, + uint16_t attrib_idx, uint16_t credits) +{ + int pos = 0; + uint8_t evt_param[100]; + + LE_UINT16_TO_ARRAY(evt_param + pos, credits); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, conn_id); pos += 1; + LE_UINT8_TO_ARRAY(evt_param + pos, service_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, attrib_idx); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, cause); pos += 2; + + hrp_profile_general_id_event(HRP_PROFILE_EVT_SRV_SEND_DATA_COMPLETE, pos, evt_param); +} + + +T_APP_RESULT hrp_profile_callback(T_SERVER_ID service_id, void *p_data) +{ + T_APP_RESULT app_result = APP_RESULT_SUCCESS; + if (service_id == SERVICE_PROFILE_GENERAL_ID) + { + T_SERVER_APP_CB_DATA *p_param = (T_SERVER_APP_CB_DATA *)p_data; + switch (p_param->eventId) + { + case PROFILE_EVT_SRV_REG_COMPLETE:// srv register result event. + { + APP_PRINT_INFO1("PROFILE_EVT_SRV_REG_COMPLETE: result %d", + p_param->event_data.service_reg_result); + hrp_profile_handle_profile_evt_srv_reg_complete(p_param->event_data.service_reg_result); + } + + break; + + case PROFILE_EVT_SEND_DATA_COMPLETE: + { + APP_PRINT_INFO5("PROFILE_EVT_SEND_DATA_COMPLETE: conn_id %d, cause 0x%x, service_id %d, attrib_idx 0x%x, credits %d", + p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + if (p_param->event_data.send_data_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO0("PROFILE_EVT_SEND_DATA_COMPLETE success"); + } + else + { + APP_PRINT_ERROR0("PROFILE_EVT_SEND_DATA_COMPLETE failed"); + } + + hrp_profile_handle_profile_evt_send_data_complete(p_param->event_data.send_data_result.conn_id, + p_param->event_data.send_data_result.cause, + p_param->event_data.send_data_result.service_id, + p_param->event_data.send_data_result.attrib_idx, + p_param->event_data.send_data_result.credits); + } + + break; + + default: + break; + } + } + else if (service_id == simp_srv_id) + { + TSIMP_CALLBACK_DATA *p_simp_cb_data = (TSIMP_CALLBACK_DATA *)p_data; + hrp_profile_server_simp_ble_callback(p_simp_cb_data); + } + return app_result; +} + +#if F_BT_LE_GATT_CLIENT_SUPPORT +void hrp_profile_client_init(uint16_t le_profile_client_mask) +{ + client_init(3); + gaps_client_id = gaps_add_client(hrp_client_callback, 4); + APP_PRINT_INFO1("hrp_profile_client_init: le_profile_client_mask %d", + le_profile_client_mask); + + if (SIMPLE_BLE_CLIENT & le_profile_client_mask) + { + simple_ble_client_id = simp_ble_add_client(hrp_client_callback, 4); + } + +} +#endif +#if F_BT_LE_PRIVACY_SUPPORT +void hrp_privacy_init() +{ + hrp_test_privacy = false; + + uint8_t central_address_resolution = 1; + privacy_manage_mode(false); + privacy_init(app_privacy_callback, false); + gaps_set_parameter(GAPS_PARAM_CENTRAL_ADDRESS_RESOLUTION, sizeof(central_address_resolution), + ¢ral_address_resolution); +} +#endif +/** + * @brief Callback will be called when data sent from profile client layer. + * @param client_id the ID distinguish which module sent the data. + * @param conn_id connection ID. + * @param p_data pointer to data. + * @retval result @ref T_APP_RESULT + */ + +/****************************hrp client event function **************************************/ +#if F_BT_LE_GATT_CLIENT_SUPPORT +void hrp_profile_handle_client_app_cb_type_disc_state(T_DISCOVERY_STATE disc_state) +{ + int pos = 0; + uint8_t evt_param[1]; + + LE_UINT8_TO_ARRAY(evt_param + pos, disc_state); pos += 1; + + hrp_profile_general_id_event(HRP_PROFILE_EVT_CLIENT_DISC_STATE, pos, evt_param); +} +void hrp_profile_handle_client_app_cb_type_disc_result(T_DISCOVERY_RESULT_TYPE result_type) +{ + int pos = 0; + uint8_t evt_param[1]; + + LE_UINT8_TO_ARRAY(evt_param + pos, result_type); pos += 1; + + hrp_profile_general_id_event(HRP_PROFILE_EVT_CLIENT_DISC_RESULT, pos, evt_param); +} + +T_APP_RESULT hrp_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + APP_PRINT_INFO2("app_client_callback: client_id %d, conn_id %d", + client_id, conn_id); + if (client_id == CLIENT_PROFILE_GENERAL_ID) + { + T_CLIENT_APP_CB_DATA *p_client_app_cb_data = (T_CLIENT_APP_CB_DATA *)p_data; + switch (p_client_app_cb_data->cb_type) + { + case CLIENT_APP_CB_TYPE_DISC_STATE: + { + + if (p_client_app_cb_data->cb_content.disc_state_data.disc_state == DISC_STATE_SRV_DONE) + { + APP_PRINT_INFO0("Discovery All Service Procedure Done."); + } + else + { + APP_PRINT_INFO0("Discovery state send to application directly."); + } + + hrp_profile_handle_client_app_cb_type_disc_state( + p_client_app_cb_data->cb_content.disc_state_data.disc_state); + } + + break; + case CLIENT_APP_CB_TYPE_DISC_RESULT: + { + + if (p_client_app_cb_data->cb_content.disc_result_data.result_type == DISC_RESULT_ALL_SRV_UUID16) + { + APP_PRINT_INFO3("Discovery All Primary Service: UUID16 0x%x, start handle 0x%x, end handle 0x%x.", + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->uuid16, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->att_handle, + p_client_app_cb_data->cb_content.disc_result_data.result_data.p_srv_uuid16_disc_data->end_group_handle); + } + else + { + APP_PRINT_INFO0("Discovery result send to application directly."); + } + + hrp_profile_handle_client_app_cb_type_disc_result( + p_client_app_cb_data->cb_content.disc_result_data.result_type); + } + + break; + default: + break; + } + + } + else if (client_id == gaps_client_id) + { + T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data = (T_GAPS_CLIENT_CB_DATA *)p_data; + hrp_profile_client_gaps_callback(p_gaps_cb_data); + + } + else if (client_id == simple_ble_client_id) + { + T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data = (T_SIMP_CLIENT_CB_DATA *)p_data; + hrp_profile_client_simp_ble_callback(p_simp_client_cb_data); + + } + + return result; +} +#endif +void hrp_gap_le_init(uint16_t le_profile_sever_mask, uint16_t le_profile_client_mask) +{ + bool sign_flag = true; + APP_PRINT_TRACE1("hrp_gap_le_init:link_num: %d", APP_MAX_LINKS); + le_gap_init(APP_MAX_LINKS); +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + gap_lib_init(); +#endif + le_register_app_cb(hrp_gap_le_cb); + le_bond_set_param(GAP_PARAM_BOND_SIGN_KEY_FLAG, 1, &sign_flag); + // init server profiles + hrp_profile_server_init(le_profile_sever_mask); + // init client profiles +#if F_BT_LE_GATT_CLIENT_SUPPORT + hrp_profile_client_init(le_profile_client_mask); +#endif +#if F_BT_LE_4_1_CBC_SUPPORT + le_cbc_init(HRP_CHANN_NUM); + le_cbc_register_app_cb(hrp_credit_based_conn_callback); +#endif +#if F_BT_LE_PRIVACY_SUPPORT + hrp_privacy_init(); +#endif + +} + +#if F_BT_LE_4_1_CBC_SUPPORT +void hrp_gap_handle_cbc_le_chann_state(void *data) +{ + T_LE_CBC_CHANN_STATE *tmpPtr = (T_LE_CBC_CHANN_STATE *)data; + int pos = 0; + uint8_t evt_param[100]; + + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cid); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_state); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CBC_CHANN_STATE, pos, evt_param); +} +void hrp_gap_handle_cbc_le_get_mtu(uint16_t mtu) +{ + int pos = 0; + uint8_t evt_param[2]; + LE_UINT16_TO_ARRAY(evt_param + pos, mtu); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CBC_MTU_INFO, pos, evt_param); +} +void hrp_gap_handle_cbc_le_reg_psm(void *data) +{ + T_LE_CBC_CREDIT_BASED_PSM_REG_RSP *tmpPtr = (T_LE_CBC_CREDIT_BASED_PSM_REG_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->le_psm); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CBC_REG_PSM, pos, evt_param); +} + +void hrp_gap_handle_cbc_le_set_psm_security(void *data) +{ + T_LE_CBC_CREDIT_BASED_SECURITY_REG_RSP *tmpPtr = (T_LE_CBC_CREDIT_BASED_SECURITY_REG_RSP *)data; + int pos = 0; + uint8_t evt_param[100]; + + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CBC_SET_PSM_SECURITY, pos, evt_param); +} + +void hrp_gap_handle_cbc_le_send_data(void *data) +{ + T_LE_CBC_SEND_DATA *tmpPtr = (T_LE_CBC_SEND_DATA *)data; + int pos = 0; + uint8_t evt_param[100]; + + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cid); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cause); pos += 2; + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->credit); pos += 1; + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CBC_SEND_DATA, pos, evt_param); +} + +void hrp_gap_handle_cbc_le_receive_data(void *data) +{ + T_LE_CBC_RECEIVE_DATA *tmpPtr = (T_LE_CBC_RECEIVE_DATA *)data; + int pos = 0; + uint8_t *evt_param; + evt_param = os_mem_alloc(RAM_TYPE_DATA_ON, 1500); + + LE_UINT8_TO_ARRAY(evt_param + pos, tmpPtr->conn_id); pos += 1; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->cid); pos += 2; + LE_UINT16_TO_ARRAY(evt_param + pos, tmpPtr->value_len); pos += 2; + hrp_profile_commit_buf(evt_param, &pos, tmpPtr->p_data, tmpPtr->value_len); + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_CBC_RECEIVE_DATA, pos, evt_param); + + APP_PRINT_INFO2("hrp_gap_handle_cbc_le_receive_data: len:%d pdata= %b", tmpPtr->value_len, + TRACE_BINARY(tmpPtr->value_len, tmpPtr->p_data)); + + os_mem_free(evt_param); +} + + + +T_APP_RESULT hrp_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data) +{ + T_APP_RESULT result = APP_RESULT_SUCCESS; + T_LE_CBC_DATA cb_data; + memcpy(&cb_data, p_cbc_data, sizeof(T_LE_CBC_DATA)); + APP_PRINT_TRACE1("hrp_credit_based_conn_callback: cbc_type = %d", cbc_type); + switch (cbc_type) + { + case GAP_CBC_MSG_LE_CHANN_STATE: + { + APP_PRINT_INFO4("GAP_CBC_MSG_LE_CHANN_STATE: conn_id %d, cid 0x%x, conn_state %d, cause 0x%x", + cb_data.p_le_chann_state->conn_id, + cb_data.p_le_chann_state->cid, + cb_data.p_le_chann_state->conn_state, + cb_data.p_le_chann_state->cause); + if (cb_data.p_le_chann_state->conn_state == GAP_CHANN_STATE_CONNECTED) + { + uint16_t mtu; + le_cbc_get_chann_param(CBC_CHANN_PARAM_MTU, &mtu, cb_data.p_le_chann_state->cid); + APP_PRINT_INFO1("GAP_CHANN_STATE_CONNECTED: mtu %d", mtu); + hrp_gap_handle_cbc_le_get_mtu(mtu); + } + hrp_gap_handle_cbc_le_chann_state(cb_data.p_le_chann_state); + } + + break; + + case GAP_CBC_MSG_LE_REG_PSM: + { + APP_PRINT_INFO2("GAP_CBC_MSG_LE_REG_PSM: le_psm 0x%x, cause 0x%x", + cb_data.p_le_reg_psm_rsp->le_psm, + cb_data.p_le_reg_psm_rsp->cause); + hrp_gap_handle_cbc_le_reg_psm(cb_data.p_le_reg_psm_rsp); + } + + break; + + case GAP_CBC_MSG_LE_SET_PSM_SECURITY: + { + APP_PRINT_INFO1("GAP_CBC_MSG_LE_SET_PSM_SECURITY: cause 0x%x", + cb_data.p_le_set_psm_security_rsp->cause); + hrp_gap_handle_cbc_le_set_psm_security(cb_data.p_le_set_psm_security_rsp); + } + + break; + + case GAP_CBC_MSG_LE_SEND_DATA: + { + APP_PRINT_INFO4("GAP_CBC_MSG_LE_SEND_DATA: conn_id %d, cid 0x%x, cause 0x%x, credit %d", + cb_data.p_le_send_data->conn_id, + cb_data.p_le_send_data->cid, + cb_data.p_le_send_data->cause, + cb_data.p_le_send_data->credit); + hrp_gap_handle_cbc_le_send_data(cb_data.p_le_send_data); + } + + break; + + case GAP_CBC_MSG_LE_RECEIVE_DATA: + { + APP_PRINT_INFO3("GAP_CBC_MSG_LE_RECEIVE_DATA: conn_id %d, cid 0x%x, value_len %d", + cb_data.p_le_receive_data->conn_id, + cb_data.p_le_receive_data->cid, + cb_data.p_le_receive_data->value_len); + hrp_gap_handle_cbc_le_receive_data(cb_data.p_le_receive_data); + } + + break; + + default: + break; + } + return result; +} +#endif + + +//================================cmd =============================// + +static void hrp_gap_le_bond_delete_by_bd(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t bd_addr[6] = {0}; + uint8_t bd_type; + + T_GAP_CAUSE tgap_cause; + memcpy(bd_addr, p_param_list + pos, 6); pos += 6; + LE_ARRAY_TO_UINT8(bd_type, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_delete_by_bd(bd_addr, (T_GAP_REMOTE_ADDR_TYPE)bd_type); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} + +static void hrp_gap_le_bond_delete_by_idx(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t idx; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(idx, p_param_list + pos); pos += 1; + tgap_cause = le_bond_delete_by_idx(idx); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} + +static void hrp_gap_le_set_gap_param(uint16_t len, uint8_t *p_param_list) +{ + uint8_t pos = 0; + uint8_t param_type; + uint8_t data_len; + uint16_t data_type; + uint8_t *p_value; + T_GAP_CAUSE tgap_cause; + + while (pos < len) + { + param_type = p_param_list[pos++]; + /* parse data field: len(1 byte) + type(GAP_DATA_TYPE_LEN byte) + value (len - GAP_DATA_TYPE_LEN)*/ + data_len = p_param_list[pos++]; + LE_ARRAY_TO_UINT16(data_type, p_param_list); pos += 2; + p_value = p_param_list + pos; + pos += data_len - GAP_DATA_TYPE_LEN; + switch (param_type) + { + case LE_SET_PARAM_TYPE_GAP: + tgap_cause = hrp_le_set_gap_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + hrp_profile_gap_le_cmd_result(tgap_cause); + break; + case LE_SET_PARAM_TYPE_BOND: + tgap_cause = hrp_le_set_bond_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + hrp_profile_gap_le_cmd_result(tgap_cause); + break; +#if F_BT_LE_GAP_SCAN_SUPPORT + case LE_SET_PARAM_TYPE_SCAN: + tgap_cause = hrp_le_set_scan_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + hrp_profile_gap_le_cmd_result(tgap_cause); + break; +#endif +#if F_BT_LE_PRIVACY_SUPPORT + case LE_SET_PARAM_TYPE_PRIVACY: + tgap_cause = hrp_le_set_privacy_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + hrp_profile_gap_le_cmd_result(tgap_cause); + break; +#endif + case LE_SET_PARAM_TYPE_ADV: + tgap_cause = hrp_le_set_adv_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + hrp_profile_gap_le_cmd_result(tgap_cause); + break; + default: + break; + } + } + +} + + + + +static void hrp_gap_le_get_gap_param(uint16_t len, uint8_t *p_param_list) +{ + uint8_t pos = 0; + uint8_t param_type; + uint16_t data_type; + uint8_t *p_value; + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, 6); + + param_type = p_param_list[pos++]; + + /* parse data field: type(GAP_DATA_TYPE_LEN byte) + value (len - GAP_DATA_TYPE_LEN-param_type)*/ + LE_ARRAY_TO_UINT16(data_type, p_param_list); pos += 2; + // p_value = p_param_list + pos; + + switch (param_type) + { + case LE_GET_PARAM_TYPE_GAP: + hrp_le_get_gap_param(data_type, (void *)p_value); + break; + case LE_GET_PARAM_TYPE_BOND: + hrp_le_get_bond_param(data_type, (void *)p_value); + break; +#if F_BT_LE_GAP_SCAN_SUPPORT + case LE_GET_PARAM_TYPE_SCAN: + hrp_le_get_scan_param(data_type, (void *)p_value); + break; +#endif +#if F_BT_LE_PRIVACY_SUPPORT + case LE_GET_PARAM_TYPE_PRIVACY: + hrp_le_get_privacy_param(data_type, (void *)p_value); + break; +#endif + case LE_GET_PARAM_TYPE_ADV: + hrp_le_get_adv_param(data_type, (void *)p_value); + break; + default: + break; + } + os_mem_free(p_value); +} +static void hrp_gap_le_bond_clear_all_keys(uint16_t len, uint8_t *p_param_list) +{ + le_bond_clear_all_keys(); + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); + +} +#if F_BT_LE_SMP_SC_OOB_SUPPORT +static void hrp_gap_le_bond_sc_peer_oob_init(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE tgap_cause; + T_GAP_LE_PEER_OOB_DATA *p_peer_oob_data = 0; + p_peer_oob_data = os_mem_alloc(RAM_TYPE_DATA_ON, sizeof(T_GAP_LE_PEER_OOB_DATA)); + hrp_profile_fetch_buf(p_peer_oob_data, &pos, p_param_list, sizeof(T_GAP_LE_PEER_OOB_DATA)); + tgap_cause = le_bond_sc_peer_oob_init(p_peer_oob_data); + + hrp_profile_gap_le_cmd_result(tgap_cause); + os_mem_free(p_peer_oob_data); +} + +static void hrp_gap_le_bond_sc_local_oob_init(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + APP_PRINT_INFO0("hrp_profile_le_bond_sc_local_oob_init"); + uint64_t ecc_rand_in[4] = {0x1111111111111111, 0x1111111111111111, 0x1111111111111111, 0x1111111111111111}; + uint8_t local_rand[16] = {0x11, 0x11}; + T_GAP_LE_LOCAL_OOB_DATA *local_oob_data; + local_oob_data = os_mem_alloc(RAM_TYPE_DATA_ON, sizeof(T_GAP_LE_LOCAL_OOB_DATA)); + T_GAP_CAUSE tgap_cause; + hrp_profile_fetch_buf(ecc_rand_in, &pos, p_param_list, 32); + hrp_profile_fetch_buf(local_rand, &pos, p_param_list, 16); + hrp_profile_fetch_buf(local_oob_data, &pos, p_param_list, sizeof(T_GAP_LE_LOCAL_OOB_DATA)); + tgap_cause = le_bond_sc_local_oob_init(ecc_rand_in, local_rand, local_oob_data); + + hrp_profile_gap_le_cmd_result(tgap_cause); + os_mem_free(local_oob_data); + +} + +#endif +static void hrp_gap_le_bond_cfg_local_key_distribute(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t init_dist; + uint8_t rsp_dist; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(init_dist, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(rsp_dist, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_cfg_local_key_distribute(init_dist, rsp_dist); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} + +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT +static void hrp_gap_le_bond_keypress_notify(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint8_t type; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(type, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_keypress_notify(conn_id, (T_GAP_KEYPRESS_NOTIF_TYPE)type); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +static void hrp_gap_le_bond_user_confirm(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint8_t cause; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_user_confirm(conn_id, (T_GAP_CFM_CAUSE)cause); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_bond_passkey_display_confirm(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint8_t cause; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_passkey_display_confirm(conn_id, (T_GAP_CFM_CAUSE)cause); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_bond_just_work_confirm(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint8_t cause; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_just_work_confirm(conn_id, (T_GAP_CFM_CAUSE)cause); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#if F_BT_LE_SMP_OOB_SUPPORT +static void hrp_gap_le_bond_oob_input_confirm(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint8_t cause; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_oob_input_confirm(conn_id, (T_GAP_CFM_CAUSE)cause); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +static void hrp_gap_le_bond_passkey_input_confirm(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint32_t passcode; + uint8_t cause; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT32(passcode, p_param_list + pos); pos += 4; + LE_ARRAY_TO_UINT8(cause, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_passkey_input_confirm(conn_id, passcode, (T_GAP_CFM_CAUSE)cause); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_bond_get_display_key(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + uint32_t *p_key; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_get_display_key(conn_id, p_key); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_bond_pair(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + + T_GAP_CAUSE tgap_cause; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + tgap_cause = le_bond_pair(conn_id); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_scan_stop(uint16_t len, uint8_t *p_param_list) +{ + + T_GAP_CAUSE tgap_cause; + + tgap_cause = le_scan_stop(); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_scan_start(uint16_t len, uint8_t *p_param_list) +{ + + T_GAP_CAUSE tgap_cause; + + tgap_cause = le_scan_start(); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT +static void hrp_gap_le_adv_read_tx_power(uint16_t len, uint8_t *p_param_list) +{ + + T_GAP_CAUSE tgap_cause; + + tgap_cause = le_adv_read_tx_power(); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +static void hrp_gap_le_adv_update_param(uint16_t len, uint8_t *p_param_list) +{ + + + T_GAP_CAUSE tgap_cause; + + tgap_cause = le_adv_update_param(); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_adv_stop(uint16_t len, uint8_t *p_param_list) +{ + + + T_GAP_CAUSE tgap_cause; + + tgap_cause = le_adv_stop(); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_adv_start(uint16_t len, uint8_t *p_param_list) +{ + + T_GAP_CAUSE tgap_cause; + + tgap_cause = le_adv_start(); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +static void hrp_gap_le_update_conn_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t ce_length_min; + uint16_t ce_length_max; + + T_GAP_CAUSE tgap_cause; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(conn_interval_min, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(conn_interval_max, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(conn_latency, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(supervision_timeout, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(ce_length_min, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(ce_length_max, p_param_list + pos); pos += 2; + + tgap_cause = le_update_conn_param(conn_id, conn_interval_min, conn_interval_max, conn_latency, + supervision_timeout, ce_length_min, ce_length_max); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#if 0 +static void hrp_gap_le_disable_slave_latency(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + bool disable; + + T_GAP_CAUSE tgap_cause; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(disable, p_param_list + pos); pos += 1; + tgap_cause = le_disable_slave_latency(conn_id, disable); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE +static void hrp_gap_le_update_passed_chann_map(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + bool enable; + + T_GAP_CAUSE tgap_cause; + + LE_ARRAY_TO_UINT8(enable, p_param_list + pos); pos += 1; + + tgap_cause = le_update_passed_chann_map(enable); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT +static void hrp_gap_le_set_conn_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t type; + T_GAP_LE_CONN_REQ_PARAM *p_conn_param = NULL; + T_GAP_CAUSE tgap_cause; + p_conn_param = os_mem_alloc(RAM_TYPE_DATA_ON, sizeof(T_GAP_LE_CONN_REQ_PARAM)); + + LE_ARRAY_TO_UINT8(type, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(p_conn_param->scan_interval, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->scan_window, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->conn_interval_min, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->conn_interval_max, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->conn_latency, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->supv_tout, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->ce_len_min, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(p_conn_param->ce_len_max, p_param_list + pos); pos += 2; + + tgap_cause = le_set_conn_param((T_GAP_CONN_PARAM_TYPE)type, p_conn_param); + + hrp_profile_gap_le_cmd_result(tgap_cause); + os_mem_free(p_conn_param); + +} +static void hrp_gap_le_connect(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t init_phys; + uint8_t remote_bd[6] = {0}; + uint8_t remote_bd_type; + uint8_t local_bd_type; + uint16_t scan_timeout; + + T_GAP_CAUSE tgap_cause; + + LE_ARRAY_TO_UINT8(init_phys, p_param_list + pos); pos += 1; + memcpy(remote_bd, p_param_list + pos, 6); pos += 6; + + LE_ARRAY_TO_UINT8(remote_bd_type, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(local_bd_type, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(scan_timeout, p_param_list + pos); pos += 2; + + tgap_cause = le_connect(init_phys, remote_bd, (T_GAP_REMOTE_ADDR_TYPE)remote_bd_type, + (T_GAP_LOCAL_ADDR_TYPE)local_bd_type, scan_timeout); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT +static void hrp_gap_le_set_phy(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + uint8_t phy_options; + + T_GAP_CAUSE tgap_cause; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(all_phys, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(tx_phys, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(rx_phys, p_param_list + pos); pos += 1; + phy_options = p_param_list[pos++]; + tgap_cause = le_set_phy(conn_id, all_phys, tx_phys, rx_phys, (T_GAP_PHYS_OPTIONS)phy_options); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT +static void hrp_gap_le_set_data_len(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + uint16_t tx_octets; + uint16_t tx_time; + + T_GAP_CAUSE tgap_cause; + + conn_id = p_param_list[pos++]; + LE_ARRAY_TO_UINT16(tx_octets, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(tx_time, p_param_list + pos); pos += 2; + + tgap_cause = le_set_data_len(conn_id, tx_octets, tx_time); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +#if F_BT_LE_READ_CHANN_MAP +static void hrp_gap_le_read_chann_map(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + + T_GAP_CAUSE tgap_cause; + + conn_id = p_param_list[pos++]; + + tgap_cause = le_read_chann_map(conn_id); + + hrp_profile_gap_le_cmd_result(tgap_cause); + +} +#endif +static void hrp_gap_le_read_rssi(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + + T_GAP_CAUSE tgap_status; + + conn_id = p_param_list[pos++]; + + tgap_status = le_read_rssi(conn_id); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +static void hrp_gap_le_disconnect(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + + T_GAP_CAUSE tgap_status; + + conn_id = p_param_list[pos++]; + + tgap_status = le_disconnect(conn_id); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +static void hrp_gap_le_get_idle_link_num(uint16_t len, uint8_t *p_param_list) +{ + le_get_idle_link_num(); + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); +} + +static void hrp_gap_le_get_active_link_num(uint16_t len, uint8_t *p_param_list) +{ + le_get_active_link_num(); + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); +} + +static void hrp_gap_le_get_conn_addr(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + uint8_t bd_addr[6] = {0};; + uint8_t *bd_type; + + conn_id = p_param_list[pos++]; + + if (le_get_conn_addr(conn_id, bd_addr, bd_type)) + { + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); + } + else + { + hrp_profile_gap_le_cmd_result(GAP_CAUSE_NON_CONN); + } +} +#if F_BT_DLPS_EN +static void hrp_gap_le_set_lps_bootup_active_time(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint16_t active_time; + + LE_ARRAY_TO_UINT16(active_time, p_param_list + pos); pos += 2; + + if (gap_set_lps_bootup_active_time(active_time)) + { + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); + } + else + { + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SEND_REQ_FAILED); + } +} + +static void hrp_gap_le_check_lps_wakeup_time_enable(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint16_t check_time; + uint8_t enable; + LE_ARRAY_TO_UINT16(check_time, p_param_list + pos); pos += 2; + + LE_ARRAY_TO_UINT8(enable, p_param_list + pos); pos += 1; + + if (enable) + { + if (NULL == g_check_lps_wakeup_timer_handle) + { + os_timer_create(&g_check_lps_wakeup_timer_handle, "CheckTimer", 1, check_time, true, + hrp_gap_le_check_lps_event_to_app); + } + APP_PRINT_INFO0("check lps wakeup time Enable"); + //start total timer + os_timer_start(&g_check_lps_wakeup_timer_handle); + + } + else + { + APP_PRINT_INFO0("check lps wakeup time Disable"); + os_timer_stop(&g_check_lps_wakeup_timer_handle); + + } + +} +extern void *hIoQueueHandle; + +void hrp_gap_le_check_lps_event_to_app(void *pxTimer) +{ + T_IO_MSG io_driver_msg_send; + uint8_t event = EVENT_IO_TO_APP; + io_driver_msg_send.type = IO_MSG_TYPE_TIMER; + //APP_PRINT_INFO0("hrp_gap_le_check_lps_event_to_app"); + if (os_msg_send(hIoQueueHandle, &io_driver_msg_send, 0) == false) + { + return; + } + else if (os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleEvent, &event, 0) == false) + { + return; + } + //APP_PRINT_INFO0("hrp_gap_le_check_lps_event_to_app: success"); +} +static void hrp_gap_le_check_lps_wakeup_time_disable(uint16_t len, uint8_t *p_param_list) +{ + APP_PRINT_INFO0("check lps wakeup time Disable"); + os_timer_stop(&g_check_lps_wakeup_timer_handle); +} +void hrp_gap_le_check_lps_wakeup_time_handler(void *pxTimer) +{ + + //tell how long has not been in DLPS mode + static uint32_t wakeCountLast = 0; + static uint32_t totalwakeuptimeLast = 0; + static uint32_t totaltimeLast = 0; + + + uint32_t wakeupCount = 0; //sleep_mode_param.lps_wakeup_count + uint32_t totalwakeuptime = 0; //sleep_mode_param.lps_wakeup_time + uint32_t totaltime = 0; //sleep_mode_param.lps_total_time + + lps_get_wakeup_time(&wakeupCount, &totalwakeuptime, &totaltime); + + if (wakeCountLast == wakeupCount && + totalwakeuptimeLast == totalwakeuptime && + totaltimeLast == totaltime + ) + { + hrp_profile_gap_le_check_lps_wakeup_time_result(GAP_CAUSE_SEND_REQ_FAILED); + APP_PRINT_INFO0("NOT in DLPS"); + } + else + { + APP_PRINT_INFO6("wakeupCount: %d <->%d ,totalwakeuptime:%d <->%d ,totaltime: %d<->%d", + wakeCountLast, wakeupCount, totalwakeuptimeLast, totalwakeuptime, totaltimeLast, totaltime); + //hrp_profile_gap_le_check_lps_wakeup_time_result(GAP_CAUSE_SUCCESS); + APP_PRINT_INFO0(" Success in DLPS "); + } + + wakeCountLast = wakeupCount; + totalwakeuptimeLast = totalwakeuptime; + totaltimeLast = totaltime; + +} +#endif +static void hrp_gap_le_get_conn_info(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t conn_id; + T_GAP_CONN_INFO *p_conn_info; + + conn_id = p_param_list[pos++]; + + if (le_get_conn_info(conn_id, p_conn_info)) + { + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); + } + else + + { + hrp_profile_gap_le_cmd_result(GAP_CAUSE_NON_CONN); + } + + +} +static void hrp_gap_le_get_conn_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint16_t param; + void *p_value; + uint8_t conn_id; + + T_GAP_CAUSE tgap_status; + LE_ARRAY_TO_UINT16(param, p_param_list + pos); pos += 2; + + conn_id = p_param_list[pos++]; + + tgap_status = le_get_conn_param((T_LE_CONN_PARAM_TYPE)param, p_value, conn_id); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +#if F_BT_LE_GAP_CENTRAL_SUPPORT +static void hrp_gap_le_set_host_chann_classif(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t *p_channel_map; + + T_GAP_CAUSE tgap_status; + + p_channel_map = &p_param_list[pos]; + + tgap_status = le_set_host_chann_classif(p_channel_map); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +#endif +static void hrp_gap_le_cfg_local_identity_address(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t addr[6] = {0}; + uint8_t type; + T_GAP_CAUSE tgap_status; + + hrp_profile_fetch_buf(addr, &pos, p_param_list, 6); + type = p_param_list[pos++]; + + tgap_status = le_cfg_local_identity_address(addr, (T_GAP_IDENT_ADDR_TYPE)type); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +static void hrp_gap_le_set_rand_addr(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t random_bd[6] = {0}; + + T_GAP_CAUSE tgap_status; + + hrp_profile_fetch_buf(random_bd, &pos, p_param_list, 6); + + tgap_status = le_set_rand_addr(random_bd); + + hrp_profile_gap_le_cmd_result(tgap_status); +} +static void hrp_gap_le_gen_rand_addr(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t rand_addr_type; + uint8_t random_bd[6] = {0}; + + T_GAP_CAUSE tgap_status; + + rand_addr_type = p_param_list[pos++]; + + //hrp_profile_fetch_buf(random_bd, &pos, p_param_list, 6); + + tgap_status = le_gen_rand_addr((T_GAP_RAND_ADDR_TYPE)rand_addr_type, random_bd); + + hrp_profile_gap_le_event(HRP_GAP_MSG_LE_GEN_RAND_ADDR_RSP, 6, random_bd); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +static void hrp_gap_le_modify_white_list(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + + uint8_t operation; + uint8_t bd_addr[6] = {0}; + uint8_t bd_type; + + T_GAP_CAUSE tgap_status; + + operation = p_param_list[pos++]; + + hrp_profile_fetch_buf(bd_addr, &pos, p_param_list, 6); + bd_type = p_param_list[pos++]; + + tgap_status = le_modify_white_list((T_GAP_WHITE_LIST_OP)operation, bd_addr, + (T_GAP_REMOTE_ADDR_TYPE)bd_type); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +static void hrp_gap_le_get_max_link_num(uint16_t len, uint8_t *p_param_list) +{ + + uint8_t link_num = le_get_max_link_num(); + + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); + +} +//=================bt 5 cmd========================= +#if F_BT_LE_5_0_AE_ADV_SUPPORT +static void hrp_gap_le_ext_adv_get_param(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + + uint32_t param; + void *p_value; + T_GAP_CAUSE tgap_status; + + LE_ARRAY_TO_UINT16(param, p_param_list + pos); pos += 2; + + tgap_status = le_ext_adv_get_param((T_LE_EXT_ADV_PARAM_TYPE)param, p_value); + + hrp_profile_gap_le_cmd_result(tgap_status); + +} +static void hrp_gap_le_ext_adv_set_adv_param(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + T_GAP_CAUSE cause; + uint16_t adv_event_prop = (uint16_t) LE_EXT_ADV_EXTENDED_ADV_CONN_UNDIRECTED; + uint32_t primary_adv_interval_min = 320; + uint32_t primary_adv_interval_max = 320; + uint8_t primary_adv_channel_map = GAP_ADVCHAN_ALL; + uint8_t own_address_type = GAP_LOCAL_ADDR_LE_PUBLIC; + uint8_t peer_address_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t p_peer_address[6] = {0}; + uint8_t filter_policy = 0; + uint8_t tx_power = 10; + uint8_t primary_adv_phy = GAP_PHYS_PRIM_ADV_CODED; + uint8_t secondary_adv_max_skip = 0x00; + uint8_t secondary_adv_phy = GAP_PHYS_CODED; + uint8_t adv_sid = 0; + bool scan_req_notification_enable = false; + + adv_handle = le_ext_adv_create_adv_handle(); + + LE_ARRAY_TO_UINT16(adv_event_prop, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT32(primary_adv_interval_min, p_param_list + pos); pos += 4; + LE_ARRAY_TO_UINT32(primary_adv_interval_max, p_param_list + pos); pos += 4; + LE_ARRAY_TO_UINT8(primary_adv_channel_map, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(own_address_type, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(peer_address_type, p_param_list + pos); pos += 1; + hrp_profile_fetch_buf(p_peer_address, &pos, p_param_list, 6); + LE_ARRAY_TO_UINT8(filter_policy, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(tx_power, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(primary_adv_phy, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(secondary_adv_max_skip, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(secondary_adv_phy, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(adv_sid, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(scan_req_notification_enable, p_param_list + pos); pos += 1; + + + cause = le_ext_adv_set_adv_param(adv_handle, + adv_event_prop, + primary_adv_interval_min, + primary_adv_interval_max, + primary_adv_channel_map, + (T_GAP_LOCAL_ADDR_TYPE)own_address_type, + (T_GAP_REMOTE_ADDR_TYPE)peer_address_type, + p_peer_address, + (T_GAP_ADV_FILTER_POLICY)filter_policy, + tx_power, + (T_GAP_PHYS_PRIM_ADV_TYPE)primary_adv_phy, + secondary_adv_max_skip, + (T_GAP_PHYS_TYPE)secondary_adv_phy, + adv_sid, + scan_req_notification_enable); + + hrp_profile_gap_le_cmd_result(cause); + +} + +static void hrp_gap_le_ext_adv_set_adv_data(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + + uint16_t adv_data_len; + uint8_t *p_adv_data; + T_GAP_CAUSE cause; + LE_ARRAY_TO_UINT16(adv_data_len, p_param_list + pos); pos += 2; + p_adv_data = os_mem_alloc(RAM_TYPE_DATA_ON, adv_data_len); + + hrp_profile_fetch_buf(p_adv_data, &pos, p_param_list, adv_data_len); + cause = le_ext_adv_set_adv_data(adv_handle, adv_data_len, p_adv_data); + APP_PRINT_INFO2("hrp_gap_le_ext_adv_set_adv_data: len:%d pdata= %b", adv_data_len, + TRACE_BINARY(adv_data_len, p_adv_data)); + hrp_profile_gap_le_cmd_result(cause); + os_mem_free(p_adv_data); + +} +static void hrp_gap_le_ext_adv_set_scan_response_data(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + + uint16_t scan_data_len; + uint8_t *p_scan_data; + T_GAP_CAUSE cause; + LE_ARRAY_TO_UINT16(scan_data_len, p_param_list + pos); pos += 2; + p_scan_data = os_mem_alloc(RAM_TYPE_DATA_ON, scan_data_len); + hrp_profile_fetch_buf(p_scan_data, &pos, p_param_list, scan_data_len); + + cause = le_ext_adv_set_scan_response_data(adv_handle, scan_data_len, p_scan_data); + APP_PRINT_INFO2("hrp_gap_le_ext_adv_set_scan_response_data: len:%d pdata= %b", scan_data_len, + TRACE_BINARY(scan_data_len, p_scan_data)); + hrp_profile_gap_le_cmd_result(cause); + os_mem_free(p_scan_data); + +} +static void hrp_gap_le_ext_adv_set_random(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + + uint8_t random_address[6] = {0}; + T_GAP_CAUSE cause; + + hrp_profile_fetch_buf(random_address, &pos, p_param_list, 6); + + cause = le_ext_adv_set_random(adv_handle, random_address); + + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_adv_start_setting(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t update_flags; + T_GAP_CAUSE cause; + + LE_ARRAY_TO_UINT8(update_flags, p_param_list + pos); pos += 1; + cause = le_ext_adv_start_setting(adv_handle, update_flags); + APP_PRINT_TRACE3("hrp_gap_le_ext_adv_start_setting :adv_handle: %d,update_flags:%d, Return Cause=%x ", + adv_handle, update_flags, cause); + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_adv_set_adv_enable_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint16_t duration; + uint8_t max_ext_adv_evt; + uint8_t adv_handle; + T_GAP_CAUSE cause; + + LE_ARRAY_TO_UINT16(duration, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT8(max_ext_adv_evt, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(adv_handle, p_param_list + pos); pos += 1; + cause = le_ext_adv_set_adv_enable_param(adv_handle, duration, max_ext_adv_evt); + + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_adv_enable(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t i; + + T_GAP_CAUSE cause; + uint8_t num_of_sets; + uint8_t adv_handle[4] = {0}; + LE_ARRAY_TO_UINT8(num_of_sets, p_param_list + pos); pos += 1; + for (i = 0; i < num_of_sets; i++) + { + adv_handle[i] = i; + } + + cause = le_ext_adv_enable(num_of_sets, adv_handle); + + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_adv_disable(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t i; + + T_GAP_CAUSE cause; + uint8_t num_of_sets; + uint8_t adv_handle[4] = {0}; + LE_ARRAY_TO_UINT8(num_of_sets, p_param_list + pos); pos += 1; + for (i = 0; i < num_of_sets; i++) + { + adv_handle[i] = i; + } + + cause = le_ext_adv_disable(num_of_sets, adv_handle); + + hrp_profile_gap_le_cmd_result(cause); +} +static void hrp_gap_le_ext_adv_clear_set(uint16_t len, uint8_t *p_param_list) +{ + + T_GAP_CAUSE cause; + + cause = le_ext_adv_clear_set(); + + hrp_profile_gap_le_cmd_result(cause); +} +static void hrp_gap_le_ext_adv_remove_set(uint16_t len, uint8_t *p_param_list) +{ + //uint8_t adv_handle = 0; + //uint16_t pos = 0; + T_GAP_CAUSE cause; + //LE_ARRAY_TO_UINT8(adv_handle, p_param_list + pos); pos += 1; + cause = le_ext_adv_remove_set(adv_handle); + hrp_profile_gap_le_cmd_result(cause); +} + +#endif + +#if F_BT_LE_5_0_AE_SCAN_SUPPORT +static void hrp_gap_le_ext_scan_set_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t param_type; + uint8_t data_len; + void *p_value; + + LE_ARRAY_TO_UINT16(param_type, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT8(data_len, p_param_list + pos); pos += 1; + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, data_len); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, len); + + cause = le_ext_scan_set_param((T_LE_EXT_SCAN_PARAM_TYPE)param_type, data_len, p_value); + + hrp_profile_gap_le_cmd_result(cause); + os_mem_free(p_value); +} +static void hrp_gap_le_ext_scan_get_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t param_type; + void *p_value; + + LE_ARRAY_TO_UINT16(param_type, p_param_list + pos); pos += 2; + + cause = le_ext_scan_get_param((T_LE_EXT_SCAN_PARAM_TYPE)param_type, p_value); + + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_scan_start(uint16_t len, uint8_t *p_param_list) +{ + T_GAP_CAUSE cause; + cause = le_ext_scan_start(); + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_scan_stop(uint16_t len, uint8_t *p_param_list) +{ + T_GAP_CAUSE cause; + cause = le_ext_scan_stop(); + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_ext_scan_set_phy_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t type; + T_GAP_LE_EXT_SCAN_PARAM *p_param; + + LE_ARRAY_TO_UINT8(type, p_param_list + pos); pos += 1; + p_param = os_mem_alloc(RAM_TYPE_DATA_ON, sizeof(T_GAP_LE_EXT_SCAN_PARAM)); + + hrp_profile_fetch_buf(p_param, &pos, p_param_list, sizeof(T_GAP_LE_EXT_SCAN_PARAM)); + + le_ext_scan_set_phy_param((T_LE_EXT_SCAN_PHY_TYPE)type, p_param); + hrp_profile_gap_le_cmd_result(GAP_CAUSE_SUCCESS); + os_mem_free(p_param); + +} +#endif + + +#if F_BT_LE_4_1_CBC_SUPPORT +static void hrp_gap_le_cbc_set_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t param_type; + uint8_t length; + void *p_value; + + LE_ARRAY_TO_UINT16(param_type, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT8(length, p_param_list + pos); pos += 1; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + cause = le_cbc_set_param((T_LE_CBC_PARAM_TYPE)param_type, length, p_value); + + hrp_profile_gap_le_cmd_result(cause); + os_mem_free(p_value); + +} + +static void hrp_gap_le_cbc_get_chann_param(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t param_type; + uint16_t cid; + uint16_t p_value; + + LE_ARRAY_TO_UINT16(param_type, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(cid, p_param_list + pos); pos += 2; + + cause = le_cbc_get_chann_param((T_LE_CBC_CHANN_PARAM_TYPE)param_type, &p_value, cid); + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_cbc_create(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint8_t conn_id; + uint16_t le_psm; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(le_psm, p_param_list + pos); pos += 2; + + cause = le_cbc_create(conn_id, le_psm); + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_cbc_disc(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t cid; + LE_ARRAY_TO_UINT16(cid, p_param_list + pos); pos += 2; + + cause = le_cbc_disc(cid); + hrp_profile_gap_le_cmd_result(cause); +} +static void hrp_gap_le_cbc_send_data(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t cid; + uint8_t *p_data; + uint16_t data_len; + + LE_ARRAY_TO_UINT16(cid, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(data_len, p_param_list + pos); pos += 2; + + p_data = os_mem_alloc(RAM_TYPE_DATA_ON, data_len); + + hrp_profile_fetch_buf(p_data, &pos, p_param_list, data_len); + + APP_PRINT_INFO2("hrp_gap_le_cbc_send_data0: len:%d pdata= %b", data_len, + TRACE_BINARY(data_len, p_data + (data_len - 100))); + + cause = le_cbc_send_data(cid, p_data, data_len); + + hrp_profile_gap_le_cmd_result(cause); + os_mem_free(p_data); +} + +static void hrp_gap_le_cbc_reg_psm(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t le_psm; + uint8_t action; + + LE_ARRAY_TO_UINT16(le_psm, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT8(action, p_param_list + pos); pos += 1; + + cause = le_cbc_reg_psm(le_psm, action); + hrp_profile_gap_le_cmd_result(cause); +} +static void hrp_gap_le_cbc_set_psm_security(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint16_t le_psm; + bool active; + uint8_t mode; + uint8_t key_size; + + LE_ARRAY_TO_UINT16(le_psm, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT8(active, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(mode, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(key_size, p_param_list + pos); pos += 1; + + cause = le_cbc_set_psm_security(le_psm, active, (T_LE_CBC_SECURITY_MODE) mode, key_size); + hrp_profile_gap_le_cmd_result(cause); +} +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +static void hrp_gap_le_privacy_set_addr_resolution(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + T_GAP_CAUSE cause; + bool enable; + + LE_ARRAY_TO_UINT8(enable, p_param_list + pos); pos += 1; + + cause = privacy_set_addr_resolution(enable); + hrp_profile_gap_le_cmd_result(cause); +} + +static void hrp_gap_le_privacy_read_peer_resolv_addr(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + T_GAP_CAUSE cause = GAP_CAUSE_INVALID_PARAM; + uint8_t idx; + T_LE_KEY_ENTRY *p_entry; + + LE_ARRAY_TO_UINT8(idx, p_param_list + pos); pos += 1; + + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + cause = privacy_read_peer_resolv_addr((T_GAP_REMOTE_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + hrp_profile_gap_le_cmd_result(cause); +} + +static void hrp_gap_le_privacy_read_local_resolv_addr(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t pos = 0; + T_GAP_CAUSE cause = GAP_CAUSE_INVALID_PARAM; + uint8_t idx; + T_LE_KEY_ENTRY *p_entry; + + LE_ARRAY_TO_UINT8(idx, p_param_list + pos); pos += 1; + + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + cause = privacy_read_local_resolv_addr((T_GAP_REMOTE_ADDR_TYPE)p_entry->remote_bd.remote_bd_type, + p_entry->remote_bd.addr); + } + + hrp_profile_gap_le_cmd_result(cause); +} +static void hrp_gap_le_privacy_set_resolv_priv_addr_timeout(uint16_t len, uint8_t *p_param_list) +{ + + uint16_t interval; + T_GAP_CAUSE cause; + + le_privacy_get_param(GAP_PARAM_PRIVACY_TIMEOUT, &interval); + cause = privacy_set_gen_priv_addr_interval(interval); + hrp_profile_gap_le_cmd_result(cause); +} + +static void hrp_gap_le_privacy_modify_resolv_list(uint16_t len, uint8_t *p_param_list) +{ +#if 0 + uint16_t pos = 0; + T_GAP_CAUSE cause; + uint8_t operation; + uint8_t peer_identity_address_type; + uint8_t peer_identity_address[6] = {0}; + + LE_ARRAY_TO_UINT8(operation, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(peer_identity_address_type, p_param_list + pos); pos += 1; + hrp_profile_fetch_buf(peer_identity_address, &pos, p_param_list, 6); + + cause = le_privacy_modify_resolv_list((T_GAP_RESOLV_LIST_OP) operation, + (T_GAP_IDENT_ADDR_TYPE)peer_identity_address_type, peer_identity_address); + hrp_profile_gap_le_cmd_result(cause); +#endif +} +/* +static void hrp_gap_le_privacy_set_mode(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint8_t privacy_mode; + uint8_t idx; + + LE_ARRAY_TO_UINT8(privacy_mode, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(idx, p_param_list + pos); pos += 1; + + cause = le_privacy_set_mode((T_GAP_IDENT_ADDR_TYPE)privacy_table[idx].remote_bd_type, + privacy_table[idx].addr, (T_GAP_PRIVACY_MODE) privacy_mode); + hrp_profile_gap_le_cmd_result(cause); + +} +*/ +static void hrp_gap_le_privacy_set_mode(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint8_t privacy_mode; + uint8_t remote_bd_type; + uint8_t addr[6] = {0}; + + LE_ARRAY_TO_UINT8(privacy_mode, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(remote_bd_type, p_param_list + pos); pos += 1; + hrp_profile_fetch_buf(addr, &pos, p_param_list, 6); + + cause = privacy_set_peer_mode((T_GAP_REMOTE_ADDR_TYPE)remote_bd_type, + addr, privacy_mode); + hrp_profile_gap_le_cmd_result(cause); +} +static void hrp_gap_le_privacy_modify_whitelist(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + + uint8_t op; + uint8_t idx; + T_LE_KEY_ENTRY *p_entry; + + LE_ARRAY_TO_UINT8(op, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(idx, p_param_list + pos); pos += 1; + + if (op == (uint8_t)GAP_WHITE_LIST_OP_CLEAR) + { + cause = le_modify_white_list((T_GAP_WHITE_LIST_OP)op, NULL, GAP_REMOTE_ADDR_LE_PUBLIC); + } + else + { + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + cause = le_modify_white_list((T_GAP_WHITE_LIST_OP)op, p_entry->resolved_remote_bd.addr, + (T_GAP_REMOTE_ADDR_TYPE)p_entry->resolved_remote_bd.remote_bd_type); + } + else + { + cause = GAP_CAUSE_ERROR_UNKNOWN; + } + } + + hrp_profile_gap_le_cmd_result(cause); + +} +static void hrp_gap_le_privacy_adv_start(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + T_GAP_CAUSE cause; + uint8_t idx; + uint8_t adv_direct_type = GAP_REMOTE_ADDR_LE_PUBLIC; + uint8_t adv_direct_addr[GAP_BD_ADDR_LEN] = {0}; + T_LE_KEY_ENTRY *p_entry; + + LE_ARRAY_TO_UINT8(idx, p_param_list + pos); pos += 1; + p_entry = le_find_key_entry_by_idx(idx); + if (p_entry) + { + adv_direct_type = p_entry->resolved_remote_bd.remote_bd_type; + memcpy(adv_direct_addr, p_entry->resolved_remote_bd.addr, 6); + } + + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR_TYPE, sizeof(adv_direct_type), &adv_direct_type); + le_adv_set_param(GAP_PARAM_ADV_DIRECT_ADDR, sizeof(adv_direct_addr), adv_direct_addr); + + cause = le_adv_start(); + hrp_profile_gap_le_cmd_result(cause); + +} +#endif + + +//================================hrp gap le handle req=============================// + +void (*(hrp_profile_handle_gap_le[]))(uint16_t len, uint8_t *p_param_list) = +{ + NULL, + hrp_gap_le_set_gap_param, // 0x01 + hrp_gap_le_get_gap_param, // 0x02 + hrp_gap_le_get_max_link_num, //0x03 + hrp_gap_le_modify_white_list, //0x04 + hrp_gap_le_gen_rand_addr, //0x05 + hrp_gap_le_set_rand_addr, //06 + hrp_gap_le_cfg_local_identity_address, //07 +#if F_BT_LE_GAP_CENTRAL_SUPPORT + hrp_gap_le_set_host_chann_classif, //08 +#else + NULL, //08 +#endif + hrp_gap_le_get_conn_param, //0x09 + hrp_gap_le_get_conn_info, //0x0a + hrp_gap_le_get_conn_addr, //0x0b +#if F_BT_DLPS_EN + hrp_gap_le_set_lps_bootup_active_time, //0c + hrp_gap_le_check_lps_wakeup_time_enable, //0d + hrp_gap_le_check_lps_wakeup_time_disable, //0e +#else + NULL, //0c + NULL, //0d + NULL, //0e +#endif + NULL, //0f + hrp_gap_le_get_active_link_num, //0x10 + hrp_gap_le_get_idle_link_num, //0x11 + hrp_gap_le_disconnect, //12 + hrp_gap_le_read_rssi, //0x13 +#if F_BT_LE_READ_CHANN_MAP + hrp_gap_le_read_chann_map, //0x14 +#else + NULL, //0x14 +#endif +#if F_BT_LE_4_2_DATA_LEN_EXT_SUPPORT + hrp_gap_le_set_data_len, //0x15 +#else + NULL, //0x15 +#endif +#if F_BT_LE_5_0_SET_PHYS_SUPPORT + hrp_gap_le_set_phy, //0x16 +#else + NULL, //0x16 +#endif +#if F_BT_GAP_HANDLE_VENDOR_FEATURE + hrp_gap_le_disable_slave_latency, //0x17 + hrp_gap_le_update_passed_chann_map, //0x18 +#else + NULL, //0x17 + NULL, //0x18 +#endif +#if F_BT_LE_GAP_CENTRAL_SUPPORT + hrp_gap_le_set_conn_param, //0x19 + hrp_gap_le_connect, //0x1A +#else + NULL, //0x19 + NULL, //0x1A +#endif + hrp_gap_le_update_conn_param, //0x1B + NULL, //0x1C + NULL, //0x1D + NULL, //0x1E + NULL, //0x1F + hrp_gap_le_adv_start, //0x20 + hrp_gap_le_adv_stop, //0x21 + hrp_gap_le_adv_update_param, //0x22 +#if F_BT_LE_READ_ADV_TX_POWRE_SUPPORT + hrp_gap_le_adv_read_tx_power, //0x23 +#else + NULL, //0x23 +#endif + NULL, //0x24 + NULL, //0x25 + NULL, //0x26 + NULL, //0x27 + NULL, //0x28 + NULL, //0x29 + NULL, //0x2A + NULL, //0x2B + NULL, //0x2C + NULL, //0x2D + NULL, //0x2E + NULL, //0x2F + hrp_gap_le_scan_start, //0x30 + hrp_gap_le_scan_stop, //0x31 + NULL, //0x32 + NULL, //0x33 + NULL, //0x34 + NULL, //0x35 + NULL, //0x36 + NULL, //0x37 + NULL, //0x38 + NULL, //0x39 + NULL, //0x3A + NULL, //0x3B + NULL, //0x3C + NULL, //0x3D + NULL, //0x3E + NULL, //0x3F + hrp_gap_le_bond_pair, //0x40 + hrp_gap_le_bond_get_display_key, //0x41 + hrp_gap_le_bond_passkey_input_confirm, //0x42 +#if F_BT_LE_SMP_OOB_SUPPORT + hrp_gap_le_bond_oob_input_confirm, //0x43 +#else + NULL, +#endif + hrp_gap_le_bond_just_work_confirm, //0x44 + hrp_gap_le_bond_passkey_display_confirm, //0x45 + hrp_gap_le_bond_user_confirm, //0x46 +#if F_BT_LE_4_2_KEY_PRESS_SUPPORT + hrp_gap_le_bond_keypress_notify, //0x47 +#else + NULL, +#endif + hrp_gap_le_bond_cfg_local_key_distribute, //0x48 +#if F_BT_LE_SMP_SC_OOB_SUPPORT + hrp_gap_le_bond_sc_local_oob_init, //0x49 + hrp_gap_le_bond_sc_peer_oob_init, //0x4A +#else + NULL, + NULL, +#endif + hrp_gap_le_bond_clear_all_keys, //0x4B + hrp_gap_le_bond_delete_by_idx, //0x4C + hrp_gap_le_bond_delete_by_bd, //0x4D + NULL, //0x4E + NULL, //0x4F +#if F_BT_LE_5_0_AE_ADV_SUPPORT + hrp_gap_le_ext_adv_get_param, //0x50 + hrp_gap_le_ext_adv_set_adv_param, //0x51 + hrp_gap_le_ext_adv_set_adv_data, //0x52 + hrp_gap_le_ext_adv_set_scan_response_data, //0x53 + hrp_gap_le_ext_adv_set_random, //0x54 + hrp_gap_le_ext_adv_start_setting, //0x55 + hrp_gap_le_ext_adv_set_adv_enable_param, //0x56 + hrp_gap_le_ext_adv_enable, //0x57 + hrp_gap_le_ext_adv_disable, //0x58 + hrp_gap_le_ext_adv_clear_set, //0x59 + hrp_gap_le_ext_adv_remove_set, //0x5a +#else + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +#endif + NULL, + NULL, + NULL, + NULL, + NULL, //0x5f +#if F_BT_LE_5_0_AE_SCAN_SUPPORT + hrp_gap_le_ext_scan_set_param, //0x60 + hrp_gap_le_ext_scan_get_param, //0x61 + hrp_gap_le_ext_scan_start, //0x62 + hrp_gap_le_ext_scan_stop, //0x63 + hrp_gap_le_ext_scan_set_phy_param, //0x64 +#else + NULL, + NULL, + NULL, + NULL, + NULL, +#endif + NULL, //0x65 + NULL, //0x66 + NULL, //0x67 + NULL, //0x68 + NULL, //0x69 +#if F_BT_LE_4_1_CBC_SUPPORT + hrp_gap_le_cbc_set_param, //0x6a + hrp_gap_le_cbc_get_chann_param, //0x6b + hrp_gap_le_cbc_create, //0x6c + hrp_gap_le_cbc_disc, //0x6d + hrp_gap_le_cbc_send_data,//0x6e + hrp_gap_le_cbc_reg_psm, //0x6f + hrp_gap_le_cbc_set_psm_security, //0x70 +#else + NULL, //0x6a + NULL,//0x6b + NULL,//0x6c + NULL, //0x6d + NULL,//0x6e + NULL,//0x6f + NULL, //0x70 +#endif + NULL,//0x71 + NULL, //0x72 + NULL, //0x73 +#if F_BT_LE_PRIVACY_SUPPORT + hrp_gap_le_privacy_set_addr_resolution, //0x74 + hrp_gap_le_privacy_read_peer_resolv_addr, //0x75 + hrp_gap_le_privacy_read_local_resolv_addr, //0x76 + hrp_gap_le_privacy_set_resolv_priv_addr_timeout, //0x77 + hrp_gap_le_privacy_modify_resolv_list, //0x78 + hrp_gap_le_privacy_set_mode, //0x79 + hrp_gap_le_privacy_modify_whitelist, //0x7a + hrp_gap_le_privacy_adv_start, //0x7b +#else + NULL, //0x74 + NULL, //0x75 + NULL, //0x76 + NULL, //0x77 + NULL, //0x78 + NULL, //0x79 + NULL, //0x7a + NULL, //0x7b +#endif + + +}; + + + + + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_gap_le.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_gap_le.h new file mode 100644 index 00000000..45474493 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_gap_le.h @@ -0,0 +1,198 @@ +#ifndef _HRP_GAP_LE_H_ +#define _HRP_GAP_LE_H_ + + +#include "gap_le.h" +#include "gap_bond_le.h" +#include +#include + +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include "gaps_client.h" +#include +#endif +#include +#if F_BT_LE_PRIVACY_SUPPORT +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define HRP_MAX_LE_LINKS 4 +#define HRP_MAX_EVE_PARAM_LEN 100 + + +typedef enum +{ + HRP_GAP_MSG_LE_RESULT = 0x00, + HRP_GAP_MSG_LE_MODIFY_WHITE_LIST = 0x01, + HRP_GAP_MSG_LE_SET_RAND_ADDR = 0x02, + HRP_GAP_MSG_LE_SET_HOST_CHANN_CLASSIF = 0x03, + HRP_GAP_MSG_LE_VENDOR_ONE_SHOT_ADV = 0x04, + + HRP_GAP_MSG_LE_READ_RSSI = 0x10, + HRP_GAP_MSG_LE_READ_CHANN_MAP, + HRP_GAP_MSG_LE_DISABLE_SLAVE_LATENCY, + HRP_GAP_MSG_LE_SET_DATA_LEN, + HRP_GAP_MSG_LE_DATA_LEN_CHANGE_INFO, + HRP_GAP_MSG_LE_CONN_UPDATE_IND, + HRP_GAP_MSG_LE_CREATE_CONN_IND, + HRP_GAP_MSG_LE_PHY_UPDATE_INFO, + HRP_GAP_MSG_LE_UPDATE_PASSED_CHANN_MAP, + + HRP_GAP_MSG_LE_REMOTE_FEATS_INFO, + + + + HRP_GAP_MSG_LE_BOND_MODIFY_INFO = 0x20, + HRP_GAP_MSG_LE_KEYPRESS_NOTIFY, + HRP_GAP_MSG_LE_KEYPRESS_NOTIFY_INFO, + HRP_GAP_MSG_LE_GATT_SIGNED_STATUS_INFO, + + + HRP_GAP_MSG_LE_SCAN_INFO = 0x30, + HRP_GAP_MSG_LE_DIRECT_ADV_INFO, + + HRP_GAP_MSG_LE_ADV_UPDATE_PARAM = 0x40, + HRP_GAP_MSG_LE_ADV_READ_TX_POWER, + + HRP_GAP_MSG_LE_EXT_ADV_REPORT_INFO = 0x50, + + HRP_GAP_MSG_LE_EXT_ADV_START_SETTING = 0x60, + HRP_GAP_MSG_LE_EXT_ADV_REMOVE_SET, + HRP_GAP_MSG_LE_EXT_ADV_CLEAR_SET, + HRP_GAP_MSG_LE_EXT_ADV_ENABLE, + HRP_GAP_MSG_LE_EXT_ADV_DISABLE, + HRP_GAP_MSG_LE_SCAN_REQ_RECEIVED_INFO, + HRP_GAP_MSG_LE_EXT_ADV_STATE_CHANGE, + + + HRP_GAP_MSG_LE_PRIVACY_RESOLUTION_STATUS_INFO = 0x70, + HRP_GAP_MSG_LE_PRIVACY_SET_RESOLV_PRIV_ADDR_TIMEOUT, //0x71 + HRP_GAP_MSG_LE_PRIVACY_MODIFY_RESOLV_LIST, //0x72 + + HRP_GAP_MSG_LE_PRIVACY_READ_PEER_RESOLV_ADDR, //0x73 + HRP_GAP_MSG_LE_PRIVACY_READ_LOCAL_RESOLV_ADDR, //0x74 + HRP_GAP_MSG_LE_PRIVACY_SET_MODE, //0x75 + + + + HRP_GAP_MSG_LE_VENDOR_ADV_3_DATA_ENABLE = 0xA0, + HRP_GAP_MSG_LE_VENDOR_ADV_3_DATA_SET, //0xA1 + HRP_GAP_MSG_LE_SET_LPS_BOOTUP_ACTIVE_TIME, //0xA2 + HRP_GAP_MSG_LE_CHECK_LPS_WAKEUP_TIME_RSP, //0xA3 + + + HRP_GAP_MSG_LE_DEV_STATE_CHANGE = 0xB1, + HRP_GAP_MSG_LE_CONN_STATE_CHANGE, + HRP_GAP_MSG_LE_CONN_PARAM_UPDATE, + HRP_GAP_MSG_LE_CONN_MTU_INFO, + HRP_GAP_MSG_LE_AUTHEN_STATE_CHANGE, + HRP_GAP_MSG_LE_BOND_PASSKEY_DISPLAY, + HRP_GAP_MSG_LE_BOND_PASSKEY_INPUT, + + HRP_GAP_MSG_LE_BOND_OOB_INPUT, + HRP_GAP_MSG_LE_BOND_USER_CONFIRMATION, + HRP_GAP_MSG_LE_BOND_JUST_WORK, + + HRP_GAP_MSG_LE_GEN_RAND_ADDR_RSP = 0xC0, + + HRP_GAP_MSG_LE_CBC_CHANN_STATE = 0xC1, + HRP_GAP_MSG_LE_CBC_REG_PSM = 0xC2, + HRP_GAP_MSG_LE_CBC_SET_PSM_SECURITY = 0xC3, + HRP_GAP_MSG_LE_CBC_SEND_DATA = 0xC4, + HRP_GAP_MSG_LE_CBC_RECEIVE_DATA = 0xC5, + HRP_GAP_MSG_LE_CBC_MTU_INFO = 0xC6, + + +} T_PROFILE_GAP_LE_MSG_INDEX; + + +typedef enum +{ + HRP_PROFILE_EVT_GENERAL_RESULT = 0x00, + + HRP_PROFILE_EVT_SRV_REG_COMPLETE = 0x01, + + HRP_PROFILE_EVT_SRV_SEND_DATA_COMPLETE, + + HRP_PROFILE_EVT_CLIENT_DISC_STATE = 0x10, + + HRP_PROFILE_EVT_CLIENT_DISC_RESULT, + + +} T_PROFILE_LE_GENERAL_MSG_INDEX; + + +typedef enum +{ + NONE = 0x0000, +//server mask + SIMPLE_BLE_SERVICE = 0x01, + + SIMPLE_BLE_ADD_SERVICE = 0x10, + +//client mask + SIMPLE_BLE_CLIENT = 0x30, + + +} T_HRP_PROFILE_LE_MASK; + +#if F_BT_LE_GATT_CLIENT_SUPPORT +extern T_CLIENT_ID gaps_client_id; /**< Simple ble service client id*/ +extern T_CLIENT_ID simple_ble_client_id; /**< gap service client id*/ +#endif +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ + +T_APP_RESULT hrp_profile_callback(T_SERVER_ID service_id, void *p_data); +#if F_BT_LE_GATT_CLIENT_SUPPORT +T_APP_RESULT hrp_client_callback(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data); + +extern void hrp_profile_client_gaps_callback(T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data); +extern void hrp_profile_server_simp_ble_callback(TSIMP_CALLBACK_DATA *p_simp_cb_data); +extern void hrp_profile_client_simp_ble_callback(T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data); +#endif +T_GAP_CAUSE hrp_gap_le_set_param(uint8_t type, uint8_t len, void *p_value); + +void hrp_gap_le_init(uint16_t le_profile_sever_mask, uint16_t le_profile_client_mask); + +void hrp_gap_le_server_init(uint16_t le_profile_sever_mask); + +void hrp_gap_le_client_init(uint16_t le_profile_client_mask); + +void hrp_gap_le_handle_io_msg(T_IO_MSG io_msg); + +void hrp_app_handle_gap_le_msg(T_IO_MSG *p_io_msg); + +void hrp_app_handle_dev_state_evt(T_GAP_DEV_STATE new_state); +void hrp_gap_le_check_lps_wakeup_time_handler(void *pxTimer); +void hrp_gap_le_check_lps_event_to_app(void *pxTimer); + +T_GAP_CAUSE hrp_le_set_gap_param(uint16_t type, uint8_t len, void *p_value); +T_GAP_CAUSE hrp_le_set_bond_param(uint16_t type, uint8_t len, void *p_value); +T_GAP_CAUSE hrp_le_set_scan_param(uint16_t type, uint8_t len, void *p_value); +T_GAP_CAUSE hrp_le_set_adv_param(uint16_t type, uint8_t len, void *p_value); +T_GAP_CAUSE hrp_le_set_privacy_param(uint16_t type, uint8_t len, void *p_value); +/* hrp_profile_system_api.c */ +void hrp_profile_handle_initCmplete(uint8_t initiated_mode); + +#if F_BT_LE_4_1_CBC_SUPPORT +T_APP_RESULT hrp_credit_based_conn_callback(uint8_t cbc_type, void *p_cbc_data); +#endif + +#if F_BT_LE_PRIVACY_SUPPORT +void app_privacy_callback(T_PRIVACY_CB_TYPE type, T_PRIVACY_CB_DATA cb_data); +#endif + +extern T_GAP_CAUSE le_adv_read_tx_power(void); +extern T_GAP_CAUSE le_adv_update_param(void); +extern T_GAP_CAUSE le_adv_stop(void); +extern T_GAP_CAUSE le_adv_start(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _HRP_GAP_LE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_entry.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_entry.c new file mode 100644 index 00000000..679ae567 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_entry.c @@ -0,0 +1,115 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file hrp_profile_entry.c +* @brief +* @details none. +* @author Thomas +* @date 2017-11-8 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include +#include + +#if F_BT_DLPS_EN +#include +#endif + +extern void hrp_profile_system_send_cmd_ack(uint8_t cmd_group, uint16_t cmd_index, + HRP_PROFILE_SYSTEM_CMD_STATUS status); + +void hrp_profile_handle_req(uint8_t cmd_group, uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + if ((system_status == HRP_STATUS_ACTIVE) && + (active_module != HRP_MODULE_PROFILE)) + { + APP_PRINT_ERROR2("wrong module status: system_status= %d active_module= %d", + system_status, active_module); + return ; + } + + APP_PRINT_TRACE3("down cmd group: cmdGroup= %x cmd_index= %d , posLength = %d", + cmd_group, cmd_index, param_list_len); +#if F_BT_DLPS_EN + if (hrp_dlps_status == HRP_DLPS_STATUS_ACTIVED) + { + if (!((cmd_group == HRP_PROFILE_CMD_GROUP_EVENT_SYS) && (cmd_index == PROFILE_SYSTEM_EVENT_ACK))) + { + hrp_profile_system_send_cmd_ack(cmd_group, cmd_index, HRP_PROFILE_SYSTEM_COMMAND_COMPLETE); + } + hrp_dlps_allow_enter(true); + APP_PRINT_INFO0("hrp_profile_handle_req allow enter dlps"); + } + +#endif + + switch (cmd_group) + { + case HRP_PROFILE_CMD_GROUP_SYSTEM: + if (hrp_profile_handle_system[cmd_index] != NULL) + { + hrp_profile_handle_system[cmd_index](param_list_len, p_param_list); + } + break; + + + + case HRP_PROFILE_CMD_GROUP_LE: + if (hrp_profile_handle_gap_le[cmd_index] != NULL) + { + hrp_profile_handle_gap_le[cmd_index](param_list_len, p_param_list); + } + break; + case HRP_PROFILE_CMD_GROUP_SIMP_BLE: + if (hrp_profile_handle_simp_ble[cmd_index] != NULL) + { + hrp_profile_handle_simp_ble[cmd_index](param_list_len, p_param_list); + } + break; + case HRP_PROFILE_CMD_GROUP_GAPS_CLIENT: + if (hrp_profile_handle_gaps_client[cmd_index] != NULL) + { + hrp_profile_handle_gaps_client[cmd_index](param_list_len, p_param_list); + } + break; + default: + APP_PRINT_INFO2("unknown cmd group: cmd_group= %d cmd_index= %d", + cmd_group, cmd_index); + break; + } +} + +//========================utils=============================// +void hrp_profile_commit_buf(uint8_t *destbuf, int *pos, void *srcbuf, int length) +{ + int position = *pos; + memcpy(destbuf + position, srcbuf, length); + *pos = position + length; +} + +void hrp_profile_fetch_buf(void *destbuf, uint16_t *pos, void *srcbuf, int length) +{ + int position = *pos; + memcpy(destbuf, (uint8_t *)srcbuf + position, length); + *pos = position + length; +} + +void hrp_profile_evet(uint8_t cmd_group, uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + HRP_MODULE_ID module_id = HRP_MODULE_PROFILE; + + APP_PRINT_INFO4("hrp_profile_evet : upperstream events: cmdGroup= %x cmdIndex= %d , posLength = %d , pData= %b", + cmd_group, cmd_index, param_list_len, TRACE_BINARY(param_list_len, p_param_list)); + hrp_handle_upperstream_events(module_id, cmd_group, + cmd_index, param_list_len, p_param_list); +} + + + + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_entry.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_entry.h new file mode 100644 index 00000000..0b858e73 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_entry.h @@ -0,0 +1,87 @@ +#ifndef _HRP_PROFILE_ENTRY_H_ +#define _HRP_PROFILE_ENTRY_H_ + +#include +#include +#include +//#include + +#define MAX_PROFILE_CMD_INDEX 10 +typedef enum +{ + HRP_PROFILE_CMD_GROUP_SYSTEM = 0x0f, + HRP_PROFILE_CMD_GROUP_GAP = 1, + HRP_PROFILE_CMD_GROUP_A2DP = 2, + HRP_PROFILE_CMD_GROUP_AVRCP = 3, + HRP_PROFILE_CMD_GROUP_HFP = 4, + HRP_PROFILE_CMD_GROUP_SPP = 5, + + HRP_PROFILE_CMD_GROUP_GAP_LEGACY = 0x10, + HRP_PROFILE_CMD_GROUP_EVENT_GAP_LEGACY = 0x11, + + HRP_PROFILE_CMD_GROUP_LE = 0x21, + + HRP_PROFILE_CMD_GROUP_EVENT_SYS = 0x4f, + HRP_PROFILE_CMD_GROUP_EVENT_GAP = 0x41, + HRP_PROFILE_CMD_GROUP_EVENT_A2DP = 0x42, + HRP_PROFILE_CMD_GROUP_EVENT_AVRCP = 0x43, + HRP_PROFILE_CMD_GROUP_EVENT_HFP = 0x44, + HRP_PROFILE_CMD_GROUP_EVENT_SPP = 0X45, + + HRP_PROFILE_CMD_GROUP_EVENT_LE = 0X61, + + HRP_PROFILE_CMD_GROUP_EVENT_GENERAL_ID = 0x65, + + HRP_PROFILE_CMD_GROUP_SIMP_BLE = 0X70, + HRP_PROFILE_CMD_GROUP_GAPS_CLIENT = 0X71, + + HRP_PROFILE_CMD_GROUP_EVENT_SIMP_BLE = 0X80, + HRP_PROFILE_CMD_GROUP_EVENT_GAPS_CLIENT = 0X81, + +} HRP_PROFILE_CMD_GROUP; + +typedef enum +{ + HRP_PROFILE_SYSTEM_COMMAND_COMPLETE = 0, + HRP_PROFILE_SYSTEM_COMMAND_DISALLOW = 1, + HRP_PROFILE_SYSTEM_UNKNOWN_COMMAND = 2, +} HRP_PROFILE_SYSTEM_CMD_STATUS; + +typedef enum +{ + PROFILE_SYSTEM_CMD_RESULT = 1, + PROFILE_SYSTEM_RESET_COMPLETE = 2, + PROFILE_SYSTEM_INIT_COMPLETE = 3, + PROFILE_SYSTEM_SET_GAP_PARAM_RSP = 4, + PROFILE_SYSTEM_SET_PAIRABLE_MODE_RSP = 5, + PROFILE_SYSTEM_ENABLE_DLPS_RSP = 6, + + PROFILE_SYSTEM_EVENT_ACK = 7, + PROFILE_SYSTEM_CMD_ACK = 8, + +} PROFILE_SYSTEM_CMD_ENTRY; + +void hrp_profile_handle_req(uint8_t cmd_group, uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list); + +extern void (*(hrp_profile_handle_system[]))(uint16_t len, uint8_t *p_param_list) ; +extern void (*(hrp_profile_handle_gap[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_profile_handle_a2dp[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_profile_handle_avrcp[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_profile_handle_hfp[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_profile_handle_spp[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_gap_legacy_cmd_table[]))(uint16_t len, uint8_t *p_param_list); + +extern void (*(hrp_profile_handle_gap_le[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_profile_handle_simp_ble[]))(uint16_t len, uint8_t *p_param_list); +extern void (*(hrp_profile_handle_gaps_client[]))(uint16_t len, uint8_t *p_param_list); + + +/*--------------------------------------------------------------------------*/ +//============utils=====================// +void hrp_profile_evet(uint8_t cmd_group, uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list); +void hrp_profile_commit_buf(uint8_t *destbuf, int *pos, void *srcbuf, int length); +void hrp_profile_fetch_buf(void *destbuf, uint16_t *pos, void *srcbuf, int length); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_le_simple_ble.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_le_simple_ble.c new file mode 100644 index 00000000..2ba1a7be --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_le_simple_ble.c @@ -0,0 +1,1217 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file hrp_profile_simple_ble_service.c +* @brief +* @details none. +* @author +* @date 2018-1-26 +* @version v0.1 +* ********************************************************************************************************* +*/ +#include "trace_app.h" +#include +#include +#include +#include +#if F_BT_LE_GATT_CLIENT_SUPPORT +#include +#include "gaps_client.h" +#endif + +extern T_SERVER_ID simp_srv_id; /**< Simple ble service id*/ +extern T_APP_RESULT hrp_profile_callback(T_SERVER_ID service_id, void *p_data); +//==============================SimpBle Event======================// +static void hrp_profile_simp_ble_evet(uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + uint8_t cmd_group = HRP_PROFILE_CMD_GROUP_EVENT_SIMP_BLE; + hrp_profile_evet(cmd_group, cmd_index, param_list_len, p_param_list); +} + + +static void hrp_profile_simp_ble_cmd_result(bool result) +{ + uint8_t Cause; + if (result == true) + { + Cause = 0; + } + else + { + Cause = 1; + } + hrp_profile_simp_ble_evet(HRP_SIMP_BLE_CMD_RESULT, sizeof(uint8_t), (uint8_t *)&Cause); +} + + +//==============================Gaps Client Event======================// +#if F_BT_LE_GATT_CLIENT_SUPPORT +static void hrp_profile_gaps_cleint_evet(uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + uint8_t cmd_group = HRP_PROFILE_CMD_GROUP_EVENT_GAPS_CLIENT; + hrp_profile_evet(cmd_group, cmd_index, param_list_len, p_param_list); +} + + +static void hrp_profile_gaps_client_cmd_result(bool result) +{ + uint8_t Cause; + if (result == true) + { + Cause = 0; + } + else + { + Cause = 1; + } + hrp_profile_gaps_cleint_evet(HRP_GAPS_CLIENT_CMD_RESULT, sizeof(uint8_t), (uint8_t *)&Cause); +} +#endif + + +/*********************************handle simp ble server event function**********************************/ +void hrp_profile_handle_service_callback_type_indication_notification(uint8_t conn_id, + T_SERVICE_CALLBACK_TYPE msg_type, uint8_t notification_indification_index) +{ + + uint8_t Param[3]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, conn_id); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, msg_type); pos += 1; + + LE_UINT8_TO_ARRAY(Param + pos, notification_indification_index); pos += 1; + + hrp_profile_simp_ble_evet(HRP_SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION, pos, Param); +} +void hrp_profile_handle_service_callback_type_read_char_value(uint8_t conn_id, + T_SERVICE_CALLBACK_TYPE msg_type, uint8_t read_value_index) +{ + + uint8_t Param[3]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, conn_id); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, msg_type); pos += 1; + + LE_UINT8_TO_ARRAY(Param + pos, read_value_index); pos += 1; + + hrp_profile_simp_ble_evet(HRP_SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE, pos, Param); +} +void hrp_profile_handle_service_callback_type_write_char_value(uint8_t conn_id, + T_SERVICE_CALLBACK_TYPE msg_type, + uint8_t opcode, + T_WRITE_TYPE write_type, + uint16_t len) +{ + uint8_t Param[6]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, conn_id); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, msg_type); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, opcode); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, write_type); pos += 1; + LE_UINT16_TO_ARRAY(Param + pos, len); pos += 2; + + hrp_profile_simp_ble_evet(HRP_SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE, pos, Param); +} + +// *************************************************************************************************** +void hrp_profile_server_simp_ble_callback(TSIMP_CALLBACK_DATA *p_simp_cb_data) +{ + switch (p_simp_cb_data->msg_type) + { + case SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION: + { + switch (p_simp_cb_data->msg_data.notification_indification_index) + { + case SIMP_NOTIFY_INDICATE_V3_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_ENABLE"); + } + break; + + case SIMP_NOTIFY_INDICATE_V3_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V3_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V4_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V4_DISABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_NOTIFY_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_INDICATE_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_NOTIFY_INDICATE_ENABLE"); + } + break; + case SIMP_NOTIFY_INDICATE_V8_DISABLE: + { + APP_PRINT_INFO0("SIMP_NOTIFY_INDICATE_V8_DISABLE"); + } + break; + } + hrp_profile_handle_service_callback_type_indication_notification(p_simp_cb_data->conn_id, + p_simp_cb_data->msg_type, p_simp_cb_data->msg_data.notification_indification_index); + + } + break; + + case SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE: + { + if (p_simp_cb_data->msg_data.read_value_index == SIMP_READ_V1) + { + uint8_t value = 0x88; + APP_PRINT_INFO1("SIMP_READ_V1: 0x%x", value); + //simp_ble_service_set_parameter(SIMPLE_BLE_SERVICE_PARAM_V1_READ_CHAR_VAL, 1, &value); + } + hrp_profile_handle_service_callback_type_read_char_value(p_simp_cb_data->conn_id, + p_simp_cb_data->msg_type, p_simp_cb_data->msg_data.read_value_index); + + } + break; + case SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE: + { + switch (p_simp_cb_data->msg_data.write.opcode) + { + case SIMP_WRITE_V2: + { + APP_PRINT_INFO2("SIMP_WRITE_V2: write type %d, len %d", p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + + case SIMP_WRITE_V6: + { + APP_PRINT_INFO1("SIMP_WRITE_V6: len = 0x%x", p_simp_cb_data->msg_data.write.len); + } + break; + + default: + break; + } + hrp_profile_handle_service_callback_type_write_char_value(p_simp_cb_data->conn_id, + p_simp_cb_data->msg_type, + p_simp_cb_data->msg_data.write.opcode, + p_simp_cb_data->msg_data.write.write_type, + p_simp_cb_data->msg_data.write.len); + } + break; + + default: + break; + } + +} +/*********************************handle simp ble client event function**********************************/ + + +void hrp_profile_handle_simp_ble_common_event(uint16_t cmd_index, uint16_t cause) +{ + uint8_t Param[2]; + int pos = 0; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + + hrp_profile_simp_ble_evet(cmd_index, pos, Param); + +} + +void hrp_profile_handle_simp_ble_notif_ind_common_event(uint16_t cmd_index, uint16_t value_size, + uint8_t *p_value) +{ + uint8_t Param[500] = {0}; + int pos = 0; + LE_UINT16_TO_ARRAY(Param + pos, value_size); pos += 2; + hrp_profile_commit_buf(Param, &pos, p_value, value_size); + + hrp_profile_simp_ble_evet(cmd_index, pos, Param); + +} +#if F_BT_LE_GATT_CLIENT_SUPPORT +void hrp_profile_handle_simp_client_cb_type_disc_state(T_SIMP_DISC_STATE disc_state) +{ + + uint8_t Param[1]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, disc_state); pos += 1; + + hrp_profile_simp_ble_evet(HRP_SIMP_CLIENT_CB_TYPE_DISC_STATE, pos, Param); +} + +void hrp_profile_handle_simp_read_v1_read(uint16_t cause, uint16_t value_size, uint8_t *p_value) +{ + + uint8_t Param[100] = {0}; + int pos = 0; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + LE_UINT16_TO_ARRAY(Param + pos, value_size); pos += 2; + hrp_profile_commit_buf(Param, &pos, p_value, value_size); + + hrp_profile_simp_ble_evet(HRP_SIMP_READ_V1_READ, pos, Param); +} +void hrp_profile_handle_simp_read_v3_notify_cccd(bool v3_notify_cccd, uint16_t cause) +{ + uint8_t Param[3]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, v3_notify_cccd); pos += 1; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + + hrp_profile_simp_ble_evet(HRP_SIMP_READ_V3_NOTIFY_CCCD, pos, Param); +} + +void hrp_profile_handle_simp_read_v4_indicate_cccd(bool v4_indicate_cccd, uint16_t cause) +{ + uint8_t Param[3]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, v4_indicate_cccd); pos += 1; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + + hrp_profile_simp_ble_evet(HRP_SIMP_READ_V4_INDICATE_CCCD, pos, Param); +} + +void hrp_profile_handle_simp_read_v8_cccd(uint16_t v8_notify_ind_cccd, uint16_t cause) +{ + uint8_t Param[4]; + int pos = 0; + LE_UINT16_TO_ARRAY(Param + pos, v8_notify_ind_cccd); pos += 2; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + + hrp_profile_simp_ble_evet(HRP_SIMP_READ_V8_CCCD, pos, Param); +} + +void hrp_profile_handle_simp_read_v7_read_long(uint16_t value_size, uint8_t *p_value, + uint16_t cause) +{ + + uint8_t Param[500] = {0}; + int pos = 0; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + LE_UINT16_TO_ARRAY(Param + pos, value_size); pos += 2; + hrp_profile_commit_buf(Param, &pos, p_value, value_size); + + hrp_profile_simp_ble_evet(HRP_SIMP_READ_V7_READ_LONG, pos, Param); +} + + +void hrp_profile_simp_ble_get_hdl_cache_rsp(uint8_t srv_start, uint8_t cache_len, + uint16_t *hdl_cache) +{ + uint8_t Param[2 + sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, srv_start); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, cache_len); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN); pos += 1; + + hrp_profile_commit_buf(Param, &pos, hdl_cache, sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN); + + hrp_profile_simp_ble_evet(HRP_SIMP_GET_HDL_CACHE_RSP, pos, Param); + +} + + + +void hrp_profile_client_simp_ble_callback(T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data) +{ + uint16_t value_size; + uint8_t *p_value = NULL; + switch (p_simp_client_cb_data->cb_type) + { + case SIMP_CLIENT_CB_TYPE_DISC_STATE: + { + + switch (p_simp_client_cb_data->cb_content.disc_state) + { + case DISC_SIMP_DONE: + APP_PRINT_INFO0("app_client_callback: discover simp procedure done."); + break; + case DISC_SIMP_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("app_client_callback: discover simp request failed."); + break; + default: + break; + } + hrp_profile_handle_simp_client_cb_type_disc_state(p_simp_client_cb_data->cb_content.disc_state); + + } + break; + case SIMP_CLIENT_CB_TYPE_READ_RESULT: + switch (p_simp_client_cb_data->cb_content.read_result.type) + { + case SIMP_READ_V1_READ: + { + + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_simp_client_cb_data->cb_content.read_result.data.v1_read.value_size; + + p_value = p_simp_client_cb_data->cb_content.read_result.data.v1_read.p_value; + APP_PRINT_INFO2("SIMP_READ_V1_READ: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V1_READ: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + + hrp_profile_handle_simp_read_v1_read(p_simp_client_cb_data->cb_content.read_result.cause, + value_size, p_value); + } + + break; + case SIMP_READ_V3_NOTIFY_CCCD: + { + + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V3_NOTIFY_CCCD: notify %d", + p_simp_client_cb_data->cb_content.read_result.data.v3_notify_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V3_NOTIFY_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + + hrp_profile_handle_simp_read_v3_notify_cccd( + p_simp_client_cb_data->cb_content.read_result.data.v3_notify_cccd, + p_simp_client_cb_data->cb_content.read_result.cause); + } + + break; + case SIMP_READ_V4_INDICATE_CCCD: + { + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V4_INDICATE_CCCD: indicate %d", + p_simp_client_cb_data->cb_content.read_result.data.v4_indicate_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V4_INDICATE_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + hrp_profile_handle_simp_read_v4_indicate_cccd( + p_simp_client_cb_data->cb_content.read_result.data.v4_indicate_cccd, + p_simp_client_cb_data->cb_content.read_result.cause); + } + + break; + + case SIMP_READ_V8_CCCD: + { + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("SIMP_READ_V8_CCCD: cccd 0x%x", + p_simp_client_cb_data->cb_content.read_result.data.v8_notify_ind_cccd); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V8_CCCD: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + hrp_profile_handle_simp_read_v8_cccd( + p_simp_client_cb_data->cb_content.read_result.data.v8_notify_ind_cccd, + p_simp_client_cb_data->cb_content.read_result.cause); + } + + break; + + case SIMP_READ_V7_READ_LONG: + { + if (p_simp_client_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + value_size = p_simp_client_cb_data->cb_content.read_result.data.v7_read.value_size; + p_value = p_simp_client_cb_data->cb_content.read_result.data.v7_read.p_value; + APP_PRINT_INFO2("SIMP_READ_V7_READ_LONG: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + } + else + { + APP_PRINT_ERROR1("SIMP_READ_V7_READ_LONG: failed cause 0x%x", + p_simp_client_cb_data->cb_content.read_result.cause); + } + + hrp_profile_handle_simp_read_v7_read_long(value_size, p_value, + p_simp_client_cb_data->cb_content.read_result.cause); + } + + break; + + default: + break; + } + break; + + case SIMP_CLIENT_CB_TYPE_WRITE_RESULT: + switch (p_simp_client_cb_data->cb_content.write_result.type) + { + case SIMP_WRITE_V2_WRITE: + { + APP_PRINT_INFO1("SIMP_WRITE_V2_WRITE: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + hrp_profile_handle_simp_ble_common_event(HRP_SIMP_WRITE_V2_WRITE, + p_simp_client_cb_data->cb_content.write_result.cause); + + } + + break; + case SIMP_WRITE_V3_NOTIFY_CCCD: + { + APP_PRINT_INFO1("SIMP_WRITE_V3_NOTIFY_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + hrp_profile_handle_simp_ble_common_event(HRP_SIMP_WRITE_V3_NOTIFY_CCCD, + p_simp_client_cb_data->cb_content.write_result.cause); + } + + break; + case SIMP_WRITE_V4_INDICATE_CCCD: + { + APP_PRINT_INFO1("SIMP_WRITE_V4_INDICATE_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + hrp_profile_handle_simp_ble_common_event(HRP_SIMP_WRITE_V4_INDICATE_CCCD, + p_simp_client_cb_data->cb_content.write_result.cause); + } + + break; + case SIMP_WRITE_V6_WRITE_LONG: + { + APP_PRINT_INFO1("SIMP_WRITE_V6_WRITE_LONG: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + hrp_profile_handle_simp_ble_common_event(HRP_SIMP_WRITE_V6_WRITE_LONG, + p_simp_client_cb_data->cb_content.write_result.cause); + + } + + break; + case SIMP_WRITE_V8_CCCD: + { + APP_PRINT_INFO1("SIMP_WRITE_V8_CCCD: write result 0x%x", + p_simp_client_cb_data->cb_content.write_result.cause); + + hrp_profile_handle_simp_ble_common_event(HRP_SIMP_WRITE_V8_CCCD, + p_simp_client_cb_data->cb_content.write_result.cause); + + } + + break; + default: + break; + } + break; + + case SIMP_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + value_size = p_simp_client_cb_data->cb_content.notif_ind_data.data.value_size; + p_value = p_simp_client_cb_data->cb_content.notif_ind_data.data.p_value; + + switch (p_simp_client_cb_data->cb_content.notif_ind_data.type) + { + case SIMP_V3_NOTIFY: + { + APP_PRINT_INFO2("SIMP_V3_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + /* if (gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + gap_v3_notif_test.v3_rx_num++; + } + */ + hrp_profile_handle_simp_ble_notif_ind_common_event(HRP_SIMP_V3_NOTIFY, value_size, p_value); + } + + break; + case SIMP_V4_INDICATE: + { + APP_PRINT_INFO2("SIMP_V4_INDICATE: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + hrp_profile_handle_simp_ble_notif_ind_common_event(HRP_SIMP_V4_INDICATE, value_size, p_value); + } + + break; + case SIMP_V8_INDICATE: + { + APP_PRINT_INFO2("SIMP_V8_INDICATE: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + hrp_profile_handle_simp_ble_notif_ind_common_event(HRP_SIMP_V8_INDICATE, value_size, p_value); + } + + break; + case SIMP_V8_NOTIFY: + { + /* + if (gap_v3_notif_test.v3_tx_conn_id == conn_id) + { + gap_v3_notif_test.v8_rx_num++; + } + */ + APP_PRINT_INFO2("SIMP_V8_NOTIFY: value_size %d, value %b", + value_size, TRACE_BINARY(value_size, p_value)); + hrp_profile_handle_simp_ble_notif_ind_common_event(HRP_SIMP_V8_NOTIFY, value_size, p_value); + } + + break; + default: + break; + } + break; + + default: + break; + } + +} + +///=============================Simp Ble Client cmd====================== + +static void hrp_simp_ble_client_start_all_discovery(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + bool result; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + if ((client_all_primary_srv_discovery(conn_id, CLIENT_PROFILE_GENERAL_ID)) == GAP_CAUSE_SUCCESS) + { + result = true; + } + else + { + result = false; + } + + APP_PRINT_INFO1("hrp_simp_ble_client_start_all_discovery: result 0x%x", result); + hrp_profile_simp_ble_cmd_result(result); +} +static void hrp_simp_ble_client_start_discovery(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t conn_id; + bool result; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + result = simp_ble_client_start_discovery(conn_id); + + APP_PRINT_INFO1("hrp_simp_ble_client_start_discovery: result 0x%x", result); + hrp_profile_simp_ble_cmd_result(result); +} +static void hrp_simp_ble_client_read_by_handle(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint8_t read_type; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(read_type, p_param_list + pos); pos += 1; + + result = simp_ble_client_read_by_handle(conn_id, (T_SIMP_READ_TYPE)read_type); + + hrp_profile_simp_ble_cmd_result(result); +} + +static void hrp_simp_ble_client_read_by_uuid(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint8_t read_type; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(read_type, p_param_list + pos); pos += 1; + + result = simp_ble_client_read_by_uuid(conn_id, (T_SIMP_READ_TYPE) read_type); + + hrp_profile_simp_ble_cmd_result(result); + + +} +static void hrp_simp_ble_client_write_v2_char(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint8_t type; + uint16_t length; + uint8_t *p_value; + + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(type, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_client_write_v2_char(conn_id, length, p_value, (T_GATT_WRITE_TYPE)type); + + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_value); +} + +static void hrp_simp_ble_client_write_v6_char(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint16_t length; + uint8_t *p_value; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_client_write_v6_char(conn_id, length, p_value); + + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_value); + +} + +static void hrp_simp_ble_client_set_v3_notify(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + bool notify; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(notify, p_param_list + pos); pos += 1; + + result = simp_ble_client_set_v3_notify(conn_id, notify); + + hrp_profile_simp_ble_cmd_result(result); +} + +static void hrp_simp_ble_client_set_v4_ind(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + bool ind; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(ind, p_param_list + pos); pos += 1; + + result = simp_ble_client_set_v4_ind(conn_id, ind); + + hrp_profile_simp_ble_cmd_result(result); + +} +static void hrp_simp_ble_client_set_v8_cccd(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint16_t cccd_bits; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(cccd_bits, p_param_list + pos); pos += 2; + + result = simp_ble_client_set_v8_cccd(conn_id, cccd_bits); + + hrp_profile_simp_ble_cmd_result(result); +} +static void hrp_simp_ble_client_get_hdl_cache(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint8_t hdl_idx; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + uint16_t hdl_cache[HDL_SIMBLE_CACHE_LEN] = {0}; + + result = simp_ble_client_get_hdl_cache(conn_id, hdl_cache, sizeof(uint16_t) * HDL_SIMBLE_CACHE_LEN); + hrp_profile_simp_ble_cmd_result(result); + if (result) + { + for (hdl_idx = HDL_SIMBLE_SRV_START; hdl_idx < HDL_SIMBLE_CACHE_LEN; hdl_idx++) + { + APP_PRINT_INFO2("-->Index %d -- Handle 0x%x\r\n", hdl_idx, hdl_cache[hdl_idx]); + } + hrp_profile_simp_ble_get_hdl_cache_rsp(HDL_SIMBLE_SRV_START, HDL_SIMBLE_CACHE_LEN, hdl_cache); + } +} +static void hrp_simp_ble_client_set_hdl_cache(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint8_t length; + uint16_t *p_hdl_cache; + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(length, p_param_list + pos); pos += 1; + + p_hdl_cache = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_hdl_cache, &pos, p_param_list, length); + + result = simp_ble_client_set_hdl_cache(conn_id, p_hdl_cache, length); + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_hdl_cache); +} +#endif +///=============================Simp Ble Server cmd====================== +static void hrp_simp_ble_service_set_parameter(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t param_type; + uint16_t length; + uint8_t *p_value; + LE_ARRAY_TO_UINT8(param_type, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_service_set_parameter((T_SIMP_PARAM_TYPE)param_type, length, p_value); + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_value); +} + + +static void hrp_simp_ble_service_send_v3_notify(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + //T_SERVER_ID service_id; + uint8_t *p_value; + uint16_t length; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + //LE_ARRAY_TO_UINT8(service_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_service_send_v3_notify(conn_id, simp_srv_id, p_value, length); + hrp_profile_simp_ble_cmd_result(result); + APP_PRINT_INFO5("hrp_simp_ble_service_send_v3_notify: result=%d ,conn_id= %d, simp_srv_id= %d, length =%d, pValue= %b", + result, conn_id, simp_srv_id, length, TRACE_BINARY(length, p_value)); + os_mem_free(p_value); +} + +static void hrp_simp_ble_service_send_v4_indicate(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + //T_SERVER_ID service_id; + uint8_t *p_value; + uint16_t length; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + // LE_ARRAY_TO_UINT8(service_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_service_send_v4_indicate(conn_id, simp_srv_id, p_value, length); + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_value); +} + + +static void hrp_simp_ble_service_simple_v8_notify(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + // T_SERVER_ID service_id; + uint8_t *p_value; + uint16_t length; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + //LE_ARRAY_TO_UINT8(service_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_service_simple_v8_notify(conn_id, simp_srv_id, p_value, length); + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_value); +} + +static void hrp_simp_ble_service_simple_v8_indicate(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + // T_SERVER_ID service_id; + uint8_t *p_value; + uint16_t length; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + // LE_ARRAY_TO_UINT8(service_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT16(length, p_param_list + pos); pos += 2; + + p_value = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_value, &pos, p_param_list, length); + + result = simp_ble_service_simple_v8_indicate(conn_id, simp_srv_id, p_value, length); + hrp_profile_simp_ble_cmd_result(result); + os_mem_free(p_value); +} + +static void hrp_simp_ble_service_add_service(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + uint8_t count; + + LE_ARRAY_TO_UINT8(count, p_param_list + pos); pos += 1; + for (uint8_t i = 1; i <= count; i++) + { + simp_ble_service_add_service((void *)hrp_profile_callback); + APP_PRINT_INFO1("hrp_simp_ble_service_add_service :add service %d times.", i); + } +} + + +void (*(hrp_profile_handle_simp_ble[]))(uint16_t len, uint8_t *p_param_list) = +{ +#if F_BT_LE_GATT_CLIENT_SUPPORT + hrp_simp_ble_client_start_all_discovery, + hrp_simp_ble_client_start_discovery, //0x01 + hrp_simp_ble_client_read_by_handle, + hrp_simp_ble_client_read_by_uuid, + hrp_simp_ble_client_write_v2_char, + hrp_simp_ble_client_write_v6_char, //0x05 + hrp_simp_ble_client_set_v3_notify, + hrp_simp_ble_client_set_v4_ind, + hrp_simp_ble_client_set_v8_cccd, + hrp_simp_ble_client_get_hdl_cache, + hrp_simp_ble_client_set_hdl_cache, //0x0a +#else + NULL, + NULL, //0x01 + NULL, + NULL, + NULL, + NULL, //0x05 + NULL, + NULL, + NULL, + NULL, + NULL, //0x0a +#endif + NULL, + NULL, + NULL, + NULL, + NULL, + hrp_simp_ble_service_set_parameter, //0x10 + hrp_simp_ble_service_send_v3_notify, + hrp_simp_ble_service_send_v4_indicate, + hrp_simp_ble_service_simple_v8_notify, + hrp_simp_ble_service_simple_v8_indicate, + hrp_simp_ble_service_add_service, //0x15 + + +}; + + +#if F_BT_LE_GATT_CLIENT_SUPPORT +/*********************************handle gaps client event function**********************************/ +void hrp_profile_handle_gaps_client_cb_type_disc_state(T_GAPS_CLIENT_CB_TYPE cb_type, + T_GAPS_DISC_STATE disc_state) +{ + + uint8_t Param[2]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, cb_type); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, disc_state); pos += 1; + + hrp_profile_gaps_cleint_evet(HRP_GAPS_CLIENT_CB_TYPE_DISC_STATE, pos, Param); +} + +void hrp_profile_handle_gaps_client_cb_type_read_device_name(T_GAPS_CLIENT_CB_TYPE cb_type, + T_GAPS_READ_TYPE type, + uint16_t cause, uint16_t value_size, uint8_t *p_value) +{ + uint8_t Param[100] = {0}; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, cb_type); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, type); pos += 1; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + LE_UINT16_TO_ARRAY(Param + pos, value_size); pos += 2; + + hrp_profile_commit_buf(Param, &pos, p_value, value_size); + + hrp_profile_gaps_cleint_evet(HRP_GAPS_READ_DEVICE_NAME, pos, Param); + +} +void hrp_profile_handle_gaps_client_cb_type_read_apperance(T_GAPS_CLIENT_CB_TYPE cb_type, + T_GAPS_READ_TYPE type, + uint16_t cause, uint16_t appearance) +{ + uint8_t Param[6]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, cb_type); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, type); pos += 1; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + LE_UINT16_TO_ARRAY(Param + pos, appearance); pos += 2; + + hrp_profile_gaps_cleint_evet(HRP_GAPS_READ_APPEARANCE, pos, Param); + +} +void hrp_profile_handle_gaps_client_cb_type_read_central_addr_resolution( + T_GAPS_CLIENT_CB_TYPE cb_type, T_GAPS_READ_TYPE type, uint16_t cause, uint8_t central_addr_res) +{ + uint8_t Param[5]; + int pos = 0; + LE_UINT8_TO_ARRAY(Param + pos, cb_type); pos += 1; + LE_UINT8_TO_ARRAY(Param + pos, type); pos += 1; + LE_UINT16_TO_ARRAY(Param + pos, cause); pos += 2; + LE_UINT8_TO_ARRAY(Param + pos, central_addr_res); pos += 1; + + hrp_profile_gaps_cleint_evet(HRP_GAPS_READ_CENTRAL_ADDR_RESOLUTION, pos, Param); + +} + + +void hrp_profile_client_gaps_callback(T_GAPS_CLIENT_CB_DATA *p_gaps_cb_data) +{ + switch (p_gaps_cb_data->cb_type) + { + case GAPS_CLIENT_CB_TYPE_DISC_STATE: + { + switch (p_gaps_cb_data->cb_content.disc_state) + { + case DISC_GAPS_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + APP_PRINT_INFO0("app_client_callback: discover gaps procedure done."); + break; + case DISC_GAPS_FAILED: + /* Discovery Request failed. */ + APP_PRINT_INFO0("app_client_callback: discover gaps request failed."); + break; + default: + break; + } + + hrp_profile_handle_gaps_client_cb_type_disc_state(p_gaps_cb_data->cb_type, + p_gaps_cb_data->cb_content.disc_state); + + } + + break; + case GAPS_CLIENT_CB_TYPE_READ_RESULT: + { + switch (p_gaps_cb_data->cb_content.read_result.type) + { + case GAPS_READ_DEVICE_NAME: + { + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: device name %s.", + TRACE_STRING(p_gaps_cb_data->cb_content.read_result.data.device_name.p_value)); + } + else + { + APP_PRINT_INFO1("GAPS_READ_DEVICE_NAME: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + hrp_profile_handle_gaps_client_cb_type_read_device_name(p_gaps_cb_data->cb_type, + p_gaps_cb_data->cb_content.read_result.type, + p_gaps_cb_data->cb_content.read_result.cause, + p_gaps_cb_data->cb_content.read_result.data.device_name.value_size, + p_gaps_cb_data->cb_content.read_result.data.device_name.p_value); + } + + break; + case GAPS_READ_APPEARANCE: + { + + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: appearance %d", + p_gaps_cb_data->cb_content.read_result.data.appearance); + } + else + { + APP_PRINT_INFO1("GAPS_READ_APPEARANCE: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + + hrp_profile_handle_gaps_client_cb_type_read_apperance(p_gaps_cb_data->cb_type, + p_gaps_cb_data->cb_content.read_result.type, + p_gaps_cb_data->cb_content.read_result.cause, + p_gaps_cb_data->cb_content.read_result.data.appearance); + } + + break; + case GAPS_READ_CENTRAL_ADDR_RESOLUTION: + { + if (p_gaps_cb_data->cb_content.read_result.cause == GAP_SUCCESS) + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: central_addr_res %d", + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + } + else + { + APP_PRINT_INFO1("GAPS_READ_CENTRAL_ADDR_RESOLUTION: failded cause 0x%x", + p_gaps_cb_data->cb_content.read_result.cause); + } + hrp_profile_handle_gaps_client_cb_type_read_central_addr_resolution(p_gaps_cb_data->cb_type, + p_gaps_cb_data->cb_content.read_result.type, + p_gaps_cb_data->cb_content.read_result.cause, + p_gaps_cb_data->cb_content.read_result.data.central_addr_res); + } + + break; + default: + break; + } + } + + break; + + default: + break; + } + +} +///=============================Gaps client cmd function====================== +static void hrp_gaps_start_discovery(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + result = gaps_start_discovery(conn_id); + + hrp_profile_gaps_client_cmd_result(result); +} + +static void hrp_gaps_read(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint8_t read_type; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(read_type, p_param_list + pos); pos += 1; + + result = gaps_read(conn_id, (T_GAPS_READ_TYPE)read_type); + + hrp_profile_gaps_client_cmd_result(result); +} + +static void hrp_gaps_get_hdl_cache(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint16_t *p_hdl_cache; + uint8_t length; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(length, p_param_list + pos); pos += 1; + p_hdl_cache = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + //hrp_profile_fetch_buf(p_hdl_cache, &pos, p_param_list, length); + + result = gaps_get_hdl_cache(conn_id, p_hdl_cache, length); + + hrp_profile_gaps_client_cmd_result(result); + + os_mem_free(p_hdl_cache); +} + +static void hrp_gaps_set_hdl_cache(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + uint16_t *p_hdl_cache; + uint8_t length; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + LE_ARRAY_TO_UINT8(length, p_param_list + pos); pos += 1; + p_hdl_cache = os_mem_alloc(RAM_TYPE_DATA_ON, length); + + hrp_profile_fetch_buf(p_hdl_cache, &pos, p_param_list, length); + + result = gaps_set_hdl_cache(conn_id, p_hdl_cache, length); + + hrp_profile_gaps_client_cmd_result(result); + os_mem_free(p_hdl_cache); +} +#endif +#if F_BT_LE_PRIVACY_SUPPORT +static void hrp_gaps_check_resolvable_private_addr_only_char(uint16_t len, uint8_t *p_param_list) +{ + uint16_t pos = 0; + bool result; + uint8_t conn_id; + bool *p_is_exist; + + LE_ARRAY_TO_UINT8(conn_id, p_param_list + pos); pos += 1; + + result = gaps_check_resolvable_private_addr_only_char(conn_id, p_is_exist); + + hrp_profile_gaps_client_cmd_result(result); +} +#endif + +void (*(hrp_profile_handle_gaps_client[]))(uint16_t len, uint8_t *p_param_list) = +{ + NULL, +#if F_BT_LE_GATT_CLIENT_SUPPORT + hrp_gaps_start_discovery, //0x01 + hrp_gaps_read, + hrp_gaps_get_hdl_cache, + hrp_gaps_set_hdl_cache, +#else + NULL, //0x01 + NULL, + NULL, + NULL, +#endif +#if F_BT_LE_PRIVACY_SUPPORT + hrp_gaps_check_resolvable_private_addr_only_char, +#else + NULL, +#endif + NULL, + NULL, + NULL, + + +}; diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_le_simple_ble.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_le_simple_ble.h new file mode 100644 index 00000000..12504fa5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_le_simple_ble.h @@ -0,0 +1,68 @@ +#ifndef _HRP_PROFILE_SIMPLE_BLE_H_ +#define _HRP_PROFILE_SIMPLE_BLE_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "complete_ble_service.h" +#include "complete_ble_client.h" + +typedef enum +{ + HRP_SIMP_BLE_CMD_RESULT = 0x01, + + HRP_SIMP_CLIENT_CB_TYPE_DISC_STATE, //02 + HRP_SIMP_READ_V1_READ, //03 + HRP_SIMP_READ_V3_NOTIFY_CCCD, //04 + + HRP_SIMP_READ_V4_INDICATE_CCCD, //05 + HRP_SIMP_READ_V8_CCCD, //06 + + HRP_SIMP_READ_V7_READ_LONG, //07 + + HRP_SIMP_WRITE_V2_WRITE, //08 + HRP_SIMP_WRITE_V3_NOTIFY_CCCD, //09 + + HRP_SIMP_WRITE_V4_INDICATE_CCCD, //0x0a + + HRP_SIMP_WRITE_V6_WRITE_LONG, //0x0b + + HRP_SIMP_WRITE_V8_CCCD, //0x0c + + HRP_SIMP_V3_NOTIFY, //0x0d + HRP_SIMP_V4_INDICATE, //0x0e + HRP_SIMP_V8_INDICATE, //0x0f + HRP_SIMP_V8_NOTIFY, //0x10 + + HRP_SIMP_GET_HDL_CACHE_RSP, //0x11 + + + HRP_SERVICE_CALLBACK_TYPE_INDIFICATION_NOTIFICATION = 0x30, + HRP_SERVICE_CALLBACK_TYPE_READ_CHAR_VALUE = 0x31, + HRP_SERVICE_CALLBACK_TYPE_WRITE_CHAR_VALUE, + + +} T_PROFILE_SIMP_BLE_MSG_INDEX; + +typedef enum +{ + HRP_GAPS_CLIENT_CMD_RESULT = 0x01, + HRP_GAPS_CLIENT_CB_TYPE_DISC_STATE, + + HRP_GAPS_READ_DEVICE_NAME, + HRP_GAPS_READ_APPEARANCE, + HRP_GAPS_READ_CENTRAL_ADDR_RESOLUTION, + +} T_PROFILE_GAPS_CLIENT_MSG_INDEX; + +void hrp_profile_server_simp_ble_callback(TSIMP_CALLBACK_DATA *p_simp_cb_data); +#if F_BT_LE_GATT_CLIENT_SUPPORT +void hrp_profile_client_simp_ble_callback(T_SIMP_CLIENT_CB_DATA *p_simp_client_cb_data); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* _HRP_PROFILE_SIMPLE_BLE_SERVICE_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_system_api.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_system_api.c new file mode 100644 index 00000000..2dbf4ddc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_system_api.c @@ -0,0 +1,309 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file hrp_profile_system_api.c +* @brief +* @details none. +* @author Thomas +* @date 2017-11-8 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#include + +#include "hrp_profile_system_api.h" + + +#include + +#if F_BT_DLPS_EN +#include +#endif + + +//#include "cod.h" + + +#define REMOVE_OLD_PROFILE_INIT 1 + +extern void *hIoQueueHandle; + +uint8_t hrp_gap_support_mode = 0; + +uint8_t hrp_gap_initiated_mode = 0; + +//=============================event============================// +static void hrp_profile_sys_event(uint16_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + uint8_t cmd_group = HRP_PROFILE_CMD_GROUP_EVENT_SYS; + hrp_profile_evet(cmd_group, cmd_index, param_list_len, p_param_list); +} +static void hrp_profile_system_cmd_result(uint8_t sysCause) +{ + hrp_profile_sys_event(PROFILE_SYSTEM_CMD_RESULT, sizeof(uint8_t), &sysCause); +} + +static void hrp_profile_system_reset_cmp(uint8_t sysCause) +{ + hrp_profile_sys_event(PROFILE_SYSTEM_RESET_COMPLETE, sizeof(uint8_t), &sysCause); +} + +static void hrp_profile_system_init_cmp(uint8_t sysCause) +{ + uint8_t Param[8]; + int pos = 0; + + LE_UINT8_TO_ARRAY(Param + pos, sysCause); pos += 1; + if (sysCause == PROFILE_SYS_CMD_SUCESS) + { + gap_get_param(GAP_PARAM_BD_ADDR, P_BtHrp->ownBDAddress); + memcpy(Param + pos, P_BtHrp->ownBDAddress, 6); + } + + pos += 6; + LE_UINT8_TO_ARRAY(Param + pos, sysCause); pos += 1; + hrp_profile_sys_event(PROFILE_SYSTEM_INIT_COMPLETE, pos, Param); +} + +static void hrp_profile_system_set_gap_param_rsp(PROFILE_SYS_CAUSE sysCause) +{ + + hrp_profile_sys_event(PROFILE_SYSTEM_SET_GAP_PARAM_RSP, sizeof(uint8_t), &(sysCause)); +} + +static void hrp_profile_system_set_pairable_mode_rsp(PROFILE_SYS_CAUSE sysCause) +{ + hrp_profile_sys_event(PROFILE_SYSTEM_SET_PAIRABLE_MODE_RSP, sizeof(uint8_t), &(sysCause)); +} + +static void hrp_profile_system_enable_dlps_rsp(PROFILE_SYS_CAUSE sysCause) +{ + hrp_profile_sys_event(PROFILE_SYSTEM_ENABLE_DLPS_RSP, sizeof(uint8_t), &(sysCause)); +} + +void hrp_profile_system_send_cmd_ack(uint8_t cmd_group, uint16_t cmd_index, + HRP_PROFILE_SYSTEM_CMD_STATUS status) +{ + HRP_MODULE_ID module_id = HRP_MODULE_PROFILE; + uint8_t event_group = HRP_PROFILE_CMD_GROUP_EVENT_SYS; + uint16_t event_index = PROFILE_SYSTEM_CMD_ACK; + uint16_t param_list_len = 5; + uint8_t param_list[5]; + uint8_t *p_param_list = ¶m_list[0]; + uint8_t pos = 0; + uint32_t cmd_id = (((uint32_t)cmd_group) << 16) + cmd_index; + + LE_UINT32_TO_ARRAY(p_param_list + pos, cmd_id); pos += 4; + LE_UINT8_TO_ARRAY(p_param_list + pos, status); + + hrp_handle_upperstream_events(module_id, event_group, + event_index, param_list_len, p_param_list); +} + +//======================handle legacy msg=============================// +void hrp_profile_handle_initCmplete(uint8_t initiated_mode) +{ + hrp_gap_initiated_mode |= initiated_mode; + + /* both supported mode have completed initiate */ + if ((hrp_gap_initiated_mode & hrp_gap_support_mode) == hrp_gap_support_mode) + { + APP_PRINT_TRACE0("gap init complete\n"); + hrp_profile_system_init_cmp(PROFILE_SYS_CMD_SUCESS); + } +} + +//===============================cmd=============================// +void hrp_profile_system_reset(uint16_t len, uint8_t *p_param_list) +{ + APP_PRINT_INFO1("hrp_profile_system_reset:system_status= %d", system_status); + hrp_profile_system_cmd_result(PROFILE_SYS_CMD_SUCESS); + hrp_profile_system_reset_cmp(PROFILE_SYS_CMD_SUCESS); + hrp_system_reset(); +} +T_GAP_CAUSE hrp_gap_common_set_param(uint16_t type, uint8_t len, void *p_value) +{ + APP_PRINT_INFO2("hrp_gap_common_set_param: type:%x data= %b", type, TRACE_BINARY(len, p_value)); + return gap_set_param((T_GAP_PARAM_TYPE)type, len, (void *)p_value); +} + +void hrp_profile_system_set_gap_param(uint16_t len, uint8_t *p_param_list) +{ + uint8_t pos = 0; + uint8_t param_type; + uint8_t data_len; + uint16_t data_type; + uint8_t *p_value; + T_GAP_CAUSE return_cause = GAP_CAUSE_INVALID_PARAM; + + if (len < GAP_DATA_TYPE_LEN + 2) + { + APP_PRINT_ERROR0("hrp_profile_system_set_gap_param: wrong length"); + hrp_profile_system_set_gap_param_rsp(PROFILE_SYS_CMD_INVALID_PARAM); + return; + } + + while ((pos + 1 + GAP_DATA_TYPE_LEN + 1) < len) + { + /* parse data field: data_len(1 byte) + type(GAP_DATA_TYPE_LEN bytes) + value (data_len - GAP_DATA_TYPE_LEN)*/ + param_type = p_param_list[pos++]; + data_len = p_param_list[pos++]; + if (data_len < 3) + { + APP_PRINT_ERROR1("hrp_profile_system_set_gap_param: invalid data_len =%d ", data_len); + hrp_profile_system_set_gap_param_rsp(PROFILE_SYS_CMD_INVALID_PARAM); + return; + } + LE_ARRAY_TO_UINT16(data_type, p_param_list + pos); pos += 2; + p_value = p_param_list + pos; + pos += data_len - GAP_DATA_TYPE_LEN; + + APP_PRINT_INFO4("param_type %x data_len %x data_type %x data %b", param_type, data_len, data_type, + TRACE_BINARY(data_len - GAP_DATA_TYPE_LEN, p_value)); + switch (param_type) + { + case GAP_PARAM_TYPE_COMMON: + return_cause = hrp_gap_common_set_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; + case GAP_PARAM_TYPE_LEGACY: + //hrp_gap_legacy_set_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; + case GAP_PARAM_TYPE_LEGACY_BOND: + // hrp_gap_legacy_set_bond_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; + case GAP_PARAM_TYPE_LE: + return_cause = hrp_le_set_gap_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; + case GAP_PARAM_TYPE_LE_BOND: + return_cause = hrp_le_set_bond_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; +#if F_BT_LE_GAP_SCAN_SUPPORT + case GAP_PARAM_TYPE_LE_SCAN: + return_cause = hrp_le_set_scan_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; +#endif +#if F_BT_LE_PRIVACY_SUPPORT + case GAP_PARAM_TYPE_LE_PRIVACY: + return_cause = hrp_le_set_privacy_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; +#endif + case GAP_PARAM_TYPE_LE_ADV: + return_cause = hrp_le_set_adv_param(data_type, data_len - GAP_DATA_TYPE_LEN, (void *)p_value); + break; + default: + { + APP_PRINT_ERROR1("hrp_profile_system_set_gap_param:invalid param type = %d ", param_type); + hrp_profile_system_set_gap_param_rsp(PROFILE_SYS_CMD_INVALID_PARAM); + return; + } + } + + hrp_profile_system_set_gap_param_rsp((PROFILE_SYS_CAUSE)return_cause); + + } +} +void hrp_profile_system_set_pairable_mode(uint16_t len, uint8_t *p_param_list) +{ + PROFILE_SYS_CAUSE cause = PROFILE_SYS_CMD_SUCESS; + + hrp_profile_system_cmd_result(PROFILE_SYS_CMD_SUCESS); + if (gap_set_pairable_mode() != GAP_CAUSE_SUCCESS) + { + cause = PROFILE_SYS_CMD_FAIL; + } + hrp_profile_system_set_pairable_mode_rsp(cause); +} + +void hrp_profile_system_enable_dlps(uint16_t len, uint8_t *p_param_list) +{ + PROFILE_SYS_CAUSE cause = PROFILE_SYS_CMD_FAIL; + APP_PRINT_INFO0("hrp_profile_system_enable_dlps"); +#if F_BT_DLPS_EN + uint16_t pos = 0; + uint8_t active; + LE_ARRAY_TO_UINT8(active, p_param_list); pos++; + + if (hrp_dlps_active_dlps(active)) + { + cause = PROFILE_SYS_CMD_SUCESS; + } + hrp_dlps_allow_enter(false); + hrp_profile_system_enable_dlps_rsp(cause); +#else + hrp_profile_system_enable_dlps_rsp(cause); +#endif +} + +void hrp_profile_system_init_gap(uint16_t len, uint8_t *p_param_list) +{ + hrp_profile_system_cmd_result(PROFILE_SYS_CMD_SUCESS); + + APP_PRINT_INFO1("hrp_profile_system_init_gap:system_status= %d", system_status); + /* + if (system_status != HRP_STATUS_RESET) + { + APP_PRINT_ERROR0("hrp_profile_system_init_gap: wrong status"); + hrp_profile_system_init_cmp(PROFILE_SYS_CMD_INVALID_STATE); + return; + } + */ + uint16_t pos = 0; + uint8_t legacy_profile_mask; + uint16_t le_profile_sever_mask; + uint16_t le_profile_client_mask; + + hrp_gap_support_mode = p_param_list[pos]; pos++; + legacy_profile_mask = p_param_list[pos]; pos++; + LE_ARRAY_TO_UINT16(le_profile_sever_mask, p_param_list + pos); pos += 2; + LE_ARRAY_TO_UINT16(le_profile_client_mask, p_param_list + pos); pos += 2; + + if (hrp_gap_support_mode == 0) + { + APP_PRINT_ERROR0("hrp_profile_system_init_gap: at least support one of bredr/ble"); + hrp_profile_system_init_cmp(PROFILE_SYS_CMD_INVALID_PARAM); + return; + } + + /* gap common init */ + //gap_init_timer(P_BtHrp->p_aci_tcb->QueueHandleEvent, MAX_NUMBER_OF_GAP_TIMER); + + /* gap legacy init */ + if (hrp_gap_support_mode & HRP_GAP_LEGACY) + { + //hrp_gap_common_set_default_param(); + //hrp_gap_legacy_set_default_param(); + //hrp_gap_legacy_init(legacy_profile_mask); + APP_PRINT_INFO1("legacy_profile_mask :%d", legacy_profile_mask); + } + + /* gap le init */ + if (hrp_gap_support_mode & HRP_GAP_LE) + { + hrp_gap_le_init(le_profile_sever_mask, le_profile_client_mask); + } + + /* start gap */ + system_status = HRP_STATUS_ACTIVE; + active_module = HRP_MODULE_PROFILE; + + gap_start_bt_stack(P_BtHrp->p_aci_tcb->QueueHandleEvent, hIoQueueHandle, MAX_NUMBER_OF_MESSAGE); + + //wait le/legacy gap init complete msg, then send init_gap_rsp +} + + + +void (*(hrp_profile_handle_system[]))(uint16_t len, uint8_t *p_param_list) = +{ + + NULL, + hrp_profile_system_reset, /* 0x01 */ + hrp_profile_system_init_gap, + hrp_profile_system_set_gap_param, /* 0x03, PROFILE_SYSTEM_SET_GAP_PARAM_REQ 0x03*/ + hrp_profile_system_set_pairable_mode,/* 0x04 */ + hrp_profile_system_enable_dlps, //0x05 +}; + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_system_api.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_system_api.h new file mode 100644 index 00000000..cc90bf4b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap/hrp_profile_system_api.h @@ -0,0 +1,69 @@ +#ifndef _HRP_PROFILE_SYSTEM_API_H_ +#define _HRP_PROFILE_SYSTEM_API_H_ + +#include +#include +#include + +#define GAP_DATA_TYPE_LEN 2 +typedef enum +{ + GAP_PARAM_TYPE_LE = 0, + GAP_PARAM_TYPE_LE_BOND = 1, + GAP_PARAM_TYPE_LE_SCAN = 2, + GAP_PARAM_TYPE_LE_PRIVACY = 3, + GAP_PARAM_TYPE_LE_ADV = 4, + + GAP_PARAM_TYPE_LEGACY = 0x10, + GAP_PARAM_TYPE_LEGACY_BOND = 0x11, + + GAP_PARAM_TYPE_COMMON = 0x20, + +} T_HRP_GAP_PARAM_TYPE; + +typedef enum +{ + LE_SET_PARAM_TYPE_GAP = 0, + LE_SET_PARAM_TYPE_BOND = 1, + LE_SET_PARAM_TYPE_SCAN = 2, + LE_SET_PARAM_TYPE_PRIVACY = 3, + LE_SET_PARAM_TYPE_ADV = 4, +} T_HRP_LE_SET_PARAM_TYPE; +typedef enum +{ + LE_GET_PARAM_TYPE_GAP = 0, + LE_GET_PARAM_TYPE_BOND = 1, + LE_GET_PARAM_TYPE_SCAN = 2, + LE_GET_PARAM_TYPE_PRIVACY = 3, + LE_GET_PARAM_TYPE_ADV = 4, + +} T_HRP_LE_GET_PARAM_TYPE; + + + + +typedef enum +{ + HRP_GAP_LEGACY = 1, + HRP_GAP_LE = 2, +} T_HRP_GAP_SUPPORT_MODE; + + + +typedef enum +{ + PROFILE_SYS_CMD_SUCESS = 0X00, + PROFILE_SYS_CMD_FAIL = 0X01, + PROFILE_SYS_CMD_UNSUPPORT = 0X02, + PROFILE_SYS_CMD_TRYAGAIN = 0X04, + PROFILE_SYS_CMD_EXEFAIL = 0X05, + PROFILE_SYS_CMD_INVALID_PARAM = 0x06, + PROFILE_SYS_CMD_INVALID_STATE = 0x07, +} PROFILE_SYS_CAUSE; + + + +void hrp_profile_system_send_cmd_ack(uint8_t cmd_group, uint16_t cmd_index, + HRP_PROFILE_SYSTEM_CMD_STATUS status); + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_api.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_api.c new file mode 100644 index 00000000..170d328a --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_api.c @@ -0,0 +1,18 @@ + +#include + +//#include +#include + +void hrp_gap_ble_handle_adv_0000_perf_config_req(uint16_t len, uint8_t *p_param_list) +{ +// bt_hrp_tgt_send_hrp_message(pBTLtp, pBTLtp->pMsgBuffer, 0, pos); +} + +void hrp_gap_ble_handle_adv_0000_perf_start_req(uint16_t len, uint8_t *p_param_list) +{ + +} + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_api.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_api.h new file mode 100644 index 00000000..82a4e5d9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_api.h @@ -0,0 +1,12 @@ +#ifndef _HRP_GAP_BLE_API_H_ +#define _HRP_GAP_BLE_API_H_ + +#include +#include +#include + +void hrp_gap_ble_handle_adv_0000_perf_config_req(uint16_t len, uint8_t *p_param_list); +void hrp_gap_ble_handle_adv_0000_perf_start_req(uint16_t len, uint8_t *p_param_list); + + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_cmd_table.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_cmd_table.c new file mode 100644 index 00000000..070a4ae5 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_cmd_table.c @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +void (*(hrp_gap_ble_handle_adv_req[]))(uint16_t len, uint8_t *p_param_list) = +{ + hrp_gap_ble_handle_adv_0000_perf_config_req, + hrp_gap_ble_handle_adv_0000_perf_config_rsp, + hrp_gap_ble_handle_adv_0000_perf_start_req, + hrp_gap_ble_handle_adv_0000_perf_start_rsp, + hrp_gap_ble_handle_adv_0000_perf_cmpl_info, +}; + + + +void hrp_gap_ble_handle_req(uint8_t cmd_group, uint8_t cmd_index, uint16_t param_list_len, + uint8_t *p_param_list) +{ + + switch (cmd_group) + { + case HRP_GAP_BLE_CMD_GROUP_ADV: + hrp_gap_ble_handle_adv_req[cmd_index](param_list_len, p_param_list); + break; + + case HRP_GAP_BLE_CMD_GROUP_SCAN: + break; + + case HRP_GAP_BLE_CMD_GROUP_CONN: + break; + + case HRP_GAP_BLE_CMD_GROUP_PAIR: + break; + + default: + break; + } +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_cmd_table.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_cmd_table.h new file mode 100644 index 00000000..ecee7ef8 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_cmd_table.h @@ -0,0 +1,56 @@ +#ifndef _HRP_GAP_BLE_CMD_TABLE_H_ +#define _HRP_GAP_BLE_CMD_TABLE_H_ + +#include +//#include + +typedef enum _HRP_GAP_BLE_CMD_GROUP_INDEX +{ + HRP_GAP_BLE_CMD_GROUP_ADV = 0, + HRP_GAP_BLE_CMD_GROUP_SCAN = 1, + HRP_GAP_BLE_CMD_GROUP_CONN = 2, + HRP_GAP_BLE_CMD_GROUP_PAIR = 3 + +} HRP_GAP_BLE_CMD_GROUP_INDEX; + +typedef enum _HRP_GAP_BLE_CMD_GROUP_ADV_INDEX +{ + HRP_GAP_BLE_CMD_ADV_0000_PERFOAMANCE_CONFIG_REQ = 0, + HRP_GAP_BLE_CMD_ADV_0000_PERFOAMANCE_CONFIG_RSP, + HRP_GAP_BLE_CMD_ADV_0000_PERFOAMANCE_START_REQ, + HRP_GAP_BLE_CMD_ADV_0000_PERFOAMANCE_START_RSP, + HRP_GAP_BLE_CMD_ADV_0000_PERFOAMANCE_CMPL_INFO, + + HRP_GAP_BLE_CMD_ADV_0001_STRESS_START_STOP_CONFIG_REQ, + HRP_GAP_BLE_CMD_ADV_0001_STRESS_START_STOP_CONFIG_RSP, + HRP_GAP_BLE_CMD_ADV_0001_STRESS_START_STOP_START_REQ, + HRP_GAP_BLE_CMD_ADV_0001_STRESS_START_STOP_START_RSP, + HRP_GAP_BLE_CMD_ADV_0001_STRESS_START_STOP_CMPL_INFO + +} HRP_GAP_BLE_CMD_GROUP_ADV_INDEX; + + +typedef enum _HRP_GAP_BLE_CMD_GROUP_SCAN_INDEX +{ + HRP_GAP_BLE_CMD_SCAN_0000_PERFOAMANCE_CONFIG_REQ = 0, + HRP_GAP_BLE_CMD_SCAN_0000_PERFOAMANCE_CONFIG_RSP, + HRP_GAP_BLE_CMD_SCAN_0000_PERFOAMANCE_START_REQ, + HRP_GAP_BLE_CMD_SCAN_0000_PERFOAMANCE_START_RSP, + HRP_GAP_BLE_CMD_SCAN_0000_PERFOAMANCE_CMPL_INFO, + + HRP_GAP_BLE_CMD_SCAN_0001_STRESS_START_STOP_CONFIG_REQ, + HRP_GAP_BLE_CMD_SCAN_0001_STRESS_START_STOP_CONFIG_RSP, + HRP_GAP_BLE_CMD_SCAN_0001_STRESS_START_STOP_START_REQ, + HRP_GAP_BLE_CMD_SCAN_0001_STRESS_START_STOP_START_RSP, + HRP_GAP_BLE_CMD_SCAN_0001_STRESS_START_STOP_CMPL_INFO, + +} HRP_GAP_BLE_CMD_GROUP_SCAN_INDEX; + +//add more here + + +void hrp_gap_ble_handle_req(uint8_t cmd_group, uint8_t cmd_index, uint16_t len, + uint8_t *p_param_list); + + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_msg.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_msg.c new file mode 100644 index 00000000..5c9ce4e3 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_msg.c @@ -0,0 +1,28 @@ + +#include "hrp.h" +//#include +//#include "hrp_gap_ble_cmd_table.h" +//#include +//#include + +#define LTP_SOURCE_FILE_ID 0x81 + + +void hrp_gap_ble_handle_adv_0000_perf_config_rsp(uint16_t len, uint8_t *p_param_list) +{ + //hrp_gap_ble_send_adv_0000_perf_config_rsp(&pBTLtp->HRPLib, copmsk, pOpt, cause); +} + +void hrp_gap_ble_handle_adv_0000_perf_start_rsp(uint16_t len, uint8_t *p_param_list) +{ + //hrp_gap_ble_send_adv_0000_perf_start_rsp(&pBTLtp->HRPLib, copmsk, pOpt, cause); +} + +void hrp_gap_ble_handle_adv_0000_perf_cmpl_info(uint16_t len, uint8_t *p_param_list) +{ + + //hrp_gap_ble_send_adv_0000_perf_cmpl_info(&pBTLtp->HRPLib, copmsk, pOpt, cause); +} + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_msg.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_msg.h new file mode 100644 index 00000000..7a6319f9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_msg.h @@ -0,0 +1,21 @@ + +#ifndef _HRP_GAP_BLE_MSG_H_ +#define _HRP_GAP_BLE_MSG_H_ + +#include +//#include + + +#include "hrp.h" +#include +#include "hrp_gap_ble_api.h" +//#include +#include "hrp_gap_ble_cmd_table.h" + +void hrp_gap_ble_handle_adv_0000_perf_config_rsp(uint16_t len, uint8_t *p_param_list); +void hrp_gap_ble_handle_adv_0000_perf_start_rsp(uint16_t len, uint8_t *p_param_list); +void hrp_gap_ble_handle_adv_0000_perf_cmpl_info(uint16_t len, uint8_t *p_param_list); + + + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_utils.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_utils.c new file mode 100644 index 00000000..811a1f99 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_utils.c @@ -0,0 +1,34 @@ +//#include +#include + +//#include "hrp_btif_cmd_table.h" +//#include + + +#define LTP_SOURCE_FILE_ID 0x83 + + + +bool hrp_gap_ble_send_adv_0000_perf_config_rsp(uint16_t len, uint8_t *p_param_list) +{ +#if 0 + return LTPLibSendSubMessage_WORD(pLTPLib, copmsk, pOpt, LTP_SUB_DEVICE_CONFIG_DEVICE_NAME_SET_RSP, + cause); +#endif + return true; +} + +bool hrp_gap_ble_send_adv_0000_perf_start_rsp(P_HRP_LIB pLTPLib, uint8_t copmsk, uint8_t *pOpt, + uint16_t cause) +{ + return true; +} + +bool hrp_gap_ble_send_adv_0000_perf_cmpl_info(P_HRP_LIB pLTPLib, uint8_t copmsk, uint8_t *pOpt, + uint16_t cause) +{ + return true; +} + + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_utils.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_utils.h new file mode 100644 index 00000000..c6034dd4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/gap_ble/hrp_gap_ble_utils.h @@ -0,0 +1,25 @@ +#ifndef _HRP_GAP_BLE_UTILS_H_ +#define _HRP_GAP_BLE_UTILS_H_ + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +bool hrp_gap_ble_send_adv_0000_perf_config_rsp(PLTPLib pLTPLib, uint8_t copmsk, uint8_t *pOpt, + uint16_t cause); +bool hrp_gap_ble_send_adv_0000_perf_start_rsp(PLTPLib pLTPLib, uint8_t copmsk, uint8_t *pOpt, + uint16_t cause); +bool hrp_gap_ble_send_adv_0000_perf_cmpl_info(PLTPLib pLTPLib, uint8_t copmsk, uint8_t *pOpt, + uint16_t cause); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/lps/hrp_dlps.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/lps/hrp_dlps.c new file mode 100644 index 00000000..21a33949 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/lps/hrp_dlps.c @@ -0,0 +1,142 @@ +#if F_BT_DLPS_EN + +#include +#include +#include +#include "rtl876x_io_dlps.h" +#include +#include + + +HRP_DLPS_STATUS hrp_dlps_status = HRP_DLPS_STATUS_IDLE; +bool can_enter_dlps = true; +uint32_t enter_dlps_count = 0; + + +void data_uart_dlps_exit_cb(void) +{ +#if 0 + //TODO(cheer): remove log later + DBG_DIRECT("data_uart_dlps_exit_cb mode %d", lps_mode_get()); + Pad_ControlSelectValue(DATA_UART_TX_PIN, PAD_PINMUX_MODE); + Pad_ControlSelectValue(DATA_UART_RX_PIN, PAD_PINMUX_MODE); +#endif +} + +void data_uart_dlps_enter_cb(void) +{ +#if 0 + //TODO(cheer): remove log later + enter_dlps_count++ ; + DBG_DIRECT("data_uart_dlps_enter_cb mode %d", lps_mode_get()); + + Pad_ControlSelectValue(DATA_UART_TX_PIN, PAD_SW_MODE); + Pad_ControlSelectValue(DATA_UART_RX_PIN, PAD_SW_MODE); + System_WakeUpPinEnable(DATA_UART_RX_PIN, PAD_WAKEUP_POL_LOW, 0); +#endif + +} +#if 0 +bool data_uart_dlps_check_cb(void) +{ +#if 1 + //TODO(cheer): remove log later + static int i = 0; + + if (i == 2000) + { + DBG_DIRECT("data_uart_dlps_check_cb %x", can_enter_dlps); + i = 0; + } + i++; +#endif + + if (can_enter_dlps) + { + return true; + } + else + { + DlpsErrorCode = (DLPSErrorCode)0xF0; + return false; + } +} + +void System_Handler(void) +{ + DBG_DIRECT("System_Handler"); + if (System_WakeUpInterruptValue(DATA_UART_RX_PIN) == SET) + { + DBG_DIRECT("System_Handler: Rx wakeup"); + can_enter_dlps = false; + } + Pad_ClearAllWakeupINT(); +} + +void data_uart_dlps_init(void) +{ + DLPS_IORegister(); + if (dlps_check_cb_reg(data_uart_dlps_check_cb) == false) + { + APP_PRINT_ERROR0("data_uart_dlps_init: dlps_check_cb_reg register failed"); + } + DLPS_IORegUserDlpsEnterCb(data_uart_dlps_enter_cb); + DLPS_IORegUserDlpsExitCb(data_uart_dlps_exit_cb); +} + +void hrp_dlps_allow_enter(bool enter) +{ + can_enter_dlps = enter; +} +#endif +void hrp_init_dlps(void) +{ +#if 0 + data_uart_dlps_init(); + lps_mode_set(LPM_DLPS_MODE); + lps_mode_pause(); + hrp_dlps_status = HRP_DLPS_STATUS_INITIATED; + APP_PRINT_INFO0("dlps status initiated"); +#endif +} + +bool hrp_dlps_active_dlps(bool active) +{ +#if 0 + if (active == 0) + { + if (hrp_dlps_status == HRP_DLPS_STATUS_ACTIVED) + { + lps_mode_pause(); + APP_PRINT_INFO0("dlps status paused"); + hrp_dlps_status = HRP_DLPS_STATUS_PAUSED; + } + else + { + APP_PRINT_ERROR1("hrp_enable_dlps: disable dlps in non-active status: %d", hrp_dlps_status); + return false; + } + } + else + { + if (hrp_dlps_status == HRP_DLPS_STATUS_IDLE) + { + APP_PRINT_INFO0("hrp_enable_dlps: init dlps mode"); + hrp_init_dlps(); + } + else if (hrp_dlps_status == HRP_DLPS_STATUS_ACTIVED) + { + APP_PRINT_ERROR0("hrp_enable_dlps: enable dlps in active status: %d"); + return false; + } + + lps_mode_resume(); + hrp_dlps_allow_enter(false); /* not allow enter dlps right now, hrp_app decide if allow enter*/ + APP_PRINT_INFO0("dlps status resumed"); + hrp_dlps_status = HRP_DLPS_STATUS_ACTIVED; + } +#endif + return true; +} + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/lps/hrp_dlps.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/lps/hrp_dlps.h new file mode 100644 index 00000000..4a72f948 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/lps/hrp_dlps.h @@ -0,0 +1,43 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************** +* @file hrp_dlps.h +* @brief Hrp dlps reference api. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +********************************************************************************************************* +*/ +#ifndef _HRP_DLPS_H_ +#define _HRP_DLPS_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +typedef enum +{ + HRP_DLPS_STATUS_IDLE = 0, + HRP_DLPS_STATUS_INITIATED = 1, + HRP_DLPS_STATUS_ACTIVED = 2, + HRP_DLPS_STATUS_PAUSED = 3 +} HRP_DLPS_STATUS; + +extern HRP_DLPS_STATUS hrp_dlps_status; +extern uint32_t enter_dlps_count; + +extern bool hrp_dlps_active_dlps(bool active); +extern void hrp_dlps_allow_enter(bool enter); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/platform/wdt_reset.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/platform/wdt_reset.c new file mode 100644 index 00000000..0b5babf1 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/platform/wdt_reset.c @@ -0,0 +1,28 @@ +#include "wdt_reset.h" +#ifdef AMEBAD_BOARD +#include "ameba_soc.h" +#include "rtl8721d.h" +#endif +#ifdef PLATFORM_STO +#include +#endif +#ifdef CONFIG_PLATFORM_8710C +#include "ota_8710c.h" +#endif + +void wdt_reset(void) +{ +#ifdef PLATFORM_STO /* stollman only */ + SCB->AIRCR = 0x05FA0000 | SCB_AIRCR_SYSRESETREQ; +#endif + +#ifdef AMEBAD_BOARD + u32 Temp = HAL_READ32(SYSTEM_CTRL_BASE_LP, REG_LP_BOOT_CFG); + Temp |= BIT_SOC_BOOT_PATCH_KM4_RUN; + HAL_WRITE32(SYSTEM_CTRL_BASE_LP, REG_LP_BOOT_CFG, Temp); + NVIC_SystemReset(); +#endif +#ifdef CONFIG_PLATFORM_8710C + ota_platform_reset(); +#endif +} diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/platform/wdt_reset.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/platform/wdt_reset.h new file mode 100644 index 00000000..71e6af2d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/platform/wdt_reset.h @@ -0,0 +1,16 @@ +#ifndef _WDT_RESET_H_ +#define _WDT_RESET_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +//#define AMEBAD_BOARD + +void wdt_reset(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _WDT_RESET_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_bas.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_bas.c new file mode 100644 index 00000000..302309b9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_bas.c @@ -0,0 +1,85 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_bas.c +* @brief GATT built-in BAS (Battery Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#include + +#ifndef __GATTSVC_BAS_H +#include +#endif + + +/** + * @brief service definition. + * + * Battery Service + */ +const T_ATTRIB_APPL gatt_svc_bas[] = +{ + /** primary Service */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_BATTERY), /**< service UUID */ + HI_WORD(GATT_UUID_BATTERY) + }, + UUID_16BIT_SIZE, /**< bValueLen */ + NULL, /**< ValueContext */ + GATT_PERM_READ /**< permissions */ + }, + + /** Characteristic */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ | /**< characteristic properties */ + GATT_CHAR_PROP_NOTIFY) + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Battery Level value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_BAS_LEVEL), + HI_WORD(GATT_UUID_CHAR_BAS_LEVEL) + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /**< client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /**< bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /**< permissions */ + } +}; + +const int gatt_svc_bas_size = sizeof(gatt_svc_bas); +const int gatt_svc_bas_nbr_of_attrib = sizeof(gatt_svc_bas) / sizeof(T_ATTRIB_APPL); + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_bas.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_bas.h new file mode 100644 index 00000000..4a5affa0 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_bas.h @@ -0,0 +1,49 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_bas.h +* @brief GATT built-in BAS (Battery Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#ifndef __GATTSVC_BAS_H +#define __GATTSVC_BAS_H + +#ifndef __GATT_H +#include +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** service definition */ + +extern const T_ATTRIB_APPL gatt_svc_bas[]; + +extern const int gatt_svc_bas_size; +extern const int gatt_svc_bas_nbr_of_attrib; + +/** BAS Battery Service */ +#define GATT_UUID_BATTERY 0x180F + +#define GATT_UUID_CHAR_BAS_LEVEL 0x2A19 +/** attribute indices signaled to GATT server application. */ +/** do NOT change these values !!!! */ + +#define GATT_SVC_BAS_BATTERY_LEVEL_INDEX 2 /**< battery level value */ + + +#ifdef __cplusplus +} +#endif + +#endif /**< __GATTSVC_BAS_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_cts.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_cts.c new file mode 100644 index 00000000..206e95ad --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_cts.c @@ -0,0 +1,141 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_cts.c +* @brief GATT built-in GLS (Current Time Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#include + +#ifndef __GATTSVC_CTS_H +#include +#endif + +/** CTS Current Time Service */ +#define GATT_UUID_CURRENT_TIME 0x1805 + +#define GATT_UUID_CHAR_CTS_CURRENT_TIME 0x2A2B +#define GATT_UUID_CHAR_CTS_LOCAL_TIME_INFO 0x2A0F +#define GATT_UUID_CHAR_CTS_REF_TIME_INFO 0x2A14 +/** + * @brief service definition. + * + * Current Time Service + */ +const T_ATTRIB_APPL gatt_svc_cts[] = +{ + /** Primary Service */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_CURRENT_TIME), /**< service UUID */ + HI_WORD(GATT_UUID_CURRENT_TIME) + }, + UUID_16BIT_SIZE, /**< bValueLen */ + NULL, /**< p_value_context */ + GATT_PERM_READ /**< permissions */ + }, + + /**Characteristic>>*/ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + (GATT_CHAR_PROP_READ | /**< characteristic properties */ + GATT_CHAR_PROP_NOTIFY) + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Current Time value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_CTS_CURRENT_TIME), + HI_WORD(GATT_UUID_CHAR_CTS_CURRENT_TIME) + }, + 10, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** client characteristic configuration */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /**< client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /**< bValueLen */ + NULL, + (GATT_PERM_READ | GATT_PERM_WRITE) /**< permissions */ + }, + + /** Characteristic */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /**< characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Local Time Information value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_CTS_LOCAL_TIME_INFO), + HI_WORD(GATT_UUID_CHAR_CTS_LOCAL_TIME_INFO) + }, + 2, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + + /** Characteristic*/ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /**< characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Reference Time Information value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_CTS_REF_TIME_INFO), + HI_WORD(GATT_UUID_CHAR_CTS_REF_TIME_INFO) + }, + 4, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + } +}; + +const int gatt_svc_cts_size = sizeof(gatt_svc_cts); +const int gatt_svc_cts_nbr_of_attrib = sizeof(gatt_svc_cts) / sizeof(T_ATTRIB_APPL); + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_cts.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_cts.h new file mode 100644 index 00000000..c362c701 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_cts.h @@ -0,0 +1,51 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_cts.h +* @brief GATT built-in GLS (Current Time Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#ifndef __GATTSVC_CTS_H +#define __GATTSVC_CTS_H + +#ifndef __GATT_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** service definition */ + +extern const T_ATTRIB_APPL gatt_svc_cts[]; + +extern const int gatt_svc_cts_size; +extern const int gatt_svc_cts_nbr_of_attrib; + +/** CTS Current Time Service */ +#define GATT_UUID_CURRENT_TIME 0x1805 + +#define GATT_UUID_CHAR_CTS_CURRENT_TIME 0x2A2B +#define GATT_UUID_CHAR_CTS_LOCAL_TIME_INFO 0x2A0F +#define GATT_UUID_CHAR_CTS_REF_TIME_INFO 0x2A14 +/** attribute indices signaled to GATT server application. */ +/** do NOT change these values !!!! */ + +#define GATT_SVC_CTS_CURRENT_TIME_INDEX 2 /**< Current Time value */ +#define GATT_SVC_CTS_LOCAL_TIME_INFO_INDEX 5 /**< Local Time Information value */ +#define GATT_SVC_CTS_REF_TIME_INFO_INDEX 7 /**< Reference Time Information value */ + + +#ifdef __cplusplus +} +#endif + +#endif /**< __GATTSVC_CTS_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_dis.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_dis.c new file mode 100644 index 00000000..9273da16 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_dis.c @@ -0,0 +1,120 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file gattsvc_dis.c +* @brief device information service +* @details +* +* @author gordon +* @date 2015-06-30 +* @version v0.1 +*/ + +#include + +#ifndef __GATTSVC_DIS_H +#include +#endif + + +/** +* @brief device information service +* +* +*/ +const T_ATTRIB_APPL gatt_svc_dis[] = +{ + /** Primary Service */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /**< flags */ + { /** +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** service definition */ +extern const T_ATTRIB_APPL gatt_svc_dis[]; + +extern const int gatt_svc_dis_size; +extern const int gatt_svc_dis_nbr_of_attrib; + +#define GATT_UUID_DEVICE_INFORMATION_SERVICE 0x180A + +#define GATT_UUID_CHAR_SYSTEM_ID 0x2A23 +#define GATT_UUID_CHAR_MODEL_NUMBER 0x2A24 +#define GATT_UUID_CHAR_SERIAL_NUMBER 0x2A25 +#define GATT_UUID_CHAR_FIRMWARE_REVISION 0x2A26 +#define GATT_UUID_CHAR_HARDWARE_REVISION 0x2A27 +#define GATT_UUID_CHAR_SOFTWARE_REVISION 0x2A28 +#define GATT_UUID_CHAR_MANUFACTURER_NAME 0x2A29 +#define GATT_UUID_CHAR_IEEE_CERTIF_DATA_LIST 0x2A2A +#define GATT_UUID_CHAR_PNP_ID 0x2A50 +/** attribute indices signaled to GATT server application. */ +/** do NOT change these values !!!! */ + +#define GATT_SVC_DIS_SYSTEM_ID_INDEX 2 /**< index of System ID value */ +#define GATT_SVC_DIS_MANUFACTURER_NAME_INDEX 4 /**< index of Manufacturer Name value */ +#define GATT_SVC_DIS_MODEL_NUMBER_INDEX 6 /**< index of Model Number value */ + + +#ifdef __cplusplus +} +#endif + +#endif /**< __GATTSVC_DIS_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_gls.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_gls.c new file mode 100644 index 00000000..04027520 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_gls.c @@ -0,0 +1,195 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_gls.c +* @brief GATT built-in GLS (Glucose Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#include + +#ifndef __GATTSVC_GLS_H +#include +#endif + + +/** + * @brief service definition. + * + * Glucose Servic + */ +const T_ATTRIB_APPL gatt_svc_gls[] = +{ + /** Primary Service>>, .. */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_GLUCOSE), /**< service UUID */ + HI_WORD(GATT_UUID_GLUCOSE) + }, + UUID_16BIT_SIZE, /**< bValueLen */ + NULL, /**< p_value_context */ + GATT_PERM_READ /**< permissions */ + }, + + /** Characteristic*/ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_NOTIFY, /**< characteristic properties */ + //XXXXMJMJ GATT_CHAR_PROP_INDICATE, /**< characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Glucose Measurement characteristic value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_GLS_MEASUREMENT), + HI_WORD(GATT_UUID_CHAR_GLS_MEASUREMENT) + }, + 0, /**< variable size */ + (void *)NULL, + GATT_PERM_NONE /**< permissions */ + }, + /** client characteristic configuration */ + { + (ATTRIB_FLAG_VALUE_INCL | /**< flags */ + ATTRIB_FLAG_CCCD_APPL), + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + /* NOTE: this value has an instantiation for each client, a write to */ + /* this attribute does not modify this default value: */ + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /** + +#ifdef __cplusplus +extern "C" { +#endif + + +/** service definition */ +extern const T_ATTRIB_APPL gatt_svc_gls[]; + +extern const int gatt_svc_gls_size; +extern const int gatt_svc_gls_nbr_of_attrib; + +/** GLC Glucose Service */ +#define GATT_UUID_GLUCOSE 0x1808 + +#define GATT_UUID_CHAR_GLS_MEASUREMENT 0x2A18 +#define GATT_UUID_CHAR_GLS_MEASUREMENT_CTXT 0x2A34 +#define GATT_UUID_CHAR_GLS_FEATURES 0x2A51 +#define GATT_UUID_CHAR_GLS_RACP 0x2A52 +/** attribute indices signaled to GATT server application. */ +/** do NOT change these values !!!! */ + +#define GATT_SVC_GLS_MEASUREMENT_INDEX 2 /**< index measurement value */ +#define GATT_SVC_GLS_MEASUREMENT_CCCD_INDEX 3 /**< index of CCCD */ +#define GATT_SVC_GLS_MEASUREMENT_CTXT_INDEX 5 /**< index measurement context value */ +#define GATT_SVC_GLS_MEASUREMENT_CTXT_CCCD_INDEX 6 /**< index of CCCD */ +#define GATT_SVC_GLS_FEATURE_INDEX 8 /**< index of feature value */ +#define GATT_SVC_GLS_RACP_INDEX 10 /**< index of RACP value */ +#define GATT_SVC_GLS_RACP_CCCD_INDEX 11 /**< index of CCCD */ + + +#ifdef __cplusplus +} +#endif + +#endif /**< __GATTSVC_GLS_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_ndcs.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_ndcs.c new file mode 100644 index 00000000..f050169b --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_ndcs.c @@ -0,0 +1,69 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_ndcs.c +* @brief GATT built-in NDCS (Next DST (Daylight Saving Time) Change Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#include + +#ifndef __GATTSVC_NDCS_H +#include +#endif + +/** + * @brief service definition. + * + * Next DST (Daylight Saving Time) Change Service + */ +const T_ATTRIB_APPL gatt_svc_ndcs[] = +{ + /** Primary Service */ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_NEXT_DST_CHANGE), /**< service UUID */ + HI_WORD(GATT_UUID_NEXT_DST_CHANGE) + }, + UUID_16BIT_SIZE, /**< bValueLen */ + NULL, /**< p_value_context */ + GATT_PERM_READ /**< permissions */ + }, + + /** Characteristic */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /**< characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Time with DST value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_NDCS_TIME_WITH_DST), + HI_WORD(GATT_UUID_CHAR_NDCS_TIME_WITH_DST) + }, + 8, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + } +}; + +const int gatt_svc_ndcs_size = sizeof(gatt_svc_ndcs); +const int gatt_svc_ndcs_nbr_of_attrib = sizeof(gatt_svc_ndcs) / sizeof(T_ATTRIB_APPL); + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_ndcs.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_ndcs.h new file mode 100644 index 00000000..e496d0a4 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_ndcs.h @@ -0,0 +1,43 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_ndcs.h +* @brief GATT built-in NDCS (Next DST (Daylight Saving Time) Change Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#ifndef __GATTSVC_NDCS_H +#define __GATTSVC_NDCS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/** service definition */ +extern const T_ATTRIB_APPL gatt_svc_ndcs[]; + +extern const int gatt_svc_ndcs_size; +extern const int gatt_svc_ndcs_nbr_of_attrib; +/** NDCS Next DST Change Service */ +#define GATT_UUID_NEXT_DST_CHANGE 0x1807 + +#define GATT_UUID_CHAR_NDCS_TIME_WITH_DST 0x2A11 +/** attribute indices signaled to GATT server application. */ +/** do NOT change these values !!!! */ + +#define GATT_SVC_NDCS_TIME_WITH_DST_INDEX 2 /**< Time with DST value */ + + +#ifdef __cplusplus +} +#endif + +#endif /**< __GATTSVC_NDCS_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_rtus.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_rtus.c new file mode 100644 index 00000000..b980e667 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_rtus.c @@ -0,0 +1,91 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_rtus.c +* @brief GATT built-in RTUS (Reference Time Update Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#include +#include + +/** + * @brief service definition. + * + * Reference Time Update Service + */ +const T_ATTRIB_APPL gatt_svc_rtus[] = +{ + /** Primary Service*/ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(GATT_UUID_REFERENCE_TIME_UPDATE), /**< service UUID */ + HI_WORD(GATT_UUID_REFERENCE_TIME_UPDATE) + }, + UUID_16BIT_SIZE, /**< bValueLen */ + NULL, /**< p_value_context */ + GATT_PERM_READ /**< permissions */ + }, + + /** Characteristic */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_WRITE_NO_RSP /**< characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Time Update Control Point value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_RTUS_CONTROL_POINT), + HI_WORD(GATT_UUID_CHAR_RTUS_CONTROL_POINT) + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_WRITE /**< permissions */ + }, + + /** Characteristic */ + { + ATTRIB_FLAG_VALUE_INCL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ /**< characteristic properties */ + /* characteristic UUID not needed here, is UUID of next attrib. */ + }, + 1, /**< bValueLen */ + NULL, + GATT_PERM_READ /**< permissions */ + }, + /** Time Update State value */ + { + ATTRIB_FLAG_VALUE_APPL, /**< flags */ + { /**< type_value */ + LO_WORD(GATT_UUID_CHAR_RTUS_STATE), + HI_WORD(GATT_UUID_CHAR_RTUS_STATE) + }, + 2, /**< bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + } +}; + +const int gatt_svc_rtus_size = sizeof(gatt_svc_rtus); +const int gatt_svc_rtus_nbr_of_attrib = sizeof(gatt_svc_rtus) / sizeof(T_ATTRIB_APPL); + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_rtus.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_rtus.h new file mode 100644 index 00000000..c1f61aa6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/gattsvc_rtus.h @@ -0,0 +1,47 @@ +/** +******************************************************************************************************** +Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file Gattsvc_rtus.h +* @brief GATT built-in RTUS (Reference Time Update Service) +* @details +* +* @author gordon +* @date 2015-07-09 +* @version v0.1 +*/ + +#ifndef __GATTSVC_RTUS_H +#define __GATTSVC_RTUS_H + +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** service definition */ +extern const T_ATTRIB_APPL gatt_svc_rtus[]; + +extern const int gatt_svc_rtus_size; +extern const int gatt_svc_rtus_nbr_of_attrib; + +/** RTUS Reference Time Update Service */ +#define GATT_UUID_REFERENCE_TIME_UPDATE 0x1806 + +#define GATT_UUID_CHAR_RTUS_CONTROL_POINT 0x2A16 +#define GATT_UUID_CHAR_RTUS_STATE 0x2A17 +/** attribute indices signaled to GATT server application. */ +/** do NOT change these values !!!! */ + +#define GATT_SVC_RTUS_CONTROL_POINT_INDEX 2 /**< Time UpdateControl Point value */ +#define GATT_SVC_RTUS_STATE_INDEX 4 /**< Time Update State value */ + + +#ifdef __cplusplus +} +#endif + +#endif /**< __GATTSVC_RTUS_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/service/hrp_service.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/hrp_service.c new file mode 100644 index 00000000..0a6bb918 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/service/hrp_service.c @@ -0,0 +1,208 @@ +/* find me service for ltp to register service */ +#include "hrp.h" +#include "gatt.h" + +uint8_t cha_val_v8_011[1] = {0x08}; +uint8_t cha_val_v8_d11[1] = {0x01}; +uint8_t cha_val_v8_d21[1] = {0x02}; +uint8_t cha_val_v8_d31[1] = {0x03}; + +const T_ATTRIB_APPL gatt_dfindme_profile[] = +{ + /*----------handle = 0x0008 {Service=0x1801 ("Attribute Profile")}---*/ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(0x1801), /* service UUID */ + HI_WORD(0x1801) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + + /* +++++++++++ handle = 0x0009 Characteristic -- Service Changed +++++++++++++ */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_INDICATE /* characteristic properties */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + + /* handle = 0x000a Characteristic value -- Service Changed */ + { + ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(0x2A05), + HI_WORD(0x2A05), + 0x01, + 0x00, + 0xff, + 0xff + }, + 4, /* bValueLen */ + NULL, + GATT_PERM_NOTIF_IND /* permissions */ + }, + + + /* handle = 0x000b Characteristic value -- Client Characteristic Configuration */ + + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + }, + + /*----------------- handle = 0x000c {{Service=0xA00B ("Service B.5")} -------------------*/ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(0xA00B), /* service UUID */ + HI_WORD(0xA00B) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + + /* +++++++++++ handle = 0x000d Characteristic -- Value V8 +++++++++++++ */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_READ | GATT_CHAR_PROP_WRITE /* characteristic properties */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + + /* handle = 0x000e Characteristic value -- Value V8 */ + { + ATTRIB_FLAG_VOID, /* flags */ + { /* type_value */ + LO_WORD(0xB008), + HI_WORD(0xB008), + }, + 1, /* bValueLen */ + (void *)cha_val_v8_011, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + }, + + + /* +++++++++++ handle = 0x000f Descriptor --Descriptor V5D1 +++++++++++++ */ + { + ATTRIB_FLAG_VOID, /* flags */ + { + LO_WORD(0xB015), + HI_WORD(0xB015), + }, + 1, /* bValueLen */ + (void *)cha_val_v8_d11, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + }, + + /* +++++++++++ handle = 0x0010 Descriptor --Descriptor V5D2 +++++++++++++ */ + { + ATTRIB_FLAG_VOID, /* flags */ + { + LO_WORD(0xB016), + HI_WORD(0xB016), + }, + 1, /* bValueLen */ + (void *)cha_val_v8_d21, + GATT_PERM_READ /* permissions */ + }, + + /* +++++++++++ handle = 0x0011 Descriptor --Descriptor V5D3 +++++++++++++ */ + { + ATTRIB_FLAG_VOID, /* flags */ + { + LO_WORD(0xB017), + HI_WORD(0xB017), + }, + 1, /* bValueLen */ + (void *)cha_val_v8_d31, + GATT_PERM_WRITE /* permissions */ + }, + + + /*----------------- handle = 0x0012 {Service = 0x180f (Battery Service)}-------------------*/ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_LE), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_PRIMARY_SERVICE), + HI_WORD(GATT_UUID_PRIMARY_SERVICE), + LO_WORD(0x180F), /* service UUID */ + HI_WORD(0x180F) + }, + UUID_16BIT_SIZE, /* bValueLen */ + NULL, /* p_value_context */ + GATT_PERM_READ /* permissions */ + }, + + /* +++++++++++ handle = 0x0013 Characteristic -- Value V8 +++++++++++++ */ + { + ATTRIB_FLAG_VALUE_INCL, /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHARACTERISTIC), + HI_WORD(GATT_UUID_CHARACTERISTIC), + GATT_CHAR_PROP_NOTIFY | GATT_CHAR_PROP_READ | GATT_CHAR_PROP_WRITE/* characteristic properties */ + }, + 1, /* bValueLen */ + NULL, + GATT_PERM_READ /* permissions */ + }, + + /* handle = 0x0014 Characteristic value -- Value V8 */ + { + ATTRIB_FLAG_VOID | ATTRIB_FLAG_VALUE_APPL, /* flags */ + { /* type_value */ + LO_WORD(0x2A19), + HI_WORD(0x2A19), + }, + 0, /* bValueLen */ + NULL, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + //lorna added GATT_PERM_WRITE for test BTIF_MSG_GATT_ATTR_WRITE_REQ_IND/CFM + }, + + /* handle = 0x0015 Characteristic value client Characteristic configuration*/ + { + (ATTRIB_FLAG_VALUE_INCL | ATTRIB_FLAG_CCCD_APPL), /* flags */ + { /* type_value */ + LO_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + HI_WORD(GATT_UUID_CHAR_CLIENT_CONFIG), + LO_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT), /* client char. config. bit field */ + HI_WORD(GATT_CLIENT_CHAR_CONFIG_DEFAULT) + }, + 2, /* bValueLen */ + NULL, + GATT_PERM_READ | GATT_PERM_WRITE /* permissions */ + }, + +}; + +const int gatt_dfindme_profile_size = sizeof(gatt_dfindme_profile); +const int gatt_svc_findme_nbr_of_attrib = sizeof(gatt_dfindme_profile) / sizeof(T_ATTRIB_APPL); + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/storage/gap_storage_le_int.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/storage/gap_storage_le_int.h new file mode 100644 index 00000000..b9f4850c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/storage/gap_storage_le_int.h @@ -0,0 +1,47 @@ +/** +********************************************************************************************************* +* Copyright(c) 2016, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file flash_key_mgr_le_int.h +* @brief key storage function. +* @details +* @author jane +* @date 2016-02-18 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef FLASH_KEY_MGR_LE_INT_H +#define FLASH_KEY_MGR_LE_INT_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include +#include + +void le_key_init(void); +uint8_t le_get_key(P_LE_KEY_ENTRY p_entry, T_BTIF_KEY_TYPE key_type, uint8_t *key); +bool le_save_key(P_LE_KEY_ENTRY p_entry, T_BTIF_KEY_TYPE key_type, uint8_t key_length, + uint8_t *key); +bool le_update_remote_bd(P_LE_KEY_ENTRY p_entry, uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE bd_type); +P_LE_KEY_ENTRY le_allocate_key_entry(uint8_t *bd_addr, T_BTIF_REMOTE_ADDR_TYPE bd_type); +void le_clear_all_keys(void); +void le_delete_bond(P_LE_KEY_ENTRY p_entry); + +bool le_get_cccd_data(P_LE_KEY_ENTRY p_entry, P_LE_CCCD p_data); +bool le_save_cccd_data(P_LE_KEY_ENTRY p_entry, P_LE_CCCD p_data); +bool le_add_cccd_data(P_LE_KEY_ENTRY p_entry, uint8_t add_size, uint8_t offset, uint8_t *p_data); + + +P_LE_KEY_ENTRY le_find_entry_by_aes(uint8_t *unresolved_addr, uint8_t addr_type); +bool le_check_local_resolved_address(uint8_t *unresolved_addr, uint8_t *local_irk); + +#ifdef __cplusplus +} +#endif + +#endif /* FLASH_KEY_MGR_LE_INT_H */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart.h b/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart.h new file mode 100644 index 00000000..c953da8d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart.h @@ -0,0 +1,30 @@ +/** +********************************************************************************************************* +* Copyright(c) 2014, Realtek Semiconductor Corporation. All rights reserved. +********************************************************************************************************* +* @file aci_low_power.h +* @brief low power handle when using ACI. +* @details none. +* @author tifnan +* @date 2014-11-19 +* @version v0.1 +* ********************************************************************************************************* +*/ + +#ifndef _BTLTP_UART_BB3_H_ +#define _BTLTP_UART_BB3_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void TxAssistTask(void *pParameters); +void ltpPeripheralInit(void); +void ltpStartTransmit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _BTLTP_UART_BB3_H_ */ + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart_amebaz2.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart_amebaz2.c new file mode 100644 index 00000000..a2a53e2c --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart_amebaz2.c @@ -0,0 +1,598 @@ +#include "hrp.h" +#include "trace_app.h" +#include "os_msg.h" +#include "btltp_uart.h" +#include "serial_api.h" +#include "serial_ex_api.h" +#include "timer_api.h" +#if 0 +#include "ameba_soc.h" +#endif +#include "basic_types.h" +#if F_BT_DLPS_EN +#include "hrp_dlps.h" +#endif +static uint32_t hrp_rx_idle = 1; +#define UART_IRQ 12 +uint8_t RxTriggerLevel = 14; +#if 0 +UART_TypeDef *data_uart_def; +#endif + +static void *bb3_UarthandleEvent; +#define DATA_UART_TX_PIN PA_16 +#define DATA_UART_RX_PIN PA_15 +static serial_t ltpuart_sobj; +//#define LTP_TIM_PRESCALER 40 /* 40 bits timeout */ + +//#define LTP_BAUDRATE 115200 /* baudrate */ +gtimer_t my_timer3; +const unsigned char ltpEventUartRx = LTP_EVENT_UART_RX; +const unsigned char ltpEventUartTx = LTP_EVENT_UART_TX; +const unsigned char ltpEventUartTxCompleted = LTP_EVENT_UART_TX_COMPLETED; +/****************************************************************************/ +/** + * @brief send to ltp task to release tx buffer space. + * + * @param p_tx_buf, pointer to the tx bufer to be released. + * @return . +*/ +void LtpRxDataLengthUpdate(void); +bool ltpSendTxBufReleaseMsg(T_HRP_DATA *p_tx_buf) +{ + bool ReturnValue; + + ReturnValue = os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleTxRel, p_tx_buf, 0); + + return (ReturnValue); +} + +/** + * @brief send event to ltp task. + * + * @param pEvent, pointer to the event to b sent. + * @return send result. + * @retval true--send successfully. + * false-- queue is full. +*/ +bool ltpSendEventMsg(const unsigned char *pEvent) +{ + bool ReturnValue; + + ReturnValue = os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleEvent, (void *)pEvent, 0); + return (ReturnValue); +} + +static inline void uart_hrp_insert_char(uint8_t ch) +{ + /* Should neve happen */ + P_BtHrp->p_aci_tcb->P_RxBuffer[0] = ch; + P_BtHrp->p_aci_tcb->P_RxBuffer ++; + if (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] >= RX_BUFFER_SIZE) + { + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + } + + LtpRxDataLengthUpdate(); +} + + +/** + * @brief tx task, tx bytes in polling mode. + * + * @param pParameters, not used. + * @return void. +*/ +void TxAssistTask(void *pParameters) +{ + uint32_t i = 0; + uint8_t *pBuffer = NULL; + uint8_t event = 0; + uint16_t blk_count = 0; + T_HRP_DATA data = {NULL, 0}; + + while (true) + { + // if (os_sem_take(bb3_UarthandleEvent, 0xFFFFFFFF) == true) + // { + + if (os_msg_recv(P_BtHrp->p_aci_tcb->QueueHandleTxData, &data, 0xFFFFFFFF) == true) + { + pBuffer = data.pBuffer; + blk_count = data.Length; + // dbg_printf("TxAssistTask: send %d\r\n", data.Length); + serial_send_blocked(<puart_sobj, pBuffer, blk_count, 0xffffffff); + +#if 0 + for (i = 0; i < blk_count; i++) + { + //while (UART_GetFlagState(UART, UART_FLAG_THR_EMPTY) != SET); + //UART_SendData(data_uart_def, pBuffer, 16); + pBuffer += 16; + } + + //the ramain data + blk_count = data.Length % 16; + + if (blk_count) + { + //while (UART_GetFlagState(UART, UART_FLAG_THR_EMPTY) != SET); + // UART_SendData(data_uart_def, pBuffer, blk_count); + + serial_putc(); + } +#endif + + if (false == ltpSendTxBufReleaseMsg(&data)) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("ltpSendTxBufReleaseMsg fail"); + } + } + event = LTP_EVENT_UART_TX_COMPLETED; + if (false == ltpSendEventMsg(&event)) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("hrp_send_event(TX_COMPLETED) fail"); + } + } +#if 0 + if (hrp_dlps_status == HRP_DLPS_STATUS_ACTIVED) + { + uint32_t msg_num; + os_msg_queue_peek(P_BtHrp->p_aci_tcb->QueueHandleTxData, &msg_num); + if (msg_num == 0) + { + hrp_dlps_allow_enter(true); /* no data to be sent*/ + //APP_PRINT_INFO0("TxAssistTask allow enter dlps"); + } + } +#endif + +#if ACI_LP_EN + /* reset moniter timer */ + if (MoniterTimer) + { + xTimerReset(MoniterTimer, 5); + MonitorTimeout = 0; + } +#endif + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("TxAssistTask: xQueueReceive fail"); + } + } + //} + } +} + +/** + * @brief update rx data length when received data from uart or spi. + * + * @param none. + * @return none. + * @retval void. +*/ +void LtpRxDataLengthUpdate(void) +{ + uint16_t RxOffset = 0; + uint16_t Length = 0; + +#if 1 + RxOffset = P_BtHrp->p_aci_tcb->P_RxBuffer - + &P_BtHrp->p_aci_tcb->p_rx_buf[0]; /* tifnan: num of char received */ +#endif + /* will not occur in our uart framework!!! */ + if (P_BtHrp->p_aci_tcb->RxOffset == RxOffset) + { + if (P_BtHrp->p_aci_tcb->RxDataLength == RX_BUFFER_SIZE) /* overrun */ + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("LtpRxDataLengthUpdate: Rx overrun"); + } + + P_BtHrp->p_aci_tcb->RxDataLength = 0; + Length = RX_BUFFER_SIZE; + } + else + { + return; /* no data */ + } + } + else + { + /* [p_aci_tcb->RxOffset----RxBufferSize-1] + [P_BtLtp->p_aci_tcb->p_rx_buf[0]----RxOffset] */ + if (P_BtHrp->p_aci_tcb->RxOffset > RxOffset) + { + Length = RX_BUFFER_SIZE - P_BtHrp->p_aci_tcb->RxOffset + RxOffset; + } + /* [p_aci_tcb->RxOffset ---- RxOffset] */ + else + { + Length = RxOffset - P_BtHrp->p_aci_tcb->RxOffset; + } + + /* update new P_BtHrp->p_aci_tcb->RxOffset */ + P_BtHrp->p_aci_tcb->RxOffset = RxOffset; + } + + if ((Length + P_BtHrp->p_aci_tcb->RxDataLength) > RX_BUFFER_SIZE) /* Rx overrun */ + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR1("LtpRxDataLengthUpdate: Rx overrun (%d)", + Length + P_BtHrp->p_aci_tcb->RxDataLength); + } + + P_BtHrp->p_aci_tcb->RxDataLength = RX_BUFFER_SIZE; + P_BtHrp->p_aci_tcb->RxWriteIndex += Length; + P_BtHrp->p_aci_tcb->RxWriteIndex &= (RX_BUFFER_SIZE - 1); + P_BtHrp->p_aci_tcb->RxReadIndex = P_BtHrp->p_aci_tcb->RxWriteIndex; + } + else + { + P_BtHrp->p_aci_tcb->RxDataLength += Length; /* update length */ + P_BtHrp->p_aci_tcb->RxWriteIndex += Length; + P_BtHrp->p_aci_tcb->RxWriteIndex &= (RX_BUFFER_SIZE - 1); + } +} + +/** + * @brief uart interrupt handle ISR. + * + * @param none. + * @return none. + * @retval void. +*/ +void data_uart_irq(uint32_t id, SerialIrq event) +{ + uint8_t rx_char; + uint8_t ltp_event = LTP_EVENT_UART_RX; + int max_count = 16; + + serial_t *sobj = (void *)id; + if (event == RxIrq) + { + /* For reading the remaining in rx fifo if time-out */ + gtimer_reload(&my_timer3, 2000); + do + { + rx_char = serial_getc(sobj); + uart_hrp_insert_char(rx_char); + } + while (serial_readable(sobj) && max_count-- > 0); + + if (hrp_rx_idle) + { + if (false == ltpSendEventMsg(<p_event)) + { + APP_PRINT_ERROR1("ltpSendEventMsg fai %d", ltp_event); + } + } + hrp_rx_idle = 0; + } +#if 0 + volatile u8 reg_iir; + u8 int_id; + u32 reg_val; + uint8_t event = LTP_EVENT_UART_RX; + reg_iir = UART_IntStatus(data_uart_def); + if ((reg_iir & RUART_IIR_INT_PEND) != 0) + { + /* No pending IRQ */ + return 0; + } + + int_id = (reg_iir & RUART_IIR_INT_ID) >> 1; + + switch (int_id) + { + case RUART_RECEIVER_DATA_AVAILABLE: + if ((P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] + RxTriggerLevel)\ + <= RX_BUFFER_SIZE) + { + UART_ReceiveData(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel); + P_BtHrp->p_aci_tcb->P_RxBuffer += RxTriggerLevel; + } + else + { + uint16_t len = 0; + len = RX_BUFFER_SIZE - (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0]); + UART_ReceiveData(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer, len); + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + UART_ReceiveData(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel - len); + P_BtHrp->p_aci_tcb->P_RxBuffer += (RxTriggerLevel - len); + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fail"); + } + break; + case RUART_TIME_OUT_INDICATION: + /* read out all bytes in fifo */ + while (UART_Readable(data_uart_def)) + { + if (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] == RX_BUFFER_SIZE) + { + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + } + UART_CharGet(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer); + P_BtHrp->p_aci_tcb->P_RxBuffer++; + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fai"); + } + break; + + case RUART_RECEIVE_LINE_STATUS: + reg_val = (UART_LineStatusGet(data_uart_def)); + APP_PRINT_INFO1("data_uart_irq: LSR %08x interrupt", reg_val); + + if (reg_val & RUART_LINE_STATUS_ERR_OVERRUN) + { + APP_PRINT_ERROR0("data_uart_irq: LSR over run interrupt"); + } + + if (reg_val & RUART_LINE_STATUS_ERR_PARITY) + { + APP_PRINT_ERROR0("data_uart_irq: LSR parity error interrupt"); + } + + if (reg_val & RUART_LINE_STATUS_ERR_FRAMING) + { + APP_PRINT_ERROR0("data_uart_irq: LSR frame error(stop bit error) interrupt"); + } + + if (reg_val & RUART_LINE_STATUS_ERR_BREAK) + { + APP_PRINT_ERROR0("data_uart_irq: LSR break error interrupt"); + } + + /* if (reg_val & RUART_LINE_STATUS_REG_THRE) + * transmit_chars(hci_adapter); + */ + + break; + + default: + HCI_PRINT_ERROR1("data_uart_irq: Unknown interrupt type %u", int_id); + break; + } +#endif + //return 0; +} +#if 0 +void UART0_Handler(void) +{ + /* read interrupt status */ + uint32_t int_status; + uint8_t event = LTP_EVENT_UART_RX; + /* read interrupt id */ + int_status = UART_GetIID(UART); + /* disable interrupt */ + UART_INTConfig(UART, UART_INT_RD_AVA | UART_INT_LINE_STS, DISABLE); + + switch (int_status) + { + /* tx fifo empty */ + case UART_INT_ID_TX_EMPTY: + break; + + /* rx data valiable */ + case UART_INT_ID_RX_LEVEL_REACH: + if ((P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] + RxTriggerLevel)\ + <= RX_BUFFER_SIZE) + { + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel); + P_BtHrp->p_aci_tcb->P_RxBuffer += RxTriggerLevel; + } + else + { + uint16_t len = 0; + len = RX_BUFFER_SIZE - (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0]); + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, len); + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel - len); + P_BtHrp->p_aci_tcb->P_RxBuffer += (RxTriggerLevel - len); + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fail"); + } + break; + + /* rx time out */ + case UART_INT_ID_RX_TMEOUT: + /* read out all bytes in fifo */ + while (UART_GetFlagState(UART, UART_FLAG_RX_DATA_RDY) == SET) + { + if (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] == RX_BUFFER_SIZE) + { + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + } + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, 1); + P_BtHrp->p_aci_tcb->P_RxBuffer++; + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fai"); + } + break; + + /* receive line status interrupt */ + case UART_INT_ID_LINE_STATUS: + APP_PRINT_ERROR0("Line status error!"); + break; + + default: + break; + } + + /* enable interrupt again */ + //UART_INTConfig(UART, UART_INT_RD_AVA | UART_INT_LINE_STS, ENABLE); + UART_INTConfig(UART, UART_INT_RD_AVA, ENABLE); +} +#endif + +void ltpStartTransmit(void) +{ + +#if 0 + if (P_BtHrp->p_aci_tcb->TxData.pBuffer == (uint8_t)0 && + xQueueReceive(P_BtHrp->p_aci_tcb->QueueHandleTxData, &P_BtHrp->p_aci_tcb->TxData, 0) == pdPASS) + { + P_BtHrp->p_aci_tcb->DMA_Tx_InitStructure.DMA_MemoryBaseAddr = (uint32_t) + P_BtHrp->p_aci_tcb->TxData.pBuffer; + P_BtHrp->p_aci_tcb->DMA_Tx_InitStructure.DMA_BufferSize = P_BtHrp->p_aci_tcb->TxData.Length; + +#if 0 + DMA_Init(DMA1_Channel4, &P_BtHrp->p_aci_tcb->DMA_Tx_InitStructure); + + DMA_ITConfig(DMA1_Channel4, (DMA_IT_TC | DMA_IT_TE), ENABLE); + USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); + DMA_Cmd(DMA1_Channel4, ENABLE); + + GDMA_INTConfig(AciTxDMAChannelNum, GDMA_INT_Transfer, ENABLE); + GDMA_SetSourceAddress(AciTxDMAChannel, (uint32_t)P_BtHrp->p_aci_tcb->TxData.pBuffer); + GDMA_SetBufferSize(AciTxDMAChannel, P_BtHrp->p_aci_tcb->TxData.Length); + GDMA_Cmd(AciTxDMAChannelNum, ENABLE); +#endif + int ret; + ret = serial_send_stream(<puart_sobj, P_BtHrp->p_aci_tcb->TxData.pBuffer, + P_BtHrp->p_aci_tcb->TxData.Length); + if (ret != 0) + { + dbg_printf("%s Error(%d)\n", __FUNCTION__, ret); + } + } +#endif + +} +void timer3_timeout_handler(uint32_t id) +{ + serial_t *sobj = (void *)id; + uint16_t rx_len = 0; + uint8_t ch; + uint32_t s; + uint8_t ltp_event = LTP_EVENT_UART_RX; + // s=os_lock(); + + while (serial_readable(sobj)) + { + ch = serial_getc(sobj); + uart_hrp_insert_char(ch); + rx_len++; + + } + + /* If use hci_comuart.rx_data_len to check, the rx event queue will be full + */ + if (rx_len > 0 || hrp_rx_idle == 0) + { + if (false == ltpSendEventMsg(<p_event)) + { + APP_PRINT_ERROR1("ltpSendEventMsg fai %d", ltp_event); + } + } + hrp_rx_idle = 1; + +// os_unlock(s); +} +void ltpPeripheralInit(void) +{ + + hal_pinmux_unregister(DATA_UART_TX_PIN, 0x01 << 4); + hal_pinmux_unregister(DATA_UART_RX_PIN, 0x01 << 4); + hal_gpio_pull_ctrl(DATA_UART_TX_PIN, 0); + hal_gpio_pull_ctrl(DATA_UART_RX_PIN, 0); + serial_init(<puart_sobj, DATA_UART_TX_PIN, DATA_UART_RX_PIN); + serial_baud(<puart_sobj, 115200); + serial_format(<puart_sobj, 8, ParityNone, 1); + serial_irq_handler(<puart_sobj, data_uart_irq, (uint32_t)<puart_sobj); + serial_irq_set(<puart_sobj, RxIrq, 0); + serial_irq_set(<puart_sobj, RxIrq, 1); + //serial_irq_set(<puart_sobj, TxIrq, 1); + serial_rx_fifo_level(<puart_sobj, FifoLvHalf); + //serial_irq_set(<puart_sobj, TxIrq, 1); + serial_clear_rx(<puart_sobj); + + gtimer_init(&my_timer3, TIMER3); + gtimer_start_periodical(&my_timer3, 2000, (void *)timer3_timeout_handler, (uint32_t)<puart_sobj); + + // os_sem_create(&bb3_UarthandleEvent, 1, 1); + +#if 0 + //Config DATA UART0 pinmux + RCC_PeriphClockCmd(APBPeriph_UART0, APBPeriph_UART0_CLOCK, ENABLE); + Pinmux_Config(DATA_UART_TX_PIN, UART0_TX); + Pinmux_Config(DATA_UART_RX_PIN, UART0_RX); + Pad_Config(DATA_UART_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, + PAD_OUT_HIGH); + Pad_Config(DATA_UART_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, + PAD_OUT_LOW); + + /* uart init */ + UART_InitTypeDef uartInitStruct; + UART_StructInit(&uartInitStruct); + uartInitStruct.rxTriggerLevel = UART_RX_FIFO_TRIGGER_LEVEL_14BYTE; + UART_Init(UART, &uartInitStruct); + UART_INTConfig(UART, UART_INT_RD_AVA, ENABLE); + + /* Enable UART IRQ */ + NVIC_InitTypeDef nvic_init_struct; + nvic_init_struct.NVIC_IRQChannel = UART0_IRQn; + nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; + nvic_init_struct.NVIC_IRQChannelPriority = 5; + NVIC_Init(&nvic_init_struct); +#endif +#if 0 + IRQn_Type irqn = UART0_IRQ; + UART_InitTypeDef UART_InitStruct; + + data_uart_def = UART0_DEV; + + //UART_PinMuxInit(0, S0); + UART_StructInit(&UART_InitStruct); + UART_InitStruct.WordLen = RUART_WLS_8BITS; + UART_InitStruct.StopBit = RUART_STOP_BIT_1; + UART_InitStruct.Parity = RUART_PARITY_DISABLE; + UART_InitStruct.ParityType = RUART_EVEN_PARITY; + UART_InitStruct.StickParity = RUART_STICK_PARITY_DISABLE; + UART_InitStruct.RxFifoTrigLevel = UART_RX_FIFOTRIG_LEVEL_14BYTES; + UART_InitStruct.FlowControl = FALSE; + UART_Init(data_uart_def, &UART_InitStruct); + UART_SetBaud(data_uart_def, 115200); + + InterruptDis(irqn); + InterruptUnRegister(irqn); + InterruptRegister((IRQ_FUN)data_uart_irq, irqn, NULL, DATAUART_IRQ_PRIO); + InterruptEn(irqn, DATAUART_IRQ_PRIO); + UART_INTConfig(data_uart_def, RUART_IER_ERBI | RUART_IER_ETOI | RUART_IER_ELSI, ENABLE); + + UART_RxCmd(data_uart_def, ENABLE); +#endif +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart_bb3.c b/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart_bb3.c new file mode 100644 index 00000000..888ff168 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/hrp/uart/btltp_uart_bb3.c @@ -0,0 +1,484 @@ +#include "hrp.h" +#include "trace_app.h" +#include "os_msg.h" +#include "btltp_uart.h" +#include "ameba_soc.h" + +#if F_BT_DLPS_EN +#include "hrp_dlps.h" +#endif + +#define UART_IRQ 12 +uint8_t RxTriggerLevel = 14; +UART_TypeDef *data_uart_def; + +#define DATA_UART_TX_PIN P2_4 +#define DATA_UART_RX_PIN P2_5 +//#define LTP_TIM_PRESCALER 40 /* 40 bits timeout */ + +//#define LTP_BAUDRATE 115200 /* baudrate */ + +const unsigned char ltpEventUartRx = LTP_EVENT_UART_RX; +const unsigned char ltpEventUartTx = LTP_EVENT_UART_TX; +const unsigned char ltpEventUartTxCompleted = LTP_EVENT_UART_TX_COMPLETED; +/****************************************************************************/ +/** + * @brief send to ltp task to release tx buffer space. + * + * @param p_tx_buf, pointer to the tx bufer to be released. + * @return . +*/ +bool ltpSendTxBufReleaseMsg(T_HRP_DATA *p_tx_buf) +{ + bool ReturnValue; + + ReturnValue = os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleTxRel, p_tx_buf, 0); + + return (ReturnValue); +} + +/** + * @brief send event to ltp task. + * + * @param pEvent, pointer to the event to b sent. + * @return send result. + * @retval true--send successfully. + * false-- queue is full. +*/ +bool ltpSendEventMsg(const unsigned char *pEvent) +{ + bool ReturnValue; + + ReturnValue = os_msg_send(P_BtHrp->p_aci_tcb->QueueHandleEvent, (void *)pEvent, 0); + return (ReturnValue); +} + +/** + * @brief tx task, tx bytes in polling mode. + * + * @param pParameters, not used. + * @return void. +*/ +void TxAssistTask(void *pParameters) +{ + uint32_t i = 0; + uint8_t *pBuffer = NULL; + uint8_t event = 0; + uint16_t blk_count = 0; + T_HRP_DATA data = {NULL, 0}; + + while (true) + { + if (os_msg_recv(P_BtHrp->p_aci_tcb->QueueHandleTxData, &data, 0xFFFFFFFF) == true) + { + pBuffer = data.pBuffer; + blk_count = data.Length / 16; + + for (i = 0; i < blk_count; i++) + { + //while (UART_GetFlagState(UART, UART_FLAG_THR_EMPTY) != SET); + UART_SendData(data_uart_def, pBuffer, 16); + pBuffer += 16; + } + + //the ramain data + blk_count = data.Length % 16; + + if (blk_count) + { + //while (UART_GetFlagState(UART, UART_FLAG_THR_EMPTY) != SET); + UART_SendData(data_uart_def, pBuffer, blk_count); + } + + if (false == ltpSendTxBufReleaseMsg(&data)) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("ltpSendTxBufReleaseMsg fail"); + } + } + event = LTP_EVENT_UART_TX_COMPLETED; + if (false == ltpSendEventMsg(&event)) + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("hrp_send_event(TX_COMPLETED) fail"); + } + } +#if F_BT_DLPS_EN + if (hrp_dlps_status == HRP_DLPS_STATUS_ACTIVED) + { + uint32_t msg_num; + os_msg_queue_peek(P_BtHrp->p_aci_tcb->QueueHandleTxData, &msg_num); + if (msg_num == 0) + { + hrp_dlps_allow_enter(true); /* no data to be sent*/ + //APP_PRINT_INFO0("TxAssistTask allow enter dlps"); + } + } +#endif + +#if ACI_LP_EN + /* reset moniter timer */ + if (MoniterTimer) + { + xTimerReset(MoniterTimer, 5); + MonitorTimeout = 0; + } +#endif + } + else + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("TxAssistTask: xQueueReceive fail"); + } + } + } + +} + +/** + * @brief update rx data length when received data from uart or spi. + * + * @param none. + * @return none. + * @retval void. +*/ +void LtpRxDataLengthUpdate(void) +{ + uint16_t RxOffset = 0; + uint16_t Length = 0; + +#ifdef PLATFORM_STO + RxOffset = RX_BUFFER_SIZE - AciRxDMAChannel->CTL_HIGH ; +#endif + +#if 1 + RxOffset = P_BtHrp->p_aci_tcb->P_RxBuffer - + &P_BtHrp->p_aci_tcb->p_rx_buf[0]; /* tifnan: num of char received */ +#endif + /* will not occur in our uart framework!!! */ + if (P_BtHrp->p_aci_tcb->RxOffset == RxOffset) + { + if (P_BtHrp->p_aci_tcb->RxDataLength == RX_BUFFER_SIZE) /* overrun */ + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR0("LtpRxDataLengthUpdate: Rx overrun"); + } + + P_BtHrp->p_aci_tcb->RxDataLength = 0; + Length = RX_BUFFER_SIZE; + } + else + { + return; /* no data */ + } + } + else + { + /* [p_aci_tcb->RxOffset----RxBufferSize-1] + [P_BtLtp->p_aci_tcb->p_rx_buf[0]----RxOffset] */ + if (P_BtHrp->p_aci_tcb->RxOffset > RxOffset) + { + Length = RX_BUFFER_SIZE - P_BtHrp->p_aci_tcb->RxOffset + RxOffset; + } + /* [p_aci_tcb->RxOffset ---- RxOffset] */ + else + { + Length = RxOffset - P_BtHrp->p_aci_tcb->RxOffset; + } + + /* update new P_BtHrp->p_aci_tcb->RxOffset */ + P_BtHrp->p_aci_tcb->RxOffset = RxOffset; + } + + if ((Length + P_BtHrp->p_aci_tcb->RxDataLength) > RX_BUFFER_SIZE) /* Rx overrun */ + { + if (P_AciConfig->ltp_trace_level >= LTP_TRACE_ERROR) + { + APP_PRINT_ERROR1("LtpRxDataLengthUpdate: Rx overrun (%d)", + Length + P_BtHrp->p_aci_tcb->RxDataLength); + } + + P_BtHrp->p_aci_tcb->RxDataLength = RX_BUFFER_SIZE; + P_BtHrp->p_aci_tcb->RxWriteIndex += Length; + P_BtHrp->p_aci_tcb->RxWriteIndex &= (RX_BUFFER_SIZE - 1); + P_BtHrp->p_aci_tcb->RxReadIndex = P_BtHrp->p_aci_tcb->RxWriteIndex; + } + else + { + P_BtHrp->p_aci_tcb->RxDataLength += Length; /* update length */ + P_BtHrp->p_aci_tcb->RxWriteIndex += Length; + P_BtHrp->p_aci_tcb->RxWriteIndex &= (RX_BUFFER_SIZE - 1); + } +} + +/** + * @brief uart interrupt handle ISR. + * + * @param none. + * @return none. + * @retval void. +*/ +u32 data_uart_irq(void *data) +{ + volatile u8 reg_iir; + u8 int_id; + u32 reg_val; + uint8_t event = LTP_EVENT_UART_RX; + reg_iir = UART_IntStatus(data_uart_def); + if ((reg_iir & RUART_IIR_INT_PEND) != 0) + { + /* No pending IRQ */ + return 0; + } + + int_id = (reg_iir & RUART_IIR_INT_ID) >> 1; + + switch (int_id) + { + case RUART_RECEIVER_DATA_AVAILABLE: + if ((P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] + RxTriggerLevel)\ + <= RX_BUFFER_SIZE) + { + UART_ReceiveData(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel); + P_BtHrp->p_aci_tcb->P_RxBuffer += RxTriggerLevel; + } + else + { + uint16_t len = 0; + len = RX_BUFFER_SIZE - (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0]); + UART_ReceiveData(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer, len); + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + UART_ReceiveData(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel - len); + P_BtHrp->p_aci_tcb->P_RxBuffer += (RxTriggerLevel - len); + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fail"); + } + break; + case RUART_TIME_OUT_INDICATION: + /* read out all bytes in fifo */ + while (UART_Readable(data_uart_def)) + { + if (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] == RX_BUFFER_SIZE) + { + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + } + UART_CharGet(data_uart_def, P_BtHrp->p_aci_tcb->P_RxBuffer); + P_BtHrp->p_aci_tcb->P_RxBuffer++; + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fai"); + } + break; + + case RUART_RECEIVE_LINE_STATUS: + reg_val = (UART_LineStatusGet(data_uart_def)); + APP_PRINT_INFO1("data_uart_irq: LSR %08x interrupt", reg_val); + + if (reg_val & RUART_LINE_STATUS_ERR_OVERRUN) + { + APP_PRINT_ERROR0("data_uart_irq: LSR over run interrupt"); + } + + if (reg_val & RUART_LINE_STATUS_ERR_PARITY) + { + APP_PRINT_ERROR0("data_uart_irq: LSR parity error interrupt"); + } + + if (reg_val & RUART_LINE_STATUS_ERR_FRAMING) + { + APP_PRINT_ERROR0("data_uart_irq: LSR frame error(stop bit error) interrupt"); + } + + if (reg_val & RUART_LINE_STATUS_ERR_BREAK) + { + APP_PRINT_ERROR0("data_uart_irq: LSR break error interrupt"); + } + + /* if (reg_val & RUART_LINE_STATUS_REG_THRE) + * transmit_chars(hci_adapter); + */ + + break; + + default: + APP_PRINT_ERROR1("data_uart_irq: Unknown interrupt type %u", int_id); + break; + } + + return 0; +} +#if 0 +void UART0_Handler(void) +{ + /* read interrupt status */ + uint32_t int_status; + uint8_t event = LTP_EVENT_UART_RX; + /* read interrupt id */ + int_status = UART_GetIID(UART); + /* disable interrupt */ + UART_INTConfig(UART, UART_INT_RD_AVA | UART_INT_LINE_STS, DISABLE); + + switch (int_status) + { + /* tx fifo empty */ + case UART_INT_ID_TX_EMPTY: + break; + + /* rx data valiable */ + case UART_INT_ID_RX_LEVEL_REACH: + if ((P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] + RxTriggerLevel)\ + <= RX_BUFFER_SIZE) + { + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel); + P_BtHrp->p_aci_tcb->P_RxBuffer += RxTriggerLevel; + } + else + { + uint16_t len = 0; + len = RX_BUFFER_SIZE - (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0]); + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, len); + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, RxTriggerLevel - len); + P_BtHrp->p_aci_tcb->P_RxBuffer += (RxTriggerLevel - len); + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fail"); + } + break; + + /* rx time out */ + case UART_INT_ID_RX_TMEOUT: + /* read out all bytes in fifo */ + while (UART_GetFlagState(UART, UART_FLAG_RX_DATA_RDY) == SET) + { + if (P_BtHrp->p_aci_tcb->P_RxBuffer - &P_BtHrp->p_aci_tcb->p_rx_buf[0] == RX_BUFFER_SIZE) + { + P_BtHrp->p_aci_tcb->P_RxBuffer = &P_BtHrp->p_aci_tcb->p_rx_buf[0]; + } + UART_ReceiveData(UART, P_BtHrp->p_aci_tcb->P_RxBuffer, 1); + P_BtHrp->p_aci_tcb->P_RxBuffer++; + } + + /* update rx data length */ + LtpRxDataLengthUpdate(); + /* notify ltp task */ + if (false == ltpSendEventMsg(&event)) + { + APP_PRINT_ERROR0("ltpSendEventMsg fai"); + } + break; + + /* receive line status interrupt */ + case UART_INT_ID_LINE_STATUS: + APP_PRINT_ERROR0("Line status error!"); + break; + + default: + break; + } + + /* enable interrupt again */ + //UART_INTConfig(UART, UART_INT_RD_AVA | UART_INT_LINE_STS, ENABLE); + UART_INTConfig(UART, UART_INT_RD_AVA, ENABLE); +} +#endif + +void ltpStartTransmit(void) +{ +#ifdef PLATFORM_STO + if (P_BtHrp->p_aci_tcb->TxData.pBuffer == (uint8_t)0 && + xQueueReceive(P_BtHrp->p_aci_tcb->QueueHandleTxData, &P_BtHrp->p_aci_tcb->TxData, 0) == pdPASS) + { + P_BtHrp->p_aci_tcb->DMA_Tx_InitStructure.DMA_MemoryBaseAddr = (uint32_t) + P_BtHrp->p_aci_tcb->TxData.pBuffer; + P_BtHrp->p_aci_tcb->DMA_Tx_InitStructure.DMA_BufferSize = P_BtHrp->p_aci_tcb->TxData.Length; + DMA_Init(DMA1_Channel4, &P_BtHrp->p_aci_tcb->DMA_Tx_InitStructure); + + DMA_ITConfig(DMA1_Channel4, (DMA_IT_TC | DMA_IT_TE), ENABLE); + USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); + DMA_Cmd(DMA1_Channel4, ENABLE); + + GDMA_INTConfig(AciTxDMAChannelNum, GDMA_INT_Transfer, ENABLE); + GDMA_SetSourceAddress(AciTxDMAChannel, (uint32_t)P_BtHrp->p_aci_tcb->TxData.pBuffer); + GDMA_SetBufferSize(AciTxDMAChannel, P_BtHrp->p_aci_tcb->TxData.Length); + GDMA_Cmd(AciTxDMAChannelNum, ENABLE); + } +#endif +} +#define DATAUART_IRQ_PRIO 11 +void ltpPeripheralInit(void) +{ +#if 0 + //Config DATA UART0 pinmux + RCC_PeriphClockCmd(APBPeriph_UART0, APBPeriph_UART0_CLOCK, ENABLE); + Pinmux_Config(DATA_UART_TX_PIN, UART0_TX); + Pinmux_Config(DATA_UART_RX_PIN, UART0_RX); + Pad_Config(DATA_UART_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, + PAD_OUT_HIGH); + Pad_Config(DATA_UART_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_DISABLE, + PAD_OUT_LOW); + + /* uart init */ + UART_InitTypeDef uartInitStruct; + UART_StructInit(&uartInitStruct); + uartInitStruct.rxTriggerLevel = UART_RX_FIFO_TRIGGER_LEVEL_14BYTE; + UART_Init(UART, &uartInitStruct); + UART_INTConfig(UART, UART_INT_RD_AVA, ENABLE); + + /* Enable UART IRQ */ + NVIC_InitTypeDef nvic_init_struct; + nvic_init_struct.NVIC_IRQChannel = UART0_IRQn; + nvic_init_struct.NVIC_IRQChannelCmd = ENABLE; + nvic_init_struct.NVIC_IRQChannelPriority = 5; + NVIC_Init(&nvic_init_struct); +#endif + IRQn_Type irqn = UART0_IRQ; + UART_InitTypeDef UART_InitStruct; + + data_uart_def = UART0_DEV; +//PIN TX:A_18 RX:PA 19 + Pinmux_Config(_PA_18, PINMUX_FUNCTION_UART); + Pinmux_Config(_PA_19, PINMUX_FUNCTION_UART); + + PAD_PullCtrl(_PA_18, GPIO_PuPd_UP); + PAD_PullCtrl(_PA_19, GPIO_PuPd_UP); + //UART_PinMuxInit(0, S0); + UART_StructInit(&UART_InitStruct); + UART_InitStruct.WordLen = RUART_WLS_8BITS; + UART_InitStruct.StopBit = RUART_STOP_BIT_1; + UART_InitStruct.Parity = RUART_PARITY_DISABLE; + UART_InitStruct.ParityType = RUART_EVEN_PARITY; + UART_InitStruct.StickParity = RUART_STICK_PARITY_DISABLE; + UART_InitStruct.RxFifoTrigLevel = UART_RX_FIFOTRIG_LEVEL_14BYTES; + UART_InitStruct.FlowControl = FALSE; + UART_Init(data_uart_def, &UART_InitStruct); + UART_SetBaud(data_uart_def, 115200); + + InterruptDis(irqn); + InterruptUnRegister(irqn); + InterruptRegister((IRQ_FUN)data_uart_irq, irqn, NULL, DATAUART_IRQ_PRIO); + InterruptEn(irqn, DATAUART_IRQ_PRIO); + UART_INTConfig(data_uart_def, RUART_IER_ERBI | RUART_IER_ETOI | RUART_IER_ELSI, ENABLE); + + UART_RxCmd(data_uart_def, ENABLE); +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_flags.h b/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_flags.h new file mode 100644 index 00000000..84c38749 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_flags.h @@ -0,0 +1,26 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_flags.h + * @brief This file is used to config app functions. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_FLAGS_H_ +#define _APP_FLAGS_H_ + +#define APP_TEST_BT_TRACE 1 +#define APP_TEST_RANDOM 1 +#define APP_TEST_OSIF 1 +#define APP_TEST_HCI_TP 1 +#define APP_TEST_FTL 1 +#define APP_TEST_FTL_COUNT 3 + + +#endif diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_task.c b/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_task.c new file mode 100644 index 00000000..603e31a7 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_task.c @@ -0,0 +1,112 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.c + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include "app_task.h" +#include +#include "porting_test_app.h" +#include "app_flags.h" +#include + + + +/** @defgroup PERIPH_APP_TASK Peripheral App Task + * @brief This file handles the implementation of application task related functions. + * + * Create App task and handle events & messages + * @{ + */ +/*============================================================================* + * Macros + *============================================================================*/ +#define APP_TASK_PRIORITY 1 //!< Task priorities +#define APP_TASK_STACK_SIZE 256 * 4 //!< Task stack size +#define MAX_NUMBER_OF_IO_MESSAGE 0x20 //!< IO message queue size +#define MAX_NUMBER_OF_EVENT_MESSAGE (MAX_NUMBER_OF_IO_MESSAGE) //!< Event message queue size + +/*============================================================================* + * Variables + *============================================================================*/ +void *app_task_handle; //!< APP Task handle +void *evt_queue_handle; //!< Event queue handle +void *io_queue_handle; //!< IO queue handle + +/*============================================================================* + * Functions + *============================================================================*/ +void app_main_task(void *p_param); + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init() +{ + os_task_create(&app_task_handle, "app", app_main_task, 0, APP_TASK_STACK_SIZE, + APP_TASK_PRIORITY); +} + +void app_send_msg(uint16_t sub_type) +{ + uint8_t event = EVENT_IO_TO_APP; + T_IO_MSG io_msg; + io_msg.type = IO_MSG_TYPE_QDECODE; + io_msg.subtype = sub_type; + + if (os_msg_send(io_queue_handle, &io_msg, 0) == false) + { + APP_PRINT_ERROR1("app_send_msg msg fail: subtype 0x%x", io_msg.subtype); + } + else if (os_msg_send(evt_queue_handle, &event, 0) == false) + { + APP_PRINT_ERROR1("app_send_msg event fail: subtype 0x%x", io_msg.subtype); + } +} +/** + * @brief App task to handle events & messages + * @param[in] p_param Parameters sending to the task + * @return void + */ +void app_main_task(void *p_param) +{ + uint8_t event; + os_msg_queue_create(&io_queue_handle, MAX_NUMBER_OF_IO_MESSAGE, sizeof(T_IO_MSG)); + os_msg_queue_create(&evt_queue_handle, MAX_NUMBER_OF_EVENT_MESSAGE, sizeof(uint8_t)); + + app_send_msg(1); + + while (true) + { + if (os_msg_recv(evt_queue_handle, &event, 0xFFFFFFFF) == true) + { + if (event == EVENT_IO_TO_APP) + { + T_IO_MSG io_msg; + if (os_msg_recv(io_queue_handle, &io_msg, 0) == true) + { + app_handle_io_msg(io_msg); + } + } + } + } +} + +/** @} */ /* End of group PERIPH_APP_TASK */ + + diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_task.h b/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_task.h new file mode 100644 index 00000000..8dfcd2ac --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/app_task.h @@ -0,0 +1,27 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file app_task.h + * @brief Routines to create App task and handle events & messages + * @author jane + * @date 2017-06-02 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ +#ifndef _APP_TASK_H_ +#define _APP_TASK_H_ + +extern void driver_init(void); + +/** + * @brief Initialize App task + * @return void + */ +void app_task_init(void); + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/ble_app_main.c b/component/common/bluetooth/realtek/sdk/src/app/porting_test/ble_app_main.c new file mode 100644 index 00000000..a6fb5b3d --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/ble_app_main.c @@ -0,0 +1,43 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file main.c + * @brief Source file for BLE peripheral project, mainly used for initialize modules + * @author jane + * @date 2017-06-12 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include "app_flags.h" + + +void task_init(void) +{ + app_task_init(); +} + +/** + * @brief Entry of APP code + * @return int (To avoid compile warning) + */ +int ble_app_main(void) +{ +#if APP_TEST_BT_TRACE + bt_trace_init(); +#endif + task_init(); + + return 0; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/bt_types.h b/component/common/bluetooth/realtek/sdk/src/app/porting_test/bt_types.h new file mode 100644 index 00000000..327a120e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/bt_types.h @@ -0,0 +1,702 @@ +/** + * Copyright (c) 2017, Realtek Semiconductor Corporation. All rights reserved. + */ + +#ifndef _BT_TYPES_H_ +#define _BT_TYPES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \defgroup BTTYPES BT Types + * + * \brief Defines BT related macros for the upper layers. + * + */ + + +/** + * bt_types.h + * + * \name BT_LE_LOCAL_SUPPORTED_FEATURES + * \brief BT LE Local Supported Features definitions. + * \anchor BT_LE_LOCAL_SUPPORTED_FEATURES + */ +/** + * \ingroup BTTYPES + */ +#define LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX0 0 + +#define LE_SUPPORT_FEATURES_ENCRYPTION_MASK_BIT ((uint8_t)0x01) +#define LE_SUPPORT_FEATURES_CONNPARA_REQ_PROC_MASK_BIT ((uint8_t)0x02) +#define LE_SUPPORT_FEATURES_EXTENDED_REJECTION_IND_MASK_BIT ((uint8_t)0x04) +#define LE_SUPPORT_FEATURES_SLAVE_INITIATED_FEATURE_EXCHANGE_MASK_BIT ((uint8_t)0x08) +#define LE_SUPPORT_FEATURES_LE_PING_MASK_BIT ((uint8_t)0x10) +#define LE_SUPPORT_FEATURES_LE_DATA_LENGTH_EXTENSION_MASK_BIT ((uint8_t)0x20) +#define LE_SUPPORT_FEATURES_LL_PRIVACY_MASK_BIT ((uint8_t)0x40) +#define LE_SUPPORT_FEATURES_EXTENDED_SCANNER_FILTER_POLICY_MASK_BIT ((uint8_t)0x80) + +#define LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX1 1 + +#define LE_SUPPORT_FEATURES_LE_2M_MASK_BIT ((uint8_t)0x01) +#define LE_SUPPORT_FEATURES_STABLE_MODULATION_INDEX_TX_MASK_BIT ((uint8_t)0x02) +#define LE_SUPPORT_FEATURES_STABLE_MODULATION_INDEX_RX_MASK_BIT ((uint8_t)0x04) +#define LE_SUPPORT_FEATURES_LE_CODED_PHY_MASK_BIT ((uint8_t)0x08) +#define LE_SUPPORT_FEATURES_LE_EXTENDED_ADV_BIT ((uint8_t)0x10) +#define LE_SUPPORT_FEATURES_LE_PERIODIC_ADV_MASK_BIT ((uint8_t)0x20) +#define LE_SUPPORT_FEATURES_CSA2_BIT ((uint8_t)0x40) +#define LE_SUPPORT_FEATURES_LE_POWER_CLASS1_MASK_BIT ((uint8_t)0x80) + +#define LE_SUPPORT_FEATURES_MASK_ARRAY_INDEX2 2 + +#define LE_SUPPORT_FEATURES_MIN_NUM_USED_CHANNEL_MASK_BIT ((uint8_t)0x01) + +/** + * bt_types.h + * + * \name BT_STACK_MODULE_ERROR + * \brief BT stack module error code mask. + * \anchor BT_STACK_MODULE_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define GAP_ERR 0x0000 +#define HCI_ERR 0x0100 +#define L2C_ERR 0x0200 +#define SDP_ERR 0x0300 +#define ATT_ERR 0x0400 +#define SM_ERR 0x0500 + +#define GATT_ERR 0x0C00 +#define APP_ERR 0x0D00 + +/** + * bt_types.h + * + * \name BT_HCI_ERROR + * \brief BT hci error code definitions. + * \anchor BT_HCI_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define HCI_SUCCESS 0x00 +#define HCI_ERR_UNKNOWN_CMD 0x01 +#define HCI_ERR_UNKNOWN_CONN_ID 0x02 +#define HCI_ERR_HARDWARE_FAIL 0x03 +#define HCI_ERR_PAGE_TIMEOUT 0x04 +#define HCI_ERR_AUTHEN_FAIL 0x05 +#define HCI_ERR_KEY_MISSING 0x06 +#define HCI_ERR_MEMORY_FULL 0x07 +#define HCI_ERR_CONN_TIMEOUT 0x08 +#define HCI_ERR_MAX_NUM_CONN 0x09 +#define HCI_ERR_MAX_NUM_SCO_CONN 0x0A /* 10 */ +#define HCI_ERR_ACL_CONN_EXIST 0x0B /* 11 */ +#define HCI_ERR_CMD_DISALLOWED 0x0C /* 12 */ +#define HCI_ERR_REJECT_LIMITED_RESOURCE 0x0D /* 13 */ +#define HCI_ERR_REJECT_SECURITY_REASON 0x0E /* 14 */ +#define HCI_ERR_REJECT_UNACCEPTABLE_ADDR 0x0F /* 15 */ +#define HCI_ERR_HOST_TIMEOUT 0x10 /* 16 */ +#define HCI_ERR_UNSUPPORTED_PARAM 0x11 /* 17 */ +#define HCI_ERR_INVALID_PARAM 0x12 /* 18 */ +#define HCI_ERR_REMOTE_USER_TERMINATE 0x13 /* 19 */ +#define HCI_ERR_REMOTE_LOW_RESOURCE 0x14 /* 20 */ +#define HCI_ERR_REMOTE_POWER_OFF 0x15 /* 21 */ +#define HCI_ERR_LOCAL_HOST_TERMINATE 0x16 /* 22 */ +#define HCI_ERR_REPEATED_ATTEMPTS 0x17 /* 23 */ +#define HCI_ERR_PARING_NOT_ALLOWED 0x18 /* 24 */ +#define HCI_ERR_UNKNOWN_LMP_PDU 0x19 /* 25 */ +#define HCI_ERR_UNSUPPORTED_REMOTE_FEAT 0x1A /* 26 */ +#define HCI_ERR_SCO_OFFSET_REJECTED 0x1B /* 27 */ +#define HCI_ERR_SCO_INTERVAL_REJECTED 0x1C /* 28 */ +#define HCI_ERR_SCO_AIR_MODE_REJECTED 0x1D /* 29 */ +#define HCI_ERR_INVALID_LMP_PARAM 0x1E /* 30 */ +#define HCI_ERR_UNSPECIFIED_ERROR 0x1F /* 31 */ +#define HCI_ERR_UNSUPPORTED_LMP_PARAM 0x20 /* 32 */ +#define HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 /* 33 */ +#define HCI_ERR_LMP_RESPONSE_TIMEOUT 0x22 /* 34 */ +#define HCI_ERR_LMP_ERROR_TRANS_COLLISION 0x23 /* 35 */ +#define HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24 /* 36 */ +#define HCI_ERR_ENCRYPT_MODE_NOT_ACCEPTABLE 0x25 /* 37 */ +#define HCI_ERR_UNIT_KEY_USED 0x26 /* 38 */ +#define HCI_ERR_QOS_NOT_SUPPORTED 0x27 /* 39 */ +#define HCI_ERR_INSTANT_PASSED 0x28 /* 40 */ +#define HCI_ERR_PAIR_UNIT_KEY_NOT_SUPPORT 0x29 /* 41 */ +#define HCI_ERR_DIFF_TRANS_COLLISION 0x2A /* 42 */ +#define HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2C /* 44 */ +#define HCI_ERR_QOS_REJECT 0x2D /* 45 */ +#define HCI_ERR_CHANN_ASSESS_NOT_SUPPORT 0x2E /* 46 */ +#define HCI_ERR_INSUFFICIENT_SECURITY 0x2F /* 47 */ +#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30 /* 48 */ +#define HCI_ERR_ROLE_SWITCH_PANDING 0x32 /* 50 */ +#define HCI_ERR_RESERVED_SLOT_VIOLATION 0x34 /* 52 */ +#define HCI_ERR_ROLE_SWITCH_FAILED 0x35 /* 53 */ +#define HCI_ERR_EXT_INQUIRY_RSP_TOO_LARGE 0x36 /* 54 */ +#define HCI_ERR_SSP_NOT_SUPPORTED_BY_HOST 0x37 /* 55 */ +#define HCI_ERR_HOST_BUSY_PAIRING 0x38 /* 56 */ +#define HCI_ERR_REJECT_NO_SUITABLE_CHANN 0x39 /* 57 */ +#define HCI_ERR_CONTROLLER_BUSY 0x3A /* 58 */ +#define HCI_ERR_UNACCEPTABLE_CONN_INTERVAL 0x3B /* 59 */ +#define HCI_ERR_DIRECTED_ADV_TIMEOUT 0x3C /* 60 */ +#define HCI_ERR_MIC_FAILURE 0x3D /* 61 */ +#define HCI_ERR_FAIL_TO_ESTABLISH_CONN 0x3E /* 62 */ +#define HCI_ERR_MAC_CONN_FAIL 0x3F /* 63 */ +#define HCI_ERR_COARSE_CLOCK_ADJUST_REJECTED 0x40 +#define HCI_ERR_TYPE0_SUBMAP_NOT_DEFINED 0x41 +#define HCI_ERR_UNKNOWN_ADVERTISING_IDENTIFIER 0x42 +#define HCI_ERR_LIMIT_REACHED 0x43 +#define HCI_ERR_OPERATION_CANCELLED_BY_HOST 0x44 + +/* hci local error code */ +#define HCI_ERR_INVALID_ADDR 0x64 /* 100 */ +#define HCI_ERR_TIMEOUT 0x65 /* 101 */ +#define HCI_ERR_OUT_OF_SYNC 0x66 /* 102 */ +#define HCI_ERR_NO_DESCRIPTOR 0x67 /* 103 */ +#define HCI_ERR_NO_MEMORY 0x68 + +/** + * bt_types.h + * + * \name BT_L2CAP_ERROR + * \brief BT l2cap error code definitions. + * \anchor BT_L2CAP_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define L2C_SUCCESS 0x00 + +#define L2C_CONN_ACCEPT 0x0000 +#define L2C_CONN_RSP_PENDING 0x0001 +#define L2C_CONN_RSP_INVALID_PSM 0x0002 +#define L2C_CONN_RSP_SECURITY_BLOCK 0x0003 +#define L2C_CONN_RSP_NO_RESOURCE 0x0004 +#define L2C_CONN_RSP_INVALID_PARAM 0x0005 +#define L2C_CONN_RSP_INVALID_SOURCE_CID 0x0006 +#define L2C_CONN_RSP_SOURCE_CID_ALLOCATED 0x0007 + +/* requset cmd reject reasons */ +#define L2C_CMD_REJ_NOT_UNDERSTOOD 0x0000 +#define L2C_CMD_REJ_SIGNAL_MTU_EXCEEDED 0x0001 +#define L2C_CMD_REJ_INVALID_CID_IN_REQ 0x0002 + +/* config response result codes */ +#define L2C_CFG_RSP_SUCCESS 0x0000 +#define L2C_CFG_RSP_UNACCEPTABLE_PARAMS 0x0001 +#define L2C_CFG_RSP_REJECTED 0x0002 +#define L2C_CFG_RSP_UNKNOWN_OPTIONS 0x0003 +#define L2C_CFG_RSP_PENDING 0x0004 +#define L2C_CFG_RSP_FLOW_SPEC_REJECTED 0x0005 + +#define L2C_LE_CREDIT_CONN_SUCCESS 0x0000 +#define L2C_LE_CREDIT_RSP_PSM_NOT_SUPPORTED 0x0002 +#define L2C_LE_CREDIT_RSP_NO_RESOURCES 0x0004 +#define L2C_LE_CREDIT_RSP_INSUFFICIENT_AUTHEN 0x0005 +#define L2C_LE_CREDIT_RSP_INSUFFICIENT_AUTHOR 0x0006 +#define L2C_LE_CREDIT_RSP_INSUFFICIENT_ENCRYP_KEY_SIZE 0x0007 +#define L2C_LE_CREDIT_RSP_INSUFFICIENT_ENCRYP 0x0008 +#define L2C_LE_CREDIT_RSP_INVALID_SOURCE_CID 0x0009 +#define L2C_LE_CREDIT_RSP_SOURCE_CID_ALREADY_ALLOC 0x000A + +/* status for connection updata response */ +#define L2C_LE_CONN_UPDATE_ACCEPT 0x0000 +#define L2C_LE_CONN_UPDATE_RSP_REJECT 0x0001 +#define L2C_LE_CONN_UPDATE_RSP_TOUT 0x0002 + +/* l2cap error code */ +#define L2C_ERR_REJ_BASE 0x0010 +#define L2C_ERR_CFG_BASE 0x0020 +#define L2C_ERR_LE_CREDIT_BASE 0x0030 +#define L2C_ERR_LE_CONN_UPDATE_BASE 0x0040 +#define L2C_ERR_VND_BASE 0x00F0 + +#define L2C_ERR_PENDING L2C_CONN_RSP_PENDING +#define L2C_ERR_INVALID_PSM L2C_CONN_RSP_INVALID_PSM +#define L2C_ERR_SECURITY_BLOCK L2C_CONN_RSP_SECURITY_BLOCK +#define L2C_ERR_NO_RESOURCE L2C_CONN_RSP_NO_RESOURCE +#define L2C_ERR_INVALID_PARAM L2C_CONN_RSP_INVALID_PARAM +#define L2C_ERR_INVALID_SOURCE_CID L2C_CONN_RSP_INVALID_SOURCE_CID +#define L2C_ERR_SOURCE_CID_ALLOCATED L2C_CONN_RSP_SOURCE_CID_ALLOCATED + +#define L2C_ERR_CMD_NOT_UNDERSTOOD (L2C_ERR_REJ_BASE + L2C_CMD_REJ_NOT_UNDERSTOOD) +#define L2C_ERR_SIGNAL_MTU_EXCEEDED (L2C_ERR_REJ_BASE + L2C_CMD_REJ_SIGNAL_MTU_EXCEEDED) +#define L2C_ERR_INVALID_CID_IN_REQ (L2C_ERR_REJ_BASE + L2C_CMD_REJ_INVALID_CID_IN_REQ) + +#define L2C_ERR_CFG_UNACCEPTABLE_PARAM (L2C_ERR_CFG_BASE + L2C_CFG_RSP_UNACCEPTABLE_PARAMS) +#define L2C_ERR_CFG_REJECTED (L2C_ERR_CFG_BASE + L2C_CFG_RSP_REJECTED) +#define L2C_ERR_CFG_UNKNOWN_OPTIONS (L2C_ERR_CFG_BASE + L2C_CFG_RSP_UNKNOWN_OPTIONS) +#define L2C_ERR_CFG_PENDING (L2C_ERR_CFG_BASE + L2C_CFG_RSP_PENDING) +#define L2C_ERR_CFG_FLOW_SPEC_REJECTED (L2C_ERR_CFG_BASE + L2C_CFG_RSP_FLOW_SPEC_REJECTED) + +#define L2C_ERR_LE_CREDIT_PSM_NOT_SUPPORTED (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_PSM_NOT_SUPPORTED) +#define L2C_ERR_LE_CREDIT_NO_RESOURCES (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_NO_RESOURCES) +#define L2C_ERR_LE_CREDIT_INSUFFICIENT_AUTHEN (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_INSUFFICIENT_AUTHEN) +#define L2C_ERR_LE_CREDIT_INSUFFICIENT_AUTHOR (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_INSUFFICIENT_AUTHOR) +#define L2C_ERR_LE_CREDIT_INSUFFICIENT_ENCRYP_KEY_SIZE (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_INSUFFICIENT_ENCRYP_KEY_SIZE) +#define L2C_ERR_LE_CREDIT_INSUFFICIENT_ENCRYP (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_INSUFFICIENT_ENCRYP) +#define L2C_ERR_LE_CREDIT_INVALID_SOURCE_CID (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_INVALID_SOURCE_CID) +#define L2C_ERR_LE_CREDIT_SOURCE_CID_ALREADY_ALLOC (L2C_ERR_LE_CREDIT_BASE + L2C_LE_CREDIT_RSP_SOURCE_CID_ALREADY_ALLOC) + +#define L2C_ERR_LE_CONN_PARAM_UPDATE_REJECT (L2C_ERR_LE_CONN_UPDATE_BASE + L2C_LE_CONN_UPDATE_RSP_REJECT) +#define L2C_ERR_LE_CONN_PARAM_UPDATE_TOUT (L2C_ERR_LE_CONN_UPDATE_BASE + L2C_LE_CONN_UPDATE_RSP_TOUT) + +#define L2C_ERR_VND_CREDITS_EXCEED (L2C_ERR_VND_BASE + 0x00) +#define L2C_ERR_VND_INVAILD_PDU (L2C_ERR_VND_BASE + 0x01) +#define L2C_ERR_VND_CREDITS_LACK (L2C_ERR_VND_BASE + 0x02) +#define L2C_ERR_VND_NO_MEMORY (L2C_ERR_VND_BASE + 0x03) +#define L2C_ERR_VND_INVALID_STATE (L2C_ERR_VND_BASE + 0x04) +#define L2C_ERR_VND_INVALID_RX_SEQ (L2C_ERR_VND_BASE + 0x05) +#define L2C_ERR_VND_TIMEOUT (L2C_ERR_VND_BASE + 0x06) +#define L2C_ERR_VND_INVALID_MODE (L2C_ERR_VND_BASE + 0x07) +#define L2C_ERR_VND_REMOTE_DISCONNECT (L2C_ERR_VND_BASE + 0x08) + +/** + * bt_types.h + * + * \name BT_ATT_ERROR + * \brief BT att error code definitions. + * \anchor BT_ATT_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define ATT_SUCCESS 0 /**< internal value .. */ +#define ATT_ERR_INVALID_HANDLE 0x01 /**< Attribute handle value given was not valid on this attribute server */ +#define ATT_ERR_READ_NOT_PERMITTED 0x02 /**< Attribute cannot be read */ +#define ATT_ERR_WRITE_NOT_PERMITTED 0x03 /**< Attribute cannot be written */ +#define ATT_ERR_INVALID_PDU 0x04 /**< The attribute PDU was invalid */ +#define ATT_ERR_INSUFFICIENT_AUTHEN 0x05 /**< The attribute requires authentication before it can be read or written */ +#define ATT_ERR_UNSUPPORTED_REQ 0x06 /**< Attribute server doesn't support the request received from the attribute client */ +#define ATT_ERR_INVALID_OFFSET 0x07 /**< Offset specified was past the end of the attribute */ +#define ATT_ERR_INSUFFICIENT_AUTHOR 0x08 /**< The attribute requires an authorization before it can be read or written */ +#define ATT_ERR_PREP_QUEUE_FULL 0x09 /**< Too many prepare writes have been queued */ +#define ATT_ERR_ATTR_NOT_FOUND 0x0A /**< No attribute found within the given attribute handle range */ +#define ATT_ERR_ATTR_NOT_LONG 0x0B /**< Attribute cannot be read or written using the Read Blob Request or Prepare Write Request */ +#define ATT_ERR_INSUFFICIENT_KEY_SIZE 0x0C /**< The Encryption Key Size used for encrypting this link is insufficient */ +#define ATT_ERR_INVALID_VALUE_SIZE 0x0D /**< The attribute value length is invalid for the operation */ +#define ATT_ERR_UNLIKELY 0x0E /**< The attribute request that was requested has encountered an error that was very unlikely, and therefore could not be completed as requested */ +#define ATT_ERR_INSUFFICIENT_ENCRYPT 0x0F /**< The attribute requires encryption before it can be read or written */ +#define ATT_ERR_UNSUPPORTED_GROUP_TYPE 0x10 /**< The attribute type is not a supported grouping attribute as defined by a higher layer specification */ +#define ATT_ERR_INSUFFICIENT_RESOURCES 0x11 /**< Insufficient Resources to complete the request */ + +/* profile dependent application error codes >= 0x80: */ +#define ATT_ERR_MIN_APPLIC_CODE 0x80 /**< minimal application error code */ +#define ATT_ERR_INVALID_VALUE 0x80 /**< The attribute value is invalid for the operation */ + +/* manufacturer specific error codes that are "missing" in GATT spec. >= 0xC0: */ +#define ATT_ERR_INVALID_CCC_BITS 0xC0 /**< Invalid client char. config. bits */ +#define ATT_ERR_INVALID_SIGNED_COUNT 0xC1 /**< Invalid sign count */ +#define ATT_ERR_INVALID_SIGNED_MAC_FAILED 0xC2 /**< Invalid sign mac value */ + +/* error codes common to various profiles (see "CSS v2.pdf"), >= 0xE0 */ +#define ATT_ERR_CCCD_IMPROPERLY_CONFIGURED 0xFD /**< CCCD improperly configured */ +#define ATT_ERR_PROC_ALREADY_IN_PROGRESS 0xFE /**< Procedure Already in Progress */ +#define ATT_ERR_OUT_OF_RANGE 0xFF /**< Client Characteristic Configuration Descriptor Improperly Configured */ + +/** + * bt_types.h + * + * \name BT_GATT_ERROR + * \brief BT gatt error code definitions. + * \anchor BT_GATT_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define GATT_SUCCESS 0x00 +#define GATT_ERR_OUT_OF_RESOURCE 0x01 +#define GATT_ERR_UNSUPPORTED 0x02 +#define GATT_ERR_INVALID_ROLE 0x03 +#define GATT_ERR_INVALID_STATE 0x04 +#define GATT_ERR_INVALID_CODING 0x05 +#define GATT_ERR_INVALID_HANDLE 0x06 +#define GATT_ERR_INVALID_PARAM 0x07 +#define GATT_ERR_INTERNAL 0x08 +#define GATT_ERR_NOT_ALLOWED 0x09 +#define GATT_ERR_NOTIF_IND_NOT_CFG 0x0A +#define GATT_ERR_NOTIF_IND_CFG 0x0B +#define GATT_ERR_NOTIF_IND_CONF_PD 0x0C +#define GATT_ERR_TIMEOUT 0x0D +#define GATT_ERR_LINK_DEACTIVATED 0x0E +#define GATT_ERR_NOT_AUTHENTICATED 0x0F +#define GATT_ERR_NOT_ENCRYPTED 0x10 +#define GATT_ERR_PROC_FAIL 0x11 + +/* sm error code */ +#define SM_SUCCESS 0x00 +/* SMP_OP_PAIRING_FAILED causes */ +#define SMP_ERR_SUCCESS 0x00 +#define SMP_ERR_PASSKEY_ENTRY_FAIL 0x01 +#define SMP_ERR_OOB_NOT_AVAIABLE 0x02 +#define SMP_ERR_AUTHEN_REQUIREMENTS 0x03 +#define SMP_ERR_CFM_VALUE_FAILED 0x04 +#define SMP_ERR_PAIRING_NOT_SUPPORTED 0x05 +#define SMP_ERR_ENCRYPTION_KEY_SIZE 0x06 +#define SMP_ERR_CMD_NOT_SUPPORTED 0x07 +#define SMP_ERR_UNSPECIFIED_REASON 0x08 +#define SMP_ERR_REPEATED_ATTEMPTS 0x09 +#define SMP_ERR_INVALID_PARAM 0x0A +#define SMP_ERR_DHKEY_CHECK_FAILED 0x0B +#define SMP_ERR_NUMERIC_COMPARISION_FAIL 0x0C +#define SMP_ERR_BREDR_PAIRING_IN_PROGRESS 0x0D +#define SMP_ERR_CRS_TRANS_KEY_GEN_NOT_ALLOW 0x0E + +#define SM_ERR_NO_ENTRY 0xE1 +#define SM_ERR_DB_FULL 0xE2 +#define SM_ERR_INVALID_PARAM 0xE3 +#define SM_ERR_INSUFFICIENT_LINK_KEY 0xE4 +#define SM_ERR_LE_ADDR_NOT_RESOLVED 0xE5 +#define SM_ERR_INVALID_STATE 0xE6 +#define SM_ERR_NO_RESOURCE 0xE7 +#define SM_ERR_LINK_KEY_MISSING 0xE8 +#define SM_ERR_DISCONNECT 0xE9 +#define SM_ERR_PARING_NOT_ALLOWED 0xEA +#define SM_ERR_KEY_SAVE_FAILED 0xEB +#define SM_ERR_TIMEOUT 0xEC +#define SM_ERR_UNKNOWN 0xED +#define SM_ERR_VENDOR 0xEF + +/** + * bt_types.h + * + * \name BT_BTIF_ERROR + * \brief BT btif error code definitions. + * \anchor BT_BTIF_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define BTIF_ERR 0x0000 +#define BTIF_SUCCESS 0x00 +#define BTIF_ACCEPT 0x01 +#define BTIF_ERR_REJECT 0x02 +#define BTIF_ERR_NO_RESOURCE 0x03 +#define BTIF_ERR_INVALID_PARAM 0x04 +#define BTIF_ERR_INVALID_STATE 0x05 +#define BTIF_ERR_CONN_DISCONNECT 0x06 +#define BTIF_ERR_CONN_LOST 0x07 +#define BTIF_ERR_AUTHEN_FAIL 0x08 +#define BTIF_ERR_INIT_TOUT 0x09 +#define BTIF_ERR_INIT_OUT_OF_SYNC 0x0A +#define BTIF_ERR_INIT_HARDWARE_ERROR 0x0B +#define BTIF_ERR_LOWER_LAYER_ERROR 0x0C +#define BTIF_ERR_ADDR_NOT_RESOLVED 0x0D +#define BTIF_ERR_TOUT 0x0E + +#define BTIF_ERR_UNSPECIFIED 0xFD +#define BTIF_ERR_NOT_SUPPORTED 0xFE + +/** + * bt_types.h + * + * \name BT_GAP_ERROR + * \brief BT GAP error code definitions. + * \anchor BT_GAP_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define GAP_SUCCESS 0x00 +#define GAP_ACCEPT 0x01 +#define GAP_ERR_REJECT 0x02 +#define GAP_ERR_NO_RESOURCE 0x03 +#define GAP_ERR_INVALID_PARAM 0x04 +#define GAP_ERR_INVALID_STATE 0x05 +#define GAP_ERR_CONN_DISCONNECT 0x06 +#define GAP_ERR_CONN_LOST 0x07 +#define GAP_ERR_AUTHEN_FAIL 0x08 +#define GAP_ERR_INIT_TOUT 0x09 +#define GAP_ERR_INIT_OUT_OF_SYNC 0x0A +#define GAP_ERR_INIT_HARDWARE_ERROR 0x0B +#define GAP_ERR_LOWER_LAYER_ERROR 0x0C +#define GAP_ERR_ADDR_NOT_RESOLVED 0x0D +#define GAP_ERR_TOUT 0x0E + +#define GAP_ERR_SW_RESET 0xFC +#define GAP_ERR_UNSPECIFIED 0xFD +#define GAP_ERR_NOT_SUPPORTED 0xFE + +/** + * bt_types.h + * + * \name BT_APP_ERROR + * \brief BT APP error code definitions. + * \anchor BT_APP_ERROR + */ +/** + * \ingroup BTTYPES + */ +#define APP_SUCCESS 0x00 +#define APP_ERR_PENDING 0x01 +#define APP_ERR_ACCEPT 0x03 +#define APP_ERR_REJECT 0x04 +#define APP_ERR_NOT_RELEASE 0x05 + +/** + * bt_types.h + * + * \name BT_BYTE_ORDER + * \brief BT buffer/array byte-order utility macros. + * \anchor BT_BYTE_ORDER + */ +/** + * \ingroup BTTYPES + */ +/** Calculate integer bit count of b'1 */ +#define INT_BIT_COUNT(integer, count) { \ + count = 0; \ + while (integer) \ + { \ + count++; \ + integer &= integer - 1; \ + } \ + } + +/** Stream skip len */ +#define STREAM_SKIP_LEN(s, len) { \ + s += len; \ + } + +/** Stream to array */ +#define STREAM_TO_ARRAY(a, s, len) { \ + uint32_t ii; \ + for (ii = 0; ii < len; ii++) \ + { \ + *((uint8_t *)(a) + ii) = *s++; \ + } \ + } + +/** Array to stream */ +#define ARRAY_TO_STREAM(s, a, len) { \ + uint32_t ii; \ + for (ii = 0; ii < len; ii++) \ + { \ + *s++ = *((uint8_t *)(a) + ii); \ + } \ + } + +/** Little Endian stream to uint8 */ +#define LE_STREAM_TO_UINT8(u8, s) { \ + u8 = (uint8_t)(*s); \ + s += 1; \ + } + +/** Little Endian stream to uint16 */ +#define LE_STREAM_TO_UINT16(u16, s) { \ + u16 = ((uint16_t)(*(s + 0)) << 0) + \ + ((uint16_t)(*(s + 1)) << 8); \ + s += 2; \ + } + +/** Little Endian stream to uint24 */ +#define LE_STREAM_TO_UINT24(u24, s) { \ + u24 = ((uint32_t)(*(s + 0)) << 0) + \ + ((uint32_t)(*(s + 1)) << 8) + \ + ((uint32_t)(*(s + 2)) << 16); \ + s += 3; \ + } + +/** Little Endian stream to uint32 */ +#define LE_STREAM_TO_UINT32(u32, s) { \ + u32 = ((uint32_t)(*(s + 0)) << 0) + \ + ((uint32_t)(*(s + 1)) << 8) + \ + ((uint32_t)(*(s + 2)) << 16) + \ + ((uint32_t)(*(s + 3)) << 24); \ + s += 4; \ + } + +/** Little Endian uint8 to stream */ +#define LE_UINT8_TO_STREAM(s, u8) { \ + *s++ = (uint8_t)(u8); \ + } + +/** Little Endian uint16 to stream */ +#define LE_UINT16_TO_STREAM(s, u16) { \ + *s++ = (uint8_t)((u16) >> 0); \ + *s++ = (uint8_t)((u16) >> 8); \ + } + +/** Little Endian uint24 to stream */ +#define LE_UINT24_TO_STREAM(s, u24) { \ + *s++ = (uint8_t)((u24) >> 0); \ + *s++ = (uint8_t)((u24) >> 8); \ + *s++ = (uint8_t)((u24) >> 16); \ + } + +/** Little Endian uint32 to stream */ +#define LE_UINT32_TO_STREAM(s, u32) { \ + *s++ = (uint8_t)((u32) >> 0); \ + *s++ = (uint8_t)((u32) >> 8); \ + *s++ = (uint8_t)((u32) >> 16); \ + *s++ = (uint8_t)((u32) >> 24); \ + } + +/** Little Endian array to uint8 */ +#define LE_ARRAY_TO_UINT8(u8, a) { \ + u8 = (uint8_t)(*(a + 0)); \ + } + +/** Little Endian array to uint16 */ +#define LE_ARRAY_TO_UINT16(u16, a) { \ + u16 = ((uint16_t)(*(a + 0)) << 0) + \ + ((uint16_t)(*(a + 1)) << 8); \ + } + +/** Little Endian array to uint24 */ +#define LE_ARRAY_TO_UINT24(u24, a) { \ + u24 = ((uint32_t)(*(a + 0)) << 0) + \ + ((uint32_t)(*(a + 1)) << 8) + \ + ((uint32_t)(*(a + 2)) << 16); \ + } + +/** Little Endian array to uint32 */ +#define LE_ARRAY_TO_UINT32(u32, a) { \ + u32 = ((uint32_t)(*(a + 0)) << 0) + \ + ((uint32_t)(*(a + 1)) << 8) + \ + ((uint32_t)(*(a + 2)) << 16) + \ + ((uint32_t)(*(a + 3)) << 24); \ + } + +/** Little Endian uint8 to array */ +#define LE_UINT8_TO_ARRAY(a, u8) { \ + *((uint8_t *)(a) + 0) = (uint8_t)(u8); \ + } + +/** Little Endian uint16 to array */ +#define LE_UINT16_TO_ARRAY(a, u16) { \ + *((uint8_t *)(a) + 0) = (uint8_t)((u16) >> 0); \ + *((uint8_t *)(a) + 1) = (uint8_t)((u16) >> 8); \ + } + +/** Little Endian uint24 to array */ +#define LE_UINT24_TO_ARRAY(a, u24) { \ + *((uint8_t *)(a) + 0) = (uint8_t)((u24) >> 0); \ + *((uint8_t *)(a) + 1) = (uint8_t)((u24) >> 8); \ + *((uint8_t *)(a) + 2) = (uint8_t)((u24) >> 16); \ + } + +/** Little Endian uint32 to array */ +#define LE_UINT32_TO_ARRAY(a, u32) { \ + *((uint8_t *)(a) + 0) = (uint8_t)((u32) >> 0); \ + *((uint8_t *)(a) + 1) = (uint8_t)((u32) >> 8); \ + *((uint8_t *)(a) + 2) = (uint8_t)((u32) >> 16); \ + *((uint8_t *)(a) + 3) = (uint8_t)((u32) >> 24); \ + } + +/** Big Endian stream to uint8 */ +#define BE_STREAM_TO_UINT8(u8, s) { \ + u8 = (uint8_t)(*(s + 0)); \ + s += 1; \ + } + +/** Big Endian stream to uint16 */ +#define BE_STREAM_TO_UINT16(u16, s) { \ + u16 = ((uint16_t)(*(s + 0)) << 8) + \ + ((uint16_t)(*(s + 1)) << 0); \ + s += 2; \ + } + +/** Big Endian stream to uint24 */ +#define BE_STREAM_TO_UINT24(u24, s) { \ + u24 = ((uint32_t)(*(s + 0)) << 16) + \ + ((uint32_t)(*(s + 1)) << 8) + \ + ((uint32_t)(*(s + 2)) << 0); \ + s += 3; \ + } + +/** Big Endian stream to uint32 */ +#define BE_STREAM_TO_UINT32(u32, s) { \ + u32 = ((uint32_t)(*(s + 0)) << 24) + \ + ((uint32_t)(*(s + 1)) << 16) + \ + ((uint32_t)(*(s + 2)) << 8) + \ + ((uint32_t)(*(s + 3)) << 0); \ + s += 4; \ + } + +/** Big Endian uint8 to stream */ +#define BE_UINT8_TO_STREAM(s, u8) { \ + *s++ = (uint8_t)(u8); \ + } + +/** Big Endian uint16 to stream */ +#define BE_UINT16_TO_STREAM(s, u16) { \ + *s++ = (uint8_t)((u16) >> 8); \ + *s++ = (uint8_t)((u16) >> 0); \ + } + +/** Big Endian uint24 to stream */ +#define BE_UINT24_TO_STREAM(s, u24) { \ + *s++ = (uint8_t)((u24) >> 16); \ + *s++ = (uint8_t)((u24) >> 8); \ + *s++ = (uint8_t)((u24) >> 0); \ + } + +/** Big Endian uint32 to stream */ +#define BE_UINT32_TO_STREAM(s, u32) { \ + *s++ = (uint8_t)((u32) >> 24); \ + *s++ = (uint8_t)((u32) >> 16); \ + *s++ = (uint8_t)((u32) >> 8); \ + *s++ = (uint8_t)((u32) >> 0); \ + } + +/** Big Endian array to uint8 */ +#define BE_ARRAY_TO_UINT8(u8, a) { \ + u8 = (uint8_t)(*(a + 0)); \ + } + +/** Big Endian array to uint16 */ +#define BE_ARRAY_TO_UINT16(u16, a) { \ + u16 = ((uint16_t)(*(a + 0)) << 8) + \ + ((uint16_t)(*(a + 1)) << 0); \ + } + +/** Big Endian array to uint24 */ +#define BE_ARRAY_TO_UINT24(u24, a) { \ + u24 = ((uint32_t)(*(a + 0)) << 16) + \ + ((uint32_t)(*(a + 1)) << 8) + \ + ((uint32_t)(*(a + 2)) << 0); \ + } + +/** Big Endian array to uint32 */ +#define BE_ARRAY_TO_UINT32(u32, a) { \ + u32 = ((uint32_t)(*(a + 0)) << 24) + \ + ((uint32_t)(*(a + 1)) << 16) + \ + ((uint32_t)(*(a + 2)) << 8) + \ + ((uint32_t)(*(a + 3)) << 0); \ + } + +/** Big Endian uint8 to array */ +#define BE_UINT8_TO_ARRAY(a, u8) { \ + *((uint8_t *)(a) + 0) = (uint8_t)(u8); \ + } + +/** Big Endian uint16 to array */ +#define BE_UINT16_TO_ARRAY(a, u16) { \ + *((uint8_t *)(a) + 0) = (uint8_t)((u16) >> 8); \ + *((uint8_t *)(a) + 1) = (uint8_t)((u16) >> 0); \ + } + +/** Big Endian uint24 to array */ +#define BE_UINT24_TO_ARRAY(a, u24) { \ + *((uint8_t *)(a) + 0) = (uint8_t)((u24) >> 16); \ + *((uint8_t *)(a) + 1) = (uint8_t)((u24) >> 8); \ + *((uint8_t *)(a) + 2) = (uint8_t)((u24) >> 0); \ + } + +/** Big Endian uint32 to array */ +#define BE_UINT32_TO_ARRAY(a, u32) { \ + *((uint8_t *)(a) + 0) = (uint8_t)((u32) >> 24); \ + *((uint8_t *)(a) + 1) = (uint8_t)((u32) >> 16); \ + *((uint8_t *)(a) + 2) = (uint8_t)((u32) >> 8); \ + *((uint8_t *)(a) + 3) = (uint8_t)((u32) >> 0); \ + } + +#ifdef __cplusplus +} +#endif + +#endif /* _BT_TYPES_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/hci_if.h b/component/common/bluetooth/realtek/sdk/src/app/porting_test/hci_if.h new file mode 100644 index 00000000..521991fc --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/hci_if.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2015, Realsil Semiconductor Corporation. All rights reserved. + */ + +#ifndef _HCI_IF_H_ +#define _HCI_IF_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + HCI_IF_EVT_OPENED, /* hci I/F open completed */ + HCI_IF_EVT_CLOSED, /* hci I/F close completed */ + HCI_IF_EVT_DATA_IND, /* hci I/F rx data indicated */ + HCI_IF_EVT_DATA_XMIT, /* hci I/F tx data transmitted */ + HCI_IF_EVT_ERROR, /* hci I/F error occurred */ +} T_HCI_IF_EVT; + +typedef bool (*P_HCI_IF_CALLBACK)(T_HCI_IF_EVT evt, bool status, uint8_t *p_buf, uint32_t len); + +bool hci_if_open(P_HCI_IF_CALLBACK p_callback); + +bool hci_if_close(void); + +bool hci_if_write(uint8_t *p_buf, uint32_t len); + +bool hci_if_confirm(uint8_t *p_buf); + + +#ifdef __cplusplus +} +#endif + +#endif /* _HCI_IF_H_ */ diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/porting_test_app.c b/component/common/bluetooth/realtek/sdk/src/app/porting_test/porting_test_app.c new file mode 100644 index 00000000..6ff281a6 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/porting_test_app.c @@ -0,0 +1,305 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.c + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +/*============================================================================* + * Header Files + *============================================================================*/ +#include +#include +#include +#include "porting_test_app.h" +#include "app_flags.h" +#include +#if APP_TEST_RANDOM +#include "platform_utils.h" +#endif +#if APP_TEST_OSIF +#include +#endif +#if APP_TEST_FTL +#include "ftl_if.h" +#endif +#if APP_TEST_HCI_TP +#include "hci_if.h" +#endif + +typedef enum +{ + APP_TC_START, +#if APP_TEST_RANDOM + APP_TC_RANDOM, +#endif +#if APP_TEST_OSIF + APP_TC_OSIF, +#endif +#if APP_TEST_FTL + APP_TC_FTL, +#endif +#if APP_TEST_HCI_TP + APP_TC_HCI_TP, +#endif + APP_TC_END, +} T_APP_TEST_CASE; + +uint8_t test_case = APP_TC_START; +uint8_t fail_count = 0; +#if APP_TEST_FTL +uint32_t ftl_test_count = APP_TEST_FTL_COUNT; +uint8_t cmd_data[20]; +#endif +void app_handle_io_msg(T_IO_MSG io_msg) +{ + uint16_t msg_type = io_msg.type; + + switch (msg_type) + { + case IO_MSG_TYPE_QDECODE: + { + app_run_test_case(); + } + break; + default: + break; + } +} + +#if APP_TEST_HCI_TP +extern bool bte_sys_init(void); +extern unsigned char rtlbt_config[]; +bool hci_if_callback(T_HCI_IF_EVT evt, bool status, uint8_t *p_buf, uint32_t len) +{ + bool result = true; + bool ret = true; + APP_PRINT_TRACE4("hci_if_callback: evt %d status %d, buf %p, len %u", + evt, status, p_buf, len); + + switch (evt) + { + case HCI_IF_EVT_DATA_IND: + { + APP_PRINT_INFO0("HCI_IF_EVT_DATA_IND"); + APP_PRINT_INFO1("Data: %b", TRACE_BINARY(len, p_buf)); + if(len == 13) + { + uint8_t status = p_buf[6]; + uint8_t bt_addr[6]; + if(status != 0) + { + ret = false; + break; + } + memcpy(bt_addr, &(p_buf[7]), 6); + APP_PRINT_INFO6("local bd addr: 0x%x:%x:%x:%x:%x:%x", + bt_addr[5], bt_addr[4], bt_addr[3], + bt_addr[2], bt_addr[1], bt_addr[0]); +#if 0 + if(memcmp(bt_addr, &(rtlbt_config[9]), 6) == 0) + { + APP_PRINT_INFO0("APP_TC_HCI_TP: Success"); + } + else + { + ret = false; + APP_PRINT_ERROR0("APP_TC_HCI_TP: Check Address Failed"); + break; + } +#endif + } + else + { + ret = false; + APP_PRINT_ERROR0("APP_TC_HCI_TP: Check Address Failed"); + break; + } + hci_if_confirm(p_buf); + test_case++; + app_send_msg(1); + } + break; + + case HCI_IF_EVT_DATA_XMIT: + { + APP_PRINT_INFO0("HCI_IF_EVT_DATA_XMIT"); + } + break; + + case HCI_IF_EVT_ERROR: + APP_PRINT_INFO0("HCI_IF_EVT_ERROR"); + break; + + case HCI_IF_EVT_OPENED: + { + APP_PRINT_INFO0("HCI_IF_EVT_OPENED"); + if(status == false) + { + ret = false; + } + else + { + cmd_data[0] = 0x01; //read bt address + cmd_data[1] = 0x09; + cmd_data[2] = 0x10; + cmd_data[3] = 0x00; + if(hci_if_write(cmd_data, 4) == false) + { + ret = false; + } + } + } + break; + + case HCI_IF_EVT_CLOSED: + break; + + default: + break; + } + + if(ret == false) + { + APP_PRINT_ERROR0("APP_TC_HCI_TP: Failed 2"); + fail_count++; + test_case++; + app_send_msg(1); + } + + return result; +} +#endif + +void app_run_test_case(void) +{ + switch (test_case) + { + case APP_TC_START: + { + APP_PRINT_INFO0("APP_TC_START"); + } + break; + +#if APP_TEST_RANDOM + case APP_TC_RANDOM: + { + uint32_t random_1; + uint32_t random_2; + uint8_t i = 0; + APP_PRINT_INFO0("APP_TC_RANDOM"); + for(i=0;i<10;i++) + { + random_1 = platform_random(0); + random_2 = platform_random(0); + APP_PRINT_INFO2("APP_TC_RANDOM: random_1 0x%x, random_2 0x%x", random_1, random_2); + if(random_1 == random_2) + { + APP_PRINT_ERROR0("APP_TC_RANDOM: Failed"); + fail_count++; + break; + } + } + if(i == 10) + { + APP_PRINT_INFO0("APP_TC_RANDOM: Success"); + } + } + break; +#endif + +#if APP_TEST_OSIF + case APP_TC_OSIF: + { + void *p_buffer; + uint32_t heap_size_before = os_mem_peek(1); + uint32_t heap_size_after; + APP_PRINT_INFO0("APP_TC_OSIF"); + APP_PRINT_INFO1("Heap size: %d", heap_size_before); + p_buffer = os_mem_alloc(1, 1000); + if(p_buffer != NULL) + { + os_mem_free(p_buffer); + heap_size_after = os_mem_peek(1); + if(heap_size_after == heap_size_before) + { + APP_PRINT_INFO0("APP_TC_OSIF: Success"); + break; + } + } + APP_PRINT_ERROR0("APP_TC_OSIF: Failed"); + fail_count++; + } + break; +#endif + +#if APP_TEST_FTL + case APP_TC_FTL: + { + uint8_t data[80]; + uint8_t data_load[80]; + uint32_t ret; + APP_PRINT_INFO1("APP_TC_FTL: ftl_test_count %d", ftl_test_count); + memset(data, ftl_test_count, 80); + ret = ftl_save_to_storage(data, 1024, 80); + if(ret == 0) + { + ftl_load_from_storage(data_load, 1024, 80); + if(memcmp(data, data_load, 80) == 0) + { + ftl_test_count--; + if(ftl_test_count == 0) + { + APP_PRINT_INFO0("APP_TC_FTL: Success"); + break; + } + app_send_msg(1); + return; + } + } + APP_PRINT_ERROR0("APP_TC_FTL: Failed"); + fail_count++; + } + break; +#endif +#if APP_TEST_HCI_TP + case APP_TC_HCI_TP: + { + APP_PRINT_INFO0("APP_TC_HCI_TP"); + if(bte_sys_init() == true) + { + if (hci_if_open(hci_if_callback) == true) + { + return; + } + } + APP_PRINT_ERROR0("APP_TC_HCI_TP: Failed 1"); + fail_count++; + } + break; +#endif + case APP_TC_END: + { + APP_PRINT_INFO1("APP_TC_END: fail_count %d", fail_count); + return; + } + break; + default: + { + APP_PRINT_ERROR1("app_run_test_case: unknown test_case %d", test_case); + } + break; + } + test_case++; + os_delay(100); + app_send_msg(1); +} + diff --git a/component/common/bluetooth/realtek/sdk/src/app/porting_test/porting_test_app.h b/component/common/bluetooth/realtek/sdk/src/app/porting_test/porting_test_app.h new file mode 100644 index 00000000..cb73d55e --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/app/porting_test/porting_test_app.h @@ -0,0 +1,35 @@ +/** +***************************************************************************************** +* Copyright(c) 2017, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file peripheral_app.h + * @brief This file handles BLE peripheral application routines. + * @author jane + * @date 2017-06-06 + * @version v1.0 + ************************************************************************************** + * @attention + *

© COPYRIGHT 2017 Realtek Semiconductor Corporation

+ ************************************************************************************** + */ + +#ifndef _PERIPHERAL_APP__ +#define _PERIPHERAL_APP__ + +#ifdef __cplusplus +extern "C" { +#endif +/*============================================================================* + * Header Files + *============================================================================*/ +#include + +void app_handle_io_msg(T_IO_MSG io_msg); +void app_send_msg(uint16_t sub_type); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/component/common/bluetooth/realtek/sdk/src/ble/profile/client/dfu_client.c b/component/common/bluetooth/realtek/sdk/src/ble/profile/client/dfu_client.c new file mode 100644 index 00000000..1b7dd9e9 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/ble/profile/client/dfu_client.c @@ -0,0 +1,1314 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file dfu_client.c + * @brief dfu service client source file. + * @details + * @author bill + * @date 2017-8-28 + * @version v1.0 + ****************************************************************************** + * @attention + *

© COPYRIGHT 2015 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#include +#include +#include "gap_conn_le.h" +#include "gap_scan.h" +#include "patch_header_check.h" +#include "mem_types.h" +#include "os_mem.h" +#include "trace.h" +#include "trace_app.h" +#include "dfu_client.h" +#include "crypto_api.h" +#include "device_lock.h" +#include "data_uart.h" +#include "platform_stdlib.h" +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT +#include +#endif + +#define DFU_HEADER_SIZE 12 +#define IMG_HEADER_SIZE 1024 + +#define DFU_CLIENT_INVALID_CONN_ID 0xff + +#define GATT_UUID128_DFU_DATA 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x63, 0x00, 0x00 +#define GATT_UUID128_DFU_CONTROL_POINT 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x64, 0x00, 0x00 +#define GATT_UUID128_DFU_SERVICE 0x12, 0xA2, 0x4D, 0x2E, 0xFE, 0x14, 0x48, 0x8e, 0x93, 0xD2, 0x17, 0x3C, 0x87, 0x62, 0x00, 0x00 + + +//convert img version bit map to deirectly copmare version value +#define IMG_VER_TO_LITTLE_ENDIAN(p) (((p & 0xf) << 28 )+ (((p & 0xff0) >> 4) << 20) + (((p & 0x07fff000) >> 12) << 5) + ((p & 0xf8000000) >> 27)) + +#define MAJOR_IMG_VER(p) (p & 0xf) +#define MINOR_IMG_VER(p) ((p & 0xff0) >> 4) +#define REVISION_IMG_VER(p) ((p & 0x07fff000) >> 12) +#define RESERVE_IMG_VER(p) ((p & 0xf8000000) >> 27) + +#undef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +/* PUT external 2 CHARS from local SHORT, Big-Endian format STANDARD NETWORK BYTE ORDER */ +#define BE_WORD2EXTRN(p,w) \ + {*((p)+1) = (unsigned char)((w) & 0xff); \ + *(p) = /*lint -e(572,778)*/ (unsigned char)(((w)>>8) & 0xff);} + +/* Get local WORD from external 2 BYTE, Little-Endian format */ +#define LE_EXTRN2WORD(p) (((*(p)) & 0xff) + ((*((p)+1)) << 8)) + +/* Get local DWORD from external 4 BYTE, Little-Endian format */ +#define LE_EXTRN2DWORD(p) (((unsigned long)(*((p)+0)) & 0xff) + ((unsigned long)(*((p)+1)) << 8) \ + + ((unsigned long)(*((p)+2)) << 16) + ((unsigned long)(*((p)+3)) << 24)) + +/* PUT external 2 BYTE from local WORD, Little-Endian Format */ +#define LE_WORD2EXTRN(p,w) \ + {*((unsigned char*)p) = (unsigned char)((unsigned short)(w) & 0xff); \ + *(((unsigned char*)p)+1) = /*lint -e(572,778)*/ (unsigned char)(((unsigned short)(w)>>8) & 0xff);} + + +const uint8_t dfu_data_uuid[16] = {GATT_UUID128_DFU_DATA}; +const uint8_t dfu_control_point_uuid[16] = {GATT_UUID128_DFU_CONTROL_POINT}; +const uint8_t dfu_service_uuid[16] = {GATT_UUID128_DFU_SERVICE}; + +T_DFU_CLIENT_FSM_WRITE g_dfu_fsm_write = DFU_FSM_WRITE_DO_NOT_CARE; + +/*when ota target enable buffer check*/ +uint16_t g_buf_check_pkt_num; +uint16_t g_buf_check_pkt_count; +uint16_t g_buf_check_crc; + +/* for record data that target send by notification*/ +T_DFU_CTX g_dfu_ctx; + +uint8_t g_cp_msg[20]; //for cache control point masg +uint8_t g_cp_msg_len; + +extern uint8_t* bt_ota_central_client_get_image(void); +extern uint8_t* bt_ota_central_client_get_key(void); + +/******************************************************************************************************** +* local static variables defined here, only used in this source file. +********************************************************************************************************/ +/** + * @brief dfu client Link control block definition. + */ +typedef struct +{ + T_DFU_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_DFU_CACHE_LEN]; +} T_DFU_LINK, *P_DFU_LINK; + + +static P_DFU_LINK dfu_table; +static uint8_t dfu_link_num; + +/**< Callback used to send data to app from Dfu client layer. */ +static P_FUN_GENERAL_APP_CB pf_dfu_client_cb = NULL; +static P_FUN_GENERAL_APP_CB pf_dfu_client_app_info_cb = NULL; + +/**< Dfu client ID. */ +static T_CLIENT_ID dfu_client = CLIENT_PROFILE_GENERAL_ID; + +/**< Dfu discovery end handle control. */ +static T_DFU_HANDLE_TYPE dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + +/**< Discovery State indicate which CCCD is in discovery. */ +static T_DFU_CCCD_DISC_STATE dfu_cccd_disc_state = DFU_CCCD_DISC_START; + +static void dfu_client_init(void); + +/** + * @brief Used by application, to set the handles in Dfu handle cache. + * @param handle_type: handle types of this specific profile. + * @param handle_value: handle value to set. + * @retval true--set success. + * flase--set failed. + */ +bool dfu_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (dfu_table[conn_id].disc_state != DISC_DFU_IDLE) + { + PROFILE_PRINT_ERROR1("dfu_client_set_hdl_cache: failed invalid state %d", + dfu_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_DFU_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("dfu_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(dfu_table[conn_id].hdl_cache, p_hdl_cache, len); + dfu_table[conn_id].disc_state = DISC_DFU_DONE; + return true; +} + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool dfu_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (dfu_table[conn_id].disc_state != DISC_DFU_DONE) + { + PROFILE_PRINT_ERROR1("dfu_client_get_hdl_cache: failed invalid state %d", + dfu_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_DFU_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("dfu_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, dfu_table[conn_id].hdl_cache, len); + return true; +} + + +/** + * @brief Used by application, to start the discovery procedure of Dfu server. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_start_discovery(uint8_t conn_id) +{ + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + + APP_PRINT_INFO0("dfu_client_start_discovery"); + data_uart_print("dfu_client_start_discovery\n\r"); + /* First clear handle cache. */ + memset(&dfu_table[conn_id], 0, sizeof(T_DFU_LINK)); + dfu_table[conn_id].disc_state = DISC_DFU_START; + if (client_by_uuid128_srv_discovery(conn_id, dfu_client, + (uint8_t *)dfu_service_uuid) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +/** + * @brief Used internal, start the discovery of Dfu characteristics. + * NOTE--user can offer this interface for application if required. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +static bool dfu_client_start_all_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + PROFILE_PRINT_INFO0("dfu_client_start_all_char_discovery"); + start_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_START]; + end_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END]; + return (client_all_char_discovery(conn_id, dfu_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS); +} + +/** + * @brief Used internal, start the discovery of Dfu characteristics descriptor. + * NOTE--user can offer this interface for application if required. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +static bool dfu_client_start_all_char_descriptor_discovery(uint8_t conn_id, uint16_t start_handle, + uint16_t end_handle) +{ + DFU_PRINT_INFO0("dfu_client_start_all_char_descriptor_discovery"); + return (client_all_char_descriptor_discovery(conn_id, dfu_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS); +} + +/** + * @brief Used by application, read data from server by using handles. + * @param readCharType: one of characteristic that has the readable property. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_read_by_handle(uint8_t conn_id, T_DFU_READ_TYPE type) +{ + bool hdl_valid = false; + uint16_t handle = 0; + + if (conn_id >= dfu_link_num) + { + PROFILE_PRINT_ERROR1("dfu_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + switch (type) + { + case DFU_READ_CP_CCCD: + if (dfu_table[conn_id].hdl_cache[DFU_READ_CP_CCCD]) + { + handle = dfu_table[conn_id].hdl_cache[DFU_READ_CP_CCCD]; + hdl_valid = true; + } + break; + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, dfu_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + DFU_PRINT_INFO0("dfu_client_read_by_handle: Request fail! Please check!"); + return false; +} + +/** + * @brief Used by application, to enable or disable the notification of peer server's V3 Notify Characteristic. + * @param command: 0--disable the notification, 1--enable the notification. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_cp_cccd_set(uint8_t conn_id, bool command) +{ + uint16_t handle; + uint16_t length; + uint8_t *pdata; + uint16_t cccd_value; + handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD]; + if (handle) + { + cccd_value = command ? 1 : 0; + length = sizeof(uint16_t); + pdata = (uint8_t *)&cccd_value; + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_REQ, handle, length, + pdata) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + DFU_PRINT_INFO0("dfu_client_cp_cccd_set: Request fail! Please check!"); + return false; +} + +/** + * @brief Used internal, to send write request to peer server's V5 Control Point Characteristic. + * @param ctl_pnt_ptr: pointer of control point data to write. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_cp_write(uint8_t conn_id, uint8_t *pdata, uint16_t length) +{ + uint16_t handle; + DFU_PRINT_INFO2("==>dfu_client_cp_write: opcode = %d, datalen = %d.", pdata[0], + length); //opcode = pdata[0] + g_dfu_fsm_write = DFU_FSM_WRITE_WAIT_WRITE_RESP; + handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP]; + if (handle) + { +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(if_queue_in(0, conn_id, dfu_client, handle, length, pdata) != 0) + { + printf("(conn_id %d)no dfu write request send\r\n", conn_id); + return false; + } + + request_in_process_flag[conn_id] = 1; + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_REQ, handle, length, pdata) == GAP_CAUSE_SUCCESS) + return true; + else + request_in_process_flag[conn_id] = 0; //if write request fail then reset flag=0 + +#else + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_REQ, handle, length, pdata) == GAP_CAUSE_SUCCESS) + return true; +#endif + } + DFU_PRINT_INFO0("==>dfu_client_cp_write: Request fail! Please check!"); + printf("==>dfu_client_cp_write: Request fail! Please check!\r\n"); + return false; +} + +/** + * @brief Used internal, to send write request to peer server's V5 Control Point Characteristic. + * @param ctl_pnt_ptr: pointer of control point data to write. + * @retval true--send request to upper stack success. + * flase--send request to upper stack failed. + */ +bool dfu_client_data_write(uint8_t conn_id, uint8_t *pdata, uint16_t length) +{ + uint16_t handle; + g_dfu_fsm_write = DFU_FSM_WRITE_DFU_DATA; + handle = dfu_table[conn_id].hdl_cache[HDL_DFU_DATA]; + DFU_PRINT_INFO2("==>dfu_client_data_write: datalen = %d, conn_id=%d", length, conn_id); + if (handle) + { + if (client_attr_write(conn_id, dfu_client, GATT_WRITE_TYPE_CMD, handle, length, + pdata) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + DFU_PRINT_INFO0("dfu_client_data_write: command fail! Please check!"); + return false; +} + +/** + * @brief Used internal, switch to the next CCCD handle to be discovered. + * NOTE--this function only used when peer service has more than one CCCD. + * @param pSwitchState: CCCD discovery state. + * @retval none. + */ +static void dfu_client_switch_next_descriptor(uint8_t conn_id, T_DFU_CCCD_DISC_STATE *cccd_state) +{ + T_DFU_CCCD_DISC_STATE new_state; + switch (*cccd_state) + { + case DFU_CCCD_DISC_START: + if (dfu_table[conn_id].hdl_cache[HDL_DFU_CP_END]) + { + new_state = DFU_CCCD_DISC_CP_NOTIFY; + } + else + { + new_state = DFU_CCCD_DISC_END; + } + break; + case DFU_CCCD_DISC_CP_NOTIFY: + new_state = DFU_CCCD_DISC_END; + break; + default: + new_state = DFU_CCCD_DISC_END; + break; + } + + *cccd_state = new_state; +} + +/** + * @brief Called by profile client layer, when discover state of discovery procedure changed. + * @param discoveryState: current service discovery state. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_disc_state_cb(uint8_t conn_id, T_DISCOVERY_STATE disc_state) +{ + bool cb_flag = false; + bool descriptor_disc_flag = false; + + uint16_t start_handle; + uint16_t end_handle; + + T_DFU_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DFU_CLIENT_CB_TYPE_DISC_STATE; + + DFU_PRINT_INFO1("dfu_client_disc_state_cb: disc_state = %d", disc_state); + printf("dfu_client_disc_state_cb: disc_state = %d\n", disc_state); + if (dfu_table[conn_id].disc_state == DISC_DFU_START) + { + switch (disc_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_START] != 0) + || (dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END] != 0)) + { + if (dfu_client_start_all_char_discovery(conn_id) == false) + { + cb_data.cb_content.disc_state = DISC_DFU_FAIL; + cb_flag = true; + } + } + /* No dfu service handle found. Discover procedure complete. */ + else + { + cb_data.cb_content.disc_state = DISC_DFU_FAIL; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + /* We should store the last char end handle if needed. */ + if (dfu_end_hdl_idx < HDL_DFU_CACHE_LEN) + { + dfu_table[conn_id].hdl_cache[dfu_end_hdl_idx] = dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END]; + dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + } + /* Find the first descriptor to be discovered. */ + dfu_cccd_disc_state = DFU_CCCD_DISC_START; + dfu_client_switch_next_descriptor(conn_id, &dfu_cccd_disc_state); + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + /* Find the next descriptor to be discovered. */ + dfu_client_switch_next_descriptor(conn_id, &dfu_cccd_disc_state); + break; + default: + DFU_PRINT_INFO0("dfu_client_disc_state_cb: Invalid Discovery State!"); + break; + } + } + + /* Switch different char descriptor discovery, if has multi char descriptors. */ + switch (dfu_cccd_disc_state) + { + case DFU_CCCD_DISC_CP_NOTIFY: + /* Need to discover notify char descriptor. */ + start_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP] + 1; + end_handle = dfu_table[conn_id].hdl_cache[HDL_DFU_CP_END]; + descriptor_disc_flag = true; + break; + case DFU_CCCD_DISC_END: + cb_data.cb_content.disc_state = DISC_DFU_DONE; + cb_flag = true; + break; + default: + /* No need to send char descriptor discovery. */ + break; + } + if (descriptor_disc_flag) + { + if (dfu_client_start_all_char_descriptor_discovery(conn_id, start_handle, end_handle) == false) + { + cb_data.cb_content.disc_state = DISC_DFU_FAIL; + cb_flag = true; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } +} + +/** + * @brief Called by profile client layer, when discover result fetched. + * @param resultType: indicate which type of value discovered in service discovery procedure. + * @param resultData: value discovered. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_disc_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: result_type = %d", result_type); + printf("==>dfu_client_disc_result_cb: result_type = %d\n", result_type); + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + /* send service handle range to application. */ + dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_START] = result_data.p_srv_disc_data->att_handle; + dfu_table[conn_id].hdl_cache[HDL_DFU_SRV_END] = result_data.p_srv_disc_data->end_group_handle; + break; + case DISC_RESULT_CHAR_UUID128: + /* When use clientAPI_AllCharDiscovery. */ + if (dfu_end_hdl_idx < HDL_DFU_CACHE_LEN) + { + DFU_PRINT_INFO2("==>dfu_client_disc_result_cb: dfu_end_hdl_idx = %d, hnadle=0x%4x", + dfu_end_hdl_idx, result_data.p_char_uuid128_disc_data->decl_handle - 1); + dfu_table[conn_id].hdl_cache[dfu_end_hdl_idx] = result_data.p_char_uuid128_disc_data->decl_handle - + 1; + dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + + } + /* we should inform intrested handles to upper application. */ + if (0 == memcmp(result_data.p_char_uuid128_disc_data->uuid128, dfu_data_uuid, 16)) + { + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: set dfu_data handle=0x%4x", + result_data.p_char_uuid128_disc_data->value_handle); + dfu_table[conn_id].hdl_cache[HDL_DFU_DATA] = result_data.p_char_uuid128_disc_data->value_handle; + } + else if (0 == memcmp(result_data.p_char_uuid128_disc_data->uuid128, dfu_control_point_uuid, 16)) + { + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: set dfu_control_point handle=0x%4x", + result_data.p_char_uuid128_disc_data->value_handle); + dfu_table[conn_id].hdl_cache[HDL_DFU_CP] = result_data.p_char_uuid128_disc_data->value_handle; + dfu_end_hdl_idx = HDL_DFU_CP_END; + } + break; + case DISC_RESULT_CHAR_DESC_UUID16: + /* When use clientAPI_AllCharDescriptorDiscovery. */ + if (result_data.p_char_desc_uuid16_disc_data->uuid16 == + GATT_UUID_CHAR_CLIENT_CONFIG) //GATT Client Characteristic Configuration descriptors uuid + { + uint16_t temp_handle = result_data.p_char_desc_uuid16_disc_data->handle; + if ((temp_handle > dfu_table[conn_id].hdl_cache[HDL_DFU_CP]) + && (temp_handle <= dfu_table[conn_id].hdl_cache[HDL_DFU_CP_END])) + { + DFU_PRINT_INFO1("==>dfu_client_disc_result_cb: set dfu_cccd handle=0x%4x", temp_handle); + dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD] = temp_handle; + } + else + { + /* have no intrest in this handle. */ + } + } + break; + default: + DFU_PRINT_INFO0("dfu_client_disc_result_cb: Invalid Discovery Result Type!"); + break; + } +} + +/** + * @brief Called by profile client layer, when read request responsed. + * @param reqResult: read request from peer device success or not. + * @param wHandle: handle of the value in read response. + * @param iValueSize: size of the value in read response. + * @param pValue: pointer to the value in read response. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_read_result_cb(uint8_t conn_id, uint16_t cause, uint16_t handle, + uint16_t len, uint8_t *pvalue) +{ + T_DFU_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DFU_CLIENT_CB_TYPE_READ_RESULT; + cb_data.cb_content.read_result.cause = cause; + DFU_PRINT_INFO3("==>dfu_client_read_result_cb: cause=%d, handle=0x%x, size=%d", cause, + handle, len); + printf("==>dfu_client_read_result_cb: cause=%d, handle=0x%x, size=%d\n", cause, + handle, len); + /* If read req success, branch to fetch value and send to application. */ + if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD]) + { + cb_data.cb_content.read_result.type = DFU_READ_CP_CCCD; + if (cause == GAP_SUCCESS && len == sizeof(uint16_t)) + { + uint16_t cccd_value = LE_EXTRN2WORD(pvalue); + cb_data.cb_content.read_result.data.dfu_cp_cccd = cccd_value & + GATT_CLIENT_CHAR_CONFIG_NOTIFY; + } + } + + /* Inform application the read result. */ + if (pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } +} + +/** + * @brief Called by profile client layer, when write request complete. + * @param reqResult: write request send success or not. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static void dfu_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, uint16_t handle, + uint16_t cause, uint8_t credits) +{ + T_DFU_CLIENT_CB_DATA cb_data; + cb_data.cb_type = DFU_CLIENT_CB_TYPE_WRITE_RESULT; + cb_data.cb_content.write_result.cause = cause; + + DFU_PRINT_INFO4("==>dfu_client_write_result_cb: cause=%d, handle=0x%x, type=%d, credits=%d", + cause, handle, type, credits); + printf("==>dfu_client_write_result_cb: cause=%d, handle=0x%x, type=%d, credits=%d\n", + cause, handle, type, credits); + /* If write req success, branch to fetch value and send to application. */ + if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP_CCCD]) + + { + cb_data.cb_content.write_result.type = DFU_WRITE_CP_CCCD; + } + else if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP]) + { + cb_data.cb_content.write_result.type = DFU_WRITE_CP; + } + else if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_DATA]) + { + cb_data.cb_content.write_result.type = DFU_WRITE_DATA; + } + else + { + return; + } + + /* Inform application the write result. */ + if (pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } +} + +/** + * @brief Called by profile client layer, when notification or indication arrived. + * @param wHandle: handle of the value in received data. + * @param iValueSize: size of the value in received data. + * @param pValue: pointer to the value in received data. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +static T_APP_RESULT dfu_client_notify_indicate_cb(uint8_t conn_id, bool notify, + uint16_t handle, uint16_t len, uint8_t *pvalue) +{ + T_APP_RESULT app_result = APP_RESULT_REJECT; + T_DFU_CLIENT_CB_DATA cb_data; + + DFU_PRINT_INFO3("==>dfu_client_notify_indicate_cb: handle=0x%x, len=%d, is notify=%d", + handle, len, notify); + printf("==>dfu_client_notify_indicate_cb: handle=0x%x, len=%d, is notify=%d\n", + handle, len, notify); + if (handle == dfu_table[conn_id].hdl_cache[HDL_DFU_CP]) + { + cb_data.cb_type = DFU_CLIENT_CB_TYPE_NOTIF_IND_RESULT; + cb_data.cb_content.notif_ind_data.type = DFU_NOTIF_RECEIVE_DFU_CP_NOTIFY; + cb_data.cb_content.notif_ind_data.value.len = len; + cb_data.cb_content.notif_ind_data.value.pdata = pvalue; + + /* Inform application the notif/ind result. */ + if (pf_dfu_client_cb) + { + (*pf_dfu_client_cb)(dfu_client, conn_id, &cb_data); + } + app_result = APP_RESULT_SUCCESS; + } + + return app_result; +} + +/** + * @brief Called by profile client layer, when link disconnected. + * NOTE--we should reset some state when disconnected. + * @retval ProfileResult_Success--procedure OK. + * other--procedure exception. + */ +void dfu_client_disconnect_cb(uint8_t conn_id) +{ + DFU_PRINT_INFO1("dfu_client_disconnect_cb: conn_id=%d", conn_id); + + dfu_end_hdl_idx = HDL_DFU_CACHE_LEN; + dfu_cccd_disc_state = DFU_CCCD_DISC_START; + dfu_client_init(); + + if (g_dfu_ctx.fsm_client == DFU_CB_START) + { + g_dfu_ctx.fsm_client = DFU_CB_NONE; + if (pf_dfu_client_app_info_cb) + { + T_DFU_CB_MSG cb_msg; + cb_msg.type = DFU_CB_FAIL; + pf_dfu_client_app_info_cb(dfu_client, conn_id, &cb_msg); + } + } +} + + +static void swap_buf(uint8_t *dst, const uint8_t *src, uint16_t len) +{ + int i; + if (dst == NULL || src == NULL) + { + return; + } + + for (i = 0; i < len; i++) + { + dst[len - 1 - i] = src[i]; + } +} + +unsigned char bt_ota_central_client_tmp_image[16] __attribute__((aligned(32))) = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char bt_ota_central_client_tmp_encrypted[16] __attribute__((aligned(32))) = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +unsigned char bt_ota_central_client_tmp_key[32] __attribute__((aligned(32))) = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +bool dfu_encrypt(uint8_t image[16]) +{ + int ret = false; + +#if defined(CONFIG_PLATFORM_8710C) + const u8 *key; + + swap_buf(bt_ota_central_client_tmp_key, bt_ota_central_client_get_key(), 32); + key = bt_ota_central_client_tmp_key; + + memcpy(bt_ota_central_client_tmp_image, image, 16); + + device_mutex_lock(RT_DEV_LOCK_CRYPTO); + ret = crypto_aes_ecb_init(key, 32); + if(ret != 0){ + printf("crypto_aes_ecb_init: ret=%d\n", ret); + return ret; + } + ret = crypto_aes_ecb_encrypt(bt_ota_central_client_tmp_image, 16, NULL, 0, bt_ota_central_client_tmp_encrypted); + if(ret !=0){ + printf("crypto_aes_ecb_encrypt: ret=%d\n", ret); + return ret; + } + device_mutex_unlock(RT_DEV_LOCK_CRYPTO); + + memcpy(image, bt_ota_central_client_tmp_encrypted, 16); +#endif + + return ret; +} + +uint16_t dfu_client_crc_cal(uint8_t *buf, uint32_t length, uint16_t checksum16) +{ + uint32_t i; + uint16_t *p16; + p16 = (uint16_t *)buf; + for (i = 0; i < length / 2; ++i) + { + checksum16 = checksum16 ^ (*p16); + ++p16; + } + return checksum16; +} + +bool dfu_client_push_image(uint8_t conn_id) +{ + uint16_t mtu_size = 0; + uint16_t push_img_size = 0; + uint32_t image_size = 0; + uint8_t *pheader; + uint8_t *pdata; + + DFU_PRINT_INFO0("==>dfu_client_push_image"); + if (g_dfu_fsm_write == DFU_FSM_WRITE_WAIT_WRITE_RESP) + { + // in case that the credit is bigger then the buffer check packet num + DFU_PRINT_INFO0("==>dfu_client_push_image: current waiting cp response"); + return false; + } + +#if 0 + mtu_size = 20; +#else + le_get_conn_param(GAP_PARAM_CONN_MTU_SIZE, &mtu_size, 0); + DFU_PRINT_INFO1("==>dfu_client_push_image: mtu_size=%d", mtu_size); + mtu_size -= 3; + mtu_size &= 0xfff0; //mtu size down align 16 bytes +#endif + + image_size = g_dfu_ctx.image_length - g_dfu_ctx.curr_offset; + push_img_size = MIN(image_size, mtu_size); + DFU_PRINT_INFO2("==>dfu_client_push_image: push_img_size=%d, img_size=%d", push_img_size, + image_size); + +#if (SILENT_OTA == 0) + if (!g_dfu_ctx.mode.buffercheck) + { + image_size = NORMAL_OTA_MAX_BUFFER_SIZE - (g_dfu_ctx.curr_offset % NORMAL_OTA_MAX_BUFFER_SIZE); + push_img_size = MIN(image_size, push_img_size); + DFU_PRINT_INFO2("==>dfu_client_push_image: push_img_size=%d, img_size=%d", push_img_size, + image_size); + } + +#endif + + DFU_PRINT_INFO3("==>dfu_client_push_image: image_length=%d, g_dfu_ctx.curr_offset=%d, push_img_size=%d", + g_dfu_ctx.image_length, g_dfu_ctx.curr_offset, push_img_size); + + //pheader = (uint8_t *)TEMP_OTA_IMG_ADDR; + pheader = bt_ota_central_client_get_image(); + pdata = os_mem_alloc(RAM_TYPE_DATA_ON, push_img_size); //send one packet(mtu size) or left img size + if (pdata == NULL) + { + return false; + } + memcpy(pdata, pheader + g_dfu_ctx.curr_offset, push_img_size); + g_dfu_ctx.curr_offset += push_img_size; + + //aes encrypt when ota and all data is encrypted + if (g_dfu_ctx.mode.aesflg && g_dfu_ctx.mode.aesmode) + { + uint8_t *ptmp = pdata; + for (uint16_t loop = 0; loop < push_img_size / 16; loop++) //only encrypt 16 bytes align + { + dfu_encrypt(ptmp); + ptmp += 16; + } + } + dfu_client_data_write(conn_id, pdata, push_img_size); + + //target enable buffer check + if (g_dfu_ctx.mode.buffercheck) + { + if (!g_buf_check_pkt_count) + { + g_buf_check_crc = 0; + } + g_buf_check_pkt_count++; + g_buf_check_crc = dfu_client_crc_cal(pdata, push_img_size, g_buf_check_crc); + if (g_buf_check_pkt_count == g_buf_check_pkt_num || g_dfu_ctx.curr_offset == g_dfu_ctx.image_length) + { + uint8_t data[5]; + data[0] = DFU_OPCODE_REPORT_BUFFER_CRC; + LE_WORD2EXTRN(data + 1, (g_buf_check_pkt_count - 1) * mtu_size + push_img_size); + BE_WORD2EXTRN(data + 3, g_buf_check_crc); + dfu_client_cp_write(conn_id, data, DFU_LENGTH_REPORT_BUFFER_CRC); + g_buf_check_pkt_count = 0; + } + } + + os_mem_free(pdata); + return true; +} + +void dfu_client_handle_cp_msg(uint8_t conn_id, uint8_t *pdata, uint16_t len) +{ + uint8_t opcode = pdata[0]; + uint8_t req_opcode = pdata[1]; + DFU_PRINT_INFO2("==>dfu_client_handle_cp_msg: opcode=%d len=%d.", req_opcode, len); + printf("==>dfu_client_handle_cp_msg: opcode=%d len=%d.\n", req_opcode, len); + if (opcode != DFU_OPCODE_NOTIFICATION) + { + DFU_PRINT_INFO1("==>handle cp msg: invalid notify opcode=%d!", opcode); + return; + } + + if (req_opcode == DFU_OPCODE_REPORT_TARGET_INFO && len == DFU_NOTIFY_LENGTH_REPORT_TARGET_INFO) + { +#if (RCU_SILENT_OTA == 1) + uint16_t target_version = LE_EXTRN2WORD(pdata + 3); //obey git_ver format + uint32_t cur_offset = LE_EXTRN2DWORD(pdata + 5); + printf("handle cp msg: report target info(bee2 rcu)\r\n");//debug +#else + + uint32_t target_version = LE_EXTRN2DWORD(pdata + 3); //obey git_ver format + uint32_t cur_offset = LE_EXTRN2DWORD(pdata + 7); + PROFILE_PRINT_INFO5("handle cp msg: report target info, target_version=%d.%d.%d.%d, cur_offset=0x%x", + MAJOR_IMG_VER(target_version), MINOR_IMG_VER(target_version), + REVISION_IMG_VER(target_version), RESERVE_IMG_VER(target_version), cur_offset); + +#if (ONLY_SUPPORT_UPGRADE == 1) + if (IMG_VER_TO_LITTLE_ENDIAN(LE_EXTRN2DWORD(g_dfu_ctx.dfu_img_version) <= IMG_VER_TO_LITTLE_ENDIAN( + LE_EXTRN2DWORD(pdata + 3))) + { + DBG_DIRECT("handle cp msg: Img no need ota!"); + return; + } +#endif +#endif + + //uint8_t *pheader = (uint8_t *)TEMP_OTA_IMG_ADDR; + uint8_t *pheader = bt_ota_central_client_get_image(); + uint8_t data[DFU_LENGTH_START_DFU]; + data[0] = DFU_OPCODE_START_DFU; + memcpy(data + 1, pheader, DFU_HEADER_SIZE); + memset(data + 1 + DFU_HEADER_SIZE, 0, 4); + + //aes encrypt when ota + if (g_dfu_ctx.mode.aesflg) + { + DFU_PRINT_TRACE1("===>Data before encryped: %b", TRACE_BINARY(16, data + 1)); + dfu_encrypt(data + 1); + DFU_PRINT_TRACE1("===>Data after encryped: %b", TRACE_BINARY(16, data + 1)); + } + + dfu_client_cp_write(conn_id, data, DFU_LENGTH_START_DFU); + g_dfu_ctx.curr_offset = DFU_HEADER_SIZE; + g_dfu_ctx.image_length = ((T_IMG_CTRL_HEADER_FORMAT *)pheader)->payload_len + IMG_HEADER_SIZE; + DFU_PRINT_INFO4("==>handle cp msg: otaing img_id 0x%x, verision 0x%x->0x%x, dfu_img_total_len=%d", + g_dfu_ctx.signature, target_version, g_dfu_ctx.dfu_img_version, g_dfu_ctx.image_length); + + /*notify application*/ + g_dfu_ctx.fsm_client = DFU_CB_START; + if (pf_dfu_client_app_info_cb) + { + T_DFU_CB_MSG cb_msg; + cb_msg.type = DFU_CB_START; + pf_dfu_client_app_info_cb(dfu_client, conn_id, &cb_msg); + } + } + else if (req_opcode == DFU_OPCODE_START_DFU && len == DFU_NOTIFY_LENGTH_ARV) + { + if (g_dfu_ctx.mode.buffercheck) + { + DFU_PRINT_INFO0("==>handle cp msg: Enable buffer check"); + uint8_t data[1]; + data[0] = DFU_OPCODE_BUFFER_CHECK_EN; + dfu_client_cp_write(conn_id, data, DFU_LENGTH_BUFFER_CHECK_EN); + } + else + { + DFU_PRINT_INFO0("==>handle cp msg: Disable buffer check"); + //start push image, make use of credits + for (uint8_t loop = 0; loop < 4; loop++) + { + dfu_client_push_image(conn_id); + } + } + } + else if (req_opcode == DFU_OPCODE_BUFFER_CHECK_EN && len == DFU_NOTIFY_LENGTH_BUFFER_CHECK_EN) + { + uint16_t buffer_check_len = LE_EXTRN2WORD(pdata + 3); + uint16_t mtu_size = LE_EXTRN2WORD(pdata + 5); + + g_buf_check_pkt_num = buffer_check_len / ((mtu_size - 3) & 0xfff0); //buffer check paket num + g_buf_check_pkt_count = 0; + + DFU_PRINT_INFO3("==>handle cp msg: buffer_check_lengeth=%d, mtu_size=%d, g_buf_check_pkt_num=%d", + buffer_check_len, mtu_size, g_buf_check_pkt_num); + + //start push image, make use of credits + for (uint8_t loop = 0; loop < 8; loop++) + { + dfu_client_push_image(conn_id); + } + } + else if (req_opcode == DFU_OPCODE_REPORT_BUFFER_CRC && len == DFU_NOTIFY_LENGTH_REPORT_BUFFER_CRC) + { + uint32_t offset = LE_EXTRN2DWORD(pdata + 3); + DFU_PRINT_INFO2("==>handle cp msg: Target offset=%d,g_dfu_ctx.curr_offset=%d", offset, + g_dfu_ctx.curr_offset); + g_dfu_ctx.curr_offset = offset; + if (g_dfu_ctx.image_length > g_dfu_ctx.curr_offset) + { + dfu_client_push_image(conn_id); + } + else + { + DFU_PRINT_INFO0("==>handle cp msg: Img trans done(BufCheckEn)!"); + uint8_t data[DFU_LENGTH_VALID_FW]; + data[0] = DFU_OPCODE_VALID_FW; + LE_WORD2EXTRN(data + 1, g_dfu_ctx.signature); + dfu_client_cp_write(conn_id, data, DFU_LENGTH_VALID_FW); + } + } + else if (req_opcode == DFU_OPCODE_VALID_FW && len == DFU_NOTIFY_LENGTH_ARV) + { + DFU_PRINT_INFO1("==>handle cp msg: verify image rst=%d(1 success)", pdata[2]); + uint8_t data[DFU_LENGTH_ACTIVE_IMAGE_RESET]; + data[0] = pdata[2] == DFU_ARV_SUCCESS ? DFU_OPCODE_ACTIVE_IMAGE_RESET : DFU_OPCODE_SYSTEM_RESET; + dfu_client_cp_write(conn_id, data, DFU_LENGTH_ACTIVE_IMAGE_RESET); + g_dfu_ctx.fsm_client = DFU_CB_NONE; + if (pf_dfu_client_app_info_cb) + { + T_DFU_CB_MSG cb_msg; + cb_msg.type = pdata[2] == DFU_ARV_SUCCESS ? DFU_CB_END : DFU_CB_FAIL; + pf_dfu_client_app_info_cb(dfu_client, conn_id, &cb_msg); + } + } +} + +/*profile callback to handle msg*/ +T_APP_RESULT dfu_client_handle_msg(T_CLIENT_ID client_id, uint8_t conn_id, void *p_data) +{ + T_DFU_CLIENT_CB_DATA *pcb_data = (T_DFU_CLIENT_CB_DATA *)p_data; + DFU_PRINT_INFO2("==>dfu client hdl msg: type=%d, g_dfu_fsm_write=%d.", pcb_data->cb_type, + g_dfu_fsm_write); + printf("==>dfu client hdl msg: client_id=%d, type=%d, g_dfu_fsm_write=%d.\n", client_id, pcb_data->cb_type, + g_dfu_fsm_write); + switch (pcb_data->cb_type) + { + case DFU_CLIENT_CB_TYPE_DISC_STATE: + switch (pcb_data->cb_content.disc_state) + { + case DISC_DFU_DONE: + /* Discovery Simple BLE service procedure successfully done. */ + DFU_PRINT_INFO0("==>dfu client hdl msg: discover procedure done."); + + if (dfu_client_cp_cccd_set(conn_id, 1)) //enable server notification + { + g_dfu_fsm_write = DFU_FSM_WRITE_CCCD_ENABLE; + DFU_PRINT_INFO0("==>dfu client hdl msg: Enable CCCD."); + } + break; + case DISC_DFU_FAIL: + /* Discovery Request failed. */ + DFU_PRINT_INFO0("==>dfu client hdl msg: discover request failed."); + break; + default: + break; + } + break; + case DFU_CLIENT_CB_TYPE_READ_RESULT: + switch (pcb_data->cb_content.read_result.type) + { + case DFU_READ_CP_CCCD: + DFU_PRINT_INFO1("==>dfu client hdl msg: dfu_cp_cccd=%d.", + pcb_data->cb_content.read_result.data.dfu_cp_cccd); + break; + default: + break; + } + break; + case DFU_CLIENT_CB_TYPE_WRITE_RESULT: + if (pcb_data->cb_content.write_result.cause == 0) + { +#if defined(CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT) && CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT + if(pcb_data->cb_content.write_result.type == DFU_WRITE_CP_CCCD || pcb_data->cb_content.write_result.type == DFU_WRITE_CP) + { + request_in_process_flag[conn_id] = 0; + if_queue_out_and_send(conn_id); + } +#endif + switch (pcb_data->cb_content.write_result.type) + { + case DFU_WRITE_CP_CCCD: + DFU_PRINT_INFO1("==>dfu client hdl msg: CB Type(DFU_WRITE_CP_CCCD),g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_CCCD_ENABLE) + { + //T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)TEMP_OTA_IMG_ADDR; + uint8_t *ota_app_image = bt_ota_central_client_get_image(); + T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)ota_app_image; + + g_dfu_ctx.signature = p_header->ctrl_header.image_id; + uint8_t data[DFU_LENGTH_REPORT_TARGET_INFO]; + data[0] = DFU_OPCODE_REPORT_TARGET_INFO; + LE_WORD2EXTRN(data + 1, g_dfu_ctx.signature); + + /*after enable CCCD, start handle control point procedure*/ + dfu_client_cp_write(conn_id, data, DFU_LENGTH_REPORT_TARGET_INFO); + } + break; + case DFU_WRITE_DATA: + DFU_PRINT_INFO1("==>dfu client hdl msg: CB Type(DFU_WRITE_DATA),g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_DFU_DATA) + { + if (g_dfu_ctx.image_length > g_dfu_ctx.curr_offset) + { + DFU_PRINT_INFO0("==>dfu client hdl msg: CB Type(DFU_WRITE_DATA)"); + dfu_client_push_image(conn_id); + } + else + { + if (!g_dfu_ctx.mode.buffercheck) + { + /*when not enable buf check, img trans done, verify img*/ + DFU_PRINT_INFO0("==>dfu client hdl msg: Img trans done(BufCheckDisable)"); + uint8_t data[DFU_LENGTH_VALID_FW]; + data[0] = DFU_OPCODE_VALID_FW; + LE_WORD2EXTRN(data + 1, g_dfu_ctx.signature); + dfu_client_cp_write(conn_id, data, DFU_LENGTH_VALID_FW); + } + } + } + break; + case DFU_WRITE_CP: + DFU_PRINT_INFO1("==>dfu client hdl msg: DFU_WRITE_CP, g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_WAIT_WRITE_RESP) + { + g_dfu_fsm_write = DFU_FSM_WRITE_DO_NOT_CARE; + if (g_cp_msg_len) + { + DFU_PRINT_INFO2("==>dfu client hdl msg: DFU_WRITE_CP, g_dfu_fsm_write=%d, g_cp_msg_len=%d", + g_dfu_fsm_write, g_cp_msg_len); + dfu_client_handle_cp_msg(conn_id, g_cp_msg, g_cp_msg_len); + g_cp_msg_len = 0; + } + } + break; + default: + break; + } + } + else + { + DFU_PRINT_INFO3("==>dfu client hdl msg: fail to send msg! type=%d, cause=0x%x g_dfu_fsm_write=%d", + pcb_data->cb_content.write_result.type, pcb_data->cb_content.write_result.cause, g_dfu_fsm_write); + DFU_PRINT_INFO0("==>dfu client hdl msg: le_disconnect"); + le_disconnect(conn_id); + } + break; + case DFU_CLIENT_CB_TYPE_NOTIF_IND_RESULT: + switch (pcb_data->cb_content.notif_ind_data.type) + { + case DFU_NOTIF_RECEIVE_DFU_CP_NOTIFY: + { + DFU_PRINT_INFO1("==>dfu client hdl msg: NOTIF_IND_RESULT, g_dfu_fsm_write=%d.", + g_dfu_fsm_write); + if (g_dfu_fsm_write == DFU_FSM_WRITE_DO_NOT_CARE) + { + DFU_PRINT_INFO1("==>dfu client hdl msg: NOTIF_IND_RESULT, g_dfu_fsm_write=%d(if 0 hdl cp msg)", + g_dfu_fsm_write); + dfu_client_handle_cp_msg(conn_id, pcb_data->cb_content.notif_ind_data.value.pdata, + pcb_data->cb_content.notif_ind_data.value.len); + } + else + { + //cache + g_cp_msg_len = pcb_data->cb_content.notif_ind_data.value.len; + memcpy(g_cp_msg, pcb_data->cb_content.notif_ind_data.value.pdata, + g_cp_msg_len > 20 ? 20 : g_cp_msg_len); + DFU_PRINT_INFO1("==>dfu client hdl msg: Cached Received Notify Data, len=%d", g_cp_msg_len); + + } + } + break; + default: + break; + } + break; + + default: + break; + } + return APP_RESULT_SUCCESS; +} + +/** + * @brief Dfu Client Callbacks. +*/ +const T_FUN_CLIENT_CBS dfu_client_cbs = +{ + dfu_client_disc_state_cb, //!< Discovery State callback function pointer + dfu_client_disc_result_cb, //!< Discovery result callback function pointer + dfu_client_read_result_cb, //!< Read response callback function pointer + dfu_client_write_result_cb, //!< Write result callback function pointer + dfu_client_notify_indicate_cb, //!< Notify Indicate callback function pointer + NULL //dfu_client_disconnect_cb //!< Link disconnection callback function pointer +}; + +static void dfu_client_init(void) +{ + //T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)TEMP_OTA_IMG_ADDR; + uint8_t *ota_app_image = bt_ota_central_client_get_image(); + T_IMG_HEADER_FORMAT *p_header = (T_IMG_HEADER_FORMAT *)ota_app_image; + + if (p_header && p_header->ctrl_header.payload_len) + { + T_IMG_ID dfu_img_id = (T_IMG_ID)p_header->ctrl_header.image_id; + if (dfu_img_id < IMAGE_MAX && dfu_img_id >= SecureBoot) + { + DFU_PRINT_INFO5("==>dfu_client_init: will dfu img:0x%x, version:%d.%d.%d.%d", dfu_img_id, + MAJOR_IMG_VER(p_header->git_ver.ver_info.version), + MINOR_IMG_VER(p_header->git_ver.ver_info.version), + REVISION_IMG_VER(p_header->git_ver.ver_info.version), + RESERVE_IMG_VER(p_header->git_ver.ver_info.version)); + + g_dfu_ctx.dfu_img_version = p_header->git_ver.ver_info.version; + } + else + { + DFU_PRINT_ERROR1("==>dfu_client_init: Temp bank img_id:0x%x Invalid!", dfu_img_id); + } + + + } + +#if defined(CONFIG_PLATFORM_8710C) + if(crypto_init()) printf("crypto_init fail!\n"); +#endif +} + +/** + * @brief add Dfu client to application. + * @param appCB: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID dfu_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > DFU_MAX_LINKS) + { + PROFILE_PRINT_ERROR1("dfu_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&dfu_client, &dfu_client_cbs)) + { + dfu_client = CLIENT_PROFILE_GENERAL_ID; + DFU_PRINT_ERROR0("dfu_client_add: fail!"); + return dfu_client; + } + DFU_PRINT_INFO1("dfu_client_add: client ID = %d", dfu_client); + APP_PRINT_INFO1("dfu_client_add: client ID = %d", dfu_client); + + dfu_link_num = link_num; + size = dfu_link_num * sizeof(T_DFU_LINK); + dfu_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + /* register callback for profile to inform application that some events happened. */ + pf_dfu_client_cb = dfu_client_handle_msg; + pf_dfu_client_app_info_cb = app_cb; + dfu_client_init(); + + return dfu_client; +} + +void dfu_delete_client(void) +{ + if (dfu_table != NULL) { + os_mem_free(dfu_table); + dfu_table = NULL; + } +} + + +/** + * @brief dfu client connect target device. + * @param p_le_scan_info: filtered scan info + */ +void dfu_client_connect_device(T_LE_SCAN_INFO *p_le_scan_info) +{ + PROFILE_PRINT_INFO1("dfu_client_connect_device: p_le_scan_info->adv_type = %d", + p_le_scan_info->adv_type); + + /* corresponding to silent ota or normal ota */ + if (p_le_scan_info->adv_type == GAP_ADV_EVT_TYPE_UNDIRECTED || + p_le_scan_info->adv_type == GAP_ADV_EVT_TYPE_SCAN_RSP) + { + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + conn_req_param.scan_interval = 0x10; + conn_req_param.scan_window = 0x10; + conn_req_param.conn_interval_min = 0x80; + conn_req_param.conn_interval_max = 0x80; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + T_GAP_CAUSE cause; + if (GAP_CAUSE_SUCCESS == (cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, p_le_scan_info->bd_addr, + p_le_scan_info->remote_addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, 1000))) + { + + PROFILE_PRINT_INFO2("==>dfu_client_connect_device: try connecting %s, remote_addr_type=%d", + TRACE_BDADDR(p_le_scan_info->bd_addr), p_le_scan_info->remote_addr_type); + } + else + { + PROFILE_PRINT_WARN1("==>dfu_client_connect_device: FAIL cause=%d!", cause); + } + } + else + { + PROFILE_PRINT_ERROR1("dfu_client_connect_device: invalid adv type=%d!", p_le_scan_info->adv_type); + } + + return; +} + diff --git a/component/common/bluetooth/realtek/sdk/src/ble/profile/client/ota_client.c b/component/common/bluetooth/realtek/sdk/src/ble/profile/client/ota_client.c new file mode 100644 index 00000000..e480db29 --- /dev/null +++ b/component/common/bluetooth/realtek/sdk/src/ble/profile/client/ota_client.c @@ -0,0 +1,654 @@ +/** +***************************************************************************************** +* Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved. +***************************************************************************************** + * @file ota_client.c + * @brief ota service client source file. + * @details + * @author + * @date + * @version + ****************************************************************************** + * @attention + *

© COPYRIGHT 2015 Realtek Semiconductor Corporation

+ ****************************************************************************** + */ + +/** Add Includes here **/ +#include +#include +#include "trace_app.h" +#include "gap_conn_le.h" +#include "bt_types.h" +#include "mem_types.h" +#include "os_mem.h" +#include "ota_client.h" +/** + * @brief OTA client Link control block definition. + */ +typedef struct +{ + T_OTA_DISC_STATE disc_state; + uint16_t hdl_cache[HDL_OTA_CACHE_LEN]; +} T_OTA_LINK, *P_OTA_LINK; + + +static P_OTA_LINK ota_table; +static uint8_t ota_link_num; + +/**< OTA client ID. */ +static T_CLIENT_ID ota_client = CLIENT_PROFILE_GENERAL_ID; +/**< Callback used to send data to app from OTA client layer. */ +static P_FUN_GENERAL_APP_CB ota_client_cb = NULL; + +const uint8_t ota_service_uuid[16] = {GATT_UUID_OTA_SERVICE}; + +/** + * @brief Used by application, to start the discovery procedure of OTA server. + * @param[in] conn_id connection ID. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool ota_client_start_discovery(uint8_t conn_id) +{ + APP_PRINT_INFO0("ota_client_start_discovery"); + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_start_discovery: failed invalid conn_id %d", conn_id); + return false; + } + /* First clear handle cache. */ + memset(&ota_table[conn_id], 0, sizeof(T_OTA_LINK)); + ota_table[conn_id].disc_state = DISC_OTA_START; + if (client_by_uuid128_srv_discovery(conn_id, ota_client, + (uint8_t *)ota_service_uuid) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + + +static bool ota_client_start_char_discovery(uint8_t conn_id) +{ + uint16_t start_handle; + uint16_t end_handle; + + APP_PRINT_INFO0("ota_client_start_char_discovery"); + start_handle = ota_table[conn_id].hdl_cache[HDL_OTA_SRV_START]; + end_handle = ota_table[conn_id].hdl_cache[HDL_OTA_SRV_END]; + if (client_all_char_discovery(conn_id, ota_client, start_handle, + end_handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + return false; +} + +/** + * @brief Used by application, to read data from server by using handles. + * @param[in] conn_id connection ID. + * @param[in] read_type one of characteristic that has the readable property. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool ota_client_read_by_handle(uint8_t conn_id, T_OTA_READ_TYPE read_type) +{ + bool hdl_valid = false; + uint16_t handle; + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_read_by_handle: failed invalid conn_id %d", conn_id); + return false; + } + + switch (read_type) + { + case OTA_READ_DEVICE_MAC: + if (ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_MAC]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_MAC]; + hdl_valid = true; + } + break; + case OTA_READ_PATCH_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_VER]; + hdl_valid = true; + } + break; + case OTA_READ_APP_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_APP_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_APP_VER]; + hdl_valid = true; + } + break; + case OTA_READ_PATCH_EXT_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_EXT_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_PATCH_EXT_VER]; + hdl_valid = true; + } + break; + case OTA_READ_DEVICE_INFO: + if (ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_INFO]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_DEVICE_INFO]; + hdl_valid = true; + } + break; + case OTA_READ_IMG_VER: + if (ota_table[conn_id].hdl_cache[HDL_OTA_IMG_VER]) + { + handle = ota_table[conn_id].hdl_cache[HDL_OTA_IMG_VER]; + hdl_valid = true; + } + break; + + default: + return false; + } + + if (hdl_valid) + { + if (client_attr_read(conn_id, ota_client, handle) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + + APP_PRINT_WARN0("ota_client_read_by_handle: Request fail! Please check!"); + return false; +} + + +/** + * @brief Used by application, to write ota cmd write Characteristic. + * @param[in] conn_id connection ID. + * @param[in] length write data length + * @param[in] p_value point the value to write + * @param[in] type write type. + * @retval true send request to upper stack success. + * @retval false send request to upper stack failed. + */ +bool ota_client_write_char(uint8_t conn_id, T_OTA_WRTIE_TYPE write_type) +{ + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_write_char: failed invalid conn_id %d", conn_id); + return false; + } + + switch (write_type) + { + case OTA_WRITE_CMD: + { + PROFILE_PRINT_INFO1("write handle 0x%x", ota_table[conn_id].hdl_cache[HDL_OTA_CMD]); + if (ota_table[conn_id].hdl_cache[HDL_OTA_CMD]) + { + uint16_t handle = ota_table[conn_id].hdl_cache[HDL_OTA_CMD]; + uint8_t ota_cmd = OTA_WRITE_OTA_CMD_CHAR_VAL; + if (client_attr_write(conn_id, ota_client, GATT_WRITE_TYPE_CMD, handle, + sizeof(ota_cmd), &ota_cmd) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + break; + } + case OTA_WRITE_TEST_MODE: + { + if (ota_table[conn_id].hdl_cache[HDL_OTA_TEST_MODE]) + { + uint16_t handle = ota_table[conn_id].hdl_cache[HDL_OTA_TEST_MODE]; + uint8_t test_mode = OTA_WRITE_TEST_MODE_CHAR_VAL; + if (client_attr_write(conn_id, ota_client, GATT_WRITE_TYPE_CMD, handle, + sizeof(test_mode), &test_mode) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + break; + } + case OTA_WRITE_IMG_COUNTER: + { + if (ota_table[conn_id].hdl_cache[HDL_OTA_IMG_COUNTER]) + { + uint16_t handle = ota_table[conn_id].hdl_cache[HDL_OTA_IMG_COUNTER]; + uint8_t img_counter = OTA_WRITE_OTA_IMG_COUNTER_CHAR_VAL; + if (client_attr_write(conn_id, ota_client, GATT_WRITE_TYPE_CMD, handle, + sizeof(img_counter), &img_counter) == GAP_CAUSE_SUCCESS) + { + return true; + } + } + break; + } + default: + break; + + } + + PROFILE_PRINT_WARN1("ota_client_write_char fail! write_type: %d!", write_type); + return false; +} + + +/** + * @brief Used by application, to get handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool ota_client_get_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_get_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (ota_table[conn_id].disc_state != DISC_OTA_DONE) + { + PROFILE_PRINT_ERROR1("ota_client_get_hdl_cache: failed invalid state %d", + ota_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_OTA_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("ota_client_get_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(p_hdl_cache, ota_table[conn_id].hdl_cache, len); + return true; +} +/** + * @brief Used by application, to set handle cache. + * @param[in] conn_id connection ID. + * @param[in] p_hdl_cache pointer of the handle cache table + * @param[in] len the length of handle cache table + * @retval true success. + * @retval false failed. + */ +bool ota_client_set_hdl_cache(uint8_t conn_id, uint16_t *p_hdl_cache, uint8_t len) +{ + if (conn_id >= ota_link_num) + { + PROFILE_PRINT_ERROR1("ota_client_set_hdl_cache: failed invalid conn_id %d", conn_id); + return false; + } + if (ota_table[conn_id].disc_state != DISC_OTA_IDLE) + { + PROFILE_PRINT_ERROR1("ota_client_set_hdl_cache: failed invalid state %d", + ota_table[conn_id].disc_state); + return false; + } + if (len != sizeof(uint16_t) * HDL_OTA_CACHE_LEN) + { + PROFILE_PRINT_ERROR1("ota_client_set_hdl_cache: failed invalid len %d", len); + return false; + } + memcpy(ota_table[conn_id].hdl_cache, p_hdl_cache, len); + ota_table[conn_id].disc_state = DISC_OTA_DONE; + return true; +} + + +static void ota_client_discover_state_cb(uint8_t conn_id, T_DISCOVERY_STATE discovery_state) +{ + bool cb_flag = false; + T_OTA_CLIENT_CB_DATA cb_data; + cb_data.cb_type = OTA_CLIENT_CB_TYPE_DISC_STATE; + + PROFILE_PRINT_INFO1("ota_client_discover_state_cb: discovery_state = %d", discovery_state); + if (ota_table[conn_id].disc_state == DISC_OTA_START) + { + switch (discovery_state) + { + case DISC_STATE_SRV_DONE: + /* Indicate that service handle found. Start discover characteristic. */ + if ((ota_table[conn_id].hdl_cache[HDL_OTA_SRV_START] != 0) + || (ota_table[conn_id].hdl_cache[HDL_OTA_SRV_END] != 0)) + { + if (ota_client_start_char_discovery(conn_id) == false) + { + ota_table[conn_id].disc_state = DISC_OTA_FAILED; + cb_flag = true; + } + } + /* No ota handle found. Discover procedure complete. */ + else + { + ota_table[conn_id].disc_state = DISC_OTA_FAILED; + cb_flag = true; + } + break; + case DISC_STATE_CHAR_DONE: + ota_table[conn_id].disc_state = DISC_OTA_DONE; + cb_flag = true; + break; + case DISC_STATE_CHAR_DESCRIPTOR_DONE: + break; + default: + PROFILE_PRINT_ERROR0("Invalid Discovery State!"); + break; + } + } + + /* Send discover state to application if needed. */ + if (cb_flag && ota_client_cb) + { + cb_data.cb_content.disc_state = ota_table[conn_id].disc_state; + (*ota_client_cb)(ota_client, conn_id, &cb_data); + } + return; +} + + +static void ota_client_discover_result_cb(uint8_t conn_id, T_DISCOVERY_RESULT_TYPE result_type, + T_DISCOVERY_RESULT_DATA result_data) +{ + uint16_t handle; + uint16_t *hdl_cache; + hdl_cache = ota_table[conn_id].hdl_cache; + PROFILE_PRINT_INFO1("ota_client_discover_result_cb: result_type = %d", result_type); + if (ota_table[conn_id].disc_state == DISC_OTA_START) + { + switch (result_type) + { + case DISC_RESULT_SRV_DATA: + PROFILE_PRINT_INFO0("DISC_RESULT_SRV_DATA"); + ota_table[conn_id].hdl_cache[HDL_OTA_SRV_START] = + result_data.p_srv_disc_data->att_handle; + ota_table[conn_id].hdl_cache[HDL_OTA_SRV_END] = + result_data.p_srv_disc_data->end_group_handle; + break; + + case DISC_RESULT_CHAR_UUID16: + { + PROFILE_PRINT_INFO2("DISC_RESULT_CHAR_UUID16: handle 0x%x, uuid 0x%x", + result_data.p_char_uuid16_disc_data->value_handle, + result_data.p_char_uuid16_disc_data->uuid16); + handle = result_data.p_char_uuid16_disc_data->value_handle; + switch (result_data.p_char_uuid16_disc_data->uuid16) + { + case GATT_UUID_CHAR_OTA: + hdl_cache[HDL_OTA_CMD] = handle; + break; + case GATT_UUID_CHAR_MAC: + hdl_cache[HDL_OTA_DEVICE_MAC] = handle; + break; + case GATT_UUID_CHAR_PATCH: + hdl_cache[HDL_OTA_PATCH_VER] = handle; + break; + case GATT_UUID_CHAR_APP_VERSION: + hdl_cache[HDL_OTA_APP_VER] = handle; + break; + case GATT_UUID_CHAR_PATCH_EXTENSION: + hdl_cache[HDL_OTA_PATCH_EXT_VER] = handle; + break; + case GATT_UUID_CHAR_TEST_MODE: + hdl_cache[HDL_OTA_TEST_MODE] = handle; + break; + case GATT_UUID_CHAR_DEVICE_INFO: + hdl_cache[HDL_OTA_DEVICE_INFO] = handle; + break; + case GATT_UUID_CHAR_IMAGE_COUNT_TO_UPDATE: + hdl_cache[HDL_OTA_IMG_COUNTER] = handle; + break; + case GATT_UUID_CHAR_IMAGE_VERSION: + hdl_cache[HDL_OTA_IMG_VER] = handle; + break; + default: + /* have no intrest on this handle. */ + break; + } + } + break; + + default: + PROFILE_PRINT_ERROR0("Invalid Discovery Result Type!"); + break; + } + } + + return; +} + +static void ota_client_read_result_cb(uint8_t conn_id, uint16_t cause, + uint16_t handle, uint16_t value_size, uint8_t *p_value) +{ + T_OTA_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = ota_table[conn_id].hdl_cache; + cb_data.cb_type = OTA_CLIENT_CB_TYPE_READ_RESULT; + + PROFILE_PRINT_INFO2("ota_client_read_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.read_result.cause = cause; + + if (handle == hdl_cache[HDL_OTA_DEVICE_MAC]) + { + cb_data.cb_content.read_result.type = OTA_READ_DEVICE_MAC; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_PATCH_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_PATCH_VER; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_APP_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_APP_VER; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_PATCH_EXT_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_PATCH_EXT_VER; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_DEVICE_INFO]) + { + cb_data.cb_content.read_result.type = OTA_READ_DEVICE_INFO; + if (cause == GAP_SUCCESS) + { + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else if (handle == hdl_cache[HDL_OTA_IMG_VER]) + { + cb_data.cb_content.read_result.type = OTA_READ_IMG_VER; + if (cause == GAP_SUCCESS) + { + //ota header, secure boot, patch, app version + cb_data.cb_content.read_result.data.p_value = p_value; + cb_data.cb_content.read_result.data.value_size = value_size; + } + else + { + cb_data.cb_content.read_result.data.value_size = 0; + } + } + else + { + return; + } + + if (ota_client_cb) + { + (*ota_client_cb)(ota_client, conn_id, &cb_data); + } + return; +} + +static void ota_client_write_result_cb(uint8_t conn_id, T_GATT_WRITE_TYPE type, + uint16_t handle, + uint16_t cause, + uint8_t credits) +{ + T_OTA_CLIENT_CB_DATA cb_data; + uint16_t *hdl_cache; + hdl_cache = ota_table[conn_id].hdl_cache; + cb_data.cb_type = OTA_CLIENT_CB_TYPE_WRITE_RESULT; + + PROFILE_PRINT_INFO2("ota_client_write_result_cb: handle 0x%x, cause 0x%x", handle, cause); + cb_data.cb_content.write_result.cause = cause; + + if (handle == hdl_cache[HDL_OTA_CMD]) + { + cb_data.cb_content.write_result.type = OTA_WRITE_CMD; + } + else if (handle == hdl_cache[HDL_OTA_TEST_MODE]) + { + cb_data.cb_content.write_result.type = OTA_WRITE_TEST_MODE; + } + else if (handle == hdl_cache[HDL_OTA_IMG_COUNTER]) + { + cb_data.cb_content.write_result.type = OTA_WRITE_IMG_COUNTER; + } + else + { + return; + } + + /* Inform application the write result. */ + if (ota_client_cb) + { + (*ota_client_cb)(ota_client, conn_id, &cb_data); + } + return; +} + + +/** + * @brief OTA Client Callbacks. +*/ +const T_FUN_CLIENT_CBS ota_client_cbs = +{ + ota_client_discover_state_cb, //!< Discovery State callback function pointer + ota_client_discover_result_cb, //!< Discovery result callback function pointer + ota_client_read_result_cb, //!< Read response callback function pointer + ota_client_write_result_cb, //!< Write result callback function pointer + NULL, //ota_client_notify_ind_cb, //!< Notify Indicate callback function pointer + NULL//ota_client_disc_cb //!< Link disconnection callback function pointer +}; + +/** + * @brief add Dfu client to application. + * @param appCB: pointer of app callback function to handle specific client module data. + * @retval Client ID of the specific client module. + */ +T_CLIENT_ID ota_add_client(P_FUN_GENERAL_APP_CB app_cb, uint8_t link_num) +{ + uint16_t size; + if (link_num > OTA_MAX_LINKS) + { + PROFILE_PRINT_ERROR1("ota_add_client: invalid link_num %d", link_num); + return 0xff; + } + if (false == client_register_spec_client_cb(&ota_client, &ota_client_cbs)) + { + ota_client = CLIENT_PROFILE_GENERAL_ID; + DFU_PRINT_ERROR0("ota_client_add: fail!"); + return ota_client; + } + DFU_PRINT_INFO1("ota_client_add: client ID = %d", ota_client); + APP_PRINT_INFO1("ota_client_add: client ID = %d", ota_client); + ota_link_num = link_num; + size = ota_link_num * sizeof(T_OTA_LINK); + ota_table = os_mem_zalloc(RAM_TYPE_DATA_ON, size); + + /* register callback for profile to inform application that some events happened. */ + ota_client_cb = app_cb; + return ota_client; + +} + +void ota_delete_client(void) +{ + if (ota_table != NULL) { + os_mem_free(ota_table); + ota_table = NULL; + } +} + + +/** + * @brief ota client connect target device. + * @param p_le_scan_info: filtered scan info + */ +void ota_client_connect_device(T_LE_SCAN_INFO *p_le_scan_info) +{ + PROFILE_PRINT_INFO1("ota_client_connect_device: p_le_scan_info->adv_type = %d", + p_le_scan_info->adv_type); + if (p_le_scan_info->adv_type != GAP_ADV_EVT_TYPE_UNDIRECTED) + { + return; + } + + T_GAP_LE_CONN_REQ_PARAM conn_req_param; + conn_req_param.scan_interval = 0xA0; + conn_req_param.scan_window = 0x80; + conn_req_param.conn_interval_min = 0x60; + conn_req_param.conn_interval_max = 0x60; + conn_req_param.conn_latency = 0; + conn_req_param.supv_tout = 1000; + conn_req_param.ce_len_min = 2 * (conn_req_param.conn_interval_min - 1); + conn_req_param.ce_len_max = 2 * (conn_req_param.conn_interval_max - 1); + le_set_conn_param(GAP_CONN_PARAM_1M, &conn_req_param); + T_GAP_CAUSE cause; + if (GAP_CAUSE_SUCCESS == (cause = le_connect(GAP_PHYS_CONN_INIT_1M_BIT, p_le_scan_info->bd_addr, + p_le_scan_info->remote_addr_type, + GAP_LOCAL_ADDR_LE_PUBLIC, 1000))) + { + PROFILE_PRINT_INFO2("ota_client_connect_device: try connecting %s, remote_addr_type=%d", + TRACE_BDADDR(p_le_scan_info->bd_addr), p_le_scan_info->remote_addr_type); + } + else + { + PROFILE_PRINT_WARN1("ota_client_connect_device: FAIL cause=%d!", cause); + } + + + return; +} + diff --git a/component/common/drivers/wlan/realtek/include/wifi_constants.h b/component/common/drivers/wlan/realtek/include/wifi_constants.h index d6987749..aaef60fe 100644 --- a/component/common/drivers/wlan/realtek/include/wifi_constants.h +++ b/component/common/drivers/wlan/realtek/include/wifi_constants.h @@ -166,6 +166,17 @@ enum { }; typedef unsigned long rtw_security_t; +enum +{ + WPA_AUTO_MODE, + WPA_ONLY_MODE, + WPA2_ONLY_MODE, + WPA3_ONLY_MODE, + WPA_WPA2_MIXED_MODE, + WPA2_WPA3_MIXED_MODE +}; +typedef unsigned long rtw_wpa_mode; + enum { RTW_ENCRYPTION_UNKNOWN = 0, RTW_ENCRYPTION_OPEN = 1, @@ -609,6 +620,8 @@ enum _WIFI_EVENT_INDICATE{ WIFI_EVENT_STA_LOST_IP = 24, WIFI_EVENT_NO_BEACON = 25, WIFI_EVENT_TARGET_SSID_RSSI = 26, + WIFI_EVENT_DHCP_RENEW = 27, + WIFI_EVENT_SWITCH_CHANNE = 28, WIFI_EVENT_MAX, }; typedef unsigned long rtw_event_indicate_t; diff --git a/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h b/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h index fd2d9b51..8df571a0 100644 --- a/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h +++ b/component/common/drivers/wlan/realtek/src/osdep/wlan_intf.h @@ -69,6 +69,7 @@ int rltk_wlan_check_bus(void); int rltk_wlan_wireless_mode(unsigned char mode); int rltk_wlan_get_wireless_mode(unsigned char *pmode); unsigned char rltk_get_band_type(void); +int rltk_wlan_set_wpa_mode(const char *ifname, unsigned int wpa_mode); int rltk_wlan_set_wps_phase(unsigned char is_trigger_wps); int rtw_ps_enable(int enable); int rltk_wlan_is_connected_to_ap(void); diff --git a/component/common/example/high_load_memory_use/example_high_load_memory_use.c b/component/common/example/high_load_memory_use/example_high_load_memory_use.c index cf3479ca..010c67c4 100644 --- a/component/common/example/high_load_memory_use/example_high_load_memory_use.c +++ b/component/common/example/high_load_memory_use/example_high_load_memory_use.c @@ -349,6 +349,14 @@ static void ssl_client_handler(void *param){ mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&conf, my_random, NULL); +#if (defined(MBEDTLS_SSL_IN_CONTENT_LEN) && (MBEDTLS_SSL_IN_CONTENT_LEN == 4096)) || \ + (defined(MBEDTLS_SSL_MAX_CONTENT_LEN) && (MBEDTLS_SSL_MAX_CONTENT_LEN == 4096)) + if(ret = mbedtls_ssl_conf_max_frag_len(&conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { + printf(" failed\n\r ! mbedtls_ssl_conf_max_frag_len returned %d\n", ret); + goto exit; + } +#endif + if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { printf(" failed\n\r ! ssl_setup returned %d\n", ret); goto exit; diff --git a/component/common/example/ipv6/example_ipv6.c b/component/common/example/ipv6/example_ipv6.c new file mode 100644 index 00000000..5b494afa --- /dev/null +++ b/component/common/example/ipv6/example_ipv6.c @@ -0,0 +1,454 @@ +#include "FreeRTOS.h" +#include "task.h" +#include +#include +#include +#include +#include +#include + +#if CONFIG_EXAMPLE_IPV6 + +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 +#if !LWIP_IPV6_SCOPES +#error "Please enable LWIP_IPV6_SCOPES" +#endif +#endif + +extern struct netif xnetif[]; +_sema ipv6_semaphore; + +static void example_ipv6_udp_server(void) +{ + int server_fd; + struct sockaddr_in6 ser_addr , client_addr; + + int addrlen = sizeof(struct sockaddr_in6); + + char send_data[MAX_SEND_SIZE] = "Hi client!"; + char recv_data[MAX_RECV_SIZE]; + + //create socket + if((server_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1){ + printf("\n\r[ERROR] Create socket failed\n"); + return; + } + printf("\n\r[INFO] Create socket successfully\n"); + + //initialize structure dest + memset(&ser_addr, 0, sizeof(ser_addr)); + ser_addr.sin6_family = AF_INET6; + ser_addr.sin6_port = htons(UDP_SERVER_PORT); + ser_addr.sin6_addr = (struct in6_addr) IN6ADDR_ANY_INIT; + + //Assign a port number to socket + if(bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) != 0){ + printf("\n\r[ERROR] Bind socket failed\n"); + closesocket(server_fd); + return; + } + printf("\n\r[INFO] Bind socket successfully\n"); + + while(1){ + memset(recv_data, 0, MAX_RECV_SIZE); + if(recvfrom(server_fd, recv_data, MAX_RECV_SIZE, 0, (struct sockaddr *)&client_addr, &addrlen) > 0){ + printf("\n\r[INFO] Receive data : %s\n",recv_data); + //Send Response + if(sendto(server_fd, send_data, MAX_SEND_SIZE, 0, (struct sockaddr *)&client_addr, addrlen) == -1){ + printf("\n\r[ERROR] Send data failed\n"); + } + else{ + printf("\n\r[INFO] Send data successfully\n"); + } + } + } + + closesocket(server_fd); + + return; +} + +static void example_ipv6_udp_client(void) +{ + int client_fd; + struct sockaddr_in6 ser_addr; +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + struct sockaddr_in6 src_addr6; + ip6_addr_t dest_addr6; +#endif + + int addrlen = sizeof(struct sockaddr_in6); + + char recv_data[MAX_RECV_SIZE]; + char send_data[MAX_SEND_SIZE] = "Hi Server!!"; + + //create socket + if((client_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1){ + printf("\n\r[ERROR] Create socket failed\n"); + return; + } + printf("\n\r[INFO] Create socket successfully\n"); + + //initialize value in dest + memset(&ser_addr, 0, sizeof(ser_addr)); + ser_addr.sin6_family = AF_INET6; + ser_addr.sin6_port = htons(UDP_SERVER_PORT); + inet_pton(AF_INET6, UDP_SERVER_IP, &(ser_addr.sin6_addr)); + +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + inet6_addr_to_ip6addr(&dest_addr6, &(ser_addr.sin6_addr)); + + if(ip6_addr_ismulticast_linklocal(&dest_addr6) || ip6_addr_ismulticast_iflocal(&dest_addr6) + || ip6_addr_islinklocal(&dest_addr6)){ + memset(&src_addr6, 0, sizeof(src_addr6)); + src_addr6.sin6_family = AF_INET6; + src_addr6.sin6_port = htons(UDP_SERVER_PORT); + inet6_addr_from_ip6addr(&src_addr6.sin6_addr, (ip6_addr_t*)&xnetif[0].ip6_addr[0]); + + if(bind(client_fd, (struct sockaddr*)&src_addr6, sizeof(src_addr6)) != 0){ + printf("\n\r[ERROR] Bind socket failed\n"); + closesocket(client_fd); + return; + } + } +#endif + + while(1){ + //Send data to server + if(sendto(client_fd, send_data, MAX_SEND_SIZE, 0, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) == -1){ + printf("\n\r[ERROR] Send data failed\n"); + } + else{ + printf("\n\r[INFO] Send data to server successfully\n"); + } + + //Receive data from server response + memset(recv_data, 0, MAX_RECV_SIZE); + if(recvfrom(client_fd, recv_data, MAX_RECV_SIZE, 0, (struct sockaddr *)&ser_addr, &addrlen) <= 0){ + //printf("\n\r[ERROR] Receive data failed\n"); + } + else{ + printf("\n\r[INFO] Receive from server: %s\n", recv_data); + } + vTaskDelay(1000); + } + + closesocket(client_fd); + + return; +} + +static void example_ipv6_tcp_server(void) +{ + int server_fd, client_fd; + struct sockaddr_in6 ser_addr , client_addr; + + int addrlen = sizeof(struct sockaddr_in6); + + char send_data[MAX_SEND_SIZE] = "Hi client!!"; + char recv_data[MAX_RECV_SIZE]; + + //create socket + if((server_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1){ + printf("\n\r[ERROR] Create socket failed\n"); + return; + } + printf("\n\r[INFO] Create socket successfully\n"); + + //initialize structure dest + memset(&ser_addr, 0, sizeof(ser_addr)); + ser_addr.sin6_family = AF_INET6; + ser_addr.sin6_port = htons(TCP_SERVER_PORT); + ser_addr.sin6_addr = (struct in6_addr) IN6ADDR_ANY_INIT; + + //Assign a port number to socket + if(bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) != 0){ + printf("\n\r[ERROR] Bind socket failed\n"); + closesocket(server_fd); + return; + } + printf("\n\r[INFO] Bind socket successfully\n"); + + //Make it listen to socket with max 20 connections + if(listen(server_fd, 20) != 0){ + printf("\n\r[ERROR] Listen socket failed\n"); + closesocket(server_fd); + return; + } + printf("\n\r[INFO] Listen socket successfully\n"); + + //Accept + if((client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addrlen)) == -1){ + printf("\n\r[ERROR] Accept connection failed\n"); + closesocket(server_fd); + closesocket(client_fd); + return; + } + printf("\n\r[INFO] Accept connection successfully\n"); + + while(1){ + memset(recv_data, 0, MAX_RECV_SIZE); + if(recv(client_fd, recv_data, MAX_RECV_SIZE, 0) > 0){ + printf("\n\r[INFO] Receive data : %s\n",recv_data); + //Send Response + if(send(client_fd, send_data, MAX_SEND_SIZE, 0) == -1){ + printf("\n\r[ERROR] Send data failed\n"); + } + else{ + printf("\n\r[INFO] Send data successfully\n"); + } + } + } + closesocket(client_fd); + closesocket(server_fd); + return; +} + +static void example_ipv6_tcp_client(void) +{ + int client_fd; + struct sockaddr_in6 ser_addr; +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + struct sockaddr_in6 src_addr6; + ip6_addr_t dest_addr6; +#endif + + int addrlen = sizeof(struct sockaddr_in6); + + char recv_data[MAX_RECV_SIZE]; + char send_data[MAX_SEND_SIZE] = "Hi Server!!"; + + //create socket + if((client_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)) == -1){ + printf("\n\r[ERROR] Create socket failed\n"); + return; + } + printf("\n\r[INFO] Create socket successfully\n"); + + //initialize value in dest + memset(&ser_addr, 0, sizeof(ser_addr)); + ser_addr.sin6_family = AF_INET6; + ser_addr.sin6_port = htons(TCP_SERVER_PORT); + inet_pton(AF_INET6, TCP_SERVER_IP, &(ser_addr.sin6_addr)); + +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + inet6_addr_to_ip6addr(&dest_addr6, &(ser_addr.sin6_addr)); + + if(ip6_addr_ismulticast_linklocal(&dest_addr6) || ip6_addr_ismulticast_iflocal(&dest_addr6) + || ip6_addr_islinklocal(&dest_addr6)){ + memset(&src_addr6, 0, sizeof(src_addr6)); + src_addr6.sin6_family = AF_INET6; + src_addr6.sin6_port = htons(TCP_SERVER_PORT); + inet6_addr_from_ip6addr(&src_addr6.sin6_addr, (ip6_addr_t*)&xnetif[0].ip6_addr[0]); + + if(bind(client_fd, (struct sockaddr*)&src_addr6, sizeof(src_addr6)) != 0){ + printf("\n\r[ERROR] Bind socket failed\n"); + closesocket(client_fd); + return; + } + } +#endif + + //Connecting to server + if(connect(client_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) == -1){ + printf("\n\r[ERROR] Connect to server failed\n"); + } + printf("[INFO] Connect to server successfully\n"); + + while(1){ + //Send data to server + if(send(client_fd, send_data, MAX_SEND_SIZE,0) == -1){ + printf("\n\r[ERROR] Send data failed\n"); + } + else{ + printf("\n\r[INFO] Send data to server successfully\n"); + } + + //Receive data from server response + if(recv(client_fd, recv_data, MAX_RECV_SIZE, 0) <= 0){ + //printf("\n\r[ERROR] Receive data failed\n"); + } + else{ + printf("\n\r[INFO] Receive from server: %s\n", recv_data); + } + vTaskDelay(1000); + } + closesocket(client_fd); + return; +} + +static void example_ipv6_mcast_server() +{ + int server_fd; + struct sockaddr_in6 ser_addr , client_addr; + + int addrlen = sizeof(struct sockaddr_in6); + + char send_data[MAX_SEND_SIZE] = "Hi client!"; + char recv_data[MAX_RECV_SIZE]; + + //Register to multicast group membership + ip6_addr_t mcast_addr; + inet_pton(AF_INET6, MCAST_GROUP_IP, &(mcast_addr.addr)); +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + ip6_addr_assign_zone(&mcast_addr, IP6_MULTICAST, &xnetif[0]); +#endif + if(mld6_joingroup(IP6_ADDR_ANY , &mcast_addr) != 0){ + printf("\n\r[ERROR] Register to ipv6 multicast group failed\n"); + } + + //create socket + if((server_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0){ + printf("\n\r[ERROR] Create socket failed\n"); + return; + } + printf("\n\r[INFO] Create socket successfully\n"); + + //initialize structure dest + memset(&ser_addr, 0, sizeof(ser_addr)); + ser_addr.sin6_family = AF_INET6; + ser_addr.sin6_port = htons(MCAST_GROUP_PORT); + ser_addr.sin6_addr = (struct in6_addr) IN6ADDR_ANY_INIT; + + //Assign a port number to socket + if(bind(server_fd, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) != 0){ + printf("\n\r[ERROR] Bind socket failed\n"); + closesocket(server_fd); + return; + } + printf("\n\r[INFO] Bind socket successfully\n"); + + while(1){ + memset(recv_data, 0, MAX_RECV_SIZE); + if(recvfrom(server_fd, recv_data, MAX_RECV_SIZE, 0, (struct sockaddr *)&client_addr, &addrlen) > 0){ + printf("\n\r[INFO] Receive data : %s\n",recv_data); + //Send Response + if(sendto(server_fd, send_data, MAX_SEND_SIZE, 0, (struct sockaddr *)&client_addr, addrlen) == -1){ + printf("\n\r[ERROR] Send data failed\n"); + } + else{ + printf("\n\r[INFO] Send data successfully\n"); + } + } + } + closesocket(server_fd); + return; +} + +static void example_ipv6_mcast_client(void) +{ + int client_fd; + struct sockaddr_in6 ser_addr; +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + struct sockaddr_in6 src_addr6; + ip6_addr_t dest_addr6; +#endif + + int addrlen = sizeof(struct sockaddr_in6); + + char recv_data[MAX_RECV_SIZE]; + char send_data[MAX_SEND_SIZE] = "Hi Server!!"; + + //create socket + if((client_fd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1){ + printf("\n\r[ERROR] Create socket failed\n"); + return; + } + printf("\n\r[INFO] Create socket successfully\n"); + + //initialize value in dest + memset(&ser_addr, 0, sizeof(ser_addr)); + ser_addr.sin6_family = AF_INET6; + ser_addr.sin6_port = htons(MCAST_GROUP_PORT); + inet_pton(AF_INET6, MCAST_GROUP_IP, &(ser_addr.sin6_addr)); + +#if LWIP_VERSION_MAJOR >= 2 && LWIP_VERSION_MINOR >= 1 + inet6_addr_to_ip6addr(&dest_addr6, &(ser_addr.sin6_addr)); + ip6_addr_assign_zone(&dest_addr6, IP6_MULTICAST, &xnetif[0]); + + if(ip6_addr_ismulticast_linklocal(&dest_addr6) || ip6_addr_ismulticast_iflocal(&dest_addr6) + || ip6_addr_islinklocal(&dest_addr6)){ + memset(&src_addr6, 0, sizeof(src_addr6)); + src_addr6.sin6_family = AF_INET6; + src_addr6.sin6_port = htons(MCAST_GROUP_PORT); + inet6_addr_from_ip6addr(&src_addr6.sin6_addr, (ip6_addr_t*)&xnetif[0].ip6_addr[0]); + + if(bind(client_fd, (struct sockaddr*)&src_addr6, sizeof(src_addr6)) != 0){ + printf("\n\r[ERROR] Bind socket failed\n"); + closesocket(client_fd); + return; + } + } +#endif + + while(1){ + //Send data to server + if(sendto(client_fd, send_data, MAX_SEND_SIZE, 0, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) == -1){ + printf("\n\r[ERROR] Send data failed\n"); + } + else{ + printf("\n\r[INFO] Send data to server successfully\n"); + } + + //Receive data from server response + memset(recv_data, 0, MAX_RECV_SIZE); + if(recvfrom(client_fd, recv_data, MAX_RECV_SIZE, 0, (struct sockaddr *)&ser_addr, &addrlen) <= 0){ + //printf("\n\r[ERROR] Receive data failed\n"); + } + else{ + printf("\n\r[INFO] Receive from server: %s\n", recv_data); + } + vTaskDelay(1000); + } + closesocket(client_fd); + return; +} + +static void example_ipv6_thread(void *param) +{ + wifi_reg_event_handler(WIFI_EVENT_CONNECT, example_ipv6_callback, NULL); + rtw_init_sema(&ipv6_semaphore, 0); + if(!ipv6_semaphore){ + vTaskDelete(NULL); + return; + } + if(rtw_down_timeout_sema(&ipv6_semaphore, IPV6_SEMA_TIMEOUT) == RTW_FALSE) { + rtw_free_sema(&ipv6_semaphore); + } + LwIP_AUTOIP_IPv6(&xnetif[0]); + //Wait for ipv6 addr process conflict done + while(!ip6_addr_isvalid(netif_ip6_addr_state(&xnetif[0],0))) + vTaskDelay(100); /*GCC: To avoid busy loop*/ + + /*Wait for Wi-fi connection*/ + vTaskDelay(5000); + while (wifi_is_ready_to_transceive(RTW_STA_INTERFACE) != RTW_SUCCESS) { + printf("\n\rWait for WIFI connection ...\n"); + vTaskDelay(1000); + } + +/***---open a example service once!!---***/ + //example_ipv6_udp_server(); + //example_ipv6_tcp_server(); + //example_ipv6_mcast_server(); + + //example_ipv6_udp_client(); + //example_ipv6_tcp_client(); + example_ipv6_mcast_client(); + + vTaskDelete(NULL); +} + +//Wait for wifi association done callback +void example_ipv6_callback(char* buf, int buf_len, int flags, void* userdata) +{ + rtw_up_sema(&ipv6_semaphore); +} + +void example_ipv6(void) +{ + if(xTaskCreate(example_ipv6_thread, ((const char*)"example_ipv6_thread"), 1024, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, NULL) != pdPASS) + printf("\n\r%s xTaskCreate(example_ipv6_thread) failed", __FUNCTION__); +} + +#endif // #if CONFIG_EXAMPLE_IPV6 diff --git a/component/common/example/ipv6/readme.txt b/component/common/example/ipv6/readme.txt new file mode 100644 index 00000000..87418507 --- /dev/null +++ b/component/common/example/ipv6/readme.txt @@ -0,0 +1,33 @@ +IPV6 EXAMPLE + +Description: +Example for IPV6. + +Configuration: +[lwipopts.h] + #define LWIP_IPV6 1 +[platform_opts.h] + #define CONFIG_EXAMPLE_IPV6 1 + +[example_ipv6.h] +#define UDP_SERVER_IP "fe80:0000:0000:0000:cd3c:24de:386d:9ad1" +#define TCP_SERVER_IP "fe80:0000:0000:0000:cd3c:24de:386d:9ad1" +Change the ipv6 address according to your own device. + +[example_ipv6.c] Users can only enable one example at one time. + example_ipv6_udp_server(); +// example_ipv6_tcp_server(); +// example_ipv6_mcast_server(); +// example_ipv6_udp_client(); +// example_ipv6_tcp_client(); +// example_ipv6_mcast_client(); + +Execution: +1. Requires a router with IPv6 enabled +2. Requires two boards, one as client and another one as server. +3. Can make automatical Wi-Fi connection when booting by using wlan fast connect example. +4. A IPV6 example thread will be started automatically when booting. + +[Supported List] + Source code not in project : + Ameba-1, Ameba-z, Ameba-pro \ No newline at end of file diff --git a/component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.c b/component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.c new file mode 100644 index 00000000..015e23f6 --- /dev/null +++ b/component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.c @@ -0,0 +1,270 @@ +#include "FreeRTOS.h" +#include "task.h" +#include +#include "diag.h" +#include "platform_opts.h" + +#include +#include +#include +#include +#if (CONFIG_MBEDTLS_VERSION3 != 1) +#include "mbedtls/ssl_internal.h" +#endif +#define BUFSIZE 1024 +#define mbedtls_printf printf +#define time_t long long + +static void* my_calloc(size_t nelements, size_t elementSize) +{ + size_t size; + void *ptr = NULL; + + size = nelements * elementSize; + ptr = pvPortMalloc(size); + + if(ptr) + memset(ptr, 0, size); + + return ptr; +} + +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ + size_t use_len; + int rnd; + + if( rng_state != NULL ) + rng_state = NULL; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + rnd = rand(); + memcpy( output, &rnd, use_len ); + output += use_len; + len -= use_len; + } + + return( 0 ); +} + +static int myrand2( void *rng_state, unsigned char *output, size_t len ) +{ + size_t use_len; + int rnd; + + time_t t; + + srand((unsigned) time(&t)); + + if( rng_state != NULL ) + rng_state = NULL; + + while( len > 0 ) + { + use_len = len; + if( use_len > sizeof(int) ) + use_len = sizeof(int); + + rnd = rand(); + + memcpy( output, &rnd, use_len ); + output += use_len; + len -= use_len; + } + + return( 0 ); +} + +static void example_mbedtls_ecdhe_thread(void *param) +{ + + /* To avoid gcc warnings */ + ( void ) param; + + int ret; + mbedtls_ecdh_context ctx_cli, ctx_srv; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char cli_to_srv[32], srv_to_cli[32]; + const char pers[] = "ecdh"; + + mbedtls_ecdh_init( &ctx_cli ); + mbedtls_ecdh_init( &ctx_srv ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_platform_set_calloc_free(my_calloc, vPortFree); + + /* + * Initialize random number generation + */ + mbedtls_printf( " . Seeding the random number generator..." ); + mbedtls_entropy_init( &entropy ); + if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *) pers, + sizeof pers ) ) != 0 ) + { + printf("\n\r%s: line %d", __func__, __LINE__); + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Client: inialize context and generate keypair + */ + mbedtls_printf( " . Setting up client context..." ); + + ret = mbedtls_ecp_group_load( &ctx_cli.grp, MBEDTLS_ECP_DP_CURVE25519 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); + goto exit; + } + ret = mbedtls_ecdh_gen_public( &ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_gen_public returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_write_binary( &ctx_cli.Q.X, cli_to_srv, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_binary returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Server: initialize context and generate keypair + */ + mbedtls_printf( " . Setting up server context..." ); + + ret = mbedtls_ecp_group_load( &ctx_srv.grp, MBEDTLS_ECP_DP_CURVE25519 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_gen_public( &ctx_srv.grp, &ctx_srv.d, &ctx_srv.Q, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_gen_public returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_write_binary( &ctx_srv.Q.X, srv_to_cli, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_write_binary returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Server: read peer's key and generate shared secret + */ + mbedtls_printf( " . Server reading client key and computing secret..." ); + + ret = mbedtls_mpi_lset( &ctx_srv.Qp.Z, 1 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_read_binary( &ctx_srv.Qp.X, cli_to_srv, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_compute_shared( &ctx_srv.grp, &ctx_srv.z, + &ctx_srv.Qp, &ctx_srv.d, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Client: read peer's key and generate shared secret + */ + mbedtls_printf( " . Client reading server key and computing secret..." ); + + ret = mbedtls_mpi_lset( &ctx_cli.Qp.Z, 1 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_mpi_read_binary( &ctx_cli.Qp.X, srv_to_cli, 32 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); + goto exit; + } + + ret = mbedtls_ecdh_compute_shared( &ctx_cli.grp, &ctx_cli.z, + &ctx_cli.Qp, &ctx_cli.d, + mbedtls_ctr_drbg_random, &ctr_drbg ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * Verification: are the computed secret equal? + */ + mbedtls_printf( " . Checking if both computed secrets are equal..." ); + + ret = mbedtls_mpi_cmp_mpi( &ctx_cli.z, &ctx_srv.z ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +exit: + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + mbedtls_ecdh_free( &ctx_srv ); + mbedtls_ecdh_free( &ctx_cli ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + + vTaskDelete(NULL); + + return; +} + + +void example_mbedtls_ecdhe(void) +{ + if(xTaskCreate(example_mbedtls_ecdhe_thread, ((const char*)"example_mbedtls_ecdhe_thread"), 2048, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS) + printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__); +} diff --git a/component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.h b/component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.h new file mode 100644 index 00000000..42dddc56 --- /dev/null +++ b/component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.h @@ -0,0 +1,6 @@ +#ifndef EXAMPLE_MBEDTLS_ECDHE_H +#define EXAMPLE_MBEDTLS_ECDHE_H + +void example_mbedtls_ecdhe(void); + +#endif /* EXAMPLE_MBEDTLS_ECDHE_H */ diff --git a/component/common/example/ssl_download/example_ssl_download.c b/component/common/example/ssl_download/example_ssl_download.c index 73544dc4..18b6e875 100644 --- a/component/common/example/ssl_download/example_ssl_download.c +++ b/component/common/example/ssl_download/example_ssl_download.c @@ -8,6 +8,7 @@ #include "platform_opts.h" +#define STACKSIZE 2048 #if CONFIG_USE_POLARSSL #include @@ -127,10 +128,18 @@ void example_ssl_download(void) #elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */ -#include -#include +#include +#include #include -#include +#include + +//#define SSL_CLIENT_EXT + +#ifdef SSL_CLIENT_EXT +extern int ssl_client_ext_init(void); +extern int ssl_client_ext_setup(mbedtls_ssl_config *conf); +extern void ssl_client_ext_free(void); +#endif #define SERVER_HOST "176.34.62.248" #define SERVER_PORT "443" @@ -164,9 +173,6 @@ static void example_ssl_download_thread(void *param) mbedtls_ssl_context ssl; mbedtls_ssl_config conf; -#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) - rtw_create_secure_context(configMINIMAL_SECURE_STACK_SIZE); -#endif // Delay to wait for IP by DHCP vTaskDelay(10000); printf("\nExample: SSL download\n"); @@ -177,6 +183,13 @@ static void example_ssl_download_thread(void *param) mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); +#ifdef SSL_CLIENT_EXT + if((ret = ssl_client_ext_init()) != 0) { + printf(" failed\n\r ! ssl_client_ext_init returned %d\n", ret); + goto exit; + } +#endif + if((ret = mbedtls_net_connect(&server_fd, SERVER_HOST, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { printf("ERROR: mbedtls_net_connect ret(%d)\n", ret); goto exit; @@ -189,13 +202,28 @@ static void example_ssl_download_thread(void *param) MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { - printf("ERRPR: mbedtls_ssl_config_defaults ret(%d)\n", ret); + printf("ERROR: mbedtls_ssl_config_defaults ret(%d)\n", ret); goto exit; } mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&conf, my_random, NULL); +#ifdef SSL_CLIENT_EXT + if((ret = ssl_client_ext_setup(&conf)) != 0) { + printf(" failed\n\r ! ssl_client_ext_setup returned %d\n", ret); + goto exit; + } +#endif + +#if (defined(MBEDTLS_SSL_IN_CONTENT_LEN) && (MBEDTLS_SSL_IN_CONTENT_LEN == 4096)) || \ + (defined(MBEDTLS_SSL_MAX_CONTENT_LEN) && (MBEDTLS_SSL_MAX_CONTENT_LEN == 4096)) + if(ret = mbedtls_ssl_conf_max_frag_len(&conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { + printf("ERROR: mbedtls_ssl_conf_max_frag_len ret(%d)\n", ret); + goto exit; + } +#endif + if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { printf("ERRPR: mbedtls_ssl_setup ret(%d)\n", ret); goto exit; @@ -263,6 +291,10 @@ static void example_ssl_download_thread(void *param) mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); +#ifdef SSL_CLIENT_EXT + ssl_client_ext_free(); +#endif + vTaskDelete(NULL); } diff --git a/component/common/example/ssl_server/example_ssl_server.c b/component/common/example/ssl_server/example_ssl_server.c index 74a82418..1e306d28 100644 --- a/component/common/example/ssl_server/example_ssl_server.c +++ b/component/common/example/ssl_server/example_ssl_server.c @@ -188,12 +188,12 @@ void example_ssl_server(void) } #elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */ - #include "mbedtls/config.h" +#include "mbedtls/certs.h" #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/ssl.h" -#include "mbedtls/certs.h" + #define SERVER_PORT "443" #define STACKSIZE 2048 diff --git a/component/common/network/dhcp/dhcps.c b/component/common/network/dhcp/dhcps.c index 1255c04c..5438fc8a 100644 --- a/component/common/network/dhcp/dhcps.c +++ b/component/common/network/dhcp/dhcps.c @@ -913,9 +913,8 @@ struct pbuf *udp_packet_buffer, struct ip_addr *sender_addr, uint16_t sender_por if (udp_packet_buffer->next != NULL) { merged_packet_buffer = pbuf_coalesce(udp_packet_buffer, PBUF_TRANSPORT); - if (merged_packet_buffer->tot_len != - total_length_of_packet_buffer) { - pbuf_free(udp_packet_buffer); + if ((merged_packet_buffer->tot_len != total_length_of_packet_buffer) || (merged_packet_buffer == udp_packet_buffer)) { + pbuf_free(merged_packet_buffer); return; } udp_packet_buffer = merged_packet_buffer; diff --git a/component/common/network/httpc/httpc_tls.c b/component/common/network/httpc/httpc_tls.c index fbcdf5ee..16ee2d6d 100644 --- a/component/common/network/httpc/httpc_tls.c +++ b/component/common/network/httpc/httpc_tls.c @@ -45,17 +45,27 @@ static int _verify_func(void *data, x509_crt *crt, int depth, int *flags) } #elif (HTTPC_USE_TLS == HTTPC_TLS_MBEDTLS) + #include "mbedtls/ssl.h" #include "mbedtls/platform.h" #include "mbedtls/net_sockets.h" #include "mbedtls/base64.h" +#include "mbedtls/ssl.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/version.h" struct httpc_tls { mbedtls_ssl_context ctx; /*!< Context for mbedTLS */ mbedtls_ssl_config conf; /*!< Configuration for mbedTLS */ mbedtls_x509_crt ca; /*!< CA certificates */ - mbedtls_x509_crt cert; /*!< Certificate */ + mbedtls_x509_crt cert; /*!< Certificate */ + +#if defined(configENABLE_TRUSTZONE) && (configENABLE_TRUSTZONE == 1) && defined(CONFIG_SSL_CLIENT_PRIVATE_IN_TZ) && (CONFIG_SSL_CLIENT_PRIVATE_IN_TZ == 1) + mbedtls_pk_context* key; /*!< Private key pointer */ +#else mbedtls_pk_context key; /*!< Private key */ +#endif }; static int _verify_func(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) @@ -212,7 +222,6 @@ void *httpc_tls_new(int *sock, char *client_cert, char *client_key, char *ca_cer ret = -1; goto exit; } - if((ret = mbedtls_pk_parse_key(&tls->key, (const unsigned char *) client_key, strlen(client_key) + 1, NULL, 0)) != 0) { printf("\n[HTTPC] ERROR: mbedtls_pk_parse_key %d\n", ret); ret = -1; @@ -239,6 +248,14 @@ void *httpc_tls_new(int *sock, char *client_cert, char *client_key, char *ca_cer mbedtls_ssl_conf_verify(conf, _verify_func, NULL); } +#if MBEDTLS_SSL_IN_CONTENT_LEN == 4096 + if(ret = mbedtls_ssl_conf_max_frag_len(conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { + printf("\n[HTTPC] ERROR: mbedtls_ssl_conf_max_frag_len %d\n", ret); + ret = -1; + goto exit; + } +#endif + if((ret = mbedtls_ssl_setup(ssl, conf)) != 0) { printf("\n[HTTPC] ERROR: mbedtls_ssl_setup %d\n", ret); ret = -1; @@ -258,7 +275,7 @@ void *httpc_tls_new(int *sock, char *client_cert, char *client_key, char *ca_cer mbedtls_ssl_free(&tls->ctx); mbedtls_ssl_config_free(&tls->conf); mbedtls_x509_crt_free(&tls->ca); - mbedtls_x509_crt_free(&tls->cert); + mbedtls_x509_crt_free(&tls->cert); mbedtls_pk_free(&tls->key); free(tls); tls = NULL; diff --git a/component/common/network/httpd/httpd_tls.c b/component/common/network/httpd/httpd_tls.c index 208bad16..3f8731e7 100644 --- a/component/common/network/httpd/httpd_tls.c +++ b/component/common/network/httpd/httpd_tls.c @@ -144,7 +144,7 @@ int httpd_tls_setup_init(const char *server_cert, const char *server_key, const ret = -1; goto exit; } - + if((ret = mbedtls_pk_parse_key(&httpd_key, (const unsigned char *) server_key, strlen(server_key) + 1, NULL, 0)) != 0) { printf("\n[HTTPD] ERROR: mbedtls_pk_parse_key %d\n", ret); ret = -1; diff --git a/component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/dhcp.c b/component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/dhcp.c index b1b6da4b..549e1e10 100644 --- a/component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/dhcp.c +++ b/component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/dhcp.c @@ -1927,6 +1927,9 @@ dhcp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, /* already bound to the given lease address? */ else if ((dhcp->state == DHCP_STATE_REBOOTING) || (dhcp->state == DHCP_STATE_REBINDING) || (dhcp->state == DHCP_STATE_RENEWING)) { + if(dhcp->state == DHCP_STATE_RENEWING){ + wifi_indication(27, NULL,0, 0); + } dhcp_handle_ack(netif); dhcp_bind(netif); } diff --git a/component/common/network/ssl/mbedtls-3.1.0/Readme.txt b/component/common/network/ssl/mbedtls-3.1.0/Readme.txt new file mode 100644 index 00000000..a8f7824b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/Readme.txt @@ -0,0 +1,151 @@ +Changes of switching to mbedtls-3.1.0 : + +1. In platform_opts.h: #define CONFIG_MBEDTLS_VERSION3 1 + +2. In application.is.mk + -INCLUDES += -I../../../component/common/network/ssl/mbedtls-2.4.0/include ++INCLUDES += -I../../../component/common/network/ssl/mbedtls-3.1.0/include ++INCLUDES += -I../../../component/common/network/ssl/mbedtls-3.1.0/library +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/aesni.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/blowfish.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/camellia.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ccm.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/certs.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/cipher.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/cipher_wrap.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/cmac.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/debug.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/entropy.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/error.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/gcm.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/havege.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md2.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md4.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md_wrap.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/memory_buffer_alloc.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/net_sockets.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/padlock.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkcs11.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkcs12.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkcs5.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkparse.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/platform.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ripemd160.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/sha256.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_cache.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_ciphersuites.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_cli.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_cookie.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_srv.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_ticket.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_tls.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/threading.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/timing.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/version.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/version_features.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_create.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_crl.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_crt.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_csr.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509write_crt.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509write_csr.c +-SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/xtea.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/aes.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/aesni.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/aria.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/asn1parse.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/asn1write.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/base64.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/bignum.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/camellia.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ccm.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/chacha20.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/chachapoly.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/cipher.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/cmac.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/constant_time.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ctr_drbg.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/debug.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/des.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/dhm.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ecdh.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ecdsa.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ecjpake.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ecp.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ecp_curves.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/entropy.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/error.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/gcm.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/hkdf.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/hmac_drbg.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/md.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/md5.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/memory_buffer_alloc.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/net_sockets.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/nist_kw.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/oid.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/padlock.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pem.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pk.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pkcs12.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pkcs5.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pkparse.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/pkwrite.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/platform.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/platform_util.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/poly1305.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_client.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/psa_its_file.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ripemd160.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/rsa.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/sha1.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/sha256.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/sha512.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_cache.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_ciphersuites.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_cli.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_cookie.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_debug_helpers_generated.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_msg.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_srv.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_ticket.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_client.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_generic.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_server.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/threading.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/timing.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/version.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/version_features.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509_create.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509_crl.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509_crt.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509_csr.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509write_crt.c ++SRC_C += ../../../component/common/network/ssl/mbedtls-3.1.0/library/x509write_csr.c + +3. In wlan_source.mk +-INCLUDES += -I../../../component/common/network/ssl/mbedtls-2.4.0/include ++INCLUDES += -I../../../component/common/network/ssl/mbedtls-3.1.0/include ++INCLUDES += -I../../../component/common/network/ssl/mbedtls-3.1.0/library \ No newline at end of file diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/.gitignore b/component/common/network/ssl/mbedtls-3.1.0/include/.gitignore new file mode 100644 index 00000000..bf67d02e --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/.gitignore @@ -0,0 +1,4 @@ +Makefile +*.sln +*.vcxproj +mbedtls/check_config diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/CMakeLists.txt b/component/common/network/ssl/mbedtls-3.1.0/include/CMakeLists.txt new file mode 100644 index 00000000..e693bc17 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/CMakeLists.txt @@ -0,0 +1,22 @@ +option(INSTALL_MBEDTLS_HEADERS "Install mbed TLS headers." ON) + +if(INSTALL_MBEDTLS_HEADERS) + + file(GLOB headers "mbedtls/*.h") + file(GLOB psa_headers "psa/*.h") + + install(FILES ${headers} + DESTINATION include/mbedtls + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + + install(FILES ${psa_headers} + DESTINATION include/psa + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + +endif(INSTALL_MBEDTLS_HEADERS) + +# Make mbedtls_config.h available in an out-of-source build. ssl-opt.sh requires it. +if (ENABLE_TESTING AND NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + link_to_source(mbedtls) + link_to_source(psa) +endif() diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/aes.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/aes.h new file mode 100644 index 00000000..e381c118 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/aes.h @@ -0,0 +1,640 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +/** Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 +/** Invalid data input length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 + +/* Error codes in range 0x0021-0x0025 */ +/** Invalid input data. */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context +{ + int MBEDTLS_PRIVATE(nr); /*!< The number of rounds. */ + uint32_t *MBEDTLS_PRIVATE(rk); /*!< AES round keys. */ + uint32_t MBEDTLS_PRIVATE(buf)[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context MBEDTLS_PRIVATE(crypt); /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context MBEDTLS_PRIVATE(tweak); /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_aes_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/aria.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/aria.h new file mode 100644 index 00000000..1a96d153 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/aria.h @@ -0,0 +1,358 @@ +/** + * \file aria.h + * + * \brief ARIA block cipher + * + * The ARIA algorithm is a symmetric block cipher that can encrypt and + * decrypt information. It is defined by the Korean Agency for + * Technology and Standards (KATS) in KS X 1213:2004 (in + * Korean, but see http://210.104.33.10/ARIA/index-e.html in English) + * and also described by the IETF in RFC 5794. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_ARIA_H +#define MBEDTLS_ARIA_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */ +#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */ + +#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */ +#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */ +#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */ + +/** Bad input data. */ +#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C + +/** Invalid data input length. */ +#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARIA_ALT) +// Regular implementation +// + +/** + * \brief The ARIA context-type definition. + */ +typedef struct mbedtls_aria_context +{ + unsigned char MBEDTLS_PRIVATE(nr); /*!< The number of rounds (12, 14 or 16) */ + /*! The ARIA round keys. */ + uint32_t MBEDTLS_PRIVATE(rk)[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4]; +} +mbedtls_aria_context; + +#else /* MBEDTLS_ARIA_ALT */ +#include "aria_alt.h" +#endif /* MBEDTLS_ARIA_ALT */ + +/** + * \brief This function initializes the specified ARIA context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The ARIA context to initialize. This must not be \c NULL. + */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ); + +/** + * \brief This function releases and clears the specified ARIA context. + * + * \param ctx The ARIA context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized ARIA context. + */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ); + +/** + * \brief This function sets the encryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The encryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of \p key in Bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The ARIA context to which the key should be bound. + * This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs an ARIA single-block encryption or + * decryption operation. + * + * It performs encryption or decryption (depending on whether + * the key was set for encryption on decryption) on the input + * data buffer defined in the \p input parameter. + * + * mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or + * mbedtls_aria_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an ARIA-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aria_init(), and either + * mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the ARIA block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an ARIA-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aria_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_ARIA_ENCRYPT for encryption, or + * #MBEDTLS_ARIA_DECRYPT for decryption. + * \param length The length of the input data \p input in Bytes. + * \param iv_off The offset in IV (updated after use). + * This must not be larger than 15. + * \param iv The initialization vector (updated after use). + * This must be a readable buffer of size 16 Bytes. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an ARIA-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aria_setkey_enc() + * for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an ARIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The ARIA context to use for encryption or decryption. + * This must be initialized and bound to a key. + * \param length The length of the input data \p input in Bytes. + * \param nc_off The offset in Bytes in the current \p stream_block, + * for resuming within the current cipher stream. The + * offset pointer should be \c 0 at the start of a + * stream. This must not be larger than \c 15 Bytes. + * \param nonce_counter The 128-bit nonce and counter. This must point to + * a read/write buffer of length \c 16 bytes. + * \param stream_block The saved stream block for resuming. This must + * point to a read/write buffer of length \c 16 bytes. + * This is overwritten by the function. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must + * be a writable buffer of length \p length Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_aria_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aria.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/asn1.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/asn1.h new file mode 100644 index 00000000..4746c1cb --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/asn1.h @@ -0,0 +1,633 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +/** Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 +/** ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 +/** Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 +/** Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 +/** Data is invalid. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 +/** Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A +/** Buffer too small when writing ASN.1 data structure. */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_ENUMERATED 0x0A +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* Slightly smaller way to check if tag is a string tag + * compared to canonical implementation. */ +#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ + ( ( tag ) < 32u && ( \ + ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \ + ( 1u << MBEDTLS_ASN1_T61_STRING ) | \ + ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \ + ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \ + ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \ + memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + + /** The next entry in the sequence. + * + * The details of memory management for sequences are not documented and + * may change in future versions. Set this field to \p NULL when + * initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_sequence *next; +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + + /** The next entry in the sequence. + * + * The details of memory management for named data sequences are not + * documented and may change in future versions. Set this field to \p NULL + * when initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_named_data *next; + + /** Merge next item into the current one? + * + * This field exists for the sake of Mbed TLS's X.509 certificate parsing + * code and may change in future versions of the library. + */ + unsigned char MBEDTLS_PRIVATE(next_merged); +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p On entry, \c *p points to the first byte of the length, + * i.e. immediately after the tag. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the element. + * Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * \param tag The expected tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start + * with the requested tag. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value (\c 0 or \c 1). + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BOOLEAN. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an enumerated ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 ENUMERATED. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param bs On success, ::mbedtls_asn1_bitstring information about + * the parsed value. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid BIT STRING. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs ); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * of the content of the BIT STRING. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On success, \c *len is the length of the content in bytes. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with + * a valid BIT STRING with a nonzero number of unused bits. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF ". + * Updates the pointer to immediately behind the full sequence tag. + * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * + * \note On error, this function may return a partial list in \p cur. + * You must set `cur->next = NULL` before calling this function! + * Otherwise it is impossible to distinguish a previously non-null + * pointer from a pointer to an object allocated by this function. + * + * \note If the sequence is empty, this function does not modify + * \c *cur. If the sequence is valid and non-empty, this + * function sets `cur->buf.tag` to \p tag. This allows + * callers to distinguish between an empty sequence and + * a one-element sequence. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param cur A ::mbedtls_asn1_sequence which this function fills. + * When this function returns, \c *cur is the head of a linked + * list. Each node in this list is allocated with + * mbedtls_calloc() apart from \p cur itself, and should + * therefore be freed with mbedtls_free(). + * The list describes the content of the sequence. + * The head of the list (i.e. \c *cur itself) describes the + * first element, `*cur->next` describes the second element, etc. + * For each element, `buf.tag == tag`, `buf.len` is the length + * of the content of the content of the element, and `buf.p` + * points to the first byte of the content (i.e. immediately + * past the length of the element). + * Note that list elements may be allocated even on error. + * \param tag Each element of the sequence must have this tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid SEQUENCE OF \p tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with + * an ASN.1 SEQUENCE in which an element has a tag that + * is different from \p tag. + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); + +/** + * \brief Traverse an ASN.1 SEQUENCE container and + * call a callback for each entry. + * + * This function checks that the input is a SEQUENCE of elements that + * each have a "must" tag, and calls a callback function on the elements + * that have a "may" tag. + * + * For example, to validate that the input is a SEQUENCE of `tag1` and call + * `cb` on each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of ANY and call `cb` on + * each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} + * and call `cb` on each element that is an OCTET STRING, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); + * ``` + * + * The callback is called on the elements with a "may" tag from left to + * right. If the input is not a valid SEQUENCE of elements with a "must" tag, + * the callback is called on the elements up to the leftmost point where + * the input is invalid. + * + * \warning This function is still experimental and may change + * at any time. + * + * \param p The address of the pointer to the beginning of + * the ASN.1 SEQUENCE header. This is updated to + * point to the end of the ASN.1 SEQUENCE container + * on a successful invocation. + * \param end The end of the ASN.1 SEQUENCE container. + * \param tag_must_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_must_value. + * \param tag_must_val The required value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_must_mask. + * Mismatching tags lead to an error. + * For example, a value of \c 0 for both \p tag_must_mask + * and \p tag_must_val means that every tag is allowed, + * while a value of \c 0xFF for \p tag_must_mask means + * that \p tag_must_val is the only allowed tag. + * \param tag_may_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_may_value. + * \param tag_may_val The desired value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_may_mask. + * Mismatching tags will be silently ignored. + * For example, a value of \c 0 for \p tag_may_mask and + * \p tag_may_val means that any tag will be considered, + * while a value of \c 0xFF for \p tag_may_mask means + * that all tags with value different from \p tag_may_val + * will be ignored. + * \param cb The callback to trigger for each component + * in the ASN.1 SEQUENCE that matches \p tag_may_val. + * The callback function is called with the following + * parameters: + * - \p ctx. + * - The tag of the current element. + * - A pointer to the start of the current element's + * content inside the input. + * - The length of the content of the current element. + * If the callback returns a non-zero value, + * the function stops immediately, + * forwarding the callback's return value. + * \param ctx The context to be passed to the callback \p cb. + * + * \return \c 0 if successful the entire ASN.1 SEQUENCE + * was traversed without parsing or callback errors. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input + * contains extra data after a valid SEQUENCE + * of elements with an accepted tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts + * with an ASN.1 SEQUENCE in which an element has a tag + * that is not accepted. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + * \return A non-zero error code forwarded from the callback + * \p cb in case the latter returns a non-zero value. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char* start, size_t len ), + void *ctx ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param X On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + * \return An MPI error code if the parsed value is too large. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * \param params The buffer to receive the parameters. + * This is zeroized if there are no parameters. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p`. + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list. + * + * \param head Pointer to the head of the list of named data entries to free. + * This function calls mbedtls_asn1_free_named_data() and + * mbedtls_free() on each list element and + * sets \c *head to \c NULL. + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/asn1write.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/asn1write.h new file mode 100644 index 00000000..d60ca0da --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/asn1write.h @@ -0,0 +1,366 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) \ + do \ + { \ + if( ( ret = (f) ) < 0 ) \ + return( ret ); \ + else \ + (g) += ret; \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param len The length value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, + size_t len ); +/** + * \brief Write an ASN.1 tag in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The tag to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_tag( unsigned char **p, const unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The data buffer to write. + * \param size The length of the data buffer. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, const unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER) + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param X The MPI to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_mpi( unsigned char **p, const unsigned char *start, + const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_null( unsigned char **p, const unsigned char *start ); + +/** + * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID to write. + * \param oid_len The length of the OID. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_oid( unsigned char **p, const unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param oid The OID of the algorithm to write. + * \param oid_len The length of the algorithm's OID. + * \param par_len The length of the parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, + const unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param boolean The boolean value to write, either \c 0 or \c 1. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_bool( unsigned char **p, const unsigned char *start, + int boolean ); + +/** + * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * It must be non-negative. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_int( unsigned char **p, const unsigned char *start, int val ); + +/** + * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value + * in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param val The integer value to write. + * + * \return The number of bytes written to \p p on success. + * \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_asn1_write_enum( unsigned char **p, const unsigned char *start, int val ); + +/** + * \brief Write a string in ASN.1 format using a specific + * string encoding tag. + + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param tag The string encoding tag to write, e.g. + * #MBEDTLS_ASN1_UTF8_STRING. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_tagged_string( unsigned char **p, const unsigned char *start, + int tag, const char *text, + size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the PrintableString + * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, + const unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a UTF8 string in ASN.1 format using the UTF8String + * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_utf8_string( unsigned char **p, const unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a string in ASN.1 format using the IA5String + * string encoding tag (#MBEDTLS_ASN1_IA5_STRING). + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param text The string to write. + * \param text_len The length of \p text in bytes (which might + * be strictly larger than the number of characters). + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, const unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, const unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief This function writes a named bitstring tag + * (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format. + * + * As stated in RFC 5280 Appendix B, trailing zeroes are + * omitted when encoding named bitstrings in DER. + * + * \note This function works backwards within the data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer which is used for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + const unsigned char *start, + const unsigned char *buf, + size_t bits ); + +/** + * \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING) + * and value in ASN.1 format. + * + * \note This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The buffer holding the data to write. + * \param size The length of the data buffer \p buf. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, const unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list The pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry). + * \param oid The OID to look for. + * \param oid_len The size of the OID. + * \param val The associated data to store. If this is \c NULL, + * no data is copied to the new or existing buffer. + * \param val_len The minimum length of the data buffer needed. + * If this is 0, do not allocate a buffer for the associated + * data. + * If the OID was already present, enlarge, shrink or free + * the existing buffer to fit \p val_len. + * + * \return A pointer to the new / existing entry on success. + * \return \c NULL if if there was a memory allocation error. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/base64.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/base64.h new file mode 100644 index 00000000..8378589f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/base64.h @@ -0,0 +1,94 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#include "mbedtls/build_info.h" + +#include + +/** Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A +/** Invalid character in input. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/bignum.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/bignum.h new file mode 100644 index 00000000..45d31199 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/bignum.h @@ -0,0 +1,1029 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/** An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 +/** There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 +/** The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 +/** The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A +/** The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C +/** The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E +/** Memory allocation failed. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 + +#define MBEDTLS_MPI_CHK(f) \ + do \ + { \ + if( ( ret = (f) ) != 0 ) \ + goto cleanup; \ + } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) || \ + defined(__aarch64__) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + int MBEDTLS_PRIVATE(s); /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + size_t MBEDTLS_PRIVATE(n); /*!< total # of limbs */ + mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X The MPI context to initialize. This must not be \c NULL. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief This function frees the components of an MPI context. + * + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge an MPI to the specified number of limbs. + * + * \note This function does nothing if the MPI is + * already large enough. + * + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. + * + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of two MPIs. + * + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. + * + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. + * + * \note This function is equivalent to + * `if( assign ) mbedtls_mpi_copy( X, Y );` + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. + * + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Store integer value in MPI. + * + * \param X The MPI to set. This must be initialized. + * \param z The value to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from an MPI. + * + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. + * + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Modify a specific bit in an MPI. + * + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. + * + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. + * + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant bit of value \c 1. + * + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. + * + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import an MPI from an ASCII string. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export an MPI to an ASCII string. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. + * + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read an MPI from a line in an opened file. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Export an MPI into an opened file. + * + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import an MPI from unsigned big endian binary data. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Import X from unsigned binary data, little endian + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); + +/** + * \brief Export X into unsigned binary data, little endian. + * Always fills the whole buffer, which will end with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ); + +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Perform a right-shift on an MPI: X >>= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare the absolute values of two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \brief Compare an MPI with an integer. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. + * + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of MPIs: X = A + B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed subtraction of MPIs: X = A - B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of an MPI and an integer: X = A + b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); + +/** + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a modular reduction. R = A mod B + * + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b + * + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a sliding-window exponentiation: X = A^E mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param prec_RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p prec_RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p prec_RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *prec_RR ); + +/** + * \brief Fill an MPI with a number of random bytes. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param min The minimum value to return. + * It must be nonnegative. + * \param N The upper bound of the range, exclusive. + * In other words, this is one plus the maximum value to return. + * \p N must be strictly larger than \p min. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid + * or if they are incompatible. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_random( mbedtls_mpi *X, + mbedtls_mpi_sint min, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute the greatest common divisor: G = gcd(A, B) + * + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Compute the modular inverse: X = A^-1 mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/build_info.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/build_info.h new file mode 100644 index 00000000..cef6566c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/build_info.h @@ -0,0 +1,83 @@ +/** + * \file build_info.h + * + * \brief Build-time configuration info + * + * Include this file if you need to depend on the + * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE + */ + /* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_BUILD_INFO_H +#define MBEDTLS_BUILD_INFO_H + +/* + * This set of compile-time defines can be used to determine the version number + * of the Mbed TLS library used. Run-time variables for the same can be found in + * version.h + */ + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 3 +#define MBEDTLS_VERSION_MINOR 1 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x03010000 +#define MBEDTLS_VERSION_STRING "3.1.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.1.0" + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/mbedtls_config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CONFIG_VERSION) && ( \ + MBEDTLS_CONFIG_VERSION < 0x03000000 || \ + MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER ) +#error "Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported" +#endif + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#include "mbedtls/config_psa.h" +#endif + +#include "mbedtls/check_config.h" + +#endif /* MBEDTLS_BUILD_INFO_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/camellia.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/camellia.h new file mode 100644 index 00000000..6feeaf04 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/camellia.h @@ -0,0 +1,316 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#include "mbedtls/platform_util.h" + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +/** Bad input data. */ +#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 + +/** Invalid data input length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context +{ + int MBEDTLS_PRIVATE(nr); /*!< number of rounds */ + uint32_t MBEDTLS_PRIVATE(rk)[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +/** + * \brief Initialize a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be initialized. + * This must not be \c NULL. + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear a CAMELLIA context. + * + * \param ctx The CAMELLIA context to be cleared. This may be \c NULL, + * in which case this function returns immediately. If it is not + * \c NULL, it must be initialized. + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief Perform a CAMELLIA key schedule operation for encryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The encryption key to use. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA key schedule operation for decryption. + * + * \param ctx The CAMELLIA context to use. This must be initialized. + * \param key The decryption key. This must be a readable buffer + * of size \p keybits Bits. + * \param keybits The length of \p key in Bits. This must be either \c 128, + * \c 192 or \c 256. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Perform a CAMELLIA-ECB block encryption/decryption operation. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param input The input block. This must be a readable buffer + * of size \c 16 Bytes. + * \param output The output block. This must be a writable buffer + * of size \c 16 Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length in Bytes of the input data \p input. + * This must be a multiple of \c 16 Bytes. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated to allow streaming + * use as explained above. + * \param input The buffer holding the input data. This must point to a + * readable buffer of length \p length Bytes. + * \param output The buffer holding the output data. This must point to a + * writable buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption + * operation. + * + * \note Due to the nature of CFB mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param mode The mode of operation. This must be either + * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * \param length The length of the input data \p input. Any value is allowed. + * \param iv_off The current offset in the IV. This must be smaller + * than \c 16 Bytes. It is updated after this call to allow + * the aforementioned streaming usage. + * \param iv The initialization vector. This must be a read/write buffer + * of length \c 16 Bytes. It is updated after this call to + * allow the aforementioned streaming usage. + * \param input The buffer holding the input data. This must be a readable + * buffer of size \p length Bytes. + * \param output The buffer to hold the output data. This must be a writable + * buffer of length \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation. + * + * *note Due to the nature of CTR mode, you should use the same + * key for both encryption and decryption. In particular, calls + * to this function should be preceded by a key-schedule via + * mbedtls_camellia_setkey_enc() regardless of whether \p mode + * is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first \c 12 Bytes for the + * per-message nonce, and the last \c 4 Bytes for internal use. + * In that case, before calling this function on a new message you + * need to set the first \c 12 Bytes of \p nonce_counter to your + * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0 + * (which will cause \p stream_block to be ignored). That way, you + * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks + * each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be + * unique. The recommended way to ensure uniqueness is to use a + * message counter. An alternative is to generate random nonces, + * but this limits the number of messages that can be securely + * encrypted: for example, with 96-bit random nonces, you should + * not encrypt more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is \c 16 Bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The CAMELLIA context to use. This must be initialized + * and bound to a key. + * \param length The length of the input data \p input in Bytes. + * Any value is allowed. + * \param nc_off The offset in the current \p stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be \c 0 at the start of a stream. It is updated + * at the end of this call. + * \param nonce_counter The 128-bit nonce and counter. This must be a read/write + * buffer of length \c 16 Bytes. + * \param stream_block The saved stream-block for resuming. This must be a + * read/write buffer of length \c 16 Bytes. + * \param input The input data stream. This must be a readable buffer of + * size \p length Bytes. + * \param output The output data stream. This must be a writable buffer + * of size \p length Bytes. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ccm.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ccm.h new file mode 100644 index 00000000..1be1689d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ccm.h @@ -0,0 +1,532 @@ +/** + * \file ccm.h + * + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#define MBEDTLS_CCM_DECRYPT 0 +#define MBEDTLS_CCM_ENCRYPT 1 +#define MBEDTLS_CCM_STAR_DECRYPT 2 +#define MBEDTLS_CCM_STAR_ENCRYPT 3 + +/** Bad input parameters to the function. */ +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D +/** Authenticated decryption failed. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CCM_ALT) +// Regular implementation +// + +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct mbedtls_ccm_context +{ + unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working buffer */ + unsigned char MBEDTLS_PRIVATE(ctr)[16]; /*!< The counter buffer */ + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ + size_t MBEDTLS_PRIVATE(plaintext_len); /*!< Total plaintext length */ + size_t MBEDTLS_PRIVATE(add_len); /*!< Total authentication data length */ + size_t MBEDTLS_PRIVATE(tag_len); /*!< Total tag length */ + size_t MBEDTLS_PRIVATE(processed); /*!< Track how many bytes of input data + were processed (chunked input). + Used independently for both auth data + and plaintext/ciphertext. + This variable is set to zero after + auth data input is finished. */ + unsigned char MBEDTLS_PRIVATE(q); /*!< The Q working value */ + unsigned char MBEDTLS_PRIVATE(mode); /*!< The operation to perform: + #MBEDTLS_CCM_ENCRYPT or + #MBEDTLS_CCM_DECRYPT or + #MBEDTLS_CCM_STAR_ENCRYPT or + #MBEDTLS_CCM_STAR_DECRYPT. */ + int MBEDTLS_PRIVATE(state); /*!< Working value holding context's + state. Used for chunked data + input */ +} +mbedtls_ccm_context; + +#else /* MBEDTLS_CCM_ALT */ +#include "ccm_alt.h" +#endif /* MBEDTLS_CCM_ALT */ + +/** + * \brief This function initializes the specified CCM context, + * to make references valid, and prepare the context + * for mbedtls_ccm_setkey() or mbedtls_ccm_free(). + * + * \param ctx The CCM context to initialize. This must not be \c NULL. + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ); + +/** + * \brief This function initializes the CCM context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The CCM context to initialize. This must be an initialized + * context. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must not be \c NULL. + * \param keybits The key size in bits. This must be acceptable by the cipher. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function releases and clears the specified CCM context + * and underlying cipher sub-context. + * + * \param ctx The CCM context to clear. If this is \c NULL, the function + * has no effect. Otherwise, this must be initialized. + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ); + +/** + * \brief This function encrypts a buffer using CCM. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param ad The additional data field. If \p ad_len is greater than + * zero, \p ad must be a readable buffer of at least that + * length. + * \param ad_len The length of additional data in Bytes. + * This must be less than `2^16 - 2^8`. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function encrypts a buffer using CCM*. + * + * \note The tag is written to a separate buffer. To concatenate + * the \p tag with the \p output, as done in RFC-3610: + * Counter with CBC-MAC (CCM), use + * \p tag = \p output + \p length, and make sure that the + * output buffer is at least \p length + \p tag_len wide. + * + * \note When using this function in a variable tag length context, + * the tag length has to be encoded into the \p iv passed to + * this function. + * + * \param ctx The CCM context to use for encryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * For tag length = 0, input length is ignored. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param ad The additional data field. This must be a readable buffer of + * at least \p ad_len Bytes. + * \param ad_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * writable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is no + * longer authenticated. + * + * \return \c 0 on success. + * \return A CCM or cipher-specific error code on failure. + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM authenticated decryption of a + * buffer. + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param ad The additional data field. This must be a readable buffer + * of at least that \p ad_len Bytes.. + * \param ad_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * + * \return \c 0 on success. This indicates that the message is authentic. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief This function performs a CCM* authenticated decryption of a + * buffer. + * + * \note When using this function in a variable tag length context, + * the tag length has to be decoded from \p iv and passed to + * this function as \p tag_len. (\p tag needs to be adjusted + * accordingly.) + * + * \param ctx The CCM context to use for decryption. This must be + * initialized and bound to a key. + * \param length The length of the input data in Bytes. + * For tag length = 0, input length is ignored. + * \param iv The initialization vector (nonce). This must be a readable + * buffer of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * \param ad The additional data field. This must be a readable buffer of + * at least that \p ad_len Bytes. + * \param ad_len The length of additional data in Bytes. + * This must be less than 2^16 - 2^8. + * \param input The buffer holding the input data. If \p length is greater + * than zero, \p input must be a readable buffer of at least + * that length. + * \param output The buffer holding the output data. If \p length is greater + * than zero, \p output must be a writable buffer of at least + * that length. + * \param tag The buffer holding the authentication field. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the authentication field in Bytes. + * 0, 4, 6, 8, 10, 12, 14 or 16. + * + * \warning Passing \c 0 as \p tag_len means that the message is nos + * longer authenticated. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match. + * \return A cipher-specific error code on calculation failure. + */ +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ); + +/** + * \brief This function starts a CCM encryption or decryption + * operation. + * + * This function and mbedtls_ccm_set_lengths() must be called + * before calling mbedtls_ccm_update_ad() or + * mbedtls_ccm_update(). This function can be called before + * or after mbedtls_ccm_set_lengths(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_CCM_ENCRYPT or + * #MBEDTLS_CCM_DECRYPT or #MBEDTLS_CCM_STAR_ENCRYPT or + * #MBEDTLS_CCM_STAR_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12, + * or 13. The length L of the message length field is + * 15 - \p iv_len. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * \p mode is invalid, + * \p iv_len is invalid (lower than \c 7 or greater than + * \c 13). + */ +int mbedtls_ccm_starts( mbedtls_ccm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function declares the lengths of the message + * and additional data for a CCM encryption or decryption + * operation. + * + * This function and mbedtls_ccm_starts() must be called + * before calling mbedtls_ccm_update_ad() or + * mbedtls_ccm_update(). This function can be called before + * or after mbedtls_ccm_starts(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must be initialized. + * \param total_ad_len The total length of additional data in bytes. + * This must be less than `2^16 - 2^8`. + * \param plaintext_len The length in bytes of the plaintext to encrypt or + * result of the decryption (thus not encompassing the + * additional data that are not encrypted). + * \param tag_len The length of the tag to generate in Bytes: + * 4, 6, 8, 10, 12, 14 or 16. + * For CCM*, zero is also valid. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * \p total_ad_len is greater than \c 0xFF00. + */ +int mbedtls_ccm_set_lengths( mbedtls_ccm_context *ctx, + size_t total_ad_len, + size_t plaintext_len, + size_t tag_len ); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a CCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the additional data. The + * lengths \p ad_len of the data parts should eventually add + * up exactly to the total length of additional data + * \c total_ad_len passed to mbedtls_ccm_set_lengths(). You + * may not call this function after calling + * mbedtls_ccm_update(). + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts(), the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths() and this must not have yet + * received any input with mbedtls_ccm_update(). + * \param ad The buffer holding the additional data, or \c NULL + * if \p ad_len is \c 0. + * \param ad_len The length of the additional data. If \c 0, + * \p ad may be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * total input length too long. + */ +int mbedtls_ccm_update_ad( mbedtls_ccm_context *ctx, + const unsigned char *ad, + size_t ad_len ); + +/** + * \brief This function feeds an input buffer into an ongoing CCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_ccm_finish(). The lengths \p input_len of the + * data parts should eventually add up exactly to the + * plaintext length \c plaintext_len passed to + * mbedtls_ccm_set_lengths(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: except for the last part of input data, + * the output consists of a whole number of 16-byte blocks. + * If the total input length so far (not including + * associated data) is 16 \* *B* + *A* with *A* < 16 then + * the total output length is 16 \* *B*. + * For the last part of input data, the output length is + * equal to the input length plus the number of bytes (*A*) + * buffered in the previous call to the function (if any). + * The function uses the plaintext length + * \c plaintext_len passed to mbedtls_ccm_set_lengths() + * to detect the last part of input data. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_len + 15. + * - If \p input_len is a multiple of 16 for all the calls + * to this function during an operation (not necessary for + * the last one) then it is correct to use \p output_size + * =\p input_len. + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts() and the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths(). + * \param input The buffer holding the input data. If \p input_len + * is greater than zero, this must be a readable buffer + * of at least \p input_len bytes. + * \param input_len The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_len On success, \p *output_len contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_len is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * total input length too long, + * or \p output_size too small. + */ +int mbedtls_ccm_update( mbedtls_ccm_context *ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t output_size, + size_t *output_len ); + +/** + * \brief This function finishes the CCM operation and generates + * the authentication tag. + * + * It wraps up the CCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \note This function is not implemented in Mbed TLS yet. + * + * \param ctx The CCM context. This must have been started with + * mbedtls_ccm_starts() and the lengths of the message and + * additional data must have been declared with + * mbedtls_ccm_set_lengths(). + * \param tag The buffer for holding the tag. If \p tag_len is greater + * than zero, this must be a writable buffer of at least \p + * tag_len Bytes. + * \param tag_len The length of the tag. Must match the tag length passed to + * mbedtls_ccm_set_lengths() function. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CCM_BAD_INPUT on failure: + * \p ctx is in an invalid state, + * invalid value of \p tag_len, + * the total amount of additional data passed to + * mbedtls_ccm_update_ad() was lower than the total length of + * additional data \c total_ad_len passed to + * mbedtls_ccm_set_lengths(), + * the total amount of input data passed to + * mbedtls_ccm_update() was lower than the plaintext length + * \c plaintext_len passed to mbedtls_ccm_set_lengths(). + */ +int mbedtls_ccm_finish( mbedtls_ccm_context *ctx, + unsigned char *tag, size_t tag_len ); + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The CCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ccm_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/chacha20.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/chacha20.h new file mode 100644 index 00000000..8af16ede --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/chacha20.h @@ -0,0 +1,215 @@ +/** + * \file chacha20.h + * + * \brief This file contains ChaCha20 definitions and functions. + * + * ChaCha20 is a stream cipher that can encrypt and decrypt + * information. ChaCha was created by Daniel Bernstein as a variant of + * its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf + * ChaCha20 is the variant with 20 rounds, that was also standardized + * in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CHACHA20_H +#define MBEDTLS_CHACHA20_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** Invalid input parameter(s). */ +#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CHACHA20_ALT) + +typedef struct mbedtls_chacha20_context +{ + uint32_t MBEDTLS_PRIVATE(state)[16]; /*! The state (before round operations). */ + uint8_t MBEDTLS_PRIVATE(keystream8)[64]; /*! Leftover keystream bytes. */ + size_t MBEDTLS_PRIVATE(keystream_bytes_used); /*! Number of keystream bytes already used. */ +} +mbedtls_chacha20_context; + +#else /* MBEDTLS_CHACHA20_ALT */ +#include "chacha20_alt.h" +#endif /* MBEDTLS_CHACHA20_ALT */ + +/** + * \brief This function initializes the specified ChaCha20 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by calls to + * \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts(), then one or more calls to + * to \c mbedtls_chacha20_update(), and finally to + * \c mbedtls_chacha20_free(). + * + * \param ctx The ChaCha20 context to initialize. + * This must not be \c NULL. + */ +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20 context. + * + * \param ctx The ChaCha20 context to clear. This may be \c NULL, + * in which case this function is a no-op. If it is not + * \c NULL, it must point to an initialized context. + * + */ +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ); + +/** + * \brief This function sets the encryption/decryption key. + * + * \note After using this function, you must also call + * \c mbedtls_chacha20_starts() to set a nonce before you + * start encrypting/decrypting data with + * \c mbedtls_chacha_update(). + * + * \param ctx The ChaCha20 context to which the key should be bound. + * It must be initialized. + * \param key The encryption/decryption key. This must be \c 32 Bytes + * in length. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL. + */ +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function sets the nonce and initial counter value. + * + * \note A ChaCha20 context can be re-used with the same key by + * calling this function to change the nonce. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality guarantees for the + * messages encrypted with the same nonce and key. + * + * \param ctx The ChaCha20 context to which the nonce should be bound. + * It must be initialized and bound to a key. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is + * NULL. + */ +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ); + +/** + * \brief This function encrypts or decrypts data. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \note \c mbedtls_chacha20_setkey() and + * \c mbedtls_chacha20_starts() must be called at least once + * to setup the context before this function can be called. + * + * \note This function can be called multiple times in a row in + * order to encrypt of decrypt data piecewise with the same + * key and nonce. + * + * \param ctx The ChaCha20 context to use for encryption or decryption. + * It must be initialized and bound to a key and nonce. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function encrypts or decrypts data with ChaCha20 and + * the given key and nonce. + * + * Since ChaCha20 is a stream cipher, the same operation is + * used for encrypting and decrypting data. + * + * \warning You must never use the same (key, nonce) pair more than + * once. This would void any confidentiality guarantees for + * the messages encrypted with the same nonce and key. + * + * \note The \p input and \p output pointers must either be equal or + * point to non-overlapping buffers. + * + * \param key The encryption/decryption key. + * This must be \c 32 Bytes in length. + * \param nonce The nonce. This must be \c 12 Bytes in size. + * \param counter The initial counter value. This is usually \c 0. + * \param size The length of the input data in Bytes. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `size == 0`. + * \param output The buffer holding the output data. + * This must be able to hold \p size Bytes. + * This pointer can be \c NULL if `size == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t size, + const unsigned char* input, + unsigned char* output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chacha20_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHA20_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/chachapoly.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/chachapoly.h new file mode 100644 index 00000000..3f4318fb --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/chachapoly.h @@ -0,0 +1,356 @@ +/** + * \file chachapoly.h + * + * \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and + * functions. + * + * ChaCha20-Poly1305 is an algorithm for Authenticated Encryption + * with Associated Data (AEAD) that can be used to encrypt and + * authenticate data. It is based on ChaCha20 and Poly1305 by Daniel + * Bernstein and was standardized in RFC 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CHACHAPOLY_H +#define MBEDTLS_CHACHAPOLY_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +/* for shared error codes */ +#include "mbedtls/poly1305.h" + +/** The requested operation is not permitted in the current state. */ +#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 +/** Authenticated decryption failed: data was not authentic. */ +#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */ + MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */ +} +mbedtls_chachapoly_mode_t; + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +#include "mbedtls/chacha20.h" + +typedef struct mbedtls_chachapoly_context +{ + mbedtls_chacha20_context MBEDTLS_PRIVATE(chacha20_ctx); /**< The ChaCha20 context. */ + mbedtls_poly1305_context MBEDTLS_PRIVATE(poly1305_ctx); /**< The Poly1305 context. */ + uint64_t MBEDTLS_PRIVATE(aad_len); /**< The length (bytes) of the Additional Authenticated Data. */ + uint64_t MBEDTLS_PRIVATE(ciphertext_len); /**< The length (bytes) of the ciphertext. */ + int MBEDTLS_PRIVATE(state); /**< The current state of the context. */ + mbedtls_chachapoly_mode_t MBEDTLS_PRIVATE(mode); /**< Cipher mode (encrypt or decrypt). */ +} +mbedtls_chachapoly_context; + +#else /* !MBEDTLS_CHACHAPOLY_ALT */ +#include "chachapoly_alt.h" +#endif /* !MBEDTLS_CHACHAPOLY_ALT */ + +/** + * \brief This function initializes the specified ChaCha20-Poly1305 context. + * + * It must be the first API called before using + * the context. It must be followed by a call to + * \c mbedtls_chachapoly_setkey() before any operation can be + * done, and to \c mbedtls_chachapoly_free() once all + * operations with that context have been finished. + * + * In order to encrypt or decrypt full messages at once, for + * each message you should make a single call to + * \c mbedtls_chachapoly_crypt_and_tag() or + * \c mbedtls_chachapoly_auth_decrypt(). + * + * In order to encrypt messages piecewise, for each + * message you should make a call to + * \c mbedtls_chachapoly_starts(), then 0 or more calls to + * \c mbedtls_chachapoly_update_aad(), then 0 or more calls to + * \c mbedtls_chachapoly_update(), then one call to + * \c mbedtls_chachapoly_finish(). + * + * \warning Decryption with the piecewise API is discouraged! Always + * use \c mbedtls_chachapoly_auth_decrypt() when possible! + * + * If however this is not possible because the data is too + * large to fit in memory, you need to: + * + * - call \c mbedtls_chachapoly_starts() and (if needed) + * \c mbedtls_chachapoly_update_aad() as above, + * - call \c mbedtls_chachapoly_update() multiple times and + * ensure its output (the plaintext) is NOT used in any other + * way than placing it in temporary storage at this point, + * - call \c mbedtls_chachapoly_finish() to compute the + * authentication tag and compared it in constant time to the + * tag received with the ciphertext. + * + * If the tags are not equal, you must immediately discard + * all previous outputs of \c mbedtls_chachapoly_update(), + * otherwise you can now safely use the plaintext. + * + * \param ctx The ChachaPoly context to initialize. Must not be \c NULL. + */ +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function releases and clears the specified + * ChaCha20-Poly1305 context. + * + * \param ctx The ChachaPoly context to clear. This may be \c NULL, in which + * case this function is a no-op. + */ +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ); + +/** + * \brief This function sets the ChaCha20-Poly1305 + * symmetric encryption key. + * + * \param ctx The ChaCha20-Poly1305 context to which the key should be + * bound. This must be initialized. + * \param key The \c 256 Bit (\c 32 Bytes) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This function starts a ChaCha20-Poly1305 encryption or + * decryption operation. + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \note If the context is being used for AAD only (no data to + * encrypt or decrypt) then \p mode can be set to any value. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param nonce The nonce/IV to use for the message. + * This must be a redable buffer of length \c 12 Bytes. + * \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or + * #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ); + +/** + * \brief This function feeds additional data to be authenticated + * into an ongoing ChaCha20-Poly1305 operation. + * + * The Additional Authenticated Data (AAD), also called + * Associated Data (AD) is only authenticated but not + * encrypted nor included in the encrypted output. It is + * usually transmitted separately from the ciphertext or + * computed locally by each party. + * + * \note This function is called before data is encrypted/decrypted. + * I.e. call this function to process the AAD before calling + * \c mbedtls_chachapoly_update(). + * + * You may call this function multiple times to process + * an arbitrary amount of AAD. It is permitted to call + * this function 0 times, if no AAD is used. + * + * This function cannot be called any more if data has + * been processed by \c mbedtls_chachapoly_update(), + * or if the context has been finished. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context. This must be initialized + * and bound to a key. + * \param aad_len The length in Bytes of the AAD. The length has no + * restrictions. + * \param aad Buffer containing the AAD. + * This pointer can be \c NULL if `aad_len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA + * if \p ctx or \p aad are NULL. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operations has not been started or has been + * finished, or if the AAD has been finished. + */ +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ); + +/** + * \brief Thus function feeds data to be encrypted or decrypted + * into an on-going ChaCha20-Poly1305 + * operation. + * + * The direction (encryption or decryption) depends on the + * mode that was given when calling + * \c mbedtls_chachapoly_starts(). + * + * You may call this function multiple times to process + * an arbitrary amount of data. It is permitted to call + * this function 0 times, if no data is to be encrypted + * or decrypted. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param len The length (in bytes) of the data to encrypt or decrypt. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `len == 0`. + * \param output The buffer to where the encrypted or decrypted data is + * written. This must be able to hold \p len bytes. + * This pointer can be \c NULL if `len == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function finished the ChaCha20-Poly1305 operation and + * generates the MAC (authentication tag). + * + * \param ctx The ChaCha20-Poly1305 context to use. This must be initialized. + * \param mac The buffer to where the 128-bit (16 bytes) MAC is written. + * + * \warning Decryption with the piecewise API is discouraged, see the + * warning on \c mbedtls_chachapoly_init(). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE + * if the operation has not been started or has been + * finished. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated encryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \warning You must never use the same nonce twice with the same key. + * This would void any confidentiality and authenticity + * guarantees for the messages encrypted with the same nonce + * and key. + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * This must be initialized. + * \param length The length (in bytes) of the data to encrypt or decrypt. + * \param nonce The 96-bit (12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated + * data (AAD). This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param input The buffer containing the data to encrypt or decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the encrypted or decrypted data + * is written. This pointer can be \c NULL if `ilen == 0`. + * \param tag The buffer to where the computed 128-bit (16 bytes) MAC + * is written. This must not be \c NULL. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ); + +/** + * \brief This function performs a complete ChaCha20-Poly1305 + * authenticated decryption with the previously-set key. + * + * \note Before using this function, you must set the key with + * \c mbedtls_chachapoly_setkey(). + * + * \param ctx The ChaCha20-Poly1305 context to use (holds the key). + * \param length The length (in Bytes) of the data to decrypt. + * \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use. + * \param aad The buffer containing the additional authenticated data (AAD). + * This pointer can be \c NULL if `aad_len == 0`. + * \param aad_len The length (in bytes) of the AAD data to process. + * \param tag The buffer holding the authentication tag. + * This must be a readable buffer of length \c 16 Bytes. + * \param input The buffer containing the data to decrypt. + * This pointer can be \c NULL if `ilen == 0`. + * \param output The buffer to where the decrypted data is written. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED + * if the data was not authentic. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The ChaCha20-Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_chachapoly_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CHACHAPOLY_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/check_config.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/check_config.h new file mode 100644 index 00000000..d6d8c4a5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/check_config.h @@ -0,0 +1,835 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in mbedtls_config.h as + * it would confuse config.py. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif + +#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) +#error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ + defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ + ( !defined(MBEDTLS_SHA256_C) && \ + !defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA1_C) ) +#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && \ + !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \ + defined(MBEDTLS_ENTROPY_C) ) || \ + defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ + defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) +#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + ! defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + defined(MBEDTLS_ENTROPY_NV_SEED) ) +#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" +#endif + +/* +#if defined(MBEDTLS_PSA_ITS_FILE_C) && \ + !defined(MBEDTLS_FS_IO) +#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" +#endif +*/ + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO." +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SHA384_C) && !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA384_C defined without MBEDTLS_SHA512_C" +#endif + +#if defined(MBEDTLS_SHA224_C) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_SHA224_C defined without MBEDTLS_SHA256_C" +#endif + +#if defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA224_C) +#error "MBEDTLS_SHA256_C defined without MBEDTLS_SHA224_C" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +/* + * HKDF is mandatory for TLS 1.3. + * Otherwise support for at least one ciphersuite mandates either SHA_256 or + * SHA_384. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + ( ( !defined(MBEDTLS_HKDF_C) ) || \ + ( !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA384_C) ) || \ + ( !defined(MBEDTLS_PSA_CRYPTO_C) ) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \ + MBEDTLS_SSL_CID_IN_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \ + MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ) +#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" +#endif + + + +/* Reject attempts to enable options that have been removed and that could + * cause a build to succeed but with features removed. */ + +#if defined(MBEDTLS_HAVEGE_C) //no-check-names +#error "MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/2599" +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names +#error "MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names +#error "MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names +#error "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates." +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names +#error "MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) //no-check-names +#error "MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4313" +#endif + +#if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4341" +#endif + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/cipher.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/cipher.h new file mode 100644 index 00000000..c04097da --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/cipher.h @@ -0,0 +1,1159 @@ +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 +/** Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 +/** Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 +/** Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 +/** Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 +/** The context is invalid. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported cipher types. + * + * \warning DES is considered weak cipher and its use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; + +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning DES is considered weak cipher and its use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ + MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_CCM_STAR_NO_TAG, /**< The CCM*-no-tag cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ + MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ + MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined + * in library/ssl_misc.h. */ +#define MBEDTLS_MAX_IV_LENGTH 16 + +/** Maximum block size of any cipher, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in library/ssl_misc.h. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** Maximum key length, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * For now, only check whether XTS is enabled which uses 64 Byte keys, + * and use 32 Bytes as an upper bound for the maximum key length otherwise. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in library/ssl_misc.h, which however deliberately ignores the case of XTS + * since the latter isn't used in SSL/TLS. */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#define MBEDTLS_MAX_KEY_LENGTH 64 +#else +#define MBEDTLS_MAX_KEY_LENGTH 32 +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + * + * \note The library does not support custom cipher info structures, + * only built-in structures returned by the functions + * mbedtls_cipher_info_from_string(), + * mbedtls_cipher_info_from_type(), + * mbedtls_cipher_info_from_values(), + * mbedtls_cipher_info_from_psa(). + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t MBEDTLS_PRIVATE(type); + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t MBEDTLS_PRIVATE(mode); + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int MBEDTLS_PRIVATE(key_bitlen); + + /** Name of the cipher. */ + const char * MBEDTLS_PRIVATE(name); + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int MBEDTLS_PRIVATE(iv_size); + + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int MBEDTLS_PRIVATE(flags); + + /** The block size, in Bytes. */ + unsigned int MBEDTLS_PRIVATE(block_size); + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *MBEDTLS_PRIVATE(base); + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info); + + /** Key length to use. */ + int MBEDTLS_PRIVATE(key_bitlen); + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t MBEDTLS_PRIVATE(operation); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*MBEDTLS_PRIVATE(add_padding))( unsigned char *output, size_t olen, size_t data_len ); + int (*MBEDTLS_PRIVATE(get_padding))( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t MBEDTLS_PRIVATE(unprocessed_len); + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t MBEDTLS_PRIVATE(iv_size); + + /** The cipher-specific context. */ + void *MBEDTLS_PRIVATE(cipher_ctx); + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /** Indicates whether the cipher operations should be performed + * by Mbed TLS' own crypto library or an external implementation + * of the PSA Crypto API. + * This is unset if the cipher context was established through + * mbedtls_cipher_setup(), and set if it was established through + * mbedtls_cipher_setup_psa(). + */ + unsigned char MBEDTLS_PRIVATE(psa_enabled); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported + * by the generic cipher module. + * + * For any cipher identifier in the returned list, you can + * obtain the corresponding generic cipher information structure + * via mbedtls_cipher_info_from_type(), which can then be used + * to prepare a cipher context via mbedtls_cipher_setup(). + * + * + * \return A statically-allocated array of cipher identifiers + * of type cipher_type_t. The last entry is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief Retrieve the identifier for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). + * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( MBEDTLS_CIPHER_NONE ); + else + return( info->MBEDTLS_PRIVATE(type) ); +} + +/** + * \brief Retrieve the operation mode for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher mode (\c MBEDTLS_MODE_xxx). + * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( MBEDTLS_MODE_NONE ); + else + return( info->MBEDTLS_PRIVATE(mode) ); +} + +/** + * \brief Retrieve the key size for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The key length in bits. + * For variable-sized ciphers, this is the default length. + * For DES, this includes the parity bits. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_key_bitlen( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + else + return( info->MBEDTLS_PRIVATE(key_bitlen) ); +} + +/** + * \brief Retrieve the human-readable name for a + * cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher name, which is a human readable string, + * with static storage duration. + * \return \c NULL if \c info is \p NULL. + */ +static inline const char *mbedtls_cipher_info_get_name( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( NULL ); + else + return( info->MBEDTLS_PRIVATE(name) ); +} + +/** + * \brief This function returns the size of the IV or nonce + * for the cipher info structure, in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The recommended IV size. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_iv_size( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + + return( (size_t) info->MBEDTLS_PRIVATE(iv_size) ); +} + +/** + * \brief This function returns the block size of the given + * cipher info structure in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The block size of the cipher. + * \return \c 1 if the cipher is a stream cipher. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_block_size( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + + return( (size_t) info->MBEDTLS_PRIVATE(block_size) ); +} + +/** + * \brief This function returns a non-zero value if the key length for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the key length is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_key_bitlen( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + + return( info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ); +} + +/** + * \brief This function returns a non-zero value if the IV size for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the IV size is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_iv_size( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + + return( info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN ); +} + +/** + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function prepares a cipher context for + * use with the given cipher primitive. + * + * \note After calling this function, you should call + * mbedtls_cipher_setkey() and, if the mode uses padding, + * mbedtls_cipher_set_padding_mode(), then for each + * message to encrypt or decrypt with this key, either: + * - mbedtls_cipher_crypt() for one-shot processing with + * non-AEAD modes; + * - mbedtls_cipher_auth_encrypt_ext() or + * mbedtls_cipher_auth_decrypt_ext() for one-shot + * processing with AEAD modes or NIST_KW; + * - for multi-part processing, see the documentation of + * mbedtls_cipher_reset(). + * + * \param ctx The context to prepare. This must be initialized by + * a call to mbedtls_cipher_init() first. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief This function initializes a cipher context for + * PSA-based use with the given cipher primitive. + * + * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. + * + * \param ctx The context to initialize. May not be \c NULL. + * \param cipher_info The cipher to use. + * \param taglen For AEAD ciphers, the length in bytes of the + * authentication tag to use. Subsequent uses of + * mbedtls_cipher_auth_encrypt_ext() or + * mbedtls_cipher_auth_decrypt_ext() must provide + * the same tag length. + * For non-AEAD ciphers, the value must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief This function returns the block size of the given cipher + * in bytes. + * + * \param ctx The context of the cipher. + * + * \return The block size of the underlying cipher. + * \return \c 1 if the cipher is a stream cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return 0; + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size); +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_MODE_NONE; + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode); +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return 0; + + if( ctx->MBEDTLS_PRIVATE(iv_size) != 0 ) + return (int) ctx->MBEDTLS_PRIVATE(iv_size); + + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size); +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_CIPHER_NONE; + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type); +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return 0; + + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(name); +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen); +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_OPERATION_NONE; + + return ctx->MBEDTLS_PRIVATE(operation); +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \note With non-AEAD ciphers, the order of calls for each message + * is as follows: + * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. + * 2. mbedtls_cipher_reset() + * 3. mbedtls_cipher_update() one or more times + * 4. mbedtls_cipher_finish() + * . + * This sequence can be repeated to encrypt or decrypt multiple + * messages with the same key. + * + * \note With AEAD ciphers, the order of calls for each message + * is as follows: + * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. + * 2. mbedtls_cipher_reset() + * 3. mbedtls_cipher_update_ad() + * 4. mbedtls_cipher_update() one or more times + * 5. mbedtls_cipher_finish() + * 6. mbedtls_cipher_check_tag() (for decryption) or + * mbedtls_cipher_write_tag() (for encryption). + * . + * This sequence can be repeated to encrypt or decrypt multiple + * messages with the same key. + * + * \param ctx The generic cipher context. This must be bound to a key. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad in Bytes. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, + size_t ilen, unsigned char *output, + size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) +/** + * \brief The authenticated encryption (AEAD/NIST_KW) function. + * + * \note For AEAD modes, the tag will be appended to the + * ciphertext, as recommended by RFC 5116. + * (NIST_KW doesn't have a separate tag.) + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key, with an AEAD algorithm or NIST_KW. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and may be \c NULL if \p + * iv_len is \c 0. + * \param iv_len The length of the nonce. For AEAD ciphers, this must + * satisfy the constraints imposed by the cipher used. + * For NIST_KW, this must be \c 0. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p output_len Bytes, and + * must not be \c NULL. + * \param output_len The length of the \p output buffer in Bytes. For AEAD + * ciphers, this must be at least \p ilen + \p tag_len. + * For NIST_KW, this must be at least \p ilen + 8 + * (rounded up to a multiple of 8 if KWP is used); + * \p ilen + 15 is always a safe value. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag_len The desired length of the authentication tag. For AEAD + * ciphers, this must match the constraints imposed by + * the cipher used, and in particular must not be \c 0. + * For NIST_KW, this must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ); + +/** + * \brief The authenticated encryption (AEAD/NIST_KW) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \note For AEAD modes, the tag must be appended to the + * ciphertext, as recommended by RFC 5116. + * (NIST_KW doesn't have a separate tag.) + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key, with an AEAD algorithm or NIST_KW. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and may be \c NULL if \p + * iv_len is \c 0. + * \param iv_len The length of the nonce. For AEAD ciphers, this must + * satisfy the constraints imposed by the cipher used. + * For NIST_KW, this must be \c 0. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. For AEAD ciphers this + * must be at least \p tag_len. For NIST_KW this must be + * at least \c 8. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p output_len Bytes, and + * may be \c NULL if \p output_len is \c 0. + * \param output_len The length of the \p output buffer in Bytes. For AEAD + * ciphers, this must be at least \p ilen - \p tag_len. + * For NIST_KW, this must be at least \p ilen - 8. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag_len The actual length of the authentication tag. For AEAD + * ciphers, this must match the constraints imposed by + * the cipher used, and in particular must not be \c 0. + * For NIST_KW, this must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/cmac.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/cmac.h new file mode 100644 index 00000000..21ce8827 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/cmac.h @@ -0,0 +1,240 @@ +/** + * \file cmac.h + * + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char MBEDTLS_PRIVATE(state)[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t MBEDTLS_PRIVATE(unprocessed_len); +}; + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +/** + * \brief This function starts a new CMAC computation + * by setting the CMAC key, and preparing to authenticate + * the input data. + * It must be called with an initialized cipher context. + * + * Once this function has completed, data can be supplied + * to the CMAC computation by calling + * mbedtls_cipher_cmac_update(). + * + * To start a CMAC computation using the same key as a previous + * CMAC computation, use mbedtls_cipher_cmac_finish(). + * + * \note When the CMAC implementation is supplied by an alternate + * implementation (through #MBEDTLS_CMAC_ALT), some ciphers + * may not be supported by that implementation, and thus + * return an error. Alternate implementations must support + * AES-128 and AES-256, and may support AES-192 and 3DES. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * The CMAC computation must have previously been started + * by calling mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(). + * + * Call this function as many times as needed to input the + * data to be authenticated. + * Once all of the required data has been input, + * call mbedtls_cipher_cmac_finish() to obtain the result + * of the CMAC operation. + * + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes an ongoing CMAC operation, and + * writes the result to the output buffer. + * + * It should be followed either by + * mbedtls_cipher_cmac_reset(), which starts another CMAC + * operation with the same key, or mbedtls_cipher_free(), + * which clears the cipher context. + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function starts a new CMAC operation with the same + * key as the previous one. + * + * It should be called after finishing the previous CMAC + * operation with mbedtls_cipher_cmac_finish(). + * After calling this function, + * call mbedtls_cipher_cmac_update() to supply the new + * CMAC operation with data. + * + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * \note When the CMAC implementation is supplied by an alternate + * implementation (through #MBEDTLS_CMAC_ALT), some ciphers + * may not be supported by that implementation, and thus + * return an error. Alternate implementations must support + * AES-128 and AES-256, and may support AES-192 and 3DES. + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \note In case the CMAC routines are provided by an alternative + * implementation (i.e. #MBEDTLS_CMAC_ALT is defined), the + * checkup routine will succeed even if the implementation does + * not support the less widely used AES-192 or 3DES primitives. + * The self-test requires at least AES-128 and AES-256 to be + * supported by the underlying implementation. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/compat-2.x.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/compat-2.x.h new file mode 100644 index 00000000..cdf81dcb --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/compat-2.x.h @@ -0,0 +1,58 @@ +/** + * \file compat-2.x.h + * + * \brief Compatibility definitions + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-2.x.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT2X_H +#define MBEDTLS_COMPAT2X_H + +/* + * Macros for renamed functions + */ +#define mbedtls_ctr_drbg_update_ret mbedtls_ctr_drbg_update +#define mbedtls_hmac_drbg_update_ret mbedtls_hmac_drbg_update +#define mbedtls_md5_starts_ret mbedtls_md5_starts +#define mbedtls_md5_update_ret mbedtls_md5_update +#define mbedtls_md5_finish_ret mbedtls_md5_finish +#define mbedtls_md5_ret mbedtls_md5 +#define mbedtls_ripemd160_starts_ret mbedtls_ripemd160_starts +#define mbedtls_ripemd160_update_ret mbedtls_ripemd160_update +#define mbedtls_ripemd160_finish_ret mbedtls_ripemd160_finish +#define mbedtls_ripemd160_ret mbedtls_ripemd160 +#define mbedtls_sha1_starts_ret mbedtls_sha1_starts +#define mbedtls_sha1_update_ret mbedtls_sha1_update +#define mbedtls_sha1_finish_ret mbedtls_sha1_finish +#define mbedtls_sha1_ret mbedtls_sha1 +#define mbedtls_sha256_starts_ret mbedtls_sha256_starts +#define mbedtls_sha256_update_ret mbedtls_sha256_update +#define mbedtls_sha256_finish_ret mbedtls_sha256_finish +#define mbedtls_sha256_ret mbedtls_sha256 +#define mbedtls_sha512_starts_ret mbedtls_sha512_starts +#define mbedtls_sha512_update_ret mbedtls_sha512_update +#define mbedtls_sha512_finish_ret mbedtls_sha512_finish +#define mbedtls_sha512_ret mbedtls_sha512 + +#endif /* MBEDTLS_COMPAT2X_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/config_psa.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/config_psa.h new file mode 100644 index 00000000..68dda0f3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/config_psa.h @@ -0,0 +1,800 @@ +/** + * \file mbedtls/config_psa.h + * \brief PSA crypto configuration options (set of defines) + * + * This set of compile-time options takes settings defined in + * include/mbedtls/mbedtls_config.h and include/psa/crypto_config.h and uses + * those definitions to define symbols used in the library code. + * + * Users and integrators should not edit this file, please edit + * include/mbedtls/mbedtls_config.h for MBETLS_XXX settings or + * include/psa/crypto_config.h for PSA_WANT_XXX settings. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CONFIG_PSA_H +#define MBEDTLS_CONFIG_PSA_H + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#include "psa/crypto_config.h" +#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */ + +#ifdef __cplusplus +extern "C" { +#endif + + + +/****************************************************************/ +/* De facto synonyms */ +/****************************************************************/ + +#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY +#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW +#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN +#endif + +#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT +#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS +#endif + + + +/****************************************************************/ +/* Require built-in implementations based on PSA requirements */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) + +#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define MBEDTLS_ECDSA_DETERMINISTIC +#define MBEDTLS_ECDSA_C +#define MBEDTLS_HMAC_DRBG_C +#define MBEDTLS_MD_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */ +#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */ + +#if defined(PSA_WANT_ALG_ECDH) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 +#define MBEDTLS_ECDH_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDH */ +#endif /* PSA_WANT_ALG_ECDH */ + +#if defined(PSA_WANT_ALG_ECDSA) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define MBEDTLS_ECDSA_C +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */ +#endif /* PSA_WANT_ALG_ECDSA */ + +#if defined(PSA_WANT_ALG_HKDF) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */ +#endif /* PSA_WANT_ALG_HKDF */ + +#if defined(PSA_WANT_ALG_HMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */ +#endif /* PSA_WANT_ALG_HMAC */ + +#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5) +#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 +#define MBEDTLS_MD5_C +#endif + +#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) +#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 +#define MBEDTLS_RIPEMD160_C +#endif + +#if defined(PSA_WANT_ALG_RSA_OAEP) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_MD_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */ +#endif /* PSA_WANT_ALG_RSA_OAEP */ + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */ +#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */ + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_MD_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */ +#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */ + +#if defined(PSA_WANT_ALG_RSA_PSS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PKCS1_V21 +#define MBEDTLS_MD_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */ +#endif /* PSA_WANT_ALG_RSA_PSS */ + +#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 +#define MBEDTLS_SHA1_C +#endif + +#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 +#define MBEDTLS_SHA224_C +#endif + +#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 +#define MBEDTLS_SHA256_C +#endif + +#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 +#define MBEDTLS_SHA384_C +#endif + +#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 +#define MBEDTLS_SHA512_C +#endif + +#if defined(PSA_WANT_ALG_TLS12_PRF) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */ +#endif /* PSA_WANT_ALG_TLS12_PRF */ + +#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS) +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */ +#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR */ +#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define MBEDTLS_ECP_C +#define MBEDTLS_BIGNUM_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */ +#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_GENPRIME +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PK_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR */ +#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */ + +#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#define MBEDTLS_RSA_C +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_PK_WRITE_C +#define MBEDTLS_PK_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_ASN1_WRITE_C +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */ +#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */ + +/* If any of the block modes are requested that don't have an + * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking + * in the block cipher key types. */ +#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \ + (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \ + (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \ + (defined(PSA_WANT_ALG_XTS) && !defined(MBEDTLS_PSA_ACCEL_ALG_XTS)) || \ + defined(PSA_WANT_ALG_ECB_NO_PADDING) || \ + (defined(PSA_WANT_ALG_CBC_NO_PADDING) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \ + (defined(PSA_WANT_ALG_CBC_PKCS7) && \ + !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \ + (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC)) +#define PSA_HAVE_SOFT_BLOCK_MODE 1 +#endif + +#if (defined(PSA_WANT_ALG_GCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_GCM)) || \ + (defined(PSA_WANT_ALG_CCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_CCM)) +#define PSA_HAVE_SOFT_BLOCK_AEAD 1 +#endif + +#if defined(PSA_WANT_KEY_TYPE_AES) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES) +#define PSA_HAVE_SOFT_KEY_TYPE_AES 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ + defined(PSA_HAVE_SOFT_BLOCK_AEAD) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 +#define MBEDTLS_AES_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_AES */ + +#if defined(PSA_WANT_KEY_TYPE_ARIA) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA) +#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ + defined(PSA_HAVE_SOFT_BLOCK_AEAD) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 +#define MBEDTLS_ARIA_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_ARIA */ + +#if defined(PSA_WANT_KEY_TYPE_CAMELLIA) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA) +#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) || \ + defined(PSA_HAVE_SOFT_BLOCK_AEAD) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 +#define MBEDTLS_CAMELLIA_C +#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */ + +#if defined(PSA_WANT_KEY_TYPE_DES) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) +#define PSA_HAVE_SOFT_KEY_TYPE_DES 1 +#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ + defined(PSA_HAVE_SOFT_BLOCK_MODE) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 +#define MBEDTLS_DES_C +#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */ +#endif /* PSA_WANT_KEY_TYPE_DES */ + +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) +#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 +#define MBEDTLS_CHACHA20_C +#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */ +#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ + +/* If any of the software block ciphers are selected, define + * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these + * situations. */ +#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define PSA_HAVE_SOFT_BLOCK_CIPHER 1 +#endif + +#if defined(PSA_WANT_ALG_STREAM_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 +#endif /* PSA_WANT_ALG_STREAM_CIPHER */ + +#if defined(PSA_WANT_ALG_CBC_MAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC) +#error "CBC-MAC is not yet supported via the PSA API in Mbed TLS." +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1 +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */ +#endif /* PSA_WANT_ALG_CBC_MAC */ + +#if defined(PSA_WANT_ALG_CMAC) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 +#define MBEDTLS_CMAC_C +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */ +#endif /* PSA_WANT_ALG_CMAC */ + +#if defined(PSA_WANT_ALG_CTR) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 +#define MBEDTLS_CIPHER_MODE_CTR +#endif +#endif /* PSA_WANT_ALG_CTR */ + +#if defined(PSA_WANT_ALG_CFB) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 +#define MBEDTLS_CIPHER_MODE_CFB +#endif +#endif /* PSA_WANT_ALG_CFB */ + +#if defined(PSA_WANT_ALG_OFB) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 +#define MBEDTLS_CIPHER_MODE_OFB +#endif +#endif /* PSA_WANT_ALG_OFB */ + +#if defined(PSA_WANT_ALG_XTS) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_XTS) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1 +#define MBEDTLS_CIPHER_MODE_XTS +#endif +#endif /* PSA_WANT_ALG_XTS */ + +#if defined(PSA_WANT_ALG_ECB_NO_PADDING) +#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(PSA_WANT_ALG_CBC_NO_PADDING) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 +#endif +#endif /* PSA_WANT_ALG_CBC_NO_PADDING */ + +#if defined(PSA_WANT_ALG_CBC_PKCS7) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \ + defined(PSA_HAVE_SOFT_BLOCK_CIPHER) +#define MBEDTLS_CIPHER_MODE_CBC +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#endif /* PSA_WANT_ALG_CBC_PKCS7 */ + +#if defined(PSA_WANT_ALG_CCM) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 +#define MBEDTLS_CCM_C +#endif +#endif /* PSA_WANT_ALG_CCM */ + +#if defined(PSA_WANT_ALG_GCM) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \ + defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) +#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 +#define MBEDTLS_GCM_C +#endif +#endif /* PSA_WANT_ALG_GCM */ + +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) +#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305) +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) +#define MBEDTLS_CHACHAPOLY_C +#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 +#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */ +#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */ +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256 */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384 */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */ + +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512 */ +#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */ + +#if defined(PSA_WANT_ECC_MONTGOMERY_255) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255 */ +#endif /* PSA_WANT_ECC_MONTGOMERY_255 */ + +#if defined(PSA_WANT_ECC_MONTGOMERY_448) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) +#define MBEDTLS_ECP_DP_CURVE448_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448 */ +#endif /* PSA_WANT_ECC_MONTGOMERY_448 */ + +#if defined(PSA_WANT_ECC_SECP_R1_192) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192 */ +#endif /* PSA_WANT_ECC_SECP_R1_192 */ + +#if defined(PSA_WANT_ECC_SECP_R1_224) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224 */ +#endif /* PSA_WANT_ECC_SECP_R1_224 */ + +#if defined(PSA_WANT_ECC_SECP_R1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 */ +#endif /* PSA_WANT_ECC_SECP_R1_256 */ + +#if defined(PSA_WANT_ECC_SECP_R1_384) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 */ +#endif /* PSA_WANT_ECC_SECP_R1_384 */ + +#if defined(PSA_WANT_ECC_SECP_R1_521) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521 */ +#endif /* PSA_WANT_ECC_SECP_R1_521 */ + +#if defined(PSA_WANT_ECC_SECP_K1_192) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192 */ +#endif /* PSA_WANT_ECC_SECP_K1_192 */ + +#if defined(PSA_WANT_ECC_SECP_K1_224) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) +/* + * SECP224K1 is buggy via the PSA API in Mbed TLS + * (https://github.com/ARMmbed/mbedtls/issues/3541). + */ +#error "SECP224K1 is buggy via the PSA API in Mbed TLS." +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224 */ +#endif /* PSA_WANT_ECC_SECP_K1_224 */ + +#if defined(PSA_WANT_ECC_SECP_K1_256) +#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 +#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256 */ +#endif /* PSA_WANT_ECC_SECP_K1_256 */ + + + +/****************************************************************/ +/* Infer PSA requirements from Mbed TLS capabilities */ +/****************************************************************/ + +#else /* MBEDTLS_PSA_CRYPTO_CONFIG */ + +/* + * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG + * is not defined + */ + +#if defined(MBEDTLS_CCM_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1 +#define PSA_WANT_ALG_CCM 1 +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CMAC_C) +#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1 +#define PSA_WANT_ALG_CMAC 1 +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1 +#define PSA_WANT_ALG_ECDH 1 +#endif /* MBEDTLS_ECDH_C */ + +#if defined(MBEDTLS_ECDSA_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1 +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_ECDSA_ANY 1 + +// Only add in DETERMINISTIC support if ECDSA is also enabled +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_GCM_C) +#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1 +#define PSA_WANT_ALG_GCM 1 +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HKDF_C) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define PSA_WANT_ALG_HMAC 1 +#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1 +#define PSA_WANT_ALG_HKDF 1 +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_MD_C) +#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1 +#define PSA_WANT_ALG_HMAC 1 +#define PSA_WANT_KEY_TYPE_HMAC +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1 +#define PSA_WANT_ALG_TLS12_PRF 1 +#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1 +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_MD5_C) +#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1 +#define PSA_WANT_ALG_MD5 1 +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1 +#define PSA_WANT_ALG_RIPEMD160 1 +#endif + +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_PKCS1_V15) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1 +#endif /* MBEDTLS_PKCS1_V15 */ +#if defined(MBEDTLS_PKCS1_V21) +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1 +#define PSA_WANT_ALG_RSA_OAEP 1 +#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1 +#define PSA_WANT_ALG_RSA_PSS 1 +#endif /* MBEDTLS_PKCS1_V21 */ +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SHA1_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1 +#define PSA_WANT_ALG_SHA_1 1 +#endif + +#if defined(MBEDTLS_SHA224_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1 +#define PSA_WANT_ALG_SHA_224 1 +#endif + +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1 +#define PSA_WANT_ALG_SHA_256 1 +#endif + +#if defined(MBEDTLS_SHA384_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1 +#define PSA_WANT_ALG_SHA_384 1 +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1 +#define PSA_WANT_ALG_SHA_512 1 +#endif + +#if defined(MBEDTLS_AES_C) +#define PSA_WANT_KEY_TYPE_AES 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1 +#endif + +#if defined(MBEDTLS_ARIA_C) +#define PSA_WANT_KEY_TYPE_ARIA 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1 +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1 +#endif + +#if defined(MBEDTLS_DES_C) +#define PSA_WANT_KEY_TYPE_DES 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1 +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1 +#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1 +#if defined(MBEDTLS_CHACHAPOLY_C) +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1 +#endif +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1 +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1 +#define PSA_WANT_ALG_CBC_PKCS7 1 +#endif +#endif + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \ + defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C) +#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1 +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1 +#define PSA_WANT_ALG_CFB 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1 +#define PSA_WANT_ALG_CTR 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1 +#define PSA_WANT_ALG_OFB 1 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1 +#define PSA_WANT_ALG_XTS 1 +#endif + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 +#endif + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 +#endif + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1 +#define PSA_WANT_ECC_MONTGOMERY_255 +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1 +#define PSA_WANT_ECC_MONTGOMERY_448 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1 +#define PSA_WANT_ECC_SECP_R1_192 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1 +#define PSA_WANT_ECC_SECP_R1_224 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1 +#define PSA_WANT_ECC_SECP_R1_256 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1 +#define PSA_WANT_ECC_SECP_R1_384 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1 +#define PSA_WANT_ECC_SECP_R1_521 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1 +#define PSA_WANT_ECC_SECP_K1_192 +#endif + +/* SECP224K1 is buggy via the PSA API (https://github.com/ARMmbed/mbedtls/issues/3541) */ +#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1 +#define PSA_WANT_ECC_SECP_K1_224 +#endif + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1 +#define PSA_WANT_ECC_SECP_K1_256 +#endif + +#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */ + +/* These features are always enabled. */ +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CONFIG_PSA_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/constant_time.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/constant_time.h new file mode 100644 index 00000000..c5de57a0 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/constant_time.h @@ -0,0 +1,45 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_H +#define MBEDTLS_CONSTANT_TIME_H + +#include + + +/** Constant-time buffer comparison without branches. + * + * This is equivalent to the standard memcmp function, but is likely to be + * compiled to code using bitwise operation rather than a branch. + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param a Pointer to the first buffer. + * \param b Pointer to the second buffer. + * \param n The number of bytes to compare in the buffer. + * + * \return Zero if the content of the two buffer is the same, + * otherwise non-zero. + */ +int mbedtls_ct_memcmp( const void *a, + const void *b, + size_t n ); + +#endif /* MBEDTLS_CONSTANT_TIME_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ctr_drbg.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ctr_drbg.h new file mode 100644 index 00000000..959a5d57 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ctr_drbg.h @@ -0,0 +1,579 @@ +/** + * \file ctr_drbg.h + * + * \brief This file contains definitions and functions for the + * CTR_DRBG pseudorandom generator. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128 + * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time) + * as the underlying block cipher, with a derivation function. + * + * The security strength as defined in NIST SP 800-90A is + * 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled) + * and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * kept at its default value (and not overridden in mbedtls_config.h) and that the + * DRBG instance is set up with default parameters. + * See the documentation of mbedtls_ctr_drbg_seed() for more + * information. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 +/** The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 +/** The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 +/** Read or write error in file. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +#define MBEDTLS_CTR_DRBG_KEYSIZE 16 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 16 bytes (128 bits) + * because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled. + */ +#else +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 +/**< The key size in bytes used by the cipher. + * + * Compile-time choice: 32 bytes (256 bits) + * because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled. + */ +#endif + +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them using the compiler command + * line. + * \{ + */ + +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). + */ +#if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +/** \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer in bytes. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** The default length of the nonce read from the entropy source. + * + * This is \c 0 because a single read from the entropy source is sufficient + * to include a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0 +#else +/** The default length of the nonce read from the entropy source. + * + * This is half of the default entropy length because a single read from + * the entropy source does not provide enough material to form a nonce. + * See the documentation of mbedtls_ctr_drbg_seed() for more information. + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2 +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct mbedtls_ctr_drbg_context +{ + unsigned char MBEDTLS_PRIVATE(counter)[16]; /*!< The counter (V). */ + int MBEDTLS_PRIVATE(reseed_counter); /*!< The reseed counter. + * This is the number of requests that have + * been made since the last (re)seeding, + * minus one. + * Before the initial seeding, this field + * contains the amount of entropy in bytes + * to use as a nonce for the initial seeding, + * or -1 if no nonce length has been explicitly + * set (see mbedtls_ctr_drbg_set_nonce_len()). + */ + int MBEDTLS_PRIVATE(prediction_resistance); /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t MBEDTLS_PRIVATE(entropy_len); /*!< The amount of entropy grabbed on each + seed or reseed operation, in bytes. */ + int MBEDTLS_PRIVATE(reseed_interval); /*!< The reseed interval. + * This is the maximum number of requests + * that can be made between reseedings. */ + + mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx); /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *MBEDTLS_PRIVATE(p_entropy); /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if f_entropy != NULL. + * This means that the mutex is initialized during the initial seeding + * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \note The reseed interval is + * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. + * You can override it by calling + * mbedtls_ctr_drbg_set_reseed_interval(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * The entropy nonce length is: + * - \c 0 if the entropy length is at least 3/2 times the entropy length, + * which guarantees that the security strength is the maximum permitted + * by the key size and entropy length according to NIST SP 800-90A §10.2.1; + * - Half the entropy length otherwise. + * You can override it by calling mbedtls_ctr_drbg_set_nonce_len(). + * With the default entropy length, the entropy nonce length is + * #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN. + * + * You can provide a nonce and personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * See SP 800-90A §8.6.7 for more details about nonces. + * + * The _seed_material_ value passed to the derivation function in + * the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the following strings: + * - A string obtained by calling \p f_entropy function for the entropy + * length. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0 +/** + * - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string + * obtained by calling \p f_entropy function for the specified length. + */ +#else +/** + * - A string obtained by calling \p f_entropy function for the entropy nonce + * length. If the entropy nonce length is \c 0, this function does not + * make a second call to \p f_entropy. + */ +#endif +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * - The \p custom string. + * + * \note To achieve the nominal security strength permitted + * by CTR_DRBG, the entropy length must be: + * - at least 16 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 32 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * In addition, if you do not pass a nonce in \p custom, + * the sum of the entropy length + * and the entropy nonce length must be: + * - at least 24 bytes for a 128-bit strength + * (maximum achievable strength when using AES-128); + * - at least 48 bytes for a 256-bit strength + * (maximum achievable strength when using AES-256). + * + * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. + * After a failed call to mbedtls_ctr_drbg_seed(), + * you must call mbedtls_ctr_drbg_free(). + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a buffer size + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add() + * or mbedtls_ctr_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus: + * - When using AES-256 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled, + * which is the default), + * \p len must be at least 32 (in bytes) + * to achieve a 256-bit strength. + * - When using AES-128 + * (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled) + * \p len must be at least 16 (in bytes) + * to achieve a 128-bit strength. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the amount of entropy grabbed + * as a nonce for the initial seeding. + * + * Call this function before calling mbedtls_ctr_drbg_seed() to read + * a nonce from the entropy source during the initial seeding. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab for the nonce, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * and at most the maximum length accepted by the + * entropy function that is set in the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is + * more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED + * if the initial seeding has already taken place. + */ +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be \c NULL. + * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/debug.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/debug.h new file mode 100644 index 00000000..0aed5961 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/debug.h @@ -0,0 +1,311 @@ +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \ + mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \ + MBEDTLS_DEBUG_STRIP_PARENS args ) + +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \ + mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret ) + +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \ + mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len ) + +#if defined(MBEDTLS_BIGNUM_C) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \ + mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_ECP_C) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \ + mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X ) +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \ + mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt ) +#else +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#endif /* MBEDTLS_X509_REMOVE_INFO */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_ECDH_C) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \ + mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr ) +#endif + +#else /* MBEDTLS_DEBUG_C */ + +#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 ) +#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 ) + +#endif /* MBEDTLS_DEBUG_C */ + +/** + * \def MBEDTLS_PRINTF_ATTRIBUTE + * + * Mark a function as having printf attributes, and thus enable checking + * via -wFormat and other flags. This does nothing on builds with compilers + * that do not support the format attribute + * + * Module: library/debug.c + * Caller: + * + * This module provides debugging functions. + */ +#if defined(__has_attribute) +#if __has_attribute(format) +#if defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__ (gnu_printf, string_index, first_to_check))) +#else /* defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 1 */ +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((format(printf, string_index, first_to_check))) +#endif +#else /* __has_attribute(format) */ +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) +#endif /* __has_attribute(format) */ +#else /* defined(__has_attribute) */ +#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) +#endif + +/** + * \def MBEDTLS_PRINTF_SIZET + * + * MBEDTLS_PRINTF_xxx: Due to issues with older window compilers + * and MinGW we need to define the printf specifier for size_t + * and long long per platform. + * + * Module: library/debug.c + * Caller: + * + * This module provides debugging functions. + */ +#if (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) + #include + #define MBEDTLS_PRINTF_SIZET PRIuPTR + #define MBEDTLS_PRINTF_LONGLONG "I64d" +#else /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ + #define MBEDTLS_PRINTF_SIZET "zu" + #define MBEDTLS_PRINTF_LONGLONG "lld" +#endif /* (defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Set the threshold error level to handle globally all debug output. + * Debug messages that have a level over the threshold value are + * discarded. + * (Default value: 0 = No debug ) + * + * \param threshold theshold level of messages to filter on. Messages at a + * higher level will be discarded. + * - Debug levels + * - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ +void mbedtls_debug_set_threshold( int threshold ); + +/** + * \brief Print a message to the debug output. This function is always used + * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl + * context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the message has occurred in + * \param line line number the message has occurred at + * \param format format specifier, in printf format + * \param ... variables used by the format specifier + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) MBEDTLS_PRINTF_ATTRIBUTE(5, 6); + +/** + * \brief Print the return value of a function to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text the name of the function that returned the error + * \param ret the return code value + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ); + +/** + * \brief Output a buffer of size len bytes to the debug output. This function + * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the buffer being dumped. Normally the + * variable or buffer name + * \param buf the buffer to be outputted + * \param len length of the buffer + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Print a MPI variable to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the MPI being output. Normally the + * variable name + * \param X the MPI variable + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ); +#endif + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Print an ECP point to the debug output. This function is always + * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the + * ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the ECP point being output. Normally the + * variable name + * \param X the ECP point + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Print a X.509 certificate structure to the debug output. This + * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro, + * which supplies the ssl context, file and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param text a name or label for the certificate being output + * \param crt X.509 certificate structure + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ); +#endif + +#if defined(MBEDTLS_ECDH_C) +typedef enum +{ + MBEDTLS_DEBUG_ECDH_Q, + MBEDTLS_DEBUG_ECDH_QP, + MBEDTLS_DEBUG_ECDH_Z, +} mbedtls_debug_ecdh_attr; + +/** + * \brief Print a field of the ECDH structure in the SSL context to the debug + * output. This function is always used through the + * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file + * and line number parameters. + * + * \param ssl SSL context + * \param level error level of the debug message + * \param file file the error has occurred in + * \param line line number the error has occurred in + * \param ecdh the ECDH context + * \param attr the identifier of the attribute being output + * + * \attention This function is intended for INTERNAL usage within the + * library only. + */ +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* debug.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/des.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/des.h new file mode 100644 index 00000000..be74cb11 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/des.h @@ -0,0 +1,363 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +/** The data input has an invalid length. */ +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t MBEDTLS_PRIVATE(sk)[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t MBEDTLS_PRIVATE(sk)[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_des_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/dhm.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/dhm.h new file mode 100644 index 00000000..32a957d5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/dhm.h @@ -0,0 +1,986 @@ +/** + * \file dhm.h + * + * \brief This file contains Diffie-Hellman-Merkle (DHM) key exchange + * definitions and functions. + * + * Diffie-Hellman-Merkle (DHM) key exchange is defined in + * RFC-2631: Diffie-Hellman Key Agreement Method and + * Public-Key Cryptography Standards (PKCS) #3: Diffie + * Hellman Key Agreement Standard. + * + * RFC-3526: More Modular Exponential (MODP) Diffie-Hellman groups for + * Internet Key Exchange (IKE) defines a number of standardized + * Diffie-Hellman groups for IKE. + * + * RFC-5114: Additional Diffie-Hellman Groups for Use with IETF + * Standards defines a number of standardized Diffie-Hellman + * groups that can be used. + * + * \warning The security of the DHM key exchange relies on the proper choice + * of prime modulus - optimally, it should be a safe prime. The usage + * of non-safe primes both decreases the difficulty of the underlying + * discrete logarithm problem and can lead to small subgroup attacks + * leaking private exponent bits when invalid public keys are used + * and not detected. This is especially relevant if the same DHM + * parameters are reused for multiple key exchanges as in static DHM, + * while the criticality of small-subgroup attacks is lower for + * ephemeral DHM. + * + * \warning For performance reasons, the code does neither perform primality + * nor safe primality tests, nor the expensive checks for invalid + * subgroups. Moreover, even if these were performed, non-standardized + * primes cannot be trusted because of the possibility of backdoors + * that can't be effectively checked for. + * + * \warning Diffie-Hellman-Merkle is therefore a security risk when not using + * standardized primes generated using a trustworthy ("nothing up + * my sleeve") method, such as the RFC 3526 / 7919 primes. In the TLS + * protocol, DH parameters need to be negotiated, so using the default + * primes systematically is not always an option. If possible, use + * Elliptic Curve Diffie-Hellman (ECDH), which has better performance, + * and for which the TLS protocol mandates the use of standard + * parameters. + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_DHM_H +#define MBEDTLS_DHM_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" +#include "mbedtls/bignum.h" + +/* + * DHM Error codes + */ +/** Bad input parameters. */ +#define MBEDTLS_ERR_DHM_BAD_INPUT_DATA -0x3080 +/** Reading of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_READ_PARAMS_FAILED -0x3100 +/** Making of the DHM parameters failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED -0x3180 +/** Reading of the public values failed. */ +#define MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED -0x3200 +/** Making of the public value failed. */ +#define MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED -0x3280 +/** Calculation of the DHM secret failed. */ +#define MBEDTLS_ERR_DHM_CALC_SECRET_FAILED -0x3300 +/** The ASN.1 data is not formatted correctly. */ +#define MBEDTLS_ERR_DHM_INVALID_FORMAT -0x3380 +/** Allocation of memory failed. */ +#define MBEDTLS_ERR_DHM_ALLOC_FAILED -0x3400 +/** Read or write of file failed. */ +#define MBEDTLS_ERR_DHM_FILE_IO_ERROR -0x3480 +/** Setting the modulus and generator failed. */ +#define MBEDTLS_ERR_DHM_SET_GROUP_FAILED -0x3580 + +/** Which parameter to access in mbedtls_dhm_get_value(). */ +typedef enum +{ + MBEDTLS_DHM_PARAM_P, /*!< The prime modulus. */ + MBEDTLS_DHM_PARAM_G, /*!< The generator. */ + MBEDTLS_DHM_PARAM_X, /*!< Our secret value. */ + MBEDTLS_DHM_PARAM_GX, /*!< Our public key = \c G^X mod \c P. */ + MBEDTLS_DHM_PARAM_GY, /*!< The public key of the peer = \c G^Y mod \c P. */ + MBEDTLS_DHM_PARAM_K, /*!< The shared secret = \c G^(XY) mod \c P. */ +} mbedtls_dhm_parameter; + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +/** + * \brief The DHM context structure. + */ +typedef struct mbedtls_dhm_context +{ + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The prime modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(G); /*!< The generator. */ + mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< Our secret value. */ + mbedtls_mpi MBEDTLS_PRIVATE(GX); /*!< Our public key = \c G^X mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(GY); /*!< The public key of the peer = \c G^Y mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(K); /*!< The shared secret = \c G^(XY) mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< The cached value = \c R^2 mod \c P. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(pX); /*!< The previous \c X. */ +} +mbedtls_dhm_context; + +#else /* MBEDTLS_DHM_ALT */ +#include "dhm_alt.h" +#endif /* MBEDTLS_DHM_ALT */ + +/** + * \brief This function initializes the DHM context. + * + * \param ctx The DHM context to initialize. + */ +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ); + +/** + * \brief This function parses the DHM parameters in a + * TLS ServerKeyExchange handshake message + * (DHM modulus, generator, and public key). + * + * \note In a TLS handshake, this is the how the client + * sets up its DHM context from the server's public + * DHM key material. + * + * \param ctx The DHM context to use. This must be initialized. + * \param p On input, *p must be the start of the input buffer. + * On output, *p is updated to point to the end of the data + * that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ); + +/** + * \brief This function generates a DHM key pair and exports its + * public part together with the DHM parameters in the format + * used in a TLS ServerKeyExchange handshake message. + * + * \note This function assumes that the DHM parameters \c ctx->P + * and \c ctx->G have already been properly set. For that, use + * mbedtls_dhm_set_group() below in conjunction with + * mbedtls_mpi_read_binary() and mbedtls_mpi_read_string(). + * + * \note In a TLS handshake, this is the how the server generates + * and exports its DHM key material. + * + * \param ctx The DHM context to use. This must be initialized + * and have the DHM parameters set. It may or may not + * already have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param olen The address at which to store the number of Bytes + * written on success. This must not be \c NULL. + * \param output The destination buffer. This must be a writable buffer of + * sufficient size to hold the reduced binary presentation of + * the modulus, the generator and the public key, each wrapped + * with a 2-byte length field. It is the responsibility of the + * caller to ensure that enough space is available. Refer to + * mbedtls_mpi_size() to computing the byte-size of an MPI. + * \param f_rng The RNG function. Must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function sets the prime modulus and generator. + * + * \note This function can be used to set \c ctx->P, \c ctx->G + * in preparation for mbedtls_dhm_make_params(). + * + * \param ctx The DHM context to configure. This must be initialized. + * \param P The MPI holding the DHM prime modulus. This must be + * an initialized MPI. + * \param G The MPI holding the DHM generator. This must be an + * initialized MPI. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ); + +/** + * \brief This function imports the raw public value of the peer. + * + * \note In a TLS handshake, this is the how the server imports + * the Client's public DHM key. + * + * \param ctx The DHM context to use. This must be initialized and have + * its DHM parameters set, e.g. via mbedtls_dhm_set_group(). + * It may or may not already have generated its own private key. + * \param input The input buffer containing the \c G^Y value of the peer. + * This must be a readable buffer of size \p ilen Bytes. + * \param ilen The size of the input buffer \p input in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function creates a DHM key pair and exports + * the raw public key in big-endian format. + * + * \note The destination buffer is always fully written + * so as to contain a big-endian representation of G^X mod P. + * If it is larger than \c ctx->len, it is padded accordingly + * with zero-bytes at the beginning. + * + * \param ctx The DHM context to use. This must be initialized and + * have the DHM parameters set. It may or may not already + * have imported the peer's public key. + * \param x_size The private key size in Bytes. + * \param output The destination buffer. This must be a writable buffer of + * size \p olen Bytes. + * \param olen The length of the destination buffer. This must be at least + * equal to `ctx->len` (the size of \c P). + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function derives and exports the shared secret + * \c (G^Y)^X mod \c P. + * + * \note If \p f_rng is not \c NULL, it is used to blind the input as + * a countermeasure against timing attacks. Blinding is used + * only if our private key \c X is re-used, and not used + * otherwise. We recommend always passing a non-NULL + * \p f_rng argument. + * + * \param ctx The DHM context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param output The buffer to write the generated shared key to. This + * must be a writable buffer of size \p output_size Bytes. + * \param output_size The size of the destination buffer. This must be at + * least the size of \c ctx->len (the size of \c P). + * \param olen On exit, holds the actual number of Bytes written. + * \param f_rng The RNG function. Must not be \c NULL. Used for + * blinding. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX error code on failure. + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function returns the size of the prime modulus in bits. + * + * \param ctx The DHM context to query. + * + * \return The size of the prime modulus in bits, + * i.e. the number n such that 2^(n-1) <= P < 2^n. + */ +size_t mbedtls_dhm_get_bitlen( const mbedtls_dhm_context *ctx ); + +/** + * \brief This function returns the size of the prime modulus in bytes. + * + * \param ctx The DHM context to query. + * + * \return The size of the prime modulus in bytes, + * i.e. the number n such that 2^(8*(n-1)) <= P < 2^(8*n). + */ +size_t mbedtls_dhm_get_len( const mbedtls_dhm_context *ctx ); + +/** + * \brief This function copies a parameter of a DHM key. + * + * \param ctx The DHM context to query. + * \param param The parameter to copy. + * \param dest The MPI object to copy the value into. It must be + * initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p field is invalid. + * \return An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails. + */ +int mbedtls_dhm_get_value( const mbedtls_dhm_context *ctx, + mbedtls_dhm_parameter param, + mbedtls_mpi *dest ); + +/** + * \brief This function frees and clears the components + * of a DHM context. + * + * \param ctx The DHM context to free and clear. This may be \c NULL, + * in which case this function is a no-op. If it is not \c NULL, + * it must point to an initialized DHM context. + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ); + +#if defined(MBEDTLS_ASN1_PARSE_C) +/** + * \brief This function parses DHM parameters in PEM or DER format. + * + * \param dhm The DHM context to import the DHM parameters into. + * This must be initialized. + * \param dhmin The input buffer. This must be a readable buffer of + * length \p dhminlen Bytes. + * \param dhminlen The size of the input buffer \p dhmin, including the + * terminating \c NULL Byte for PEM data. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX error + * code on failure. + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function loads and parses DHM parameters from a file. + * + * \param dhm The DHM context to load the parameters to. + * This must be initialized. + * \param path The filename to read the DHM parameters from. + * This must not be \c NULL. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_DHM_XXX or \c MBEDTLS_ERR_PEM_XXX + * error code on failure. + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The DMH checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_dhm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ +#ifdef __cplusplus +} +#endif + +/** + * RFC 3526, RFC 5114 and RFC 7919 standardize a number of + * Diffie-Hellman groups, some of which are included here + * for use within the SSL/TLS module and the user's convenience + * when configuring the Diffie-Hellman parameters by hand + * through \c mbedtls_ssl_conf_dh_param. + * + * The following lists the source of the above groups in the standards: + * - RFC 5114 section 2.2: 2048-bit MODP Group with 224-bit Prime Order Subgroup + * - RFC 3526 section 3: 2048-bit MODP Group + * - RFC 3526 section 4: 3072-bit MODP Group + * - RFC 3526 section 5: 4096-bit MODP Group + * - RFC 7919 section A.1: ffdhe2048 + * - RFC 7919 section A.2: ffdhe3072 + * - RFC 7919 section A.3: ffdhe4096 + * - RFC 7919 section A.4: ffdhe6144 + * - RFC 7919 section A.5: ffdhe8192 + * + * The constants with suffix "_p" denote the chosen prime moduli, while + * the constants with suffix "_g" denote the chosen generator + * of the associated prime field. + * + * The constants further suffixed with "_bin" are provided in binary format, + * while all other constants represent null-terminated strings holding the + * hexadecimal presentation of the respective numbers. + * + * The primes from RFC 3526 and RFC 7919 have been generating by the following + * trust-worthy procedure: + * - Fix N in { 2048, 3072, 4096, 6144, 8192 } and consider the N-bit number + * the first and last 64 bits are all 1, and the remaining N - 128 bits of + * which are 0x7ff...ff. + * - Add the smallest multiple of the first N - 129 bits of the binary expansion + * of pi (for RFC 5236) or e (for RFC 7919) to this intermediate bit-string + * such that the resulting integer is a safe-prime. + * - The result is the respective RFC 3526 / 7919 prime, and the corresponding + * generator is always chosen to be 2 (which is a square for these prime, + * hence the corresponding subgroup has order (p-1)/2 and avoids leaking a + * bit in the private exponent). + * + */ + +/* + * Trustworthy DHM parameters in binary form + */ + +#define MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34, \ + 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, \ + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, \ + 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, \ + 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, \ + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, \ + 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, \ + 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, \ + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, \ + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, \ + 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, \ + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, \ + 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, \ + 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, \ + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, \ + 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, \ + 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, \ + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, \ + 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB, \ + 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, \ + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, \ + 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C, \ + 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B, \ + 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, \ + 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F, \ + 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9, \ + 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, \ + 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5, \ + 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10, \ + 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, \ + 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33, \ + 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64, \ + 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, \ + 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D, \ + 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7, \ + 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, \ + 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D, \ + 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B, \ + 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, \ + 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64, \ + 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C, \ + 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, \ + 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2, \ + 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31, \ + 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, \ + 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01, \ + 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7, \ + 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, \ + 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C, \ + 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA, \ + 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, \ + 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9, \ + 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6, \ + 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, \ + 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2, \ + 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED, \ + 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, \ + 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C, \ + 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9, \ + 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, \ + 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F, \ + 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC3526_MODP_4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x28, 0x5C, 0x97, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, } + +#define MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0xC6, 0x2E, 0x37, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x65, 0x5F, 0x6A, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xD0, 0xE4, 0x0E, 0x65, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN { 0x02 } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN { \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xAD, 0xF8, 0x54, 0x58, 0xA2, 0xBB, 0x4A, 0x9A, \ + 0xAF, 0xDC, 0x56, 0x20, 0x27, 0x3D, 0x3C, 0xF1, \ + 0xD8, 0xB9, 0xC5, 0x83, 0xCE, 0x2D, 0x36, 0x95, \ + 0xA9, 0xE1, 0x36, 0x41, 0x14, 0x64, 0x33, 0xFB, \ + 0xCC, 0x93, 0x9D, 0xCE, 0x24, 0x9B, 0x3E, 0xF9, \ + 0x7D, 0x2F, 0xE3, 0x63, 0x63, 0x0C, 0x75, 0xD8, \ + 0xF6, 0x81, 0xB2, 0x02, 0xAE, 0xC4, 0x61, 0x7A, \ + 0xD3, 0xDF, 0x1E, 0xD5, 0xD5, 0xFD, 0x65, 0x61, \ + 0x24, 0x33, 0xF5, 0x1F, 0x5F, 0x06, 0x6E, 0xD0, \ + 0x85, 0x63, 0x65, 0x55, 0x3D, 0xED, 0x1A, 0xF3, \ + 0xB5, 0x57, 0x13, 0x5E, 0x7F, 0x57, 0xC9, 0x35, \ + 0x98, 0x4F, 0x0C, 0x70, 0xE0, 0xE6, 0x8B, 0x77, \ + 0xE2, 0xA6, 0x89, 0xDA, 0xF3, 0xEF, 0xE8, 0x72, \ + 0x1D, 0xF1, 0x58, 0xA1, 0x36, 0xAD, 0xE7, 0x35, \ + 0x30, 0xAC, 0xCA, 0x4F, 0x48, 0x3A, 0x79, 0x7A, \ + 0xBC, 0x0A, 0xB1, 0x82, 0xB3, 0x24, 0xFB, 0x61, \ + 0xD1, 0x08, 0xA9, 0x4B, 0xB2, 0xC8, 0xE3, 0xFB, \ + 0xB9, 0x6A, 0xDA, 0xB7, 0x60, 0xD7, 0xF4, 0x68, \ + 0x1D, 0x4F, 0x42, 0xA3, 0xDE, 0x39, 0x4D, 0xF4, \ + 0xAE, 0x56, 0xED, 0xE7, 0x63, 0x72, 0xBB, 0x19, \ + 0x0B, 0x07, 0xA7, 0xC8, 0xEE, 0x0A, 0x6D, 0x70, \ + 0x9E, 0x02, 0xFC, 0xE1, 0xCD, 0xF7, 0xE2, 0xEC, \ + 0xC0, 0x34, 0x04, 0xCD, 0x28, 0x34, 0x2F, 0x61, \ + 0x91, 0x72, 0xFE, 0x9C, 0xE9, 0x85, 0x83, 0xFF, \ + 0x8E, 0x4F, 0x12, 0x32, 0xEE, 0xF2, 0x81, 0x83, \ + 0xC3, 0xFE, 0x3B, 0x1B, 0x4C, 0x6F, 0xAD, 0x73, \ + 0x3B, 0xB5, 0xFC, 0xBC, 0x2E, 0xC2, 0x20, 0x05, \ + 0xC5, 0x8E, 0xF1, 0x83, 0x7D, 0x16, 0x83, 0xB2, \ + 0xC6, 0xF3, 0x4A, 0x26, 0xC1, 0xB2, 0xEF, 0xFA, \ + 0x88, 0x6B, 0x42, 0x38, 0x61, 0x1F, 0xCF, 0xDC, \ + 0xDE, 0x35, 0x5B, 0x3B, 0x65, 0x19, 0x03, 0x5B, \ + 0xBC, 0x34, 0xF4, 0xDE, 0xF9, 0x9C, 0x02, 0x38, \ + 0x61, 0xB4, 0x6F, 0xC9, 0xD6, 0xE6, 0xC9, 0x07, \ + 0x7A, 0xD9, 0x1D, 0x26, 0x91, 0xF7, 0xF7, 0xEE, \ + 0x59, 0x8C, 0xB0, 0xFA, 0xC1, 0x86, 0xD9, 0x1C, \ + 0xAE, 0xFE, 0x13, 0x09, 0x85, 0x13, 0x92, 0x70, \ + 0xB4, 0x13, 0x0C, 0x93, 0xBC, 0x43, 0x79, 0x44, \ + 0xF4, 0xFD, 0x44, 0x52, 0xE2, 0xD7, 0x4D, 0xD3, \ + 0x64, 0xF2, 0xE2, 0x1E, 0x71, 0xF5, 0x4B, 0xFF, \ + 0x5C, 0xAE, 0x82, 0xAB, 0x9C, 0x9D, 0xF6, 0x9E, \ + 0xE8, 0x6D, 0x2B, 0xC5, 0x22, 0x36, 0x3A, 0x0D, \ + 0xAB, 0xC5, 0x21, 0x97, 0x9B, 0x0D, 0xEA, 0xDA, \ + 0x1D, 0xBF, 0x9A, 0x42, 0xD5, 0xC4, 0x48, 0x4E, \ + 0x0A, 0xBC, 0xD0, 0x6B, 0xFA, 0x53, 0xDD, 0xEF, \ + 0x3C, 0x1B, 0x20, 0xEE, 0x3F, 0xD5, 0x9D, 0x7C, \ + 0x25, 0xE4, 0x1D, 0x2B, 0x66, 0x9E, 0x1E, 0xF1, \ + 0x6E, 0x6F, 0x52, 0xC3, 0x16, 0x4D, 0xF4, 0xFB, \ + 0x79, 0x30, 0xE9, 0xE4, 0xE5, 0x88, 0x57, 0xB6, \ + 0xAC, 0x7D, 0x5F, 0x42, 0xD6, 0x9F, 0x6D, 0x18, \ + 0x77, 0x63, 0xCF, 0x1D, 0x55, 0x03, 0x40, 0x04, \ + 0x87, 0xF5, 0x5B, 0xA5, 0x7E, 0x31, 0xCC, 0x7A, \ + 0x71, 0x35, 0xC8, 0x86, 0xEF, 0xB4, 0x31, 0x8A, \ + 0xED, 0x6A, 0x1E, 0x01, 0x2D, 0x9E, 0x68, 0x32, \ + 0xA9, 0x07, 0x60, 0x0A, 0x91, 0x81, 0x30, 0xC4, \ + 0x6D, 0xC7, 0x78, 0xF9, 0x71, 0xAD, 0x00, 0x38, \ + 0x09, 0x29, 0x99, 0xA3, 0x33, 0xCB, 0x8B, 0x7A, \ + 0x1A, 0x1D, 0xB9, 0x3D, 0x71, 0x40, 0x00, 0x3C, \ + 0x2A, 0x4E, 0xCE, 0xA9, 0xF9, 0x8D, 0x0A, 0xCC, \ + 0x0A, 0x82, 0x91, 0xCD, 0xCE, 0xC9, 0x7D, 0xCF, \ + 0x8E, 0xC9, 0xB5, 0x5A, 0x7F, 0x88, 0xA4, 0x6B, \ + 0x4D, 0xB5, 0xA8, 0x51, 0xF4, 0x41, 0x82, 0xE1, \ + 0xC6, 0x8A, 0x00, 0x7E, 0x5E, 0x0D, 0xD9, 0x02, \ + 0x0B, 0xFD, 0x64, 0xB6, 0x45, 0x03, 0x6C, 0x7A, \ + 0x4E, 0x67, 0x7D, 0x2C, 0x38, 0x53, 0x2A, 0x3A, \ + 0x23, 0xBA, 0x44, 0x42, 0xCA, 0xF5, 0x3E, 0xA6, \ + 0x3B, 0xB4, 0x54, 0x32, 0x9B, 0x76, 0x24, 0xC8, \ + 0x91, 0x7B, 0xDD, 0x64, 0xB1, 0xC0, 0xFD, 0x4C, \ + 0xB3, 0x8E, 0x8C, 0x33, 0x4C, 0x70, 0x1C, 0x3A, \ + 0xCD, 0xAD, 0x06, 0x57, 0xFC, 0xCF, 0xEC, 0x71, \ + 0x9B, 0x1F, 0x5C, 0x3E, 0x4E, 0x46, 0x04, 0x1F, \ + 0x38, 0x81, 0x47, 0xFB, 0x4C, 0xFD, 0xB4, 0x77, \ + 0xA5, 0x24, 0x71, 0xF7, 0xA9, 0xA9, 0x69, 0x10, \ + 0xB8, 0x55, 0x32, 0x2E, 0xDB, 0x63, 0x40, 0xD8, \ + 0xA0, 0x0E, 0xF0, 0x92, 0x35, 0x05, 0x11, 0xE3, \ + 0x0A, 0xBE, 0xC1, 0xFF, 0xF9, 0xE3, 0xA2, 0x6E, \ + 0x7F, 0xB2, 0x9F, 0x8C, 0x18, 0x30, 0x23, 0xC3, \ + 0x58, 0x7E, 0x38, 0xDA, 0x00, 0x77, 0xD9, 0xB4, \ + 0x76, 0x3E, 0x4E, 0x4B, 0x94, 0xB2, 0xBB, 0xC1, \ + 0x94, 0xC6, 0x65, 0x1E, 0x77, 0xCA, 0xF9, 0x92, \ + 0xEE, 0xAA, 0xC0, 0x23, 0x2A, 0x28, 0x1B, 0xF6, \ + 0xB3, 0xA7, 0x39, 0xC1, 0x22, 0x61, 0x16, 0x82, \ + 0x0A, 0xE8, 0xDB, 0x58, 0x47, 0xA6, 0x7C, 0xBE, \ + 0xF9, 0xC9, 0x09, 0x1B, 0x46, 0x2D, 0x53, 0x8C, \ + 0xD7, 0x2B, 0x03, 0x74, 0x6A, 0xE7, 0x7F, 0x5E, \ + 0x62, 0x29, 0x2C, 0x31, 0x15, 0x62, 0xA8, 0x46, \ + 0x50, 0x5D, 0xC8, 0x2D, 0xB8, 0x54, 0x33, 0x8A, \ + 0xE4, 0x9F, 0x52, 0x35, 0xC9, 0x5B, 0x91, 0x17, \ + 0x8C, 0xCF, 0x2D, 0xD5, 0xCA, 0xCE, 0xF4, 0x03, \ + 0xEC, 0x9D, 0x18, 0x10, 0xC6, 0x27, 0x2B, 0x04, \ + 0x5B, 0x3B, 0x71, 0xF9, 0xDC, 0x6B, 0x80, 0xD6, \ + 0x3F, 0xDD, 0x4A, 0x8E, 0x9A, 0xDB, 0x1E, 0x69, \ + 0x62, 0xA6, 0x95, 0x26, 0xD4, 0x31, 0x61, 0xC1, \ + 0xA4, 0x1D, 0x57, 0x0D, 0x79, 0x38, 0xDA, 0xD4, \ + 0xA4, 0x0E, 0x32, 0x9C, 0xCF, 0xF4, 0x6A, 0xAA, \ + 0x36, 0xAD, 0x00, 0x4C, 0xF6, 0x00, 0xC8, 0x38, \ + 0x1E, 0x42, 0x5A, 0x31, 0xD9, 0x51, 0xAE, 0x64, \ + 0xFD, 0xB2, 0x3F, 0xCE, 0xC9, 0x50, 0x9D, 0x43, \ + 0x68, 0x7F, 0xEB, 0x69, 0xED, 0xD1, 0xCC, 0x5E, \ + 0x0B, 0x8C, 0xC3, 0xBD, 0xF6, 0x4B, 0x10, 0xEF, \ + 0x86, 0xB6, 0x31, 0x42, 0xA3, 0xAB, 0x88, 0x29, \ + 0x55, 0x5B, 0x2F, 0x74, 0x7C, 0x93, 0x26, 0x65, \ + 0xCB, 0x2C, 0x0F, 0x1C, 0xC0, 0x1B, 0xD7, 0x02, \ + 0x29, 0x38, 0x88, 0x39, 0xD2, 0xAF, 0x05, 0xE4, \ + 0x54, 0x50, 0x4A, 0xC7, 0x8B, 0x75, 0x82, 0x82, \ + 0x28, 0x46, 0xC0, 0xBA, 0x35, 0xC3, 0x5F, 0x5C, \ + 0x59, 0x16, 0x0C, 0xC0, 0x46, 0xFD, 0x82, 0x51, \ + 0x54, 0x1F, 0xC6, 0x8C, 0x9C, 0x86, 0xB0, 0x22, \ + 0xBB, 0x70, 0x99, 0x87, 0x6A, 0x46, 0x0E, 0x74, \ + 0x51, 0xA8, 0xA9, 0x31, 0x09, 0x70, 0x3F, 0xEE, \ + 0x1C, 0x21, 0x7E, 0x6C, 0x38, 0x26, 0xE5, 0x2C, \ + 0x51, 0xAA, 0x69, 0x1E, 0x0E, 0x42, 0x3C, 0xFC, \ + 0x99, 0xE9, 0xE3, 0x16, 0x50, 0xC1, 0x21, 0x7B, \ + 0x62, 0x48, 0x16, 0xCD, 0xAD, 0x9A, 0x95, 0xF9, \ + 0xD5, 0xB8, 0x01, 0x94, 0x88, 0xD9, 0xC0, 0xA0, \ + 0xA1, 0xFE, 0x30, 0x75, 0xA5, 0x77, 0xE2, 0x31, \ + 0x83, 0xF8, 0x1D, 0x4A, 0x3F, 0x2F, 0xA4, 0x57, \ + 0x1E, 0xFC, 0x8C, 0xE0, 0xBA, 0x8A, 0x4F, 0xE8, \ + 0xB6, 0x85, 0x5D, 0xFE, 0x72, 0xB0, 0xA6, 0x6E, \ + 0xDE, 0xD2, 0xFB, 0xAB, 0xFB, 0xE5, 0x8A, 0x30, \ + 0xFA, 0xFA, 0xBE, 0x1C, 0x5D, 0x71, 0xA8, 0x7E, \ + 0x2F, 0x74, 0x1E, 0xF8, 0xC1, 0xFE, 0x86, 0xFE, \ + 0xA6, 0xBB, 0xFD, 0xE5, 0x30, 0x67, 0x7F, 0x0D, \ + 0x97, 0xD1, 0x1D, 0x49, 0xF7, 0xA8, 0x44, 0x3D, \ + 0x08, 0x22, 0xE5, 0x06, 0xA9, 0xF4, 0x61, 0x4E, \ + 0x01, 0x1E, 0x2A, 0x94, 0x83, 0x8F, 0xF8, 0x8C, \ + 0xD6, 0x8C, 0x8B, 0xB7, 0xC5, 0xC6, 0x42, 0x4C, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } + +#define MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN { 0x02 } + +#endif /* dhm.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecdh.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecdh.h new file mode 100644 index 00000000..7fa7440a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecdh.h @@ -0,0 +1,458 @@ +/** + * \file ecdh.h + * + * \brief This file contains ECDH definitions and functions. + * + * The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous + * key agreement protocol allowing two parties to establish a shared + * secret over an insecure channel. Each party must have an + * elliptic-curve public–private key pair. + * + * For more information, see NIST SP 800-56A Rev. 2: Recommendation for + * Pair-Wise Key Establishment Schemes Using Discrete Logarithm + * Cryptography. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ecp.h" + +/* + * Mbed TLS supports two formats for ECDH contexts (#mbedtls_ecdh_context + * defined in `ecdh.h`). For most applications, the choice of format makes + * no difference, since all library functions can work with either format, + * except that the new format is incompatible with MBEDTLS_ECP_RESTARTABLE. + + * The new format used when this option is disabled is smaller + * (56 bytes on a 32-bit platform). In future versions of the library, it + * will support alternative implementations of ECDH operations. + * The new format is incompatible with applications that access + * context fields directly and with restartable ECP operations. + */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define MBEDTLS_ECDH_LEGACY_CONTEXT +#else +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#endif + +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) +#undef MBEDTLS_ECDH_LEGACY_CONTEXT +#include "everest/everest.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Defines the source of the imported EC key. + */ +typedef enum +{ + MBEDTLS_ECDH_OURS, /**< Our key. */ + MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */ +} mbedtls_ecdh_side; + +#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +/** + * Defines the ECDH implementation used. + * + * Later versions of the library may add new variants, therefore users should + * not make any assumptions about them. + */ +typedef enum +{ + MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */ + MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */ +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */ +#endif +} mbedtls_ecdh_variant; + +/** + * The context used by the default ECDH implementation. + * + * Later versions might change the structure of this context, therefore users + * should not make any assumptions about the structure of + * mbedtls_ecdh_context_mbed. + */ +typedef struct mbedtls_ecdh_context_mbed +{ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ + mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ +#endif +} mbedtls_ecdh_context_mbed; +#endif + +/** + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + * \brief The ECDH context structure. + */ +typedef struct mbedtls_ecdh_context +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< The elliptic curve used. */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< The private key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< The public key. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Qp); /*!< The value of the public key of the peer. */ + mbedtls_mpi MBEDTLS_PRIVATE(z); /*!< The shared secret. */ + int MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Vi); /*!< The blinding value. */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Vf); /*!< The unblinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(_d); /*!< The previous \p d. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + int MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. */ + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(rs); /*!< The restart context for EC computations. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#else + uint8_t MBEDTLS_PRIVATE(point_format); /*!< The format of point export in TLS messages + as defined in RFC 4492. */ + mbedtls_ecp_group_id MBEDTLS_PRIVATE(grp_id);/*!< The elliptic curve used. */ + mbedtls_ecdh_variant MBEDTLS_PRIVATE(var); /*!< The ECDH implementation/structure used. */ + union + { + mbedtls_ecdh_context_mbed MBEDTLS_PRIVATE(mbed_ecdh); +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + mbedtls_ecdh_context_everest MBEDTLS_PRIVATE(everest_ecdh); +#endif + } MBEDTLS_PRIVATE(ctx); /*!< Implementation-specific context. The + context in use is specified by the \c var + field. */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + uint8_t MBEDTLS_PRIVATE(restart_enabled); /*!< The flag for restartable mode. Functions of + an alternative implementation not supporting + restartable mode must return + MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error + if this flag is set. */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */ +} +mbedtls_ecdh_context; + +/** + * \brief Check whether a given group can be used for ECDH. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function generates an ECDH keypair on an elliptic + * curve. + * + * This function performs the first of two core computations + * implemented during the ECDH key exchange. The second core + * computation is performed by mbedtls_ecdh_compute_shared(). + * + * \see ecp.h + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param d The destination MPI (private key). + * This must be initialized. + * \param Q The destination point (public key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the shared secret. + * + * This function performs the second of two core computations + * implemented during the ECDH key exchange. The first core + * computation is performed by mbedtls_ecdh_gen_public(). + * + * \see ecp.h + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \param grp The ECP group to use. This must be initialized and have + * domain parameters loaded, for example through + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group(). + * \param z The destination MPI (shared secret). + * This must be initialized. + * \param Q The public key from another party. + * This must be initialized. + * \param d Our secret exponent (private key). + * This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't need a + * context argument. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function initializes an ECDH context. + * + * \param ctx The ECDH context to initialize. This must not be \c NULL. + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function sets up the ECDH context with the information + * given. + * + * This function should be called after mbedtls_ecdh_init() but + * before mbedtls_ecdh_make_params(). There is no need to call + * this function before mbedtls_ecdh_read_params(). + * + * This is the first function used by a TLS server for ECDHE + * ciphersuites. + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param grp_id The group id of the group to set up the context for. + * + * \return \c 0 on success. + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function frees a context. + * + * \param ctx The context to free. This may be \c NULL, in which + * case this function does nothing. If it is not \c NULL, + * it must point to an initialized ECDH context. + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); + +/** + * \brief This function generates an EC key pair and exports its + * in the format used in a TLS ServerKeyExchange handshake + * message. + * + * This is the second function used by a TLS server for ECDHE + * ciphersuites. (It is called after mbedtls_ecdh_setup().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param olen The address at which to store the number of Bytes written. + * \param buf The destination buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses the ECDHE parameters in a + * TLS ServerKeyExchange handshake message. + * + * \note In a TLS handshake, this is the how the client + * sets up its ECDHE context from the server's public + * ECDHE key material. + * + * \see ecp.h + * + * \param ctx The ECDHE context to use. This must be initialized. + * \param buf On input, \c *buf must be the start of the input buffer. + * On output, \c *buf is updated to point to the end of the + * data that has been read. On success, this is the first byte + * past the end of the ServerKeyExchange parameters. + * On error, this is the point at which an error has been + * detected, which is usually not useful except to debug + * failures. + * \param end The end of the input buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ); + +/** + * \brief This function sets up an ECDH context from an EC key. + * + * It is used by clients and servers in place of the + * ServerKeyEchange for static ECDH, and imports ECDH + * parameters from the EC key information of a certificate. + * + * \see ecp.h + * + * \param ctx The ECDH context to set up. This must be initialized. + * \param key The EC key to use. This must be initialized. + * \param side Defines the source of the key. Possible values are: + * - #MBEDTLS_ECDH_OURS: The key is ours. + * - #MBEDTLS_ECDH_THEIRS: The key is that of the peer. + * + * \return \c 0 on success. + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + * + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ); + +/** + * \brief This function generates a public key and exports it + * as a TLS ClientKeyExchange payload. + * + * This is the second function used by a TLS client for ECDH(E) + * ciphersuites. + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, the latter usually by + * mbedtls_ecdh_read_params(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The destination buffer. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The size of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL in case \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function parses and processes the ECDHE payload of a + * TLS ClientKeyExchange message. + * + * This is the third function used by a TLS server for ECDH(E) + * ciphersuites. (It is called after mbedtls_ecdh_setup() and + * mbedtls_ecdh_make_params().) + * + * \see ecp.h + * + * \param ctx The ECDH context to use. This must be initialized + * and bound to a group, for example via mbedtls_ecdh_setup(). + * \param buf The pointer to the ClientKeyExchange payload. This must + * be a readable buffer of length \p blen Bytes. + * \param blen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ); + +/** + * \brief This function derives and exports the shared secret. + * + * This is the last function used by both TLS client + * and servers. + * + * \note If \p f_rng is not NULL, it is used to implement + * countermeasures against side-channel attacks. + * For more information, see mbedtls_ecp_mul(). + * + * \see ecp.h + + * \param ctx The ECDH context to use. This must be initialized + * and have its own private key generated and the peer's + * public key imported. + * \param olen The address at which to store the total number of + * Bytes written on success. This must not be \c NULL. + * \param buf The buffer to write the generated shared key to. This + * must be a writable buffer of size \p blen Bytes. + * \param blen The length of the destination buffer \p buf in Bytes. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context. This may be \c NULL if \p f_rng + * doesn't need a context argument. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief This function enables restartable EC computations for this + * context. (Default: disabled.) + * + * \see \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx The ECDH context to use. This must be initialized. + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdh.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecdsa.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecdsa.h new file mode 100644 index 00000000..71b73eee --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecdsa.h @@ -0,0 +1,506 @@ +/** + * \file ecdsa.h + * + * \brief This file contains ECDSA definitions and functions. + * + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +/** + * \brief Maximum ECDSA signature size for a given curve bit size + * + * \param bits Curve size in bits + * \return Maximum signature size in bytes + * + * \note This macro returns a compile-time constant if its argument + * is one. It may evaluate its argument multiple times. + */ +/* + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * For each of r and s, the value (V) may include an extra initial "0" bit. + */ +#define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \ + ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \ + /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \ + /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) ) + +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The ECDSA context structure. + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx MBEDTLS_PRIVATE(ecp); /*!< base context for ECP restart and + shared administrative info */ + mbedtls_ecdsa_restart_ver_ctx *MBEDTLS_PRIVATE(ver); /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *MBEDTLS_PRIVATE(sig); /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *MBEDTLS_PRIVATE(det); /*!< ecdsa_sign_det() sub-context */ +#endif +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function checks whether a given group can be used + * for ECDSA. + * + * \param gid The ECP group ID to check. + * + * \return \c 1 if the group can be used, \c 0 otherwise + */ +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ); + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version implemented in + * mbedtls_ecdsa_sign_det_ext() is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized. + * \param buf The content to be signed. This is usually the hash of + * the original data to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param buf The hashed content that was signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param Q The public key to use for verification. This must be + * initialized and setup. + * \param r The first integer of the signature. + * This must be initialized. + * \param s The second integer of the signature. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, + const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param sig_size The size of the \p sig buffer in bytes. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is used only for blinding and may be set to \c NULL, but + * doing so is DEPRECATED. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, in a restartable way. + * + * \see \c mbedtls_ecdsa_write_signature() + * + * \note This function is like \c mbedtls_ecdsa_write_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and private key bound to it, for example + * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair(). + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash to be signed. This must be a readable + * buffer of length \p blen Bytes. + * \param hlen The length of the hash \p hash in Bytes. + * \param sig The buffer to which to write the signature. This must be a + * writable buffer of length at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * \param sig_size The size of the \p sig buffer in bytes. + * \param slen The address at which to store the actual length of + * the signature written. Must not be \c NULL. + * \param f_rng The RNG function. This must not be \c NULL if + * #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise, + * it is unused and may be set to \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng is \c NULL or doesn't use a context. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function reads and verifies an ECDSA signature, + * in a restartable way. + * + * \see \c mbedtls_ecdsa_read_signature() + * + * \note This function is like \c mbedtls_ecdsa_read_signature() + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx The ECDSA context to use. This must be initialized + * and have a group and public key bound to it. + * \param hash The message hash that was signed. This must be a readable + * buffer of length \p size Bytes. + * \param hlen The size of the hash \p hash. + * \param sig The signature to read and verify. This must be a readable + * buffer of length \p slen Bytes. + * \param slen The size of \p sig in Bytes. + * \param rs_ctx The restart context to use. This may be \c NULL to disable + * restarting. If it is not \c NULL, it must point to an + * initialized restart context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * This must be initialized. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets up an ECDSA context from an EC key pair. + * + * \see ecp.h + * + * \param ctx The ECDSA context to setup. This must be initialized. + * \param key The EC key to use. This must be initialized and hold + * a private-public key pair or a public key. In the former + * case, the ECDSA context may be used for signature creation + * and verification after this call. In the latter case, it + * may be used for signature verification. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, + const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must be initialized. + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecjpake.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecjpake.h new file mode 100644 index 00000000..a73f6249 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecjpake.h @@ -0,0 +1,287 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ECJPAKE_H +#define MBEDTLS_ECJPAKE_H +#include "mbedtls/private_access.h" + +/* + * J-PAKE is a password-authenticated key exchange that allows deriving a + * strong shared secret from a (potentially low entropy) pre-shared + * passphrase, with forward secrecy and mutual authentication. + * https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling + * + * This file implements the Elliptic Curve variant of J-PAKE, + * as defined in Chapter 7.4 of the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + * + * As the J-PAKE algorithm is inherently symmetric, so is our API. + * Each party needs to send its first round message, in any order, to the + * other party, then each sends its second round message, in any order. + * The payloads are serialized in a way suitable for use in TLS, but could + * also be use outside TLS. + */ +#include "mbedtls/build_info.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Roles in the EC J-PAKE exchange + */ +typedef enum { + MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */ + MBEDTLS_ECJPAKE_SERVER, /**< Server */ +} mbedtls_ecjpake_role; + +#if !defined(MBEDTLS_ECJPAKE_ALT) +/** + * EC J-PAKE context structure. + * + * J-PAKE is a symmetric protocol, except for the identifiers used in + * Zero-Knowledge Proofs, and the serialization of the second message + * (KeyExchange) as defined by the Thread spec. + * + * In order to benefit from this symmetry, we choose a different naming + * convetion from the Thread v1.0 spec. Correspondance is indicated in the + * description as a pair C: client name, S: server name + */ +typedef struct mbedtls_ecjpake_context +{ + const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); /**< Hash to use */ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /**< Elliptic curve */ + mbedtls_ecjpake_role MBEDTLS_PRIVATE(role); /**< Are we client or server? */ + int MBEDTLS_PRIVATE(point_format); /**< Format for point export */ + + mbedtls_ecp_point MBEDTLS_PRIVATE(Xm1); /**< My public key 1 C: X1, S: X3 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xm2); /**< My public key 2 C: X2, S: X4 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp1); /**< Peer public key 1 C: X3, S: X1 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp2); /**< Peer public key 2 C: X4, S: X2 */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Xp); /**< Peer public key C: Xs, S: Xc */ + + mbedtls_mpi MBEDTLS_PRIVATE(xm1); /**< My private key 1 C: x1, S: x3 */ + mbedtls_mpi MBEDTLS_PRIVATE(xm2); /**< My private key 2 C: x2, S: x4 */ + + mbedtls_mpi MBEDTLS_PRIVATE(s); /**< Pre-shared secret (passphrase) */ +} mbedtls_ecjpake_context; + +#else /* MBEDTLS_ECJPAKE_ALT */ +#include "ecjpake_alt.h" +#endif /* MBEDTLS_ECJPAKE_ALT */ + +/** + * \brief Initialize an ECJPAKE context. + * + * \param ctx The ECJPAKE context to initialize. + * This must not be \c NULL. + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ); + +/** + * \brief Set up an ECJPAKE context for use. + * + * \note Currently the only values for hash/curve allowed by the + * standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1. + * + * \param ctx The ECJPAKE context to set up. This must be initialized. + * \param role The role of the caller. This must be either + * #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER. + * \param hash The identifier of the hash function to use, + * for example #MBEDTLS_MD_SHA256. + * \param curve The identifier of the elliptic curve to use, + * for example #MBEDTLS_ECP_DP_SECP256R1. + * \param secret The pre-shared secret (passphrase). This must be + * a readable buffer of length \p len Bytes. It need + * only be valid for the duration of this call. + * \param len The length of the pre-shared secret \p secret. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ); + +/** + * \brief Set the point format for future reads and writes. + * + * \param ctx The ECJPAKE context to configure. + * \param point_format The point format to use: + * #MBEDTLS_ECP_PF_UNCOMPRESSED (default) + * or #MBEDTLS_ECP_PF_COMPRESSED. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p point_format + * is invalid. + */ +int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx, + int point_format ); + +/** + * \brief Check if an ECJPAKE context is ready for use. + * + * \param ctx The ECJPAKE context to check. This must be + * initialized. + * + * \return \c 0 if the context is ready for use. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise. + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ); + +/** + * \brief Generate and write the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be + * initialized and set up. + * \param buf The buffer to write the contents to. This must be a + * writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number + * of Bytes written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the first round message + * (TLS: contents of the Client/ServerHello extension, + * excluding extension type and length bytes). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up. + * \param buf The buffer holding the first round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Generate and write the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up, and already have performed round one. + * \param buf The buffer to write the round two contents to. + * This must be a writable buffer of length \p len Bytes. + * \param len The size of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Read and process the second round message + * (TLS: contents of the Client/ServerKeyExchange). + * + * \param ctx The ECJPAKE context to use. This must be initialized + * and set up and already have performed round one. + * \param buf The buffer holding the second round message. This must + * be a readable buffer of length \p len Bytes. + * \param len The length in Bytes of \p buf. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Derive the shared secret + * (TLS: Pre-Master Secret). + * + * \param ctx The ECJPAKE context to use. This must be initialized, + * set up and have performed both round one and two. + * \param buf The buffer to write the derived secret to. This must + * be a writable buffer of length \p len Bytes. + * \param len The length of \p buf in Bytes. + * \param olen The address at which to store the total number of Bytes + * written to \p buf. This must not be \c NULL. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This + * may be \c NULL if \p f_rng doesn't use a context. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This clears an ECJPAKE context and frees any + * embedded data structure. + * + * \param ctx The ECJPAKE context to free. This may be \c NULL, + * in which case this function does nothing. If it is not + * \c NULL, it must point to an initialized ECJPAKE context. + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_ecjpake_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* ecjpake.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecp.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecp.h new file mode 100644 index 00000000..5b26084d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ecp.h @@ -0,0 +1,1297 @@ +/** + * \file ecp.h + * + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/bignum.h" + +/* + * ECP error codes + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 +/** The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 +/** The requested feature is not available, for example, the requested curve is not supported. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 +/** The signature is not valid. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 +/** Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 +/** Generation of random value, such as ephemeral key, failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 +/** Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 +/** The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 +/** Operation in progress, call again with the same parameters to continue. */ +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 + +/* Flags indicating whether to include code that is specific to certain + * types of curves. These flags are for internal library use only. */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MONTGOMERY_ENABLED +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain-parameter identifiers: curve, subgroup, and generator. + * + * \note Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only standardized domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +/* Note: when adding a new curve: + * - Add it at the end of this enum, otherwise you'll break the ABI by + * changing the numerical value for existing curves. + * - Increment MBEDTLS_ECP_DP_MAX below if needed. + * - Update the calculation of MBEDTLS_ECP_MAX_BITS below. + * - Add the corresponding MBEDTLS_ECP_DP_xxx_ENABLED macro definition to + * mbedtls_config.h. + * - List the curve as a dependency of MBEDTLS_ECP_C and + * MBEDTLS_ECDSA_C if supported in check_config.h. + * - Add the curve to the appropriate curve type macro + * MBEDTLS_ECP_yyy_ENABLED above. + * - Add the necessary definitions to ecp_curves.c. + * - Add the curve to the ecp_supported_curves array in ecp.c. + * - Add the curve to applicable profiles in x509_crt.c. + * - Add the curve to applicable presets in ssl_tls.c. + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ +} mbedtls_ecp_group_id; + +/** + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. + */ +#define MBEDTLS_ECP_DP_MAX 14 + +/* + * Curve types + */ +typedef enum +{ + MBEDTLS_ECP_TYPE_NONE = 0, + MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + MBEDTLS_ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} mbedtls_ecp_curve_type; + +/** + * Curve information, for use by other modules. + * + * The fields of this structure are part of the public API and can be + * accessed directly by applications. Future versions of the library may + * add extra fields or reorder existing fields. + */ +typedef struct mbedtls_ecp_curve_info +{ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ +} mbedtls_ecp_curve_info; + +/** + * \brief The ECP point structure, in Jacobian coordinates. + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. + */ +typedef struct mbedtls_ecp_point +{ + mbedtls_mpi MBEDTLS_PRIVATE(X); /*!< The X coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(Y); /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi MBEDTLS_PRIVATE(Z); /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +/** + * \brief The ECP group structure. + * + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + * \note Alternative implementations of the ECP module must obey the + * following constraints. + * * Group IDs must be distinct: if two group structures have + * the same ID, then they must be identical. + * * The fields \c id, \c P, \c A, \c B, \c G, \c N, + * \c pbits and \c nbits must have the same type and semantics + * as in the built-in implementation. + * They must be available for reading, but direct modification + * of these fields does not need to be supported. + * They do not need to be at the same offset in the structure. + */ +typedef struct mbedtls_ecp_group +{ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + /* End of public fields */ + + unsigned int MBEDTLS_PRIVATE(h); /*!< \internal 1 if the constants are static. */ + int (*MBEDTLS_PRIVATE(modp))(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*MBEDTLS_PRIVATE(t_pre))(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*MBEDTLS_PRIVATE(t_post))(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *MBEDTLS_PRIVATE(t_data); /*!< Unused. */ + mbedtls_ecp_point *MBEDTLS_PRIVATE(T); /*!< Pre-computed points for ecp_mul_comb(). */ + size_t MBEDTLS_PRIVATE(T_size); /*!< The number of dynamic allocated pre-computed points. */ +} +mbedtls_ecp_group; + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h, or define them using the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: a point where higher memory usage yields disminishing performance + * returns. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 4 /**< The maximum window size used. */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade code size for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * For each n-bit Short Weierstrass curve that is enabled, this adds 4n bytes + * of code size if n < 384 and 8n otherwise. + * + * Change this value to 0 to reduce code size. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#if !defined(MBEDTLS_ECP_C) +/* Dummy definition to help code that has optional ECP support and + * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */ +#define MBEDTLS_ECP_MAX_BITS 1 +/* Note: the curves must be listed in DECREASING size! */ +#elif defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 448 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 225 // n is slightly above 2^224 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define MBEDTLS_ECP_MAX_BITS 192 +#else +#error "Missing definition of MBEDTLS_ECP_MAX_BITS" +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + unsigned MBEDTLS_PRIVATE(ops_done); /*!< current ops count */ + unsigned MBEDTLS_PRIVATE(depth); /*!< call depth (0 = top-level) */ + mbedtls_ecp_restart_mul_ctx *MBEDTLS_PRIVATE(rsm); /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *MBEDTLS_PRIVATE(ma); /*!< ecp_muladd() sub-context */ +} mbedtls_ecp_restart_ctx; + +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, \ + (unsigned) (ops) ) ); + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group MBEDTLS_PRIVATE(grp); /*!< Elliptic curve and base point */ + mbedtls_mpi MBEDTLS_PRIVATE(d); /*!< our secret value */ + mbedtls_ecp_point MBEDTLS_PRIVATE(Q); /*!< our public value */ +} +mbedtls_ecp_keypair; + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * parameters until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. + * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 + * + * \note Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 + * + * \note This setting is currently ignored by Curve25519. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_is_enabled( void ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ); + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array. The last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. + * + * \note This function returns information about all curves + * supported by the library. Some curves may not be + * supported for all algorithms. Call mbedtls_ecdh_can_do() + * or mbedtls_ecdsa_can_do() to check if a curve is + * supported for ECDH or ECDSA. + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief This function retrieves curve information from an internal + * group identifier. + * + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function retrieves curve information from a TLS + * NamedCurve value. + * + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief This function retrieves curve information from a + * human-readable name. + * + * \param name The human-readable name. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_group_load() or mbedtls_ecp_tls_read_group() + * functions. + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief This function frees the components of a point. + * + * \param pt The point to free. + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief This function frees the components of an ECP group. + * + * \param grp The group to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP group. + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief This function frees the components of a key pair. + * + * \param key The key pair to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized ECP key pair. + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context. + * + * \param ctx The restart context to initialize. This must + * not be \c NULL. + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context. + * + * \param ctx The restart context to free. This may be \c NULL, in which + * case this function returns immediately. If it is not + * \c NULL, it must point to an initialized restart context. + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. This must be initialized. + * \param Q The source point. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code for other kinds of failure. + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief This function copies the contents of group \p src into + * group \p dst. + * + * \param dst The destination group. This must be initialized. + * \param src The source group. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, + const mbedtls_ecp_group *src ); + +/** + * \brief This function sets a point to the point at infinity. + * + * \param pt The point to set. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function checks if a point is the point at infinity. + * + * \param pt The point to test. This must be initialized. + * + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + * \return A negative error code on failure. + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function compares two points. + * + * \note This assumes that the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P The first point to compare. This must be initialized. + * \param Q The second point to compare. This must be initialized. + * + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief This function imports a non-zero point from two ASCII + * strings. + * + * \param P The destination point. This must be initialized. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief This function exports a point into unsigned binary data. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The point to export. This must be initialized. + * \param format The point format. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * (For groups without these formats, this parameter is + * ignored. But it still has to be either of the above + * values.) + * \param olen The address at which to store the length of + * the output in Bytes. This must not be \c NULL. + * \param buf The output buffer. This must be a writable buffer + * of length \p buflen Bytes. + * \param buflen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer + * is too small to hold the point. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * or the export for the given group is not implemented. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function imports a point from unsigned binary data. + * + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. + * + * \param grp The group to which the point should belong. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param P The destination context to import the point to. + * This must be initialized. + * \param buf The input buffer. This must be a readable buffer + * of length \p ilen Bytes. + * \param ilen The length of the input buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the import for the + * given group is not implemented. + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief This function imports a point from a TLS ECPoint record. + * + * \note On function return, \p *buf is updated to point immediately + * after the ECPoint record. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization + * failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief This function exports a point as a TLS ECPoint record + * defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to be exported. This must be initialized. + * \param format The point format to use. This must be either + * #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED. + * \param olen The address at which to store the length in Bytes + * of the data written. + * \param buf The target buffer. This must be a writable buffer of + * length \p blen Bytes. + * \param blen The length of the target buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the input is invalid. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the target buffer + * is too small to hold the exported point. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function sets up an ECP group context + * from a standardized set of domain parameters. + * + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. + * + * \param grp The group context to setup. This must be initialized. + * \param id The identifier of the domain parameter set to load. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p id doesn't + * correspond to a known group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief This function sets up an ECP group context from a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The group context to setup. This must be initialized. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ); + +/** + * \brief This function extracts an elliptic curve group ID from a + * TLS ECParameters record as defined in RFC 4492, Section 5.4. + * + * \note The read pointer \p buf is updated to point right after + * the ECParameters record on exit. + * + * \param grp The address at which to store the group id. + * This must not be \c NULL. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the input buffer \c *buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the group is not + * recognized. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, + size_t len ); +/** + * \brief This function exports an elliptic curve as a TLS + * ECParameters record as defined in RFC 4492, Section 5.4. + * + * \param grp The ECP group to be exported. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param olen The address at which to store the number of Bytes written. + * This must not be \c NULL. + * \param buf The buffer to write to. This must be a writable buffer + * of length \p blen Bytes. + * \param blen The length of the output buffer \p buf in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output + * buffer is too small to hold the exported group. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, + size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function performs a scalar multiplication of a point + * by an integer: \p R = \p m * \p P. + * + * It is not thread-safe to use same group in multiple threads. + * + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. If also uses + * \p f_rng to randomize some intermediate results. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P in a restartable way. + * + * \see mbedtls_ecp_mul() + * + * \note This function does the same as \c mbedtls_ecp_mul(), but + * it can return early and restart according to the limit set + * with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply. This must be initialized. + * \param P The point to multiply. This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \note This function is only defined for short Weierstrass curves. + * It may not be included in builds without any short + * Weierstrass curve. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not + * designate a short Weierstrass curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q in a + * restartable way. + * + * \see \c mbedtls_ecp_muladd() + * + * \note This function works the same as \c mbedtls_ecp_muladd(), + * but it can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \note This function is only defined for short Weierstrass curves. + * It may not be included in builds without any short + * Weierstrass curve. + * + * \param grp The ECP group to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param R The point in which to store the result of the calculation. + * This must be initialized. + * \param m The integer by which to multiply \p P. + * This must be initialized. + * \param P The point to multiply by \p m. This must be initialized. + * \param n The integer by which to multiply \p Q. + * This must be initialized. + * \param Q The point to be multiplied by \p n. + * This must be initialized. + * \param rs_ctx The restart context (NULL disables restart). + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if \p grp does not + * designate a short Weierstrass curve. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +/** + * \brief This function checks that a point is a valid public key + * on this curve. + * + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the point should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param pt The point to check. This must be initialized. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not + * a valid public key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ); + +/** + * \brief This function checks that an \p mbedtls_mpi is a + * valid private key for this curve. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group the private key should belong to. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The integer to check. This must be initialized. + * + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if the point is not a valid + * private key for the given curve. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ); + +/** + * \brief This function generates a private key. + * + * \param grp The ECP group to generate a private key for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param G The base point to use. This must be initialized + * and belong to \p grp. It replaces the default base + * point \c grp->G used by mbedtls_ecp_gen_keypair(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP keypair. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group to generate a key pair for. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param d The destination MPI (secret part). + * This must be initialized. + * \param Q The destination point (public part). + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, + mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. This must be initialized. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function reads an elliptic curve private key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. + * \param buf The buffer containing the binary representation of the + * key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY error if the key is + * invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ); + +/** + * \brief This function exports an elliptic curve private key. + * + * \param key The private key. + * \param buf The output buffer for containing the binary representation + * of the key. (Big endian integer for Weierstrass curves, byte + * string for Montgomery curves.) + * \param buflen The total length of the buffer in bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key + representation is larger than the available space in \p buf. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for + * the group is not implemented. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. + * + * \param pub The keypair structure holding the public key. This + * must be initialized. If it contains a private key, that + * part is ignored. + * \param prv The keypair structure holding the full keypair. + * This must be initialized. + * \param f_rng The RNG function. This must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c + * NULL if \p f_rng doesn't need a context. + * + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_check_pub_priv( + const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The ECP checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/entropy.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/entropy.h new file mode 100644 index 00000000..fede05ff --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/entropy.h @@ -0,0 +1,293 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "mbedtls/sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "mbedtls/sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + + +/** Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C +/** No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E +/** No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 +/** No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D +/** Read/write error in file. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct mbedtls_entropy_source_state +{ + mbedtls_entropy_f_source_ptr MBEDTLS_PRIVATE(f_source); /**< The entropy source callback */ + void * MBEDTLS_PRIVATE(p_source); /**< The callback data pointer */ + size_t MBEDTLS_PRIVATE(size); /**< Amount received in bytes */ + size_t MBEDTLS_PRIVATE(threshold); /**< Minimum bytes required before release */ + int MBEDTLS_PRIVATE(strong); /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context +{ + int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init. + * 1 after the first update. + * -1 after free. */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context MBEDTLS_PRIVATE(accumulator); +#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR) + mbedtls_sha256_context MBEDTLS_PRIVATE(accumulator); +#endif + int MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */ + mbedtls_entropy_source_state MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int MBEDTLS_PRIVATE(initial_entropy_run); +#endif +} +mbedtls_entropy_context; + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTLS_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/error.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/error.h new file mode 100644 index 00000000..8b2b9ea5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/error.h @@ -0,0 +1,214 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#include "mbedtls/build_info.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) + * + * Module Nr Codes assigned + * ERROR 2 0x006E 0x0001 + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0016 0x0013-0x0013 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 2 0x0070-0x0072 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * SSL 5 2 (Started from 0x5F00) + * CIPHER 6 8 (Started from 0x6080) + * SSL 6 22 (Started from top, plus 0x6000) + * SSL 7 20 (Started from 0x7000, gaps at + * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80) + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic error */ +#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 +/** This is a bug in the library */ +#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E + +/** Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 +/** The requested feature is not supported by the platform */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 + +/** + * \brief Combines a high-level and low-level error code together. + * + * Wrapper macro for mbedtls_error_add(). See that function for + * more details. + */ +#define MBEDTLS_ERROR_ADD( high, low ) \ + mbedtls_error_add( high, low, __FILE__, __LINE__ ) + +#if defined(MBEDTLS_TEST_HOOKS) +/** + * \brief Testing hook called before adding/combining two error codes together. + * Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS. + */ +extern void (*mbedtls_test_hook_error_add)( int, int, const char *, int ); +#endif + +/** + * \brief Combines a high-level and low-level error code together. + * + * This function can be called directly however it is usually + * called via the #MBEDTLS_ERROR_ADD macro. + * + * While a value of zero is not a negative error code, it is still an + * error code (that denotes success) and can be combined with both a + * negative error code or another value of zero. + * + * \note When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to + * call \link mbedtls_test_hook_error_add \endlink. + * + * \param high high-level error code. See error.h for more details. + * \param low low-level error code. See error.h for more details. + * \param file file where this error code addition occurred. + * \param line line where this error code addition occurred. + */ +static inline int mbedtls_error_add( int high, int low, + const char *file, int line ) +{ +#if defined(MBEDTLS_TEST_HOOKS) + if( *mbedtls_test_hook_error_add != NULL ) + ( *mbedtls_test_hook_error_add )( high, low, file, line ); +#endif + (void)file; + (void)line; + + return( high + low ); +} + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +/** + * \brief Translate the high-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_high_level_strerr( int error_code ); + +/** + * \brief Translate the low-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_low_level_strerr( int error_code ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/gcm.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/gcm.h new file mode 100644 index 00000000..7dc9dfb8 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/gcm.h @@ -0,0 +1,383 @@ +/** + * \file gcm.h + * + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_GCM_H +#define MBEDTLS_GCM_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#include + +#define MBEDTLS_GCM_ENCRYPT 1 +#define MBEDTLS_GCM_DECRYPT 0 + +/** Authenticated decryption failed. */ +#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 +/** An output buffer is too small. */ +#define MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL -0x0016 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_GCM_ALT) + +/** + * \brief The GCM context structure. + */ +typedef struct mbedtls_gcm_context +{ + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ + uint64_t MBEDTLS_PRIVATE(HL)[16]; /*!< Precalculated HTable low. */ + uint64_t MBEDTLS_PRIVATE(HH)[16]; /*!< Precalculated HTable high. */ + uint64_t MBEDTLS_PRIVATE(len); /*!< The total length of the encrypted data. */ + uint64_t MBEDTLS_PRIVATE(add_len); /*!< The total length of the additional data. */ + unsigned char MBEDTLS_PRIVATE(base_ectr)[16]; /*!< The first ECTR for tag. */ + unsigned char MBEDTLS_PRIVATE(y)[16]; /*!< The Y working value. */ + unsigned char MBEDTLS_PRIVATE(buf)[16]; /*!< The buf working value. */ + int MBEDTLS_PRIVATE(mode); /*!< The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +#else /* !MBEDTLS_GCM_ALT */ +#include "gcm_alt.h" +#endif /* !MBEDTLS_GCM_ALT */ + +/** + * \brief This function initializes the specified GCM context, + * to make references valid, and prepares the context + * for mbedtls_gcm_setkey() or mbedtls_gcm_free(). + * + * The function does not bind the GCM context to a particular + * cipher, nor set the key. For this purpose, use + * mbedtls_gcm_setkey(). + * + * \param ctx The GCM context to initialize. This must not be \c NULL. + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ); + +/** + * \brief This function associates a GCM context with a + * cipher algorithm and a key. + * + * \param ctx The GCM context. This must be initialized. + * \param cipher The 128-bit block cipher to use. + * \param key The encryption key. This must be a readable buffer of at + * least \p keybits bits. + * \param keybits The key size in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function performs GCM encryption or decryption of a buffer. + * + * \note For encryption, the output buffer can be the same as the + * input buffer. For decryption, the output buffer cannot be + * the same as input buffer. If the buffers overlap, the output + * buffer must trail at least 8 Bytes behind the input buffer. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * + * \param ctx The GCM context to use for encryption or decryption. This + * must be initialized. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param input The buffer holding the input data. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size in Bytes. + * \param output The buffer for holding the output data. If \p length is greater + * than zero, this must be a writable buffer of at least that + * size in Bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the encryption + * or decryption failed. + */ +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ); + +/** + * \brief This function performs a GCM authenticated decryption of a + * buffer. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param length The length of the ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \param iv The initialization vector. This must be a readable buffer + * of at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * \param add The buffer holding the additional data. This must be of at + * least that size in Bytes. + * \param add_len The length of the additional data. + * \param tag The buffer holding the tag to verify. This must be a + * readable buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. If \p length is greater + * than zero, this must be a readable buffer of at least that + * size. + * \param output The buffer for holding the decrypted plaintext. If \p length + * is greater than zero, this must be a writable buffer of at + * least that size. + * + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are + * not valid or a cipher-specific error code if the decryption + * failed. + */ +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function starts a GCM encryption or decryption + * operation. + * + * \param ctx The GCM context. This must be initialized. + * \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or + * #MBEDTLS_GCM_DECRYPT. + * \param iv The initialization vector. This must be a readable buffer of + * at least \p iv_len Bytes. + * \param iv_len The length of the IV. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len ); + +/** + * \brief This function feeds an input buffer as associated data + * (authenticated but not encrypted data) in a GCM + * encryption or decryption operation. + * + * Call this function after mbedtls_gcm_starts() to pass + * the associated data. If the associated data is empty, + * you do not need to call this function. You may not + * call this function after calling mbedtls_cipher_update(). + * + * \param ctx The GCM context. This must have been started with + * mbedtls_gcm_starts() and must not have yet received + * any input with mbedtls_gcm_update(). + * \param add The buffer holding the additional data, or \c NULL + * if \p add_len is \c 0. + * \param add_len The length of the additional data. If \c 0, + * \p add may be \c NULL. + * + * \return \c 0 on success. + */ +int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx, + const unsigned char *add, + size_t add_len ); + +/** + * \brief This function feeds an input buffer into an ongoing GCM + * encryption or decryption operation. + * + * You may call this function zero, one or more times + * to pass successive parts of the input: the plaintext to + * encrypt, or the ciphertext (not including the tag) to + * decrypt. After the last part of the input, call + * mbedtls_gcm_finish(). + * + * This function may produce output in one of the following + * ways: + * - Immediate output: the output length is always equal + * to the input length. + * - Buffered output: the output consists of a whole number + * of 16-byte blocks. If the total input length so far + * (not including associated data) is 16 \* *B* + *A* + * with *A* < 16 then the total output length is 16 \* *B*. + * + * In particular: + * - It is always correct to call this function with + * \p output_size >= \p input_length + 15. + * - If \p input_length is a multiple of 16 for all the calls + * to this function during an operation, then it is + * correct to use \p output_size = \p input_length. + * + * \note For decryption, the output buffer cannot be the same as + * input buffer. If the buffers overlap, the output buffer + * must trail at least 8 Bytes behind the input buffer. + * + * \param ctx The GCM context. This must be initialized. + * \param input The buffer holding the input data. If \p input_length + * is greater than zero, this must be a readable buffer + * of at least \p input_length bytes. + * \param input_length The length of the input data in bytes. + * \param output The buffer for the output data. If \p output_size + * is greater than zero, this must be a writable buffer of + * of at least \p output_size bytes. + * \param output_size The size of the output buffer in bytes. + * See the function description regarding the output size. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * total input length too long, + * unsupported input/output buffer overlap detected, + * or \p output_size too small. + */ +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length ); + +/** + * \brief This function finishes the GCM operation and generates + * the authentication tag. + * + * It wraps up the GCM stream, and generates the + * tag. The tag can have a maximum length of 16 Bytes. + * + * \param ctx The GCM context. This must be initialized. + * \param tag The buffer for holding the tag. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to generate. This must be at least + * four. + * \param output The buffer for the final output. + * If \p output_size is nonzero, this must be a writable + * buffer of at least \p output_size bytes. + * \param output_size The size of the \p output buffer in bytes. + * This must be large enough for the output that + * mbedtls_gcm_update() has not produced. In particular: + * - If mbedtls_gcm_update() produces immediate output, + * or if the total input size is a multiple of \c 16, + * then mbedtls_gcm_finish() never produces any output, + * so \p output_size can be \c 0. + * - \p output_size never needs to be more than \c 15. + * \param output_length On success, \p *output_length contains the actual + * length of the output written in \p output. + * On failure, the content of \p *output_length is + * unspecified. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure: + * invalid value of \p tag_len, + * or \p output_size too small. + */ +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function clears a GCM context and the underlying + * cipher sub-context. + * + * \param ctx The GCM context to clear. If this is \c NULL, the call has + * no effect. Otherwise, this must be initialized. + */ +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The GCM checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_gcm_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + + +#endif /* gcm.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/hkdf.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/hkdf.h new file mode 100644 index 00000000..e6bfe056 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/hkdf.h @@ -0,0 +1,136 @@ +/** + * \file hkdf.h + * + * \brief This file contains the HKDF interface. + * + * The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is + * specified by RFC 5869. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_HKDF_H +#define MBEDTLS_HKDF_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" + +/** + * \name HKDF Error codes + * \{ + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This is the HMAC-based Extract-and-Expand Key Derivation Function + * (HKDF). + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros of + * md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ); + +/** + * \brief Take the input keying material \p ikm and extract from it a + * fixed-length pseudorandom key \p prk. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the + * hash function output in bytes. + * \param salt An optional salt value (a non-secret random value); + * if the salt is not provided, a string of all zeros + * of md.size length is used as the salt. + * \param salt_len The length in bytes of the optional \p salt. + * \param ikm The input keying material. + * \param ikm_len The length in bytes of \p ikm. + * \param[out] prk A pseudorandom key of at least md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ); + +/** + * \brief Expand the supplied \p prk into several additional pseudorandom + * keys, which is the output of the HKDF. + * + * \warning This function should only be used if the security of it has been + * studied and established in that particular context (eg. TLS 1.3 + * key schedule). For standard HKDF security guarantees use + * \c mbedtls_hkdf instead. + * + * \param md A hash function; md.size denotes the length of the hash + * function output in bytes. + * \param prk A pseudorandom key of at least md.size bytes. \p prk is + * usually the output from the HKDF extract step. + * \param prk_len The length in bytes of \p prk. + * \param info An optional context and application specific information + * string. This can be a zero-length string. + * \param info_len The length of \p info in bytes. + * \param okm The output keying material of \p okm_len bytes. + * \param okm_len The length of the output keying material in bytes. This + * must be less than or equal to 255 * md.size bytes. + * + * \return 0 on success. + * \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid. + * \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying + * MD layer. + */ +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* hkdf.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/hmac_drbg.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/hmac_drbg.h new file mode 100644 index 00000000..0f1653f7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/hmac_drbg.h @@ -0,0 +1,447 @@ +/** + * \file hmac_drbg.h + * + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * Error codes + */ +/** Too many random requested in single call. */ +#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 +/** Input too large (Entropy + additional). */ +#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 +/** Read/write error in file. */ +#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 +/** The entropy source failed. */ +#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL) +#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST) +#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +#endif + +#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */ +#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * HMAC_DRBG context. + */ +typedef struct mbedtls_hmac_drbg_context +{ + /* Working state: the key K is not stored explicitly, + * but is implied by the HMAC context */ + mbedtls_md_context_t MBEDTLS_PRIVATE(md_ctx); /*!< HMAC context (inc. K) */ + unsigned char MBEDTLS_PRIVATE(V)[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */ + int MBEDTLS_PRIVATE(reseed_counter); /*!< reseed counter */ + + /* Administrative state */ + size_t MBEDTLS_PRIVATE(entropy_len); /*!< entropy bytes grabbed on each (re)seed */ + int MBEDTLS_PRIVATE(prediction_resistance); /*!< enable prediction resistance (Automatic + reseed before every random generation) */ + int MBEDTLS_PRIVATE(reseed_interval); /*!< reseed interval */ + + /* Callbacks */ + int (*MBEDTLS_PRIVATE(f_entropy))(void *, unsigned char *, size_t); /*!< entropy function */ + void *MBEDTLS_PRIVATE(p_entropy); /*!< context for the entropy function */ + +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized if and only if + * md_ctx->md_info != NULL. This means that the mutex is initialized + * during the initial seeding in mbedtls_hmac_drbg_seed() or + * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization. + * + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL + * by default. Override this value by calling + * mbedtls_hmac_drbg_set_reseed_interval(). + * + * \param ctx HMAC_DRBG context to be initialized. + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding. + * + * Set the initial seed and set up the entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. + * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). + * + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy failed. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief Initilisation of simpified HMAC_DRBG (never reseeds). + * + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The HMAC_DRBG context. + * \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF. + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The amount of entropy to grab, in bytes. + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, + size_t len ); + +/** + * \brief Set the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + */ +int mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function uses HMAC_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + * + * \param ctx The HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The HMAC_DRBG Checkup routine. + * + * \return \c 0 if successful. + * \return \c 1 if the test failed. + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/mbedtls_config.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/mbedtls_config.h new file mode 100644 index 00000000..a671eb0a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/mbedtls_config.h @@ -0,0 +1,3322 @@ +/** + * \file mbedtls_config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +/** + * This is an optional version symbol that enables comatibility handling of + * config files. + * + * It is equal to the #MBEDTLS_VERSION_NUMBER of the Mbed TLS version that + * introduced the config format we want to be compatible with. + */ +//#define MBEDTLS_CONFIG_VERSION 0x03000000 + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h, time(), and an implementation for + * mbedtls_platform_gmtime_r() (see below). + * The time needs to be correct (not necessarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + * + * \note mbedtls_platform_gmtime_r() is an abstraction in platform_util.h that + * behaves similarly to the gmtime_r() function from the C standard. Refer to + * the documentation for mbedtls_platform_gmtime_r() for more information. + * + * \note It is possible to configure an implementation for + * mbedtls_platform_gmtime_r() at compile-time by using the macro + * MBEDTLS_PLATFORM_GMTIME_R_ALT. + */ +#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions and features so that they generate a warning if + * used. Functionality deprecated in one version will usually be removed in the + * next version. You can enable this to help you prepare the transition to a + * new major version by making sure your code is not using this functionality. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions and features. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions and features so that they generate an error if + * used. Functionality deprecated in one version will usually be removed in the + * next version. You can enable this to help you prepare the transition to a + * new major version by making sure your code is not using this functionality. + * + * Uncomment to get errors on using deprecated functions and features. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD5, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_SHA256_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note If you use the AES_xxx_ALT macros, then it is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext(). + * + */ +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * The original implementation can in addition be removed by setting the + * MBEDTLS_ECP_NO_FALLBACK option, in which case any function for which the + * corresponding MBEDTLS_ECP__FUNCTION_NAME__ALT macro is defined will not be + * able to fallback to curves not supported by the alternative implementation. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_free are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you set MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac() + * function, but will use your mbedtls_internal_ecp_double_jac() if the group + * for the operation is supported by your implementation (i.e. your + * mbedtls_internal_ecp_grp_capable() function returns 1 for this group). If the + * group is not supported by your implementation, then the original mbed TLS + * implementation of ecp_double_jac() is used instead, unless this fallback + * behaviour is disabled by setting MBEDTLS_ECP_NO_FALLBACK (in which case + * ecp_double_jac() will return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE). + * + * The function prototypes and the definition of mbedtls_ecp_group and + * mbedtls_ecp_point will not change based on MBEDTLS_ECP_INTERNAL_ALT, so your + * implementation of mbedtls_internal_ecp__function_name__ must be compatible + * with their definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Turn off software fallback for curves not supported in hardware */ +//#define MBEDTLS_ECP_NO_FALLBACK +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in library/entropy_poll.h, and accept NULL as first + * argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CHECK_RETURN_WARNING + * + * If this macro is defined, emit a compile-time warning if application code + * calls a function without checking its return value, but the return value + * should generally be checked in portable applications. + * + * This is only supported on platforms where #MBEDTLS_CHECK_RETURN is + * implemented. Otherwise this option has no effect. + * + * Uncomment to get warnings on using fallible functions without checking + * their return value. + * + * \note This feature is a work in progress. + * Warnings will be added to more functions in the future. + * + * \note A few functions are considered critical, and ignoring the return + * value of these functions will trigger a warning even if this + * macro is not defined. To completely disable return value check + * warnings, define #MBEDTLS_CHECK_RETURN with an empty expansion. + */ +//#define MBEDTLS_CHECK_RETURN_WARNING + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * To enable the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** \def MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + * + * Uncomment this macro to use a 128-bit key in the CTR_DRBG module. + * By default, CTR_DRBG uses a 256-bit key. + */ +//#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +/* Short Weierstrass curves (supporting ECP, ECDH, ECDSA) */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +/* Montgomery curves (supporting ECP) */ +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECP_RESTARTABLE + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. + * + * This is useful in non-threaded environments if you want to avoid blocking + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. + * + * Uncomment this macro to enable restartable ECC computations. + * + * \note This option only works with the default software implementation of + * elliptic curve functionality. It is incompatible with + * MBEDTLS_ECP_ALT, MBEDTLS_ECDH_XXX_ALT, MBEDTLS_ECDSA_XXX_ALT. + */ +#define MBEDTLS_ECP_RESTARTABLE + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C, MBEDTLS_ECDSA_C + * + * Comment this macro to disable deterministic ECDSA. + */ +#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +//#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources in mbedtls_entropy_init(). + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER + * + * Enable key identifiers that encode a key owner identifier. + * + * The owner of a key is identified by a value of type ::mbedtls_key_owner_id_t + * which is currently hard-coded to be int32_t. + * + * Note that this option is meant for internal use only and may be removed + * without notice. It is incompatible with MBEDTLS_USE_PSA_CRYPTO. + */ +//#define MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** \def MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS + * + * Enable support for platform built-in keys. If you enable this feature, + * you must implement the function mbedtls_psa_platform_get_builtin_key(). + * See the documentation of that function for more information. + * + * Built-in keys are typically derived from a hardware unique key or + * stored in a secure element. + * + * Requires: MBEDTLS_PSA_CRYPTO_C. + * + * \warning This interface is experimental and may change or be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS + +/** \def MBEDTLS_PSA_CRYPTO_CLIENT + * + * Enable support for PSA crypto client. + * + * \note This option allows to include the code necessary for a PSA + * crypto client when the PSA crypto implementation is not included in + * the library (MBEDTLS_PSA_CRYPTO_C disabled). The code included is the + * code to set and get PSA key attributes. + * The development of PSA drivers partially relying on the library to + * fulfill the hardware gaps is another possible usage of this option. + * + * \warning This interface is experimental and may change or be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_CLIENT + +/** \def MBEDTLS_PSA_CRYPTO_DRIVERS + * + * Enable support for the experimental PSA crypto driver interface. + * + * Requires: MBEDTLS_PSA_CRYPTO_C + * + * \warning This interface is experimental and may change or be removed + * without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_DRIVERS + +/** \def MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + * + * Make the PSA Crypto module use an external random generator provided + * by a driver, instead of Mbed TLS's entropy and DRBG modules. + * + * \note This random generator must deliver random numbers with cryptographic + * quality and high performance. It must supply unpredictable numbers + * with a uniform distribution. The implementation of this function + * is responsible for ensuring that the random generator is seeded + * with sufficient entropy. If you have a hardware TRNG which is slow + * or delivers non-uniform output, declare it as an entropy source + * with mbedtls_entropy_add_source() instead of enabling this option. + * + * If you enable this option, you must configure the type + * ::mbedtls_psa_external_random_context_t in psa/crypto_platform.h + * and define a function called mbedtls_psa_external_get_random() + * with the following prototype: + * ``` + * psa_status_t mbedtls_psa_external_get_random( + * mbedtls_psa_external_random_context_t *context, + * uint8_t *output, size_t output_size, size_t *output_length); + * ); + * ``` + * The \c context value is initialized to 0 before the first call. + * The function must fill the \c output buffer with \p output_size bytes + * of random data and set \c *output_length to \p output_size. + * + * Requires: MBEDTLS_PSA_CRYPTO_C + * + * \warning If you enable this option, code that uses the PSA cryptography + * interface will not use any of the entropy sources set up for + * the entropy module, nor the NV seed that MBEDTLS_ENTROPY_NV_SEED + * enables. + * + * \note This option is experimental and may be removed without notice. + */ +//#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + +/** + * \def MBEDTLS_PSA_CRYPTO_SPM + * + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is built for SPM (Secure + * Partition Manager) integration which separates the code into two parts: a + * NSPE (Non-Secure Process Environment) and an SPE (Secure Process + * Environment). + * + * Module: library/psa_crypto.c + * Requires: MBEDTLS_PSA_CRYPTO_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SPM + +/** + * \def MBEDTLS_PSA_INJECT_ENTROPY + * + * Enable support for entropy injection at first boot. This feature is + * required on systems that do not have a built-in entropy source (TRNG). + * This feature is currently not supported on systems that have a built-in + * entropy source. + * + * Requires: MBEDTLS_PSA_CRYPTO_STORAGE_C, MBEDTLS_ENTROPY_NV_SEED + * + */ +//#define MBEDTLS_PSA_INJECT_ENTROPY + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SHA512_SMALLER + * + * Enable an implementation of SHA-512 that has lower ROM footprint but also + * lower performance. + * + * Uncomment to enable the smaller implementation of SHA512. + */ +//#define MBEDTLS_SHA512_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_DTLS_CONNECTION_ID + * + * Enable support for the DTLS Connection ID extension + * (version draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05) + * which allows to identify DTLS connections across changes + * in the underlying transport. + * + * Setting this option enables the SSL APIs `mbedtls_ssl_set_cid()`, + * `mbedtls_ssl_get_peer_cid()` and `mbedtls_ssl_conf_cid()`. + * See the corresponding documentation for more information. + * + * \warning The Connection ID extension is still in draft state. + * We make no stability promises for the availability + * or the shape of the API controlled by this option. + * + * The maximum lengths of outgoing and incoming CIDs can be configured + * through the options + * - MBEDTLS_SSL_CID_OUT_LEN_MAX + * - MBEDTLS_SSL_CID_IN_LEN_MAX. + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Uncomment to enable the Connection ID extension. + */ +//#define MBEDTLS_SSL_DTLS_CONNECTION_ID + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_CONTEXT_SERIALIZATION + * + * Enable serialization of the TLS context structures, through use of the + * functions mbedtls_ssl_context_save() and mbedtls_ssl_context_load(). + * + * This pair of functions allows one side of a connection to serialize the + * context associated with the connection, then free or re-use that context + * while the serialized state is persisted elsewhere, and finally deserialize + * that state to a live context for resuming read/write operations on the + * connection. From a protocol perspective, the state of the connection is + * unaffected, in particular this is entirely transparent to the peer. + * + * Note: this is distinct from TLS session resumption, which is part of the + * protocol and fully visible by the peer. TLS session resumption enables + * establishing new connections associated to a saved session with shorter, + * lighter handshakes, while context serialization is a local optimization in + * handling a single, potentially long-lived connection. + * + * Enabling these APIs makes some SSL structures larger, as 64 extra bytes are + * saved after the handshake to allow for more efficient serialization, so if + * you don't need this feature you'll save RAM by disabling it. + * + * Comment to disable the context serialization APIs. + */ +#define MBEDTLS_SSL_CONTEXT_SERIALIZATION + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for RFC 7627: Session Hash and Extended Master Secret + * Extension. + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + * + * This option controls the availability of the API mbedtls_ssl_get_peer_cert() + * giving access to the peer's certificate after completion of the handshake. + * + * Unless you need mbedtls_ssl_peer_cert() in your application, it is + * recommended to disable this option for reduced RAM usage. + * + * \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still + * defined, but always returns \c NULL. + * + * \note This option has no influence on the protection against the + * triple handshake attack. Even if it is disabled, Mbed TLS will + * still ensure that certificates do not change during renegotiation, + * for exaple by keeping a hash of the peer's certificate. + * + * Comment this macro to disable storing the peer's certificate + * after the handshake. + */ +#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Enable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_3 + * + * Enable support for TLS 1.3. + * + * \note The support for TLS 1.3 is not comprehensive yet, in particular + * pre-shared keys are not supported. + * See docs/architecture/tls13-support.md for a description of the TLS + * 1.3 support that this option enables. + * + * Uncomment this macro to enable the support for TLS 1.3. + * + */ +//#define MBEDTLS_SSL_PROTO_TLS1_3 + +/** + * \def MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE + * + * Enable TLS 1.3 middlebox compatibility mode. + * + * As specified in Section D.4 of RFC 8446, TLS 1.3 offers a compatibility + * mode to make a TLS 1.3 connection more likely to pass through middle boxes + * expecting TLS 1.2 traffic. + * + * Turning on the compatibility mode comes at the cost of a few added bytes + * on the wire, but it doesn't affect compatibility with TLS 1.3 implementations + * that don't use it. Therefore, unless transmission bandwidth is critical and + * you know that middlebox compatibility issues won't occur, it is therefore + * recommended to set this option. + * + * Comment to disable compatibility mode for TLS 1.3. If + * MBEDTLS_SSL_PROTO_TLS1_3 is not enabled, this option does not have any + * effect on the build. + * + */ +//#define MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_SRTP + * + * Enable support for negotiation of DTLS-SRTP (RFC 5764) + * through the use_srtp extension. + * + * \note This feature provides the minimum functionality required + * to negotiate the use of DTLS-SRTP and to allow the derivation of + * the associated SRTP packet protection key material. + * In particular, the SRTP packet protection itself, as well as the + * demultiplexing of RTP and DTLS packets at the datagram layer + * (see Section 5 of RFC 5764), are not handled by this feature. + * Instead, after successful completion of a handshake negotiating + * the use of DTLS-SRTP, the extended key exporter API + * mbedtls_ssl_conf_export_keys_cb() should be used to implement + * the key exporter described in Section 4.2 of RFC 5764 and RFC 5705 + * (this is implemented in the SSL example programs). + * The resulting key should then be passed to an SRTP stack. + * + * Setting this option enables the runtime API + * mbedtls_ssl_conf_dtls_srtp_protection_profiles() + * through which the supported DTLS-SRTP protection + * profiles can be configured. You must call this API at + * runtime if you wish to negotiate the use of DTLS-SRTP. + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Uncomment this to enable support for use_srtp extension. + */ +//#define MBEDTLS_SSL_DTLS_SRTP + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintenance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + * + * When this option is enabled, the SSL buffer will be resized automatically + * based on the negotiated maximum fragment length in each direction. + * + * Requires: MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + */ +//#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** + * \def MBEDTLS_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * See `docs/architecture/testing/mbed-crypto-invasive-testing.md` for more + * information. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_USE_PSA_CRYPTO + * + * Make the X.509 and TLS library use PSA for cryptographic operations, and + * enable new APIs for using keys handled by PSA Crypto. + * + * \note Development of this option is currently in progress, and parts of Mbed + * TLS's X.509 and TLS modules are not ported to PSA yet. However, these parts + * will still continue to work as usual, so enabling this option should not + * break backwards compatibility. + * + * \note See docs/use-psa-crypto.md for a complete description of what this + * option currently does, and of parts that are not affected by it so far. + * + * \warning This option enables new Mbed TLS APIs which are currently + * considered experimental and may change in incompatible ways at any time. + * That is, the APIs enabled by this option are not covered by the usual + * promises of API stability. + * + * Requires: MBEDTLS_PSA_CRYPTO_C. + * + * Uncomment this to enable internal use of PSA Crypto and new associated APIs. + */ +//#define MBEDTLS_USE_PSA_CRYPTO + +/** + * \def MBEDTLS_PSA_CRYPTO_CONFIG + * + * This setting allows support for cryptographic mechanisms through the PSA + * API to be configured separately from support through the mbedtls API. + * + * Uncomment this to enable use of PSA Crypto configuration settings which + * can be found in include/psa/crypto_config.h. + * + * This feature is still experimental and is not ready for production since + * it is not completed. + */ +//#define MBEDTLS_PSA_CRYPTO_CONFIG + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + * + * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()` + * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure + * the set of trusted certificates through a callback instead of a linked + * list. + * + * This is useful for example in environments where a large number of trusted + * certificates is present and storing them in a linked list isn't efficient + * enough, or when the set of trusted certificates changes frequently. + * + * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and + * `mbedtls_ssl_conf_ca_cb()` for more information. + * + * Uncomment to enable trusted certificate callbacks. + */ +//#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + +/** + * \def MBEDTLS_X509_REMOVE_INFO + * + * Disable mbedtls_x509_*_info() and related APIs. + * + * Uncomment to omit mbedtls_x509_*_info(), as well as mbedtls_debug_print_crt() + * and other functions/constants only used by these functions, thus reducing + * the code footprint by several KB. + */ +//#define MBEDTLS_X509_REMOVE_INFO + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_alt_helpers.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * \note When #MBEDTLS_CMAC_ALT is active, meaning that the underlying + * implementation of the CMAC algorithm is provided by an alternate + * implementation, that alternate implementation may opt to not support + * AES-192 or 3DES as underlying block ciphers for the CMAC operation. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-based random generator. + * The CTR_DRBG generator uses AES-256 by default. + * To use AES-128 instead, enable \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY above. + * + * \note To achieve a 256-bit security strength with CTR_DRBG, + * you must use AES-256 *and* use sufficient entropy. + * See ctr_drbg.h for more details. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C, + * and at least one MBEDTLS_ECP_DP_XXX_ENABLED for a + * short Weierstrass curve. + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \note EC J-PAKE support is based on the Thread v1.0.0 specification. + * It has not been reviewed for compliance with newer standards such as + * Thread v1.1 or RFC 8236. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM). + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C or MBEDTLS_ARIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for TLS 1.2 depending on the handshake parameters. + * Further, it is used for checking MD5-signed certificates, and for PBKDF1 + * when decrypting PEM-encoded encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_PSA_CRYPTO_C + * + * Enable the Platform Security Architecture cryptography API. + * + * Module: library/psa_crypto.c + * + * Requires: either MBEDTLS_CTR_DRBG_C and MBEDTLS_ENTROPY_C, + * or MBEDTLS_HMAC_DRBG_C and MBEDTLS_ENTROPY_C, + * or MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. + * + */ +#define MBEDTLS_PSA_CRYPTO_C + +/** + * \def MBEDTLS_PSA_CRYPTO_SE_C + * + * Enable secure element support in the Platform Security Architecture + * cryptography API. + * + * \warning This feature is not yet suitable for production. It is provided + * for API evaluation and testing purposes only. + * + * Module: library/psa_crypto_se.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, MBEDTLS_PSA_CRYPTO_STORAGE_C + * + */ +//#define MBEDTLS_PSA_CRYPTO_SE_C + +/** + * \def MBEDTLS_PSA_CRYPTO_STORAGE_C + * + * Enable the Platform Security Architecture persistent key storage. + * + * Module: library/psa_crypto_storage.c + * + * Requires: MBEDTLS_PSA_CRYPTO_C, + * either MBEDTLS_PSA_ITS_FILE_C or a native implementation of + * the PSA ITS interface + */ +#define MBEDTLS_PSA_CRYPTO_STORAGE_C + +/** + * \def MBEDTLS_PSA_ITS_FILE_C + * + * Enable the emulation of the Platform Security Architecture + * Internal Trusted Storage (PSA ITS) over files. + * + * Module: library/psa_its_file.c + * + * Requires: MBEDTLS_FS_IO + */ +#define MBEDTLS_PSA_ITS_FILE_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_alt_helpers.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for TLS 1.2 depending on the handshake parameters, + * and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA224_C + * + * Enable the SHA-224 cryptographic hash algorithm. + * + * Requires: MBEDTLS_SHA256_C. The library does not currently support enabling + * SHA-224 without SHA-256. + * + * Module: library/sha256.c + * Caller: library/md.c + * library/ssl_cookie.c + * + * This module adds support for SHA-224. + */ +#define MBEDTLS_SHA224_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-256 cryptographic hash algorithm. + * + * Requires: MBEDTLS_SHA224_C. The library does not currently support enabling + * SHA-256 without SHA-224. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA384_C + * + * Enable the SHA-384 cryptographic hash algorithm. + * + * Requires: MBEDTLS_SHA512_C + * + * Module: library/sha512.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Comment to disable SHA-384 + */ +#define MBEDTLS_SHA384_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_tls.c + * library/ssl_cookie.c + * + * This module adds support for SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + */ +#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define MBEDTLS_X509_CSR_WRITE_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_WINDOW_SIZE 4 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correctly zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_VSNPRINTF_MACRO vsnprintf /**< Default vsnprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/** \def MBEDTLS_CHECK_RETURN + * + * This macro is used at the beginning of the declaration of a function + * to indicate that its return value should be checked. It should + * instruct the compiler to emit a warning or an error if the function + * is called without checking its return value. + * + * There is a default implementation for popular compilers in platform_util.h. + * You can override the default implementation by defining your own here. + * + * If the implementation here is empty, this will effectively disable the + * checking of functions' return values. + */ +//#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) + +/** \def MBEDTLS_IGNORE_RETURN + * + * This macro requires one argument, which should be a C function call. + * If that function call would cause a #MBEDTLS_CHECK_RETURN warning, this + * warning is suppressed. + */ +//#define MBEDTLS_IGNORE_RETURN( result ) ((void) !(result)) + +/* PSA options */ +/** + * Use HMAC_DRBG with the specified hash algorithm for HMAC_DRBG for the + * PSA crypto subsystem. + * + * If this option is unset: + * - If CTR_DRBG is available, the PSA subsystem uses it rather than HMAC_DRBG. + * - Otherwise, the PSA subsystem uses HMAC_DRBG with either + * #MBEDTLS_MD_SHA512 or #MBEDTLS_MD_SHA256 based on availability and + * on unspecified heuristics. + */ +//#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 + +/** \def MBEDTLS_PSA_KEY_SLOT_COUNT + * Restrict the PSA library to supporting a maximum amount of simultaneously + * loaded keys. A loaded key is a key stored by the PSA Crypto core as a + * volatile key, or a persistent key which is loaded temporarily by the + * library as part of a crypto operation in flight. + * + * If this option is unset, the library will fall back to a default value of + * 32 keys. + */ +//#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum length (in bytes) of incoming plaintext fragments. + * + * This determines the size of the incoming TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * \note When using a value less than the default of 16KB on the client, it is + * recommended to use the Maximum Fragment Length (MFL) extension to + * inform the server about this limitation. On the server, there + * is no supported, standardized way of informing the client about + * restriction on the maximum size of incoming messages, and unless + * the limitation has been communicated by other means, it is recommended + * to only change the outgoing buffer size #MBEDTLS_SSL_OUT_CONTENT_LEN + * while keeping the default value of 16KB for the incoming buffer. + * + * Uncomment to set the maximum plaintext size of the incoming I/O buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_CID_IN_LEN_MAX + * + * The maximum length of CIDs used for incoming DTLS messages. + * + */ +//#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 + +/** \def MBEDTLS_SSL_CID_OUT_LEN_MAX + * + * The maximum length of CIDs used for outgoing DTLS messages. + * + */ +//#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 + +/** \def MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY + * + * This option controls the use of record plaintext padding + * in TLS 1.3 and when using the Connection ID extension in DTLS 1.2. + * + * The padding will always be chosen so that the length of the + * padded plaintext is a multiple of the value of this option. + * + * Note: A value of \c 1 means that no padding will be used + * for outgoing records. + * + * Note: On systems lacking division instructions, + * a power of two should be preferred. + */ +//#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum length (in bytes) of outgoing plaintext fragments. + * + * This determines the size of the outgoing TLS I/O buffer in such a way + * that it is capable of holding the specified amount of plaintext data, + * regardless of the protection mechanism used. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * Uncomment to set the maximum plaintext size of the outgoing I/O buffer. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLS_SSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** \def MBEDTLS_TLS_EXT_CID + * + * At the time of writing, the CID extension has not been assigned its + * final value. Set this configuration option to make Mbed TLS use a + * different value. + * + * A future minor revision of Mbed TLS may change the default value of + * this option to match evolving standards and usage. + */ +//#define MBEDTLS_TLS_EXT_CID 254 + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/** + * Uncomment the macro to let Mbed TLS use your alternate implementation of + * mbedtls_platform_gmtime_r(). This replaces the default implementation in + * platform_util.c. + * + * gmtime() is not a thread-safe function as defined in the C standard. The + * library will try to use safer implementations of this function, such as + * gmtime_r() when available. However, if Mbed TLS cannot identify the target + * system, the implementation of mbedtls_platform_gmtime_r() will default to + * using the standard gmtime(). In this case, calls from the library to + * gmtime() will be guarded by the global mutex mbedtls_threading_gmtime_mutex + * if MBEDTLS_THREADING_C is enabled. We recommend that calls from outside the + * library are also guarded with this mutex to avoid race conditions. However, + * if the macro MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, Mbed TLS will + * unconditionally use the implementation for mbedtls_platform_gmtime_r() + * supplied at compile time. + */ +//#define MBEDTLS_PLATFORM_GMTIME_R_ALT + +/** + * Enable the verified implementations of ECDH primitives from Project Everest + * (currently only Curve25519). This feature changes the layout of ECDH + * contexts and therefore is a compatibility break for applications that access + * fields of a mbedtls_ecdh_context structure directly. See also + * MBEDTLS_ECDH_LEGACY_CONTEXT in include/mbedtls/ecdh.h. + */ +//#define MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED + +/* \} name SECTION: Customisation configuration options */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/md.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/md.h new file mode 100644 index 00000000..2b668f55 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/md.h @@ -0,0 +1,464 @@ + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H +#include "mbedtls/private_access.h" + +#include + +#include "mbedtls/build_info.h" +#include "mbedtls/platform_util.h" + +/** The selected feature is not available. */ +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 +/** Opening or reading of file failed. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#else +#define MBEDTLS_MD_MAX_BLOCK_SIZE 64 +#endif + +/** + * Opaque struct. + * + * Constructed using either #mbedtls_md_info_from_string or + * #mbedtls_md_info_from_type. + * + * Fields can be accessed with #mbedtls_md_get_size, + * #mbedtls_md_get_type and #mbedtls_md_get_name. + */ +/* Defined internally in library/md_wrap.h. */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); + + /** The digest-specific context. */ + void *MBEDTLS_PRIVATE(md_ctx); + + /** The HMAC part of the context. */ + void *MBEDTLS_PRIVATE(hmac_ctx); +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \note The list starts with the strongest available hashes. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/md5.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/md5.h new file mode 100644 index 00000000..e7befc34 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/md5.h @@ -0,0 +1,203 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context +{ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ + uint32_t MBEDTLS_PRIVATE(state)[4]; /*!< intermediate digest state */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/memory_buffer_alloc.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 00000000..d4737f5c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,145 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#include "mbedtls/build_info.h" + +#include + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE) +#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_MEMORY_VERIFY_NONE 0 +#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0) +#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1) +#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize use of stack-based memory allocator. + * The stack-based allocator does memory management inside the + * presented buffer and does not call calloc() and free(). + * It sets the global mbedtls_calloc() and mbedtls_free() pointers + * to its own functions. + * (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if + * MBEDTLS_THREADING_C is defined) + * + * \note This code is not optimized and provides a straight-forward + * implementation of a stack-based memory allocator. + * + * \param buf buffer to use as heap + * \param len size of the buffer + */ +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ); + +/** + * \brief Free the mutex for thread-safety and clear remaining memory + */ +void mbedtls_memory_buffer_alloc_free( void ); + +/** + * \brief Determine when the allocator should automatically verify the state + * of the entire chain of headers / meta-data. + * (Default: MBEDTLS_MEMORY_VERIFY_NONE) + * + * \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC, + * MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS + */ +void mbedtls_memory_buffer_set_verify( int verify ); + +#if defined(MBEDTLS_MEMORY_DEBUG) +/** + * \brief Print out the status of the allocated memory (primarily for use + * after a program should have de-allocated all memory) + * Prints out a list of 'still allocated' blocks and their stack + * trace if MBEDTLS_MEMORY_BACKTRACE is defined. + */ +void mbedtls_memory_buffer_alloc_status( void ); + +/** + * \brief Get the peak heap usage so far + * + * \param max_used Peak number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param max_blocks Peak number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ); + +/** + * \brief Reset peak statistics + */ +void mbedtls_memory_buffer_alloc_max_reset( void ); + +/** + * \brief Get the current heap usage + * + * \param cur_used Current number of bytes in use or committed. This + * includes bytes in allocated blocks too small to split + * into smaller blocks but larger than the requested size. + * \param cur_blocks Current number of blocks in use, including free and used + */ +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ); +#endif /* MBEDTLS_MEMORY_DEBUG */ + +/** + * \brief Verifies that all headers in the memory buffer are correct + * and contain sane values. Helps debug buffer-overflow errors. + * + * Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined. + * Prints out full header information if MBEDTLS_MEMORY_DEBUG + * is defined. (Includes stack trace information for each block if + * MBEDTLS_MEMORY_BACKTRACE is defined as well). + * + * \return 0 if verified, 1 otherwise + */ +int mbedtls_memory_buffer_alloc_verify( void ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_memory_buffer_alloc_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* memory_buffer_alloc.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/net_sockets.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/net_sockets.h new file mode 100644 index 00000000..0c754b12 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/net_sockets.h @@ -0,0 +1,304 @@ +/** + * \file net_sockets.h + * + * \brief Network sockets abstraction layer to integrate Mbed TLS into a + * BSD-style sockets API. + * + * The network sockets module provides an example integration of the + * Mbed TLS library into a BSD sockets implementation. The module is + * intended to be an example of how Mbed TLS can be integrated into a + * networking stack, as well as to be Mbed TLS's network integration + * for its supported platforms. + * + * The module is intended only to be used with the Mbed TLS library and + * is not intended to be used by third party application software + * directly. + * + * The supported platforms are as follows: + * * Microsoft Windows and Windows CE + * * POSIX/Unix platforms including Linux, OS X + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" + +#include +#include + +/** Failed to open a socket. */ +#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 +/** The connection to the given server / port failed. */ +#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 +/** Binding of the socket failed. */ +#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 +/** Could not listen on the socket. */ +#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 +/** Could not accept the incoming connection. */ +#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A +/** Reading information from the socket failed. */ +#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C +/** Sending information through the socket failed. */ +#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E +/** Connection was reset by peer. */ +#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 +/** Failed to get an IP address for the given hostname. */ +#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 +/** Buffer is too small to hold the data. */ +#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 +/** The context is invalid, eg because it was free()ed. */ +#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 +/** Polling the net context failed. */ +#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 +/** Input invalid. */ +#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 + +#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */ + +#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */ +#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */ + +#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */ +#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Wrapper type for sockets. + * + * Currently backed by just a file descriptor, but might be more in the future + * (eg two file descriptors for combined IPv4 + IPv6 support, or additional + * structures for hand-made UDP demultiplexing). + */ +typedef struct mbedtls_net_context +{ + /** The underlying file descriptor. + * + * This field is only guaranteed to be present on POSIX/Unix-like platforms. + * On other platforms, it may have a different type, have a different + * meaning, or be absent altogether. + */ + int fd; +} +mbedtls_net_context; + +/** + * \brief Initialize a context + * Just makes the context ready to be used or freed safely. + * + * \param ctx Context to initialize + */ +void mbedtls_net_init( mbedtls_net_context *ctx ); + +/** + * \brief Initiate a connection with host:port in the given protocol + * + * \param ctx Socket to use + * \param host Host to connect to + * \param port Port to connect to + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_CONNECT_FAILED + * + * \note Sets the socket in connected mode even with UDP. + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto ); + +/** + * \brief Create a receiving socket on bind_ip:port in the chosen + * protocol. If bind_ip == NULL, all interfaces are bound. + * + * \param ctx Socket to use + * \param bind_ip IP to bind to, can be NULL + * \param port Port number to use + * \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP + * + * \return 0 if successful, or one of: + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_UNKNOWN_HOST, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_LISTEN_FAILED + * + * \note Regardless of the protocol, opens the sockets and binds it. + * In addition, make the socket listening if protocol is TCP. + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ); + +/** + * \brief Accept a connection from a remote client + * + * \param bind_ctx Relevant socket + * \param client_ctx Will contain the connected client socket + * \param client_ip Will contain the client IP address, can be NULL + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * MBEDTLS_ERR_NET_ACCEPT_FAILED, or + * MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small, + * MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to + * non-blocking and accept() would block. + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ); + +/** + * \brief Check and wait for the context to be ready for read/write + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \param ctx Socket to check + * \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and + * MBEDTLS_NET_POLL_WRITE specifying the events + * to wait for: + * - If MBEDTLS_NET_POLL_READ is set, the function + * will return as soon as the net context is available + * for reading. + * - If MBEDTLS_NET_POLL_WRITE is set, the function + * will return as soon as the net context is available + * for writing. + * \param timeout Maximal amount of time to wait before returning, + * in milliseconds. If \c timeout is zero, the + * function returns immediately. If \c timeout is + * -1u, the function blocks potentially indefinitely. + * + * \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE + * on success or timeout, or a negative return code otherwise. + */ +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ); + +/** + * \brief Set the socket blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ); + +/** + * \brief Set the socket non-blocking + * + * \param ctx Socket to set + * + * \return 0 if successful, or a non-zero error code + */ +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ); + +/** + * \brief Portable usleep helper + * + * \param usec Amount of microseconds to sleep + * + * \note Real amount of time slept will not be less than + * select()'s timeout granularity (typically, 10ms). + */ +void mbedtls_net_usleep( unsigned long usec ); + +/** + * \brief Read at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * + * \return the number of bytes received, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_READ indicates read() would block. + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ); + +/** + * \brief Write at most 'len' characters. If no error occurs, + * the actual amount read is returned. + * + * \param ctx Socket + * \param buf The buffer to read from + * \param len The length of the buffer + * + * \return the number of bytes sent, + * or a non-zero error code; with a non-blocking socket, + * MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block. + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ); + +/** + * \brief Read at most 'len' characters, blocking for at most + * 'timeout' seconds. If no error occurs, the actual amount + * read is returned. + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \param ctx Socket + * \param buf The buffer to write to + * \param len Maximum length of the buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (wait forever) + * + * \return The number of bytes received if successful. + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * Another negative error code (MBEDTLS_ERR_NET_xxx) + * for other failures. + * + * \note This function will block (until data becomes available or + * timeout is reached) even if the socket is set to + * non-blocking. Handling timeouts with non-blocking reads + * requires a different strategy. + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len, + uint32_t timeout ); + +/** + * \brief Closes down the connection and free associated data + * + * \param ctx The context to close + */ +void mbedtls_net_close( mbedtls_net_context *ctx ); + +/** + * \brief Gracefully shutdown the connection and free associated data + * + * \param ctx The context to free + */ +void mbedtls_net_free( mbedtls_net_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* net_sockets.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/nist_kw.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/nist_kw.h new file mode 100644 index 00000000..bd6c6584 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/nist_kw.h @@ -0,0 +1,179 @@ +/** + * \file nist_kw.h + * + * \brief This file provides an API for key wrapping (KW) and key wrapping with + * padding (KWP) as defined in NIST SP 800-38F. + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * + * Key wrapping specifies a deterministic authenticated-encryption mode + * of operation, according to NIST SP 800-38F: Recommendation for + * Block Cipher Modes of Operation: Methods for Key Wrapping. Its + * purpose is to protect cryptographic keys. + * + * Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP. + * https://tools.ietf.org/html/rfc3394 + * https://tools.ietf.org/html/rfc5649 + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_NIST_KW_H +#define MBEDTLS_NIST_KW_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + MBEDTLS_KW_MODE_KW = 0, + MBEDTLS_KW_MODE_KWP = 1 +} mbedtls_nist_kw_mode_t; + +#if !defined(MBEDTLS_NIST_KW_ALT) +// Regular implementation +// + +/** + * \brief The key wrapping context-type definition. The key wrapping context is passed + * to the APIs called. + * + * \note The definition of this type may change in future library versions. + * Don't make any assumptions on this context! + */ +typedef struct { + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx); /*!< The cipher context used. */ +} mbedtls_nist_kw_context; + +#else /* MBEDTLS_NIST_key wrapping_ALT */ +#include "nist_kw_alt.h" +#endif /* MBEDTLS_NIST_KW_ALT */ + +/** + * \brief This function initializes the specified key wrapping context + * to make references valid and prepare the context + * for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free(). + * + * \param ctx The key wrapping context to initialize. + * + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function initializes the key wrapping context set in the + * \p ctx parameter and sets the encryption key. + * + * \param ctx The key wrapping context. + * \param cipher The 128-bit block cipher to use. Only AES is supported. + * \param key The Key Encryption Key (KEK). + * \param keybits The KEK size in bits. This must be acceptable by the cipher. + * \param is_wrap Specify whether the operation within the context is wrapping or unwrapping + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input. + * \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers + * which are not supported. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ); + +/** + * \brief This function releases and clears the specified key wrapping context + * and underlying cipher sub-context. + * + * \param ctx The key wrapping context to clear. + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ); + +/** + * \brief This function encrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for encryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive.
  • + *
  • For KWP mode: any length between 1 and 2^32-1 inclusive.
+ * \param[out] output The buffer holding the output data. + *
  • For KW mode: Must be at least 8 bytes larger than \p in_len.
  • + *
  • For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of + * 8 bytes for KWP (15 bytes at most).
+ * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size ); + +/** + * \brief This function decrypts a buffer using key wrapping. + * + * \param ctx The key wrapping context to use for decryption. + * \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP) + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * The input uses units of 8 Bytes called semiblocks. + * The input must be a multiple of semiblocks. + *
  • For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive.
  • + *
  • For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.
+ * \param[out] output The buffer holding the output data. + * The output buffer's minimal length is 8 bytes shorter than \p in_len. + * \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure. + * For KWP mode, the length could be up to 15 bytes shorter than \p in_len, + * depending on how much padding was added to the data. + * \param[in] out_size The capacity of the output buffer. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length. + * \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext. + * \return cipher-specific error code on failure of the underlying cipher. + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t* out_len, size_t out_size); + + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/** + * \brief The key wrapping checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_nist_kw_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_NIST_KW_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/oid.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/oid.h new file mode 100644 index 00000000..836e455b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/oid.h @@ -0,0 +1,643 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +/** OID is not found. */ +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E +/** output buffer is too small */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B + +/* This is for the benefit of X.509, but defined here in order to avoid + * having a "backwards" include of x.509.h here */ +/* + * X.509 extension types (internal, arbitrary values for bitsets) + */ +#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) +#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) +#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) +#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01" +#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Certificate policies + */ +#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/** + * Wi-SUN Alliance Field Area Network + * { iso(1) identified-organization(3) dod(6) internet(1) + * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } + */ +#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" + +#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ +#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ + size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) + const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ + const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ +#endif +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); +#endif + +/** + * \brief Translate certificate policies OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pem.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pem.h new file mode 100644 index 00000000..baceb076 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pem.h @@ -0,0 +1,150 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +/** No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 +/** PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 +/** RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 +/** Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 +/** Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *MBEDTLS_PRIVATE(buf); /*!< buffer for decoded data */ + size_t MBEDTLS_PRIVATE(buflen); /*!< length of the buffer */ + unsigned char *MBEDTLS_PRIVATE(info); /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pk.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pk.h new file mode 100644 index 00000000..5f9f29ff --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pk.h @@ -0,0 +1,909 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** Memory allocation failed. */ +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 +/** Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 +/** Read/write of file failed. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 +/** Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 +/** Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 +/** Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 +/** The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 +/** The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 +/** Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 +/** Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 +/** The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 +/** The output buffer is too small. */ +#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, + MBEDTLS_PK_OPAQUE, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t MBEDTLS_PRIVATE(mgf1_hash_id); + int MBEDTLS_PRIVATE(expected_salt_len); + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Maximum size of a signature made by mbedtls_pk_sign(). + */ +/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature + * size among the supported signature types. Do it by starting at 0, + * then incrementally increasing to be large enough for each supported + * signature mechanism. + * + * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled + * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C + * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). + */ +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 + +#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \ + MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE +#endif + +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 ) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); + const char *MBEDTLS_PRIVATE(name); + void *MBEDTLS_PRIVATE(value); +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + * + * \note The library does not support custom pk info structures, + * only built-in structures returned by + * mbedtls_cipher_info_from_type(). + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void * MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void * MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx) ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx) ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + * + * \note For contexts that have been set up with + * mbedtls_pk_setup_opaque(), this does not free the underlying + * PSA key and you still need to call psa_destroy_key() + * independently if you want to destroy that key. + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Initialize a PK context to wrap a PSA key. + * + * \note This function replaces mbedtls_pk_setup() for contexts + * that wrap a (possibly opaque) PSA key instead of + * storing and manipulating the key material directly. + * + * \param ctx The context to initialize. It must be empty (type NONE). + * \param key The PSA key to wrap, which must hold an ECC key pair + * (see notes below). + * + * \note The wrapped key must remain valid as long as the + * wrapping PK context is in use, that is at least between + * the point this function is called and the point + * mbedtls_pk_free() is called on this context. The wrapped + * key might then be independently used or destroyed. + * + * \note This function is currently only available for ECC key + * pairs (that is, ECC keys containing private key material). + * Support for other key types may be added later. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input + * (context already used, invalid key identifier). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an + * ECC key pair. + * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, + const psa_key_id_t key ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used. + * This can be #MBEDTLS_MD_NONE if the signature algorithm + * does not rely on a hash algorithm (non-deterministic + * ECDSA, RSA PKCS#1 v1.5). + * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then + * \p hash is the DigestInfo structure used by RFC 8017 + * §9.2 steps 3–6. If \p md_alg is a valid hash + * algorithm then \p hash is the digest itself, and this + * function calculates the DigestInfo encoding internally. + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(). + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note \p f_rng is used for padding generation. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return \c 0 on success (keys were checked and match each other). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not + * be checked - in that case they may or may not match. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. + * \return Another non-zero value if the keys do not match. + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Turn an EC key into an opaque one. + * + * \warning This is a temporary utility function for tests. It might + * change or be removed at any time without notice. + * + * \note Only ECDSA keys are supported so far. Signing with the + * specified hash is the only allowed use of that key. + * + * \param pk Input: the EC key to import to a PSA key. + * Output: a PK context wrapping that PSA key. + * \param key Output: a PSA key identifier. + * It's the caller's responsibility to call + * psa_destroy_key() on that key identifier after calling + * mbedtls_pk_free() on the PK context. + * \param hash_alg The hash algorithm to allow for use with that key. + * + * \return \c 0 if successful. + * \return An Mbed TLS error code otherwise. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_id_t *key, + psa_algorithm_t hash_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pkcs12.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pkcs12.h new file mode 100644 index 00000000..1b87aea9 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pkcs12.h @@ -0,0 +1,117 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" +#include "mbedtls/cipher.h" +#include "mbedtls/asn1.h" + +#include + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 +/** Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 +/** PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure + * \param mode either #MBEDTLS_PKCS12_PBE_ENCRYPT or + * #MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd Latin1-encoded password used. This may only be \c NULL when + * \p pwdlen is 0. No null terminator should be used. + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an initialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length of buffer to fill + * \param pwd The password to use. For compliance with PKCS#12 §B.1, this + * should be a BMPString, i.e. a Unicode string where each + * character is encoded as 2 bytes in big-endian order, with + * no byte order mark and with a null terminator (i.e. the + * last two bytes should be 0x00 0x00). + * \param pwdlen length of the password (may be 0). + * \param salt Salt buffer to use This may only be \c NULL when + * \p saltlen is 0. + * \param saltlen length of the salt (may be zero) + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be + * #MBEDTLS_PKCS12_DERIVE_KEY, #MBEDTLS_PKCS12_DERIVE_IV or + * #MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pkcs5.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pkcs5.h new file mode 100644 index 00000000..71d716be --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/pkcs5.h @@ -0,0 +1,107 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/md.h" + +#include +#include + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 +/** Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 +/** Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform.h new file mode 100644 index 00000000..277a85c7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform.h @@ -0,0 +1,411 @@ +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +/* The older Microsoft Windows common runtime provides non-conforming + * implementations of some standard library functions, including snprintf + * and vsnprintf. This affects MSVC and MinGW builds. + */ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF +#endif + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for vsnprintf + * + * The vsnprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ); +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#include +extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg ); + +/** + * \brief Set your own snprintf function pointer + * + * \param vsnprintf_func The \c vsnprintf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, va_list arg ) ); +#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO +#else +#define mbedtls_vsnprintf vsnprintf +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char MBEDTLS_PRIVATE(dummy); /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform_time.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform_time.h new file mode 100644 index 00000000..8d4b95d1 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform_time.h @@ -0,0 +1,76 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#include "mbedtls/build_info.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform_util.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform_util.h new file mode 100644 index 00000000..5d2fefc3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/platform_util.h @@ -0,0 +1,207 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#include "mbedtls/build_info.h" + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_time.h" +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* Implementation of the check-return facility. + * See the user documentation in mbedtls_config.h. + * + * Do not use this macro directly to annotate function: instead, + * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL + * depending on how important it is to check the return value. + */ +#if !defined(MBEDTLS_CHECK_RETURN) +#if defined(__GNUC__) +#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) +#elif defined(_MSC_VER) && _MSC_VER >= 1700 +#include +#define MBEDTLS_CHECK_RETURN _Check_return_ +#else +#define MBEDTLS_CHECK_RETURN +#endif +#endif + +/** Critical-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that its return value should be checked in all applications. + * Omitting the check is very likely to indicate a bug in the application + * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN + * is implemented for the compiler in use. + * + * \note The use of this macro is a work in progress. + * This macro may be added to more functions in the future. + * Such an extension is not considered an API break, provided that + * there are near-unavoidable circumstances under which the function + * can fail. For example, signature/MAC/AEAD verification functions, + * and functions that require a random generator, are considered + * return-check-critical. + */ +#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN + +/** Ordinary-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that its return value should be generally be checked in portable + * applications. Omitting the check will result in a compile-time warning if + * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and + * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration. + * + * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value + * of a function that is annotated with #MBEDTLS_CHECK_RETURN. + * + * \note The use of this macro is a work in progress. + * This macro will be added to more functions in the future. + * Eventually this should appear before most functions returning + * an error code (as \c int in the \c mbedtls_xxx API or + * as ::psa_status_t in the \c psa_xxx API). + */ +#if defined(MBEDTLS_CHECK_RETURN_WARNING) +#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN +#else +#define MBEDTLS_CHECK_RETURN_TYPICAL +#endif + +/** Benign-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that it is rarely useful to check its return value. + * + * This macro has an empty expansion. It exists for documentation purposes: + * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function + * has been analyzed for return-check usefuless, whereas the lack of + * an annotation indicates that the function has not been analyzed and its + * return-check usefulness is unknown. + */ +#define MBEDTLS_CHECK_RETURN_OPTIONAL + +/** \def MBEDTLS_IGNORE_RETURN + * + * Call this macro with one argument, a function call, to suppress a warning + * from #MBEDTLS_CHECK_RETURN due to that function call. + */ +#if !defined(MBEDTLS_IGNORE_RETURN) +/* GCC doesn't silence the warning with just (void)(result). + * (void)!(result) is known to work up at least up to GCC 10, as well + * as with Clang and MSVC. + * + * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html + * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 + */ +#define MBEDTLS_IGNORE_RETURN(result) ( (void) !( result ) ) +#endif + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/poly1305.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/poly1305.h new file mode 100644 index 00000000..6657aa2e --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/poly1305.h @@ -0,0 +1,181 @@ +/** + * \file poly1305.h + * + * \brief This file contains Poly1305 definitions and functions. + * + * Poly1305 is a one-time message authenticator that can be used to + * authenticate messages. Poly1305-AES was created by Daniel + * Bernstein https://cr.yp.to/mac/poly1305-20050329.pdf The generic + * Poly1305 algorithm (not tied to AES) was also standardized in RFC + * 7539. + * + * \author Daniel King + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_POLY1305_H +#define MBEDTLS_POLY1305_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** Invalid input parameter(s). */ +#define MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA -0x0057 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_POLY1305_ALT) + +typedef struct mbedtls_poly1305_context +{ + uint32_t MBEDTLS_PRIVATE(r)[4]; /** The value for 'r' (low 128 bits of the key). */ + uint32_t MBEDTLS_PRIVATE(s)[4]; /** The value for 's' (high 128 bits of the key). */ + uint32_t MBEDTLS_PRIVATE(acc)[5]; /** The accumulator number. */ + uint8_t MBEDTLS_PRIVATE(queue)[16]; /** The current partial block of data. */ + size_t MBEDTLS_PRIVATE(queue_len); /** The number of bytes stored in 'queue'. */ +} +mbedtls_poly1305_context; + +#else /* MBEDTLS_POLY1305_ALT */ +#include "poly1305_alt.h" +#endif /* MBEDTLS_POLY1305_ALT */ + +/** + * \brief This function initializes the specified Poly1305 context. + * + * It must be the first API called before using + * the context. + * + * It is usually followed by a call to + * \c mbedtls_poly1305_starts(), then one or more calls to + * \c mbedtls_poly1305_update(), then one call to + * \c mbedtls_poly1305_finish(), then finally + * \c mbedtls_poly1305_free(). + * + * \param ctx The Poly1305 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function releases and clears the specified + * Poly1305 context. + * + * \param ctx The Poly1305 context to clear. This may be \c NULL, in which + * case this function is a no-op. If it is not \c NULL, it must + * point to an initialized Poly1305 context. + */ +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ); + +/** + * \brief This function sets the one-time authentication key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param ctx The Poly1305 context to which the key should be bound. + * This must be initialized. + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ); + +/** + * \brief This functions feeds an input buffer into an ongoing + * Poly1305 computation. + * + * It is called between \c mbedtls_cipher_poly1305_starts() and + * \c mbedtls_cipher_poly1305_finish(). + * It can be called repeatedly to process a stream of data. + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function generates the Poly1305 Message + * Authentication Code (MAC). + * + * \param ctx The Poly1305 context to use for the Poly1305 operation. + * This must be initialized and bound to a key. + * \param mac The buffer to where the MAC is written. This must + * be a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ); + +/** + * \brief This function calculates the Poly1305 MAC of the input + * buffer with the provided key. + * + * \warning The key must be unique and unpredictable for each + * invocation of Poly1305. + * + * \param key The buffer containing the \c 32 Byte (\c 256 Bit) key. + * \param ilen The length of the input data in Bytes. + * Any value is accepted. + * \param input The buffer holding the input data. + * This pointer can be \c NULL if `ilen == 0`. + * \param mac The buffer to where the MAC is written. This must be + * a writable buffer of length \c 16 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief The Poly1305 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_poly1305_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_POLY1305_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/private_access.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/private_access.h new file mode 100644 index 00000000..67e17846 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/private_access.h @@ -0,0 +1,34 @@ + /** + * \file private_access.h + * + * \brief Macro wrapper for struct's memebrs. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_PRIVATE_ACCESS_H +#define MBEDTLS_PRIVATE_ACCESS_H + +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_PRIVATE(member) private_##member +#else +#define MBEDTLS_PRIVATE(member) member +#endif + +#endif /* MBEDTLS_PRIVATE_ACCESS_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/psa_util.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/psa_util.h new file mode 100644 index 00000000..c54c035c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/psa_util.h @@ -0,0 +1,514 @@ +/** + * \file psa_util.h + * + * \brief Utility functions for the use of the PSA Crypto library. + * + * \warning This function is not part of the public API and may + * change at any time. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_PSA_UTIL_H +#define MBEDTLS_PSA_UTIL_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/md.h" +#include "mbedtls/pk.h" +#include "mbedtls/oid.h" +#include "mbedtls/error.h" + +#include + +/* Translations for symmetric crypto. */ + +static inline psa_key_type_t mbedtls_psa_translate_cipher_type( + mbedtls_cipher_type_t cipher ) +{ + switch( cipher ) + { + case MBEDTLS_CIPHER_AES_128_CCM: + case MBEDTLS_CIPHER_AES_192_CCM: + case MBEDTLS_CIPHER_AES_256_CCM: + case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_AES_128_GCM: + case MBEDTLS_CIPHER_AES_192_GCM: + case MBEDTLS_CIPHER_AES_256_GCM: + case MBEDTLS_CIPHER_AES_128_CBC: + case MBEDTLS_CIPHER_AES_192_CBC: + case MBEDTLS_CIPHER_AES_256_CBC: + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + return( PSA_KEY_TYPE_AES ); + + /* ARIA not yet supported in PSA. */ + /* case MBEDTLS_CIPHER_ARIA_128_CCM: + case MBEDTLS_CIPHER_ARIA_192_CCM: + case MBEDTLS_CIPHER_ARIA_256_CCM: + case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG: + case MBEDTLS_CIPHER_ARIA_128_GCM: + case MBEDTLS_CIPHER_ARIA_192_GCM: + case MBEDTLS_CIPHER_ARIA_256_GCM: + case MBEDTLS_CIPHER_ARIA_128_CBC: + case MBEDTLS_CIPHER_ARIA_192_CBC: + case MBEDTLS_CIPHER_ARIA_256_CBC: + return( PSA_KEY_TYPE_ARIA ); */ + + default: + return( 0 ); + } +} + +static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode( + mbedtls_cipher_mode_t mode, size_t taglen ) +{ + switch( mode ) + { + case MBEDTLS_MODE_ECB: + return( PSA_ALG_ECB_NO_PADDING ); + case MBEDTLS_MODE_GCM: + return( PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, taglen ) ); + case MBEDTLS_MODE_CCM: + return( PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, taglen ) ); + case MBEDTLS_MODE_CCM_STAR_NO_TAG: + return PSA_ALG_CCM_STAR_NO_TAG; + case MBEDTLS_MODE_CBC: + if( taglen == 0 ) + return( PSA_ALG_CBC_NO_PADDING ); + else + return( 0 ); + default: + return( 0 ); + } +} + +static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation( + mbedtls_operation_t op ) +{ + switch( op ) + { + case MBEDTLS_ENCRYPT: + return( PSA_KEY_USAGE_ENCRYPT ); + case MBEDTLS_DECRYPT: + return( PSA_KEY_USAGE_DECRYPT ); + default: + return( 0 ); + } +} + +/* Translations for hashing. */ + +static inline psa_algorithm_t mbedtls_psa_translate_md( mbedtls_md_type_t md_alg ) +{ + switch( md_alg ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( PSA_ALG_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( PSA_ALG_SHA_1 ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( PSA_ALG_SHA_224 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( PSA_ALG_SHA_256 ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( PSA_ALG_SHA_384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( PSA_ALG_SHA_512 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( PSA_ALG_RIPEMD160 ); +#endif + case MBEDTLS_MD_NONE: + return( 0 ); + default: + return( 0 ); + } +} + +/* Translations for ECC. */ + +static inline int mbedtls_psa_get_ecc_oid_from_id( + psa_ecc_family_t curve, size_t bits, + char const **oid, size_t *oid_len ) +{ + switch( curve ) + { + case PSA_ECC_FAMILY_SECP_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_SECP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case 521: + *oid = MBEDTLS_OID_EC_GRP_SECP521R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP521R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + } + break; + case PSA_ECC_FAMILY_SECP_K1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case 192: + *oid = MBEDTLS_OID_EC_GRP_SECP192K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP192K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case 224: + *oid = MBEDTLS_OID_EC_GRP_SECP224K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP224K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_SECP256K1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_SECP256K1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + } + break; + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch( bits ) + { +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case 256: + *oid = MBEDTLS_OID_EC_GRP_BP256R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP256R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case 384: + *oid = MBEDTLS_OID_EC_GRP_BP384R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP384R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case 512: + *oid = MBEDTLS_OID_EC_GRP_BP512R1; + *oid_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_EC_GRP_BP512R1 ); + return( 0 ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + } + break; + } + (void) oid; + (void) oid_len; + return( -1 ); +} + +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH 1 + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 521 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 192 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 224 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 256 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 384 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#if MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH < ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#undef MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH +#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH ( 2 * ( ( 512 + 7 ) / 8 ) + 1 ) +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + + +/* Translations for PK layer */ + +static inline int mbedtls_psa_err_translate_pk( psa_status_t status ) +{ + switch( status ) + { + case PSA_SUCCESS: + return( 0 ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + case PSA_ERROR_INSUFFICIENT_ENTROPY: + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + case PSA_ERROR_BAD_STATE: + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + /* All other failures */ + case PSA_ERROR_COMMUNICATION_FAILURE: + case PSA_ERROR_HARDWARE_FAILURE: + case PSA_ERROR_CORRUPTION_DETECTED: + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + default: /* We return the same as for the 'other failures', + * but list them separately nonetheless to indicate + * which failure conditions we have considered. */ + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + } +} + +/* Translations for ECC */ + +/* This function transforms an ECC group identifier from + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * into a PSA ECC group identifier. */ +#if defined(MBEDTLS_ECP_C) +static inline psa_key_type_t mbedtls_psa_parse_tls_ecc_group( + uint16_t tls_ecc_grp_reg_id, size_t *bits ) +{ + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( tls_ecc_grp_reg_id ); + if( curve_info == NULL ) + return( 0 ); + return( PSA_KEY_TYPE_ECC_KEY_PAIR( + mbedtls_ecc_group_to_psa( curve_info->grp_id, bits ) ) ); +} +#endif /* MBEDTLS_ECP_C */ + +/* This function takes a buffer holding an EC public key + * exported through psa_export_public_key(), and converts + * it into an ECPoint structure to be put into a ClientKeyExchange + * message in an ECDHE exchange. + * + * Both the present and the foreseeable future format of EC public keys + * used by PSA have the ECPoint structure contained in the exported key + * as a subbuffer, and the function merely selects this subbuffer instead + * of making a copy. + */ +static inline int mbedtls_psa_tls_psa_ec_to_ecpoint( unsigned char *src, + size_t srclen, + unsigned char **dst, + size_t *dstlen ) +{ + *dst = src; + *dstlen = srclen; + return( 0 ); +} + +/* This function takes a buffer holding an ECPoint structure + * (as contained in a TLS ServerKeyExchange message for ECDHE + * exchanges) and converts it into a format that the PSA key + * agreement API understands. + */ +static inline int mbedtls_psa_tls_ecpoint_to_psa_ec( unsigned char const *src, + size_t srclen, + unsigned char *dst, + size_t dstlen, + size_t *olen ) +{ + if( srclen > dstlen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( dst, src, srclen ); + *olen = srclen; + return( 0 ); +} + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* Expose whatever RNG the PSA subsystem uses to applications using the + * mbedtls_xxx API. The declarations and definitions here need to be + * consistent with the implementation in library/psa_crypto_random_impl.h. + * See that file for implementation documentation. */ +#if defined(MBEDTLS_PSA_CRYPTO_C) + +/* The type of a `f_rng` random generator function that many library functions + * take. + * + * This type name is not part of the Mbed TLS stable API. It may be renamed + * or moved without warning. + */ +typedef int mbedtls_f_rng_t( void *p_rng, unsigned char *output, size_t output_size ); + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + +/** The random generator function for the PSA subsystem. + * + * This function is suitable as the `f_rng` random generator function + * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE + * to obtain the \p p_rng parameter. + * + * The implementation of this function depends on the configuration of the + * library. + * + * \note Depending on the configuration, this may be a function or + * a pointer to a function. + * + * \note This function may only be used if the PSA crypto subsystem is active. + * This means that you must call psa_crypto_init() before any call to + * this function, and you must not call this function after calling + * mbedtls_psa_crypto_free(). + * + * \param p_rng The random generator context. This must be + * #MBEDTLS_PSA_RANDOM_STATE. No other state is + * supported. + * \param output The buffer to fill. It must have room for + * \c output_size bytes. + * \param output_size The number of bytes to write to \p output. + * This function may fail if \p output_size is too + * large. It is guaranteed to accept any output size + * requested by Mbed TLS library functions. The + * maximum request size depends on the library + * configuration. + * + * \return \c 0 on success. + * \return An `MBEDTLS_ERR_ENTROPY_xxx`, + * `MBEDTLS_ERR_PLATFORM_xxx, + * `MBEDTLS_ERR_CTR_DRBG_xxx` or + * `MBEDTLS_ERR_HMAC_DRBG_xxx` on error. + */ +int mbedtls_psa_get_random( void *p_rng, + unsigned char *output, + size_t output_size ); + +/** The random generator state for the PSA subsystem. + * + * This macro expands to an expression which is suitable as the `p_rng` + * random generator state parameter of many `mbedtls_xxx` functions. + * It must be used in combination with the random generator function + * mbedtls_psa_get_random(). + * + * The implementation of this macro depends on the configuration of the + * library. Do not make any assumption on its nature. + */ +#define MBEDTLS_PSA_RANDOM_STATE NULL + +#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t; +static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random; +#elif defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t; +static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random; +#endif +extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; + +#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state + +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#endif /* MBEDTLS_PSA_UTIL_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ripemd160.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ripemd160.h new file mode 100644 index 00000000..9132a83b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ripemd160.h @@ -0,0 +1,149 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RIPEMD160_ALT) +// Regular implementation +// + +/** + * \brief RIPEMD-160 context structure + */ +typedef struct mbedtls_ripemd160_context +{ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< number of bytes processed */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< intermediate digest state */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< data block being processed */ +} +mbedtls_ripemd160_context; + +#else /* MBEDTLS_RIPEMD160_ALT */ +#include "ripemd160_alt.h" +#endif /* MBEDTLS_RIPEMD160_ALT */ + +/** + * \brief Initialize RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be initialized + */ +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clear RIPEMD-160 context + * + * \param ctx RIPEMD-160 context to be cleared + */ +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ); + +/** + * \brief Clone (the state of) an RIPEMD-160 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ); + +/** + * \brief RIPEMD-160 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + */ +int mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ); + +/** + * \brief RIPEMD-160 process buffer + * + * \param ctx RIPEMD-160 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + */ +int mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief RIPEMD-160 final digest + * + * \param ctx RIPEMD-160 context + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ); + +/** + * \brief RIPEMD-160 process data block (internal use only) + * + * \param ctx RIPEMD-160 context + * \param data buffer holding one block of data + * + * \return 0 if successful + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ); + +/** + * \brief Output = RIPEMD-160( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output RIPEMD-160 checksum result + * + * \return 0 if successful + */ +int mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_ripemd160_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_ripemd160.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/rsa.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/rsa.h new file mode 100644 index 00000000..d03c31d7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/rsa.h @@ -0,0 +1,1128 @@ +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/bignum.h" +#include "mbedtls/md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* + * RSA Error codes + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 +/** Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 +/** Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 +/** Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 +/** The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 +/** The private key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 +/** The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 +/** The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 +/** The random generator failed to generate non-zeros. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 + +/* + * RSA constants + */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + */ +typedef struct mbedtls_rsa_context +{ + int MBEDTLS_PRIVATE(ver); /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + size_t MBEDTLS_PRIVATE(len); /*!< The size of \p N in Bytes. */ + + mbedtls_mpi MBEDTLS_PRIVATE(N); /*!< The public modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(E); /*!< The public exponent. */ + + mbedtls_mpi MBEDTLS_PRIVATE(D); /*!< The private exponent. */ + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The first prime factor. */ + mbedtls_mpi MBEDTLS_PRIVATE(Q); /*!< The second prime factor. */ + + mbedtls_mpi MBEDTLS_PRIVATE(DP); /*!< D % (P - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(DQ); /*!< D % (Q - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(QP); /*!< 1 / (Q % P). */ + + mbedtls_mpi MBEDTLS_PRIVATE(RN); /*!< cached R^2 mod N. */ + + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< cached R^2 mod P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RQ); /*!< cached R^2 mod Q. */ + + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The cached blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The cached un-blinding value. */ + + int MBEDTLS_PRIVATE(padding); /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int MBEDTLS_PRIVATE(hash_id); /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized iff ver != 0. */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note This function initializes the padding and the hash + * identifier to respectively #MBEDTLS_RSA_PKCS_V15 and + * #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more + * information about those parameters. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private + * key operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overridden by calling specific + * \c mbedtls_rsa_rsaes_xxx or \c mbedtls_rsa_rsassa_xxx + * functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier for PSS or OAEP, if \p padding is + * #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this + * function but may be not suitable for some operations. + * Ignored if \p padding is #MBEDTLS_RSA_PKCS_V15. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING failure: + * \p padding or \p hash_id is invalid. + */ +int mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id ); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This is mandatory and must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is mandatory. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is used for padding generation + * and it is mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng doesn't need a context argument. + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is mandatory and used for + * padding generation. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and is mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context. + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. This is mandatory and + * must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * + * \note This function enforces that the provided salt length complies + * with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1 + * step 3. The constraint is that the hash length plus the salt + * length plus 2 bytes must be at most the key length. If this + * constraint is not met, this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It is mandatory and must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param saltlen The length of the salt that should be used. + * If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use + * the largest possible salt length up to the hash length, + * which is the largest permitted by some standards including + * FIPS 186-4 §5.5. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It is mandatory and must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. If the \c hash_id set in \p ctx by + * mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \p md_alg + * parameter is used. + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \c hash_id set in \p ctx by mbedtls_rsa_set_padding() is + * ignored. + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param mgf1_hash_id The message digest algorithm used for the + * verification operation and the mask generation + * function (MGF1). For more details on the encoding + * operation and the mask generation function, consult + * RFC-3447: Public-Key Cryptography Standards + * (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha1.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha1.h new file mode 100644 index 00000000..6b55174a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha1.h @@ -0,0 +1,232 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** SHA-1 input data was malformed. */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha256.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha256.h new file mode 100644 index 00000000..0cbbac11 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha256.h @@ -0,0 +1,195 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** SHA-256 input data was malformed. */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ + int MBEDTLS_PRIVATE(is224); /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 bytes + * for SHA-256, \c 28 bytes for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char *output ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 bytes + * for SHA-256, \c 28 bytes for SHA-224. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224 ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha512.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha512.h new file mode 100644 index 00000000..48901cc3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/sha512.h @@ -0,0 +1,205 @@ +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +/** SHA-512 input data was malformed. */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint64_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[128]; /*!< The data block being processed. */ +#if defined(MBEDTLS_SHA384_C) + int MBEDTLS_PRIVATE(is384); /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +#endif +} +mbedtls_sha512_context; + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA384_C is not defined, + * \p is384 must be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 bytes + * for SHA-512, \c 48 bytes for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char *output ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * This function is for internal use only. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 bytes + * for SHA-512, \c 48 bytes for SHA-384. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA384_C is not defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384 ); + +#if defined(MBEDTLS_SELF_TEST) + + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl.h new file mode 100644 index 00000000..072ebbe4 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl.h @@ -0,0 +1,4526 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SSL_H +#define MBEDTLS_SSL_H +#include "mbedtls/platform_util.h" +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" + +#include "mbedtls/ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due + * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap + * in functionality that access to ecdh_ctx structure is needed for + * MBEDTLS_ECDSA_C which does not seem correct. + */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdh.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/* + * SSL Error codes + */ +/** A cryptographic operation is in progress. Try again later. */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000 +/** The requested feature is not available. */ +#define MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100 +/** Verification of the message MAC failed. */ +#define MBEDTLS_ERR_SSL_INVALID_MAC -0x7180 +/** An invalid SSL record was received. */ +#define MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200 +/** The connection indicated an EOF. */ +#define MBEDTLS_ERR_SSL_CONN_EOF -0x7280 +/** A message could not be parsed due to a syntactic error. */ +#define MBEDTLS_ERR_SSL_DECODE_ERROR -0x7300 +/* Error space gap */ +/** No RNG was provided to the SSL module. */ +#define MBEDTLS_ERR_SSL_NO_RNG -0x7400 +/** No client certification received from the client, but required by the authentication mode. */ +#define MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480 +/** Client received an extended server hello containing an unsupported extension */ +#define MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION -0x7500 +/** No ALPN protocols supported that the client advertises */ +#define MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL -0x7580 +/** The own private key or pre-shared key is not set, but needed. */ +#define MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600 +/** No CA Chain is set, but required to operate. */ +#define MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680 +/** An unexpected message was received from our peer. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700 +/** A fatal alert message was received from our peer. */ +#define MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780 +/** No server could be identified matching the client's SNI. */ +#define MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME -0x7800 +/** The peer notified us that the connection is going to be closed. */ +#define MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880 +/* Error space gap */ +/* Error space gap */ +/** Processing of the Certificate handshake message failed. */ +#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00 +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/** Memory allocation failed */ +#define MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00 +/** Hardware acceleration function returned with error */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80 +/** Hardware acceleration function skipped / left alone data */ +#define MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80 +/** Handshake protocol not within min/max boundaries */ +#define MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION -0x6E80 +/** The handshake negotiation failed. */ +#define MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE -0x6E00 +/** Session ticket has expired. */ +#define MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 +/** Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */ +#define MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 +/** Unknown identity received (eg, PSK identity) */ +#define MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80 +/** Internal error (eg, unexpected failure in lower-level module) */ +#define MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00 +/** A counter would wrap (eg, too many messages exchanged). */ +#define MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80 +/** Unexpected message at ServerHello in renegotiation. */ +#define MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00 +/** DTLS client must retry for hello verification */ +#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 +/** A buffer is too small to receive or write a message */ +#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 +/* Error space gap */ +/** No data of requested type currently available on underlying transport. */ +#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 +/** Connection requires a write call. */ +#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 +/** The operation timed out. */ +#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 +/** The client initiated a reconnect from the same port. */ +#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 +/** Record header looks valid but is not expected. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 +/** The alert message received indicates a non-fatal error. */ +#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 +/** A field in a message was incorrect or inconsistent with other fields. */ +#define MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER -0x6600 +/** Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 +/** The asynchronous operation is not completed yet. */ +#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 +/** Internal-only message signaling that a message arrived early. */ +#define MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480 +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/* Error space gap */ +/** An encrypted DTLS-frame with an unexpected CID was received. */ +#define MBEDTLS_ERR_SSL_UNEXPECTED_CID -0x6000 +/** An operation failed due to an unexpected version or configuration. */ +#define MBEDTLS_ERR_SSL_VERSION_MISMATCH -0x5F00 +/** Invalid value in SSL config */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 + +/* + * TLS 1.3 NamedGroup values + * + * From RF 8446 + * enum { + * // Elliptic Curve Groups (ECDHE) + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * // Finite Field Groups (DHE) + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * // Reserved Code Points + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * + */ + +/* Elliptic Curve Groups (ECDHE) */ +#define MBEDTLS_SSL_IANA_TLS_GROUP_NONE 0 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1 0x0012 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1 0x0013 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1 0x0014 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1 0x0015 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1 0x0016 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 0x0017 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 0x0018 +#define MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 0x0019 +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1 0x001A +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1 0x001B +#define MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1 0x001C +#define MBEDTLS_SSL_IANA_TLS_GROUP_X25519 0x001D +#define MBEDTLS_SSL_IANA_TLS_GROUP_X448 0x001E +/* Finite Field Groups (DHE) */ +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 0x0100 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072 0x0101 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096 0x0102 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144 0x0103 +#define MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192 0x0104 + +/* + * TLS 1.3 Key Exchange Modes + * + * Mbed TLS internal identifiers for use with the SSL configuration API + * mbedtls_ssl_conf_tls13_key_exchange_modes(). + */ + +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK ( 1u << 0 ) /*!< Pure-PSK TLS 1.3 key exchange, + * encompassing both externally agreed PSKs + * as well as resumption PSKs. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL ( 1u << 1 ) /*!< Pure-Ephemeral TLS 1.3 key exchanges, + * including for example ECDHE and DHE + * key exchanges. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ( 1u << 2 ) /*!< PSK-Ephemeral TLS 1.3 key exchanges, + * using both a PSK and an ephemeral + * key exchange. */ + +/* Convenience macros for sets of key exchanges. */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL \ + ( MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL ) /*!< All TLS 1.3 key exchanges */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL \ + ( MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) /*!< All PSK-based TLS 1.3 key exchanges */ +#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL \ + ( MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL | \ + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) /*!< All ephemeral TLS 1.3 key exchanges */ + +/* + * Various constants + */ + +/* These are the high an low bytes of ProtocolVersion as defined by: + * - RFC 5246: ProtocolVersion version = { 3, 3 }; // TLS v1.2 + * - RFC 8446: see section 4.2.1 + */ +#define MBEDTLS_SSL_MAJOR_VERSION_3 3 +#define MBEDTLS_SSL_MINOR_VERSION_3 3 /*!< TLS v1.2 */ +#define MBEDTLS_SSL_MINOR_VERSION_4 4 /*!< TLS v1.3 */ + +#define MBEDTLS_SSL_TRANSPORT_STREAM 0 /*!< TLS */ +#define MBEDTLS_SSL_TRANSPORT_DATAGRAM 1 /*!< DTLS */ + +#define MBEDTLS_SSL_MAX_HOST_NAME_LEN 255 /*!< Maximum host name defined in RFC 1035 */ +#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ + +#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ + +/* RFC 6066 section 4, see also mfl_code_to_length in ssl_tls.c + * NONE must be zero so that memset()ing structure to zero works */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_NONE 0 /*!< don't use this extension */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_512 1 /*!< MaxFragmentLength 2^9 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_1024 2 /*!< MaxFragmentLength 2^10 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_2048 3 /*!< MaxFragmentLength 2^11 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_4096 4 /*!< MaxFragmentLength 2^12 */ +#define MBEDTLS_SSL_MAX_FRAG_LEN_INVALID 5 /*!< first invalid value */ + +#define MBEDTLS_SSL_IS_CLIENT 0 +#define MBEDTLS_SSL_IS_SERVER 1 + +#define MBEDTLS_SSL_EXTENDED_MS_DISABLED 0 +#define MBEDTLS_SSL_EXTENDED_MS_ENABLED 1 + +#define MBEDTLS_SSL_CID_DISABLED 0 +#define MBEDTLS_SSL_CID_ENABLED 1 + +#define MBEDTLS_SSL_ETM_DISABLED 0 +#define MBEDTLS_SSL_ETM_ENABLED 1 + +#define MBEDTLS_SSL_COMPRESS_NULL 0 + +#define MBEDTLS_SSL_VERIFY_NONE 0 +#define MBEDTLS_SSL_VERIFY_OPTIONAL 1 +#define MBEDTLS_SSL_VERIFY_REQUIRED 2 +#define MBEDTLS_SSL_VERIFY_UNSET 3 /* Used only for sni_authmode */ + +#define MBEDTLS_SSL_LEGACY_RENEGOTIATION 0 +#define MBEDTLS_SSL_SECURE_RENEGOTIATION 1 + +#define MBEDTLS_SSL_RENEGOTIATION_DISABLED 0 +#define MBEDTLS_SSL_RENEGOTIATION_ENABLED 1 + +#define MBEDTLS_SSL_ANTI_REPLAY_DISABLED 0 +#define MBEDTLS_SSL_ANTI_REPLAY_ENABLED 1 + +#define MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED -1 +#define MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT 16 + +#define MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION 0 +#define MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION 1 +#define MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE 2 + +#define MBEDTLS_SSL_TRUNC_HMAC_DISABLED 0 +#define MBEDTLS_SSL_TRUNC_HMAC_ENABLED 1 +#define MBEDTLS_SSL_TRUNCATED_HMAC_LEN 10 /* 80 bits, rfc 6066 section 7 */ + +#define MBEDTLS_SSL_SESSION_TICKETS_DISABLED 0 +#define MBEDTLS_SSL_SESSION_TICKETS_ENABLED 1 + +#define MBEDTLS_SSL_PRESET_DEFAULT 0 +#define MBEDTLS_SSL_PRESET_SUITEB 2 + +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED 1 +#define MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED 0 + +#define MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED 0 +#define MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED 1 + +#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT 1 +#define MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER 0 + +/* + * Default range for DTLS retransmission timer value, in milliseconds. + * RFC 6347 4.2.4.1 says from 1 second to 60 seconds. + */ +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN 1000 +#define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX 60000 + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +/* + * Maximum fragment length in bytes, + * determines the size of each of the two internal I/O buffers. + * + * Note: the RFC defines the default size of SSL / TLS messages. If you + * change the value here, other clients / servers may not be able to + * communicate with you anymore. Only change this value if you control + * both sides of the connection and have it reduced at both sides, or + * if you're using the Max Fragment Length extension and you know all your + * peers are using it too! + */ +#if !defined(MBEDTLS_SSL_IN_CONTENT_LEN) +#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#endif + +#if !defined(MBEDTLS_SSL_OUT_CONTENT_LEN) +#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 +#endif + +/* + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + */ +#if !defined(MBEDTLS_SSL_DTLS_MAX_BUFFERING) +#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 +#endif + +/* + * Maximum length of CIDs for incoming and outgoing messages. + */ +#if !defined(MBEDTLS_SSL_CID_IN_LEN_MAX) +#define MBEDTLS_SSL_CID_IN_LEN_MAX 32 +#endif + +#if !defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) +#define MBEDTLS_SSL_CID_OUT_LEN_MAX 32 +#endif + +#if !defined(MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) +#define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16 +#endif + +/* \} name SECTION: Module settings */ + +/* + * Length of the verify data for secure renegotiation + */ +#define MBEDTLS_SSL_VERIFY_DATA_MAX_LEN 12 + +/* + * Signaling ciphersuite values (SCSV) + */ +#define MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO 0xFF /**< renegotiation info ext */ + +/* + * Supported Signature and Hash algorithms (For TLS 1.2) + * RFC 5246 section 7.4.1.4.1 + */ +#define MBEDTLS_SSL_HASH_NONE 0 +#define MBEDTLS_SSL_HASH_MD5 1 +#define MBEDTLS_SSL_HASH_SHA1 2 +#define MBEDTLS_SSL_HASH_SHA224 3 +#define MBEDTLS_SSL_HASH_SHA256 4 +#define MBEDTLS_SSL_HASH_SHA384 5 +#define MBEDTLS_SSL_HASH_SHA512 6 + +#define MBEDTLS_SSL_SIG_ANON 0 +#define MBEDTLS_SSL_SIG_RSA 1 +#define MBEDTLS_SSL_SIG_ECDSA 3 + +/* + * TLS 1.3 signature algorithms + * RFC 8446, Section 4.2.2 + */ + +/* RSASSA-PKCS1-v1_5 algorithms */ +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256 0x0401 +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384 0x0501 +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512 0x0601 + +/* ECDSA algorithms */ +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256 0x0403 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384 0x0503 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512 0x0603 + +/* RSASSA-PSS algorithms with public key OID rsaEncryption */ +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256 0x0804 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384 0x0805 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512 0x0806 + +/* EdDSA algorithms */ +#define MBEDTLS_TLS1_3_SIG_ED25519 0x0807 +#define MBEDTLS_TLS1_3_SIG_ED448 0x0808 + +/* RSASSA-PSS algorithms with public key OID RSASSA-PSS */ +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA256 0x0809 +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA384 0x080A +#define MBEDTLS_TLS1_3_SIG_RSA_PSS_PSS_SHA512 0x080B + +/* LEGACY ALGORITHMS */ +#define MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA1 0x0201 +#define MBEDTLS_TLS1_3_SIG_ECDSA_SHA1 0x0203 + +#define MBEDTLS_TLS1_3_SIG_NONE 0x0 + +/* + * Client Certificate Types + * RFC 5246 section 7.4.4 plus RFC 4492 section 5.5 + */ +#define MBEDTLS_SSL_CERT_TYPE_RSA_SIGN 1 +#define MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN 64 + +/* + * Message, alert and handshake types + */ +#define MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC 20 +#define MBEDTLS_SSL_MSG_ALERT 21 +#define MBEDTLS_SSL_MSG_HANDSHAKE 22 +#define MBEDTLS_SSL_MSG_APPLICATION_DATA 23 +#define MBEDTLS_SSL_MSG_CID 25 + +#define MBEDTLS_SSL_ALERT_LEVEL_WARNING 1 +#define MBEDTLS_SSL_ALERT_LEVEL_FATAL 2 + +#define MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY 0 /* 0x00 */ +#define MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE 10 /* 0x0A */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC 20 /* 0x14 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED 21 /* 0x15 */ +#define MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW 22 /* 0x16 */ +#define MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE 30 /* 0x1E */ +#define MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE 40 /* 0x28 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_CERT 41 /* 0x29 */ +#define MBEDTLS_SSL_ALERT_MSG_BAD_CERT 42 /* 0x2A */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT 43 /* 0x2B */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED 44 /* 0x2C */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED 45 /* 0x2D */ +#define MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN 46 /* 0x2E */ +#define MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER 47 /* 0x2F */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA 48 /* 0x30 */ +#define MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED 49 /* 0x31 */ +#define MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR 50 /* 0x32 */ +#define MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR 51 /* 0x33 */ +#define MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION 60 /* 0x3C */ +#define MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION 70 /* 0x46 */ +#define MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY 71 /* 0x47 */ +#define MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR 80 /* 0x50 */ +#define MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK 86 /* 0x56 */ +#define MBEDTLS_SSL_ALERT_MSG_USER_CANCELED 90 /* 0x5A */ +#define MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION 100 /* 0x64 */ +#define MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT 110 /* 0x6E */ +#define MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME 112 /* 0x70 */ +#define MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY 115 /* 0x73 */ +#define MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL 120 /* 0x78 */ + +#define MBEDTLS_SSL_HS_HELLO_REQUEST 0 +#define MBEDTLS_SSL_HS_CLIENT_HELLO 1 +#define MBEDTLS_SSL_HS_SERVER_HELLO 2 +#define MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST 3 +#define MBEDTLS_SSL_HS_NEW_SESSION_TICKET 4 +#define MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS 8 // NEW IN TLS 1.3 +#define MBEDTLS_SSL_HS_CERTIFICATE 11 +#define MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE 12 +#define MBEDTLS_SSL_HS_CERTIFICATE_REQUEST 13 +#define MBEDTLS_SSL_HS_SERVER_HELLO_DONE 14 +#define MBEDTLS_SSL_HS_CERTIFICATE_VERIFY 15 +#define MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE 16 +#define MBEDTLS_SSL_HS_FINISHED 20 + +/* + * TLS extensions + */ +#define MBEDTLS_TLS_EXT_SERVERNAME 0 +#define MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME 0 + +#define MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH 1 + +#define MBEDTLS_TLS_EXT_TRUNCATED_HMAC 4 +#define MBEDTLS_TLS_EXT_STATUS_REQUEST 5 /* RFC 6066 TLS 1.2 and 1.3 */ + +#define MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES 10 +#define MBEDTLS_TLS_EXT_SUPPORTED_GROUPS 10 /* RFC 8422,7919 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS 11 + +#define MBEDTLS_TLS_EXT_SIG_ALG 13 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_USE_SRTP 14 +#define MBEDTLS_TLS_EXT_HEARTBEAT 15 /* RFC 6520 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_ALPN 16 + +#define MBEDTLS_TLS_EXT_SCT 18 /* RFC 6962 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_CLI_CERT_TYPE 19 /* RFC 7250 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_SERV_CERT_TYPE 20 /* RFC 7250 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_PADDING 21 /* RFC 7685 TLS 1.2 and 1.3 */ +#define MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC 22 /* 0x16 */ +#define MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET 0x0017 /* 23 */ + +#define MBEDTLS_TLS_EXT_SESSION_TICKET 35 + +#define MBEDTLS_TLS_EXT_PRE_SHARED_KEY 41 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_EARLY_DATA 42 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS 43 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_COOKIE 44 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES 45 /* RFC 8446 TLS 1.3 */ + +#define MBEDTLS_TLS_EXT_CERT_AUTH 47 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_OID_FILTERS 48 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_POST_HANDSHAKE_AUTH 49 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_SIG_ALG_CERT 50 /* RFC 8446 TLS 1.3 */ +#define MBEDTLS_TLS_EXT_KEY_SHARE 51 /* RFC 8446 TLS 1.3 */ + +/* The value of the CID extension is still TBD as of + * draft-ietf-tls-dtls-connection-id-05 + * (https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05). + * + * A future minor revision of Mbed TLS may change the default value of + * this option to match evolving standards and usage. + */ +#if !defined(MBEDTLS_TLS_EXT_CID) +#define MBEDTLS_TLS_EXT_CID 254 /* TBD */ +#endif + +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP 256 /* experimental */ + +#define MBEDTLS_TLS_EXT_RENEGOTIATION_INFO 0xFF01 + +/* + * Size defines + */ +#if !defined(MBEDTLS_PSK_MAX_LEN) +#define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */ +#endif + +/* Dummy type used only for its size */ +union mbedtls_ssl_premaster_secret +{ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + unsigned char _pms_rsa[48]; /* RFC 5246 8.1.1 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + unsigned char _pms_dhm[MBEDTLS_MPI_MAX_SIZE]; /* RFC 5246 8.1.2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + unsigned char _pms_ecdh[MBEDTLS_ECP_MAX_BYTES]; /* RFC 4492 5.10 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + unsigned char _pms_psk[4 + 2 * MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + unsigned char _pms_dhe_psk[4 + MBEDTLS_MPI_MAX_SIZE + + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 3 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + unsigned char _pms_rsa_psk[52 + MBEDTLS_PSK_MAX_LEN]; /* RFC 4279 4 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + unsigned char _pms_ecdhe_psk[4 + MBEDTLS_ECP_MAX_BYTES + + MBEDTLS_PSK_MAX_LEN]; /* RFC 5489 2 */ +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + unsigned char _pms_ecjpake[32]; /* Thread spec: SHA-256 output */ +#endif +}; + +#define MBEDTLS_PREMASTER_SIZE sizeof( union mbedtls_ssl_premaster_secret ) + +#define MBEDTLS_TLS1_3_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE + +/* Length in number of bytes of the TLS sequence number */ +#define MBEDTLS_SSL_SEQUENCE_NUMBER_LEN 8 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SSL state machine + */ +typedef enum +{ + MBEDTLS_SSL_HELLO_REQUEST, + MBEDTLS_SSL_CLIENT_HELLO, + MBEDTLS_SSL_SERVER_HELLO, + MBEDTLS_SSL_SERVER_CERTIFICATE, + MBEDTLS_SSL_SERVER_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_REQUEST, + MBEDTLS_SSL_SERVER_HELLO_DONE, + MBEDTLS_SSL_CLIENT_CERTIFICATE, + MBEDTLS_SSL_CLIENT_KEY_EXCHANGE, + MBEDTLS_SSL_CERTIFICATE_VERIFY, + MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_CLIENT_FINISHED, + MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC, + MBEDTLS_SSL_SERVER_FINISHED, + MBEDTLS_SSL_FLUSH_BUFFERS, + MBEDTLS_SSL_HANDSHAKE_WRAPUP, + MBEDTLS_SSL_HANDSHAKE_OVER, + MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET, + MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT, +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + MBEDTLS_SSL_ENCRYPTED_EXTENSIONS, + MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY, +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED, +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +} +mbedtls_ssl_states; + +/** + * \brief Callback type: send data on the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the send callback (typically a file descriptor) + * \param buf Buffer holding the data to send + * \param len Length of the data to send + * + * \return The callback must return the number of bytes sent if any, + * or a non-zero error code. + * If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_WRITE + * must be returned when the operation would block. + * + * \note The callback is allowed to send fewer bytes than requested. + * It must always return the number of bytes actually sent. + */ +typedef int mbedtls_ssl_send_t( void *ctx, + const unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network. + * + * \note That callback may be either blocking or non-blocking. + * + * \param ctx Context for the receive callback (typically a file + * descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * + * \returns If data has been received, the positive number of bytes received. + * \returns \c 0 if the connection has been closed. + * \returns If performing non-blocking I/O, \c MBEDTLS_ERR_SSL_WANT_READ + * must be returned when the operation would block. + * \returns Another negative error code on other kinds of failures. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_t( void *ctx, + unsigned char *buf, + size_t len ); + +/** + * \brief Callback type: receive data from the network, with timeout + * + * \note That callback must block until data is received, or the + * timeout delay expires, or the operation is interrupted by a + * signal. + * + * \param ctx Context for the receive callback (typically a file descriptor) + * \param buf Buffer to write the received data to + * \param len Length of the receive buffer + * \param timeout Maximum number of milliseconds to wait for data + * 0 means no timeout (potentially waiting forever) + * + * \return The callback must return the number of bytes received, + * or a non-zero error code: + * \c MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out, + * \c MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * + * \note The callback may receive fewer bytes than the length of the + * buffer. It must always return the number of bytes actually + * received and written to the buffer. + */ +typedef int mbedtls_ssl_recv_timeout_t( void *ctx, + unsigned char *buf, + size_t len, + uint32_t timeout ); +/** + * \brief Callback type: set a pair of timers/delays to watch + * + * \param ctx Context pointer + * \param int_ms Intermediate delay in milliseconds + * \param fin_ms Final delay in milliseconds + * 0 cancels the current timer. + * + * \note This callback must at least store the necessary information + * for the associated \c mbedtls_ssl_get_timer_t callback to + * return correct information. + * + * \note If using a event-driven style of programming, an event must + * be generated when the final delay is passed. The event must + * cause a call to \c mbedtls_ssl_handshake() with the proper + * SSL context to be scheduled. Care must be taken to ensure + * that at most one such call happens at a time. + * + * \note Only one timer at a time must be running. Calling this + * function while a timer is running must cancel it. Cancelled + * timers must not generate any event. + */ +typedef void mbedtls_ssl_set_timer_t( void * ctx, + uint32_t int_ms, + uint32_t fin_ms ); + +/** + * \brief Callback type: get status of timers/delays + * + * \param ctx Context pointer + * + * \return This callback must return: + * -1 if cancelled (fin_ms == 0), + * 0 if none of the delays have passed, + * 1 if only the intermediate delay has passed, + * 2 if the final delay has passed. + */ +typedef int mbedtls_ssl_get_timer_t( void * ctx ); + +/* Defined below */ +typedef struct mbedtls_ssl_session mbedtls_ssl_session; +typedef struct mbedtls_ssl_context mbedtls_ssl_context; +typedef struct mbedtls_ssl_config mbedtls_ssl_config; + +/* Defined in library/ssl_misc.h */ +typedef struct mbedtls_ssl_transform mbedtls_ssl_transform; +typedef struct mbedtls_ssl_handshake_params mbedtls_ssl_handshake_params; +typedef struct mbedtls_ssl_sig_hash_set_t mbedtls_ssl_sig_hash_set_t; +#if defined(MBEDTLS_X509_CRT_PARSE_C) +typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert; +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) +typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; +#endif + +/** + * \brief Callback type: server-side session cache getter + * + * The session cache is logically a key value store, with + * keys being session IDs and values being instances of + * mbedtls_ssl_session. + * + * This callback retrieves an entry in this key-value store. + * + * \param data The address of the session cache structure to query. + * \param session_id The buffer holding the session ID to query. + * \param session_id_len The length of \p session_id in Bytes. + * \param session The address of the session structure to populate. + * It is initialized with mbdtls_ssl_session_init(), + * and the callback must always leave it in a state + * where it can safely be freed via + * mbedtls_ssl_session_free() independent of the + * return code of this function. + * + * \return \c 0 on success + * \return A non-zero return value on failure. + * + */ +typedef int mbedtls_ssl_cache_get_t( void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session ); +/** + * \brief Callback type: server-side session cache setter + * + * The session cache is logically a key value store, with + * keys being session IDs and values being instances of + * mbedtls_ssl_session. + * + * This callback sets an entry in this key-value store. + * + * \param data The address of the session cache structure to modify. + * \param session_id The buffer holding the session ID to query. + * \param session_id_len The length of \p session_id in Bytes. + * \param session The address of the session to be stored in the + * session cache. + * + * \return \c 0 on success + * \return A non-zero return value on failure. + */ +typedef int mbedtls_ssl_cache_set_t( void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Callback type: start external signature operation. + * + * This callback is called during an SSL handshake to start + * a signature decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p hash if the value + * is needed for later processing, because the \p hash buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \note For RSA signatures, this function must produce output + * that is consistent with PKCS#1 v1.5 in the same way as + * mbedtls_rsa_pkcs1_sign(). Before the private key operation, + * apply the padding steps described in RFC 8017, section 9.2 + * "EMSA-PKCS1-v1_5" as follows. + * - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the DigestInfo to be + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 3, with `T = hash` and `tLen = hash_len`. + * - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5 + * encoding, treating \p hash as the hash to be encoded and + * padded. In other words, apply EMSA-PKCS1-v1_5 starting + * from step 2, with `digestAlgorithm` obtained by calling + * mbedtls_oid_get_oid_by_md() on \p md_alg. + * + * \note For ECDSA signatures, the output format is the DER encoding + * `Ecdsa-Sig-Value` defined in + * [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4). + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param md_alg Hash algorithm. + * \param hash Buffer containing the hash. This buffer is + * no longer valid when the function returns. + * \param hash_len Size of the \c hash buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ); + +/** + * \brief Callback type: start external decryption operation. + * + * This callback is called during an SSL handshake to start + * an RSA decryption operation using an + * external processor. The parameter \p cert contains + * the public key; it is up to the callback function to + * determine how to access the associated private key. + * + * This function typically sends or enqueues a request, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * The parameters \p ssl and \p cert are guaranteed to remain + * valid throughout the handshake. On the other hand, this + * function must save the contents of \p input if the value + * is needed for later processing, because the \p input buffer + * is no longer valid after this function returns. + * + * This function may call mbedtls_ssl_set_async_operation_data() + * to store an operation context for later retrieval + * by the resume or cancel callback. + * + * \warning RSA decryption as used in TLS is subject to a potential + * timing side channel attack first discovered by Bleichenbacher + * in 1998. This attack can be remotely exploitable + * in practice. To avoid this attack, you must ensure that + * if the callback performs an RSA decryption, the time it + * takes to execute and return the result does not depend + * on whether the RSA decryption succeeded or reported + * invalid padding. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param cert Certificate containing the public key. + * In simple cases, this is one of the pointers passed to + * mbedtls_ssl_conf_own_cert() when configuring the SSL + * connection. However, if other callbacks are used, this + * property may not hold. For example, if an SNI callback + * is registered with mbedtls_ssl_conf_sni(), then + * this callback determines what certificate is used. + * \param input Buffer containing the input ciphertext. This buffer + * is no longer valid when the function returns. + * \param input_len Size of the \p input buffer in bytes. + * + * \return 0 if the operation was started successfully and the SSL + * stack should call the resume callback immediately. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * was started successfully and the SSL stack should return + * immediately without calling the resume callback yet. + * \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external + * processor does not support this key. The SSL stack will + * use the private key object instead. + * \return Any other error indicates a fatal failure and is + * propagated up the call chain. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Callback type: resume external operation. + * + * This callback is called during an SSL handshake to resume + * an external operation started by the + * ::mbedtls_ssl_async_sign_t or + * ::mbedtls_ssl_async_decrypt_t callback. + * + * This function typically checks the status of a pending + * request or causes the request queue to make progress, and + * does not wait for the operation to complete. This allows + * the handshake step to be non-blocking. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * It may call mbedtls_ssl_set_async_operation_data() to modify + * this context. + * + * Note that when this function returns a status other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any + * resources associated with the operation. + * + * \param ssl The SSL connection instance. It should not be + * modified other than via + * mbedtls_ssl_set_async_operation_data(). + * \param output Buffer containing the output (signature or decrypted + * data) on success. + * \param output_len On success, number of bytes written to \p output. + * \param output_size Size of the \p output buffer in bytes. + * + * \return 0 if output of the operation is available in the + * \p output buffer. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation + * is still in progress. Subsequent requests for progress + * on the SSL connection will call the resume callback + * again. + * \return Any other error means that the operation is aborted. + * The SSL handshake is aborted. The callback should + * use \c MBEDTLS_ERR_PK_xxx error codes, and must not + * use \c MBEDTLS_ERR_SSL_xxx error codes except as + * directed in the documentation of this callback. + */ +typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ); + +/** + * \brief Callback type: cancel external operation. + * + * This callback is called if an SSL connection is closed + * while an asynchronous operation is in progress. Note that + * this callback is not called if the + * ::mbedtls_ssl_async_resume_t callback has run and has + * returned a value other than + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case + * the asynchronous operation has already completed. + * + * This function may call mbedtls_ssl_get_async_operation_data() + * to retrieve an operation context set by the start callback. + * + * \param ssl The SSL connection instance. It should not be + * modified. + */ +typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48 +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32 +#elif defined(MBEDTLS_SHA384_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48 +#elif defined(MBEDTLS_SHA1_C) +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1 +#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20 +#else +/* This is already checked in check_config.h, but be sure. */ +#error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT." +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED && + !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +typedef struct +{ + unsigned char client_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char server_application_traffic_secret_N[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char exporter_master_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char resumption_master_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; +} mbedtls_ssl_tls13_application_secrets; + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + +#define MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH 255 +#define MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH 4 +/* + * For code readability use a typedef for DTLS-SRTP profiles + * + * Use_srtp extension protection profiles values as defined in + * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + * + * Reminder: if this list is expanded mbedtls_ssl_check_srtp_profile_value + * must be updated too. + */ +#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80 ( (uint16_t) 0x0001) +#define MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32 ( (uint16_t) 0x0002) +#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80 ( (uint16_t) 0x0005) +#define MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32 ( (uint16_t) 0x0006) +/* This one is not iana defined, but for code readability. */ +#define MBEDTLS_TLS_SRTP_UNSET ( (uint16_t) 0x0000) + +typedef uint16_t mbedtls_ssl_srtp_profile; + +typedef struct mbedtls_dtls_srtp_info_t +{ + /*! The SRTP profile that was negotiated. */ + mbedtls_ssl_srtp_profile MBEDTLS_PRIVATE(chosen_dtls_srtp_profile); + /*! The length of mki_value. */ + uint16_t MBEDTLS_PRIVATE(mki_len); + /*! The mki_value used, with max size of 256 bytes. */ + unsigned char MBEDTLS_PRIVATE(mki_value)[MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH]; +} +mbedtls_dtls_srtp_info; + +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * This structure is used for storing current session data. + * + * Note: when changing this definition, we need to check and update: + * - in tests/suites/test_suite_ssl.function: + * ssl_populate_session() and ssl_serialize_session_save_load() + * - in library/ssl_tls.c: + * mbedtls_ssl_session_init() and mbedtls_ssl_session_free() + * mbedtls_ssl_session_save() and ssl_session_load() + * ssl_session_copy() + */ +struct mbedtls_ssl_session +{ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + unsigned char MBEDTLS_PRIVATE(mfl_code); /*!< MaxFragmentLength negotiated by peer */ +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + + unsigned char MBEDTLS_PRIVATE(exported); + + /* This field is temporarily duplicated with mbedtls_ssl_context.minor_ver. + * Once runtime negotiation of TLS 1.2 and TLS 1.3 is implemented, it needs + * to be studied whether one of them can be removed. */ + unsigned char MBEDTLS_PRIVATE(minor_ver); /*!< The TLS version used in the session. */ + +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t MBEDTLS_PRIVATE(start); /*!< starting time */ +#endif + int MBEDTLS_PRIVATE(ciphersuite); /*!< chosen ciphersuite */ + int MBEDTLS_PRIVATE(compression); /*!< chosen compression */ + size_t MBEDTLS_PRIVATE(id_len); /*!< session id length */ + unsigned char MBEDTLS_PRIVATE(id)[32]; /*!< session identifier */ + unsigned char MBEDTLS_PRIVATE(master)[48]; /*!< the master secret */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_x509_crt *MBEDTLS_PRIVATE(peer_cert); /*!< peer X.509 cert chain */ +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /*! The digest of the peer's end-CRT. This must be kept to detect CRT + * changes during renegotiation, mitigating the triple handshake attack. */ + unsigned char *MBEDTLS_PRIVATE(peer_cert_digest); + size_t MBEDTLS_PRIVATE(peer_cert_digest_len); + mbedtls_md_type_t MBEDTLS_PRIVATE(peer_cert_digest_type); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + uint32_t MBEDTLS_PRIVATE(verify_result); /*!< verification result */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + unsigned char *MBEDTLS_PRIVATE(ticket); /*!< RFC 5077 session ticket */ + size_t MBEDTLS_PRIVATE(ticket_len); /*!< session ticket length */ + uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< ticket lifetime hint */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int MBEDTLS_PRIVATE(encrypt_then_mac); /*!< flag for EtM activation */ +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_tls13_application_secrets MBEDTLS_PRIVATE(app_secrets); +#endif +}; + +/* + * Identifiers for PRFs used in various versions of TLS. + */ +typedef enum +{ + MBEDTLS_SSL_TLS_PRF_NONE, + MBEDTLS_SSL_TLS_PRF_SHA384, + MBEDTLS_SSL_TLS_PRF_SHA256, + MBEDTLS_SSL_HKDF_EXPAND_SHA384, + MBEDTLS_SSL_HKDF_EXPAND_SHA256 +} +mbedtls_tls_prf_types; + +typedef enum +{ + MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET = 0, +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +} mbedtls_ssl_key_export_type; + +/** + * \brief Callback type: Export key alongside random values for + * session identification, and PRF for + * implementation of TLS key exporters. + * + * \param p_expkey Context for the callback. + * \param type The type of the key that is being exported. + * \param secret The address of the buffer holding the secret + * that's being exporterd. + * \param secret_len The length of \p secret in bytes. + * \param client_random The client random bytes. + * \param server_random The server random bytes. + * \param tls_prf_type The identifier for the PRF used in the handshake + * to which the key belongs. + */ +typedef void mbedtls_ssl_export_keys_t( void *p_expkey, + mbedtls_ssl_key_export_type type, + const unsigned char *secret, + size_t secret_len, + const unsigned char client_random[32], + const unsigned char server_random[32], + mbedtls_tls_prf_types tls_prf_type ); + +/** + * SSL/TLS configuration to be shared between mbedtls_ssl_context structures. + */ +struct mbedtls_ssl_config +{ + /* Group items mostly by size. This helps to reduce memory wasted to + * padding. It also helps to keep smaller fields early in the structure, + * so that elements tend to be in the 128-element direct access window + * on Arm Thumb, which reduces the code size. */ + + unsigned char MBEDTLS_PRIVATE(max_major_ver); /*!< max. major version used */ + unsigned char MBEDTLS_PRIVATE(max_minor_ver); /*!< max. minor version used */ + unsigned char MBEDTLS_PRIVATE(min_major_ver); /*!< min. major version used */ + unsigned char MBEDTLS_PRIVATE(min_minor_ver); /*!< min. minor version used */ + + /* + * Flags (could be bit-fields to save RAM, but separate bytes make + * the code smaller on architectures with an instruction for direct + * byte access). + */ + + uint8_t MBEDTLS_PRIVATE(endpoint); /*!< 0: client, 1: server */ + uint8_t MBEDTLS_PRIVATE(transport); /*!< 0: stream (TLS), 1: datagram (DTLS) */ + uint8_t MBEDTLS_PRIVATE(authmode); /*!< MBEDTLS_SSL_VERIFY_XXX */ + /* needed even with renego disabled for LEGACY_BREAK_HANDSHAKE */ + uint8_t MBEDTLS_PRIVATE(allow_legacy_renegotiation); /*!< MBEDTLS_LEGACY_XXX */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + uint8_t MBEDTLS_PRIVATE(mfl_code); /*!< desired fragment length indicator + (MBEDTLS_SSL_MAX_FRAG_LEN_XXX) */ +#endif +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + uint8_t MBEDTLS_PRIVATE(encrypt_then_mac); /*!< negotiate encrypt-then-mac? */ +#endif +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + uint8_t MBEDTLS_PRIVATE(extended_ms); /*!< negotiate extended master secret? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint8_t MBEDTLS_PRIVATE(anti_replay); /*!< detect and prevent replay? */ +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + uint8_t MBEDTLS_PRIVATE(disable_renegotiation); /*!< disable renegotiation? */ +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t MBEDTLS_PRIVATE(session_tickets); /*!< use session tickets? */ +#endif +#if defined(MBEDTLS_SSL_SRV_C) + uint8_t MBEDTLS_PRIVATE(cert_req_ca_list); /*!< enable sending CA list in + Certificate Request messages? */ + uint8_t MBEDTLS_PRIVATE(respect_cli_pref); /*!< pick the ciphersuite according to + the client's preferences rather + than ours? */ +#endif +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t MBEDTLS_PRIVATE(ignore_unexpected_cid); /*!< Should DTLS record with + * unexpected CID + * lead to failure? */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#if defined(MBEDTLS_SSL_DTLS_SRTP) + uint8_t MBEDTLS_PRIVATE(dtls_srtp_mki_support); /* support having mki_value + in the use_srtp extension? */ +#endif + + /* + * Pointers + */ + + /** Allowed ciphersuites for (D)TLS 1.2 (0-terminated) */ + const int *MBEDTLS_PRIVATE(ciphersuite_list); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /** Allowed TLS 1.3 key exchange modes. */ + int MBEDTLS_PRIVATE(tls13_kex_modes); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /** Callback for printing debug output */ + void (*MBEDTLS_PRIVATE(f_dbg))(void *, int, const char *, int, const char *); + void *MBEDTLS_PRIVATE(p_dbg); /*!< context for the debug function */ + + /** Callback for getting (pseudo-)random numbers */ + int (*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ + + /** Callback to retrieve a session from the cache */ + mbedtls_ssl_cache_get_t *MBEDTLS_PRIVATE(f_get_cache); + /** Callback to store a session into the cache */ + mbedtls_ssl_cache_set_t *MBEDTLS_PRIVATE(f_set_cache); + void *MBEDTLS_PRIVATE(p_cache); /*!< context for cache callbacks */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /** Callback for setting cert according to SNI extension */ + int (*MBEDTLS_PRIVATE(f_sni))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_sni); /*!< context for SNI callback */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); + void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify calllback */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + /** Callback to retrieve PSK key from identity */ + int (*MBEDTLS_PRIVATE(f_psk))(void *, mbedtls_ssl_context *, const unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_psk); /*!< context for PSK callback */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a cookie for ClientHello veirifcation */ + int (*MBEDTLS_PRIVATE(f_cookie_write))( void *, unsigned char **, unsigned char *, + const unsigned char *, size_t ); + /** Callback to verify validity of a ClientHello cookie */ + int (*MBEDTLS_PRIVATE(f_cookie_check))( void *, const unsigned char *, size_t, + const unsigned char *, size_t ); + void *MBEDTLS_PRIVATE(p_cookie); /*!< context for the cookie callbacks */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) + /** Callback to create & write a session ticket */ + int (*MBEDTLS_PRIVATE(f_ticket_write))( void *, const mbedtls_ssl_session *, + unsigned char *, const unsigned char *, size_t *, uint32_t * ); + /** Callback to parse a session ticket into a session structure */ + int (*MBEDTLS_PRIVATE(f_ticket_parse))( void *, mbedtls_ssl_session *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_ticket); /*!< context for the ticket callbacks */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t MBEDTLS_PRIVATE(cid_len); /*!< The length of CIDs for incoming DTLS records. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + const mbedtls_x509_crt_profile *MBEDTLS_PRIVATE(cert_profile); /*!< verification profile */ + mbedtls_ssl_key_cert *MBEDTLS_PRIVATE(key_cert); /*!< own certificate/key pair(s) */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(ca_chain); /*!< trusted CAs */ + mbedtls_x509_crl *MBEDTLS_PRIVATE(ca_crl); /*!< trusted CAs CRLs */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_ca_cb_t MBEDTLS_PRIVATE(f_ca_cb); + void *MBEDTLS_PRIVATE(p_ca_cb); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_async_sign_t *MBEDTLS_PRIVATE(f_async_sign_start); /*!< start asynchronous signature operation */ + mbedtls_ssl_async_decrypt_t *MBEDTLS_PRIVATE(f_async_decrypt_start); /*!< start asynchronous decryption operation */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + mbedtls_ssl_async_resume_t *MBEDTLS_PRIVATE(f_async_resume); /*!< resume asynchronous operation */ + mbedtls_ssl_async_cancel_t *MBEDTLS_PRIVATE(f_async_cancel); /*!< cancel asynchronous operation */ + void *MBEDTLS_PRIVATE(p_async_config_data); /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + const int *MBEDTLS_PRIVATE(sig_hashes); /*!< allowed signature hashes */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + const uint16_t *MBEDTLS_PRIVATE(tls13_sig_algs); /*!< allowed signature algorithms for TLS 1.3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif + +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + const mbedtls_ecp_group_id *MBEDTLS_PRIVATE(curve_list); /*!< allowed curves */ +#endif + + const uint16_t *MBEDTLS_PRIVATE(group_list); /*!< allowed IANA NamedGroups */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi MBEDTLS_PRIVATE(dhm_P); /*!< prime modulus for DHM */ + mbedtls_mpi MBEDTLS_PRIVATE(dhm_G); /*!< generator for DHM */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_id_t MBEDTLS_PRIVATE(psk_opaque); /*!< PSA key slot holding opaque PSK. This field + * should only be set via + * mbedtls_ssl_conf_psk_opaque(). + * If either no PSK or a raw PSK have been + * configured, this has value \c 0. + */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + unsigned char *MBEDTLS_PRIVATE(psk); /*!< The raw pre-shared key. This field should + * only be set via mbedtls_ssl_conf_psk(). + * If either no PSK or an opaque PSK + * have been configured, this has value NULL. */ + size_t MBEDTLS_PRIVATE(psk_len); /*!< The length of the raw pre-shared key. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL. */ + + unsigned char *MBEDTLS_PRIVATE(psk_identity); /*!< The PSK identity for PSK negotiation. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * This is set if and only if either + * \c psk or \c psk_opaque are set. */ + size_t MBEDTLS_PRIVATE(psk_identity_len);/*!< The length of PSK identity. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL or \c psk_opaque + * is not \c 0. */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + const char **MBEDTLS_PRIVATE(alpn_list); /*!< ordered list of protocols */ +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /*! ordered list of supported srtp profile */ + const mbedtls_ssl_srtp_profile *MBEDTLS_PRIVATE(dtls_srtp_profile_list); + /*! number of supported profiles */ + size_t MBEDTLS_PRIVATE(dtls_srtp_profile_list_len); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Numerical settings (int) + */ + + uint32_t MBEDTLS_PRIVATE(read_timeout); /*!< timeout for mbedtls_ssl_read (ms) */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t MBEDTLS_PRIVATE(hs_timeout_min); /*!< initial value of the handshake + retransmission timeout (ms) */ + uint32_t MBEDTLS_PRIVATE(hs_timeout_max); /*!< maximum value of the handshake + retransmission timeout (ms) */ +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int MBEDTLS_PRIVATE(renego_max_records); /*!< grace period for renegotiation */ + unsigned char MBEDTLS_PRIVATE(renego_period)[8]; /*!< value of the record counters + that triggers renegotiation */ +#endif + + unsigned int MBEDTLS_PRIVATE(badmac_limit); /*!< limit of records with a bad MAC */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + unsigned int MBEDTLS_PRIVATE(dhm_min_bitlen); /*!< min. bit length of the DHM prime */ +#endif +}; + +struct mbedtls_ssl_context +{ + const mbedtls_ssl_config *MBEDTLS_PRIVATE(conf); /*!< configuration information */ + + /* + * Miscellaneous + */ + int MBEDTLS_PRIVATE(state); /*!< SSL handshake: current state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int MBEDTLS_PRIVATE(renego_status); /*!< Initial, in progress, pending? */ + int MBEDTLS_PRIVATE(renego_records_seen); /*!< Records since renego request, or with DTLS, + number of retransmissions of request if + renego_max_records is < 0 */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + int MBEDTLS_PRIVATE(major_ver); /*!< equal to MBEDTLS_SSL_MAJOR_VERSION_3 */ + + /* This field is temporarily duplicated with mbedtls_ssl_context.minor_ver. + * Once runtime negotiation of TLS 1.2 and TLS 1.3 is implemented, it needs + * to be studied whether one of them can be removed. */ + int MBEDTLS_PRIVATE(minor_ver); /*!< one of MBEDTLS_SSL_MINOR_VERSION_x macros */ + unsigned MBEDTLS_PRIVATE(badmac_seen); /*!< records with a bad MAC received */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /** Callback to customize X.509 certificate chain verification */ + int (*MBEDTLS_PRIVATE(f_vrfy))(void *, mbedtls_x509_crt *, int, uint32_t *); + void *MBEDTLS_PRIVATE(p_vrfy); /*!< context for X.509 verify callback */ +#endif + + mbedtls_ssl_send_t *MBEDTLS_PRIVATE(f_send); /*!< Callback for network send */ + mbedtls_ssl_recv_t *MBEDTLS_PRIVATE(f_recv); /*!< Callback for network receive */ + mbedtls_ssl_recv_timeout_t *MBEDTLS_PRIVATE(f_recv_timeout); + /*!< Callback for network receive with timeout */ + + void *MBEDTLS_PRIVATE(p_bio); /*!< context for I/O operations */ + + /* + * Session layer + */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_in); /*!< current session data (in) */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_out); /*!< current session data (out) */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session); /*!< negotiated session data */ + mbedtls_ssl_session *MBEDTLS_PRIVATE(session_negotiate); /*!< session data in negotiation */ + + mbedtls_ssl_handshake_params *MBEDTLS_PRIVATE(handshake); /*!< params required only during + the handshake process */ + + /* + * Record layer transformations + */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_in); /*!< current transform params (in) + * This is always a reference, + * never an owning pointer. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_out); /*!< current transform params (out) + * This is always a reference, + * never an owning pointer. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform); /*!< negotiated transform params + * This pointer owns the transform + * it references. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_negotiate); /*!< transform params in negotiation + * This pointer owns the transform + * it references. */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /*! The application data transform in TLS 1.3. + * This pointer owns the transform it references. */ + mbedtls_ssl_transform *MBEDTLS_PRIVATE(transform_application); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * Timers + */ + void *MBEDTLS_PRIVATE(p_timer); /*!< context for the timer callbacks */ + + mbedtls_ssl_set_timer_t *MBEDTLS_PRIVATE(f_set_timer); /*!< set timer callback */ + mbedtls_ssl_get_timer_t *MBEDTLS_PRIVATE(f_get_timer); /*!< get timer callback */ + + /* + * Record layer (incoming data) + */ + unsigned char *MBEDTLS_PRIVATE(in_buf); /*!< input buffer */ + unsigned char *MBEDTLS_PRIVATE(in_ctr); /*!< 64-bit incoming message counter + TLS: maintained by us + DTLS: read from peer */ + unsigned char *MBEDTLS_PRIVATE(in_hdr); /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *MBEDTLS_PRIVATE(in_cid); /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *MBEDTLS_PRIVATE(in_len); /*!< two-bytes message length field */ + unsigned char *MBEDTLS_PRIVATE(in_iv); /*!< ivlen-byte IV */ + unsigned char *MBEDTLS_PRIVATE(in_msg); /*!< message contents (in_iv+ivlen) */ + unsigned char *MBEDTLS_PRIVATE(in_offt); /*!< read offset in application data */ + + int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */ + size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */ + size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */ +#endif +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t MBEDTLS_PRIVATE(in_epoch); /*!< DTLS epoch for incoming records */ + size_t MBEDTLS_PRIVATE(next_record_offset); /*!< offset of the next record in datagram + (equal to in_left if none) */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + uint64_t MBEDTLS_PRIVATE(in_window_top); /*!< last validated record seq_num */ + uint64_t MBEDTLS_PRIVATE(in_window); /*!< bitmask for replay detection */ +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + + size_t MBEDTLS_PRIVATE(in_hslen); /*!< current handshake message length, + including the handshake header */ + int MBEDTLS_PRIVATE(nb_zero); /*!< # of 0-length encrypted messages */ + + int MBEDTLS_PRIVATE(keep_current_message); /*!< drop or reuse current message + on next call to record layer? */ + + /* The following three variables indicate if and, if yes, + * what kind of alert is pending to be sent. + */ + unsigned char MBEDTLS_PRIVATE(send_alert); /*!< Determines if a fatal alert + should be sent. Values: + - \c 0 , no alert is to be sent. + - \c 1 , alert is to be sent. */ + unsigned char MBEDTLS_PRIVATE(alert_type); /*!< Type of alert if send_alert + != 0 */ + int MBEDTLS_PRIVATE(alert_reason); /*!< The error code to be returned + to the user once the fatal alert + has been sent. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t MBEDTLS_PRIVATE(disable_datagram_packing); /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Record layer (outgoing data) + */ + unsigned char *MBEDTLS_PRIVATE(out_buf); /*!< output buffer */ + unsigned char *MBEDTLS_PRIVATE(out_ctr); /*!< 64-bit outgoing message counter */ + unsigned char *MBEDTLS_PRIVATE(out_hdr); /*!< start of record header */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + unsigned char *MBEDTLS_PRIVATE(out_cid); /*!< The start of the CID; + * (the end is marked by in_len). */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + unsigned char *MBEDTLS_PRIVATE(out_len); /*!< two-bytes message length field */ + unsigned char *MBEDTLS_PRIVATE(out_iv); /*!< ivlen-byte IV */ + unsigned char *MBEDTLS_PRIVATE(out_msg); /*!< message contents (out_iv+ivlen) */ + + int MBEDTLS_PRIVATE(out_msgtype); /*!< record header: message type */ + size_t MBEDTLS_PRIVATE(out_msglen); /*!< record header: message length */ + size_t MBEDTLS_PRIVATE(out_left); /*!< amount of data not yet written */ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t MBEDTLS_PRIVATE(out_buf_len); /*!< length of output buffer */ +#endif + + unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Outgoing record sequence number. */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint16_t MBEDTLS_PRIVATE(mtu); /*!< path mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * PKI layer + */ + int MBEDTLS_PRIVATE(client_auth); /*!< flag for client auth. */ + + /* + * User settings + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) + char *MBEDTLS_PRIVATE(hostname); /*!< expected peer CN for verification + (and SNI if available) */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ALPN) + const char *MBEDTLS_PRIVATE(alpn_chosen); /*!< negotiated protocol */ +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + /* + * use_srtp extension + */ + mbedtls_dtls_srtp_info MBEDTLS_PRIVATE(dtls_srtp_info); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + /* + * Information for DTLS hello verify + */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + unsigned char *MBEDTLS_PRIVATE(cli_id); /*!< transport-level ID of the client */ + size_t MBEDTLS_PRIVATE(cli_id_len); /*!< length of cli_id */ +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + + /* + * Secure renegotiation + */ + /* needed to know when to send extension on server */ + int MBEDTLS_PRIVATE(secure_renegotiation); /*!< does peer support legacy or + secure renegotiation */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + size_t MBEDTLS_PRIVATE(verify_data_len); /*!< length of verify data stored */ + char MBEDTLS_PRIVATE(own_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ + char MBEDTLS_PRIVATE(peer_verify_data)[MBEDTLS_SSL_VERIFY_DATA_MAX_LEN]; /*!< previous handshake verify data */ +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* CID configuration to use in subsequent handshakes. */ + + /*! The next incoming CID, chosen by the user and applying to + * all subsequent handshakes. This may be different from the + * CID currently used in case the user has re-configured the CID + * after an initial handshake. */ + unsigned char MBEDTLS_PRIVATE(own_cid)[ MBEDTLS_SSL_CID_IN_LEN_MAX ]; + uint8_t MBEDTLS_PRIVATE(own_cid_len); /*!< The length of \c own_cid. */ + uint8_t MBEDTLS_PRIVATE(negotiate_cid); /*!< This indicates whether the CID extension should + * be negotiated in the next handshake or not. + * Possible values are #MBEDTLS_SSL_CID_ENABLED + * and #MBEDTLS_SSL_CID_DISABLED. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /** Callback to export key block and master secret */ + mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys); + void *MBEDTLS_PRIVATE(p_export_keys); /*!< context for key export callback */ +}; + +/** + * \brief Return the name of the ciphersuite associated with the + * given ID + * + * \param ciphersuite_id SSL ciphersuite ID + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ); + +/** + * \brief Return the ID of the ciphersuite associated with the + * given name + * + * \param ciphersuite_name SSL ciphersuite name + * + * \return the ID with the ciphersuite or 0 if not found + */ +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ); + +/** + * \brief Initialize an SSL context + * Just makes the context ready for mbedtls_ssl_setup() or + * mbedtls_ssl_free() + * + * \param ssl SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ); + +/** + * \brief Set up an SSL context for use + * + * \note No copy of the configuration context is made, it can be + * shared by many mbedtls_ssl_context structures. + * + * \warning The conf structure will be accessed during the session. + * It must not be modified or freed as long as the session + * is active. + * + * \warning This function must be called exactly once per context. + * Calling mbedtls_ssl_setup again is not supported, even + * if no session is active. + * + * \param ssl SSL context + * \param conf SSL configuration to use + * + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED if + * memory allocation failed + */ +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ); + +/** + * \brief Reset an already initialized SSL context for re-use + * while retaining application-set variables, function + * pointers and data. + * + * \param ssl SSL context + * \return 0 if successful, or MBEDTLS_ERR_SSL_ALLOC_FAILED or + MBEDTLS_ERR_SSL_HW_ACCEL_FAILED + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ); + +/** + * \brief Set the current endpoint type + * + * \param conf SSL configuration + * \param endpoint must be MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ); + +/** + * \brief Set the transport type (TLS or DTLS). + * Default: TLS + * + * \note For DTLS, you must either provide a recv callback that + * doesn't block, or one that handles timeouts, see + * \c mbedtls_ssl_set_bio(). You also need to provide timer + * callbacks with \c mbedtls_ssl_set_timer_cb(). + * + * \param conf SSL configuration + * \param transport transport type: + * MBEDTLS_SSL_TRANSPORT_STREAM for TLS, + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS. + */ +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ); + +/** + * \brief Set the certificate verification mode + * Default: NONE on server, REQUIRED on client + * + * \param conf SSL configuration + * \param authmode can be: + * + * MBEDTLS_SSL_VERIFY_NONE: peer certificate is not checked + * (default on server) + * (insecure on client) + * + * MBEDTLS_SSL_VERIFY_OPTIONAL: peer certificate is checked, however the + * handshake continues even if verification failed; + * mbedtls_ssl_get_verify_result() can be called after the + * handshake is complete. + * + * MBEDTLS_SSL_VERIFY_REQUIRED: peer *must* present a valid certificate, + * handshake is aborted if verification failed. + * (default on client) + * + * \note On client, MBEDTLS_SSL_VERIFY_REQUIRED is the recommended mode. + * With MBEDTLS_SSL_VERIFY_OPTIONAL, the user needs to call mbedtls_ssl_get_verify_result() at + * the right time(s), which may not be obvious, while REQUIRED always perform + * the verification as soon as possible. For example, REQUIRED was protecting + * against the "triple handshake" attack even before it was found. + */ +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the verification callback (Optional). + * + * If set, the provided verify callback is called for each + * certificate in the peer's CRT chain, including the trusted + * root. For more information, please see the documentation of + * \c mbedtls_x509_crt_verify(). + * + * \note For per context callbacks and contexts, please use + * mbedtls_ssl_set_verify() instead. + * + * \param conf The SSL configuration to use. + * \param f_vrfy The verification callback to use during CRT verification. + * \param p_vrfy The opaque context to be passed to the callback. + */ +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the random number generator callback + * + * \param conf SSL configuration + * \param f_rng RNG function (mandatory) + * \param p_rng RNG parameter + */ +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set the debug callback + * + * The callback has the following argument: + * void * opaque context for the callback + * int debug level + * const char * file name + * int line number + * const char * message + * + * \param conf SSL configuration + * \param f_dbg debug function + * \param p_dbg debug parameter + */ +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ); + +/** + * \brief Set the underlying BIO callbacks for write, read and + * read-with-timeout. + * + * \param ssl SSL context + * \param p_bio parameter (context) shared by BIO callbacks + * \param f_send write callback + * \param f_recv read callback + * \param f_recv_timeout blocking read callback with timeout. + * + * \note One of f_recv or f_recv_timeout can be NULL, in which case + * the other is used. If both are non-NULL, f_recv_timeout is + * used and f_recv is ignored (as if it were NULL). + * + * \note The two most common use cases are: + * - non-blocking I/O, f_recv != NULL, f_recv_timeout == NULL + * - blocking I/O, f_recv == NULL, f_recv_timout != NULL + * + * \note For DTLS, you need to provide either a non-NULL + * f_recv_timeout callback, or a f_recv that doesn't block. + * + * \note See the documentations of \c mbedtls_ssl_send_t, + * \c mbedtls_ssl_recv_t and \c mbedtls_ssl_recv_timeout_t for + * the conventions those callbacks must follow. + * + * \note On some platforms, net_sockets.c provides + * \c mbedtls_net_send(), \c mbedtls_net_recv() and + * \c mbedtls_net_recv_timeout() that are suitable to be used + * here. + */ +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + + +/** + * \brief Configure the use of the Connection ID (CID) + * extension in the next handshake. + * + * Reference: draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * The DTLS CID extension allows the reliable association of + * DTLS records to DTLS connections across changes in the + * underlying transport (changed IP and Port metadata) by + * adding explicit connection identifiers (CIDs) to the + * headers of encrypted DTLS records. The desired CIDs are + * configured by the application layer and are exchanged in + * new `ClientHello` / `ServerHello` extensions during the + * handshake, where each side indicates the CID it wants the + * peer to use when writing encrypted messages. The CIDs are + * put to use once records get encrypted: the stack discards + * any incoming records that don't include the configured CID + * in their header, and adds the peer's requested CID to the + * headers of outgoing messages. + * + * This API enables or disables the use of the CID extension + * in the next handshake and sets the value of the CID to + * be used for incoming messages. + * + * \param ssl The SSL context to configure. This must be initialized. + * \param enable This value determines whether the CID extension should + * be used or not. Possible values are: + * - MBEDTLS_SSL_CID_ENABLED to enable the use of the CID. + * - MBEDTLS_SSL_CID_DISABLED (default) to disable the use + * of the CID. + * \param own_cid The address of the readable buffer holding the CID we want + * the peer to use when sending encrypted messages to us. + * This may be \c NULL if \p own_cid_len is \c 0. + * This parameter is unused if \p enabled is set to + * MBEDTLS_SSL_CID_DISABLED. + * \param own_cid_len The length of \p own_cid. + * This parameter is unused if \p enabled is set to + * MBEDTLS_SSL_CID_DISABLED. + * + * \note The value of \p own_cid_len must match the value of the + * \c len parameter passed to mbedtls_ssl_conf_cid() + * when configuring the ::mbedtls_ssl_config that \p ssl + * is bound to. + * + * \note This CID configuration applies to subsequent handshakes + * performed on the SSL context \p ssl, but does not trigger + * one. You still have to call `mbedtls_ssl_handshake()` + * (for the initial handshake) or `mbedtls_ssl_renegotiate()` + * (for a renegotiation handshake) explicitly after a + * successful call to this function to run the handshake. + * + * \note This call cannot guarantee that the use of the CID + * will be successfully negotiated in the next handshake, + * because the peer might not support it. Specifically: + * - On the Client, enabling the use of the CID through + * this call implies that the `ClientHello` in the next + * handshake will include the CID extension, thereby + * offering the use of the CID to the server. Only if + * the `ServerHello` contains the CID extension, too, + * the CID extension will actually be put to use. + * - On the Server, enabling the use of the CID through + * this call implies that that the server will look for + * the CID extension in a `ClientHello` from the client, + * and, if present, reply with a CID extension in its + * `ServerHello`. + * + * \note To check whether the use of the CID was negotiated + * after the subsequent handshake has completed, please + * use the API mbedtls_ssl_get_peer_cid(). + * + * \warning If the use of the CID extension is enabled in this call + * and the subsequent handshake negotiates its use, Mbed TLS + * will silently drop every packet whose CID does not match + * the CID configured in \p own_cid. It is the responsibility + * of the user to adapt the underlying transport to take care + * of CID-based demultiplexing before handing datagrams to + * Mbed TLS. + * + * \return \c 0 on success. In this case, the CID configuration + * applies to the next handshake. + * \return A negative error code on failure. + */ +int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl, + int enable, + unsigned char const *own_cid, + size_t own_cid_len ); + +/** + * \brief Get information about the use of the CID extension + * in the current connection. + * + * \param ssl The SSL context to query. + * \param enabled The address at which to store whether the CID extension + * is currently in use or not. If the CID is in use, + * `*enabled` is set to MBEDTLS_SSL_CID_ENABLED; + * otherwise, it is set to MBEDTLS_SSL_CID_DISABLED. + * \param peer_cid The address of the buffer in which to store the CID + * chosen by the peer (if the CID extension is used). + * This may be \c NULL in case the value of peer CID + * isn't needed. If it is not \c NULL, \p peer_cid_len + * must not be \c NULL. + * \param peer_cid_len The address at which to store the size of the CID + * chosen by the peer (if the CID extension is used). + * This is also the number of Bytes in \p peer_cid that + * have been written. + * This may be \c NULL in case the length of the peer CID + * isn't needed. If it is \c NULL, \p peer_cid must be + * \c NULL, too. + * + * \note This applies to the state of the CID negotiated in + * the last complete handshake. If a handshake is in + * progress, this function will attempt to complete + * the handshake first. + * + * \note If CID extensions have been exchanged but both client + * and server chose to use an empty CID, this function + * sets `*enabled` to #MBEDTLS_SSL_CID_DISABLED + * (the rationale for this is that the resulting + * communication is the same as if the CID extensions + * hadn't been used). + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, + int *enabled, + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ], + size_t *peer_cid_len ); + +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +/** + * \brief Set the Maximum Tranport Unit (MTU). + * Special value: 0 means unset (no limit). + * This represents the maximum size of a datagram payload + * handled by the transport layer (usually UDP) as determined + * by the network link and stack. In practice, this controls + * the maximum size datagram the DTLS layer will pass to the + * \c f_send() callback set using \c mbedtls_ssl_set_bio(). + * + * \note The limit on datagram size is converted to a limit on + * record payload by subtracting the current overhead of + * encapsulation and encryption/authentication if any. + * + * \note This can be called at any point during the connection, for + * example when a Path Maximum Transfer Unit (PMTU) + * estimate becomes available from other sources, + * such as lower (or higher) protocol layers. + * + * \note This setting only controls the size of the packets we send, + * and does not restrict the size of the datagrams we're + * willing to receive. Client-side, you can request the + * server to use smaller records with \c + * mbedtls_ssl_conf_max_frag_len(). + * + * \note If both a MTU and a maximum fragment length have been + * configured (or negotiated with the peer), the resulting + * lower limit on record payload (see first note) is used. + * + * \note This can only be used to decrease the maximum size + * of datagrams (hence records, see first note) sent. It + * cannot be used to increase the maximum size of records over + * the limit set by #MBEDTLS_SSL_OUT_CONTENT_LEN. + * + * \note Values lower than the current record layer expansion will + * result in an error when trying to send data. + * + * \param ssl SSL context + * \param mtu Value of the path MTU in bytes + */ +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set a connection-specific verification callback (optional). + * + * If set, the provided verify callback is called for each + * certificate in the peer's CRT chain, including the trusted + * root. For more information, please see the documentation of + * \c mbedtls_x509_crt_verify(). + * + * \note This call is analogous to mbedtls_ssl_conf_verify() but + * binds the verification callback and context to an SSL context + * as opposed to an SSL configuration. + * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify() + * are both used, mbedtls_ssl_set_verify() takes precedence. + * + * \param ssl The SSL context to use. + * \param f_vrfy The verification callback to use during CRT verification. + * \param p_vrfy The opaque context to be passed to the callback. + */ +void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** + * \brief Set the timeout period for mbedtls_ssl_read() + * (Default: no timeout.) + * + * \param conf SSL configuration context + * \param timeout Timeout value in milliseconds. + * Use 0 for no timeout (default). + * + * \note With blocking I/O, this will only work if a non-NULL + * \c f_recv_timeout was set with \c mbedtls_ssl_set_bio(). + * With non-blocking I/O, this will only work if timer + * callbacks were set with \c mbedtls_ssl_set_timer_cb(). + * + * \note With non-blocking I/O, you may also skip this function + * altogether and handle timeouts at the application layer. + */ +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ); + +/** + * \brief Check whether a buffer contains a valid and authentic record + * that has not been seen before. (DTLS only). + * + * This function does not change the user-visible state + * of the SSL context. Its sole purpose is to provide + * an indication of the legitimacy of an incoming record. + * + * This can be useful e.g. in distributed server environments + * using the DTLS Connection ID feature, in which connections + * might need to be passed between service instances on a change + * of peer address, but where such disruptive operations should + * only happen after the validity of incoming records has been + * confirmed. + * + * \param ssl The SSL context to use. + * \param buf The address of the buffer holding the record to be checked. + * This must be a read/write buffer of length \p buflen Bytes. + * \param buflen The length of \p buf in Bytes. + * + * \note This routine only checks whether the provided buffer begins + * with a valid and authentic record that has not been seen + * before, but does not check potential data following the + * initial record. In particular, it is possible to pass DTLS + * datagrams containing multiple records, in which case only + * the first record is checked. + * + * \note This function modifies the input buffer \p buf. If you need + * to preserve the original record, you have to maintain a copy. + * + * \return \c 0 if the record is valid and authentic and has not been + * seen before. + * \return MBEDTLS_ERR_SSL_INVALID_MAC if the check completed + * successfully but the record was found to be not authentic. + * \return MBEDTLS_ERR_SSL_INVALID_RECORD if the check completed + * successfully but the record was found to be invalid for + * a reason different from authenticity checking. + * \return MBEDTLS_ERR_SSL_UNEXPECTED_RECORD if the check completed + * successfully but the record was found to be unexpected + * in the state of the SSL context, including replayed records. + * \return Another negative error code on different kinds of failure. + * In this case, the SSL context becomes unusable and needs + * to be freed or reset before reuse. + */ +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ); + +/** + * \brief Set the timer callbacks (Mandatory for DTLS.) + * + * \param ssl SSL context + * \param p_timer parameter (context) shared by timer callbacks + * \param f_set_timer set timer callback + * \param f_get_timer get timer callback. Must return: + * + * \note See the documentation of \c mbedtls_ssl_set_timer_t and + * \c mbedtls_ssl_get_timer_t for the conventions this pair of + * callbacks must follow. + * + * \note On some platforms, timing.c provides + * \c mbedtls_timing_set_delay() and + * \c mbedtls_timing_get_delay() that are suitable for using + * here, except if using an event-driven style. + * + * \note See also the "DTLS tutorial" article in our knowledge base. + * https://tls.mbed.org/kb/how-to/dtls-tutorial + */ +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ); + +/** + * \brief Callback type: generate and write session ticket + * + * \note This describes what a callback implementation should do. + * This callback should generate an encrypted and + * authenticated ticket for the session and write it to the + * output buffer. Here, ticket means the opaque ticket part + * of the NewSessionTicket structure of RFC 5077. + * + * \param p_ticket Context for the callback + * \param session SSL session to be written in the ticket + * \param start Start of the output buffer + * \param end End of the output buffer + * \param tlen On exit, holds the length written + * \param lifetime On exit, holds the lifetime of the ticket in seconds + * + * \return 0 if successful, or + * a specific MBEDTLS_ERR_XXX code. + */ +typedef int mbedtls_ssl_ticket_write_t( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *lifetime ); + +/** + * \brief Callback type: parse and load session ticket + * + * \note This describes what a callback implementation should do. + * This callback should parse a session ticket as generated + * by the corresponding mbedtls_ssl_ticket_write_t function, + * and, if the ticket is authentic and valid, load the + * session. + * + * \note The implementation is allowed to modify the first len + * bytes of the input buffer, eg to use it as a temporary + * area for the decrypted ticket contents. + * + * \param p_ticket Context for the callback + * \param session SSL session to be loaded + * \param buf Start of the buffer containing the ticket + * \param len Length of the ticket. + * + * \return 0 if successful, or + * MBEDTLS_ERR_SSL_INVALID_MAC if not authentic, or + * MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED if expired, or + * any other non-zero code for other failures. + */ +typedef int mbedtls_ssl_ticket_parse_t( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Configure SSL session ticket callbacks (server only). + * (Default: none.) + * + * \note On server, session tickets are enabled by providing + * non-NULL callbacks. + * + * \note On client, use \c mbedtls_ssl_conf_session_tickets(). + * + * \param conf SSL configuration context + * \param f_ticket_write Callback for writing a ticket + * \param f_ticket_parse Callback for parsing a ticket + * \param p_ticket Context shared by the two callbacks + */ +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */ + +/** + * \brief Configure a key export callback. + * (Default: none.) + * + * This API can be used for two purposes: + * - Debugging: Use this API to e.g. generate an NSSKeylog + * file and use it to inspect encrypted traffic in tools + * such as Wireshark. + * - Application-specific export: Use this API to implement + * key exporters, e.g. for EAP-TLS or DTLS-SRTP. + * + * + * \param ssl The SSL context to which the export + * callback should be attached. + * \param f_export_keys The callback for the key export. + * \param p_export_keys The opaque context pointer to be passed to the + * callback \p f_export_keys. + */ +void mbedtls_ssl_set_export_keys_cb( mbedtls_ssl_context *ssl, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +/** + * \brief Configure asynchronous private key operation callbacks. + * + * \param conf SSL configuration context + * \param f_async_sign Callback to start a signature operation. See + * the description of ::mbedtls_ssl_async_sign_t + * for more information. This may be \c NULL if the + * external processor does not support any signature + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_decrypt Callback to start a decryption operation. See + * the description of ::mbedtls_ssl_async_decrypt_t + * for more information. This may be \c NULL if the + * external processor does not support any decryption + * operation; in this case the private key object + * associated with the certificate will be used. + * \param f_async_resume Callback to resume an asynchronous operation. See + * the description of ::mbedtls_ssl_async_resume_t + * for more information. This may not be \c NULL unless + * \p f_async_sign and \p f_async_decrypt are both + * \c NULL. + * \param f_async_cancel Callback to cancel an asynchronous operation. See + * the description of ::mbedtls_ssl_async_cancel_t + * for more information. This may be \c NULL if + * no cleanup is needed. + * \param config_data A pointer to configuration data which can be + * retrieved with + * mbedtls_ssl_conf_get_async_config_data(). The + * library stores this value without dereferencing it. + */ +void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *config_data ); + +/** + * \brief Retrieve the configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + * + * \param conf SSL configuration context + * \return The configuration data set by + * mbedtls_ssl_conf_async_private_cb(). + */ +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * + * \return The asynchronous operation user context that was last + * set during the current handshake. If + * mbedtls_ssl_set_async_operation_data() has not yet been + * called during the current handshake, this function returns + * \c NULL. + */ +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ); + +/** + * \brief Retrieve the asynchronous operation user context. + * + * \note This function may only be called while a handshake + * is in progress. + * + * \param ssl The SSL context to access. + * \param ctx The new value of the asynchronous operation user context. + * Call mbedtls_ssl_get_async_operation_data() later during the + * same handshake to retrieve this value. + */ +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/** + * \brief Callback type: generate a cookie + * + * \param ctx Context for the callback + * \param p Buffer to write to, + * must be updated to point right after the cookie + * \param end Pointer to one past the end of the output buffer + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 on success, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_write_t( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *info, size_t ilen ); + +/** + * \brief Callback type: verify a cookie + * + * \param ctx Context for the callback + * \param cookie Cookie to verify + * \param clen Length of cookie + * \param info Client ID info that was passed to + * \c mbedtls_ssl_set_client_transport_id() + * \param ilen Length of info in bytes + * + * \return The callback must return 0 if cookie is valid, + * or a negative error code. + */ +typedef int mbedtls_ssl_cookie_check_t( void *ctx, + const unsigned char *cookie, size_t clen, + const unsigned char *info, size_t ilen ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Register callbacks for DTLS cookies + * (Server only. DTLS only.) + * + * Default: dummy callbacks that fail, in order to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * + * \note See comments on \c mbedtls_ssl_handshake() about handling + * the MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED that is expected + * on the first handshake attempt when this is enabled. + * + * \note This is also necessary to handle client reconnection from + * the same port as described in RFC 6347 section 4.2.8 (only + * the variant with cookies is supported currently). See + * comments on \c mbedtls_ssl_read() for details. + * + * \param conf SSL configuration + * \param f_cookie_write Cookie write callback + * \param f_cookie_check Cookie check callback + * \param p_cookie Context for both callbacks + */ +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ); + +/** + * \brief Set client's transport-level identification info. + * (Server only. DTLS only.) + * + * This is usually the IP address (and port), but could be + * anything identify the client depending on the underlying + * network stack. Used for HelloVerifyRequest with DTLS. + * This is *not* used to route the actual packets. + * + * \param ssl SSL context + * \param info Transport-level info identifying the client (eg IP + port) + * \param ilen Length of info in bytes + * + * \note An internal copy is made, so the info buffer can be reused. + * + * \return 0 on success, + * MBEDTLS_ERR_SSL_BAD_INPUT_DATA if used on client, + * MBEDTLS_ERR_SSL_ALLOC_FAILED if out of memory. + */ +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ); + +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +/** + * \brief Enable or disable anti-replay protection for DTLS. + * (DTLS only, no effect on TLS.) + * Default: enabled. + * + * \param conf SSL configuration + * \param mode MBEDTLS_SSL_ANTI_REPLAY_ENABLED or MBEDTLS_SSL_ANTI_REPLAY_DISABLED. + * + * \warning Disabling this is a security risk unless the application + * protocol handles duplicated packets in a safe way. You + * should not disable this without careful consideration. + * However, if your application already detects duplicated + * packets and needs information about them to adjust its + * transmission strategy, then you'll want to disable this. + */ +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ); +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +/** + * \brief Set a limit on the number of records with a bad MAC + * before terminating the connection. + * (DTLS only, no effect on TLS.) + * Default: 0 (disabled). + * + * \param conf SSL configuration + * \param limit Limit, or 0 to disable. + * + * \note If the limit is N, then the connection is terminated when + * the Nth non-authentic record is seen. + * + * \note Records with an invalid header are not counted, only the + * ones going through the authentication-decryption phase. + * + * \note This is a security trade-off related to the fact that it's + * often relatively easy for an active attacker ot inject UDP + * datagrams. On one hand, setting a low limit here makes it + * easier for such an attacker to forcibly terminated a + * connection. On the other hand, a high limit or no limit + * might make us waste resources checking authentication on + * many bogus packets. + */ +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application records are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + +/** + * \brief Set retransmit timeout values for the DTLS handshake. + * (DTLS only, no effect on TLS.) + * + * \param conf SSL configuration + * \param min Initial timeout value in milliseconds. + * Default: 1000 (1 second). + * \param max Maximum timeout value in milliseconds. + * Default: 60000 (60 seconds). + * + * \note Default values are from RFC 6347 section 4.2.4.1. + * + * \note The 'min' value should typically be slightly above the + * expected round-trip time to your peer, plus whatever time + * it takes for the peer to process the message. For example, + * if your RTT is about 600ms and you peer needs up to 1s to + * do the cryptographic operations in the handshake, then you + * should set 'min' slightly above 1600. Lower values of 'min' + * might cause spurious resends which waste network resources, + * while larger value of 'min' will increase overall latency + * on unreliable network links. + * + * \note The more unreliable your network connection is, the larger + * your max / min ratio needs to be in order to achieve + * reliable handshakes. + * + * \note Messages are retransmitted up to log2(ceil(max/min)) times. + * For example, if min = 1s and max = 5s, the retransmit plan + * goes: send ... 1s -> resend ... 2s -> resend ... 4s -> + * resend ... 5s -> give up and return a timeout error. + */ +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the session cache callbacks (server-side only) + * If not set, no session resuming is done (except if session + * tickets are enabled too). + * + * The session cache has the responsibility to check for stale + * entries based on timeout. See RFC 5246 for recommendations. + * + * Warning: session.peer_cert is cleared by the SSL/TLS layer on + * connection shutdown, so do not cache the pointer! Either set + * it to NULL or make a full copy of the certificate. + * + * The get callback is called once during the initial handshake + * to enable session resuming. The get function has the + * following parameters: (void *parameter, mbedtls_ssl_session *session) + * If a valid entry is found, it should fill the master of + * the session object with the cached values and return 0, + * return 1 otherwise. Optionally peer_cert can be set as well + * if it is properly present in cache entry. + * + * The set callback is called once during the initial handshake + * to enable session resuming after the entire handshake has + * been finished. The set function has the following parameters: + * (void *parameter, const mbedtls_ssl_session *session). The function + * should create a cache entry for future retrieval based on + * the data in the session structure and should keep in mind + * that the mbedtls_ssl_session object presented (and all its referenced + * data) is cleared by the SSL/TLS layer when the connection is + * terminated. It is recommended to add metadata to determine if + * an entry is still valid in the future. Return 0 if + * successfully cached, return 1 otherwise. + * + * \param conf SSL configuration + * \param p_cache parmater (context) for both callbacks + * \param f_get_cache session get callback + * \param f_set_cache session set callback + */ +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + mbedtls_ssl_cache_get_t *f_get_cache, + mbedtls_ssl_cache_set_t *f_set_cache ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Load a session for session resumption. + * + * Sessions loaded through this call will be considered + * for session resumption in the next handshake. + * + * \note Even if this call succeeds, it is not guaranteed that + * the next handshake will indeed be shortened through the + * use of session resumption: The server is always free + * to reject any attempt for resumption and fall back to + * a full handshake. + * + * \note This function can handle a variety of mechanisms for session + * resumption: For TLS 1.2, both session ID-based resumption and + * ticket-based resumption will be considered. For TLS 1.3, + * once implemented, sessions equate to tickets, and loading + * one or more sessions via this call will lead to their + * corresponding tickets being advertised as resumption PSKs + * by the client. + * + * \note Calling this function multiple times will only be useful + * once TLS 1.3 is supported. For TLS 1.2 connections, this + * function should be called at most once. + * + * \param ssl The SSL context representing the connection which should + * be attempted to be setup using session resumption. This + * must be initialized via mbedtls_ssl_init() and bound to + * an SSL configuration via mbedtls_ssl_setup(), but + * the handshake must not yet have been started. + * \param session The session to be considered for session resumption. + * This must be a session previously exported via + * mbedtls_ssl_get_session(), and potentially serialized and + * deserialized through mbedtls_ssl_session_save() and + * mbedtls_ssl_session_load() in the meantime. + * + * \return \c 0 if successful. + * \return \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session + * could not be loaded because of an implementation limitation. + * This error is non-fatal, and has no observable effect on + * the SSL context or the session that was attempted to be loaded. + * \return Another negative error code on other kinds of failure. + * + * \sa mbedtls_ssl_get_session() + * \sa mbedtls_ssl_session_load() + */ +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Load serialized session data into a session structure. + * On client, this can be used for loading saved sessions + * before resuming them with mbedstls_ssl_set_session(). + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \warning If a peer certificate chain is associated with the session, + * the serialized state will only contain the peer's + * end-entity certificate and the result of the chain + * verification (unless verification was disabled), but not + * the rest of the chain. + * + * \see mbedtls_ssl_session_save() + * \see mbedtls_ssl_set_session() + * + * \param session The session structure to be populated. It must have been + * initialised with mbedtls_ssl_session_init() but not + * populated yet. + * \param buf The buffer holding the serialized session data. It must be a + * readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * was generated in a different version or configuration of + * Mbed TLS. + * \return Another negative value for other kinds of errors (for + * example, unsupported features in the embedded certificate). + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ); + +/** + * \brief Save session structure as serialized data in a buffer. + * On client, this can be used for saving session data, + * potentially in non-volatile storage, for resuming later. + * On server, this can be used for alternative implementations + * of session cache or session tickets. + * + * \see mbedtls_ssl_session_load() + * + * \param session The session structure to be saved. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p len bytes, or may be \c + * NULL if \p len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + +/** + * \brief Set the list of allowed ciphersuites and the preference + * order. First in the list has the highest preference. + * + * For TLS 1.2, the notion of ciphersuite determines both + * the key exchange mechanism and the suite of symmetric + * algorithms to be used during and after the handshake. + * + * For TLS 1.3 (in development), the notion of ciphersuite + * only determines the suite of symmetric algorithms to be + * used during and after the handshake, while key exchange + * mechanisms are configured separately. + * + * In Mbed TLS, ciphersuites for both TLS 1.2 and TLS 1.3 + * are configured via this function. For users of TLS 1.3, + * there will be separate API for the configuration of key + * exchange mechanisms. + * + * The list of ciphersuites passed to this function may + * contain a mixture of TLS 1.2 and TLS 1.3 ciphersuite + * identifiers. This is useful if negotiation of TLS 1.3 + * should be attempted, but a fallback to TLS 1.2 would + * be tolerated. + * + * \note By default, the server chooses its preferred + * ciphersuite among those that the client supports. If + * mbedtls_ssl_conf_preference_order() is called to prefer + * the client's preferences, the server instead chooses + * the client's preferred ciphersuite among those that + * the server supports. + * + * \warning The ciphersuites array \p ciphersuites is not copied. + * It must remain valid for the lifetime of the SSL + * configuration \p conf. + * + * \param conf The SSL configuration to modify. + * \param ciphersuites A 0-terminated list of IANA identifiers of supported + * ciphersuites, accessible through \c MBEDTLS_TLS_XXX + * and \c MBEDTLS_TLS1_3_XXX macros defined in + * ssl_ciphersuites.h. + */ +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Set the supported key exchange modes for TLS 1.3 connections. + * + * In contrast to TLS 1.2, the ciphersuite concept in TLS 1.3 does not + * include the choice of key exchange mechanism. It is therefore not + * covered by the API mbedtls_ssl_conf_ciphersuites(). See the + * documentation of mbedtls_ssl_conf_ciphersuites() for more + * information on the ciphersuite concept in TLS 1.2 and TLS 1.3. + * + * The present function is specific to TLS 1.3 and allows users to + * configure the set of supported key exchange mechanisms in TLS 1.3. + * + * \param conf The SSL configuration the change should apply to. + * \param kex_modes A bitwise combination of one or more of the following: + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK + * This flag enables pure-PSK key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL + * This flag enables combined PSK-ephemeral key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL + * This flag enables pure-ephemeral key exchanges. + * For convenience, the following pre-defined macros are + * available for combinations of the above: + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL + * Includes all of pure-PSK, PSK-ephemeral and pure-ephemeral. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL + * Includes both pure-PSK and combined PSK-ephemeral + * key exchanges, but excludes pure-ephemeral key exchanges. + * - MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL + * Includes both pure-ephemeral and combined PSK-ephemeral + * key exchanges. + * + * \note If a PSK-based key exchange mode shall be supported, applications + * must also use the APIs mbedtls_ssl_conf_psk() or + * mbedtls_ssl_conf_psk_cb() or mbedtls_ssl_conf_psk_opaque() + * to configure the PSKs to be used. + * + * \note If a pure-ephemeral key exchange mode shall be supported, + * server-side applications must also provide a certificate via + * mbedtls_ssl_conf_own_cert(). + * + */ + +void mbedtls_ssl_conf_tls13_key_exchange_modes( mbedtls_ssl_config* conf, + const int kex_modes ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_UNEXPECTED_CID_IGNORE 0 +#define MBEDTLS_SSL_UNEXPECTED_CID_FAIL 1 +/** + * \brief Specify the length of Connection IDs for incoming + * encrypted DTLS records, as well as the behaviour + * on unexpected CIDs. + * + * By default, the CID length is set to \c 0, + * and unexpected CIDs are silently ignored. + * + * \param conf The SSL configuration to modify. + * \param len The length in Bytes of the CID fields in encrypted + * DTLS records using the CID mechanism. This must + * not be larger than #MBEDTLS_SSL_CID_OUT_LEN_MAX. + * \param ignore_other_cids This determines the stack's behaviour when + * receiving a record with an unexpected CID. + * Possible values are: + * - #MBEDTLS_SSL_UNEXPECTED_CID_IGNORE + * In this case, the record is silently ignored. + * - #MBEDTLS_SSL_UNEXPECTED_CID_FAIL + * In this case, the stack fails with the specific + * error code #MBEDTLS_ERR_SSL_UNEXPECTED_CID. + * + * \note The CID specification allows implementations to either + * use a common length for all incoming connection IDs or + * allow variable-length incoming IDs. Mbed TLS currently + * requires a common length for all connections sharing the + * same SSL configuration; this allows simpler parsing of + * record headers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len + * is too large. + */ +int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, size_t len, + int ignore_other_cids ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set the X.509 security profile used for verification + * + * \note The restrictions are enforced for all certificates in the + * chain. However, signatures in the handshake are not covered + * by this setting but by \b mbedtls_ssl_conf_sig_hashes(). + * + * \param conf SSL configuration + * \param profile Profile to use + */ +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ); + +/** + * \brief Set the data required to verify peer certificate + * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * + * \param conf SSL configuration + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Set the trusted certificate callback. + * + * This API allows to register the set of trusted certificates + * through a callback, instead of a linked list as configured + * by mbedtls_ssl_conf_ca_chain(). + * + * This is useful for example in contexts where a large number + * of CAs are used, and the inefficiency of maintaining them + * in a linked list cannot be tolerated. It is also useful when + * the set of trusted CAs needs to be modified frequently. + * + * See the documentation of `mbedtls_x509_crt_ca_cb_t` for + * more information. + * + * \param conf The SSL configuration to register the callback with. + * \param f_ca_cb The trusted certificate callback to use when verifying + * certificate chains. + * \param p_ca_cb The context to be passed to \p f_ca_cb (for example, + * a reference to a trusted CA database). + * + * \note This API is incompatible with mbedtls_ssl_conf_ca_chain(): + * Any call to this function overwrites the values set through + * earlier calls to mbedtls_ssl_conf_ca_chain() or + * mbedtls_ssl_conf_ca_cb(). + * + * \note This API is incompatible with CA indication in + * CertificateRequest messages: A server-side SSL context which + * is bound to an SSL configuration that uses a CA callback + * configured via mbedtls_ssl_conf_ca_cb(), and which requires + * client authentication, will send an empty CA list in the + * corresponding CertificateRequest message. + * + * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain(): + * If an SSL context is bound to an SSL configuration which uses + * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then + * calls to mbedtls_ssl_set_hs_ca_chain() have no effect. + * + * \note The use of this API disables the use of restartable ECC + * during X.509 CRT signature verification (but doesn't affect + * other uses). + * + * \warning This API is incompatible with the use of CRLs. Any call to + * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through + * earlier calls to mbedtls_ssl_conf_ca_chain(). + * + * \warning In multi-threaded environments, the callback \p f_ca_cb + * must be thread-safe, and it is the user's responsibility + * to guarantee this (for example through a mutex + * contained in the callback context pointed to by \p p_ca_cb). + */ +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +/** + * \brief Set own certificate chain and private key + * + * \note own_cert should contain in order from the bottom up your + * certificate chain. The top certificate (self-signed) + * can be omitted. + * + * \note On server, this function can be called multiple times to + * provision more than one cert/key pair (eg one ECDSA, one + * RSA with SHA-256, one RSA with SHA-1). An adequate + * certificate will be selected according to the client's + * advertised capabilities. In case multiple certificates are + * adequate, preference is given to the one set by the first + * call to this function, then second, etc. + * + * \note On client, only the first call has any effect. That is, + * only one client certificate can be provisioned. The + * server's preferences in its CertficateRequest message will + * be ignored and our only cert will be sent regardless of + * whether it matches those preferences - the server can then + * decide what it wants to do with it. + * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * + * \param conf SSL configuration + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +/** + * \brief Configure pre-shared keys (PSKs) and their + * identities to be used in PSK-based ciphersuites. + * + * Only one PSK can be registered, through either + * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). + * If you attempt to register more than one PSK, this function + * fails, though this may change in future versions, which + * may add support for multiple PSKs. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note A PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * takes precedence over a PSK configured by this function. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The pointer to the pre-shared key to use. + * \param psk_len The length of the pre-shared key in bytes. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK and its identity are copied internally and + * hence need not be preserved by the caller for the lifetime + * of the SSL configuration. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs + * can be configured. In this case, the old PSK(s) remain intact. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Configure one or more opaque pre-shared keys (PSKs) and + * their identities to be used in PSK-based ciphersuites. + * + * Only one PSK can be registered, through either + * mbedtls_ssl_conf_psk() or mbedtls_ssl_conf_psk_opaque(). + * If you attempt to register more than one PSK, this function + * fails, though this may change in future versions, which + * may add support for multiple PSKs. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \note An opaque PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in + * the PSK callback takes precedence over an opaque PSK + * configured by this function. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The identifier of the key slot holding the PSK. + * Until \p conf is destroyed or this function is successfully + * called again, the key slot \p psk must be populated with a + * key of type PSA_ALG_CATEGORY_KEY_DERIVATION whose policy + * allows its use for the key derivation algorithm applied + * in the handshake. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK identity hint is copied internally and hence need + * not be preserved by the caller for the lifetime of the + * SSL configuration. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no more PSKs + * can be configured. In this case, the old PSK(s) remain intact. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_id_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Set the pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \note A PSK set by this function takes precedence over a PSK + * configured by \c mbedtls_ssl_conf_psk(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The pointer to the pre-shared key. + * \param psk_len The length of the pre-shared key in bytes. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Set an opaque pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \note An opaque PSK set by this function takes precedence over an + * opaque PSK configured by \c mbedtls_ssl_conf_psk_opaque(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The identifier of the key slot holding the PSK. + * For the duration of the current handshake, the key slot + * must be populated with a key of type + * PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its + * use for the key derivation algorithm + * applied in the handshake. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_id_t psk ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +/** + * \brief Set the PSK callback (server-side only). + * + * If set, the PSK callback is called for each + * handshake where a PSK-based ciphersuite was negotiated. + * The caller provides the identity received and wants to + * receive the actual PSK data and length. + * + * The callback has the following parameters: + * - \c void*: The opaque pointer \p p_psk. + * - \c mbedtls_ssl_context*: The SSL context to which + * the operation applies. + * - \c const unsigned char*: The PSK identity + * selected by the client. + * - \c size_t: The length of the PSK identity + * selected by the client. + * + * If a valid PSK identity is found, the callback should use + * \c mbedtls_ssl_set_hs_psk() or + * \c mbedtls_ssl_set_hs_psk_opaque() + * on the SSL context to set the correct PSK and return \c 0. + * Any other return value will result in a denied PSK identity. + * + * \note A dynamic PSK (i.e. set by the PSK callback) takes + * precedence over a static PSK (i.e. set by + * \c mbedtls_ssl_conf_psk() or + * \c mbedtls_ssl_conf_psk_opaque()). + * This means that if you set a PSK callback using this + * function, you don't need to set a PSK using + * \c mbedtls_ssl_conf_psk() or + * \c mbedtls_ssl_conf_psk_opaque()). + * + * \param conf The SSL configuration to register the callback with. + * \param f_psk The callback for selecting and setting the PSK based + * in the PSK identity chosen by the client. + * \param p_psk A pointer to an opaque structure to be passed to + * the callback, for example a PSK store. + */ +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Set the Diffie-Hellman public P and G values + * from big-endian binary presentations. + * (Default values: MBEDTLS_DHM_RFC3526_MODP_2048_[PG]_BIN) + * + * \param conf SSL configuration + * \param dhm_P Diffie-Hellman-Merkle modulus in big-endian binary form + * \param P_len Length of DHM modulus + * \param dhm_G Diffie-Hellman-Merkle generator in big-endian binary form + * \param G_len Length of DHM generator + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ); + +/** + * \brief Set the Diffie-Hellman public P and G values, + * read from existing context (server-side only) + * + * \param conf SSL configuration + * \param dhm_ctx Diffie-Hellman-Merkle context + * + * \return 0 if successful + */ +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ); +#endif /* MBEDTLS_DHM_C && defined(MBEDTLS_SSL_SRV_C) */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Set the minimum length for Diffie-Hellman parameters. + * (Client-side only.) + * (Default: 1024 bits.) + * + * \param conf SSL configuration + * \param bitlen Minimum bit length of the DHM prime + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ); +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/** + * \brief Set the allowed curves in order of preference. + * + * On server: this only affects selection of the ECDHE curve; + * the curves used for ECDH and ECDSA are determined by the + * list of available certificates instead. + * + * On client: this affects the list of curves offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of curves accepted for use in + * ECDHE and in the peer's end-entity certificate. + * + * \deprecated Superseeded by mbedtls_ssl_conf_groups(). + * + * \note This has no influence on which curves are allowed inside the + * certificate chains, see \c mbedtls_ssl_conf_cert_profile() + * for that. For the end-entity certificate however, the key + * will be accepted only if it is allowed both by this list + * and by the cert profile. + * + * \note This list should be ordered by decreasing preference + * (preferred curve first). + * + * \note The default list is the same set of curves that + * #mbedtls_x509_crt_profile_default allows, plus + * ECDHE-only curves selected according to the same criteria. + * The order favors curves with the lowest resource usage. + * + * \note New minor versions of Mbed TLS may extend this list, + * for example if new curves are added to the library. + * New minor versions of Mbed TLS will not remove items + * from this list unless serious security concerns require it. + * New minor versions of Mbed TLS may change the order in + * keeping with the general principle of favoring the lowest + * resource usage. + * + * \param conf SSL configuration + * \param curves Ordered list of allowed curves, + * terminated by MBEDTLS_ECP_DP_NONE. + */ +void MBEDTLS_DEPRECATED mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curves ); +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +/** + * \brief Set the allowed groups in order of preference. + * + * On server: This only affects the choice of key agreement mechanism + * + * On client: this affects the list of groups offered for any + * use. The server can override our preference order. + * + * Both sides: limits the set of groups accepted for use in + * key sharing. + * + * \note This function replaces the deprecated mbedtls_ssl_conf_curves(), + * which only allows ECP curves to be configured. + * + * \note The most recent invocation of either mbedtls_ssl_conf_curves() + * or mbedtls_ssl_conf_groups() nullifies all previous invocations + * of both. + * + * \note This list should be ordered by decreasing preference + * (preferred group first). + * + * \note When this function is not called, a default list is used, + * consisting of all supported curves at 255 bits and above, + * and all supported finite fields at 2048 bits and above. + * The order favors groups with the lowest resource usage. + * + * \note New minor versions of Mbed TLS will not remove items + * from the default list unless serious security concerns require it. + * New minor versions of Mbed TLS may change the order in + * keeping with the general principle of favoring the lowest + * resource usage. + * + * \param conf SSL configuration + * \param groups List of allowed groups ordered by preference, terminated by 0. + * Must contain valid IANA NamedGroup IDs (provided via either an integer + * or using MBEDTLS_TLS1_3_NAMED_GROUP_XXX macros). + */ +void mbedtls_ssl_conf_groups( mbedtls_ssl_config *conf, + const uint16_t *groups ); + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/** + * \brief Set the allowed hashes for signatures during the handshake. + * + * \note This only affects which hashes are offered and can be used + * for signatures during the handshake. Hashes for message + * authentication and the TLS PRF are controlled by the + * ciphersuite, see \c mbedtls_ssl_conf_ciphersuites(). Hashes + * used for certificate signature are controlled by the + * verification profile, see \c mbedtls_ssl_conf_cert_profile(). + * + * \note This list should be ordered by decreasing preference + * (preferred hash first). + * + * \note By default, all supported hashes whose length is at least + * 256 bits are allowed. This is the same set as the default + * for certificate verification + * (#mbedtls_x509_crt_profile_default). + * The preference order is currently unspecified and may + * change in future versions. + * + * \note New minor versions of Mbed TLS may extend this list, + * for example if new curves are added to the library. + * New minor versions of Mbed TLS will not remove items + * from this list unless serious security concerns require it. + * + * \param conf SSL configuration + * \param hashes Ordered list of allowed signature hashes, + * terminated by \c MBEDTLS_MD_NONE. + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/** + * \brief Configure allowed signature algorithms for use in TLS 1.3 + * + * \param conf The SSL configuration to use. + * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms, + * terminated by \c MBEDTLS_TLS1_3_SIG_NONE. The list must remain + * available throughout the lifetime of the conf object. Supported + * values are available as \c MBEDTLS_TLS1_3_SIG_XXXX + */ +void mbedtls_ssl_conf_sig_algs( mbedtls_ssl_config *conf, + const uint16_t* sig_algs ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Set or reset the hostname to check against the received + * server certificate. It sets the ServerName TLS extension, + * too, if that extension is enabled. (client-side only) + * + * \param ssl SSL context + * \param hostname the server hostname, may be NULL to clear hostname + + * \note Maximum hostname length MBEDTLS_SSL_MAX_HOST_NAME_LEN. + * + * \return 0 if successful, MBEDTLS_ERR_SSL_ALLOC_FAILED on + * allocation failure, MBEDTLS_ERR_SSL_BAD_INPUT_DATA on + * too long input hostname. + * + * Hostname set to the one provided on success (cleared + * when NULL). On allocation failure hostname is cleared. + * On too long input failure, old hostname is unchanged. + */ +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +/** + * \brief Set own certificate and key for the current handshake + * + * \note Same as \c mbedtls_ssl_conf_own_cert() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param own_cert own public certificate chain + * \param pk_key own private key + * + * \return 0 on success or MBEDTLS_ERR_SSL_ALLOC_FAILED + */ +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ); + +/** + * \brief Set the data required to verify peer certificate for the + * current handshake + * + * \note Same as \c mbedtls_ssl_conf_ca_chain() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param ca_chain trusted CA chain (meaning all fully trusted top-level CAs) + * \param ca_crl trusted CA CRLs + */ +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ); + +/** + * \brief Set authmode for the current handshake. + * + * \note Same as \c mbedtls_ssl_conf_authmode() but for use within + * the SNI callback. + * + * \param ssl SSL context + * \param authmode MBEDTLS_SSL_VERIFY_NONE, MBEDTLS_SSL_VERIFY_OPTIONAL or + * MBEDTLS_SSL_VERIFY_REQUIRED + */ +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ); + +/** + * \brief Set server side ServerName TLS extension callback + * (optional, server-side only). + * + * If set, the ServerName callback is called whenever the + * server receives a ServerName TLS extension from the client + * during a handshake. The ServerName callback has the + * following parameters: (void *parameter, mbedtls_ssl_context *ssl, + * const unsigned char *hostname, size_t len). If a suitable + * certificate is found, the callback must set the + * certificate(s) and key(s) to use with \c + * mbedtls_ssl_set_hs_own_cert() (can be called repeatedly), + * and may optionally adjust the CA and associated CRL with \c + * mbedtls_ssl_set_hs_ca_chain() as well as the client + * authentication mode with \c mbedtls_ssl_set_hs_authmode(), + * then must return 0. If no matching name is found, the + * callback must either set a default cert, or + * return non-zero to abort the handshake at this point. + * + * \param conf SSL configuration + * \param f_sni verification function + * \param p_sni verification parameter + */ +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_sni ); +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/** + * \brief Set the EC J-PAKE password for current handshake. + * + * \note An internal copy is made, and destroyed as soon as the + * handshake is completed, or when the SSL context is reset or + * freed. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pw EC J-PAKE password (pre-shared secret) + * \param pw_len length of pw in bytes + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ); +#endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +/** + * \brief Set the supported Application Layer Protocols. + * + * \param conf SSL configuration + * \param protos Pointer to a NULL-terminated list of supported protocols, + * in decreasing preference order. The pointer to the list is + * recorded by the library for later reference as required, so + * the lifetime of the table must be atleast as long as the + * lifetime of the SSL configuration structure. + * + * \return 0 on success, or MBEDTLS_ERR_SSL_BAD_INPUT_DATA. + */ +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ); + +/** + * \brief Get the name of the negotiated Application Layer Protocol. + * This function should be called after the handshake is + * completed. + * + * \param ssl SSL context + * + * \return Protcol name, or NULL if no protocol was negotiated. + */ +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +#if defined(MBEDTLS_DEBUG_C) +static inline const char *mbedtls_ssl_get_srtp_profile_as_string( mbedtls_ssl_srtp_profile profile ) +{ + switch( profile ) + { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80" ); + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + return( "MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32" ); + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80" ); + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return( "MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32" ); + default: break; + } + return( "" ); +} +#endif /* MBEDTLS_DEBUG_C */ +/** + * \brief Manage support for mki(master key id) value + * in use_srtp extension. + * MKI is an optional part of SRTP used for key management + * and re-keying. See RFC3711 section 3.1 for details. + * The default value is + * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED. + * + * \param conf The SSL configuration to manage mki support. + * \param support_mki_value Enable or disable mki usage. Values are + * #MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED + * or #MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED. + */ +void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf, + int support_mki_value ); + +/** + * \brief Set the supported DTLS-SRTP protection profiles. + * + * \param conf SSL configuration + * \param profiles Pointer to a List of MBEDTLS_TLS_SRTP_UNSET terminated + * supported protection profiles + * in decreasing preference order. + * The pointer to the list is recorded by the library + * for later reference as required, so the lifetime + * of the table must be at least as long as the lifetime + * of the SSL configuration structure. + * The list must not hold more than + * MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH elements + * (excluding the terminating MBEDTLS_TLS_SRTP_UNSET). + * + * \return 0 on success + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA when the list of + * protection profiles is incorrect. + */ +int mbedtls_ssl_conf_dtls_srtp_protection_profiles + ( mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles ); + +/** + * \brief Set the mki_value for the current DTLS-SRTP session. + * + * \param ssl SSL context to use. + * \param mki_value The MKI value to set. + * \param mki_len The length of the MKI value. + * + * \note This function is relevant on client side only. + * The server discovers the mki value during handshake. + * A mki value set on server side using this function + * is ignored. + * + * \return 0 on success + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE + */ +int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len ); +/** + * \brief Get the negotiated DTLS-SRTP informations: + * Protection profile and MKI value. + * + * \warning This function must be called after the handshake is + * completed. The value returned by this function must + * not be trusted or acted upon before the handshake completes. + * + * \param ssl The SSL context to query. + * \param dtls_srtp_info The negotiated DTLS-SRTP informations: + * - Protection profile in use. + * A direct mapping of the iana defined value for protection + * profile on an uint16_t. + http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + * #MBEDTLS_TLS_SRTP_UNSET if the use of SRTP was not negotiated + * or peer's Hello packet was not parsed yet. + * - mki size and value( if size is > 0 ). + */ +void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info ); +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/** + * \brief Set the maximum supported version sent from the client side + * and/or accepted at the server side + * (Default: MBEDTLS_SSL_MAX_MAJOR_VERSION, MBEDTLS_SSL_MAX_MINOR_VERSION) + * + * \note This ignores ciphersuites from higher versions. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (only MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ); + +/** + * \brief Set the minimum accepted SSL/TLS protocol version + * (Default: TLS 1.2) + * + * \note Input outside of the SSL_MAX_XXXXX_VERSION and + * SSL_MIN_XXXXX_VERSION range is ignored. + * + * \note With DTLS, use MBEDTLS_SSL_MINOR_VERSION_3 for DTLS 1.2 + * + * \param conf SSL configuration + * \param major Major version number (only MBEDTLS_SSL_MAJOR_VERSION_3 supported) + * \param minor Minor version number (only MBEDTLS_SSL_MINOR_VERSION_3 supported) + */ +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ); + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +/** + * \brief Enable or disable Encrypt-then-MAC + * (Default: MBEDTLS_SSL_ETM_ENABLED) + * + * \note This should always be enabled, it is a security + * improvement, and should not cause any interoperability + * issue (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param etm MBEDTLS_SSL_ETM_ENABLED or MBEDTLS_SSL_ETM_DISABLED + */ +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ); +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +/** + * \brief Enable or disable Extended Master Secret negotiation. + * (Default: MBEDTLS_SSL_EXTENDED_MS_ENABLED) + * + * \note This should always be enabled, it is a security fix to the + * protocol, and should not cause any interoperability issue + * (used only if the peer supports it too). + * + * \param conf SSL configuration + * \param ems MBEDTLS_SSL_EXTENDED_MS_ENABLED or MBEDTLS_SSL_EXTENDED_MS_DISABLED + */ +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ); +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Whether to send a list of acceptable CAs in + * CertificateRequest messages. + * (Default: do send) + * + * \param conf SSL configuration + * \param cert_req_ca_list MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED or + * MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED + */ +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Set the maximum fragment length to emit and/or negotiate. + * (Typical: the smaller of #MBEDTLS_SSL_IN_CONTENT_LEN and + * #MBEDTLS_SSL_OUT_CONTENT_LEN, usually `2^14` bytes) + * (Server: set maximum fragment length to emit, + * usually negotiated by the client during handshake) + * (Client: set maximum fragment length to emit *and* + * negotiate with the server during handshake) + * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) + * + * \note On the client side, the maximum fragment length extension + * *will not* be used, unless the maximum fragment length has + * been set via this function to a value different than + * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. + * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \note For DTLS, it is also possible to set a limit for the total + * size of daragrams passed to the transport layer, including + * record overhead, see \c mbedtls_ssl_set_mtu(). + * + * \param conf SSL configuration + * \param mfl_code Code for maximum fragment length (allowed values: + * MBEDTLS_SSL_MAX_FRAG_LEN_512, MBEDTLS_SSL_MAX_FRAG_LEN_1024, + * MBEDTLS_SSL_MAX_FRAG_LEN_2048, MBEDTLS_SSL_MAX_FRAG_LEN_4096) + * + * \return 0 if successful or MBEDTLS_ERR_SSL_BAD_INPUT_DATA + */ +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_SRV_C) +/** + * \brief Pick the ciphersuites order according to the second parameter + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * (Default, if never called: MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER) + * + * \param conf SSL configuration + * \param order Server or client (MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER + * or MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) + */ +void mbedtls_ssl_conf_preference_order( mbedtls_ssl_config *conf, int order ); +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Enable / Disable session tickets (client only). + * (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.) + * + * \note On server, use \c mbedtls_ssl_conf_session_tickets_cb(). + * + * \param conf SSL configuration + * \param use_tickets Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or + * MBEDTLS_SSL_SESSION_TICKETS_DISABLED) + */ +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ); +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enable / Disable renegotiation support for connection when + * initiated by peer + * (Default: MBEDTLS_SSL_RENEGOTIATION_DISABLED) + * + * \warning It is recommended to always disable renegotation unless you + * know you need it and you know what you're doing. In the + * past, there have been several issues associated with + * renegotiation or a poor understanding of its properties. + * + * \note Server-side, enabling renegotiation also makes the server + * susceptible to a resource DoS by a malicious client. + * + * \param conf SSL configuration + * \param renegotiation Enable or disable (MBEDTLS_SSL_RENEGOTIATION_ENABLED or + * MBEDTLS_SSL_RENEGOTIATION_DISABLED) + */ +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Prevent or allow legacy renegotiation. + * (Default: MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION) + * + * MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION allows connections to + * be established even if the peer does not support + * secure renegotiation, but does not allow renegotiation + * to take place if not secure. + * (Interoperable and secure option) + * + * MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION allows renegotiations + * with non-upgraded peers. Allowing legacy renegotiation + * makes the connection vulnerable to specific man in the + * middle attacks. (See RFC 5746) + * (Most interoperable and least secure option) + * + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE breaks off connections + * if peer does not support secure renegotiation. Results + * in interoperability issues with non-upgraded peers + * that do not support renegotiation altogether. + * (Most secure option, interoperability issues) + * + * \param conf SSL configuration + * \param allow_legacy Prevent or allow (SSL_NO_LEGACY_RENEGOTIATION, + * SSL_ALLOW_LEGACY_RENEGOTIATION or + * MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE) + */ +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Enforce renegotiation requests. + * (Default: enforced, max_records = 16) + * + * When we request a renegotiation, the peer can comply or + * ignore the request. This function allows us to decide + * whether to enforce our renegotiation requests by closing + * the connection if the peer doesn't comply. + * + * However, records could already be in transit from the peer + * when the request is emitted. In order to increase + * reliability, we can accept a number of records before the + * expected handshake records. + * + * The optimal value is highly dependent on the specific usage + * scenario. + * + * \note With DTLS and server-initiated renegotiation, the + * HelloRequest is retransmited every time mbedtls_ssl_read() times + * out or receives Application Data, until: + * - max_records records have beens seen, if it is >= 0, or + * - the number of retransmits that would happen during an + * actual handshake has been reached. + * Please remember the request might be lost a few times + * if you consider setting max_records to a really low value. + * + * \warning On client, the grace period can only happen during + * mbedtls_ssl_read(), as opposed to mbedtls_ssl_write() and mbedtls_ssl_renegotiate() + * which always behave as if max_record was 0. The reason is, + * if we receive application data from the server, we need a + * place to write it, which only happens during mbedtls_ssl_read(). + * + * \param conf SSL configuration + * \param max_records Use MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED if you don't want to + * enforce renegotiation, or a non-negative value to enforce + * it but allow for a grace period of max_records records. + */ +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ); + +/** + * \brief Set record counter threshold for periodic renegotiation. + * (Default: 2^48 - 1) + * + * Renegotiation is automatically triggered when a record + * counter (outgoing or incoming) crosses the defined + * threshold. The default value is meant to prevent the + * connection from being closed when the counter is about to + * reached its maximal value (it is not allowed to wrap). + * + * Lower values can be used to enforce policies such as "keys + * must be refreshed every N packets with cipher X". + * + * The renegotiation period can be disabled by setting + * conf->disable_renegotiation to + * MBEDTLS_SSL_RENEGOTIATION_DISABLED. + * + * \note When the configured transport is + * MBEDTLS_SSL_TRANSPORT_DATAGRAM the maximum renegotiation + * period is 2^48 - 1, and for MBEDTLS_SSL_TRANSPORT_STREAM, + * the maximum renegotiation period is 2^64 - 1. + * + * \param conf SSL configuration + * \param period The threshold value: a big-endian 64-bit number. + */ +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Check if there is data already read from the + * underlying transport but not yet processed. + * + * \param ssl SSL context + * + * \return 0 if nothing's pending, 1 otherwise. + * + * \note This is different in purpose and behaviour from + * \c mbedtls_ssl_get_bytes_avail in that it considers + * any kind of unprocessed data, not only unread + * application data. If \c mbedtls_ssl_get_bytes + * returns a non-zero value, this function will + * also signal pending data, but the converse does + * not hold. For example, in DTLS there might be + * further records waiting to be processed from + * the current underlying transport's datagram. + * + * \note If this function returns 1 (data pending), this + * does not imply that a subsequent call to + * \c mbedtls_ssl_read will provide any data; + * e.g., the unprocessed data might turn out + * to be an alert or a handshake message. + * + * \note This function is useful in the following situation: + * If the SSL/TLS module successfully returns from an + * operation - e.g. a handshake or an application record + * read - and you're awaiting incoming data next, you + * must not immediately idle on the underlying transport + * to have data ready, but you need to check the value + * of this function first. The reason is that the desired + * data might already be read but not yet processed. + * If, in contrast, a previous call to the SSL/TLS module + * returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary + * to call this function, as the latter error code entails + * that all internal data has been processed. + * + */ +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the number of application data bytes + * remaining to be read from the current record. + * + * \param ssl SSL context + * + * \return How many bytes are available in the application + * data record read buffer. + * + * \note When working over a datagram transport, this is + * useful to detect the current datagram's boundary + * in case \c mbedtls_ssl_read has written the maximal + * amount of data fitting into the input buffer. + * + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the result of the certificate verification + * + * \param ssl The SSL context to use. + * + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure flags; see x509.h. + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the name of the current ciphersuite + * + * \param ssl SSL context + * + * \return a string containing the ciphersuite name + */ +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current TLS version + * + * \param ssl SSL context + * + * \return a string containing the TLS version + */ +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the (maximum) number of bytes added by the record + * layer: header + encryption/MAC overhead (inc. padding) + * + * \param ssl SSL context + * + * \return Current maximum record expansion in bytes + */ +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current maximum outgoing record payload in bytes. + * + * \note The logic to determine the maximum outgoing record payload is + * version-specific. It takes into account various factors, such as + * the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions + * such as the max fragment length or record size limit extension if + * used, and for DTLS the path MTU as configured and current + * record expansion. + * + * \note With DTLS, \c mbedtls_ssl_write() will return an error if + * called with a larger length value. + * With TLS, \c mbedtls_ssl_write() will fragment the input if + * necessary and return the number of bytes written; it is up + * to the caller to call \c mbedtls_ssl_write() again in + * order to send the remaining bytes if any. + * + * \sa mbedtls_ssl_get_max_out_record_payload() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an outgoing record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the current maximum incoming record payload in bytes. + * + * \note The logic to determine the maximum outgoing record payload is + * version-specific. It takes into account various factors, such as + * the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN, extensions + * such as the max fragment length extension or record size limit + * extension if used, and the current record expansion. + * + * \sa mbedtls_ssl_set_mtu() + * \sa mbedtls_ssl_get_max_in_record_payload() + * \sa mbedtls_ssl_get_record_expansion() + * + * \param ssl SSL context + * + * \return Current maximum payload for an outgoing record, + * or a negative error code. + */ +int mbedtls_ssl_get_max_in_record_payload( const mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * \brief Return the peer certificate from the current connection. + * + * \param ssl The SSL context to use. This must be initialized and setup. + * + * \return The current peer certificate, if available. + * The returned certificate is owned by the SSL context and + * is valid only until the next call to the SSL API. + * \return \c NULL if no peer certificate is available. This might + * be because the chosen ciphersuite doesn't use CRTs + * (PSK-based ciphersuites, for example), or because + * #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled, + * allowing the stack to free the peer's CRT to save memory. + * + * \note For one-time inspection of the peer's certificate during + * the handshake, consider registering an X.509 CRT verification + * callback through mbedtls_ssl_conf_verify() instead of calling + * this function. Using mbedtls_ssl_conf_verify() also comes at + * the benefit of allowing you to influence the verification + * process, for example by masking expected and tolerated + * verification failures. + * + * \warning You must not use the pointer returned by this function + * after any further call to the SSL API, including + * mbedtls_ssl_read() and mbedtls_ssl_write(); this is + * because the pointer might change during renegotiation, + * which happens transparently to the user. + * If you want to use the certificate across API calls, + * you must make a copy. + */ +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +/** + * \brief Export a session in order to resume it later. + * + * \param ssl The SSL context representing the connection for which to + * to export a session structure for later resumption. + * \param session The target structure in which to store the exported session. + * This must have been initialized with mbedtls_ssl_init_session() + * but otherwise be unused. + * + * \note This function can handle a variety of mechanisms for session + * resumption: For TLS 1.2, both session ID-based resumption and + * ticket-based resumption will be considered. For TLS 1.3, + * once implemented, sessions equate to tickets, and calling + * this function multiple times will export the available + * tickets one a time until no further tickets are available, + * in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will + * be returned. + * + * \note Calling this function multiple times will only be useful + * once TLS 1.3 is supported. For TLS 1.2 connections, this + * function should be called at most once. + * + * \return \c 0 if successful. In this case, \p session can be used for + * session resumption by passing it to mbedtls_ssl_set_session(), + * and serialized for storage via mbedtls_ssl_session_save(). + * \return #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session + * is available for export. + * This error is a non-fatal, and has no observable effect on + * the SSL context or the destination session. + * \return Another negative error code on other kinds of failure. + * + * \sa mbedtls_ssl_set_session() + * \sa mbedtls_ssl_session_save() + */ +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, + mbedtls_ssl_session *session ); +#endif /* MBEDTLS_SSL_CLI_C */ + +/** + * \brief Perform the SSL handshake + * + * \param ssl SSL context + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. + * + * \note Remarks regarding event-driven DTLS: + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. This is not true for a successful handshake, + * in which case the datagram of the underlying transport that is + * currently being processed might or might not contain further + * DTLS records. + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Perform a single step of the SSL handshake + * + * \note The state of the context (ssl->state) will be at + * the next state after this function returns \c 0. Do not + * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. + * + * \param ssl SSL context + * + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + */ +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/** + * \brief Initiate an SSL renegotiation on the running connection. + * Client: perform the renegotiation right now. + * Server: request renegotiation, which will be performed + * during the next call to mbedtls_ssl_read() if honored by + * client. + * + * \param ssl SSL context + * + * \return 0 if successful, or any mbedtls_ssl_handshake() return + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. + * + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/** + * \brief Read at most 'len' application data bytes + * + * \param ssl SSL context + * \param buf buffer that will hold the data + * \param len maximum number of bytes to read + * + * \return The (positive) number of bytes read if successful. + * \return \c 0 if the read end of the underlying transport was closed + * without sending a CloseNotify beforehand, which might happen + * because of various reasons (internal error of an underlying + * stack, non-conformant peer not sending a CloseNotify and + * such) - in this case you must stop using the context + * (see below). + * \return #MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY if the underlying + * transport is still functional, but the peer has + * acknowledged to not send anything anymore. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new connection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * (which can only happen server-side), it means that a client + * is initiating a new connection using the same source port. + * You can either treat that as a connection close and wait + * for the client to resend a ClientHello, or directly + * continue with \c mbedtls_ssl_handshake() with the same + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new + * connection: application state, if any, should be reset, and + * most importantly the identity of the client must be checked + * again. WARNING: not validating the identity of the client + * again, or not transmitting the new identity to the + * application layer, would allow authentication bypass! + * + * \note Remarks regarding event-driven DTLS: + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram + * from the underlying transport layer is currently being processed, + * and it is safe to idle until the timer or the underlying transport + * signal a new event. + * - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was + * initially available on the underlying transport, as this data may have + * been only e.g. duplicated messages or a renegotiation request. + * Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even + * when reacting to an incoming-data event from the underlying transport. + * - On success, the datagram of the underlying transport that is currently + * being processed may contain further DTLS records. You should call + * \c mbedtls_ssl_check_pending to check for remaining records. + * + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ); + +/** + * \brief Try to write exactly 'len' application data bytes + * + * \warning This function will do partial writes in some cases. If the + * return value is non-negative but less than length, the + * function must be called again with updated arguments: + * buf + ret, len - ret (if ret is the return value) until + * it returns a value equal to the last 'len' argument. + * + * \param ssl SSL context + * \param buf buffer holding the data + * \param len how many bytes must be written + * + * \return The (non-negative) number of bytes actually written if + * successful (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * if the handshake is incomplete and waiting for data to + * be available for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). + * + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * it must be called later with the *same* arguments, + * until it returns a value greater that or equal to 0. When + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. + * + * \note If the requested length is greater than the maximum + * fragment length (either the built-in limit or the one set + * or negotiated with the peer), then: + * - with TLS, less bytes than requested are written. + * - with DTLS, MBEDTLS_ERR_SSL_BAD_INPUT_DATA is returned. + * \c mbedtls_ssl_get_max_out_record_payload() may be used to + * query the active maximum fragment length. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ); + +/** + * \brief Send an alert message + * + * \param ssl SSL context + * \param level The alert level of the message + * (MBEDTLS_SSL_ALERT_LEVEL_WARNING or MBEDTLS_SSL_ALERT_LEVEL_FATAL) + * \param message The alert message (SSL_ALERT_MSG_*) + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ); +/** + * \brief Notify the peer that the connection is being closed + * + * \param ssl SSL context + * + * \return 0 if successful, or a specific SSL error code. + * + * \note If this function returns something other than 0 or + * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using + * the SSL context for reading or writing, and either free it or + * call \c mbedtls_ssl_session_reset() on it before re-using it + * for a new connection; the current connection must be closed. + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ); + +/** + * \brief Free referenced items in an SSL context and clear memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) +/** + * \brief Save an active connection as serialized data in a buffer. + * This allows the freeing or re-using of the SSL context + * while still picking up the connection later in a way that + * it entirely transparent to the peer. + * + * \see mbedtls_ssl_context_load() + * + * \note This feature is currently only available under certain + * conditions, see the documentation of the return value + * #MBEDTLS_ERR_SSL_BAD_INPUT_DATA for details. + * + * \note When this function succeeds, it calls + * mbedtls_ssl_session_reset() on \p ssl which as a result is + * no longer associated with the connection that has been + * serialized. This avoids creating copies of the connection + * state. You're then free to either re-use the context + * structure for a different connection, or call + * mbedtls_ssl_free() on it. See the documentation of + * mbedtls_ssl_session_reset() for more details. + * + * \param ssl The SSL context to save. On success, it is no longer + * associated with the connection that has been serialized. + * \param buf The buffer to write the serialized data to. It must be a + * writeable buffer of at least \p buf_len bytes, or may be \c + * NULL if \p buf_len is \c 0. + * \param buf_len The number of bytes available for writing in \p buf. + * \param olen The size in bytes of the data that has been or would have + * been written. It must point to a valid \c size_t. + * + * \note \p olen is updated to the correct value regardless of + * whether \p buf_len was large enough. This makes it possible + * to determine the necessary size by calling this function + * with \p buf set to \c NULL and \p buf_len to \c 0. However, + * the value of \p olen is only guaranteed to be correct when + * the function returns #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL or + * \c 0. If the return value is different, then the value of + * \p olen is undefined. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed + * while reseting the context. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if a handshake is in + * progress, or there is pending data for reading or sending, + * or the connection does not use DTLS 1.2 with an AEAD + * ciphersuite, or renegotiation is enabled. + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ); + +/** + * \brief Load serialized connection data to an SSL context. + * + * \see mbedtls_ssl_context_save() + * + * \warning The same serialized data must never be loaded into more + * that one context. In order to ensure that, after + * successfully loading serialized data to an SSL context, you + * should immediately destroy or invalidate all copies of the + * serialized data that was loaded. Loading the same data in + * more than one context would cause severe security failures + * including but not limited to loss of confidentiality. + * + * \note Before calling this function, the SSL context must be + * prepared in one of the two following ways. The first way is + * to take a context freshly initialised with + * mbedtls_ssl_init() and call mbedtls_ssl_setup() on it with + * the same ::mbedtls_ssl_config structure that was used in + * the original connection. The second way is to + * call mbedtls_ssl_session_reset() on a context that was + * previously prepared as above but used in the meantime. + * Either way, you must not use the context to perform a + * handshake between calling mbedtls_ssl_setup() or + * mbedtls_ssl_session_reset() and calling this function. You + * may however call other setter functions in that time frame + * as indicated in the note below. + * + * \note Before or after calling this function successfully, you + * also need to configure some connection-specific callbacks + * and settings before you can use the connection again + * (unless they were already set before calling + * mbedtls_ssl_session_reset() and the values are suitable for + * the present connection). Specifically, you want to call + * at least mbedtls_ssl_set_bio() and + * mbedtls_ssl_set_timer_cb(). All other SSL setter functions + * are not necessary to call, either because they're only used + * in handshakes, or because the setting is already saved. You + * might choose to call them anyway, for example in order to + * share code between the cases of establishing a new + * connection and the case of loading an already-established + * connection. + * + * \note If you have new information about the path MTU, you want to + * call mbedtls_ssl_set_mtu() after calling this function, as + * otherwise this function would overwrite your + * newly-configured value with the value that was active when + * the context was saved. + * + * \note When this function returns an error code, it calls + * mbedtls_ssl_free() on \p ssl. In this case, you need to + * prepare the context with the usual sequence starting with a + * call to mbedtls_ssl_init() if you want to use it again. + * + * \param ssl The SSL context structure to be populated. It must have + * been prepared as described in the note above. + * \param buf The buffer holding the serialized connection data. It must + * be a readable buffer of at least \p len bytes. + * \param len The size of the serialized data in bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_SSL_VERSION_MISMATCH if the serialized data + * comes from a different Mbed TLS version or build. + * \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid. + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ); +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/** + * \brief Initialize an SSL configuration context + * Just makes the context ready for + * mbedtls_ssl_config_defaults() or mbedtls_ssl_config_free(). + * + * \note You need to call mbedtls_ssl_config_defaults() unless you + * manually set all of the relevant fields yourself. + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ); + +/** + * \brief Load reasonnable default SSL configuration values. + * (You need to call mbedtls_ssl_config_init() first.) + * + * \param conf SSL configuration context + * \param endpoint MBEDTLS_SSL_IS_CLIENT or MBEDTLS_SSL_IS_SERVER + * \param transport MBEDTLS_SSL_TRANSPORT_STREAM for TLS, or + * MBEDTLS_SSL_TRANSPORT_DATAGRAM for DTLS + * \param preset a MBEDTLS_SSL_PRESET_XXX value + * + * \note See \c mbedtls_ssl_conf_transport() for notes on DTLS. + * + * \return 0 if successful, or + * MBEDTLS_ERR_XXX_ALLOC_FAILED on memory allocation error. + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ); + +/** + * \brief Free an SSL configuration context + * + * \param conf SSL configuration context + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ); + +/** + * \brief Initialize SSL session structure + * + * \param session SSL session + */ +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ); + +/** + * \brief Free referenced items in an SSL session including the + * peer certificate and clear memory + * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +/** + * \brief TLS-PRF function for key derivation. + * + * \param prf The tls_prf type function type to be used. + * \param secret Secret for the key derivation function. + * \param slen Length of the secret. + * \param label String label for the key derivation function, + * terminated with null character. + * \param random Random bytes. + * \param rlen Length of the random bytes buffer. + * \param dstbuf The buffer holding the derived key. + * \param dlen Length of the output buffer. + * + * \return 0 on success. An SSL specific error on failure. + */ +int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_cache.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_cache.h new file mode 100644 index 00000000..6a81ac99 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_cache.h @@ -0,0 +1,161 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT) +#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */ +#endif + +#if !defined(MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES) +#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct mbedtls_ssl_cache_context mbedtls_ssl_cache_context; +typedef struct mbedtls_ssl_cache_entry mbedtls_ssl_cache_entry; + +/** + * \brief This structure is used for storing cache entries + */ +struct mbedtls_ssl_cache_entry +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t MBEDTLS_PRIVATE(timestamp); /*!< entry timestamp */ +#endif + + unsigned char MBEDTLS_PRIVATE(session_id)[32]; /*!< session ID */ + size_t MBEDTLS_PRIVATE(session_id_len); + + unsigned char *MBEDTLS_PRIVATE(session); /*!< serialized session */ + size_t MBEDTLS_PRIVATE(session_len); + + mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(next); /*!< chain pointer */ +}; + +/** + * \brief Cache context + */ +struct mbedtls_ssl_cache_context +{ + mbedtls_ssl_cache_entry *MBEDTLS_PRIVATE(chain); /*!< start of the chain */ + int MBEDTLS_PRIVATE(timeout); /*!< cache entry timeout */ + int MBEDTLS_PRIVATE(max_entries); /*!< maximum entries */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< mutex */ +#endif +}; + +/** + * \brief Initialize an SSL cache context + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ); + +/** + * \brief Cache get callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * for the session to load. + * \param session_id_len The length of \p session_id in bytes. + * \param session The address at which to store the session + * associated with \p session_id, if present. + */ +int mbedtls_ssl_cache_get( void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session ); + +/** + * \brief Cache set callback implementation + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data The SSL cache context to use. + * \param session_id The pointer to the buffer holding the session ID + * associated to \p session. + * \param session_id_len The length of \p session_id in bytes. + * \param session The session to store. + */ +int mbedtls_ssl_cache_set( void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session ); + +#if defined(MBEDTLS_HAVE_TIME) +/** + * \brief Set the cache timeout + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT (1 day)) + * + * A timeout of 0 indicates no timeout. + * + * \param cache SSL cache context + * \param timeout cache entry timeout in seconds + */ +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ); +#endif /* MBEDTLS_HAVE_TIME */ + +/** + * \brief Set the maximum number of cache entries + * (Default: MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES (50)) + * + * \param cache SSL cache context + * \param max cache entry maximum + */ +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ); + +/** + * \brief Free referenced items in a cache context and clear memory + * + * \param cache SSL cache context + */ +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cache.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_ciphersuites.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 00000000..18e7c987 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,535 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/pk.h" +#include "mbedtls/cipher.h" +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Supported ciphersuites (Official IANA names) + */ +#define MBEDTLS_TLS_RSA_WITH_NULL_MD5 0x01 /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA 0x02 /**< Weak! */ + +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA 0x2C /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA 0x2D /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA 0x2E /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA 0x2F + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x33 +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA 0x35 +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x39 + +#define MBEDTLS_TLS_RSA_WITH_NULL_SHA256 0x3B /**< Weak! */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 0x3C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 0x3D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x41 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x45 + +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 0x67 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 0x6B /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x84 +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x88 + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA 0x8C +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA 0x8D + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA 0x90 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA 0x91 + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA 0x94 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA 0x95 + +#define MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 0x9C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 0x9D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 0x9E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 0x9F /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 0xA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 0xA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 0xAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 0xAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 0xAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 0xAD /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 0xAE +#define MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 0xAF +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA256 0xB0 /**< Weak! */ +#define MBEDTLS_TLS_PSK_WITH_NULL_SHA384 0xB1 /**< Weak! */ + +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 0xB2 +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 0xB3 +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 0xB4 /**< Weak! */ +#define MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 0xB5 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 0xB6 +#define MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 0xB7 +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 0xB8 /**< Weak! */ +#define MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 0xB9 /**< Weak! */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xBE /**< TLS 1.2 */ + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 0xC4 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001 /**< Weak! */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xC004 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xC005 + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA 0xC006 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xC009 +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xC00A + +#define MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA 0xC00B /**< Weak! */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xC00E +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0xC00F + +#define MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA 0xC010 /**< Weak! */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xC013 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xC014 + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 0xC023 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 0xC024 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 0xC025 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 0xC026 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 0xC027 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 0xC028 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 0xC029 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 0xC02A /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 0xC02B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 0xC02C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 0xC02D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 0xC02E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 0xC02F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 0xC030 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 0xC031 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 0xC032 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA 0xC035 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA 0xC036 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 0xC037 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 0xC038 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA 0xC039 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 0xC03A +#define MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 0xC03B + +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 0xC03C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 0xC03D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC044 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC045 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC048 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC049 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 0xC04A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 0xC04B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 0xC04C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 0xC04D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 0xC04E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 0xC04F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 0xC050 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 0xC051 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC052 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC053 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 0xC05E /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 0xC05F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 0xC060 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 0xC061 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 0xC062 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 0xC063 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 0xC064 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 0xC065 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC066 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC067 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 0xC068 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 0xC069 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 0xC06A /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 0xC06B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 0xC06C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 0xC06D /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 0xC06E /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 0xC06F /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 0xC070 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 0xC071 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC072 +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC073 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 0xC074 +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 0xC075 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC076 +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC077 +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 0xC078 +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 0xC079 + +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07A /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07B /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC07C /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC07D /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC086 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC087 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 0xC088 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 0xC089 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08A /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08B /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 0xC08C /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 0xC08D /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC08E /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC08F /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC090 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC091 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 0xC092 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 0xC093 /**< TLS 1.2 */ + +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC094 +#define MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC095 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC096 +#define MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC097 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC098 +#define MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC099 +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0xC09A +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0xC09B + +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM 0xC09C /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM 0xC09D /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM 0xC09E /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM 0xC09F /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 0xC0A0 /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 0xC0A1 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 0xC0A2 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 0xC0A3 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM 0xC0A4 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM 0xC0A5 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM 0xC0A6 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM 0xC0A7 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 0xC0A8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 0xC0A9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 0xC0AA /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 0xC0AB /**< TLS 1.2 */ +/* The last two are named with PSK_DHE in the RFC, which looks like a typo */ + +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM 0xC0AC /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM 0xC0AD /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 0xC0AE /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 0xC0AF /**< TLS 1.2 */ + +#define MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 0xC0FF /**< experimental */ + +/* RFC 7905 */ +#define MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA8 /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0xCCA9 /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0xCCAA /**< TLS 1.2 */ +#define MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAB /**< TLS 1.2 */ +#define MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAC /**< TLS 1.2 */ +#define MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAD /**< TLS 1.2 */ +#define MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 0xCCAE /**< TLS 1.2 */ + +/* RFC 8446, Appendix B.4 */ +#define MBEDTLS_TLS1_3_AES_128_GCM_SHA256 0x1301 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_256_GCM_SHA384 0x1302 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256 0x1303 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_128_CCM_SHA256 0x1304 /**< TLS 1.3 */ +#define MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256 0x1305 /**< TLS 1.3 */ + +/* Reminder: update mbedtls_ssl_premaster_secret when adding a new key exchange. + * Reminder: update MBEDTLS_KEY_EXCHANGE__xxx below + */ +typedef enum { + MBEDTLS_KEY_EXCHANGE_NONE = 0, + MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_KEY_EXCHANGE_ECJPAKE, +} mbedtls_key_exchange_type_t; + +/* Key exchanges using a certificate */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED +#endif + +/* Key exchanges allowing client certificate requests */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED +#endif + +/* Key exchanges involving server signature in ServerKeyExchange */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED +#endif + +/* Key exchanges using ECDH */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED +#endif + +/* Key exchanges that don't involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED +#endif + +/* Key exchanges that involve ephemeral keys */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED +#endif + +/* Key exchanges using a PSK */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED +#endif + +/* Key exchanges using DHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED +#endif + +/* Key exchanges using ECDHE */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED +#endif + +typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t; + +#define MBEDTLS_CIPHERSUITE_WEAK 0x01 /**< Weak ciphersuite flag */ +#define MBEDTLS_CIPHERSUITE_SHORT_TAG 0x02 /**< Short authentication tag, + eg for CCM_8 */ +#define MBEDTLS_CIPHERSUITE_NODTLS 0x04 /**< Can't be used with DTLS */ + +/** + * \brief This structure is used for storing ciphersuite information + */ +struct mbedtls_ssl_ciphersuite_t +{ + int MBEDTLS_PRIVATE(id); + const char * MBEDTLS_PRIVATE(name); + + mbedtls_cipher_type_t MBEDTLS_PRIVATE(cipher); + mbedtls_md_type_t MBEDTLS_PRIVATE(mac); + mbedtls_key_exchange_type_t MBEDTLS_PRIVATE(key_exchange); + + int MBEDTLS_PRIVATE(min_major_ver); + int MBEDTLS_PRIVATE(min_minor_ver); + int MBEDTLS_PRIVATE(max_major_ver); + int MBEDTLS_PRIVATE(max_minor_ver); + + unsigned char MBEDTLS_PRIVATE(flags); +}; + +const int *mbedtls_ssl_list_ciphersuites( void ); + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( const char *ciphersuite_name ); +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite_id ); + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ); +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ); +#endif + +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ); +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_has_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) +static inline int mbedtls_ssl_ciphersuite_no_pfs( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdh( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + +static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_ecdhe( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +static inline int mbedtls_ssl_ciphersuite_uses_server_signature( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->MBEDTLS_PRIVATE(key_exchange) ) + { + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ciphersuites.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_cookie.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_cookie.h new file mode 100644 index 00000000..86698b05 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_cookie.h @@ -0,0 +1,110 @@ +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ +#ifndef MBEDTLS_SSL_COOKIE_TIMEOUT +#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ +#endif + +/* \} name SECTION: Module settings */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Context for the default cookie functions. + */ +typedef struct mbedtls_ssl_cookie_ctx +{ + mbedtls_md_context_t MBEDTLS_PRIVATE(hmac_ctx); /*!< context for the HMAC portion */ +#if !defined(MBEDTLS_HAVE_TIME) + unsigned long MBEDTLS_PRIVATE(serial); /*!< serial number for expiration */ +#endif + unsigned long MBEDTLS_PRIVATE(timeout); /*!< timeout delay, in seconds if HAVE_TIME, + or in number of tickets issued */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); +#endif +} mbedtls_ssl_cookie_ctx; + +/** + * \brief Initialize cookie context + */ +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Setup cookie context (generate keys) + */ +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Set expiration delay for cookies + * (Default MBEDTLS_SSL_COOKIE_TIMEOUT) + * + * \param ctx Cookie contex + * \param delay Delay, in seconds if HAVE_TIME, or in number of cookies + * issued in the meantime. + * 0 to disable expiration (NOT recommended) + */ +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ); + +/** + * \brief Free cookie context + */ +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ); + +/** + * \brief Generate cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_write_t mbedtls_ssl_cookie_write; + +/** + * \brief Verify cookie, see \c mbedtls_ssl_cookie_write_t + */ +mbedtls_ssl_cookie_check_t mbedtls_ssl_cookie_check; + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_cookie.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_ticket.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_ticket.h new file mode 100644 index 00000000..0f4117d3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/ssl_ticket.h @@ -0,0 +1,137 @@ +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +/* + * This implementation of the session ticket callbacks includes key + * management, rotating the keys periodically in order to preserve forward + * secrecy, when MBEDTLS_HAVE_TIME is defined. + */ + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Information for session ticket protection + */ +typedef struct mbedtls_ssl_ticket_key +{ + unsigned char MBEDTLS_PRIVATE(name)[4]; /*!< random key identifier */ + uint32_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */ + mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx); /*!< context for auth enc/decryption */ +} +mbedtls_ssl_ticket_key; + +/** + * \brief Context for session ticket handling functions + */ +typedef struct mbedtls_ssl_ticket_context +{ + mbedtls_ssl_ticket_key MBEDTLS_PRIVATE(keys)[2]; /*!< ticket protection keys */ + unsigned char MBEDTLS_PRIVATE(active); /*!< index of the currently active key */ + + uint32_t MBEDTLS_PRIVATE(ticket_lifetime); /*!< lifetime of tickets in seconds */ + + /** Callback for getting (pseudo-)random numbers */ + int (*MBEDTLS_PRIVATE(f_rng))(void *, unsigned char *, size_t); + void *MBEDTLS_PRIVATE(p_rng); /*!< context for the RNG function */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); +#endif +} +mbedtls_ssl_ticket_context; + +/** + * \brief Initialize a ticket context. + * (Just make it ready for mbedtls_ssl_ticket_setup() + * or mbedtls_ssl_ticket_free().) + * + * \param ctx Context to be initialized + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ); + +/** + * \brief Prepare context to be actually used + * + * \param ctx Context to be set up + * \param f_rng RNG callback function (mandatory) + * \param p_rng RNG callback context + * \param cipher AEAD cipher to use for ticket protection. + * Recommended value: MBEDTLS_CIPHER_AES_256_GCM. + * \param lifetime Tickets lifetime in seconds + * Recommended value: 86400 (one day). + * + * \note It is highly recommended to select a cipher that is at + * least as strong as the strongest ciphersuite + * supported. Usually that means a 256-bit key. + * + * \note The lifetime of the keys is twice the lifetime of tickets. + * It is recommended to pick a reasonnable lifetime so as not + * to negate the benefits of forward secrecy. + * + * \return 0 if successful, + * or a specific MBEDTLS_ERR_XXX error code + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ); + +/** + * \brief Implementation of the ticket write callback + * + * \note See \c mbedtls_ssl_ticket_write_t for description + */ +mbedtls_ssl_ticket_write_t mbedtls_ssl_ticket_write; + +/** + * \brief Implementation of the ticket parse callback + * + * \note See \c mbedtls_ssl_ticket_parse_t for description + */ +mbedtls_ssl_ticket_parse_t mbedtls_ssl_ticket_parse; + +/** + * \brief Free a context's content and zeroize it. + * + * \param ctx Context to be cleaned up + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_ticket.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/threading.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/threading.h new file mode 100644 index 00000000..fbc73747 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/threading.h @@ -0,0 +1,118 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C +/** Locking / unlocking / free failed with error code. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct mbedtls_threading_mutex_t +{ + pthread_mutex_t MBEDTLS_PRIVATE(mutex); + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ + char MBEDTLS_PRIVATE(is_valid); +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +/* This mutex may or may not be used in the default definition of + * mbedtls_platform_gmtime_r(), but in order to determine that, + * we need to check POSIX features, hence modify _POSIX_C_SOURCE. + * With the current approach, this declaration is orphaned, lacking + * an accompanying definition, in case mbedtls_platform_gmtime_r() + * doesn't need it, but that's not a problem. */ +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/timing.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/timing.h new file mode 100644 index 00000000..25db1c6a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/timing.h @@ -0,0 +1,97 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char MBEDTLS_PRIVATE(opaque)[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context +{ + struct mbedtls_timing_hr_time MBEDTLS_PRIVATE(timer); + uint32_t MBEDTLS_PRIVATE(int_ms); + uint32_t MBEDTLS_PRIVATE(fin_ms); +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +/* Internal use */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/version.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/version.h new file mode 100644 index 00000000..773da4a6 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/version.h @@ -0,0 +1,90 @@ +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * This set of run-time variables can be used to determine the version number of + * the Mbed TLS library used. Compile-time version defines for the same can be + * found in build_info.h + */ +#ifndef MBEDTLS_VERSION_H +#define MBEDTLS_VERSION_H + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_VERSION_C) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Get the version number. + * + * \return The constructed version number in the format + * MMNNPP00 (Major, Minor, Patch). + */ +unsigned int mbedtls_version_get_number( void ); + +/** + * Get the version string ("x.y.z"). + * + * \param string The string that will receive the value. + * (Should be at least 9 bytes in size) + */ +void mbedtls_version_get_string( char *string ); + +/** + * Get the full version string ("mbed TLS x.y.z"). + * + * \param string The string that will receive the value. The mbed TLS version + * string will use 18 bytes AT MOST including a terminating + * null byte. + * (So the buffer should be at least 18 bytes to receive this + * version string). + */ +void mbedtls_version_get_string_full( char *string ); + +/** + * \brief Check if support for a feature was compiled into this + * mbed TLS binary. This allows you to see at runtime if the + * library was for instance compiled with or without + * Multi-threading support. + * + * \note only checks against defines in the sections "System + * support", "mbed TLS modules" and "mbed TLS feature + * support" in mbedtls_config.h + * + * \param feature The string for the define to check (e.g. "MBEDTLS_AES_C") + * + * \return 0 if the feature is present, + * -1 if the feature is not present and + * -2 if support for feature checking as a whole was not + * compiled in. + */ +int mbedtls_version_check_feature( const char *feature ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_VERSION_C */ + +#endif /* version.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509.h new file mode 100644 index 00000000..9a4be95a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509.h @@ -0,0 +1,367 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/asn1.h" +#include "mbedtls/pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +/** Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 +/** Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 +/** The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 +/** The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 +/** The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 +/** The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 +/** The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 +/** The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 +/** The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 +/** The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 +/** CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 +/** Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 +/** Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 +/** Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 +/** Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 +/** Input invalid. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 +/** Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 +/** Read/write of file failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 +/** Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 +/** A fatal error occurred, eg the chain is too long or the vrfy callback failed. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Subject Alternative Name types. + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER + */ +#define MBEDTLS_X509_SAN_OTHER_NAME 0 +#define MBEDTLS_X509_SAN_RFC822_NAME 1 +#define MBEDTLS_X509_SAN_DNS_NAME 2 +#define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3 +#define MBEDTLS_X509_SAN_DIRECTORY_NAME 4 +#define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5 +#define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6 +#define MBEDTLS_X509_SAN_IP_ADDRESS 7 +#define MBEDTLS_X509_SAN_REGISTERED_ID 8 + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + * + * Those are defined in oid.h as oid.c needs them in a data structure. Since + * these were previously defined here, let's have aliases for compatibility. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define MBEDTLS_X509_EXT_KEY_USAGE MBEDTLS_OID_X509_EXT_KEY_USAGE +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY +#define MBEDTLS_X509_EXT_FRESHEST_CRL MBEDTLS_OID_X509_EXT_FRESHEST_CRL +#define MBEDTLS_X509_EXT_NS_CERT_TYPE MBEDTLS_OID_X509_EXT_NS_CERT_TYPE + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occurred, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +#if !defined(MBEDTLS_X509_REMOVE_INFO) +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +#endif +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_crl.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_crl.h new file mode 100644 index 00000000..52bd43cd --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_crl.h @@ -0,0 +1,186 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields points to is unspecified. + */ +typedef struct mbedtls_x509_crl_entry +{ + /** Direct access to the whole entry inside the containing buffer. */ + mbedtls_x509_buf raw; + /** The serial number of the revoked certificate. */ + mbedtls_x509_buf serial; + /** The revocation date of this entry. */ + mbedtls_x509_time revocation_date; + /** Direct access to the list of CRL entry extensions + * (an ASN.1 constructed sequence). + * + * If there are no extensions, `entry_ext.len == 0` and + * `entry_ext.p == NULL`. */ + mbedtls_x509_buf entry_ext; + + /** Next element in the linked list of entries. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf MBEDTLS_PRIVATE(sig_oid2); + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + /** Next element in the linked list of CRL. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Multiple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_crt.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_crt.h new file mode 100644 index 00000000..3c11a998 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_crt.h @@ -0,0 +1,1193 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/x509.h" +#include "mbedtls/x509_crl.h" +#include "mbedtls/bignum.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields points to is unspecified. + */ +typedef struct mbedtls_x509_crt +{ + int MBEDTLS_PRIVATE(own_buffer); /**< Indicates if \c raw is owned + * by the structure or not. */ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_x509_buf pk_raw; + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */ + + mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */ + + int MBEDTLS_PRIVATE(ext_types); /**< Bit string containing detected and parsed extensions */ + int MBEDTLS_PRIVATE(ca_istrue); /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int MBEDTLS_PRIVATE(max_pathlen); /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int MBEDTLS_PRIVATE(key_usage); /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char MBEDTLS_PRIVATE(ns_cert_type); /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + /** Next certificate in the linked list that constitutes the CA chain. + * \p NULL indicates the end of the list. + * Do not modify this field directly. */ + struct mbedtls_x509_crt *next; +} +mbedtls_x509_crt; + +/** + * From RFC 5280 section 4.2.1.6: + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * Future versions of the library may add new fields to this structure or + * to its embedded union and structure. + */ +typedef struct mbedtls_x509_san_other_name +{ + /** + * The type_id is an OID as deifned in RFC 5280. + * To check the value of the type id, you should use + * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf. + */ + mbedtls_x509_buf type_id; /**< The type id. */ + union + { + /** + * From RFC 4108 section 5: + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + */ + struct + { + mbedtls_x509_buf oid; /**< The object identifier. */ + mbedtls_x509_buf val; /**< The named value. */ + } + hardware_module_name; + } + value; +} +mbedtls_x509_san_other_name; + +/** + * A structure for holding the parsed Subject Alternative Name, + * according to type. + * + * Future versions of the library may add new fields to this structure or + * to its embedded union and structure. + */ +typedef struct mbedtls_x509_subject_alternative_name +{ + int type; /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */ + union { + mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */ + mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */ + } + san; /**< A union of the supported SAN types */ +} +mbedtls_x509_subject_alternative_name; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( (id) - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + * + * The fields of this structure are part of the public API and can be + * manipulated directly by applications. Future versions of the library may + * add extra fields or reorder existing fields. + * + * You can create custom profiles by starting from a copy of + * an existing profile, such as mbedtls_x509_crt_profile_default or + * mbedtls_x509_ctr_profile_none and then tune it to your needs. + * + * For example to allow SHA-224 in addition to the default: + * + * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_default; + * my_profile.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ); + * + * Or to allow only RSA-3072+ with SHA-256: + * + * mbedtls_x509_crt_profile my_profile = mbedtls_x509_crt_profile_none; + * my_profile.allowed_mds = MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ); + * my_profile.allowed_pks = MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_RSA ); + * my_profile.rsa_min_bitlen = 3072; + */ +typedef struct mbedtls_x509_crt_profile +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/* This macro unfolds to the concatenation of macro invocations + * X509_CRT_ERROR_INFO( error code, + * error code as string, + * human readable description ) + * where X509_CRT_ERROR_INFO is defined by the user. + * See x509_crt.c for an example of how to use this. */ +#define MBEDTLS_X509_CRT_ERROR_INFO_LIST \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_EXPIRED, \ + "MBEDTLS_X509_BADCERT_EXPIRED", \ + "The certificate validity has expired" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_REVOKED, \ + "MBEDTLS_X509_BADCERT_REVOKED", \ + "The certificate has been revoked (is on a CRL)" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_CN_MISMATCH, \ + "MBEDTLS_X509_BADCERT_CN_MISMATCH", \ + "The certificate Common Name (CN) does not match with the expected CN" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_NOT_TRUSTED, \ + "MBEDTLS_X509_BADCERT_NOT_TRUSTED", \ + "The certificate is not correctly signed by the trusted CA" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCRL_NOT_TRUSTED, \ + "MBEDTLS_X509_BADCRL_NOT_TRUSTED", \ + "The CRL is not correctly signed by the trusted CA" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCRL_EXPIRED, \ + "MBEDTLS_X509_BADCRL_EXPIRED", \ + "The CRL is expired" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_MISSING, \ + "MBEDTLS_X509_BADCERT_MISSING", \ + "Certificate was missing" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_SKIP_VERIFY, \ + "MBEDTLS_X509_BADCERT_SKIP_VERIFY", \ + "Certificate verification was skipped" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_OTHER, \ + "MBEDTLS_X509_BADCERT_OTHER", \ + "Other reason (can be used by verify callback)" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_FUTURE, \ + "MBEDTLS_X509_BADCERT_FUTURE", \ + "The certificate validity starts in the future" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCRL_FUTURE, \ + "MBEDTLS_X509_BADCRL_FUTURE", \ + "The CRL is from the future" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_KEY_USAGE, \ + "MBEDTLS_X509_BADCERT_KEY_USAGE", \ + "Usage does not match the keyUsage extension" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, \ + "MBEDTLS_X509_BADCERT_EXT_KEY_USAGE", \ + "Usage does not match the extendedKeyUsage extension" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_NS_CERT_TYPE, \ + "MBEDTLS_X509_BADCERT_NS_CERT_TYPE", \ + "Usage does not match the nsCertType extension" ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_BAD_MD, \ + "MBEDTLS_X509_BADCERT_BAD_MD", \ + "The certificate is signed with an unacceptable hash." ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_BAD_PK, \ + "MBEDTLS_X509_BADCERT_BAD_PK", \ + "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCERT_BAD_KEY, \ + "MBEDTLS_X509_BADCERT_BAD_KEY", \ + "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCRL_BAD_MD, \ + "MBEDTLS_X509_BADCRL_BAD_MD", \ + "The CRL is signed with an unacceptable hash." ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCRL_BAD_PK, \ + "MBEDTLS_X509_BADCRL_BAD_PK", \ + "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." ) \ + X509_CRT_ERROR_INFO( MBEDTLS_X509_BADCRL_BAD_KEY, \ + "MBEDTLS_X509_BADCRL_BAD_KEY", \ + "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." ) + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int MBEDTLS_PRIVATE(version); + mbedtls_mpi MBEDTLS_PRIVATE(serial); + mbedtls_pk_context *MBEDTLS_PRIVATE(subject_key); + mbedtls_pk_context *MBEDTLS_PRIVATE(issuer_key); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(issuer); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + char MBEDTLS_PRIVATE(not_before)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char MBEDTLS_PRIVATE(not_after)[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); +} +mbedtls_x509write_cert; + +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *MBEDTLS_PRIVATE(crt); + uint32_t MBEDTLS_PRIVATE(flags); +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item MBEDTLS_PRIVATE(items)[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + unsigned MBEDTLS_PRIVATE(len); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* This stores the list of potential trusted signers obtained from + * the CA callback used for the CRT verification, if configured. + * We must track it somewhere because the callback passes its + * ownership to the caller. */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(trust_ca_cb_result); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} mbedtls_x509_crt_verify_chain; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + /* for check_signature() */ + mbedtls_pk_restart_ctx MBEDTLS_PRIVATE(pk); + + /* for find_parent_in() */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(parent); /* non-null iff parent_in in progress */ + mbedtls_x509_crt *MBEDTLS_PRIVATE(fallback_parent); + int MBEDTLS_PRIVATE(fallback_signature_is_good); + + /* for find_parent() */ + int MBEDTLS_PRIVATE(parent_is_trusted); /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } MBEDTLS_PRIVATE(in_progress); /* none if no operation is in progress */ + int MBEDTLS_PRIVATE(self_cnt); + mbedtls_x509_crt_verify_chain MBEDTLS_PRIVATE(ver_chain); + +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + * + * This profile permits: + * - SHA2 hashes with at least 256 bits: SHA-256, SHA-384, SHA-512. + * - Elliptic curves with 255 bits and above except secp256k1. + * - RSA with 2048 bits and above. + * + * New minor versions of Mbed TLS may extend this profile, for example if + * new algorithms are added to the library. New minor versions of Mbed TLS will + * not reduce this profile unless serious security concerns require it. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for allowing RSA-2048. + * This profile may change at any time. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * Empty profile that allows nothing. Useful as a basis for constructing + * custom profiles. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The buffer holding the DER encoded certificate. + * \param buflen The size in Bytes of \p buf. + * + * \note This function makes an internal copy of the CRT buffer + * \p buf. In particular, \p buf may be destroyed or reused + * after this call returns. To avoid duplicating the CRT + * buffer (at the cost of stricter lifetime constraints), + * use mbedtls_x509_crt_parse_der_nocopy() instead. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ); + +/** + * \brief The type of certificate extension callbacks. + * + * Callbacks of this type are passed to and used by the + * mbedtls_x509_crt_parse_der_with_ext_cb() routine when + * it encounters either an unsupported extension or a + * "certificate policies" extension containing any + * unsupported certificate policies. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \param p_ctx An opaque context passed to the callback. + * \param crt The certificate being parsed. + * \param oid The OID of the extension. + * \param critical Whether the extension is critical. + * \param p Pointer to the start of the extension value + * (the content of the OCTET STRING). + * \param end End of extension value. + * + * \note The callback must fail and return a negative error code + * if it can not parse or does not support the extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ext_cb_t)( void *p_ctx, + mbedtls_x509_crt const *crt, + mbedtls_x509_buf const *oid, + int critical, + const unsigned char *p, + const unsigned char *end ); + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The buffer holding the DER encoded certificate. + * \param buflen The size in Bytes of \p buf. + * \param make_copy When not zero this function makes an internal copy of the + * CRT buffer \p buf. In particular, \p buf may be destroyed + * or reused after this call returns. + * When zero this function avoids duplicating the CRT buffer + * by taking temporary ownership thereof until the CRT + * is destroyed (like mbedtls_x509_crt_parse_der_nocopy()) + * \param cb A callback invoked for every unsupported certificate + * extension. + * \param p_ctx An opaque context passed to the callback. + * + * \note This call is functionally equivalent to + * mbedtls_x509_crt_parse_der(), and/or + * mbedtls_x509_crt_parse_der_nocopy() + * but it calls the callback with every unsupported + * certificate extension and additionally the + * "certificate policies" extension if it contains any + * unsupported certificate policies. + * The callback must return a negative error code if it + * does not know how to handle such an extension. + * When the callback fails to parse a critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() also fails. + * When the callback fails to parse a non critical extension + * mbedtls_x509_crt_parse_der_with_ext_cb() simply skips + * the extension and continues parsing. + * Future versions of the library may invoke the callback + * in other cases, if and when the need arises. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ); + +/** + * \brief Parse a single DER formatted certificate and add it + * to the end of the provided chained list. This is a + * variant of mbedtls_x509_crt_parse_der() which takes + * temporary ownership of the CRT buffer until the CRT + * is destroyed. + * + * \param chain The pointer to the start of the CRT chain to attach to. + * When parsing the first CRT in a chain, this should point + * to an instance of ::mbedtls_x509_crt initialized through + * mbedtls_x509_crt_init(). + * \param buf The address of the readable buffer holding the DER encoded + * certificate to use. On success, this buffer must be + * retained and not be changed for the liftetime of the + * CRT chain \p chain, that is, until \p chain is destroyed + * through a call to mbedtls_x509_crt_free(). + * \param buflen The size in Bytes of \p buf. + * + * \note This call is functionally equivalent to + * mbedtls_x509_crt_parse_der(), but it avoids creating a + * copy of the input buffer at the cost of stronger lifetime + * constraints. This is useful in constrained environments + * where duplication of the CRT cannot be tolerated. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. + * + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. + * + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); + +#endif /* MBEDTLS_FS_IO */ +/** + * \brief This function parses an item in the SubjectAlternativeNames + * extension. + * + * \param san_buf The buffer holding the raw data item of the subject + * alternative name. + * \param san The target structure to populate with the parsed presentation + * of the subject alternative name encoded in \p san_raw. + * + * \note Only "dnsName" and "otherName" of type hardware_module_name + * as defined in RFC 4180 is supported. + * + * \note This function should be called on a single raw data of + * subject alternative name. For example, after successful + * certificate parsing, one must iterate on every item in the + * \p crt->subject_alt_names sequence, and pass it to + * this function. + * + * \warning The target structure contains pointers to the raw data of the + * parsed certificate, and its lifetime is restricted by the + * lifetime of the certificate. + * + * \return \c 0 on success + * \return #MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE for an unsupported + * SAN type. + * \return Another negative value for any other failure. + */ +int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san ); + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +/** + * \brief Verify a chain of certificates. + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param cn The expected Common Name. This will be checked to be + * present in the certificate's subjectAltNames extension or, + * if this extension is absent, as a CN component in its + * Subject name. Currently only DNS names are supported. This + * may be \c NULL if the CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify a chain of certificates with respect to + * a configurable security profile. + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * \param rs_ctx The restart context to use. This may be set to \c NULL + * to disable restartable ECC. + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + +/** + * \brief The type of trusted certificate callbacks. + * + * Callbacks of this type are passed to and used by the CRT + * verification routine mbedtls_x509_crt_verify_with_ca_cb() + * when looking for trusted signers of a given certificate. + * + * On success, the callback returns a list of trusted + * certificates to be considered as potential signers + * for the input certificate. + * + * \param p_ctx An opaque context passed to the callback. + * \param child The certificate for which to search a potential signer. + * This will point to a readable certificate. + * \param candidate_cas The address at which to store the address of the first + * entry in the generated linked list of candidate signers. + * This will not be \c NULL. + * + * \note The callback must only return a non-zero value on a + * fatal error. If, in contrast, the search for a potential + * signer completes without a single candidate, the + * callback must return \c 0 and set \c *candidate_cas + * to \c NULL. + * + * \return \c 0 on success. In this case, \c *candidate_cas points + * to a heap-allocated linked list of instances of + * ::mbedtls_x509_crt, and ownership of this list is passed + * to the caller. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, + mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidate_cas ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which + * uses a callback to acquire the list of trusted CA + * certificates. + * + * \param crt The certificate chain to be verified. + * \param f_ca_cb The callback to be used to query for potential signers + * of a given child certificate. See the documentation of + * ::mbedtls_x509_crt_ca_cb_t for more information. + * \param p_ca_cb The opaque context to be passed to \p f_ca_cb. + * \param profile The security profile for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return See \c mbedtls_crt_verify_with_profile(). + */ +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); + +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note \p f_rng is used for the signature operation. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note \p f_rng is used for the signature operation. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_csr.h b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_csr.h new file mode 100644 index 00000000..f80a1a13 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/mbedtls/x509_csr.h @@ -0,0 +1,304 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_X509_CSR_H +#define MBEDTLS_X509_CSR_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include "mbedtls/x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for X.509 Certificate Signing Requests (CSR) + * \{ + */ + +/** + * Certificate Signing Request (CSR) structure. + * + * Some fields of this structure are publicly readable. Do not modify + * them except via Mbed TLS library functions: the effect of modifying + * those fields or the data that those fields point to is unspecified. + */ +typedef struct mbedtls_x509_csr +{ + mbedtls_x509_buf raw; /**< The raw CSR data (DER). */ + mbedtls_x509_buf cri; /**< The raw CertificateRequestInfo body (DER). */ + + int version; /**< CSR version (1=v1). */ + + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf sig_oid; + mbedtls_x509_buf MBEDTLS_PRIVATE(sig); + mbedtls_md_type_t MBEDTLS_PRIVATE(sig_md); /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t MBEDTLS_PRIVATE(sig_pk); /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *MBEDTLS_PRIVATE(sig_opts); /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ +} +mbedtls_x509_csr; + +/** + * Container for writing a CSR + */ +typedef struct mbedtls_x509write_csr +{ + mbedtls_pk_context *MBEDTLS_PRIVATE(key); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject); + mbedtls_md_type_t MBEDTLS_PRIVATE(md_alg); + mbedtls_asn1_named_data *MBEDTLS_PRIVATE(extensions); +} +mbedtls_x509write_csr; + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +/** + * \brief Load a Certificate Signing Request (CSR) in DER format + * + * \note CSR attributes (if any) are currently silently ignored. + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 error code + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Load a Certificate Signing Request (CSR), DER or PEM format + * + * \note See notes for \c mbedtls_x509_csr_parse_der() + * + * \param csr CSR context to fill + * \param buf buffer holding the CRL data + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load a Certificate Signing Request (CSR) + * + * \note See notes for \c mbedtls_x509_csr_parse() + * + * \param csr CSR context to fill + * \param path filename to read the CSR from + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Returns an informational string about the + * CSR. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param csr The X509 CSR to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ); +#endif /* !MBEDTLS_X509_REMOVE_INFO */ + +/** + * \brief Initialize a CSR + * + * \param csr CSR to initialize + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ); + +/** + * \brief Unallocate all CSR data + * + * \param csr CSR to free + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CSR_WRITE_C) +/** + * \brief Initialize a CSR context + * + * \param ctx CSR context to initialize + */ +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ); + +/** + * \brief Set the subject name for a CSR + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CSR context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ); + +/** + * \brief Set the key for a CSR (public key will be included, + * private key used to sign the CSR when writing it) + * + * \param ctx CSR context to use + * \param key Asymetric key to include + */ +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CSR context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CSR context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. + */ +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CSR context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Generic function to add to or replace an extension in the + * CSR + * + * \param ctx CSR context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical Set to 1 to mark the extension as critical, 0 otherwise. + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Free the contents of a CSR context + * + * \param ctx CSR context to free + */ +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ); + +/** + * \brief Write a CSR (Certificate Signing Request) to a + * DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note \p f_rng is used for the signature operation. + */ +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a CSR (Certificate Signing Request) to a + * PEM string + * + * \param ctx CSR to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function. This must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note \p f_rng is used for the signature operation. + */ +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CSR_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_csr.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto.h new file mode 100644 index 00000000..1643b2e3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto.h @@ -0,0 +1,4114 @@ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography module + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#include "crypto_platform.h" + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param key The persistent identifier for the key. + */ +static void psa_set_key_id( psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t key ); + +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER +/** Set the owner identifier of a key. + * + * When key identifiers encode key owner identifiers, psa_set_key_id() does + * not allow to define in key attributes the owner of volatile keys as + * psa_set_key_id() enforces the key to be persistent. + * + * This function allows to set in key attributes the owner identifier of a + * key. It is intended to be used for volatile keys. For persistent keys, + * it is recommended to use the PSA Cryptography API psa_set_key_id() to define + * the owner of a key. + * + * \param[out] attributes The attribute structure to write to. + * \param owner The key owner identifier. + */ +static void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes, + mbedtls_key_owner_id_t owner ); +#endif + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static mbedtls_svc_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * - An algorithm built from #PSA_ALG_AT_LEAST_THIS_LENGTH_MAC allows + * any MAC algorithm from the same base class (e.g. CMAC) which + * generates/verifies a MAC length greater than or equal to the length + * encoded in the wildcard algorithm. + * - An algorithm built from #PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG + * allows any AEAD algorithm from the same base class (e.g. CCM) which + * generates/verifies a tag length greater than or equal to the length + * encoded in the wildcard algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] key Identifier of the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Remove non-essential copies of key material from memory. + * + * If the key identifier designates a volatile key, this functions does not do + * anything and returns successfully. + * + * If the key identifier designates a persistent key, then this function will + * free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and the key can still be used. + * + * \param key Identifier of the key to purge. + * + * \retval #PSA_SUCCESS + * The key material will have been removed from memory if it is not + * currently required. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_purge_key(mbedtls_svc_key_id_t key); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_key The key to copy. It must allow the usage + * #PSA_KEY_USAGE_COPY. If a private or secret key is + * being copied outside of a secure element it must + * also allow #PSA_KEY_USAGE_EXPORT. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_key is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *target_key); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param key Identifier of the key to erase. If this is \c 0, do nothing and + * return #PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p key was a valid identifier and the key material that it + * referred to has been erased. Alternatively, \p key is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p key is not a valid identifier nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was an failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_DATA_INVALID + * This error is typically a result of either storage corruption on a + * cleartext storage backend, or an attempt to read data that was + * written by an incompatible version of the library. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] key On success, an identifier to the newly created key. + * For persistent keys, this is the key identifier + * defined in \p attributes. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + mbedtls_svc_key_id_t *key); + + + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEY_PAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_FAMILY_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_FAMILY_SECTXXX`, `PSA_ECC_FAMILY_SECPXXX` + * and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`). + * For Weierstrass curves, this is the content of the `privateKey` field of + * the `ECPrivateKey` format defined by RFC 5915. For Montgomery curves, + * the format is defined by RFC 7748, and output is masked according to §5. + * For twisted Edwards curves, the private key is as defined by RFC 8032 + * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). + * - For Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \param key Identifier of the key to export. It must allow the + * usage #PSA_KEY_USAGE_EXPORT, unless it is a public + * key. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_EXPORT_KEY_OUTPUT_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve keys on a twisted Edwards curve (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true and #PSA_KEY_TYPE_ECC_GET_FAMILY + * returns #PSA_ECC_FAMILY_TWISTED_EDWARDS), the public key is as defined + * by RFC 8032 + * (a 32-byte string for Edwards25519, a 57-byte string for Edwards448). + * - For other elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint. + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * - For Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \param key Identifier of the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_EXPORT_KEY_OUTPUT_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length); + + + +/**@}*/ + +/** \defgroup hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_LENGTH(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it muct be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_LENGTH(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param key Identifier of the key to use for the operation. It + * must allow the usage PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage PSA_KEY_USAGE_SIGN_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation. + * + * This function sets up the verification of the MAC + * (message authentication code) of a byte string against an expected value. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. It + * must remain valid until the operation terminates. + * It must allow the usage + * PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_LENGTH(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. You can determine a + * sufficient buffer size by calling PSA_MAC_LENGTH(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param key Identifier of the key to use for the operation. + * It must allow the usage #PSA_KEY_USAGE_ENCRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param key Identifier of the key to use for the + * operation. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, + * \p alg, \p plaintext_length) where + * \c key_type is the type of \p key. + * - #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p + * plaintext_length) evaluates to the maximum + * ciphertext size of any supported AEAD + * encryption. + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small. + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\c key_type, \p alg, + * \p plaintext_length) or + * #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length) can be used to + * determine the required buffer size. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param key Identifier of the key to use for the + * operation. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, + * \p alg, \p ciphertext_length) where + * \c key_type is the type of \p key. + * - #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p + * ciphertext_length) evaluates to the maximum + * plaintext size of any supported AEAD + * decryption. + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size is too small. + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\c key_type, \p alg, + * \p ciphertext_length) or + * #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length) can be used + * to determine the required buffer size. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param key Identifier of the key to use for the operation. + * It must remain valid until the operation + * terminates. It must allow the usage + * #PSA_KEY_USAGE_DECRYPT. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + * operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, + * \c alg, \p input_length) where + * \c key_type is the type of key and \c alg is + * the algorithm that were used to set up the + * operation. + * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p + * input_length) evaluates to the maximum + * output size of any supported AEAD + * algorithm. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or + * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to + * determine the required buffer size. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, + * \c alg) where \c key_type is the type of key + * and \c alg is the algorithm that were used to + * set up the operation. + * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to + * the maximum output size of any supported AEAD + * algorithm. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c + * key_type, \c key_bits, \c alg) where + * \c key_type and \c key_bits are the type and + * bit-size of the key, and \c alg is the + * algorithm that were used in the call to + * psa_aead_encrypt_setup(). + * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the + * maximum tag size of any supported AEAD + * algorithm. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, \c alg) or + * #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE can be used to determine the + * required \p ciphertext buffer size. #PSA_AEAD_TAG_LENGTH(\c key_type, + * \c key_bits, \c alg) or #PSA_AEAD_TAG_MAX_SIZE can be used to + * determine the required \p tag buffer size. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be appropriate for the selected algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, + * \c alg) where \c key_type is the type of key + * and \c alg is the algorithm that were used to + * set up the operation. + * - #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE evaluates to + * the maximum output size of any supported AEAD + * algorithm. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c key_type, \c alg) or + * #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE can be used to determine the + * required buffer size. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a message with a private key. For hash-and-sign algorithms, + * this includes the hashing step. + * + * \note To perform a multi-part hash-and-sign signature algorithm, first use + * a multi-part hash operation and then pass the resulting hash to + * psa_sign_hash(). PSA_ALG_GET_HASH(\p alg) can be used to determine the + * hash algorithm to use. + * + * \param[in] key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_MESSAGE. + * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) + * is true), that is compatible with the type of + * \p key. + * \param[in] input The input message to sign. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. This + * must be appropriate for the selected + * algorithm and key: + * - The required signature size is + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of key. + * - #PSA_SIGNATURE_MAX_SIZE evaluates to the + * maximum signature size of any supported + * signature algorithm. + * \param[out] signature_length On success, the number of bytes that make up + * the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, + * or it does not permit the requested algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_message( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t * input, + size_t input_length, + uint8_t * signature, + size_t signature_size, + size_t * signature_length ); + +/** \brief Verify the signature of a message with a public key, using + * a hash-and-sign verification algorithm. + * + * \note To perform a multi-part hash-and-sign signature verification + * algorithm, first use a multi-part hash operation to hash the message + * and then pass the resulting hash to psa_verify_hash(). + * PSA_ALG_GET_HASH(\p alg) can be used to determine the hash algorithm + * to use. + * + * \param[in] key Identifier of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. The key must allow the usage + * #PSA_KEY_USAGE_VERIFY_MESSAGE. + * \param[in] alg An asymmetric signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_MESSAGE(\p alg) + * is true), that is compatible with the type of + * \p key. + * \param[in] input The message whose signature is to be verified. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_SIGN_MESSAGE flag, + * or it does not permit the requested algorithm. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed signature + * is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_message( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t * input, + size_t input_length, + const uint8_t * signature, + size_t signature_length ); + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). + * Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. The key must + * allow the usage #PSA_KEY_USAGE_SIGN_HASH. + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature of a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(), or alternatively by calling psa_hash_compute(). + * Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param key Identifier of the key to use for the operation. It + * must be a public key or an asymmetric key pair. The + * key must allow the usage + * #PSA_KEY_USAGE_VERIFY_HASH. + * \param alg A signature algorithm (PSA_ALG_XXX + * value such that #PSA_ALG_IS_SIGN_HASH(\p alg) + * is true), that is compatible with + * the type of \p key. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was perfomed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param key Identifer of the key to use for the operation. + * It must be a public key or an asymmetric key + * pair. It must allow the usage + * #PSA_KEY_USAGE_ENCRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param key Identifier of the key to use for the operation. + * It must be an asymmetric key pair. It must + * allow the usage #PSA_KEY_USAGE_DECRYPT. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p key. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INVALID_PADDING + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide a numeric input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * However, when an algorithm requires a particular order, numeric inputs + * usually come first as they tend to be configuration parameters. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function is used for inputs which are fixed-size non-negative + * integers. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] value The value of the numeric input. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow numeric inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_integer( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + uint64_t value); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param key Identifier of the key. It must have an + * appropriate type for step and must allow the + * usage #PSA_KEY_USAGE_DERIVE or + * #PSA_KEY_USAGE_VERIFY_DERIVATION (see note) + * and the algorithm used by the operation. + * + * \note Once all inputs steps are completed, the operations will allow: + * - psa_key_derivation_output_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_output_key() if the input for step + * #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD + * was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was + * either a direct input or a key with #PSA_KEY_USAGE_DERIVE set; + * - psa_key_derivation_verify_bytes() if each input was either a direct input + * or a key with #PSA_KEY_USAGE_VERIFY_DERIVATION set; + * - psa_key_derivation_verify_key() under the same conditions as + * psa_key_derivation_verify_bytes(). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * The key allows neither #PSA_KEY_USAGE_DERIVE nor + * #PSA_KEY_USAGE_VERIFY_DERIVATION, or it doesn't allow this + * algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type and on the key size + * (denoted \c bits below): + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\c bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARIA; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC; + * - #PSA_KEY_TYPE_PASSWORD_HASH. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - Curve25519 (#PSA_ECC_FAMILY_MONTGOMERY, 255 bits): draw a 32-byte + * string and process it as specified in RFC 7748 §5. + * - Curve448 (#PSA_ECC_FAMILY_MONTGOMERY, 448 bits): draw a 56-byte + * string and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \c bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\c bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * If the key type to be created is + * #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in + * the policy must be the same as in the current + * operation. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a + * key; or one of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_DERIVE. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key); + +/** Compare output data from a key derivation operation to an expected value. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value in constant time. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the expected number of bytes from the + * stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to the following code: + * \code + * psa_key_derivation_output_bytes(operation, tmp, output_length); + * if (memcmp(output, tmp, output_length) != 0) + * return PSA_ERROR_INVALID_SIGNATURE; + * \endcode + * except (1) it works even if the key's policy does not allow outputting the + * bytes, and (2) the comparison will be done in constant time. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected_output Buffer containing the expected derivation output. + * \param output_length Length ot the expected output; this is also the + * number of bytes that will be read. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but it differs from the expected + * output. + * \retval #PSA_ERROR_NOT_PERMITTED + * One of the inputs was a key whose policy didn't allow + * #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_bytes( + psa_key_derivation_operation_t *operation, + const uint8_t *expected_output, + size_t output_length); + +/** Compare output data from a key derivation operation to an expected value + * stored in a key object. + * + * This function calculates output bytes from a key derivation algorithm and + * compares those bytes to an expected value, provided as key of type + * #PSA_KEY_TYPE_PASSWORD_HASH. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the number of bytes corresponding the the + * length of the expected value from the stream before comparing them. + * The operation's capacity decreases by the number of bytes read. + * + * This is functionally equivalent to exporting the key and calling + * psa_key_derivation_verify_bytes() on the result, except that it + * works even if the key cannot be exported. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA or #PSA_ERROR_INVALID_SIGNATURE, + * the operation enters an error state and must be aborted by calling + * psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[in] expected A key of type #PSA_KEY_TYPE_PASSWORD_HASH + * containing the expected output. Its policy must + * include the #PSA_KEY_USAGE_VERIFY_DERIVATION flag + * and the permitted algorithm must match the + * operation. The value of this key was likely + * computed by a previous call to + * psa_key_derivation_output_key(). + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The output was read successfully, but if differs from the expected + * output. + * \retval #PSA_ERROR_INVALID_HANDLE + * The key passed as the expected value does not exist. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key passed as the expected value has an invalid type. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key passed as the expected value does not allow this usage or + * this algorithm; or one of the inputs was a key whose policy didn't + * allow #PSA_KEY_USAGE_VERIFY_DERIVATION. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * the length of the expected value. In this case, + * the operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller expected output. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_verify_key( + psa_key_derivation_operation_t *operation, + psa_key_id_t expected); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Identifier of the private key to use. It must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] key On success, an identifier for the newly created + * key. For persistent keys, this is the key + * identifier defined in \p attributes. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "crypto_sizes.h" + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#include "crypto_struct.h" + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_builtin_composites.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_builtin_composites.h new file mode 100644 index 00000000..e11e239c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_builtin_composites.h @@ -0,0 +1,115 @@ +/* + * Context structure declaration of the Mbed TLS software-based PSA drivers + * called through the PSA Crypto driver dispatch layer. + * This file contains the context structures of those algorithms which need to + * rely on other algorithms, i.e. are 'composite' algorithms. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the Mbed TLS software-based PSA drivers. The + * definition of these objects are then used by crypto_struct.h to define the + * implementation-defined types of PSA multi-part state objects. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H +#define PSA_CRYPTO_BUILTIN_COMPOSITES_H +#include "mbedtls/private_access.h" + +#include + +/* + * MAC multi-part operation definitions. + */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) +#define MBEDTLS_PSA_BUILTIN_MAC +#endif + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) +typedef struct +{ + /** The HMAC algorithm in use */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + /** The hash context. */ + struct psa_hash_operation_s hash_ctx; + /** The HMAC part of the context. */ + uint8_t MBEDTLS_PRIVATE(opad)[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; +} mbedtls_psa_hmac_operation_t; + +#define MBEDTLS_PSA_HMAC_OPERATION_INIT {0, PSA_HASH_OPERATION_INIT, {0}} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + +#include "mbedtls/cmac.h" + +typedef struct +{ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + union + { + unsigned MBEDTLS_PRIVATE(dummy); /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_psa_hmac_operation_t MBEDTLS_PRIVATE(hmac); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) || defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cmac); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ + } MBEDTLS_PRIVATE(ctx); +} mbedtls_psa_mac_operation_t; + +#define MBEDTLS_PSA_MAC_OPERATION_INIT {0, {0}} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) +#define MBEDTLS_PSA_BUILTIN_AEAD 1 +#endif + +/* Context structure for the Mbed TLS AEAD implementation. */ +typedef struct +{ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_key_type_t MBEDTLS_PRIVATE(key_type); + + unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; + + uint8_t MBEDTLS_PRIVATE(tag_length); + + union + { + unsigned dummy; /* Enable easier initializing of the union. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + mbedtls_ccm_context MBEDTLS_PRIVATE(ccm); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + mbedtls_gcm_context MBEDTLS_PRIVATE(gcm); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + mbedtls_chachapoly_context MBEDTLS_PRIVATE(chachapoly); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + + } ctx; + +} mbedtls_psa_aead_operation_t; + +#define MBEDTLS_PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, {0}} + +#endif /* PSA_CRYPTO_BUILTIN_COMPOSITES_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_builtin_primitives.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_builtin_primitives.h new file mode 100644 index 00000000..d3cf33a9 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_builtin_primitives.h @@ -0,0 +1,117 @@ +/* + * Context structure declaration of the Mbed TLS software-based PSA drivers + * called through the PSA Crypto driver dispatch layer. + * This file contains the context structures of those algorithms which do not + * rely on other algorithms, i.e. are 'primitive' algorithms. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the Mbed TLS software-based PSA drivers. The + * definition of these objects are then used by crypto_struct.h to define the + * implementation-defined types of PSA multi-part state objects. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H +#define PSA_CRYPTO_BUILTIN_PRIMITIVES_H +#include "mbedtls/private_access.h" + +#include + +/* + * Hash multi-part operation definitions. + */ + +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) +#define MBEDTLS_PSA_BUILTIN_HASH +#endif + +typedef struct +{ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + union + { + unsigned dummy; /* Make the union non-empty even with no supported algorithms. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + mbedtls_md5_context md5; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + mbedtls_ripemd160_context ripemd160; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + mbedtls_sha1_context sha1; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + mbedtls_sha256_context sha256; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + mbedtls_sha512_context sha512; +#endif + } MBEDTLS_PRIVATE(ctx); +} mbedtls_psa_hash_operation_t; + +#define MBEDTLS_PSA_HASH_OPERATION_INIT {0, {0}} + +/* + * Cipher multi-part operation definitions. + */ + +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_XTS) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) +#define MBEDTLS_PSA_BUILTIN_CIPHER 1 +#endif + +typedef struct { + /* Context structure for the Mbed TLS cipher implementation. */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + uint8_t MBEDTLS_PRIVATE(iv_length); + uint8_t MBEDTLS_PRIVATE(block_length); + union { + unsigned int MBEDTLS_PRIVATE(dummy); + mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher); + } MBEDTLS_PRIVATE(ctx); +} mbedtls_psa_cipher_operation_t; + +#define MBEDTLS_PSA_CIPHER_OPERATION_INIT {0, 0, 0, {0}} + +#endif /* PSA_CRYPTO_BUILTIN_PRIMITIVES_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_compat.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_compat.h new file mode 100644 index 00000000..1d3253cb --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_compat.h @@ -0,0 +1,165 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * To support both openless APIs and psa_open_key() temporarily, define + * psa_key_handle_t to be equal to mbedtls_svc_key_id_t. Do not mark the + * type and its utility macros and functions deprecated yet. This will be done + * in a subsequent phase. + */ +typedef mbedtls_svc_key_id_t psa_key_handle_t; + +#define PSA_KEY_HANDLE_INIT MBEDTLS_SVC_KEY_ID_INIT + +/** Check whether an handle is null. + * + * \param handle Handle + * + * \return Non-zero if the handle is null, zero otherwise. + */ +static inline int psa_key_handle_is_null( psa_key_handle_t handle ) +{ + return( mbedtls_svc_key_id_is_null( handle ) ); +} + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have an application + * key identifier in the vendor range, as documented in the description of + * #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note This API is not part of the PSA Cryptography API Release 1.0.0 + * specification. It was defined in the 1.0 Beta 3 version of the + * specification but was removed in the 1.0.0 released version. This API is + * kept for the time being to not break applications relying on it. It is not + * deprecated yet but will be in the near future. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * + * \param key The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p key. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not a valid persistent key identifier. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_open_key( mbedtls_svc_key_id_t key, + psa_key_handle_t *handle ); + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note This API is not part of the PSA Cryptography API Release 1.0.0 + * specification. It was defined in the 1.0 Beta 3 version of the + * specification but was removed in the 1.0.0 released version. This API is + * kept for the time being to not break applications relying on it. It is not + * deprecated yet but will be in the near future. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_config.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_config.h new file mode 100644 index 00000000..6476e3cf --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_config.h @@ -0,0 +1,124 @@ +/** + * \file psa/crypto_config.h + * \brief PSA crypto configuration options (set of defines) + * + */ +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +/** + * When #MBEDTLS_PSA_CRYPTO_CONFIG is enabled in mbedtls_config.h, + * this file determines which cryptographic mechanisms are enabled + * through the PSA Cryptography API (\c psa_xxx() functions). + * + * To enable a cryptographic mechanism, uncomment the definition of + * the corresponding \c PSA_WANT_xxx preprocessor symbol. + * To disable a cryptographic mechanism, comment out the definition of + * the corresponding \c PSA_WANT_xxx preprocessor symbol. + * The names of cryptographic mechanisms correspond to values + * defined in psa/crypto_values.h, with the prefix \c PSA_WANT_ instead + * of \c PSA_. + * + * Note that many cryptographic mechanisms involve two symbols: one for + * the key type (\c PSA_WANT_KEY_TYPE_xxx) and one for the algorithm + * (\c PSA_WANT_ALG_xxx). Mechanisms with additional parameters may involve + * additional symbols. + */ +#else +/** + * When \c MBEDTLS_PSA_CRYPTO_CONFIG is disabled in mbedtls_config.h, + * this file is not used, and cryptographic mechanisms are supported + * through the PSA API if and only if they are supported through the + * mbedtls_xxx API. + */ +#endif +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_CONFIG_H +#define PSA_CRYPTO_CONFIG_H + +/* + * CBC-MAC is not yet supported via the PSA API in Mbed TLS. + */ +//#define PSA_WANT_ALG_CBC_MAC 1 +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#define PSA_WANT_ALG_CBC_PKCS7 1 +#define PSA_WANT_ALG_CCM 1 +#define PSA_WANT_ALG_CMAC 1 +#define PSA_WANT_ALG_CFB 1 +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#define PSA_WANT_ALG_CMAC 1 +#define PSA_WANT_ALG_CTR 1 +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#define PSA_WANT_ALG_ECDH 1 +#define PSA_WANT_ALG_ECDSA 1 +#define PSA_WANT_ALG_GCM 1 +#define PSA_WANT_ALG_HKDF 1 +#define PSA_WANT_ALG_HMAC 1 +#define PSA_WANT_ALG_MD5 1 +#define PSA_WANT_ALG_OFB 1 +/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS. + * Note: when adding support, also adjust include/mbedtls/config_psa.h */ +//#define PSA_WANT_ALG_PBKDF2_HMAC 1 +#define PSA_WANT_ALG_RIPEMD160 1 +#define PSA_WANT_ALG_RSA_OAEP 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#define PSA_WANT_ALG_RSA_PSS 1 +#define PSA_WANT_ALG_SHA_1 1 +#define PSA_WANT_ALG_SHA_224 1 +#define PSA_WANT_ALG_SHA_256 1 +#define PSA_WANT_ALG_SHA_384 1 +#define PSA_WANT_ALG_SHA_512 1 +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#define PSA_WANT_ALG_TLS12_PRF 1 +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#define PSA_WANT_ALG_XTS 1 + +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 +#define PSA_WANT_ECC_MONTGOMERY_255 1 +#define PSA_WANT_ECC_MONTGOMERY_448 1 +#define PSA_WANT_ECC_SECP_K1_192 1 +/* + * SECP224K1 is buggy via the PSA API in Mbed TLS + * (https://github.com/ARMmbed/mbedtls/issues/3541). Thus, do not enable it by + * default. + */ +//#define PSA_WANT_ECC_SECP_K1_224 1 +#define PSA_WANT_ECC_SECP_K1_256 1 +#define PSA_WANT_ECC_SECP_R1_192 1 +#define PSA_WANT_ECC_SECP_R1_224 1 +#define PSA_WANT_ECC_SECP_R1_256 1 +#define PSA_WANT_ECC_SECP_R1_384 1 +#define PSA_WANT_ECC_SECP_R1_521 1 + +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#define PSA_WANT_KEY_TYPE_HMAC 1 +#define PSA_WANT_KEY_TYPE_AES 1 +#define PSA_WANT_KEY_TYPE_ARIA 1 +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#define PSA_WANT_KEY_TYPE_DES 1 +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1 +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 + +#endif /* PSA_CRYPTO_CONFIG_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_common.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_common.h new file mode 100644 index 00000000..26363c6b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_common.h @@ -0,0 +1,56 @@ +/** + * \file psa/crypto_driver_common.h + * \brief Definitions for all PSA crypto drivers + * + * This file contains common definitions shared by all PSA crypto drivers. + * Do not include it directly: instead, include the header file(s) for + * the type(s) of driver that you are implementing. For example, if + * you are writing a dynamically registered driver for a secure element, + * include `psa/crypto_se_driver.h`. + * + * This file is part of the PSA Crypto Driver Model, containing functions for + * driver developers to implement to enable hardware to be called in a + * standardized way by a PSA Cryptographic API implementation. The functions + * comprising the driver model, which driver authors implement, are not + * intended to be called by application developers. + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef PSA_CRYPTO_DRIVER_COMMON_H +#define PSA_CRYPTO_DRIVER_COMMON_H + +#include +#include + +/* Include type definitions (psa_status_t, psa_algorithm_t, + * psa_key_type_t, etc.) and macros to build and analyze values + * of these types. */ +#include "crypto_types.h" +#include "crypto_values.h" +/* Include size definitions which are used to size some arrays in operation + * structures. */ +#include + +/** For encrypt-decrypt functions, whether the operation is an encryption + * or a decryption. */ +typedef enum { + PSA_CRYPTO_DRIVER_DECRYPT, + PSA_CRYPTO_DRIVER_ENCRYPT +} psa_encrypt_or_decrypt_t; + +#endif /* PSA_CRYPTO_DRIVER_COMMON_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_contexts_composites.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_contexts_composites.h new file mode 100644 index 00000000..3f1c8af4 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_contexts_composites.h @@ -0,0 +1,118 @@ +/* + * Declaration of context structures for use with the PSA driver wrapper + * interface. This file contains the context structures for 'composite' + * operations, i.e. those operations which need to make use of other operations + * from the primitives (crypto_driver_contexts_primitives.h) + * + * Warning: This file will be auto-generated in the future. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the PSA drivers included in the cryptographic + * library. The definition of these objects are then used by crypto_struct.h + * to define the implementation-defined types of PSA multi-part state objects. + */ +/* Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H +#define PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H + +#include "psa/crypto_driver_common.h" + +/* Include the context structure definitions for the Mbed TLS software drivers */ +#include "psa/crypto_builtin_composites.h" + +/* Include the context structure definitions for those drivers that were + * declared during the autogeneration process. */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC) +typedef libtestdriver1_mbedtls_psa_mac_operation_t + mbedtls_transparent_test_driver_mac_operation_t; +typedef libtestdriver1_mbedtls_psa_mac_operation_t + mbedtls_opaque_test_driver_mac_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_MAC_OPERATION_INIT + +#else +typedef mbedtls_psa_mac_operation_t + mbedtls_transparent_test_driver_mac_operation_t; +typedef mbedtls_psa_mac_operation_t + mbedtls_opaque_test_driver_mac_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_MAC_OPERATION_INIT \ + MBEDTLS_PSA_MAC_OPERATION_INIT +#define MBEDTLS_OPAQUE_TEST_DRIVER_MAC_OPERATION_INIT \ + MBEDTLS_PSA_MAC_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD) +typedef libtestdriver1_mbedtls_psa_aead_operation_t + mbedtls_transparent_test_driver_aead_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_AEAD_OPERATION_INIT +#else +typedef mbedtls_psa_aead_operation_t + mbedtls_transparent_test_driver_aead_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_AEAD_OPERATION_INIT \ + MBEDTLS_PSA_AEAD_OPERATION_INIT + +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_AEAD */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Define the context to be used for an operation that is executed through the + * PSA Driver wrapper layer as the union of all possible driver's contexts. + * + * The union members are the driver's context structures, and the member names + * are formatted as `'drivername'_ctx`. This allows for procedural generation + * of both this file and the content of psa_crypto_driver_wrappers.c */ + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_mac_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_mac_operation_t transparent_test_driver_ctx; + mbedtls_opaque_test_driver_mac_operation_t opaque_test_driver_ctx; +#endif +} psa_driver_mac_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_aead_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_aead_operation_t transparent_test_driver_ctx; +#endif +} psa_driver_aead_context_t; + +#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H */ +/* End of automatically generated file. */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_contexts_primitives.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_contexts_primitives.h new file mode 100644 index 00000000..2bb01ed4 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_driver_contexts_primitives.h @@ -0,0 +1,117 @@ +/* + * Declaration of context structures for use with the PSA driver wrapper + * interface. This file contains the context structures for 'primitive' + * operations, i.e. those operations which do not rely on other contexts. + * + * Warning: This file will be auto-generated in the future. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * \note This header and its content is not part of the Mbed TLS API and + * applications must not depend on it. Its main purpose is to define the + * multi-part state objects of the PSA drivers included in the cryptographic + * library. The definition of these objects are then used by crypto_struct.h + * to define the implementation-defined types of PSA multi-part state objects. + */ +/* Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H +#define PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H + +#include "psa/crypto_driver_common.h" + +/* Include the context structure definitions for the Mbed TLS software drivers */ +#include "psa/crypto_builtin_primitives.h" + +/* Include the context structure definitions for those drivers that were + * declared during the autogeneration process. */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) +#include +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER) +typedef libtestdriver1_mbedtls_psa_cipher_operation_t + mbedtls_transparent_test_driver_cipher_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_CIPHER_OPERATION_INIT +#else +typedef mbedtls_psa_cipher_operation_t + mbedtls_transparent_test_driver_cipher_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT \ + MBEDTLS_PSA_CIPHER_OPERATION_INIT +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && + LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(MBEDTLS_TEST_LIBTESTDRIVER1) && \ + defined(LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH) +typedef libtestdriver1_mbedtls_psa_hash_operation_t + mbedtls_transparent_test_driver_hash_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ + LIBTESTDRIVER1_MBEDTLS_PSA_HASH_OPERATION_INIT +#else +typedef mbedtls_psa_hash_operation_t + mbedtls_transparent_test_driver_hash_operation_t; + +#define MBEDTLS_TRANSPARENT_TEST_DRIVER_HASH_OPERATION_INIT \ + MBEDTLS_PSA_HASH_OPERATION_INIT +#endif /* MBEDTLS_TEST_LIBTESTDRIVER1 && + LIBTESTDRIVER1_MBEDTLS_PSA_BUILTIN_HASH */ + +typedef struct { + unsigned int initialised : 1; + mbedtls_transparent_test_driver_cipher_operation_t ctx; +} mbedtls_opaque_test_driver_cipher_operation_t; + +#define MBEDTLS_OPAQUE_TEST_DRIVER_CIPHER_OPERATION_INIT \ + { 0, MBEDTLS_TRANSPARENT_TEST_DRIVER_CIPHER_OPERATION_INIT } + +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Define the context to be used for an operation that is executed through the + * PSA Driver wrapper layer as the union of all possible driver's contexts. + * + * The union members are the driver's context structures, and the member names + * are formatted as `'drivername'_ctx`. This allows for procedural generation + * of both this file and the content of psa_crypto_driver_wrappers.c */ + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_hash_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_hash_operation_t test_driver_ctx; +#endif +} psa_driver_hash_context_t; + +typedef union { + unsigned dummy; /* Make sure this union is always non-empty */ + mbedtls_psa_cipher_operation_t mbedtls_ctx; +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_transparent_test_driver_cipher_operation_t transparent_test_driver_ctx; + mbedtls_opaque_test_driver_cipher_operation_t opaque_test_driver_ctx; +#endif +} psa_driver_cipher_context_t; + +#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H */ +/* End of automatically generated file. */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_extra.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_extra.h new file mode 100644 index 00000000..1f68925f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_extra.h @@ -0,0 +1,1825 @@ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: Mbed TLS vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H +#include "mbedtls/private_access.h" + +#include "mbedtls/platform_util.h" + +#include "crypto_types.h" +#include "crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* UID for secure storage seed */ +#define PSA_CRYPTO_ITS_RANDOM_SEED_UID 0xFFFFFF52 + +/* See mbedtls_config.h for definition */ +#if !defined(MBEDTLS_PSA_KEY_SLOT_COUNT) +#define MBEDTLS_PSA_KEY_SLOT_COUNT 32 +#endif + +/** \addtogroup attributes + * @{ + */ + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2; +} + +/** Retrieve the enrollment algorithm policy from key attributes. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The enrollment algorithm stored in the attribute structure. + */ +static inline psa_algorithm_t psa_get_key_enrollment_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +/** Retrieve the slot number where a key is stored. + * + * A slot number is only defined for keys that are stored in a secure + * element. + * + * This information is only useful if the secure element is not entirely + * managed through the PSA Cryptography API. It is up to the secure + * element driver to decide how PSA slot numbers map to any other interface + * that the secure element may have. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] slot_number On success, the slot number containing the key. + * + * \retval #PSA_SUCCESS + * The key is located in a secure element, and \p *slot_number + * indicates the slot number that contains it. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not permitted to query the slot number. + * Mbed Crypto currently does not return this error. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is not located in a secure element. + */ +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number ); + +/** Choose the slot number where a key is stored. + * + * This function declares a slot number in the specified attribute + * structure. + * + * A slot number is only meaningful for keys that are stored in a secure + * element. It is up to the secure element driver to decide how PSA slot + * numbers map to any other interface that the secure element may have. + * + * \note Setting a slot number in key attributes for a key creation can + * cause the following errors when creating the key: + * - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does + * not support choosing a specific slot number. + * - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to + * choose slot numbers in general or to choose this specific slot. + * - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not + * valid in general or not valid for this specific key. + * - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the + * selected slot. + * + * \param[out] attributes The attribute structure to write to. + * \param slot_number The slot number to set. + */ +static inline void psa_set_key_slot_number( + psa_key_attributes_t *attributes, + psa_key_slot_number_t slot_number ) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; + attributes->MBEDTLS_PRIVATE(slot_number) = slot_number; +} + +/** Remove the slot number attribute from a key attribute structure. + * + * This function undoes the action of psa_set_key_slot_number(). + * + * \param[out] attributes The attribute structure to write to. + */ +static inline void psa_clear_key_slot_number( + psa_key_attributes_t *attributes ) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER; +} + +/** Register a key that is already present in a secure element. + * + * The key must be located in a secure element designated by the + * lifetime field in \p attributes, in the slot set with + * psa_set_key_slot_number() in the attribute structure. + * This function makes the key available through the key identifier + * specified in \p attributes. + * + * \param[in] attributes The attributes of the existing key. + * + * \retval #PSA_SUCCESS + * The key was successfully registered. + * Note that depending on the design of the driver, this may or may + * not guarantee that a key actually exists in the designated slot + * and is compatible with the specified attributes. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the identifier specified in + * \p attributes. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The secure element driver for the specified lifetime does not + * support registering a key. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The identifier in \p attributes is invalid, namely the identifier is + * not in the user range. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a lifetime which is not located + * in a secure element. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * No slot number is specified in \p attributes, + * or the specified slot number is not valid. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller is not authorized to register the specified key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes); + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** + * \brief Library deinitialization. + * + * This function clears all data associated with the PSA layer, + * including the whole key store. + * + * This is an Mbed TLS extension. + */ +void mbedtls_psa_crypto_free( void ); + +/** \brief Statistics about + * resource consumption related to the PSA keystore. + * + * \note The content of this structure is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + */ +typedef struct mbedtls_psa_stats_s +{ + /** Number of slots containing key material for a volatile key. */ + size_t MBEDTLS_PRIVATE(volatile_slots); + /** Number of slots containing key material for a key which is in + * internal persistent storage. */ + size_t MBEDTLS_PRIVATE(persistent_slots); + /** Number of slots containing a reference to a key in a + * secure element. */ + size_t MBEDTLS_PRIVATE(external_slots); + /** Number of slots which are occupied, but do not contain + * key material yet. */ + size_t MBEDTLS_PRIVATE(half_filled_slots); + /** Number of slots that contain cache data. */ + size_t MBEDTLS_PRIVATE(cache_slots); + /** Number of slots that are not used for anything. */ + size_t MBEDTLS_PRIVATE(empty_slots); + /** Number of slots that are locked. */ + size_t MBEDTLS_PRIVATE(locked_slots); + /** Largest key id value among open keys in internal persistent storage. */ + psa_key_id_t MBEDTLS_PRIVATE(max_open_internal_key_id); + /** Largest key id value among open keys in secure elements. */ + psa_key_id_t MBEDTLS_PRIVATE(max_open_external_key_id); +} mbedtls_psa_stats_t; + +/** \brief Get statistics about + * resource consumption related to the PSA keystore. + * + * \note When Mbed Crypto is built as part of a service, with isolation + * between the application and the keystore, the service may or + * may not expose this function. + */ +void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ); + +/** + * \brief Inject an initial entropy seed for the random generator into + * secure storage. + * + * This function injects data to be used as a seed for the random generator + * used by the PSA Crypto implementation. On devices that lack a trusted + * entropy source (preferably a hardware random number generator), + * the Mbed PSA Crypto implementation uses this value to seed its + * random generator. + * + * On devices without a trusted entropy source, this function must be + * called exactly once in the lifetime of the device. On devices with + * a trusted entropy source, calling this function is optional. + * In all cases, this function may only be called before calling any + * other function in the PSA Crypto API, including psa_crypto_init(). + * + * When this function returns successfully, it populates a file in + * persistent storage. Once the file has been created, this function + * can no longer succeed. + * + * If any error occurs, this function does not change the system state. + * You can call this function again after correcting the reason for the + * error if possible. + * + * \warning This function **can** fail! Callers MUST check the return status. + * + * \warning If you use this function, you should use it as part of a + * factory provisioning process. The value of the injected seed + * is critical to the security of the device. It must be + * *secret*, *unpredictable* and (statistically) *unique per device*. + * You should be generate it randomly using a cryptographically + * secure random generator seeded from trusted entropy sources. + * You should transmit it securely to the device and ensure + * that its value is not leaked or stored anywhere beyond the + * needs of transmitting it from the point of generation to + * the call of this function, and erase all copies of the value + * once this function returns. + * + * This is an Mbed TLS extension. + * + * \note This function is only available on the following platforms: + * * If the compile-time option MBEDTLS_PSA_INJECT_ENTROPY is enabled. + * Note that you must provide compatible implementations of + * mbedtls_nv_seed_read and mbedtls_nv_seed_write. + * * In a client-server integration of PSA Cryptography, on the client side, + * if the server supports this feature. + * \param[in] seed Buffer containing the seed value to inject. + * \param[in] seed_size Size of the \p seed buffer. + * The size of the seed in bytes must be greater + * or equal to both #MBEDTLS_ENTROPY_BLOCK_SIZE + * and the value of \c MBEDTLS_ENTROPY_MIN_PLATFORM + * in `library/entropy_poll.h` in the Mbed TLS source + * code. + * It must be less or equal to + * #MBEDTLS_ENTROPY_MAX_SEED_SIZE. + * + * \retval #PSA_SUCCESS + * The seed value was injected successfully. The random generator + * of the PSA Crypto implementation is now ready for use. + * You may now call psa_crypto_init() and use the PSA Crypto + * implementation. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p seed_size is out of range. + * \retval #PSA_ERROR_STORAGE_FAILURE + * There was a failure reading or writing from storage. + * \retval #PSA_ERROR_NOT_PERMITTED + * The library has already been initialized. It is no longer + * possible to call this function. + */ +psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed, + size_t seed_size); + +/** \addtogroup crypto_types + * @{ + */ + +/** DSA public key. + * + * The import and export format is the + * representation of the public key `y = g^x mod p` as a big-endian byte + * string. The length of the byte string is the length of the base prime `p` + * in bytes. + */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x4002) + +/** DSA key pair (private and public key). + * + * The import and export format is the + * representation of the private key `x` as a big-endian byte string. The + * length of the byte string is the private key size in bytes (leading zeroes + * are not stripped). + * + * Determinstic DSA key derivation with psa_generate_derived_key follows + * FIPS 186-4 §B.1.2: interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * + */ +#define PSA_KEY_TYPE_DSA_KEY_PAIR ((psa_key_type_t)0x7002) + +/** Whether a key type is an DSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + +#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x06000400) +/** DSA signature with hashing. + * + * This is the signature scheme defined by FIPS 186-4, + * with a random per-message secret number (*k*). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DSA(hash_alg) \ + (PSA_ALG_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_DETERMINISTIC_DSA_BASE ((psa_algorithm_t)0x06000500) +#define PSA_ALG_DSA_DETERMINISTIC_FLAG PSA_ALG_ECDSA_DETERMINISTIC_FLAG +/** Deterministic DSA signature with hashing. + * + * This is the deterministic variant defined by RFC 6979 of + * the signature scheme defined by FIPS 186-4. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_DSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_DSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_DSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_DSA_BASE) +#define PSA_ALG_DSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && PSA_ALG_DSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_DSA(alg) \ + (PSA_ALG_IS_DSA(alg) && !PSA_ALG_DSA_IS_DETERMINISTIC(alg)) + + +/* We need to expand the sample definition of this macro from + * the API definition. */ +#undef PSA_ALG_IS_VENDOR_HASH_AND_SIGN +#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) \ + PSA_ALG_IS_DSA(alg) + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** Custom Diffie-Hellman group. + * + * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes + * from domain parameters set by psa_set_key_domain_parameters(). + */ +#define PSA_DH_FAMILY_CUSTOM ((psa_dh_family_t) 0x7e) + + +/** + * \brief Set domain parameters for a key. + * + * Some key types require additional domain parameters in addition to + * the key type identifier and the key size. Use this function instead + * of psa_set_key_type() when you need to specify domain parameters. + * + * The format for the required domain parameters varies based on the key type. + * + * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR), + * the domain parameter data consists of the public exponent, + * represented as a big-endian integer with no leading zeros. + * This information is used when generating an RSA key pair. + * When importing a key, the public exponent is read from the imported + * key data and the exponent recorded in the attribute structure is ignored. + * As an exception, the public exponent 65537 is represented by an empty + * byte string. + * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR), + * the `Dss-Parms` format as defined by RFC 3279 §2.3.2. + * ``` + * Dss-Parms ::= SEQUENCE { + * p INTEGER, + * q INTEGER, + * g INTEGER + * } + * ``` + * - For Diffie-Hellman key exchange keys + * (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or + * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM)), the + * `DomainParameters` format as defined by RFC 3279 §2.3.3. + * ``` + * DomainParameters ::= SEQUENCE { + * p INTEGER, -- odd prime, p=jq +1 + * g INTEGER, -- generator, g + * q INTEGER, -- factor of p-1 + * j INTEGER OPTIONAL, -- subgroup factor + * validationParms ValidationParms OPTIONAL + * } + * ValidationParms ::= SEQUENCE { + * seed BIT STRING, + * pgenCounter INTEGER + * } + * ``` + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in,out] attributes Attribute structure where the specified domain + * parameters will be stored. + * If this function fails, the content of + * \p attributes is not modified. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). + * \param[in] data Buffer containing the key domain parameters. + * The content of this buffer is interpreted + * according to \p type as described above. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Get domain parameters for a key. + * + * Get the domain parameters for a key with this function, if any. The format + * of the domain parameters written to \p data is specified in the + * documentation for psa_set_key_domain_parameters(). + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param[in] attributes The key attribute structure to query. + * \param[out] data On success, the key domain parameters. + * \param data_size Size of the \p data buffer in bytes. + * The buffer is guaranteed to be large + * enough if its size in bytes is at least + * the value given by + * PSA_KEY_DOMAIN_PARAMETERS_SIZE(). + * \param[out] data_length On success, the number of bytes + * that make up the key domain parameters data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + */ +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** Safe output buffer size for psa_get_key_domain_parameters(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \note This is an experimental extension to the interface. It may change + * in future versions of the library. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_get_key_domain_parameters() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) : \ + PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \ + 0) +#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/) +#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) \ + (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/) + +/**@}*/ + +/** \defgroup psa_tls_helpers TLS helper functions + * @{ + */ + +#if defined(MBEDTLS_ECP_C) +#include + +/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param grpid An Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \param[out] bits On success, the bit size of the curve. + * + * \return The corresponding PSA elliptic curve identifier + * (`PSA_ECC_FAMILY_xxx`). + * \return \c 0 on failure (\p grpid is not recognized). + */ +static inline psa_ecc_family_t mbedtls_ecc_group_to_psa( mbedtls_ecp_group_id grpid, + size_t *bits ) +{ + switch( grpid ) + { + case MBEDTLS_ECP_DP_SECP192R1: + *bits = 192; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP224R1: + *bits = 224; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP256R1: + *bits = 256; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP384R1: + *bits = 384; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_SECP521R1: + *bits = 521; + return( PSA_ECC_FAMILY_SECP_R1 ); + case MBEDTLS_ECP_DP_BP256R1: + *bits = 256; + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP384R1: + *bits = 384; + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_BP512R1: + *bits = 512; + return( PSA_ECC_FAMILY_BRAINPOOL_P_R1 ); + case MBEDTLS_ECP_DP_CURVE25519: + *bits = 255; + return( PSA_ECC_FAMILY_MONTGOMERY ); + case MBEDTLS_ECP_DP_SECP192K1: + *bits = 192; + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP224K1: + *bits = 224; + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_SECP256K1: + *bits = 256; + return( PSA_ECC_FAMILY_SECP_K1 ); + case MBEDTLS_ECP_DP_CURVE448: + *bits = 448; + return( PSA_ECC_FAMILY_MONTGOMERY ); + default: + *bits = 0; + return( 0 ); + } +} + +/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS. + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param curve A PSA elliptic curve identifier + * (`PSA_ECC_FAMILY_xxx`). + * \param bits The bit-length of a private key on \p curve. + * \param bits_is_sloppy If true, \p bits may be the bit-length rounded up + * to the nearest multiple of 8. This allows the caller + * to infer the exact curve from the length of a key + * which is supplied as a byte string. + * + * \return The corresponding Mbed TLS elliptic curve identifier + * (`MBEDTLS_ECP_DP_xxx`). + * \return #MBEDTLS_ECP_DP_NONE if \c curve is not recognized. + * \return #MBEDTLS_ECP_DP_NONE if \p bits is not + * correct for \p curve. + */ +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve, + size_t bits, + int bits_is_sloppy ); +#endif /* MBEDTLS_ECP_C */ + +/**@}*/ + +/** \defgroup psa_external_rng External random generator + * @{ + */ + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** External random generator function, implemented by the platform. + * + * When the compile-time option #MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled, + * this function replaces Mbed TLS's entropy and DRBG modules for all + * random generation triggered via PSA crypto interfaces. + * + * \note This random generator must deliver random numbers with cryptographic + * quality and high performance. It must supply unpredictable numbers + * with a uniform distribution. The implementation of this function + * is responsible for ensuring that the random generator is seeded + * with sufficient entropy. If you have a hardware TRNG which is slow + * or delivers non-uniform output, declare it as an entropy source + * with mbedtls_entropy_add_source() instead of enabling this option. + * + * \param[in,out] context Pointer to the random generator context. + * This is all-bits-zero on the first call + * and preserved between successive calls. + * \param[out] output Output buffer. On success, this buffer + * contains random data with a uniform + * distribution. + * \param output_size The size of the \p output buffer in bytes. + * \param[out] output_length On success, set this value to \p output_size. + * + * \retval #PSA_SUCCESS + * Success. The output buffer contains \p output_size bytes of + * cryptographic-quality random data, and \c *output_length is + * set to \p output_size. + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * The random generator requires extra entropy and there is no + * way to obtain entropy under current environment conditions. + * This error should not happen under normal circumstances since + * this function is responsible for obtaining as much entropy as + * it needs. However implementations of this function may return + * #PSA_ERROR_INSUFFICIENT_ENTROPY if there is no way to obtain + * entropy without blocking indefinitely. + * \retval #PSA_ERROR_HARDWARE_FAILURE + * A failure of the random generator hardware that isn't covered + * by #PSA_ERROR_INSUFFICIENT_ENTROPY. + */ +psa_status_t mbedtls_psa_external_get_random( + mbedtls_psa_external_random_context_t *context, + uint8_t *output, size_t output_size, size_t *output_length ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +/**@}*/ + +/** \defgroup psa_builtin_keys Built-in keys + * @{ + */ + +/** The minimum value for a key identifier that is built into the + * implementation. + * + * The range of key identifiers from #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN + * to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX within the range from + * #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect + * with any other set of implementation-chosen key identifiers. + * + * This value is part of the library's ABI since changing it would invalidate + * the values of built-in key identifiers in applications. + */ +#define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ((psa_key_id_t)0x7fff0000) + +/** The maximum value for a key identifier that is built into the + * implementation. + * + * See #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN for more information. + */ +#define MBEDTLS_PSA_KEY_ID_BUILTIN_MAX ((psa_key_id_t)0x7fffefff) + +/** A slot number identifying a key in a driver. + * + * Values of this type are used to identify built-in keys. + */ +typedef uint64_t psa_drv_slot_number_t; + +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) +/** Test whether a key identifier belongs to the builtin key range. + * + * \param key_id Key identifier to test. + * + * \retval 1 + * The key identifier is a builtin key identifier. + * \retval 0 + * The key identifier is not a builtin key identifier. + */ +static inline int psa_key_id_is_builtin( psa_key_id_t key_id ) +{ + return( ( key_id >= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ) && + ( key_id <= MBEDTLS_PSA_KEY_ID_BUILTIN_MAX ) ); +} + +/** Platform function to obtain the location and slot number of a built-in key. + * + * An application-specific implementation of this function must be provided if + * #MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled. This would typically be provided + * as part of a platform's system image. + * + * #MBEDTLS_SVC_KEY_ID_GET_KEY_ID(\p key_id) needs to be in the range from + * #MBEDTLS_PSA_KEY_ID_BUILTIN_MIN to #MBEDTLS_PSA_KEY_ID_BUILTIN_MAX. + * + * In a multi-application configuration + * (\c MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER is defined), + * this function should check that #MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(\p key_id) + * is allowed to use the given key. + * + * \param key_id The key ID for which to retrieve the + * location and slot attributes. + * \param[out] lifetime On success, the lifetime associated with the key + * corresponding to \p key_id. Lifetime is a + * combination of which driver contains the key, + * and with what persistence level the key is + * intended to be used. If the platform + * implementation does not contain specific + * information about the intended key persistence + * level, the persistence level may be reported as + * #PSA_KEY_PERSISTENCE_DEFAULT. + * \param[out] slot_number On success, the slot number known to the driver + * registered at the lifetime location reported + * through \p lifetime which corresponds to the + * requested built-in key. + * + * \retval #PSA_SUCCESS + * The requested key identifier designates a built-in key. + * In a multi-application configuration, the requested owner + * is allowed to access it. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * The requested key identifier is not a built-in key which is known + * to this function. If a key exists in the key storage with this + * identifier, the data from the storage will be used. + * \return (any other error) + * Any other error is propagated to the function that requested the key. + * Common errors include: + * - #PSA_ERROR_NOT_PERMITTED: the key exists but the requested owner + * is not allowed to access it. + */ +psa_status_t mbedtls_psa_platform_get_builtin_key( + mbedtls_svc_key_id_t key_id, + psa_key_lifetime_t *lifetime, + psa_drv_slot_number_t *slot_number ); +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +/** @} */ + +/** \addtogroup crypto_types + * @{ + */ + +#define PSA_ALG_CATEGORY_PAKE ((psa_algorithm_t)0x0a000000) + +/** Whether the specified algorithm is a password-authenticated key exchange. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a password-authenticated key exchange (PAKE) + * algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_PAKE(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_PAKE) + +/** The Password-authenticated key exchange by juggling (J-PAKE) algorithm. + * + * This is J-PAKE as defined by RFC 8236, instantiated with the following + * parameters: + * + * - The group can be either an elliptic curve or defined over a finite field. + * - Schnorr NIZK proof as defined by RFC 8235 and using the same group as the + * J-PAKE algorithm. + * - A cryptographic hash function. + * + * To select these parameters and set up the cipher suite, call these functions + * in any order: + * + * \code + * psa_pake_cs_set_algorithm(cipher_suite, PSA_ALG_JPAKE); + * psa_pake_cs_set_primitive(cipher_suite, + * PSA_PAKE_PRIMITIVE(type, family, bits)); + * psa_pake_cs_set_hash(cipher_suite, hash); + * \endcode + * + * For more information on how to set a specific curve or field, refer to the + * documentation of the individual \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + * + * After initializing a J-PAKE operation, call + * + * \code + * psa_pake_setup(operation, cipher_suite); + * psa_pake_set_user(operation, ...); + * psa_pake_set_peer(operation, ...); + * psa_pake_set_password_key(operation, ...); + * \endcode + * + * The password is read as a byte array and must be non-empty. This can be the + * password itself (in some pre-defined character encoding) or some value + * derived from the password as mandated by some higher level protocol. + * + * (The implementation converts this byte array to a number as described in + * Section 2.3.8 of _SEC 1: Elliptic Curve Cryptography_ + * (https://www.secg.org/sec1-v2.pdf), before reducing it modulo \c q. Here + * \c q is order of the group defined by the primitive set in the cipher suite. + * The \c psa_pake_set_password_xxx() functions return an error if the result + * of the reduction is 0.) + * + * The key exchange flow for J-PAKE is as follows: + * -# To get the first round data that needs to be sent to the peer, call + * \code + * // Get g1 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x1 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Get g2 + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get the ZKP public key for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get the ZKP proof for x2 + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To provide the first round data received from the peer to the operation, + * call + * \code + * // Set g3 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x3 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * // Set g4 + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set the ZKP public key for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set the ZKP proof for x4 + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To get the second round data that needs to be sent to the peer, call + * \code + * // Get A + * psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Get ZKP public key for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Get ZKP proof for x2*s + * psa_pake_output(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To provide the second round data received from the peer to the operation, + * call + * \code + * // Set B + * psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...); + * // Set ZKP public key for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PUBLIC, ...); + * // Set ZKP proof for x4*s + * psa_pake_input(operation, #PSA_PAKE_STEP_ZK_PROOF, ...); + * \endcode + * -# To access the shared secret call + * \code + * // Get Ka=Kb=K + * psa_pake_get_implicit_key() + * \endcode + * + * For more information consult the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party it claims to be and was able to do so. + * + * That is, the authentication is only implicit (the peer is not authenticated + * at this point, and no action should be taken that assume that they are - like + * for example accessing restricted files). + * + * To make the authentication explicit there are various methods, see Section 5 + * of RFC 8236 for two examples. + * + */ +#define PSA_ALG_JPAKE ((psa_algorithm_t)0x0a000100) + +/** @} */ + +/** \defgroup pake Password-authenticated key exchange (PAKE) + * + * This is a proposed PAKE interface for the PSA Crypto API. It is not part of + * the official PSA Crypto API yet. + * + * \note The content of this section is not part of the stable API and ABI + * of Mbed Crypto and may change arbitrarily from version to version. + * Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and + * #PSA_ALG_JPAKE. + * @{ + */ + +/** \brief Encoding of the side of PAKE + * + * Encodes which side of the algorithm is being executed. For more information + * see the documentation of individual \c PSA_PAKE_SIDE_XXX constants. + */ +typedef uint8_t psa_pake_side_t; + +/** Encoding of input and output indicators for PAKE. + * + * Some PAKE algorithms need to exchange more data than just a single key share. + * This type is for encoding additional input and output data for such + * algorithms. + */ +typedef uint8_t psa_pake_step_t; + +/** Encoding of the type of the PAKE's primitive. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional types must use an encoding in this range. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_primitive_type_t; + +/** \brief Encoding of the family of the primitive associated with the PAKE. + * + * For more information see the documentation of individual + * \c PSA_PAKE_PRIMITIVE_TYPE_XXX constants. + */ +typedef uint8_t psa_pake_family_t; + +/** \brief Encoding of the primitive associated with the PAKE. + * + * For more information see the documentation of the #PSA_PAKE_PRIMITIVE macro. + */ +typedef uint32_t psa_pake_primitive_t; + +/** The first peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, both #PSA_PAKE_SIDE_FIRST and #PSA_PAKE_SIDE_SECOND are + * accepted. + */ +#define PSA_PAKE_SIDE_FIRST ((psa_pake_side_t)0x01) + +/** The second peer in a balanced PAKE. + * + * Although balanced PAKE algorithms are symmetric, some of them needs an + * ordering of peers for the transcript calculations. If the algorithm does not + * need this, either #PSA_PAKE_SIDE_FIRST or #PSA_PAKE_SIDE_SECOND are + * accepted. + */ +#define PSA_PAKE_SIDE_SECOND ((psa_pake_side_t)0x02) + +/** The client in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_SIDE_CLIENT ((psa_pake_side_t)0x11) + +/** The server in an augmented PAKE. + * + * Augmented PAKE algorithms need to differentiate between client and server. + */ +#define PSA_PAKE_SIDE_SERVER ((psa_pake_side_t)0x12) + +/** The PAKE primitive type indicating the use of elliptic curves. + * + * The values of the \c family and \c bits fields of the cipher suite identify a + * specific elliptic curve, using the same mapping that is used for ECC + * (::psa_ecc_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific curve would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * curve would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_ECC ((psa_pake_primitive_type_t)0x01) + +/** The PAKE primitive type indicating the use of Diffie-Hellman groups. + * + * The values of the \c family and \c bits fields of the cipher suite identify + * a specific Diffie-Hellman group, using the same mapping that is used for + * Diffie-Hellman (::psa_dh_family_t) keys. + * + * (Here \c family means the value returned by psa_pake_cs_get_family() and + * \c bits means the value returned by psa_pake_cs_get_bits().) + * + * Input and output during the operation can involve group elements and scalar + * values: + * -# The format for group elements is the same as for public keys on the + * specific group would be. For more information, consult the documentation of + * psa_export_public_key(). + * -# The format for scalars is the same as for private keys on the specific + * group would be. For more information, consult the documentation of + * psa_export_key(). + */ +#define PSA_PAKE_PRIMITIVE_TYPE_DH ((psa_pake_primitive_type_t)0x02) + +/** Construct a PAKE primitive from type, family and bit-size. + * + * \param pake_type The type of the primitive + * (value of type ::psa_pake_primitive_type_t). + * \param pake_family The family of the primitive + * (the type and interpretation of this parameter depends + * on \p type, for more information consult the + * documentation of individual ::psa_pake_primitive_type_t + * constants). + * \param pake_bits The bit-size of the primitive + * (Value of type \c size_t. The interpretation + * of this parameter depends on \p family, for more + * information consult the documentation of individual + * ::psa_pake_primitive_type_t constants). + * + * \return The constructed primitive value of type ::psa_pake_primitive_t. + * Return 0 if the requested primitive can't be encoded as + * ::psa_pake_primitive_t. + */ +#define PSA_PAKE_PRIMITIVE(pake_type, pake_family, pake_bits) \ + ((pake_bits & 0xFFFF) != pake_bits) ? 0 : \ + ((psa_pake_primitive_t) (((pake_type) << 24 | \ + (pake_family) << 16) | (pake_bits))) + +/** The key share being sent to or received from the peer. + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_KEY_SHARE ((psa_pake_step_t)0x01) + +/** A Schnorr NIZKP public key. + * + * This is the ephemeral public key in the Schnorr Non-Interactive + * Zero-Knowledge Proof (the value denoted by the letter 'V' in RFC 8235). + * + * The format for both input and output at this step is the same as for public + * keys on the group determined by the primitive (::psa_pake_primitive_t) would + * be. + * + * For more information on the format, consult the documentation of + * psa_export_public_key(). + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PUBLIC ((psa_pake_step_t)0x02) + +/** A Schnorr NIZKP proof. + * + * This is the proof in the Schnorr Non-Interactive Zero-Knowledge Proof (the + * value denoted by the letter 'r' in RFC 8235). + * + * Both for input and output, the value at this step is an integer less than + * the order of the group selected in the cipher suite. The format depends on + * the group as well: + * + * - For Montgomery curves, the encoding is little endian. + * - For everything else the encoding is big endian (see Section 2.3.8 of + * _SEC 1: Elliptic Curve Cryptography_ at https://www.secg.org/sec1-v2.pdf). + * + * In both cases leading zeroes are allowed as long as the length in bytes does + * not exceed the byte length of the group order. + * + * For information regarding how the group is determined, consult the + * documentation #PSA_PAKE_PRIMITIVE. + */ +#define PSA_PAKE_STEP_ZK_PROOF ((psa_pake_step_t)0x03) + +/** The type of the data strucure for PAKE cipher suites. + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. + */ +typedef struct psa_pake_cipher_suite_s psa_pake_cipher_suite_t; + +/** Retrieve the PAKE algorithm from a PAKE cipher suite. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The PAKE algorithm stored in the cipher suite structure. + */ +static psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the PAKE algorithm for the cipher suite. + * + * This function overwrites any PAKE algorithm + * previously set in \p cipher_suite. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param algorithm The PAKE algorithm to write. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_PAKE(\c alg) is true.) + * If this is 0, the PAKE algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t* cipher_suite, + psa_algorithm_t algorithm + ); + +/** Retrieve the primitive from a PAKE cipher suite. + * + * This function may be declared as `static` (i.e. without external linkage). + * This function may be provided as a function-like macro, but in this case it + * must evaluate its argument exactly once. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The primitive stored in the cipher suite structure. + */ +static psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the primitive for a PAKE cipher suite. + * + * This function overwrites any primitive previously set in \p cipher_suite. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param primitive The primitive to write. If this is 0, the + * primitive type in \p cipher_suite becomes + * unspecified. + */ +static void psa_pake_cs_set_primitive( + psa_pake_cipher_suite_t* cipher_suite, + psa_pake_primitive_t primitive + ); + +/** Retrieve the hash algorithm from a PAKE cipher suite. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] cipher_suite The cipher suite structure to query. + * + * \return The hash algorithm stored in the cipher suite structure. The return + * value is 0 if the PAKE is not parametrised by a hash algorithm or if + * the hash algorithm is not set. + */ +static psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t* cipher_suite + ); + +/** Declare the hash algorithm for a PAKE cipher suite. + * + * This function overwrites any hash algorithm + * previously set in \p cipher_suite. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[out] cipher_suite The cipher suite structure to write to. + * \param hash The hash involved in the cipher suite. + * (`PSA_ALG_XXX` values of type ::psa_algorithm_t + * such that #PSA_ALG_IS_HASH(\c alg) is true.) + * If this is 0, the hash algorithm in + * \p cipher_suite becomes unspecified. + */ +static void psa_pake_cs_set_hash( + psa_pake_cipher_suite_t* cipher_suite, + psa_algorithm_t hash + ); + +/** The type of the state data structure for PAKE operations. + * + * Before calling any function on a PAKE operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_pake_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_pake_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_PAKE_OPERATION_INIT, + * for example: + * \code + * psa_pake_operation_t operation = PSA_PAKE_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_pake_operation_init() + * to the structure, for example: + * \code + * psa_pake_operation_t operation; + * operation = psa_pake_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure. + * Implementation details can change in future versions without notice. */ +typedef struct psa_pake_operation_s psa_pake_operation_t; + +/** Return an initial value for an PAKE operation object. + */ +static psa_pake_operation_t psa_pake_operation_init(void); + +/** Set the session information for a password-authenticated key exchange. + * + * The sequence of operations to set up a password-authenticated key exchange + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_pake_operation_t, e.g. + * #PSA_PAKE_OPERATION_INIT. + * -# Call psa_pake_setup() to specify the cipher suite. + * -# Call \c psa_pake_set_xxx() functions on the operation to complete the + * setup. The exact sequence of \c psa_pake_set_xxx() functions that needs + * to be called depends on the algorithm in use. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * A typical sequence of calls to perform a password-authenticated key + * exchange: + * -# Call psa_pake_output(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to get the + * key share that needs to be sent to the peer. + * -# Call psa_pake_input(operation, #PSA_PAKE_STEP_KEY_SHARE, ...) to provide + * the key share that was received from the peer. + * -# Depending on the algorithm additional calls to psa_pake_output() and + * psa_pake_input() might be necessary. + * -# Call psa_pake_get_implicit_key() for accessing the shared secret. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * If an error occurs at any step after a call to psa_pake_setup(), + * the operation will need to be reset by a call to psa_pake_abort(). The + * application may call psa_pake_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_pake_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A call to psa_pake_abort(). + * - A successful call to psa_pake_get_implicit_key(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized but not set up yet. + * \param cipher_suite The cipher suite to use. (A cipher suite fully + * characterizes a PAKE algorithm and determines + * the algorithm as well.) + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p cipher_suite is not supported or is not valid. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_setup(psa_pake_operation_t *operation, + psa_pake_cipher_suite_t cipher_suite); + +/** Set the password for a password-authenticated key exchange from key ID. + * + * Call this function when the password, or a value derived from the password, + * is already present in the key store. + * + * \param[in,out] operation The operation object to set the password for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the password hasn't + * been set yet (psa_pake_set_password_key() + * hasn't been called yet). + * \param password Identifier of the key holding the password or a + * value derived from the password (eg. by a + * memory-hard function). It must remain valid + * until the operation terminates. It must be of + * type #PSA_KEY_TYPE_PASSWORD or + * #PSA_KEY_TYPE_PASSWORD_HASH. It has to allow + * the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must have been set up.) + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p key is not compatible with the algorithm or the cipher suite. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation, + mbedtls_svc_key_id_t password); + +/** Set the user ID for a password-authenticated key exchange. + * + * Call this function to set the user ID. For PAKE algorithms that associate a + * user identifier with each side of the session you need to call + * psa_pake_set_peer() as well. For PAKE algorithms that associate a single + * user identifier with the session, call psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the user ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the user ID hasn't + * been set (psa_pake_set_user() hasn't been + * called yet). + * \param[in] user_id The user ID to authenticate with. + * \param user_id_len Size of the \p user_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is NULL. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_user(psa_pake_operation_t *operation, + const uint8_t *user_id, + size_t user_id_len); + +/** Set the peer ID for a password-authenticated key exchange. + * + * Call this function in addition to psa_pake_set_user() for PAKE algorithms + * that associate a user identifier with each side of the session. For PAKE + * algorithms that associate a single user identifier with the session, call + * psa_pake_set_user() only. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the peer ID for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the peer ID hasn't + * been set (psa_pake_set_peer() hasn't been + * called yet). + * \param[in] peer_id The peer's ID to authenticate. + * \param peer_id_len Size of the \p peer_id buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The algorithm doesn't associate a second identity with the session. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p user_id is NULL. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_peer(psa_pake_operation_t *operation, + const uint8_t *peer_id, + size_t peer_id_len); + +/** Set the side for a password-authenticated key exchange. + * + * Not all PAKE algorithms need to differentiate the communicating entities. + * It is optional to call this function for PAKEs that don't require a side + * parameter. For such PAKEs the side parameter is ignored. + * + * Refer to the documentation of individual PAKE algorithm types (`PSA_ALG_XXX` + * values of type ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) + * for more information. + * + * \param[in,out] operation The operation object to set the side for. It + * must have been set up by psa_pake_setup() and + * not yet in use (neither psa_pake_output() nor + * psa_pake_input() has been called yet). It must + * be on operation for which the side hasn't been + * set (psa_pake_set_side() hasn't been called + * yet). + * \param side A value of type ::psa_pake_side_t signaling the + * side of the algorithm that is being set up. For + * more information see the documentation of + * \c PSA_PAKE_SIDE_XXX constants. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The \p side for this algorithm is not supported or is not valid. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_set_side(psa_pake_operation_t *operation, + psa_pake_side_t side); + +/** Get output for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step of the algorithm for which the output is + * requested. + * \param[out] output Buffer where the output is to be written in the + * format appropriate for this \p step. Refer to + * the documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param output_size Size of the \p output buffer in bytes. This must + * be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \c + * cipher_suite, \p type). + * + * \param[out] output_length On success, the number of bytes of the returned + * output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_output(psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Provide input for a step of a password-authenticated key exchange. + * + * Depending on the algorithm being executed, you might need to call this + * function several times or you might not need to call this at all. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_pake_abort(). + * + * \param[in,out] operation Active PAKE operation. + * \param step The step for which the input is provided. + * \param[out] input Buffer containing the input in the format + * appropriate for this \p step. Refer to the + * documentation of the individual + * \c PSA_PAKE_STEP_XXX constants for more + * information. + * \param[out] input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, but beyond that + * validity is specific to the algorithm). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The input is not valid for the algorithm, ciphersuite or \p step. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_input(psa_pake_operation_t *operation, + psa_pake_step_t step, + uint8_t *input, + size_t input_length); + +/** Get implicitly confirmed shared secret from a PAKE. + * + * At this point there is a cryptographic guarantee that only the authenticated + * party who used the same password is able to compute the key. But there is no + * guarantee that the peer is the party it claims to be and was able to do so. + * + * That is, the authentication is only implicit. Since the peer is not + * authenticated yet, no action should be taken yet that assumes that the peer + * is who it claims to be. For example, do not access restricted files on the + * peer's behalf until an explicit authentication has succeeded. + * + * This function can be called after the key exchange phase of the operation + * has completed. It imports the shared secret output of the PAKE into the + * provided derivation operation. The input step + * #PSA_KEY_DERIVATION_INPUT_SECRET is used when placing the shared key + * material in the key derivation operation. + * + * The exact sequence of calls to perform a password-authenticated key + * exchange depends on the algorithm in use. Refer to the documentation of + * individual PAKE algorithm types (`PSA_ALG_XXX` values of type + * ::psa_algorithm_t such that #PSA_ALG_IS_PAKE(\c alg) is true) for more + * information. + * + * When this function returns successfully, \p operation becomes inactive. + * If this function returns an error status, both \p operation + * and \p key_derivation operations enter an error state and must be aborted by + * calling psa_pake_abort() and psa_key_derivation_abort() respectively. + * + * \param[in,out] operation Active PAKE operation. + * \param[out] output A key derivation operation that is ready + * for an input step of type + * #PSA_KEY_DERIVATION_INPUT_SECRET. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The PAKE operation state is not valid (it must be active, but beyond + * that validity is specific to the algorithm). + * \retval #PSA_ERROR_BAD_STATE + * The state of \p output is not valid for + * the #PSA_KEY_DERIVATION_INPUT_SECRET step. This can happen if the + * step is out of order or the application has done this step already + * and it may not be repeated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * #PSA_KEY_DERIVATION_INPUT_SECRET is not compatible with the output’s + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_pake_get_implicit_key(psa_pake_operation_t *operation, + psa_key_derivation_operation_t *output); + +/**@}*/ + +/** A sufficient output buffer size for psa_pake_output(). + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_pake_output() will not fail due to an insufficient output buffer + * size. The actual size of the output might be smaller in any given call. + * + * See also #PSA_PAKE_OUTPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param output_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient output buffer size for the specified + * output, cipher suite and algorithm. If the cipher suite, + * the output type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_OUTPUT_SIZE(alg, primitive, output_step) 0 + +/** A sufficient input buffer size for psa_pake_input(). + * + * The value returned by this macro is guaranteed to be large enough for any + * valid input to psa_pake_input() in an operation with the specified + * parameters. + * + * See also #PSA_PAKE_INPUT_MAX_SIZE + * + * \param alg A PAKE algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_PAKE(\p alg) is true). + * \param primitive A primitive of type ::psa_pake_primitive_t that is + * compatible with algorithm \p alg. + * \param input_step A value of type ::psa_pake_step_t that is valid for the + * algorithm \p alg. + * \return A sufficient input buffer size for the specified + * input, cipher suite and algorithm. If the cipher suite, + * the input type or PAKE algorithm is not recognized, or + * the parameters are incompatible, return 0. + */ +#define PSA_PAKE_INPUT_SIZE(alg, primitive, input_step) 0 + +/** Output buffer size for psa_pake_output() for any of the supported cipher + * suites and PAKE algorithms. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p cipher_suite, \p output). + */ +#define PSA_PAKE_OUTPUT_MAX_SIZE 0 + +/** Input buffer size for psa_pake_input() for any of the supported cipher + * suites and PAKE algorithms. + * + * This macro must expand to a compile-time constant integer. + * + * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p cipher_suite, \p input). + */ +#define PSA_PAKE_INPUT_MAX_SIZE 0 + +struct psa_pake_cipher_suite_s +{ + psa_algorithm_t algorithm; + psa_pake_primitive_type_t type; + psa_pake_family_t family; + uint16_t bits; + psa_algorithm_t hash; +}; + +static inline psa_algorithm_t psa_pake_cs_get_algorithm( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return(cipher_suite->algorithm); +} + +static inline void psa_pake_cs_set_algorithm( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t algorithm) +{ + if(!PSA_ALG_IS_PAKE(algorithm)) + cipher_suite->algorithm = 0; + else + cipher_suite->algorithm = algorithm; +} + +static inline psa_pake_primitive_t psa_pake_cs_get_primitive( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return(PSA_PAKE_PRIMITIVE(cipher_suite->type, cipher_suite->family, + cipher_suite->bits)); +} + +static inline void psa_pake_cs_set_primitive( + psa_pake_cipher_suite_t *cipher_suite, + psa_pake_primitive_t primitive) +{ + cipher_suite->type = (psa_pake_primitive_type_t) (primitive >> 24); + cipher_suite->family = (psa_pake_family_t) (0xFF & (primitive >> 16)); + cipher_suite->bits = (uint16_t) (0xFFFF & primitive); +} + +static inline psa_algorithm_t psa_pake_cs_get_hash( + const psa_pake_cipher_suite_t *cipher_suite) +{ + return(cipher_suite->hash); +} + +static inline void psa_pake_cs_set_hash( + psa_pake_cipher_suite_t *cipher_suite, + psa_algorithm_t hash) +{ + if(!PSA_ALG_IS_HASH(hash)) + cipher_suite->hash = 0; + else + cipher_suite->hash = hash; +} + +struct psa_pake_operation_s +{ + psa_algorithm_t alg; + union + { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t dummy; + } ctx; +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_PAKE_OPERATION_INIT {0, {0}} +static inline struct psa_pake_operation_s psa_pake_operation_init(void) +{ + const struct psa_pake_operation_s v = PSA_PAKE_OPERATION_INIT; + return(v); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_platform.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_platform.h new file mode 100644 index 00000000..4787e44b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_platform.h @@ -0,0 +1,108 @@ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H +#include "mbedtls/private_access.h" + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#include "mbedtls/build_info.h" + +/* Translate between classic MBEDTLS_xxx feature symbols and PSA_xxx + * feature symbols. */ +#include "mbedtls/config_psa.h" + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + +/* Building for the PSA Crypto service on a PSA platform, a key owner is a PSA + * partition identifier. + * + * The function psa_its_identifier_of_slot() in psa_crypto_storage.c that + * translates a key identifier to a key storage file name assumes that + * mbedtls_key_owner_id_t is an 32 bits integer. This function thus needs + * reworking if mbedtls_key_owner_id_t is not defined as a 32 bits integer + * here anymore. + */ +typedef int32_t mbedtls_key_owner_id_t; + +/** Compare two key owner identifiers. + * + * \param id1 First key owner identifier. + * \param id2 Second key owner identifier. + * + * \return Non-zero if the two key owner identifiers are equal, zero otherwise. + */ +static inline int mbedtls_key_owner_id_equal( mbedtls_key_owner_id_t id1, + mbedtls_key_owner_id_t id2 ) +{ + return( id1 == id2 ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/* + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM + * (Secure Partition Manager) integration which separates the code into two + * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing + * Environment). When building for the SPE, an additional header file should be + * included. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) +#define PSA_CRYPTO_SECURE 1 +#include "crypto_spe.h" +#endif // MBEDTLS_PSA_CRYPTO_SPM + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** The type of the context passed to mbedtls_psa_external_get_random(). + * + * Mbed TLS initializes the context to all-bits-zero before calling + * mbedtls_psa_external_get_random() for the first time. + * + * The definition of this type in the Mbed TLS source code is for + * demonstration purposes. Implementers of mbedtls_psa_external_get_random() + * are expected to replace it with a custom definition. + */ +typedef struct { + uintptr_t MBEDTLS_PRIVATE(opaque)[2]; +} mbedtls_psa_external_random_context_t; +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_se_driver.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_se_driver.h new file mode 100644 index 00000000..91a6d0be --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_se_driver.h @@ -0,0 +1,1396 @@ +/** + * \file psa/crypto_se_driver.h + * \brief PSA external cryptoprocessor driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material via opaque references. + * This is meant for cryptoprocessors that have a separate key storage from the + * space in which the PSA Crypto implementation runs, typically secure + * elements (SEs). + * + * This file is part of the PSA Crypto Driver HAL (hardware abstraction layer), + * containing functions for driver developers to implement to enable hardware + * to be called in a standardized way by a PSA Cryptography API + * implementation. The functions comprising the driver HAL, which driver + * authors implement, are not intended to be called by application developers. + */ + +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef PSA_CRYPTO_SE_DRIVER_H +#define PSA_CRYPTO_SE_DRIVER_H +#include "mbedtls/private_access.h" + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup se_init Secure element driver initialization + */ +/**@{*/ + +/** \brief Driver context structure + * + * Driver functions receive a pointer to this structure. + * Each registered driver has one instance of this structure. + * + * Implementations must include the fields specified here and + * may include other fields. + */ +typedef struct { + /** A read-only pointer to the driver's persistent data. + * + * Drivers typically use this persistent data to keep track of + * which slot numbers are available. This is only a guideline: + * drivers may use the persistent data for any purpose, keeping + * in mind the restrictions on when the persistent data is saved + * to storage: the persistent data is only saved after calling + * certain functions that receive a writable pointer to the + * persistent data. + * + * The core allocates a memory buffer for the persistent data. + * The pointer is guaranteed to be suitably aligned for any data type, + * like a pointer returned by `malloc` (but the core can use any + * method to allocate the buffer, not necessarily `malloc`). + * + * The size of this buffer is in the \c persistent_data_size field of + * this structure. + * + * Before the driver is initialized for the first time, the content of + * the persistent data is all-bits-zero. After a driver upgrade, if the + * size of the persistent data has increased, the original data is padded + * on the right with zeros; if the size has decreased, the original data + * is truncated to the new size. + * + * This pointer is to read-only data. Only a few driver functions are + * allowed to modify the persistent data. These functions receive a + * writable pointer. These functions are: + * - psa_drv_se_t::p_init + * - psa_drv_se_key_management_t::p_allocate + * - psa_drv_se_key_management_t::p_destroy + * + * The PSA Cryptography core saves the persistent data from one + * session to the next. It does this before returning from API functions + * that call a driver method that is allowed to modify the persistent + * data, specifically: + * - psa_crypto_init() causes a call to psa_drv_se_t::p_init, and may call + * psa_drv_se_key_management_t::p_destroy to complete an action + * that was interrupted by a power failure. + * - Key creation functions cause a call to + * psa_drv_se_key_management_t::p_allocate, and may cause a call to + * psa_drv_se_key_management_t::p_destroy in case an error occurs. + * - psa_destroy_key() causes a call to + * psa_drv_se_key_management_t::p_destroy. + */ + const void *const MBEDTLS_PRIVATE(persistent_data); + + /** The size of \c persistent_data in bytes. + * + * This is always equal to the value of the `persistent_data_size` field + * of the ::psa_drv_se_t structure when the driver is registered. + */ + const size_t MBEDTLS_PRIVATE(persistent_data_size); + + /** Driver transient data. + * + * The core initializes this value to 0 and does not read or modify it + * afterwards. The driver may store whatever it wants in this field. + */ + uintptr_t MBEDTLS_PRIVATE(transient_data); +} psa_drv_se_context_t; + +/** \brief A driver initialization function. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param location The location value for which this driver + * is registered. The driver will be invoked + * for all keys whose lifetime is in this + * location. + * + * \retval #PSA_SUCCESS + * The driver is operational. + * The core will update the persistent data in storage. + * \return + * Any other return value prevents the driver from being used in + * this session. + * The core will NOT update the persistent data in storage. + */ +typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_location_t location); + +#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto with secure element support enabled defines this type in + * crypto_types.h because it is also visible to applications through an + * implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +/** An internal designation of a key slot between the core part of the + * PSA Crypto implementation and the driver. The meaning of this value + * is driver-dependent. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */ + +/**@}*/ + +/** \defgroup se_mac Secure Element Message Authentication Codes + * Generation and authentication of Message Authentication Codes (MACs) using + * a secure element can be done either as a single function call (via the + * `psa_drv_se_mac_generate_t` or `psa_drv_se_mac_verify_t` functions), or in + * parts using the following sequence: + * - `psa_drv_se_mac_setup_t` + * - `psa_drv_se_mac_update_t` + * - `psa_drv_se_mac_update_t` + * - ... + * - `psa_drv_se_mac_finish_t` or `psa_drv_se_mac_finish_verify_t` + * + * If a previously started secure element MAC operation needs to be terminated, + * it should be done so by the `psa_drv_se_mac_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + */ +/**@{*/ +/** \brief A function that starts a secure element MAC operation for a PSA + * Crypto Driver implementation + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific MAC context + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used to underly the MAC + * operation + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm); + +/** \brief A function that continues a previously started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously-established MAC operation to be + * updated + * \param[in] p_input A buffer containing the message to be appended + * to the MAC operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_se_mac_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief a function that completes a previously started secure element MAC + * operation by returning the resulting MAC. + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started MAC operation to be + * finished + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the buffer that has been + * allocated for the `output` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `p_mac` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_finish_t)(void *op_context, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that completes a previously started secure element MAC + * operation by comparing the resulting MAC against a provided value + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be fiinished + * \param[in] p_mac The MAC value against which the resulting MAC + * will be compared against + * \param[in] mac_length The size in bytes of the value stored in `p_mac` + * + * \retval #PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_finish_verify_t)(void *op_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A function that aborts a previous started secure element MAC + * operation + * + * \param[in,out] op_context A hardware-specific structure for the previously + * started MAC operation to be aborted + */ +typedef psa_status_t (*psa_drv_se_mac_abort_t)(void *op_context); + +/** \brief A function that performs a secure element MAC operation in one + * command and returns the calculated MAC + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `p_input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[out] p_mac A buffer where the generated MAC will be + * placed + * \param[in] mac_size The size in bytes of the `p_mac` buffer + * \param[out] p_mac_length After completion, will contain the number of + * bytes placed in the `output` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_mac_generate_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_size, + size_t *p_mac_length); + +/** \brief A function that performs a secure element MAC operation in one + * command and compares the resulting MAC against a provided value + * + * \param[in,out] drv_context The driver context structure. + * \param[in] p_input A buffer containing the message to be MACed + * \param[in] input_length The size in bytes of `input` + * \param[in] key_slot The slot of the key to be used + * \param[in] alg The algorithm to be used to underlie the MAC + * operation + * \param[in] p_mac The MAC value against which the resulting MAC will + * be compared against + * \param[in] mac_length The size in bytes of `mac` + * + * \retval #PSA_SUCCESS + * The operation completed successfully and the MACs matched each + * other + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The operation completed successfully, but the calculated MAC did + * not match the provided MAC + */ +typedef psa_status_t (*psa_drv_se_mac_verify_t)(psa_drv_se_context_t *drv_context, + const uint8_t *p_input, + size_t input_length, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief A struct containing all of the function pointers needed to + * perform secure element MAC operations + * + * PSA Crypto API implementations should populate the table as appropriate + * upon startup. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_mac_generate_t`), it should be set to NULL. + * + * Driver implementers should ensure that they implement all of the functions + * that make sense for their hardware, and that they provide a full solution + * (for example, if they support `p_setup`, they should also support + * `p_update` and at least one of `p_finish` or `p_finish_verify`). + * + */ +typedef struct { + /**The size in bytes of the hardware-specific secure element MAC context + * structure + */ + size_t MBEDTLS_PRIVATE(context_size); + /** Function that performs a MAC setup operation + */ + psa_drv_se_mac_setup_t MBEDTLS_PRIVATE(p_setup); + /** Function that performs a MAC update operation + */ + psa_drv_se_mac_update_t MBEDTLS_PRIVATE(p_update); + /** Function that completes a MAC operation + */ + psa_drv_se_mac_finish_t MBEDTLS_PRIVATE(p_finish); + /** Function that completes a MAC operation with a verify check + */ + psa_drv_se_mac_finish_verify_t MBEDTLS_PRIVATE(p_finish_verify); + /** Function that aborts a previoustly started MAC operation + */ + psa_drv_se_mac_abort_t MBEDTLS_PRIVATE(p_abort); + /** Function that performs a MAC operation in one call + */ + psa_drv_se_mac_generate_t MBEDTLS_PRIVATE(p_mac); + /** Function that performs a MAC and verify operation in one call + */ + psa_drv_se_mac_verify_t MBEDTLS_PRIVATE(p_mac_verify); +} psa_drv_se_mac_t; +/**@}*/ + +/** \defgroup se_cipher Secure Element Symmetric Ciphers + * + * Encryption and Decryption using secure element keys in block modes other + * than ECB must be done in multiple parts, using the following flow: + * - `psa_drv_se_cipher_setup_t` + * - `psa_drv_se_cipher_set_iv_t` (optional depending upon block mode) + * - `psa_drv_se_cipher_update_t` + * - `psa_drv_se_cipher_update_t` + * - ... + * - `psa_drv_se_cipher_finish_t` + * + * If a previously started secure element Cipher operation needs to be + * terminated, it should be done so by the `psa_drv_se_cipher_abort_t`. Failure + * to do so may result in allocated resources not being freed or in other + * undefined behavior. + * + * In situations where a PSA Cryptographic API implementation is using a block + * mode not-supported by the underlying hardware or driver, it can construct + * the block mode itself, while calling the `psa_drv_se_cipher_ecb_t` function + * for the cipher operations. + */ +/**@{*/ + +/** \brief A function that provides the cipher setup function for a + * secure element driver + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A structure that will contain the + * hardware-specific cipher context. + * \param[in] key_slot The slot of the key to be used for the + * operation + * \param[in] algorithm The algorithm to be used in the cipher + * operation + * \param[in] direction Indicates whether the operation is an encrypt + * or decrypt + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + */ +typedef psa_status_t (*psa_drv_se_cipher_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction); + +/** \brief A function that sets the initialization vector (if + * necessary) for an secure element cipher operation + * + * Rationale: The `psa_se_cipher_*` operation in the PSA Cryptographic API has + * two IV functions: one to set the IV, and one to generate it internally. The + * generate function is not necessary for the drivers to implement as the PSA + * Crypto implementation can do the generation using its RNG features. + * + * \param[in,out] op_context A structure that contains the previously set up + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vector + * \param[in] iv_length The size (in bytes) of the `p_iv` buffer + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_set_iv_t)(void *op_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief A function that continues a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to + * by `p_input` + * \param[out] p_output The caller-allocated buffer where the + * output will be placed + * \param[in] output_size The allocated size in bytes of the + * `p_output` buffer + * \param[out] p_output_length After completion, will contain the number + * of bytes placed in the `p_output` buffer + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_update_t)(void *op_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that completes a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * \param[out] p_output_length After completion, will contain the number of + * bytes placed in the `p_output` buffer + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_cipher_finish_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief A function that aborts a previously started secure element cipher + * operation + * + * \param[in,out] op_context A hardware-specific structure for the + * previously started cipher operation + */ +typedef psa_status_t (*psa_drv_se_cipher_abort_t)(void *op_context); + +/** \brief A function that performs the ECB block mode for secure element + * cipher operations + * + * Note: this function should only be used with implementations that do not + * provide a needed higher-level operation. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot The slot of the key to be used for the operation + * \param[in] algorithm The algorithm to be used in the cipher operation + * \param[in] direction Indicates whether the operation is an encrypt or + * decrypt + * \param[in] p_input A buffer containing the data to be + * encrypted/decrypted + * \param[in] input_size The size in bytes of the buffer pointed to by + * `p_input` + * \param[out] p_output The caller-allocated buffer where the output + * will be placed + * \param[in] output_size The allocated size in bytes of the `p_output` + * buffer + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + */ +typedef psa_status_t (*psa_drv_se_cipher_ecb_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size); + +/** + * \brief A struct containing all of the function pointers needed to implement + * cipher operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented (such as + * `psa_drv_se_cipher_ecb_t`), it should be set to NULL. + */ +typedef struct { + /** The size in bytes of the hardware-specific secure element cipher + * context structure + */ + size_t MBEDTLS_PRIVATE(context_size); + /** Function that performs a cipher setup operation */ + psa_drv_se_cipher_setup_t MBEDTLS_PRIVATE(p_setup); + /** Function that sets a cipher IV (if necessary) */ + psa_drv_se_cipher_set_iv_t MBEDTLS_PRIVATE(p_set_iv); + /** Function that performs a cipher update operation */ + psa_drv_se_cipher_update_t MBEDTLS_PRIVATE(p_update); + /** Function that completes a cipher operation */ + psa_drv_se_cipher_finish_t MBEDTLS_PRIVATE(p_finish); + /** Function that aborts a cipher operation */ + psa_drv_se_cipher_abort_t MBEDTLS_PRIVATE(p_abort); + /** Function that performs ECB mode for a cipher operation + * (Danger: ECB mode should not be used directly by clients of the PSA + * Crypto Client API) + */ + psa_drv_se_cipher_ecb_t MBEDTLS_PRIVATE(p_ecb); +} psa_drv_se_cipher_t; + +/**@}*/ + +/** \defgroup se_asymmetric Secure Element Asymmetric Cryptography + * + * Since the amount of data that can (or should) be encrypted or signed using + * asymmetric keys is limited by the key size, asymmetric key operations using + * keys in a secure element must be done in single function calls. + */ +/**@{*/ + +/** + * \brief A function that signs a hash or short message with a private key in + * a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg A signature algorithm that is compatible + * with the type of `key` + * \param[in] p_hash The hash to sign + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[out] p_signature Buffer where the signature is to be written + * \param[in] signature_size Size of the `p_signature` buffer in bytes + * \param[out] p_signature_length On success, the number of bytes + * that make up the returned signature value + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_sign_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + uint8_t *p_signature, + size_t signature_size, + size_t *p_signature_length); + +/** + * \brief A function that verifies the signature a hash or short message using + * an asymmetric public key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_hash The hash whose signature is to be verified + * \param[in] hash_length Size of the `p_hash` buffer in bytes + * \param[in] p_signature Buffer containing the signature to verify + * \param[in] signature_length Size of the `p_signature` buffer in bytes + * + * \retval #PSA_SUCCESS + * The signature is valid. + */ +typedef psa_status_t (*psa_drv_se_asymmetric_verify_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_hash, + size_t hash_length, + const uint8_t *p_signature, + size_t signature_length); + +/** + * \brief A function that encrypts a short message with an asymmetric public + * key in a secure element + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of a public key or an asymmetric key + * pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to encrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the encrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes that make up + * the returned output + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A function that decrypts a short message with an asymmetric private + * key in a secure element. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Key slot of an asymmetric key pair + * \param[in] alg An asymmetric encryption algorithm that is + * compatible with the type of `key` + * \param[in] p_input The message to decrypt + * \param[in] input_length Size of the `p_input` buffer in bytes + * \param[in] p_salt A salt or label, if supported by the + * encryption algorithm + * If the algorithm does not support a + * salt, pass `NULL`. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass `NULL`. + * For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param[in] salt_length Size of the `p_salt` buffer in bytes + * If `p_salt` is `NULL`, pass 0. + * \param[out] p_output Buffer where the decrypted message is to + * be written + * \param[in] output_size Size of the `p_output` buffer in bytes + * \param[out] p_output_length On success, the number of bytes + * that make up the returned output + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_asymmetric_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t alg, + const uint8_t *p_input, + size_t input_length, + const uint8_t *p_salt, + size_t salt_length, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * asymmetric cryptographic operations using secure elements. + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs an asymmetric sign operation */ + psa_drv_se_asymmetric_sign_t MBEDTLS_PRIVATE(p_sign); + /** Function that performs an asymmetric verify operation */ + psa_drv_se_asymmetric_verify_t MBEDTLS_PRIVATE(p_verify); + /** Function that performs an asymmetric encrypt operation */ + psa_drv_se_asymmetric_encrypt_t MBEDTLS_PRIVATE(p_encrypt); + /** Function that performs an asymmetric decrypt operation */ + psa_drv_se_asymmetric_decrypt_t MBEDTLS_PRIVATE(p_decrypt); +} psa_drv_se_asymmetric_t; + +/**@}*/ + +/** \defgroup se_aead Secure Element Authenticated Encryption with Additional Data + * Authenticated Encryption with Additional Data (AEAD) operations with secure + * elements must be done in one function call. While this creates a burden for + * implementers as there must be sufficient space in memory for the entire + * message, it prevents decrypted data from being made available before the + * authentication operation is complete and the data is known to be authentic. + */ +/**@{*/ + +/** \brief A function that performs a secure element authenticated encryption + * operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use. + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that will be + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_plaintext Data that will be authenticated and + * encrypted + * \param[in] plaintext_length Size of `p_plaintext` in bytes + * \param[out] p_ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is + * not part of this output. For algorithms + * where the encrypted data and the + * authentication tag are defined as + * separate outputs, the authentication + * tag is appended to the encrypted data. + * \param[in] ciphertext_size Size of the `p_ciphertext` buffer in + * bytes + * \param[out] p_ciphertext_length On success, the size of the output in + * the `p_ciphertext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_encrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_plaintext, + size_t plaintext_length, + uint8_t *p_ciphertext, + size_t ciphertext_size, + size_t *p_ciphertext_length); + +/** A function that peforms a secure element authenticated decryption operation + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key_slot Slot containing the key to use + * \param[in] algorithm The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] p_nonce Nonce or IV to use + * \param[in] nonce_length Size of the `p_nonce` buffer in bytes + * \param[in] p_additional_data Additional data that has been + * authenticated but not encrypted + * \param[in] additional_data_length Size of `p_additional_data` in bytes + * \param[in] p_ciphertext Data that has been authenticated and + * encrypted. + * For algorithms where the encrypted data + * and the authentication tag are defined + * as separate inputs, the buffer must + * contain the encrypted data followed by + * the authentication tag. + * \param[in] ciphertext_length Size of `p_ciphertext` in bytes + * \param[out] p_plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `p_plaintext` buffer in + * bytes + * \param[out] p_plaintext_length On success, the size of the output in + * the `p_plaintext` buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_aead_decrypt_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + psa_algorithm_t algorithm, + const uint8_t *p_nonce, + size_t nonce_length, + const uint8_t *p_additional_data, + size_t additional_data_length, + const uint8_t *p_ciphertext, + size_t ciphertext_length, + uint8_t *p_plaintext, + size_t plaintext_size, + size_t *p_plaintext_length); + +/** + * \brief A struct containing all of the function pointers needed to implement + * secure element Authenticated Encryption with Additional Data operations + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that performs the AEAD encrypt operation */ + psa_drv_se_aead_encrypt_t MBEDTLS_PRIVATE(p_encrypt); + /** Function that performs the AEAD decrypt operation */ + psa_drv_se_aead_decrypt_t MBEDTLS_PRIVATE(p_decrypt); +} psa_drv_se_aead_t; +/**@}*/ + +/** \defgroup se_key_management Secure Element Key Management + * Currently, key management is limited to importing keys in the clear, + * destroying keys, and exporting keys in the clear. + * Whether a key may be exported is determined by the key policies in place + * on the key slot. + */ +/**@{*/ + +/** An enumeration indicating how a key is created. + */ +typedef enum +{ + PSA_KEY_CREATION_IMPORT, /**< During psa_import_key() */ + PSA_KEY_CREATION_GENERATE, /**< During psa_generate_key() */ + PSA_KEY_CREATION_DERIVE, /**< During psa_key_derivation_output_key() */ + PSA_KEY_CREATION_COPY, /**< During psa_copy_key() */ + +#ifndef __DOXYGEN_ONLY__ + /** A key is being registered with mbedtls_psa_register_se_key(). + * + * The core only passes this value to + * psa_drv_se_key_management_t::p_validate_slot_number, not to + * psa_drv_se_key_management_t::p_allocate. The call to + * `p_validate_slot_number` is not followed by any other call to the + * driver: the key is considered successfully registered if the call to + * `p_validate_slot_number` succeeds, or if `p_validate_slot_number` is + * null. + * + * With this creation method, the driver must return #PSA_SUCCESS if + * the given attributes are compatible with the existing key in the slot, + * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there + * is no key with the specified slot number. + * + * This is an Mbed Crypto extension. + */ + PSA_KEY_CREATION_REGISTER, +#endif +} psa_key_creation_method_t; + +/** \brief A function that allocates a slot for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to determine a valid slot number, + * then calls a function to create the key material in that slot. + * In nominal conditions (that is, if no error occurs), + * the effect of a call to a key creation function in the PSA Cryptography + * API with a lifetime that places the key in a secure element is the + * following: + * -# The core calls psa_drv_se_key_management_t::p_allocate + * (or in some implementations + * psa_drv_se_key_management_t::p_validate_slot_number). The driver + * selects (or validates) a suitable slot number given the key attributes + * and the state of the secure element. + * -# The core calls a key creation function in the driver. + * + * The key creation functions in the PSA Cryptography API are: + * - psa_import_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_IMPORT + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_generate_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_GENERATE + * then a call to psa_drv_se_key_management_t::p_import. + * - psa_key_derivation_output_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_DERIVE + * then a call to psa_drv_se_key_derivation_t::p_derive. + * - psa_copy_key(), which causes + * a call to `p_allocate` with \p method = #PSA_KEY_CREATION_COPY + * then a call to psa_drv_se_key_management_t::p_export. + * + * In case of errors, other behaviors are possible. + * - If the PSA Cryptography subsystem dies after the first step, + * for example because the device has lost power abruptly, + * the second step may never happen, or may happen after a reset + * and re-initialization. Alternatively, after a reset and + * re-initialization, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * - If an error occurs, the core may call + * psa_drv_se_key_management_t::p_destroy on the slot number that + * was allocated (or validated) instead of calling a key creation function. + * + * Errors and system resets also have an impact on the driver's persistent + * data. If a reset happens before the overall key creation process is + * completed (before or after the second step above), it is unspecified + * whether the persistent data after the reset is identical to what it + * was before or after the call to `p_allocate` (or `p_validate_slot_number`). + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[out] key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * + * \retval #PSA_SUCCESS + * Success. + * The core will record \c *key_slot as the key slot where the key + * is stored and will update the persistent data in storage. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + */ +typedef psa_status_t (*psa_drv_se_allocate_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t *key_slot); + +/** \brief A function that determines whether a slot number is valid + * for a key. + * + * To create a key in a specific slot in a secure element, the core + * first calls this function to validate the choice of slot number, + * then calls a function to create the key material in that slot. + * See the documentation of #psa_drv_se_allocate_key_t for more details. + * + * As of the PSA Cryptography API specification version 1.0, there is no way + * for applications to trigger a call to this function. However some + * implementations offer the capability to create or declare a key in + * a specific slot via implementation-specific means, generally for the + * sake of initial device provisioning or onboarding. Such a mechanism may + * be added to a future version of the PSA Cryptography API specification. + * + * This function may update the driver's persistent data through + * \p persistent_data. The core will save the updated persistent data at the + * end of the key creation process. See the description of + * ::psa_drv_se_allocate_key_t for more information. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param[in] attributes Attributes of the key. + * \param method The way in which the key is being created. + * \param[in] key_slot Slot where the key is to be stored. + * + * \retval #PSA_SUCCESS + * The given slot number is valid for a key with the given + * attributes. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The given slot number is not valid for a key with the + * given attributes. This includes the case where the slot + * number is not valid at all. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the specified slot number. + * Drivers may choose to return this error from the key + * creation function instead. + */ +typedef psa_status_t (*psa_drv_se_validate_slot_number_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_key_slot_number_t key_slot); + +/** \brief A function that imports a key into a secure element in binary format + * + * This function can support any output from psa_export_key(). Refer to the + * documentation of psa_export_key() for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and the usage policy. + * Drivers should not access the key size stored + * in the attributes: it may not match the + * data passed in \p data. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[in] data Buffer containing the key data. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] bits On success, the key size in bits. The driver + * must determine this value after parsing the + * key according to the key type. + * This value is not used if the function fails. + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_se_import_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *bits); + +/** + * \brief A function that destroys a secure element key and restore the slot to + * its default state + * + * This function destroys the content of the key from a secure element. + * Implementations shall make a best effort to ensure that any previous content + * of the slot is unrecoverable. + * + * This function returns the specified slot to its default state. + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] persistent_data A pointer to the persistent data + * that allows writing. + * \param key_slot The key slot to erase. + * + * \retval #PSA_SUCCESS + * The slot's content, if any, has been erased. + */ +typedef psa_status_t (*psa_drv_se_destroy_key_t)( + psa_drv_se_context_t *drv_context, + void *persistent_data, + psa_key_slot_number_t key_slot); + +/** + * \brief A function that exports a secure element key in binary format + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If a key is created with `psa_import_key()` and then exported with + * this function, it is not guaranteed that the resulting data is + * identical: the implementation may choose a different representation + * of the same key if the format permits it. + * + * This function should generate output in the same format that + * `psa_export_key()` does. Refer to the + * documentation of `psa_export_key()` for the format for each key type. + * + * \param[in,out] drv_context The driver context structure. + * \param[in] key Slot whose content is to be exported. This must + * be an occupied key slot. + * \param[out] p_data Buffer where the key data is to be written. + * \param[in] data_size Size of the `p_data` buffer in bytes. + * \param[out] p_data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +typedef psa_status_t (*psa_drv_se_export_key_t)(psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key, + uint8_t *p_data, + size_t data_size, + size_t *p_data_length); + +/** + * \brief A function that generates a symmetric or asymmetric key on a secure + * element + * + * If the key type \c type recorded in \p attributes + * is asymmetric (#PSA_KEY_TYPE_IS_ASYMMETRIC(\c type) = 1), + * the driver may export the public key at the time of generation, + * in the format documented for psa_export_public_key() by writing it + * to the \p pubkey buffer. + * This is optional, intended for secure elements that output the + * public key at generation time and that cannot export the public key + * later. Drivers that do not need this feature should leave + * \p *pubkey_length set to 0 and should + * implement the psa_drv_key_management_t::p_export_public function. + * Some implementations do not support this feature, in which case + * \p pubkey is \c NULL and \p pubkey_size is 0. + * + * \param[in,out] drv_context The driver context structure. + * \param key_slot Slot where the key will be stored. + * This must be a valid slot for a key of the + * chosen type. It must be unoccupied. + * \param[in] attributes The key attributes, including the lifetime, + * the key type and size, and the usage policy. + * Drivers can call psa_get_key_lifetime(), + * psa_get_key_type(), psa_get_key_bits(), + * psa_get_key_usage_flags() and + * psa_get_key_algorithm() to access this + * information. + * \param[out] pubkey A buffer where the driver can write the + * public key, when generating an asymmetric + * key pair. + * This is \c NULL when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param pubkey_size The size of the `pubkey` buffer in bytes. + * This is 0 when generating a symmetric + * key or if the core does not support + * exporting the public key at generation time. + * \param[out] pubkey_length On entry, this is always 0. + * On success, the number of bytes written to + * \p pubkey. If this is 0 or unchanged on return, + * the core will not read the \p pubkey buffer, + * and will instead call the driver's + * psa_drv_key_management_t::p_export_public + * function to export the public key when needed. + */ +typedef psa_status_t (*psa_drv_se_generate_key_t)( + psa_drv_se_context_t *drv_context, + psa_key_slot_number_t key_slot, + const psa_key_attributes_t *attributes, + uint8_t *pubkey, size_t pubkey_size, size_t *pubkey_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key management + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup or at build time. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** Function that allocates a slot for a key. */ + psa_drv_se_allocate_key_t MBEDTLS_PRIVATE(p_allocate); + /** Function that checks the validity of a slot for a key. */ + psa_drv_se_validate_slot_number_t MBEDTLS_PRIVATE(p_validate_slot_number); + /** Function that performs a key import operation */ + psa_drv_se_import_key_t MBEDTLS_PRIVATE(p_import); + /** Function that performs a generation */ + psa_drv_se_generate_key_t MBEDTLS_PRIVATE(p_generate); + /** Function that performs a key destroy operation */ + psa_drv_se_destroy_key_t MBEDTLS_PRIVATE(p_destroy); + /** Function that performs a key export operation */ + psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export); + /** Function that performs a public key export operation */ + psa_drv_se_export_key_t MBEDTLS_PRIVATE(p_export_public); +} psa_drv_se_key_management_t; + +/**@}*/ + +/** \defgroup driver_derivation Secure Element Key Derivation and Agreement + * Key derivation is the process of generating new key material using an + * existing key and additional parameters, iterating through a basic + * cryptographic function, such as a hash. + * Key agreement is a part of cryptographic protocols that allows two parties + * to agree on the same key value, but starting from different original key + * material. + * The flows are similar, and the PSA Crypto Driver Model uses the same functions + * for both of the flows. + * + * There are two different final functions for the flows, + * `psa_drv_se_key_derivation_derive` and `psa_drv_se_key_derivation_export`. + * `psa_drv_se_key_derivation_derive` is used when the key material should be + * placed in a slot on the hardware and not exposed to the caller. + * `psa_drv_se_key_derivation_export` is used when the key material should be + * returned to the PSA Cryptographic API implementation. + * + * Different key derivation algorithms require a different number of inputs. + * Instead of having an API that takes as input variable length arrays, which + * can be problemmatic to manage on embedded platforms, the inputs are passed + * to the driver via a function, `psa_drv_se_key_derivation_collateral`, that + * is called multiple times with different `collateral_id`s. Thus, for a key + * derivation algorithm that required 3 parameter inputs, the flow would look + * something like: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(kdf_algorithm, source_key, dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_0, + * p_collateral_0, + * collateral_0_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_1, + * p_collateral_1, + * collateral_1_size); + * psa_drv_se_key_derivation_collateral(kdf_algorithm_collateral_id_2, + * p_collateral_2, + * collateral_2_size); + * psa_drv_se_key_derivation_derive(); + * ~~~~~~~~~~~~~ + * + * key agreement example: + * ~~~~~~~~~~~~~{.c} + * psa_drv_se_key_derivation_setup(alg, source_key. dest_key_size_bytes); + * psa_drv_se_key_derivation_collateral(DHE_PUBKEY, p_pubkey, pubkey_size); + * psa_drv_se_key_derivation_export(p_session_key, + * session_key_size, + * &session_key_length); + * ~~~~~~~~~~~~~ + */ +/**@{*/ + +/** \brief A function that Sets up a secure element key derivation operation by + * specifying the algorithm and the source key sot + * + * \param[in,out] drv_context The driver context structure. + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] kdf_alg The algorithm to be used for the key derivation + * \param[in] source_key The key to be used as the source material for + * the key derivation + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_setup_t)(psa_drv_se_context_t *drv_context, + void *op_context, + psa_algorithm_t kdf_alg, + psa_key_slot_number_t source_key); + +/** \brief A function that provides collateral (parameters) needed for a secure + * element key derivation or key agreement operation + * + * Since many key derivation algorithms require multiple parameters, it is + * expected that this function may be called multiple times for the same + * operation, each with a different algorithm-specific `collateral_id` + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] collateral_id An ID for the collateral being provided + * \param[in] p_collateral A buffer containing the collateral data + * \param[in] collateral_size The size in bytes of the collateral + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_collateral_t)(void *op_context, + uint32_t collateral_id, + const uint8_t *p_collateral, + size_t collateral_size); + +/** \brief A function that performs the final secure element key derivation + * step and place the generated key material in a slot + * + * \param[in,out] op_context A hardware-specific structure containing any + * context information for the implementation + * \param[in] dest_key The slot where the generated key material + * should be placed + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_derive_t)(void *op_context, + psa_key_slot_number_t dest_key); + +/** \brief A function that performs the final step of a secure element key + * agreement and place the generated key material in a buffer + * + * \param[out] p_output Buffer in which to place the generated key + * material + * \param[in] output_size The size in bytes of `p_output` + * \param[out] p_output_length Upon success, contains the number of bytes of + * key material placed in `p_output` + * + * \retval #PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_se_key_derivation_export_t)(void *op_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** + * \brief A struct containing all of the function pointers needed to for secure + * element key derivation and agreement + * + * PSA Crypto API implementations should populate instances of the table as + * appropriate upon startup. + * + * If one of the functions is not implemented, it should be set to NULL. + */ +typedef struct { + /** The driver-specific size of the key derivation context */ + size_t MBEDTLS_PRIVATE(context_size); + /** Function that performs a key derivation setup */ + psa_drv_se_key_derivation_setup_t MBEDTLS_PRIVATE(p_setup); + /** Function that sets key derivation collateral */ + psa_drv_se_key_derivation_collateral_t MBEDTLS_PRIVATE(p_collateral); + /** Function that performs a final key derivation step */ + psa_drv_se_key_derivation_derive_t MBEDTLS_PRIVATE(p_derive); + /** Function that perforsm a final key derivation or agreement and + * exports the key */ + psa_drv_se_key_derivation_export_t MBEDTLS_PRIVATE(p_export); +} psa_drv_se_key_derivation_t; + +/**@}*/ + +/** \defgroup se_registration Secure element driver registration + */ +/**@{*/ + +/** A structure containing pointers to all the entry points of a + * secure element driver. + * + * Future versions of this specification may add extra substructures at + * the end of this structure. + */ +typedef struct { + /** The version of the driver HAL that this driver implements. + * This is a protection against loading driver binaries built against + * a different version of this specification. + * Use #PSA_DRV_SE_HAL_VERSION. + */ + uint32_t MBEDTLS_PRIVATE(hal_version); + + /** The size of the driver's persistent data in bytes. + * + * This can be 0 if the driver does not need persistent data. + * + * See the documentation of psa_drv_se_context_t::persistent_data + * for more information about why and how a driver can use + * persistent data. + */ + size_t MBEDTLS_PRIVATE(persistent_data_size); + + /** The driver initialization function. + * + * This function is called once during the initialization of the + * PSA Cryptography subsystem, before any other function of the + * driver is called. If this function returns a failure status, + * the driver will be unusable, at least until the next system reset. + * + * If this field is \c NULL, it is equivalent to a function that does + * nothing and returns #PSA_SUCCESS. + */ + psa_drv_se_init_t MBEDTLS_PRIVATE(p_init); + + const psa_drv_se_key_management_t *MBEDTLS_PRIVATE(key_management); + const psa_drv_se_mac_t *MBEDTLS_PRIVATE(mac); + const psa_drv_se_cipher_t *MBEDTLS_PRIVATE(cipher); + const psa_drv_se_aead_t *MBEDTLS_PRIVATE(aead); + const psa_drv_se_asymmetric_t *MBEDTLS_PRIVATE(asymmetric); + const psa_drv_se_key_derivation_t *MBEDTLS_PRIVATE(derivation); +} psa_drv_se_t; + +/** The current version of the secure element driver HAL. + */ +/* 0.0.0 patchlevel 5 */ +#define PSA_DRV_SE_HAL_VERSION 0x00000005 + +/** Register an external cryptoprocessor (secure element) driver. + * + * This function is only intended to be used by driver code, not by + * application code. In implementations with separation between the + * PSA cryptography module and applications, this function should + * only be available to callers that run in the same memory space as + * the cryptography module, and should not be exposed to applications + * running in a different memory space. + * + * This function may be called before psa_crypto_init(). It is + * implementation-defined whether this function may be called + * after psa_crypto_init(). + * + * \note Implementations store metadata about keys including the lifetime + * value, which contains the driver's location indicator. Therefore, + * from one instantiation of the PSA Cryptography + * library to the next one, if there is a key in storage with a certain + * lifetime value, you must always register the same driver (or an + * updated version that communicates with the same secure element) + * with the same location value. + * + * \param location The location value through which this driver will + * be exposed to applications. + * This driver will be used for all keys such that + * `location == #PSA_KEY_LIFETIME_GET_LOCATION( lifetime )`. + * The value #PSA_KEY_LOCATION_LOCAL_STORAGE is reserved + * and may not be used for drivers. Implementations + * may reserve other values. + * \param[in] methods The method table of the driver. This structure must + * remain valid for as long as the cryptography + * module keeps running. It is typically a global + * constant. + * + * \return #PSA_SUCCESS + * The driver was successfully registered. Applications can now + * use \p location to access keys through the methods passed to + * this function. + * \return #PSA_ERROR_BAD_STATE + * This function was called after the initialization of the + * cryptography module, and this implementation does not support + * driver registration at this stage. + * \return #PSA_ERROR_ALREADY_EXISTS + * There is already a registered driver for this value of \p location. + * \return #PSA_ERROR_INVALID_ARGUMENT + * \p location is a reserved value. + * \return #PSA_ERROR_NOT_SUPPORTED + * `methods->hal_version` is not supported by this implementation. + * \return #PSA_ERROR_INSUFFICIENT_MEMORY + * \return #PSA_ERROR_NOT_PERMITTED + * \return #PSA_ERROR_STORAGE_FAILURE + * \return #PSA_ERROR_DATA_CORRUPT + */ +psa_status_t psa_register_se_driver( + psa_key_location_t location, + const psa_drv_se_t *methods); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_SE_DRIVER_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_sizes.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_sizes.h new file mode 100644 index 00000000..9bbcb344 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_sizes.h @@ -0,0 +1,1164 @@ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.h. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#include "mbedtls/build_info.h" + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + */ +#define PSA_HASH_LENGTH(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** The input block size of a hash algorithm, in bytes. + * + * Hash algorithms process their input data in blocks. Hash operations will + * retain any partial blocks until they have enough input to fill the block or + * until the operation is finished. + * This affects the output from psa_hash_suspend(). + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * PSA_ALG_IS_HASH(\p alg) is true). + * + * \return The block size in bytes for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation can return either 0 or the correct size for a + * hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_BLOCK_LENGTH(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro expands to a compile-time constant integer. This value + * is the maximum size of a hash in bytes. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA_384) +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 +#else +#define PSA_HASH_MAX_SIZE 32 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64 +#endif + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro expands to a compile-time constant integer. This value + * is the maximum size of a MAC in bytes. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The length of a tag for an AEAD algorithm, in bytes. + * + * This macro can be used to allocate a buffer of sufficient size to store the + * tag output from psa_aead_finish(). + * + * See also #PSA_AEAD_TAG_MAX_SIZE. + * + * \param key_type The type of the AEAD key. + * \param key_bits The size of the AEAD key in bits. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag length for the specified algorithm and key. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ + ((void) (key_bits), 0)) + +/** The maximum tag size for all supported AEAD algorithms, in bytes. + * + * See also #PSA_AEAD_TAG_LENGTH(\p key_type, \p key_bits, \p alg). + */ +#define PSA_AEAD_TAG_MAX_SIZE 16 + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 +#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512 +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448 +#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384 +#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256 +#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255 +#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224 +#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192 +#else +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0 +#endif + +/** This macro returns the maximum supported length of the PSK for the + * TLS-1.2 PSK-to-MS key derivation + * (#PSA_ALG_TLS12_PSK_TO_MS(\c hash_alg)). + * + * The maximum supported length does not depend on the chosen hash algorithm. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE. + */ +#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128 + +/** The maximum size of a block cipher. */ +#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_LENGTH(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + ((void)(key_type), (void)(key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * See also #PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(\p plaintext_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_encrypt(), for any of the + * supported key types and AEAD algorithms. + * + * If the size of the ciphertext buffer is at least this large, it is guaranteed + * that psa_aead_encrypt() will not fail due to an insufficient buffer size. + * + * \note This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * See also #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, + * \p plaintext_length). + * + * \param plaintext_length Size of the plaintext in bytes. + * + * \return A sufficient output buffer size for any of the + * supported key types and AEAD algorithms. + * + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(plaintext_length) \ + ((plaintext_length) + PSA_AEAD_TAG_MAX_SIZE) + + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * See also #PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(\p ciphertext_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext_length) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ? \ + (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_decrypt(), for any of the + * supported key types and AEAD algorithms. + * + * If the size of the plaintext buffer is at least this large, it is guaranteed + * that psa_aead_decrypt() will not fail due to an insufficient buffer size. + * + * \note This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * See also #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, + * \p ciphertext_length). + * + * \param ciphertext_length Size of the ciphertext in bytes. + * + * \return A sufficient output buffer size for any of the + * supported key types and AEAD algorithms. + * + */ +#define PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(ciphertext_length) \ + (ciphertext_length) + +/** The default nonce size for an AEAD algorithm, in bytes. + * + * This macro can be used to allocate a buffer of sufficient size to + * store the nonce output from #psa_aead_generate_nonce(). + * + * See also #PSA_AEAD_NONCE_MAX_SIZE. + * + * \note This is not the maximum size of nonce supported as input to + * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), + * just the default size that is generated by #psa_aead_generate_nonce(). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with + * algorithm \p alg. + * + * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The default nonce size for the specified key type and algorithm. + * If the key type or AEAD algorithm is not recognized, + * or the parameters are incompatible, return 0. + */ +#define PSA_AEAD_NONCE_LENGTH(key_type, alg) \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13 : \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12 : \ + 0 : \ + (key_type) == PSA_KEY_TYPE_CHACHA20 && \ + MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12 : \ + 0) + +/** The maximum default nonce size among all supported pairs of key types and + * AEAD algorithms, in bytes. + * + * This is equal to or greater than any value that #PSA_AEAD_NONCE_LENGTH() + * may return. + * + * \note This is not the maximum size of nonce supported as input to + * #psa_aead_set_nonce(), #psa_aead_encrypt() or #psa_aead_decrypt(), + * just the largest size that may be generated by + * #psa_aead_generate_nonce(). + */ +#define PSA_AEAD_NONCE_MAX_SIZE 13 + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * See also #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ? \ + PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \ + (input_length) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(), for any of the + * supported key types and AEAD algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_aead_update() will not fail due to an insufficient buffer size. + * + * See also #PSA_AEAD_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + */ +#define PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, (input_length))) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * See also #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE. + * + * \param key_type A symmetric key type that is + compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + 0) + +/** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the + * supported key types and AEAD algorithms. + * + * See also #PSA_AEAD_FINISH_OUTPUT_SIZE(\p key_type, \p alg). + */ +#define PSA_AEAD_FINISH_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * See also #PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE. + * + * \param key_type A symmetric key type that is + * compatible with algorithm \p alg. + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the key type or AEAD algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg) \ + (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 && \ + PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(), for any of the + * supported key types and AEAD algorithms. + * + * See also #PSA_AEAD_VERIFY_OUTPUT_SIZE(\p key_type, \p alg). + */ +#define PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) + +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void)alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro expands to a compile-time constant integer. This value + * is the maximum size of a signature in bytes. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The asymmetric encryption algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** A sufficient output buffer size for psa_asymmetric_encrypt(), for any + * supported asymmetric encryption. + * + * See also #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). + */ +/* This macro assumes that RSA is the only supported asymmetric encryption. */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a plaintext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the plaintext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The asymmetric encryption algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/** A sufficient output buffer size for psa_asymmetric_decrypt(), for any + * supported asymmetric decryption. + * + * This macro assumes that RSA is the only supported asymmetric encryption. + * + * See also #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\p key_type, \p key_bits, \p alg). + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes thatthe public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or + * psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_export_key() or psa_export_public_key() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported, + * return either a sensible size or 0. + * If the parameters are not valid, the return value is unspecified. + */ +#define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +/** Sufficient output buffer size for psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a public key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A public key or key pair key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_export_public_key() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not + * supported, return either a sensible size or 0. + * If the parameters are not valid, + * the return value is unspecified. + * + * If the parameters are valid and supported, + * return the same result as + * #PSA_EXPORT_KEY_OUTPUT_SIZE( + * \p #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(\p key_type), + * \p key_bits). + */ +#define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +/** Sufficient buffer size for exporting any asymmetric key pair. + * + * This macro expands to a compile-time constant integer. This value is + * a sufficient buffer size when calling psa_export_key() to export any + * asymmetric key pair, regardless of the exact key type and key size. + * + * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). + */ +#define PSA_EXPORT_KEY_PAIR_MAX_SIZE \ + (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ? \ + PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) + +/** Sufficient buffer size for exporting any asymmetric public key. + * + * This macro expands to a compile-time constant integer. This value is + * a sufficient buffer size when calling psa_export_key() or + * psa_export_public_key() to export any asymmetric public key, + * regardless of the exact key type and key size. + * + * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits). + */ +#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE \ + (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ? \ + PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) + +/** Sufficient output buffer size for psa_raw_key_agreement(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE. + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_raw_key_agreement() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that + * is not supported, return either a sensible size or 0. + * If the parameters are not valid, + * the return value is unspecified. + */ +/* FFDH is not yet supported in PSA. */ +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) : \ + 0) + +/** Maximum size of the output from psa_raw_key_agreement(). + * + * This macro expands to a compile-time constant integer. This value is the + * maximum size of the output any raw key agreement algorithm, in bytes. + * + * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits). + */ +#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)) + +/** The default IV size for a cipher algorithm, in bytes. + * + * The IV that is generated as part of a call to #psa_cipher_encrypt() is always + * the default IV length for the algorithm. + * + * This macro can be used to allocate a buffer of sufficient size to + * store the IV output from #psa_cipher_generate_iv() when using + * a multi-part cipher operation. + * + * See also #PSA_CIPHER_IV_MAX_SIZE. + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with algorithm \p alg. + * + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \return The default IV size for the specified key type and algorithm. + * If the algorithm does not use an IV, return 0. + * If the key type or cipher algorithm is not recognized, + * or the parameters are incompatible, return 0. + */ +#define PSA_CIPHER_IV_LENGTH(key_type, alg) \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1 && \ + ((alg) == PSA_ALG_CTR || \ + (alg) == PSA_ALG_CFB || \ + (alg) == PSA_ALG_OFB || \ + (alg) == PSA_ALG_XTS || \ + (alg) == PSA_ALG_CBC_NO_PADDING || \ + (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + (key_type) == PSA_KEY_TYPE_CHACHA20 && \ + (alg) == PSA_ALG_STREAM_CIPHER ? 12 : \ + (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13 : \ + 0) + +/** The maximum IV size for all supported cipher algorithms, in bytes. + * + * See also #PSA_CIPHER_IV_LENGTH(). + */ +#define PSA_CIPHER_IV_MAX_SIZE 16 + +/** The maximum size of the output of psa_cipher_encrypt(), in bytes. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. + * Depending on the algorithm, the actual size of the output might be smaller. + * + * See also #PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(\p input_length). + * + * \warning This macro may evaluate its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ + (alg == PSA_ALG_CBC_PKCS7 ? \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ + (input_length) + 1) + \ + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0) : \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) : \ + 0)) + +/** A sufficient output buffer size for psa_cipher_encrypt(), for any of the + * supported key types and cipher algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_encrypt() will not fail due to an insufficient buffer size. + * + * See also #PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + * + */ +#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, \ + (input_length) + 1) + \ + PSA_CIPHER_IV_MAX_SIZE) + +/** The maximum size of the output of psa_cipher_decrypt(), in bytes. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. + * Depending on the algorithm, the actual size of the output might be smaller. + * + * See also #PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(\p input_length). + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, + * return 0. + */ +#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_ALG_IS_CIPHER(alg) && \ + ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + (input_length) : \ + 0) + +/** A sufficient output buffer size for psa_cipher_decrypt(), for any of the + * supported key types and cipher algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_decrypt() will not fail due to an insufficient buffer size. + * + * See also #PSA_CIPHER_DECRYPT_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + */ +#define PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_length) \ + (input_length) + +/** A sufficient output buffer size for psa_cipher_update(). + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_update() will not fail due to an insufficient buffer size. + * The actual size of the output might be smaller in any given call. + * + * See also #PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(\p input_length). + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, return 0. + */ +#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length) \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ? \ + (((alg) == PSA_ALG_CBC_PKCS7 || \ + (alg) == PSA_ALG_CBC_NO_PADDING || \ + (alg) == PSA_ALG_ECB_NO_PADDING) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \ + input_length) : \ + (input_length)) : 0) : \ + 0) + +/** A sufficient output buffer size for psa_cipher_update(), for any of the + * supported key types and cipher algorithms. + * + * If the size of the output buffer is at least this large, it is guaranteed + * that psa_cipher_update() will not fail due to an insufficient buffer size. + * + * See also #PSA_CIPHER_UPDATE_OUTPUT_SIZE(\p key_type, \p alg, \p input_length). + * + * \param input_length Size of the input in bytes. + */ +#define PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input_length) \ + (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE, input_length)) + +/** A sufficient ciphertext buffer size for psa_cipher_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_cipher_finish() will not fail due to an insufficient + * ciphertext buffer size. The actual size of the output might be smaller in + * any given call. + * + * See also #PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE(). + * + * \param key_type A symmetric key type that is compatible with algorithm + * alg. + * \param alg A cipher algorithm (PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \return A sufficient output size for the specified key type and + * algorithm. If the key type or cipher algorithm is not + * recognized, or the parameters are incompatible, return 0. + */ +#define PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg) \ + (PSA_ALG_IS_CIPHER(alg) ? \ + (alg == PSA_ALG_CBC_PKCS7 ? \ + PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \ + 0) : \ + 0) + +/** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the + * supported key types and cipher algorithms. + * + * See also #PSA_CIPHER_FINISH_OUTPUT_SIZE(\p key_type, \p alg). + */ +#define PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE \ + (PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE) + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_struct.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_struct.h new file mode 100644 index 00000000..2c61e53c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_struct.h @@ -0,0 +1,493 @@ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: Mbed TLS structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + * + *

Design notes about multipart operation structures

+ * + * For multipart operations without driver delegation support, each multipart + * operation structure contains a `psa_algorithm_t alg` field which indicates + * which specific algorithm the structure is for. When the structure is not in + * use, `alg` is 0. Most of the structure consists of a union which is + * discriminated by `alg`. + * + * For multipart operations with driver delegation support, each multipart + * operation structure contains an `unsigned int id` field indicating which + * driver got assigned to do the operation. When the structure is not in use, + * 'id' is 0. The structure contains also a driver context which is the union + * of the contexts of all drivers able to handle the type of multipart + * operation. + * + * Note that when `alg` or `id` is 0, the content of other fields is undefined. + * In particular, it is not guaranteed that a freshly-initialized structure + * is all-zero: we initialize structures to something like `{0, 0}`, which + * is only guaranteed to initializes the first member of the union; + * GCC and Clang initialize the whole structure to 0 (at the time of writing), + * but MSVC and CompCert don't. + * + * In Mbed Crypto, multipart operation structures live independently from + * the key. This allows Mbed Crypto to free the key objects when destroying + * a key slot. If a multipart operation needs to remember the key after + * the setup function returns, the operation structure needs to contain a + * copy of the key. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H +#include "mbedtls/private_access.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Include the Mbed TLS configuration file, the way Mbed TLS does it + * in each of its header files. */ +#include "mbedtls/build_info.h" + +#include "mbedtls/cmac.h" +#include "mbedtls/gcm.h" +#include "mbedtls/ccm.h" +#include "mbedtls/chachapoly.h" + +/* Include the context definition for the compiled-in drivers for the primitive + * algorithms. */ +#include "psa/crypto_driver_contexts_primitives.h" + +struct psa_hash_operation_s +{ + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_driver_wrappers.h. + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. the driver context is not active, in use). */ + unsigned int MBEDTLS_PRIVATE(id); + psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_HASH_OPERATION_INIT { 0, { 0 } } +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + +struct psa_cipher_operation_s +{ + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + unsigned int MBEDTLS_PRIVATE(iv_required) : 1; + unsigned int MBEDTLS_PRIVATE(iv_set) : 1; + + uint8_t MBEDTLS_PRIVATE(default_iv_length); + + psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } } +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + +/* Include the context definition for the compiled-in drivers for the composite + * algorithms. */ +#include "psa/crypto_driver_contexts_composites.h" + +struct psa_mac_operation_s +{ + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + uint8_t MBEDTLS_PRIVATE(mac_size); + unsigned int MBEDTLS_PRIVATE(is_sign) : 1; + psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } } +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + +struct psa_aead_operation_s +{ + + /** Unique ID indicating which driver got assigned to do the + * operation. Since driver contexts are driver-specific, swapping + * drivers halfway through the operation is not supported. + * ID values are auto-generated in psa_crypto_driver_wrappers.h + * ID value zero means the context is not valid or not assigned to + * any driver (i.e. none of the driver contexts are active). */ + unsigned int MBEDTLS_PRIVATE(id); + + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_key_type_t MBEDTLS_PRIVATE(key_type); + + size_t MBEDTLS_PRIVATE(ad_remaining); + size_t MBEDTLS_PRIVATE(body_remaining); + + unsigned int MBEDTLS_PRIVATE(nonce_set) : 1; + unsigned int MBEDTLS_PRIVATE(lengths_set) : 1; + unsigned int MBEDTLS_PRIVATE(ad_started) : 1; + unsigned int MBEDTLS_PRIVATE(body_started) : 1; + unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1; + + psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx); +}; + +#define PSA_AEAD_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) +typedef struct +{ + uint8_t *MBEDTLS_PRIVATE(info); + size_t MBEDTLS_PRIVATE(info_length); +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + uint8_t MBEDTLS_PRIVATE(offset_in_block); + uint8_t MBEDTLS_PRIVATE(block_number); + unsigned int MBEDTLS_PRIVATE(state) : 2; + unsigned int MBEDTLS_PRIVATE(info_set) : 1; + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; + uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE]; + struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac); +} psa_hkdf_key_derivation_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +typedef enum +{ + PSA_TLS12_PRF_STATE_INIT, /* no input provided */ + PSA_TLS12_PRF_STATE_SEED_SET, /* seed has been set */ + PSA_TLS12_PRF_STATE_KEY_SET, /* key has been set */ + PSA_TLS12_PRF_STATE_LABEL_SET, /* label has been set */ + PSA_TLS12_PRF_STATE_OUTPUT /* output has been started */ +} psa_tls12_prf_key_derivation_state_t; + +typedef struct psa_tls12_prf_key_derivation_s +{ +#if PSA_HASH_MAX_SIZE > 0xff +#error "PSA_HASH_MAX_SIZE does not fit in uint8_t" +#endif + + /* Indicates how many bytes in the current HMAC block have + * not yet been read by the user. */ + uint8_t MBEDTLS_PRIVATE(left_in_block); + + /* The 1-based number of the block. */ + uint8_t MBEDTLS_PRIVATE(block_number); + + psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state); + + uint8_t *MBEDTLS_PRIVATE(secret); + size_t MBEDTLS_PRIVATE(secret_length); + uint8_t *MBEDTLS_PRIVATE(seed); + size_t MBEDTLS_PRIVATE(seed_length); + uint8_t *MBEDTLS_PRIVATE(label); + size_t MBEDTLS_PRIVATE(label_length); + + uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE]; + + /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */ + uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE]; +} psa_tls12_prf_key_derivation_t; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +struct psa_key_derivation_s +{ + psa_algorithm_t MBEDTLS_PRIVATE(alg); + unsigned int MBEDTLS_PRIVATE(can_output_key) : 1; + size_t MBEDTLS_PRIVATE(capacity); + union + { + /* Make the union non-empty even with no supported algorithms. */ + uint8_t MBEDTLS_PRIVATE(dummy); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf); +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf); +#endif + } MBEDTLS_PRIVATE(ctx); +}; + +/* This only zeroes out the first byte in the union, the rest is unspecified. */ +#define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } } +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( + void ) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return( v ); +} + +struct psa_key_policy_s +{ + psa_key_usage_t MBEDTLS_PRIVATE(usage); + psa_algorithm_t MBEDTLS_PRIVATE(alg); + psa_algorithm_t MBEDTLS_PRIVATE(alg2); +}; +typedef struct psa_key_policy_s psa_key_policy_t; + +#define PSA_KEY_POLICY_INIT { 0, 0, 0 } +static inline struct psa_key_policy_s psa_key_policy_init( void ) +{ + const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; + return( v ); +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( ( psa_key_bits_t ) -1 ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ( (psa_key_attributes_flag_t) 0x0001 ) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0 ) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0 ) + +typedef struct +{ + psa_key_type_t MBEDTLS_PRIVATE(type); + psa_key_bits_t MBEDTLS_PRIVATE(bits); + psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime); + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id); + psa_key_policy_t MBEDTLS_PRIVATE(policy); + psa_key_attributes_flag_t MBEDTLS_PRIVATE(flags); +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT { PSA_KEY_TYPE_NONE, 0, \ + PSA_KEY_LIFETIME_VOLATILE, \ + MBEDTLS_SVC_KEY_ID_INIT, \ + PSA_KEY_POLICY_INIT, 0 } + +struct psa_key_attributes_s +{ + psa_core_key_attributes_t MBEDTLS_PRIVATE(core); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *MBEDTLS_PRIVATE(domain_parameters); + size_t MBEDTLS_PRIVATE(domain_parameters_size); +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0 } +#else +#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0 } +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id( psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t key ) +{ + psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime); + + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = key; + + if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) ) + { + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) = + PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION( + PSA_KEY_LIFETIME_PERSISTENT, + PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) ); + } +} + +static inline mbedtls_svc_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes ) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) ); +} + +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER +static inline void mbedtls_set_key_owner_id( psa_key_attributes_t *attributes, + mbedtls_key_owner_id_t owner ) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner; +} +#endif + +static inline void psa_set_key_lifetime( psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime ) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) = lifetime; + if( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) ) + { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0; +#else + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes ) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) ); +} + +static inline void psa_extend_key_usage_flags( psa_key_usage_t *usage_flags ) +{ + if( *usage_flags & PSA_KEY_USAGE_SIGN_HASH ) + *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE; + + if( *usage_flags & PSA_KEY_USAGE_VERIFY_HASH ) + *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE; +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + psa_extend_key_usage_flags( &usage_flags ); + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes ) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) ); +} + +static inline void psa_set_key_algorithm( psa_key_attributes_t *attributes, + psa_algorithm_t alg ) +{ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes ) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) ); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length ); + +static inline void psa_set_key_type( psa_key_attributes_t *attributes, + psa_key_type_t type ) +{ + if( attributes->MBEDTLS_PRIVATE(domain_parameters) == NULL ) + { + /* Common case: quick path */ + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type; + } + else + { + /* Call the bigger function to free the old domain paramteres. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes ) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) ); +} + +static inline void psa_set_key_bits( psa_key_attributes_t *attributes, + size_t bits ) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE; + else + attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes ) +{ + return( attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_types.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_types.h new file mode 100644 index 00000000..2cf965d8 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_types.h @@ -0,0 +1,384 @@ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H +#include "mbedtls/private_access.h" + +#include "crypto_platform.h" + +/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT + * is defined as well to include all PSA code. + */ +#if defined(MBEDTLS_PSA_CRYPTO_C) +#define MBEDTLS_PSA_CRYPTO_CLIENT +#endif /* MBEDTLS_PSA_CRYPTO_C */ + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. */ +/* If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. + */ +#ifndef PSA_SUCCESS +typedef int32_t psa_status_t; +#endif + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + */ +typedef uint16_t psa_key_type_t; + +/** The type of PSA elliptic curve family identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + */ +typedef uint8_t psa_ecc_family_t; + +/** The type of PSA Diffie-Hellman group family identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * Values defined by this standard will never be in the range 0x80-0xff. + * Vendors who define additional families must use an encoding in this range. + */ +typedef uint8_t psa_dh_family_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Lifetime values have the following structure: + * - Bits 0-7 (#PSA_KEY_LIFETIME_GET_PERSISTENCE(\c lifetime)): + * persistence level. This value indicates what device management + * actions can cause it to be destroyed. In particular, it indicates + * whether the key is _volatile_ or _persistent_. + * See ::psa_key_persistence_t for more information. + * - Bits 8-31 (#PSA_KEY_LIFETIME_GET_LOCATION(\c lifetime)): + * location indicator. This value indicates which part of the system + * has access to the key material and can perform operations using the key. + * See ::psa_key_location_t for more information. + * + * Volatile keys are automatically destroyed when the application instance + * terminates or on a power reset of the device. Persistent keys are + * preserved until the application explicitly destroys them or until an + * integration-specific device management event occurs (for example, + * a factory reset). + * + * Persistent keys have a key identifier of type #mbedtls_svc_key_id_t. + * This identifier remains valid throughout the lifetime of the key, + * even if the application instance that created the key terminates. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + * + * The default lifetime of a key is #PSA_KEY_LIFETIME_VOLATILE. The lifetime + * #PSA_KEY_LIFETIME_PERSISTENT is supported if persistent storage is + * available. Other lifetime values may be supported depending on the + * library configuration. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of key persistence levels. + * + * What distinguishes different persistence levels is what device management + * events may cause keys to be destroyed. _Volatile_ keys are destroyed + * by a power reset. Persistent keys may be destroyed by events such as + * a transfer of ownership or a factory reset. What management events + * actually affect persistent keys at different levels is outside the + * scope of the PSA Cryptography specification. + * + * The PSA Cryptography specification defines the following values of + * persistence levels: + * - \c 0 = #PSA_KEY_PERSISTENCE_VOLATILE: volatile key. + * A volatile key is automatically destroyed by the implementation when + * the application instance terminates. In particular, a volatile key + * is automatically destroyed on a power reset of the device. + * - \c 1 = #PSA_KEY_PERSISTENCE_DEFAULT: + * persistent key with a default lifetime. + * - \c 2-254: currently not supported by Mbed TLS. + * - \c 255 = #PSA_KEY_PERSISTENCE_READ_ONLY: + * read-only or write-once key. + * A key with this persistence level cannot be destroyed. + * Mbed TLS does not currently offer a way to create such keys, but + * integrations of Mbed TLS can use it for built-in keys that the + * application cannot modify (for example, a hardware unique key (HUK)). + * + * \note Key persistence levels are 8-bit values. Key management + * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which + * encode the persistence as the lower 8 bits of a 32-bit value. + */ +typedef uint8_t psa_key_persistence_t; + +/** Encoding of key location indicators. + * + * If an integration of Mbed TLS can make calls to external + * cryptoprocessors such as secure elements, the location of a key + * indicates which secure element performs the operations on the key. + * Depending on the design of the secure element, the key + * material may be stored either in the secure element, or + * in wrapped (encrypted) form alongside the key metadata in the + * primary local storage. + * + * The PSA Cryptography API specification defines the following values of + * location indicators: + * - \c 0: primary local storage. + * This location is always available. + * The primary local storage is typically the same storage area that + * contains the key metadata. + * - \c 1: primary secure element. + * Integrations of Mbed TLS should support this value if there is a secure + * element attached to the operating environment. + * As a guideline, secure elements may provide higher resistance against + * side channel and physical attacks than the primary local storage, but may + * have restrictions on supported key types, sizes, policies and operations + * and may have different performance characteristics. + * - \c 2-0x7fffff: other locations defined by a PSA specification. + * The PSA Cryptography API does not currently assign any meaning to these + * locations, but future versions of that specification or other PSA + * specifications may do so. + * - \c 0x800000-0xffffff: vendor-defined locations. + * No PSA specification will assign a meaning to locations in this range. + * + * \note Key location indicators are 24-bit values. Key management + * interfaces operate on lifetimes (type ::psa_key_lifetime_t) which + * encode the location as the upper 24 bits of a 32-bit value. + */ +typedef uint32_t psa_key_location_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - The implementation may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + */ +typedef uint32_t psa_key_id_t; + +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) +typedef psa_key_id_t mbedtls_svc_key_id_t; + +#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ +/* Implementation-specific: The Mbed Cryptography library can be built as + * part of a multi-client service that exposes the PSA Cryptograpy API in each + * client and encodes the client identity in the key identifier argument of + * functions such as psa_open_key(). + */ +typedef struct +{ + psa_key_id_t MBEDTLS_PRIVATE(key_id); + mbedtls_key_owner_id_t MBEDTLS_PRIVATE(owner); +} mbedtls_svc_key_id_t; + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Additional implementation-defined attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure works like a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, a future version of the library may report values that are + * equivalent to the original one, but have a different encoding. Invalid + * values may be mapped to different, also invalid values. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a key identifier to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + + +#ifndef __DOXYGEN_ONLY__ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* Mbed Crypto defines this type in crypto_types.h because it is also + * visible to applications through an implementation-specific extension. + * For the PSA Cryptography specification, this type is only visible + * via crypto_se_driver.h. */ +typedef uint64_t psa_key_slot_number_t; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ +#endif /* !__DOXYGEN_ONLY__ */ + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_values.h b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_values.h new file mode 100644 index 00000000..5a903f86 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/include/psa/crypto_values.h @@ -0,0 +1,2514 @@ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * This header file only defines preprocessor macros. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H +#include "mbedtls/private_access.h" + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/** The action was completed successfully. */ +#define PSA_SUCCESS ((psa_status_t)0) + +/** An error occurred that does not correspond to any defined + * failure cause. + * + * Implementations may use this error code if none of the other standard + * error codes are applicable. */ +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * parameter such as a key type, algorithm, etc. is not recognized. + * If a combination of parameters is recognized and identified as + * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * not valid or not supported, it is unspecified whether the function + * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or + * #PSA_ERROR_INVALID_ARGUMENT. */ +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * buffer would succeed. However implementations may return this + * error if a function has invalid or unsupported parameters in addition + * to the parameters that determine the necessary output buffer size. */ +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) + +/** Asking for an item that already exists + * + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) + +/** Asking for an item that doesn't exist + * + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) + +/** The requested action cannot be performed in the current state. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations shall not return this error code to indicate that a + * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations shall not return this error code to indicate that a + * key identifier is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) + +/** There is not enough runtime memory. + * + * If the action is carried out across multiple security realms, this + * error can refer to available memory in any of the security realms. */ +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * many functions that do not otherwise access storage may return this + * error code if the implementation requires a mandatory log entry for + * the requested action and the log storage space is full. */ +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * cryptoprocessor but there was a breakdown of communication before + * the cryptoprocessor could report the status to the application. + */ +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * permanent storage corruption. However application writers should + * keep in mind that transient errors while reading the storage may be + * reported using this error code. */ +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) + +/** A hardware failure was detected. + * + * A hardware failure may be transient or permanent depending on the + * cause. */ +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * This error indicates an attack against the application. Implementations + * shall not return this error code as a consequence of the behavior of + * the application itself. */ +#define PSA_ERROR_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * secure pseudorandom generator (PRNG). However implementations may return + * this error at any time if a policy requires the PRNG to be reseeded + * during normal operation. */ +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * If the value to verify has an invalid size, implementations may return + * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * as close as possible to indistinguishable to an external observer. + * In particular, the timing of a decryption operation should not + * depend on the validity of the padding. */ +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) + +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) + +/** The key identifier is not valid. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/** Stored data has been corrupted. + * + * This error indicates that some persistent storage has suffered corruption. + * It does not indicate the following situations, which have specific error + * codes: + * + * - A corruption of volatile memory - use #PSA_ERROR_CORRUPTION_DETECTED. + * - A communication error between the cryptoprocessor and its external + * storage - use #PSA_ERROR_COMMUNICATION_FAILURE. + * - When the storage is in a valid state but is full - use + * #PSA_ERROR_INSUFFICIENT_STORAGE. + * - When the storage fails for other reasons - use + * #PSA_ERROR_STORAGE_FAILURE. + * - When the stored data is not valid - use #PSA_ERROR_DATA_INVALID. + * + * \note A storage corruption does not indicate that any data that was + * previously read is invalid. However this previously read data might no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure the + * global integrity of the keystore. + */ +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +/** Data read from storage is not valid for the implementation. + * + * This error indicates that some data read from storage does not have a valid + * format. It does not indicate the following situations, which have specific + * error codes: + * + * - When the storage or stored data is corrupted - use #PSA_ERROR_DATA_CORRUPT + * - When the storage fails for other reasons - use #PSA_ERROR_STORAGE_FAILURE + * - An invalid argument to the API - use #PSA_ERROR_INVALID_ARGUMENT + * + * This error is typically a result of either storage corruption on a + * cleartext storage backend, or an attempt to read data that was + * written by an incompatible version of the library. + */ +#define PSA_ERROR_DATA_INVALID ((psa_status_t)-153) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x0000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x8000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x7000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x1000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x2000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x4000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x7000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x3000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_RAW || \ + ((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x1001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_LENGTH(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x1100) + +/** A secret for key derivation. + * + * This key type is for high-entropy secrets only. For low-entropy secrets, + * #PSA_KEY_TYPE_PASSWORD should be used instead. + * + * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_SECRET or + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input of key derivation algorithms. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x1200) + +/** A low-entropy secret for password hashing or key derivation. + * + * This key type is suitable for passwords and passphrases which are typically + * intended to be memorizable by humans, and have a low entropy relative to + * their size. It can be used for randomly generated or derived keys with + * maximum or near-maximum entropy, but #PSA_KEY_TYPE_DERIVE is more suitable + * for such keys. It is not suitable for passwords with extremely low entropy, + * such as numerical PINs. + * + * These keys can be used as the #PSA_KEY_DERIVATION_INPUT_PASSWORD input of + * key derivation algorithms. Algorithms that accept such an input were + * designed to accept low-entropy secret and are known as password hashing or + * key stretching algorithms. + * + * These keys cannot be used as the #PSA_KEY_DERIVATION_INPUT_SECRET input of + * key derivation algorithms, as the algorithms that take such an input expect + * it to be high-entropy. + * + * The key policy determines which key derivation algorithm the key can be + * used for, among the permissible subset defined above. + */ +#define PSA_KEY_TYPE_PASSWORD ((psa_key_type_t)0x1203) + +/** A secret value that can be used to verify a password hash. + * + * The key policy determines which key derivation algorithm the key + * can be used for, among the same permissible subset as for + * #PSA_KEY_TYPE_PASSWORD. + */ +#define PSA_KEY_TYPE_PASSWORD_HASH ((psa_key_type_t)0x1205) + +/** A secret value that can be used in when computing a password hash. + * + * The key policy determines which key derivation algorithm the key + * can be used for, among the subset of algorithms that can use pepper. + */ +#define PSA_KEY_TYPE_PEPPER ((psa_key_type_t)0x1206) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x2400) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * ARIA block cipher. */ +#define PSA_KEY_TYPE_ARIA ((psa_key_type_t)0x2406) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 64 bits (single DES), 128 bits (2-key 3DES) or + * 192 bits (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x2301) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x2403) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x2004) + +/** RSA public key. + * + * The size of an RSA key is the bit size of the modulus. + */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x4001) +/** RSA key pair (private and public key). + * + * The size of an RSA key is the bit size of the modulus. + */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x7001) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x4100) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x7100) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x00ff) +/** Elliptic curve key pair. + * + * The size of an elliptic curve key is the bit size associated with the curve, + * i.e. the bit size of *q* for a curve over a field *Fq*. + * See the documentation of `PSA_ECC_FAMILY_xxx` curve families for details. + * + * \param curve A value of type ::psa_ecc_family_t that + * identifies the ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * The size of an elliptic curve public key is the same as the corresponding + * private key (see #PSA_KEY_TYPE_ECC_KEY_PAIR and the documentation of + * `PSA_ECC_FAMILY_xxx` curve families). + * + * \param curve A value of type ::psa_ecc_family_t that + * identifies the ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_ECC_GET_FAMILY(type) \ + ((psa_ecc_family_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/** SEC Koblitz curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224k1, secp256k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECP_K1 ((psa_ecc_family_t) 0x17) + +/** SEC random curves over prime fields. + * + * This family comprises the following curves: + * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECP_R1 ((psa_ecc_family_t) 0x12) +/* SECP160R2 (SEC2 v1, obsolete) */ +#define PSA_ECC_FAMILY_SECP_R2 ((psa_ecc_family_t) 0x1b) + +/** SEC Koblitz curves over binary fields. + * + * This family comprises the following curves: + * sect163k1, sect233k1, sect239k1, sect283k1, sect409k1, sect571k1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_K1 ((psa_ecc_family_t) 0x27) + +/** SEC random curves over binary fields. + * + * This family comprises the following curves: + * sect163r1, sect233r1, sect283r1, sect409r1, sect571r1. + * They are defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_R1 ((psa_ecc_family_t) 0x22) + +/** SEC additional random curves over binary fields. + * + * This family comprises the following curve: + * sect163r2. + * It is defined in _Standards for Efficient Cryptography_, + * _SEC 2: Recommended Elliptic Curve Domain Parameters_. + * https://www.secg.org/sec2-v2.pdf + */ +#define PSA_ECC_FAMILY_SECT_R2 ((psa_ecc_family_t) 0x2b) + +/** Brainpool P random curves. + * + * This family comprises the following curves: + * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, + * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. + * It is defined in RFC 5639. + */ +#define PSA_ECC_FAMILY_BRAINPOOL_P_R1 ((psa_ecc_family_t) 0x30) + +/** Curve25519 and Curve448. + * + * This family comprises the following Montgomery curves: + * - 255-bit: Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + * - 448-bit: Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_FAMILY_MONTGOMERY ((psa_ecc_family_t) 0x41) + +/** The twisted Edwards curves Ed25519 and Ed448. + * + * These curves are suitable for EdDSA (#PSA_ALG_PURE_EDDSA for both curves, + * #PSA_ALG_ED25519PH for the 255-bit curve, + * #PSA_ALG_ED448PH for the 448-bit curve). + * + * This family comprises the following twisted Edwards curves: + * - 255-bit: Edwards25519, the twisted Edwards curve birationally equivalent + * to Curve25519. + * Bernstein et al., _Twisted Edwards curves_, Africacrypt 2008. + * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent + * to Curve448. + * Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + */ +#define PSA_ECC_FAMILY_TWISTED_EDWARDS ((psa_ecc_family_t) 0x42) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x4200) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x7200) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x00ff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_family_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_family_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_DH_GET_FAMILY(type) \ + ((psa_dh_family_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/** Diffie-Hellman groups defined in RFC 7919 Appendix A. + * + * This family includes groups with the following key sizes (in bits): + * 2048, 3072, 4096, 6144, 8192. A given implementation may support + * all of these sizes or only a subset. + */ +#define PSA_DH_FAMILY_RFC7919 ((psa_dh_family_t) 0x03) + +#define PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) \ + (((type) >> 8) & 7) +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_LENGTH(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \ + 1u << PSA_GET_KEY_TYPE_BLOCK_SIZE_EXPONENT(type) : \ + 0u) + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x03000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x05000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x07000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x08000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x09000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is an asymmetric signature algorithm, + * also known as public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an asymmetric signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is an asymmetric encryption algorithm, + * also known as public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an asymmetric encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +/** Whether the specified algorithm is a key stretching / password hashing + * algorithm. + * + * A key stretching / password hashing algorithm is a key derivation algorithm + * that is suitable for use with a low-entropy secret such as a password. + * Equivalently, it's a key derivation algorithm that uses a + * #PSA_KEY_DERIVATION_INPUT_PASSWORD input step. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key stretching / password hashing algorithm, 0 + * otherwise. This macro may return either 0 or 1 if \p alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION_STRETCHING(alg) \ + (PSA_ALG_IS_KEY_DERIVATION(alg) && \ + (alg) & PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG) + +/** An invalid algorithm identifier value. */ +#define PSA_ALG_NONE ((psa_algorithm_t)0) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t)0x02000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x02000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x02000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x02000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x02000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0200000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0200000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0200000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0200000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x02000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x02000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x02000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x02000013) +/** The first 512 bits (64 bytes) of the SHAKE256 output. + * + * This is the prehashing for Ed448ph (see #PSA_ALG_ED448PH). For other + * scenarios where a hash function based on SHA3/SHAKE is desired, SHA3-512 + * has the same output size and a (theoretically) higher security strength. + */ +#define PSA_ALG_SHAKE256_512 ((psa_algorithm_t)0x02000015) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, #PSA_ALG_RSA_PSS_ANY_SALT, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(key, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x020000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x03800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x003f0000) +#define PSA_MAC_TRUNCATION_OFFSET 16 + +/* In the encoding of a MAC algorithm, the bit corresponding to + * #PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm + * is a wildcard algorithm. A key with such wildcard algorithm as permitted + * algorithm policy can be used with any algorithm corresponding to the + * same base class and having a (potentially truncated) MAC length greater or + * equal than the one encoded in #PSA_ALG_MAC_TRUNCATION_MASK. */ +#define PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t)0x00008000) + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p mac_alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ + PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) | \ + ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) + +/** Macro to build the base MAC algorithm corresponding to a truncated + * MAC algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p mac_alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~(PSA_ALG_MAC_TRUNCATION_MASK | \ + PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG)) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p mac_alg is a non-truncated MAC algorithm. + * \return Unspecified if \p mac_alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +/** Macro to build a MAC minimum-MAC-length wildcard algorithm. + * + * A minimum-MAC-length MAC wildcard algorithm permits all MAC algorithms + * sharing the same base algorithm, and where the (potentially truncated) MAC + * length of the specific algorithm is equal to or larger then the wildcard + * algorithm's minimum MAC length. + * + * \note When setting the minimum required MAC length to less than the + * smallest MAC length allowed by the base algorithm, this effectively + * becomes an 'any-MAC-length-allowed' policy for that base algorithm. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p mac_alg) + * is true). + * \param min_mac_length Desired minimum length of the message authentication + * code in bytes. This must be at most the untruncated + * length of the MAC and must be at least 1. + * + * \return The corresponding MAC wildcard algorithm with the + * specified minimum length. + * \return Unspecified if \p mac_alg is not a supported MAC + * algorithm or if \p min_mac_length is less than 1 or + * too large for the specified MAC algorithm. + */ +#define PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(mac_alg, min_mac_length) \ + ( PSA_ALG_TRUNCATED_MAC(mac_alg, min_mac_length) | \ + PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x03c00000) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x03c00100) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t)0x03c00200) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The stream cipher mode of a stream cipher algorithm. + * + * The underlying stream cipher is determined by the key type. + * - To use ChaCha20, use a key type of #PSA_KEY_TYPE_CHACHA20. + */ +#define PSA_ALG_STREAM_CIPHER ((psa_algorithm_t)0x04800100) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t)0x04c01000) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c01100) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c01200) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t)0x0440ff00) + +/** The Electronic Code Book (ECB) mode of a block cipher, with no padding. + * + * \warning ECB mode does not protect the confidentiality of the encrypted data + * except in extremely narrow circumstances. It is recommended that applications + * only use ECB if they need to construct an operating mode that the + * implementation does not provide. Implementations are encouraged to provide + * the modes that applications need in preference to supporting direct access + * to ECB. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths are a + * multiple of the block size of the chosen block cipher. + * + * ECB mode does not accept an initialization vector (IV). When using a + * multi-part cipher operation with this algorithm, psa_cipher_generate_iv() + * and psa_cipher_set_iv() must not be called. + */ +#define PSA_ALG_ECB_NO_PADDING ((psa_algorithm_t)0x04404400) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04404000) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04404100) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x05500100) + +/** The CCM* cipher mode without authentication. + * + * This is CCM* as specified in IEEE 802.15.4 §7, with a tag length of 0. + * For CCM* with a nonzero tag length, use the AEAD algorithm #PSA_ALG_CCM. + * + * The underlying block cipher is determined by the key type. + * + * Currently only 13-byte long IV's are supported. + */ +#define PSA_ALG_CCM_STAR_NO_TAG ((psa_algorithm_t)0x04c01300) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x05500200) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x05100500) + +/* In the encoding of a AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x003f0000) +#define PSA_AEAD_TAG_LENGTH_OFFSET 16 + +/* In the encoding of an AEAD algorithm, the bit corresponding to + * #PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG encodes the fact that the algorithm + * is a wildcard algorithm. A key with such wildcard algorithm as permitted + * algorithm policy can be used with any algorithm corresponding to the + * same base class and having a tag length greater than or equal to the one + * encoded in #PSA_ALG_AEAD_TAG_LENGTH_MASK. */ +#define PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ((psa_algorithm_t)0x00008000) + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) + * is true). + * \param tag_length Desired length of the authentication tag in bytes. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p aead_alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, tag_length) \ + (((aead_alg) & ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | \ + PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG)) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Retrieve the tag length of a specified AEAD algorithm + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p aead_alg) + * is true). + * + * \return The tag length specified by the input algorithm. + * \return Unspecified if \p aead_alg is not a supported + * AEAD algorithm. + */ +#define PSA_ALG_AEAD_GET_TAG_LENGTH(aead_alg) \ + (((aead_alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> \ + PSA_AEAD_TAG_LENGTH_OFFSET ) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p aead_alg) is true). + * + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(aead_alg) \ + ( \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_GCM) \ + PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 0) +#define PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG_CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, 0) == \ + PSA_ALG_AEAD_WITH_SHORTENED_TAG(ref, 0) ? \ + ref : + +/** Macro to build an AEAD minimum-tag-length wildcard algorithm. + * + * A minimum-tag-length AEAD wildcard algorithm permits all AEAD algorithms + * sharing the same base algorithm, and where the tag length of the specific + * algorithm is equal to or larger then the minimum tag length specified by the + * wildcard algorithm. + * + * \note When setting the minimum required tag length to less than the + * smallest tag length allowed by the base algorithm, this effectively + * becomes an 'any-tag-length-allowed' policy for that base algorithm. + * + * \param aead_alg An AEAD algorithm identifier (value of type + * #psa_algorithm_t such that + * #PSA_ALG_IS_AEAD(\p aead_alg) is true). + * \param min_tag_length Desired minimum length of the authentication tag in + * bytes. This must be at least 1 and at most the largest + * allowed tag length of the algorithm. + * + * \return The corresponding AEAD wildcard algorithm with the + * specified minimum length. + * \return Unspecified if \p aead_alg is not a supported + * AEAD algorithm or if \p min_tag_length is less than 1 + * or too large for the specified AEAD algorithm. + */ +#define PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(aead_alg, min_tag_length) \ + ( PSA_ALG_AEAD_WITH_SHORTENED_TAG(aead_alg, min_tag_length) | \ + PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ) + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x06000200) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x06000300) +#define PSA_ALG_RSA_PSS_ANY_SALT_BASE ((psa_algorithm_t)0x06001300) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** RSA PSS signature with hashing with relaxed verification. + * + * This algorithm has the same behavior as #PSA_ALG_RSA_PSS when signing, + * but allows an arbitrary salt length (including \c 0) when verifying a + * signature. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS_ANY_SALT(hash_alg) \ + (PSA_ALG_RSA_PSS_ANY_SALT_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is RSA PSS with standard salt. + * + * \param alg An algorithm value or an algorithm policy wildcard. + * + * \return 1 if \p alg is of the form + * #PSA_ALG_RSA_PSS(\c hash_alg), + * where \c hash_alg is a hash algorithm or + * #PSA_ALG_ANY_HASH. 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not + * a supported algorithm identifier or policy. + */ +#define PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +/** Whether the specified algorithm is RSA PSS with any salt. + * + * \param alg An algorithm value or an algorithm policy wildcard. + * + * \return 1 if \p alg is of the form + * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), + * where \c hash_alg is a hash algorithm or + * #PSA_ALG_ANY_HASH. 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not + * a supported algorithm identifier or policy. + */ +#define PSA_ALG_IS_RSA_PSS_ANY_SALT(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_ANY_SALT_BASE) + +/** Whether the specified algorithm is RSA PSS. + * + * This includes any of the RSA PSS algorithm variants, regardless of the + * constraints on salt length. + * + * \param alg An algorithm value or an algorithm policy wildcard. + * + * \return 1 if \p alg is of the form + * #PSA_ALG_RSA_PSS(\c hash_alg) or + * #PSA_ALG_RSA_PSS_ANY_SALT_BASE(\c hash_alg), + * where \c hash_alg is a hash algorithm or + * #PSA_ALG_ANY_HASH. 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not + * a supported algorithm identifier or policy. + */ +#define PSA_ALG_IS_RSA_PSS(alg) \ + (PSA_ALG_IS_RSA_PSS_STANDARD_SALT(alg) || \ + PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x06000600) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x06000700) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00000100) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Edwards-curve digital signature algorithm without prehashing (PureEdDSA), + * using standard parameters. + * + * Contexts are not supported in the current version of this specification + * because there is no suitable signature interface that can take the + * context as a parameter. A future version of this specification may add + * suitable functions and extend this algorithm to support contexts. + * + * PureEdDSA requires an elliptic curve key on a twisted Edwards curve. + * In this specification, the following curves are supported: + * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 255-bit: Ed25519 as specified + * in RFC 8032. + * The curve is Edwards25519. + * The hash function used internally is SHA-512. + * - #PSA_ECC_FAMILY_TWISTED_EDWARDS, 448-bit: Ed448 as specified + * in RFC 8032. + * The curve is Edwards448. + * The hash function used internally is the first 114 bytes of the + * SHAKE256 output. + * + * This algorithm can be used with psa_sign_message() and + * psa_verify_message(). Since there is no prehashing, it cannot be used + * with psa_sign_hash() or psa_verify_hash(). + * + * The signature format is the concatenation of R and S as defined by + * RFC 8032 §5.1.6 and §5.2.6 (a 64-byte string for Ed25519, a 114-byte + * string for Ed448). + */ +#define PSA_ALG_PURE_EDDSA ((psa_algorithm_t)0x06000800) + +#define PSA_ALG_HASH_EDDSA_BASE ((psa_algorithm_t)0x06000900) +#define PSA_ALG_IS_HASH_EDDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HASH_EDDSA_BASE) + +/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), + * using SHA-512 and the Edwards25519 curve. + * + * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. + * + * This algorithm is Ed25519 as specified in RFC 8032. + * The curve is Edwards25519. + * The prehash is SHA-512. + * The hash function used internally is SHA-512. + * + * This is a hash-and-sign algorithm: to calculate a signature, + * you can either: + * - call psa_sign_message() on the message; + * - or calculate the SHA-512 hash of the message + * with psa_hash_compute() + * or with a multi-part hash operation started with psa_hash_setup(), + * using the hash algorithm #PSA_ALG_SHA_512, + * then sign the calculated hash with psa_sign_hash(). + * Verifying a signature is similar, using psa_verify_message() or + * psa_verify_hash() instead of the signature function. + */ +#define PSA_ALG_ED25519PH \ + (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHA_512 & PSA_ALG_HASH_MASK)) + +/** Edwards-curve digital signature algorithm with prehashing (HashEdDSA), + * using SHAKE256 and the Edwards448 curve. + * + * See #PSA_ALG_PURE_EDDSA regarding context support and the signature format. + * + * This algorithm is Ed448 as specified in RFC 8032. + * The curve is Edwards448. + * The prehash is the first 64 bytes of the SHAKE256 output. + * The hash function used internally is the first 114 bytes of the + * SHAKE256 output. + * + * This is a hash-and-sign algorithm: to calculate a signature, + * you can either: + * - call psa_sign_message() on the message; + * - or calculate the first 64 bytes of the SHAKE256 output of the message + * with psa_hash_compute() + * or with a multi-part hash operation started with psa_hash_setup(), + * using the hash algorithm #PSA_ALG_SHAKE256_512, + * then sign the calculated hash with psa_sign_hash(). + * Verifying a signature is similar, using psa_verify_message() or + * psa_verify_hash() instead of the signature function. + */ +#define PSA_ALG_ED448PH \ + (PSA_ALG_HASH_EDDSA_BASE | (PSA_ALG_SHAKE256_512 & PSA_ALG_HASH_MASK)) + +/* Default definition, to be overridden if the library is extended with + * more hash-and-sign algorithms that we want to keep out of this header + * file. */ +#define PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg) 0 + +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_hash() and psa_verify_hash(). + * + * This encompasses all strict hash-and-sign algorithms categorized by + * PSA_ALG_IS_HASH_AND_SIGN(), as well as algorithms that follow the + * paradigm more loosely: + * - #PSA_ALG_RSA_PKCS1V15_SIGN_RAW (expects its input to be an encoded hash) + * - #PSA_ALG_ECDSA_ANY (doesn't specify what kind of hash the input is) + * + * \param alg An algorithm identifier (value of type psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * hash. 0 if alg is a signature algorithm that can only be used + * to sign a message. 0 if alg is not a signature algorithm. + * This macro can return either 0 or 1 if alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_HASH(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg) || PSA_ALG_IS_HASH_EDDSA(alg) || \ + PSA_ALG_IS_VENDOR_HASH_AND_SIGN(alg)) + +/** Whether the specified algorithm is a signature algorithm that can be used + * with psa_sign_message() and psa_verify_message(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if alg is a signature algorithm that can be used to sign a + * message. 0 if \p alg is a signature algorithm that can only be used + * to sign an already-calculated hash. 0 if \p alg is not a signature + * algorithm. This macro can return either 0 or 1 if \p alg is not a + * supported algorithm identifier. + */ +#define PSA_ALG_IS_SIGN_MESSAGE(alg) \ + (PSA_ALG_IS_SIGN_HASH(alg) || (alg) == PSA_ALG_PURE_EDDSA ) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are asymmetric (public-key) signature algorithms + * structured in two parts: first the calculation of a hash in a way that + * does not depend on the key, then the calculation of a signature from the + * hash value and the key. Hash-and-sign algorithms encode the hash + * used for the hashing step, and you can call #PSA_ALG_SIGN_GET_HASH + * to extract this algorithm. + * + * Thus, for a hash-and-sign algorithm, + * `psa_sign_message(key, alg, input, ...)` is equivalent to + * ``` + * psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg), input, ..., hash, ...); + * psa_sign_hash(key, alg, hash, ..., signature, ...); + * ``` + * Most usefully, separating the hash from the signature allows the hash + * to be calculated in multiple steps with psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Likewise psa_verify_message() is equivalent to + * calculating the hash and then calling psa_verify_hash(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_SIGN_HASH(alg) && \ + ((alg) & PSA_ALG_HASH_MASK) != 0) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x07000200) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x07000300) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP encryption algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x08000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x08000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x08000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +/* This flag indicates whether the key derivation algorithm is suitable for + * use on low-entropy secrets such as password - these algorithms are also + * known as key stretching or password hashing schemes. These are also the + * algorithms that accepts inputs of type #PSA_KEY_DERIVATION_INPUT_PASSWORD. + * + * Those algorithms cannot be combined with a key agreement algorithm. + */ +#define PSA_ALG_KEY_DERIVATION_STRETCHING_FLAG ((psa_algorithm_t)0x00800000) + +#define PSA_ALG_PBKDF2_HMAC_BASE ((psa_algorithm_t)0x08800100) +/** Macro to build a PBKDF2-HMAC password hashing / key stretching algorithm. + * + * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). + * This macro specifies the PBKDF2 algorithm constructed using a PRF based on + * HMAC with the specified hash. + * For example, `PSA_ALG_PBKDF2_HMAC(PSA_ALG_SHA256)` specifies PBKDF2 + * using the PRF HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs, which must be + * provided in the following order: + * - #PSA_KEY_DERIVATION_INPUT_COST is the iteration count. + * This input step must be used exactly once. + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt. + * This input step must be used one or more times; if used several times, the + * inputs will be concatenated. This can be used to build the final salt + * from multiple sources, both public and secret (also known as pepper). + * - #PSA_KEY_DERIVATION_INPUT_PASSWORD is the password to be hashed. + * This input step must be used exactly once. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding PBKDF2-HMAC-XXX algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_PBKDF2_HMAC(hash_alg) \ + (PSA_ALG_PBKDF2_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a PBKDF2-HMAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a PBKDF2-HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_PBKDF2_HMAC(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE) + +/** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm. + * + * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2). + * This macro specifies the PBKDF2 algorithm constructed using the + * AES-CMAC-PRF-128 PRF specified by RFC 4615. + * + * This key derivation algorithm uses the same inputs as + * #PSA_ALG_PBKDF2_HMAC() with the same constraints. + */ +#define PSA_ALG_PBKDF2_AES_CMAC_PRF_128 ((psa_algorithm_t)0x08800200) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0xfe00ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0xffff0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with #PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t)0x09010000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_FAMILY_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_FAMILY_SECPXXX` and `PSA_ECC_FAMILY_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_FAMILY_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t)0x09020000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + PSA_ALG_IS_MAC(alg) ? \ + (alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ + PSA_ALG_IS_AEAD(alg) ? \ + (alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0 : \ + (alg) == PSA_ALG_ANY_HASH) + +/** Get the hash used by a composite algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return The underlying hash algorithm if alg is a composite algorithm that + * uses a hash algorithm. + * + * \return \c 0 if alg is not a composite algorithm that uses a hash. + */ +#define PSA_ALG_GET_HASH(alg) \ + (((alg) & 0x000000ff) == 0 ? ((psa_algorithm_t)0) : 0x02000000 | ((alg) & 0x000000ff)) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** The default lifetime for volatile keys. + * + * A volatile key only exists as long as the identifier to it is not destroyed. + * The key material is guaranteed to be erased on a power reset. + * + * A key with this lifetime is typically stored in the RAM area of the + * PSA Crypto subsystem. However this is an implementation choice. + * If an implementation stores data about the key in a non-volatile memory, + * it must release all the resources associated with the key and erase the + * key material if the calling application terminates. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default lifetime for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but integrations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Integrations of Mbed TLS may support other persistent lifetimes. + * See ::psa_key_lifetime_t for more information. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** The persistence level of volatile keys. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_VOLATILE ((psa_key_persistence_t)0x00) + +/** The default persistence level for persistent keys. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_DEFAULT ((psa_key_persistence_t)0x01) + +/** A persistence level indicating that a key is never destroyed. + * + * See ::psa_key_persistence_t for more information. + */ +#define PSA_KEY_PERSISTENCE_READ_ONLY ((psa_key_persistence_t)0xff) + +#define PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) \ + ((psa_key_persistence_t)((lifetime) & 0x000000ff)) + +#define PSA_KEY_LIFETIME_GET_LOCATION(lifetime) \ + ((psa_key_location_t)((lifetime) >> 8)) + +/** Whether a key lifetime indicates that the key is volatile. + * + * A volatile key is automatically destroyed by the implementation when + * the application instance terminates. In particular, a volatile key + * is automatically destroyed on a power reset of the device. + * + * A key that is not volatile is persistent. Persistent keys are + * preserved until the application explicitly destroys them or until an + * implementation-specific device management event occurs (for example, + * a factory reset). + * + * \param lifetime The lifetime value to query (value of type + * ::psa_key_lifetime_t). + * + * \return \c 1 if the key is volatile, otherwise \c 0. + */ +#define PSA_KEY_LIFETIME_IS_VOLATILE(lifetime) \ + (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ + PSA_KEY_PERSISTENCE_VOLATILE) + +/** Whether a key lifetime indicates that the key is read-only. + * + * Read-only keys cannot be created or destroyed through the PSA Crypto API. + * They must be created through platform-specific means that bypass the API. + * + * Some platforms may offer ways to destroy read-only keys. For example, + * consider a platform with multiple levels of privilege, where a + * low-privilege application can use a key but is not allowed to destroy + * it, and the platform exposes the key to the application with a read-only + * lifetime. High-privilege code can destroy the key even though the + * application sees the key as read-only. + * + * \param lifetime The lifetime value to query (value of type + * ::psa_key_lifetime_t). + * + * \return \c 1 if the key is read-only, otherwise \c 0. + */ +#define PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime) \ + (PSA_KEY_LIFETIME_GET_PERSISTENCE(lifetime) == \ + PSA_KEY_PERSISTENCE_READ_ONLY) + +/** Construct a lifetime from a persistence level and a location. + * + * \param persistence The persistence level + * (value of type ::psa_key_persistence_t). + * \param location The location indicator + * (value of type ::psa_key_location_t). + * + * \return The constructed lifetime value. + */ +#define PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(persistence, location) \ + ((location) << 8 | (persistence)) + +/** The local storage area for persistent keys. + * + * This storage area is available on all systems that can store persistent + * keys without delegating the storage to a third-party cryptoprocessor. + * + * See ::psa_key_location_t for more information. + */ +#define PSA_KEY_LOCATION_LOCAL_STORAGE ((psa_key_location_t)0x000000) + +#define PSA_KEY_LOCATION_VENDOR_FLAG ((psa_key_location_t)0x800000) + +/** The null key identifier. + */ +#define PSA_KEY_ID_NULL ((psa_key_id_t)0) +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_key_id_t)0x7fffffff) + + +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + +#define MBEDTLS_SVC_KEY_ID_INIT ( (psa_key_id_t)0 ) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ( id ) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( id ) ( 0 ) + +/** Utility to initialize a key identifier at runtime. + * + * \param unused Unused parameter. + * \param key_id Identifier of the key. + */ +static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( + unsigned int unused, psa_key_id_t key_id ) +{ + (void)unused; + + return( key_id ); +} + +/** Compare two key identifiers. + * + * \param id1 First key identifier. + * \param id2 Second key identifier. + * + * \return Non-zero if the two key identifier are equal, zero otherwise. + */ +static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1, + mbedtls_svc_key_id_t id2 ) +{ + return( id1 == id2 ); +} + +/** Check whether a key identifier is null. + * + * \param key Key identifier. + * + * \return Non-zero if the key identifier is null, zero otherwise. + */ +static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) +{ + return( key == 0 ); +} + +#else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +#define MBEDTLS_SVC_KEY_ID_INIT ( (mbedtls_svc_key_id_t){ 0, 0 } ) +#define MBEDTLS_SVC_KEY_ID_GET_KEY_ID( id ) ( ( id ).key_id ) +#define MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( id ) ( ( id ).owner ) + +/** Utility to initialize a key identifier at runtime. + * + * \param owner_id Identifier of the key owner. + * \param key_id Identifier of the key. + */ +static inline mbedtls_svc_key_id_t mbedtls_svc_key_id_make( + mbedtls_key_owner_id_t owner_id, psa_key_id_t key_id ) +{ + return( (mbedtls_svc_key_id_t){ .MBEDTLS_PRIVATE(key_id) = key_id, + .MBEDTLS_PRIVATE(owner) = owner_id } ); +} + +/** Compare two key identifiers. + * + * \param id1 First key identifier. + * \param id2 Second key identifier. + * + * \return Non-zero if the two key identifier are equal, zero otherwise. + */ +static inline int mbedtls_svc_key_id_equal( mbedtls_svc_key_id_t id1, + mbedtls_svc_key_id_t id2 ) +{ + return( ( id1.MBEDTLS_PRIVATE(key_id) == id2.MBEDTLS_PRIVATE(key_id) ) && + mbedtls_key_owner_id_equal( id1.MBEDTLS_PRIVATE(owner), id2.MBEDTLS_PRIVATE(owner) ) ); +} + +/** Check whether a key identifier is null. + * + * \param key Key identifier. + * + * \return Non-zero if the key identifier is null, zero otherwise. + */ +static inline int mbedtls_svc_key_id_is_null( mbedtls_svc_key_id_t key ) +{ + return( key.MBEDTLS_PRIVATE(key_id) == 0 ); +} + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */ + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation or for + * an asymmetric message signature operation, if otherwise permitted by the + * key’s type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_MESSAGE ((psa_key_usage_t)0x00000400) + +/** Whether the key may be used to verify a message. + * + * This flag allows the key to be used for a MAC verification operation or for + * an asymmetric message signature verification operation, if otherwise + * permitted by the key’s type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_MESSAGE ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00001000) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00002000) + +/** Whether the key may be used to derive other keys or produce a password + * hash. + * + * This flag allows the key to be used for a key derivation operation or for + * a key agreement operation, if otherwise permitted by by the key's type and + * policy. + * + * If this flag is present on all keys used in calls to + * psa_key_derivation_input_key() for a key derivation operation, then it + * permits calling psa_key_derivation_output_bytes() or + * psa_key_derivation_output_key() at the end of the operation. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00004000) + +/** Whether the key may be used to verify the result of a key derivation, + * including password hashing. + * + * This flag allows the key to be used: + * + * This flag allows the key to be used in a key derivation operation, if + * otherwise permitted by by the key's type and policy. + * + * If this flag is present on all keys used in calls to + * psa_key_derivation_input_key() for a key derivation operation, then it + * permits calling psa_key_derivation_verify_bytes() or + * psa_key_derivation_verify_key() at the end of the operation. + */ +#define PSA_KEY_USAGE_VERIFY_DERIVATION ((psa_key_usage_t)0x00008000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), + * psa_key_derivation_verify_bytes(), or + * psa_key_derivation_verify_key(), but not + * psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A low-entropy secret input for password hashing / key stretching. + * + * This is usually a key of type #PSA_KEY_TYPE_PASSWORD (passed to + * psa_key_derivation_input_key()) or a direct input (passed to + * psa_key_derivation_input_bytes()) that is a password or passphrase. It can + * also be high-entropy secret such as a key of type #PSA_KEY_TYPE_DERIVE or + * the shared secret resulting from a key agreement. + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), + * psa_key_derivation_verify_bytes(), or + * psa_key_derivation_verify_key(), but not + * psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_PASSWORD ((psa_key_derivation_step_t)0x0102) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA or + * #PSA_KEY_TYPE_PEPPER. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/** A cost parameter for password hashing / key stretching. + * + * This must be a direct input, passed to psa_key_derivation_input_integer(). + */ +#define PSA_KEY_DERIVATION_INPUT_COST ((psa_key_derivation_step_t)0x0205) + +/**@}*/ + +/** \defgroup helper_macros Helper macros + * @{ + */ + +/* Helper macros */ + +/** Check if two AEAD algorithm identifiers refer to the same AEAD algorithm + * regardless of the tag length they encode. + * + * \param aead_alg_1 An AEAD algorithm identifier. + * \param aead_alg_2 An AEAD algorithm identifier. + * + * \return 1 if both identifiers refer to the same AEAD algorithm, + * 0 otherwise. + * Unspecified if neither \p aead_alg_1 nor \p aead_alg_2 are + * a supported AEAD algorithm. + */ +#define MBEDTLS_PSA_ALG_AEAD_EQUAL(aead_alg_1, aead_alg_2) \ + (!(((aead_alg_1) ^ (aead_alg_2)) & \ + ~(PSA_ALG_AEAD_TAG_LENGTH_MASK | PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG))) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/.gitignore b/component/common/network/ssl/mbedtls-3.1.0/library/.gitignore new file mode 100644 index 00000000..f6619d27 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/.gitignore @@ -0,0 +1,10 @@ +*.o +libmbed* +*.sln +*.vcxproj + +# Automatically generated files +/error.c +/version_features.c +/ssl_debug_helpers_generated.c +/ssl_debug_helpers_generated.h diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/CMakeLists.txt b/component/common/network/ssl/mbedtls-3.1.0/library/CMakeLists.txt new file mode 100644 index 00000000..07599f5d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/CMakeLists.txt @@ -0,0 +1,288 @@ +option(USE_STATIC_MBEDTLS_LIBRARY "Build mbed TLS static library." ON) +option(USE_SHARED_MBEDTLS_LIBRARY "Build mbed TLS shared library." OFF) +option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF) +option(LINK_WITH_TRUSTED_STORAGE "Explicitly link mbed TLS library to trusted_storage." OFF) + +# Set the project root directory if it's not already defined, as may happen if +# the library folder is included directly by a parent project, without +# including the top level CMakeLists.txt. +if(NOT DEFINED MBEDTLS_DIR) + set(MBEDTLS_DIR ${CMAKE_SOURCE_DIR}) +endif() + +set(src_crypto + aes.c + aesni.c + aria.c + asn1parse.c + asn1write.c + base64.c + bignum.c + camellia.c + ccm.c + chacha20.c + chachapoly.c + cipher.c + cipher_wrap.c + constant_time.c + cmac.c + ctr_drbg.c + des.c + dhm.c + ecdh.c + ecdsa.c + ecjpake.c + ecp.c + ecp_curves.c + entropy.c + entropy_poll.c + error.c + gcm.c + hkdf.c + hmac_drbg.c + md.c + md5.c + memory_buffer_alloc.c + mps_reader.c + mps_trace.c + nist_kw.c + oid.c + padlock.c + pem.c + pk.c + pk_wrap.c + pkcs12.c + pkcs5.c + pkparse.c + pkwrite.c + platform.c + platform_util.c + poly1305.c + psa_crypto.c + psa_crypto_aead.c + psa_crypto_cipher.c + psa_crypto_client.c + psa_crypto_driver_wrappers.c + psa_crypto_ecp.c + psa_crypto_hash.c + psa_crypto_mac.c + psa_crypto_rsa.c + psa_crypto_se.c + psa_crypto_slot_management.c + psa_crypto_storage.c + psa_its_file.c + ripemd160.c + rsa.c + rsa_alt_helpers.c + sha1.c + sha256.c + sha512.c + ssl_debug_helpers_generated.c + threading.c + timing.c + version.c + version_features.c +) + +set(src_x509 + x509.c + x509_create.c + x509_crl.c + x509_crt.c + x509_csr.c + x509write_crt.c + x509write_csr.c +) + +set(src_tls + debug.c + net_sockets.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_cookie.c + ssl_msg.c + ssl_srv.c + ssl_ticket.c + ssl_tls.c + ssl_tls13_keys.c + ssl_tls13_server.c + ssl_tls13_client.c + ssl_tls13_generic.c +) + +if(GEN_FILES) + find_package(Perl REQUIRED) + + file(GLOB error_headers ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/*.h) + add_custom_command( + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/error.c + COMMAND + ${PERL_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl + ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files + ${CMAKE_CURRENT_BINARY_DIR}/error.c + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_errors.pl + ${error_headers} + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/error.fmt + ) + + add_custom_command( + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/version_features.c + COMMAND + ${PERL_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl + ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files + ${CMAKE_CURRENT_BINARY_DIR}/version_features.c + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_features.pl + ${CMAKE_CURRENT_SOURCE_DIR}/../include/mbedtls/mbedtls_config.h + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/data_files/version_features.fmt + ) + + add_custom_command( + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/ssl_debug_helpers_generated.h + ${CMAKE_CURRENT_BINARY_DIR}/ssl_debug_helpers_generated.c + COMMAND + ${MBEDTLS_PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py + --mbedtls-root ${CMAKE_CURRENT_SOURCE_DIR}/.. + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/../scripts/generate_ssl_debug_helpers.py + ${error_headers} + ) +else() + link_to_source(error.c) + link_to_source(version_features.c) + link_to_source(ssl_debug_helpers_generated.c) + link_to_source(ssl_debug_helpers_generated.h) +endif() + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") +endif(CMAKE_COMPILER_IS_CLANG) + +if(WIN32) + set(libs ${libs} ws2_32) +endif(WIN32) + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + SET(CMAKE_C_ARCHIVE_CREATE " Scr ") + SET(CMAKE_CXX_ARCHIVE_CREATE " Scr ") + SET(CMAKE_C_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") + SET(CMAKE_CXX_ARCHIVE_FINISH " -no_warning_for_no_symbols -c ") +endif() + +if(HAIKU) + set(libs ${libs} network) +endif(HAIKU) + +if(LINK_WITH_PTHREAD) + set(libs ${libs} pthread) +endif() + +if(LINK_WITH_TRUSTED_STORAGE) + set(libs ${libs} trusted_storage) +endif() + +if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + message(FATAL_ERROR "Need to choose static or shared mbedtls build!") +endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + +set(mbedtls_target "${MBEDTLS_TARGET_PREFIX}mbedtls") +set(mbedx509_target "${MBEDTLS_TARGET_PREFIX}mbedx509") +set(mbedcrypto_target "${MBEDTLS_TARGET_PREFIX}mbedcrypto") + +set(mbedtls_target ${mbedtls_target} PARENT_SCOPE) +set(mbedx509_target ${mbedx509_target} PARENT_SCOPE) +set(mbedcrypto_target ${mbedcrypto_target} PARENT_SCOPE) + +if (USE_STATIC_MBEDTLS_LIBRARY) + set(mbedtls_static_target ${mbedtls_target}) + set(mbedx509_static_target ${mbedx509_target}) + set(mbedcrypto_static_target ${mbedcrypto_target}) +endif() + +set(target_libraries ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target}) + +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + string(APPEND mbedtls_static_target "_static") + string(APPEND mbedx509_static_target "_static") + string(APPEND mbedcrypto_static_target "_static") + + list(APPEND target_libraries + ${mbedcrypto_static_target} + ${mbedx509_static_target} + ${mbedtls_static_target}) +endif() + +if(USE_STATIC_MBEDTLS_LIBRARY) + add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) + set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) + target_link_libraries(${mbedcrypto_static_target} PUBLIC ${libs}) + + if(TARGET everest) + target_link_libraries(${mbedcrypto_static_target} PUBLIC everest) + endif() + + add_library(${mbedx509_static_target} STATIC ${src_x509}) + set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) + target_link_libraries(${mbedx509_static_target} PUBLIC ${libs} ${mbedcrypto_static_target}) + + add_library(${mbedtls_static_target} STATIC ${src_tls}) + set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) + target_link_libraries(${mbedtls_static_target} PUBLIC ${libs} ${mbedx509_static_target}) +endif(USE_STATIC_MBEDTLS_LIBRARY) + +if(USE_SHARED_MBEDTLS_LIBRARY) + add_library(${mbedcrypto_target} SHARED ${src_crypto}) + set_target_properties(${mbedcrypto_target} PROPERTIES VERSION 3.1.0 SOVERSION 11) + target_link_libraries(${mbedcrypto_target} PUBLIC ${libs}) + + if(TARGET everest) + target_link_libraries(${mbedcrypto_target} PUBLIC everest) + endif() + + add_library(${mbedx509_target} SHARED ${src_x509}) + set_target_properties(${mbedx509_target} PROPERTIES VERSION 3.1.0 SOVERSION 4) + target_link_libraries(${mbedx509_target} PUBLIC ${libs} ${mbedcrypto_target}) + + add_library(${mbedtls_target} SHARED ${src_tls}) + set_target_properties(${mbedtls_target} PROPERTIES VERSION 3.1.0 SOVERSION 17) + target_link_libraries(${mbedtls_target} PUBLIC ${libs} ${mbedx509_target}) +endif(USE_SHARED_MBEDTLS_LIBRARY) + +foreach(target IN LISTS target_libraries) + # Include public header files from /include and other directories + # declared by /3rdparty/**/CMakeLists.txt. Include private header files + # from /library and others declared by /3rdparty/**/CMakeLists.txt. + # /library needs to be listed explicitly when building .c files outside + # of /library (which currently means: under /3rdparty). + target_include_directories(${target} + PUBLIC $ + $ + PRIVATE ${MBEDTLS_DIR}/library/) + install( + TARGETS ${target} + EXPORT MbedTLSTargets + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) +endforeach(target) + +set(lib_target "${MBEDTLS_TARGET_PREFIX}lib") + +add_custom_target(${lib_target} DEPENDS ${mbedcrypto_target} ${mbedx509_target} ${mbedtls_target}) +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + add_dependencies(${lib_target} ${mbedcrypto_static_target} ${mbedx509_static_target} ${mbedtls_static_target}) +endif() diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/Makefile b/component/common/network/ssl/mbedtls-3.1.0/library/Makefile new file mode 100644 index 00000000..5c23aebf --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/Makefile @@ -0,0 +1,337 @@ + +# Also see "include/mbedtls/mbedtls_config.h" + +CFLAGS ?= -O2 +WARNING_CFLAGS ?= -Wall -Wextra -Wformat=2 -Wno-format-nonliteral +LDFLAGS ?= + +# Include ../include for public headers and . for private headers. +# Note that . needs to be included explicitly for the sake of library +# files that are not in the /library directory (which currently means +# under /3rdparty). +LOCAL_CFLAGS = $(WARNING_CFLAGS) -I. -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_LDFLAGS = + +ifdef DEBUG +LOCAL_CFLAGS += -g3 +endif + +# MicroBlaze specific options: +# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift + +# To compile on Plan9: +# CFLAGS += -D_BSD_EXTENSION + +PERL ?= perl + +ifdef WINDOWS +PYTHON ?= python +else +PYTHON ?= $(shell if type python3 >/dev/null 2>/dev/null; then echo python3; else echo python; fi) +endif + +# if were running on Windows build for Windows +ifdef WINDOWS +WINDOWS_BUILD=1 +else ifeq ($(shell uname -s),Darwin) +ifeq ($(AR),ar) +APPLE_BUILD ?= 1 +endif +endif + +# To compile as a shared library: +ifdef SHARED +# all code is position-indep with mingw, avoid warning about useless flag +ifndef WINDOWS_BUILD +LOCAL_CFLAGS += -fPIC -fpic +endif +endif + +SOEXT_TLS=so.17 +SOEXT_X509=so.4 +SOEXT_CRYPTO=so.11 + +# Set AR_DASH= (empty string) to use an ar implementation that does not accept +# the - prefix for command line options (e.g. llvm-ar) +AR_DASH ?= - + +ARFLAGS = $(AR_DASH)src +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +ARFLAGS = $(AR_DASH)Src +RLFLAGS = -no_warning_for_no_symbols -c +RL ?= ranlib +endif +endif + +DLEXT ?= so +ifdef WINDOWS_BUILD +# Windows shared library extension: +DLEXT = dll +else ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) +# Mac OS X shared library extension: +DLEXT = dylib +endif +endif + +OBJS_CRYPTO= \ + aes.o \ + aesni.o \ + aria.o \ + asn1parse.o \ + asn1write.o \ + base64.o \ + bignum.o \ + camellia.o \ + ccm.o \ + chacha20.o \ + chachapoly.o \ + cipher.o \ + cipher_wrap.o \ + cmac.o \ + constant_time.o \ + ctr_drbg.o \ + des.o \ + dhm.o \ + ecdh.o \ + ecdsa.o \ + ecjpake.o \ + ecp.o \ + ecp_curves.o \ + entropy.o \ + entropy_poll.o \ + error.o \ + gcm.o \ + hkdf.o \ + hmac_drbg.o \ + md.o \ + md5.o \ + memory_buffer_alloc.o \ + mps_reader.o \ + mps_trace.o \ + nist_kw.o \ + oid.o \ + padlock.o \ + pem.o \ + pk.o \ + pk_wrap.o \ + pkcs12.o \ + pkcs5.o \ + pkparse.o \ + pkwrite.o \ + platform.o \ + platform_util.o \ + poly1305.o \ + psa_crypto.o \ + psa_crypto_aead.o \ + psa_crypto_cipher.o \ + psa_crypto_client.o \ + psa_crypto_driver_wrappers.o \ + psa_crypto_ecp.o \ + psa_crypto_hash.o \ + psa_crypto_mac.o \ + psa_crypto_rsa.o \ + psa_crypto_se.o \ + psa_crypto_slot_management.o \ + psa_crypto_storage.o \ + psa_its_file.o \ + ripemd160.o \ + rsa.o \ + rsa_alt_helpers.o \ + sha1.o \ + sha256.o \ + sha512.o \ + ssl_debug_helpers_generated.o \ + threading.o \ + timing.o \ + version.o \ + version_features.o \ + # This line is intentionally left blank + +include ../3rdparty/Makefile.inc +LOCAL_CFLAGS+=$(THIRDPARTY_INCLUDES) +OBJS_CRYPTO+=$(THIRDPARTY_CRYPTO_OBJECTS) + +OBJS_X509= \ + x509.o \ + x509_create.o \ + x509_crl.o \ + x509_crt.o \ + x509_csr.o \ + x509write_crt.o \ + x509write_csr.o \ + # This line is intentionally left blank + +OBJS_TLS= \ + debug.o \ + net_sockets.o \ + ssl_cache.o \ + ssl_ciphersuites.o \ + ssl_cli.o \ + ssl_cookie.o \ + ssl_msg.o \ + ssl_srv.o \ + ssl_ticket.o \ + ssl_tls.o \ + ssl_tls13_keys.o \ + ssl_tls13_client.o \ + ssl_tls13_server.o \ + ssl_tls13_generic.o \ + # This line is intentionally left blank + +.SILENT: + +.PHONY: all static shared clean + +ifndef SHARED +all: static +else +all: shared static +endif + +static: libmbedcrypto.a libmbedx509.a libmbedtls.a + +shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT) + +# Windows builds under Mingw can fail if make tries to create archives in the same +# directory at the same time - see https://bugs.launchpad.net/gcc-arm-embedded/+bug/1848002. +# This forces builds of the .a files to be serialised. +ifdef WINDOWS +libmbedtls.a: | libmbedx509.a +libmbedx509.a: | libmbedcrypto.a +endif + +# tls +libmbedtls.a: $(OBJS_TLS) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_TLS) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS_TLS) -L. -lmbedx509 -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) + +libmbedtls.so: libmbedtls.$(SOEXT_TLS) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedtls.dylib: $(OBJS_TLS) libmbedx509.dylib + echo " LD $@" + $(CC) -dynamiclib -o $@ $(OBJS_TLS) -L. -lmbedx509 -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) + +libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedx509 -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# x509 +libmbedx509.a: $(OBJS_X509) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_X509) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS_X509) -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) + +libmbedx509.so: libmbedx509.$(SOEXT_X509) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib + echo " LD $@" + $(CC) -dynamiclib -o $@ $(OBJS_X509) -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) + +libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# crypto +libmbedcrypto.a: $(OBJS_CRYPTO) + echo " AR $@" + $(AR) $(ARFLAGS) $@ $(OBJS_CRYPTO) +ifdef APPLE_BUILD +ifneq ($(APPLE_BUILD),0) + echo " RL $@" + $(RL) $(RLFLAGS) $@ +endif +endif + +libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -o $@ $(OBJS_CRYPTO) $(LOCAL_LDFLAGS) $(LDFLAGS) + +libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedcrypto.dylib: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -dynamiclib -o $@ $(OBJS_CRYPTO) $(LOCAL_LDFLAGS) $(LDFLAGS) + +libmbedcrypto.dll: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +.c.o: + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -o $@ -c $< + +.PHONY: generated_files +GENERATED_FILES = \ + error.c version_features.c \ + ssl_debug_helpers_generated.c ssl_debug_helpers_generated.h +generated_files: $(GENERATED_FILES) + +error.c: ../scripts/generate_errors.pl +error.c: ../scripts/data_files/error.fmt +error.c: $(filter-out %config%,$(wildcard ../include/mbedtls/*.h)) +error.c: + echo " Gen $@" + $(PERL) ../scripts/generate_errors.pl + +ssl_debug_helpers_generated.c: | ssl_debug_helpers_generated.h +ssl_debug_helpers_generated.h: ../scripts/generate_ssl_debug_helpers.py +ssl_debug_helpers_generated.h: $(filter-out %config%,$(wildcard ../include/mbedtls/*.h)) +ssl_debug_helpers_generated.h: + echo " Gen $@" + $(PYTHON) ../scripts/generate_ssl_debug_helpers.py --mbedtls-root .. . + +version_features.c: ../scripts/generate_features.pl +version_features.c: ../scripts/data_files/version_features.fmt +## The generated file only depends on the options that are present in mbedtls_config.h, +## not on which options are set. To avoid regenerating this file all the time +## when switching between configurations, don't declare mbedtls_config.h as a +## dependency. Remove this file from your working tree if you've just added or +## removed an option in mbedtls_config.h. +#version_features.c: ../include/mbedtls/mbedtls_config.h +version_features.c: + echo " Gen $@" + $(PERL) ../scripts/generate_features.pl + +clean: +ifndef WINDOWS + rm -f *.o libmbed* + rm -f $(THIRDPARTY_CRYPTO_OBJECTS) +else + if exist *.o del /Q /F *.o + if exist libmbed* del /Q /F libmbed* + del /Q /F del_errors_out_if_the_file_list_is_empty_but_not_if_a_file_does_not_exist $(subst /,\,$(THIRDPARTY_CRYPTO_OBJECTS)) +endif + +neat: clean +ifndef WINDOWS + rm -f $(GENERATED_FILES) +else + for %f in ($(subst /,\,$(GENERATED_FILES))) if exist %f del /Q /F %f +endif diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/aes.c b/component/common/network/ssl/mbedtls-3.1.0/library/aes.c new file mode 100644 index 00000000..4afc3c48 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/aes.c @@ -0,0 +1,2171 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) +#define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = MBEDTLS_BYTE_0( x ^ XTIME( x ) ); + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = MBEDTLS_BYTE_0( XTIME( x ) ); + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y; y = MBEDTLS_BYTE_0( ( y << 1 ) | ( y >> 7 ) ); + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = MBEDTLS_BYTE_0( XTIME( x ) ); + z = MBEDTLS_BYTE_0( y ^ x ); + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + AES_VALIDATE( ctx != NULL ); + + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + RK[i] = MBEDTLS_GET_UINT32_LE( key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[3] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[3] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[3] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[3] ) ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[5] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[5] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[5] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[5] ) ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[7] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[7] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[7] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[7] ) ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( RK[11] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( RK[11] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( RK[11] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( RK[11] ) ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = AES_RT0( FSb[ MBEDTLS_BYTE_0( *SK ) ] ) ^ + AES_RT1( FSb[ MBEDTLS_BYTE_1( *SK ) ] ) ^ + AES_RT2( FSb[ MBEDTLS_BYTE_2( *SK ) ] ) ^ + AES_RT3( FSb[ MBEDTLS_BYTE_3( *SK ) ] ); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y0 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y1 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y2 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y3 ) ); \ + \ + (X1) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y1 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y2 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y3 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y0 ) ); \ + \ + (X2) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y2 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y3 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y0 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y1 ) ); \ + \ + (X3) = *RK++ ^ AES_FT0( MBEDTLS_BYTE_0( Y3 ) ) ^ \ + AES_FT1( MBEDTLS_BYTE_1( Y0 ) ) ^ \ + AES_FT2( MBEDTLS_BYTE_2( Y1 ) ) ^ \ + AES_FT3( MBEDTLS_BYTE_3( Y2 ) ); \ + } while( 0 ) + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y0 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y3 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y2 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y1 ) ); \ + \ + (X1) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y1 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y0 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y3 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y2 ) ); \ + \ + (X2) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y2 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y1 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y0 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y3 ) ); \ + \ + (X3) = *RK++ ^ AES_RT0( MBEDTLS_BYTE_0( Y3 ) ) ^ \ + AES_RT1( MBEDTLS_BYTE_1( Y2 ) ) ^ \ + AES_RT2( MBEDTLS_BYTE_2( Y1 ) ) ^ \ + AES_RT3( MBEDTLS_BYTE_3( Y0 ) ); \ + } while( 0 ) + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + t.X[0] = MBEDTLS_GET_UINT32_LE( input, 0 ); t.X[0] ^= *RK++; + t.X[1] = MBEDTLS_GET_UINT32_LE( input, 4 ); t.X[1] ^= *RK++; + t.X[2] = MBEDTLS_GET_UINT32_LE( input, 8 ); t.X[2] ^= *RK++; + t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[0] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[1] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[2] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) FSb[ MBEDTLS_BYTE_0( t.Y[3] ) ] ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] << 8 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^ + ( (uint32_t) FSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 ); + + MBEDTLS_PUT_UINT32_LE( t.X[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( t.X[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( t.X[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + t.X[0] = MBEDTLS_GET_UINT32_LE( input, 0 ); t.X[0] ^= *RK++; + t.X[1] = MBEDTLS_GET_UINT32_LE( input, 4 ); t.X[1] ^= *RK++; + t.X[2] = MBEDTLS_GET_UINT32_LE( input, 8 ); t.X[2] ^= *RK++; + t.X[3] = MBEDTLS_GET_UINT32_LE( input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[0] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[3] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[2] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[1] ) ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[1] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[0] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[3] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[2] ) ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[2] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[1] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[0] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[3] ) ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) RSb[ MBEDTLS_BYTE_0( t.Y[3] ) ] ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_1( t.Y[2] ) ] << 8 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_2( t.Y[1] ) ] << 16 ) ^ + ( (uint32_t) RSb[ MBEDTLS_BYTE_3( t.Y[0] ) ] << 24 ); + + MBEDTLS_PUT_UINT32_LE( t.X[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( t.X[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( t.X[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_platform_zeroize( &t, sizeof( t ) ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace > 0) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace > 0 ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + ret = mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + ret = mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + if( ret != 0 ) + goto exit; + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + a = MBEDTLS_GET_UINT64_LE( x, 0 ); + b = MBEDTLS_GET_UINT64_LE( x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + MBEDTLS_PUT_UINT64_LE( ra, r, 0 ); + MBEDTLS_PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( data_unit != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + /* Data units must be at least 16 bytes long. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + ret = 0; + +exit: + return( ret ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char c; + unsigned char ov[17]; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + while( length-- ) + { + memcpy( ov, iv, 16 ); + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( iv_off != NULL ); + AES_VALIDATE_RET( iv != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *iv_off; + + if( n > 15 ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + AES_VALIDATE_RET( ctx != NULL ); + AES_VALIDATE_RET( nc_off != NULL ); + AES_VALIDATE_RET( nonce_counter != NULL ); + AES_VALIDATE_RET( stream_block != NULL ); + AES_VALIDATE_RET( input != NULL ); + AES_VALIDATE_RET( output != NULL ); + + n = *nc_off; + + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + if( ret != 0 ) + goto exit; + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_tests = aes_test_cfb128_pt; + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3u (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ctr_ct[u], len ); + aes_tests = aes_test_ctr_pt[u]; + } + else + { + memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/aesni.c b/component/common/network/ssl/mbedtls-3.1.0/library/aesni.c new file mode 100644 index 00000000..be226c9c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/aesni.c @@ -0,0 +1,464 @@ +/* + * AES-NI support functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set + * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ + */ + +#include "common.h" + +#if defined(MBEDTLS_AESNI_C) + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#warning "MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code." +#endif +#endif + +#include "aesni.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +/* + * AES-NI support detection routine + */ +int mbedtls_aesni_has_support( unsigned int what ) +{ + static int done = 0; + static unsigned int c = 0; + + if( ! done ) + { + asm( "movl $1, %%eax \n\t" + "cpuid \n\t" + : "=c" (c) + : + : "eax", "ebx", "edx" ); + done = 1; + } + + return( ( c & what ) != 0 ); +} + +/* + * Binutils needs to be at least 2.19 to support AES-NI instructions. + * Unfortunately, a lot of users have a lower version now (2014-04). + * Emit bytecode directly in order to support "old" version of gas. + * + * Opcodes from the Intel architecture reference manual, vol. 3. + * We always use registers, so we don't need prefixes for memory operands. + * Operand macros are in gas order (src, dst) as opposed to Intel order + * (dst, src) in order to blend better into the surrounding assembly code. + */ +#define AESDEC ".byte 0x66,0x0F,0x38,0xDE," +#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," +#define AESENC ".byte 0x66,0x0F,0x38,0xDC," +#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," +#define AESIMC ".byte 0x66,0x0F,0x38,0xDB," +#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," +#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," + +#define xmm0_xmm0 "0xC0" +#define xmm0_xmm1 "0xC8" +#define xmm0_xmm2 "0xD0" +#define xmm0_xmm3 "0xD8" +#define xmm0_xmm4 "0xE0" +#define xmm1_xmm0 "0xC1" +#define xmm1_xmm2 "0xD1" + +/* + * AES-NI AES-ECB block en(de)cryption + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + asm( "movdqu (%3), %%xmm0 \n\t" // load input + "movdqu (%1), %%xmm1 \n\t" // load round key 0 + "pxor %%xmm1, %%xmm0 \n\t" // round 0 + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // normal rounds = nr - 1 + "test %2, %2 \n\t" // mode? + "jz 2f \n\t" // 0 = decrypt + + "1: \n\t" // encryption loop + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" // point to next round key + "subl $1, %0 \n\t" // loop + "jnz 1b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESENCLAST xmm1_xmm0 "\n\t" // last round + "jmp 3f \n\t" + + "2: \n\t" // decryption loop + "movdqu (%1), %%xmm1 \n\t" + AESDEC xmm1_xmm0 "\n\t" // do round + "add $16, %1 \n\t" + "subl $1, %0 \n\t" + "jnz 2b \n\t" + "movdqu (%1), %%xmm1 \n\t" // load round key + AESDECLAST xmm1_xmm0 "\n\t" // last round + + "3: \n\t" + "movdqu %%xmm0, (%4) \n\t" // export output + : + : "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output) + : "memory", "cc", "xmm0", "xmm1" ); + + + return( 0 ); +} + +/* + * GCM multiplication: c = a times b in GF(2^128) + * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ) +{ + unsigned char aa[16], bb[16], cc[16]; + size_t i; + + /* The inputs are in big-endian order, so byte-reverse them */ + for( i = 0; i < 16; i++ ) + { + aa[i] = a[15 - i]; + bb[i] = b[15 - i]; + } + + asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 + "movdqu (%1), %%xmm1 \n\t" // b1:b0 + + /* + * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 + * using [CLMUL-WP] algorithm 1 (p. 13). + */ + "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 + "movdqa %%xmm1, %%xmm3 \n\t" // same + "movdqa %%xmm1, %%xmm4 \n\t" // same + PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 + PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 + PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 + PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 + "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 + "movdqa %%xmm4, %%xmm3 \n\t" // same + "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 + "pslldq $8, %%xmm3 \n\t" // e0+f0:0 + "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 + "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 + + /* + * Now shift the result one bit to the left, + * taking advantage of [CLMUL-WP] eq 27 (p. 20) + */ + "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 + "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 + "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 + "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 + "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 + "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 + "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 + "pslldq $8, %%xmm3 \n\t" // r0>>63:0 + "pslldq $8, %%xmm4 \n\t" // r2>>63:0 + "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 + "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 + "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 + "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 + + /* + * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 + * using [CLMUL-WP] algorithm 5 (p. 20). + * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). + */ + /* Step 2 (1) */ + "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 + "movdqa %%xmm1, %%xmm4 \n\t" // same + "movdqa %%xmm1, %%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a + "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b + "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c + + /* Step 2 (2) */ + "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b + "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c + "pslldq $8, %%xmm3 \n\t" // a+b+c:0 + "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 + + /* Steps 3 and 4 */ + "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' + "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' + "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' + "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' + "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' + // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing + // bits carried from d. Now get those\t bits back in. + "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 + "movdqa %%xmm1,%%xmm4 \n\t" // same + "movdqa %%xmm1,%%xmm5 \n\t" // same + "psllq $63, %%xmm3 \n\t" // d<<63:stuff + "psllq $62, %%xmm4 \n\t" // d<<62:stuff + "psllq $57, %%xmm5 \n\t" // d<<57:stuff + "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff + "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff + "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d + "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 + "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 + "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 + + "movdqu %%xmm0, (%2) \n\t" // done + : + : "r" (aa), "r" (bb), "r" (cc) + : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); + + /* Now byte-reverse the outputs */ + for( i = 0; i < 16; i++ ) + c[i] = cc[15 - i]; + + return; +} + +/* + * Compute decryption round keys from encryption round keys + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, int nr ) +{ + unsigned char *ik = invkey; + const unsigned char *fk = fwdkey + 16 * nr; + + memcpy( ik, fk, 16 ); + + for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) + asm( "movdqu (%0), %%xmm0 \n\t" + AESIMC xmm0_xmm0 "\n\t" + "movdqu %%xmm0, (%1) \n\t" + : + : "r" (fk), "r" (ik) + : "memory", "xmm0" ); + + memcpy( ik, fk, 16 ); +} + +/* + * Key expansion, 128-bit case + */ +static void aesni_setkey_enc_128( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key + "movdqu %%xmm0, (%0) \n\t" // as round key 0 + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next round key. + * + * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff + * with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r7:r6:r5:r4 + * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 + "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm1 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! + "add $16, %0 \n\t" // point to next round key + "movdqu %%xmm0, (%0) \n\t" // write it + "ret \n\t" + + /* Main "loop" */ + "2: \n\t" + AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" + AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 192-bit case + */ +static void aesni_setkey_enc_192( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movq 16(%1), %%xmm1 \n\t" + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next 6 quarter-keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 + * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. + * + * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 + * and those are written to the round key buffer. + */ + "1: \n\t" + "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X + "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 + "pslldq $4, %%xmm0 \n\t" // etc + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 + "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 + "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 + "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 + "movq %%xmm1, (%0) \n\t" + "add $8, %0 \n\t" + "ret \n\t" + + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" + + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, 256-bit case + */ +static void aesni_setkey_enc_256( unsigned char *rk, + const unsigned char *key ) +{ + asm( "movdqu (%1), %%xmm0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + "add $16, %0 \n\t" + "movdqu 16(%1), %%xmm1 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "jmp 2f \n\t" // skip auxiliary routine + + /* + * Finish generating the next two round keys. + * + * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and + * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON + * + * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 + * and those have been written to the output buffer. + */ + "1: \n\t" + "pshufd $0xff, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm0, %%xmm2 \n\t" + "pslldq $4, %%xmm0 \n\t" + "pxor %%xmm2, %%xmm0 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm0, (%0) \n\t" + + /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) + * and proceed to generate next round key from there */ + AESKEYGENA xmm0_xmm2 ",0x00 \n\t" + "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm1, %%xmm2 \n\t" + "pslldq $4, %%xmm1 \n\t" + "pxor %%xmm2, %%xmm1 \n\t" + "add $16, %0 \n\t" + "movdqu %%xmm1, (%0) \n\t" + "ret \n\t" + + /* + * Main "loop" - Generating one more key than necessary, + * see definition of mbedtls_aes_context.buf + */ + "2: \n\t" + AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" + AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" + : + : "r" (rk), "r" (key) + : "memory", "cc", "0" ); +} + +/* + * Key expansion, wrapper + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ) +{ + switch( bits ) + { + case 128: aesni_setkey_enc_128( rk, key ); break; + case 192: aesni_setkey_enc_192( rk, key ); break; + case 256: aesni_setkey_enc_256( rk, key ); break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/aesni.h b/component/common/network/ssl/mbedtls-3.1.0/library/aesni.h new file mode 100644 index 00000000..3359cfe9 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/aesni.h @@ -0,0 +1,132 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + +#define MBEDTLS_AESNI_AES 0x02000000u +#define MBEDTLS_AESNI_CLMUL 0x00000002u + +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \ + ( defined(__amd64__) || defined(__x86_64__) ) && \ + ! defined(MBEDTLS_HAVE_X86_64) +#define MBEDTLS_HAVE_X86_64 +#endif + +#if defined(MBEDTLS_HAVE_X86_64) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal function to detect the AES-NI feature in CPUs. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param what The feature to detect + * (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL) + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int mbedtls_aesni_has_support( unsigned int what ); + +/** + * \brief Internal AES-NI AES-ECB block encryption and decryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 on success (cannot fail) + */ +int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal GCM multiplication: c = a * b in GF(2^128) + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param c Result + * \param a First operand + * \param b Second operand + * + * \note Both operands and result are bit strings interpreted as + * elements of GF(2^128) as per the GCM spec. + */ +void mbedtls_aesni_gcm_mult( unsigned char c[16], + const unsigned char a[16], + const unsigned char b[16] ); + +/** + * \brief Internal round key inversion. This function computes + * decryption round keys from the encryption round keys. + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param invkey Round keys for the equivalent inverse cipher + * \param fwdkey Original round keys (for encryption) + * \param nr Number of rounds (that is, number of round keys minus one) + */ +void mbedtls_aesni_inverse_key( unsigned char *invkey, + const unsigned char *fwdkey, + int nr ); + +/** + * \brief Internal key expansion for encryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param rk Destination buffer where the round keys are written + * \param key Encryption key + * \param bits Key size in bits (must be 128, 192 or 256) + * + * \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH + */ +int mbedtls_aesni_setkey_enc( unsigned char *rk, + const unsigned char *key, + size_t bits ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_HAVE_X86_64 */ + +#endif /* MBEDTLS_AESNI_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/aria.c b/component/common/network/ssl/mbedtls-3.1.0/library/aria.c new file mode 100644 index 00000000..bc05c4a3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/aria.c @@ -0,0 +1,1058 @@ +/* + * ARIA implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * This implementation is based on the following standards: + * [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf + * [2] https://tools.ietf.org/html/rfc5794 + */ + +#include "common.h" + +#if defined(MBEDTLS_ARIA_C) + +#include "mbedtls/aria.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_ARIA_ALT) + +#include "mbedtls/platform_util.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define ARIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ) +#define ARIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes + * + * This is submatrix P1 in [1] Appendix B.1 + * + * Common compilers fail to translate this to minimal number of instructions, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev16 available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P1 aria_p1 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p1( uint32_t x ) +{ + uint32_t r; + __asm( "rev16 r, x" ); + return( r ); +} +#define ARIA_P1 aria_p1 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +/* I couldn't find an Intel equivalent of rev16, so two instructions */ +#define ARIA_P1(x) ARIA_P2( ARIA_P3( x ) ) +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P1) +#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8)) +#endif + +/* + * modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits + * + * This is submatrix P2 in [1] Appendix B.1 + * + * Common compilers will translate this to a single instruction. + */ +#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16)) + +/* + * modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness + * + * This is submatrix P3 in [1] Appendix B.1 + * + * Some compilers fail to translate this to a single instruction, + * so let's provide asm versions for common platforms with C fallback. + */ +#if defined(MBEDTLS_HAVE_ASM) +#if defined(__arm__) /* rev available from v6 up */ +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) && \ + __ARM_ARCH >= 6 +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev %0, %1" : "=l" (r) : "l" (x) ); + return( r ); +} +#define ARIA_P3 aria_p3 +#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \ + ( __TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3 ) +static inline uint32_t aria_p3( uint32_t x ) +{ + uint32_t r; + __asm( "rev r, x" ); + return( r ); +} +#define ARIA_P3 aria_p3 +#endif +#endif /* arm */ +#if defined(__GNUC__) && \ + defined(__i386__) || defined(__amd64__) || defined( __x86_64__) +static inline uint32_t aria_p3( uint32_t x ) +{ + __asm( "bswap %0" : "=r" (x) : "0" (x) ); + return( x ); +} +#define ARIA_P3 aria_p3 +#endif /* x86 gnuc */ +#endif /* MBEDTLS_HAVE_ASM && GNUC */ +#if !defined(ARIA_P3) +#define ARIA_P3(x) ARIA_P2( ARIA_P1 ( x ) ) +#endif + +/* + * ARIA Affine Transform + * (a, b, c, d) = state in/out + * + * If we denote the first byte of input by 0, ..., the last byte by f, + * then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef. + * + * Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple + * rearrangements on adjacent pairs, output is: + * + * a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe + * = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd + * b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd + * = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc + * c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe + * = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc + * d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef + * = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef + * + * Note: another presentation of the A transform can be found as the first + * half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4. + * The implementation below uses only P1 and P2 as they are sufficient. + */ +static inline void aria_a( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d ) +{ + uint32_t ta, tb, tc; + ta = *b; // 4567 + *b = *a; // 0123 + *a = ARIA_P2( ta ); // 6745 + tb = ARIA_P2( *d ); // efcd + *d = ARIA_P1( *c ); // 98ba + *c = ARIA_P1( tb ); // fedc + ta ^= *d; // 4567+98ba + tc = ARIA_P2( *b ); // 2301 + ta = ARIA_P1( ta ) ^ tc ^ *c; // 2301+5476+89ab+fedc + tb ^= ARIA_P2( *d ); // ba98+efcd + tc ^= ARIA_P1( *a ); // 2301+7654 + *b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT + tb = ARIA_P2( tb ) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc + *a ^= ARIA_P1( tb ); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT + ta = ARIA_P2( ta ); // 0123+7654+ab89+dcfe + *d ^= ARIA_P1( ta ) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT + tc = ARIA_P2( tc ); // 0123+5476 + *c ^= ARIA_P1( tc ) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT +} + +/* + * ARIA Substitution Layer SL1 / SL2 + * (a, b, c, d) = state in/out + * (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below) + * + * By passing sb1, sb2, is1, is2 as S-Boxes you get SL1 + * By passing is1, is2, sb1, sb2 as S-Boxes you get SL2 + */ +static inline void aria_sl( uint32_t *a, uint32_t *b, + uint32_t *c, uint32_t *d, + const uint8_t sa[256], const uint8_t sb[256], + const uint8_t sc[256], const uint8_t sd[256] ) +{ + *a = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *a ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *a ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *a ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *a ) ]) << 24); + *b = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *b ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *b ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *b ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *b ) ]) << 24); + *c = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *c ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *c ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *c ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *c ) ]) << 24); + *d = ( (uint32_t) sa[ MBEDTLS_BYTE_0( *d ) ] ) ^ + (((uint32_t) sb[ MBEDTLS_BYTE_1( *d ) ]) << 8) ^ + (((uint32_t) sc[ MBEDTLS_BYTE_2( *d ) ]) << 16) ^ + (((uint32_t) sd[ MBEDTLS_BYTE_3( *d ) ]) << 24); +} + +/* + * S-Boxes + */ +static const uint8_t aria_sb1[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, + 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, + 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, + 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, + 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, + 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, + 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, + 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, + 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, + 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, + 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, + 0xB0, 0x54, 0xBB, 0x16 +}; + +static const uint8_t aria_sb2[256] = +{ + 0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46, + 0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B, + 0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B, + 0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB, + 0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA, + 0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91, + 0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38, + 0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53, + 0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74, + 0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26, + 0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD, + 0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC, + 0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E, + 0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A, + 0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5, + 0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8, + 0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24, + 0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F, + 0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33, + 0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D, + 0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A, + 0xAF, 0xBA, 0xB5, 0x81 +}; + +static const uint8_t aria_is1[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, + 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32, + 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, + 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50, + 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, + 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41, + 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, + 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B, + 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, + 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D, + 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, + 0x55, 0x21, 0x0C, 0x7D +}; + +static const uint8_t aria_is2[256] = +{ + 0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1, + 0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3, + 0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89, + 0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D, + 0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98, + 0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58, + 0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F, + 0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE, + 0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23, + 0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19, + 0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55, + 0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A, + 0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE, + 0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0, + 0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6, + 0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5, + 0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13, + 0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73, + 0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94, + 0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3, + 0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33, + 0x03, 0xA2, 0xAC, 0x60 +}; + +/* + * Helper for key schedule: r = FO( p, k ) ^ x + */ +static void aria_fo_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Helper for key schedule: r = FE( p, k ) ^ x + */ +static void aria_fe_xor( uint32_t r[4], const uint32_t p[4], + const uint32_t k[4], const uint32_t x[4] ) +{ + uint32_t a, b, c, d; + + a = p[0] ^ k[0]; + b = p[1] ^ k[1]; + c = p[2] ^ k[2]; + d = p[3] ^ k[3]; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + aria_a( &a, &b, &c, &d ); + + r[0] = a ^ x[0]; + r[1] = b ^ x[1]; + r[2] = c ^ x[2]; + r[3] = d ^ x[3]; +} + +/* + * Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup. + * + * We chose to store bytes into 32-bit words in little-endian format (see + * MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse + * bytes here. + */ +static void aria_rot128( uint32_t r[4], const uint32_t a[4], + const uint32_t b[4], uint8_t n ) +{ + uint8_t i, j; + uint32_t t, u; + + const uint8_t n1 = n % 32; // bit offset + const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset + + j = ( n / 32 ) % 4; // initial word offset + t = ARIA_P3( b[j] ); // big endian + for( i = 0; i < 4; i++ ) + { + j = ( j + 1 ) % 4; // get next word, big endian + u = ARIA_P3( b[j] ); + t <<= n1; // rotate + t |= u >> n2; + t = ARIA_P3( t ); // back to little endian + r[i] = a[i] ^ t; // store + t = u; // move to next word + } +} + +/* + * Set encryption key + */ +int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + /* round constant masks */ + const uint32_t rc[3][4] = + { + { 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA }, + { 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF }, + { 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 } + }; + + int i; + uint32_t w[4][4], *w2; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + if( keybits != 128 && keybits != 192 && keybits != 256 ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + /* Copy key to W0 (and potential remainder to W1) */ + w[0][0] = MBEDTLS_GET_UINT32_LE( key, 0 ); + w[0][1] = MBEDTLS_GET_UINT32_LE( key, 4 ); + w[0][2] = MBEDTLS_GET_UINT32_LE( key, 8 ); + w[0][3] = MBEDTLS_GET_UINT32_LE( key, 12 ); + + memset( w[1], 0, 16 ); + if( keybits >= 192 ) + { + w[1][0] = MBEDTLS_GET_UINT32_LE( key, 16 ); // 192 bit key + w[1][1] = MBEDTLS_GET_UINT32_LE( key, 20 ); + } + if( keybits == 256 ) + { + w[1][2] = MBEDTLS_GET_UINT32_LE( key, 24 ); // 256 bit key + w[1][3] = MBEDTLS_GET_UINT32_LE( key, 28 ); + } + + i = ( keybits - 128 ) >> 6; // index: 0, 1, 2 + ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16 + + aria_fo_xor( w[1], w[0], rc[i], w[1] ); // W1 = FO(W0, CK1) ^ KR + i = i < 2 ? i + 1 : 0; + aria_fe_xor( w[2], w[1], rc[i], w[0] ); // W2 = FE(W1, CK2) ^ W0 + i = i < 2 ? i + 1 : 0; + aria_fo_xor( w[3], w[2], rc[i], w[1] ); // W3 = FO(W2, CK3) ^ W1 + + for( i = 0; i < 4; i++ ) // create round keys + { + w2 = w[(i + 1) & 3]; + aria_rot128( ctx->rk[i ], w[i], w2, 128 - 19 ); + aria_rot128( ctx->rk[i + 4], w[i], w2, 128 - 31 ); + aria_rot128( ctx->rk[i + 8], w[i], w2, 61 ); + aria_rot128( ctx->rk[i + 12], w[i], w2, 31 ); + } + aria_rot128( ctx->rk[16], w[0], w[1], 19 ); + + /* w holds enough info to reconstruct the round keys */ + mbedtls_platform_zeroize( w, sizeof( w ) ); + + return( 0 ); +} + +/* + * Set decryption key + */ +int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx, + const unsigned char *key, unsigned int keybits ) +{ + int i, j, k, ret; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( key != NULL ); + + ret = mbedtls_aria_setkey_enc( ctx, key, keybits ); + if( ret != 0 ) + return( ret ); + + /* flip the order of round keys */ + for( i = 0, j = ctx->nr; i < j; i++, j-- ) + { + for( k = 0; k < 4; k++ ) + { + uint32_t t = ctx->rk[i][k]; + ctx->rk[i][k] = ctx->rk[j][k]; + ctx->rk[j][k] = t; + } + } + + /* apply affine transform to middle keys */ + for( i = 1; i < ctx->nr; i++ ) + { + aria_a( &ctx->rk[i][0], &ctx->rk[i][1], + &ctx->rk[i][2], &ctx->rk[i][3] ); + } + + return( 0 ); +} + +/* + * Encrypt a block + */ +int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx, + const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] ) +{ + int i; + + uint32_t a, b, c, d; + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( input != NULL ); + ARIA_VALIDATE_RET( output != NULL ); + + a = MBEDTLS_GET_UINT32_LE( input, 0 ); + b = MBEDTLS_GET_UINT32_LE( input, 4 ); + c = MBEDTLS_GET_UINT32_LE( input, 8 ); + d = MBEDTLS_GET_UINT32_LE( input, 12 ); + + i = 0; + while( 1 ) + { + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2 ); + aria_a( &a, &b, &c, &d ); + + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + i++; + + aria_sl( &a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2 ); + if( i >= ctx->nr ) + break; + aria_a( &a, &b, &c, &d ); + } + + /* final key mixing */ + a ^= ctx->rk[i][0]; + b ^= ctx->rk[i][1]; + c ^= ctx->rk[i][2]; + d ^= ctx->rk[i][3]; + + MBEDTLS_PUT_UINT32_LE( a, output, 0 ); + MBEDTLS_PUT_UINT32_LE( b, output, 4 ); + MBEDTLS_PUT_UINT32_LE( c, output, 8 ); + MBEDTLS_PUT_UINT32_LE( d, output, 12 ); + + return( 0 ); +} + +/* Initialize context */ +void mbedtls_aria_init( mbedtls_aria_context *ctx ) +{ + ARIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_aria_context ) ); +} + +/* Clear context */ +void mbedtls_aria_free( mbedtls_aria_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aria_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * ARIA-CBC buffer encryption/decryption + */ +int mbedtls_aria_crypt_cbc( mbedtls_aria_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE]; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + + if( length % MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_ARIA_BLOCKSIZE ); + mbedtls_aria_crypt_ecb( ctx, input, output ); + + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_ARIA_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aria_crypt_ecb( ctx, output, output ); + memcpy( iv, output, MBEDTLS_ARIA_BLOCKSIZE ); + + input += MBEDTLS_ARIA_BLOCKSIZE; + output += MBEDTLS_ARIA_BLOCKSIZE; + length -= MBEDTLS_ARIA_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * ARIA-CFB128 buffer encryption/decryption + */ +int mbedtls_aria_crypt_cfb128( mbedtls_aria_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( mode == MBEDTLS_ARIA_ENCRYPT || + mode == MBEDTLS_ARIA_DECRYPT ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( iv != NULL ); + ARIA_VALIDATE_RET( iv_off != NULL ); + + n = *iv_off; + + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_ARIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + c = *input++; + *output++ = c ^ iv[n]; + iv[n] = c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aria_crypt_ecb( ctx, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * ARIA-CTR buffer encryption/decryption + */ +int mbedtls_aria_crypt_ctr( mbedtls_aria_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + + ARIA_VALIDATE_RET( ctx != NULL ); + ARIA_VALIDATE_RET( length == 0 || input != NULL ); + ARIA_VALIDATE_RET( length == 0 || output != NULL ); + ARIA_VALIDATE_RET( nonce_counter != NULL ); + ARIA_VALIDATE_RET( stream_block != NULL ); + ARIA_VALIDATE_RET( nc_off != NULL ); + + n = *nc_off; + /* An overly large value of n can lead to an unlimited + * buffer overflow. Therefore, guard against this + * outside of parameter validation. */ + if( n >= MBEDTLS_ARIA_BLOCKSIZE ) + return( MBEDTLS_ERR_ARIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aria_crypt_ecb( ctx, nonce_counter, + stream_block ); + + for( i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_ARIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Basic ARIA ECB test vectors from RFC 5794 + */ +static const uint8_t aria_test1_ecb_key[32] = // test key +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit +}; + +static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all + 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes +}; + +static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext +{ + { 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit + 0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 }, + { 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit + 0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 }, + { 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit + 0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC } +}; + +/* + * Mode tests from "Test Vectors for ARIA" Version 1.0 + * http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf + */ +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) +static const uint8_t aria_test2_key[32] = +{ + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit +}; + +static const uint8_t aria_test2_pt[48] = +{ + 0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all + 0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb, + 0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc, + 0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd, + 0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa, + 0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb, +}; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB)) +static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] = +{ + 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB + 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV +}; +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext +{ + { 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key + 0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34, + 0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64, + 0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38, + 0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c, + 0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 }, + { 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key + 0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f, + 0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1, + 0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5, + 0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92, + 0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e }, + { 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key + 0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab, + 0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef, + 0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52, + 0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5, + 0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext +{ + { 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key + 0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00, + 0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a, + 0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01, + 0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96, + 0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b }, + { 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key + 0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c, + 0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94, + 0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59, + 0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86, + 0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b }, + { 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key + 0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35, + 0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70, + 0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa, + 0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c, + 0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext +{ + { 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key + 0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1, + 0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1, + 0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f, + 0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71, + 0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 }, + { 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key + 0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce, + 0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde, + 0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79, + 0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce, + 0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf }, + { 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key + 0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2, + 0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89, + 0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f, + 0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7, + 0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#define ARIA_SELF_TEST_IF_FAIL \ + { \ + if( verbose ) \ + mbedtls_printf( "failed\n" ); \ + goto exit; \ + } else { \ + if( verbose ) \ + mbedtls_printf( "passed\n" ); \ + } + +/* + * Checkup routine + */ +int mbedtls_aria_self_test( int verbose ) +{ + int i; + uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE]; + mbedtls_aria_context ctx; + int ret = 1; + +#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR)) + size_t j; +#endif + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \ + defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_CTR)) + uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE]; +#endif + + mbedtls_aria_init( &ctx ); + + /* + * Test set 1 + */ + for( i = 0; i < 3; i++ ) + { + /* test ECB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_pt, blk ); + if( memcmp( blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* test ECB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-ECB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test1_ecb_key, 128 + 64 * i ); + mbedtls_aria_crypt_ecb( &ctx, aria_test1_ecb_ct[i], blk ); + if( memcmp( blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + + /* + * Test set 2 + */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) + for( i = 0; i < 3; i++ ) + { + /* Test CBC encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cbc_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CBC decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CBC-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_dec( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + mbedtls_aria_crypt_cbc( &ctx, MBEDTLS_ARIA_DECRYPT, 48, iv, + aria_test2_cbc_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); + +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + for( i = 0; i < 3; i++ ) + { + /* Test CFB encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_cfb_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CFB decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CFB-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memcpy( iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE ); + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_cfb128( &ctx, MBEDTLS_ARIA_DECRYPT, 48, &j, + iv, aria_test2_cfb_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + for( i = 0; i < 3; i++ ) + { + /* Test CTR encryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (enc): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0x55, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_pt, buf ); + if( memcmp( buf, aria_test2_ctr_ct[i], 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + + /* Test CTR decryption */ + if( verbose ) + mbedtls_printf( " ARIA-CTR-%d (dec): ", 128 + 64 * i ); + mbedtls_aria_setkey_enc( &ctx, aria_test2_key, 128 + 64 * i ); + memset( iv, 0, MBEDTLS_ARIA_BLOCKSIZE ); // IV = 0 + memset( buf, 0xAA, sizeof( buf ) ); + j = 0; + mbedtls_aria_crypt_ctr( &ctx, 48, &j, iv, blk, + aria_test2_ctr_ct[i], buf ); + if( memcmp( buf, aria_test2_pt, 48 ) != 0 ) + ARIA_SELF_TEST_IF_FAIL; + } + if( verbose ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + mbedtls_aria_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARIA_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/asn1parse.c b/component/common/network/ssl/mbedtls-3.1.0/library/asn1parse.c new file mode 100644 index 00000000..83c7c58a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/asn1parse.c @@ -0,0 +1,481 @@ +/* + * Generic ASN.1 parsing + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +static int asn1_get_tagged_int( unsigned char **p, + const unsigned char *end, + int tag, int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 ) + return( ret ); + + /* + * len==0 is malformed (0 must be represented as 020100 for INTEGER, + * or 0A0100 for ENUMERATED tags + */ + if( len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + /* This is a cryptography library. Reject negative integers. */ + if( ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Skip leading zeros. */ + while( len > 0 && **p == 0 ) + { + ++( *p ); + --len; + } + + /* Reject integers that don't fit in an int. This code assumes that + * the int type has no padding bit. */ + if( len > sizeof( int ) ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + if( len == sizeof( int ) && ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) ); +} + +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Traverse an ASN.1 "SEQUENCE OF " + * and call a callback for each entry found. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char *start, size_t len ), + void *ctx ) +{ + int ret; + size_t len; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( ret ); + } + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + unsigned char const tag = *(*p)++; + + if( ( tag & tag_must_mask ) != tag_must_val ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 ) + return( ret ); + + if( ( tag & tag_may_mask ) == tag_may_val ) + { + if( cb != NULL ) + { + ret = cb( ctx, tag, *p, len ); + if( ret != 0 ) + return( ret ); + } + } + + *p += len; + } + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( *len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + --( *len ); + + if( **p != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + ++( *p ); + + return( 0 ); +} + +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) +{ + while( seq != NULL ) + { + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} + +typedef struct +{ + int tag; + mbedtls_asn1_sequence *cur; +} asn1_get_sequence_of_cb_ctx_t; + +static int asn1_get_sequence_of_cb( void *ctx, + int tag, + unsigned char *start, + size_t len ) +{ + asn1_get_sequence_of_cb_ctx_t *cb_ctx = + (asn1_get_sequence_of_cb_ctx_t *) ctx; + mbedtls_asn1_sequence *cur = + cb_ctx->cur; + + if( cur->buf.p != NULL ) + { + cur->next = + mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + cur->buf.p = start; + cur->buf.len = len; + cur->buf.tag = tag; + + cb_ctx->cur = cur; + return( 0 ); +} + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; + memset( cur, 0, sizeof( mbedtls_asn1_sequence ) ); + return( mbedtls_asn1_traverse_sequence_of( + p, end, 0xFF, tag, 0, 0, + asn1_get_sequence_of_cb, &cb_ctx ) ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/asn1write.c b/component/common/network/ssl/mbedtls-3.1.0/library/asn1write.c new file mode 100644 index 00000000..dc618541 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/asn1write.c @@ -0,0 +1,480 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, const unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = MBEDTLS_BYTE_0( len ); + *--(*p) = MBEDTLS_BYTE_1( len ); + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = MBEDTLS_BYTE_0( len ); + *--(*p) = MBEDTLS_BYTE_1( len ); + *--(*p) = MBEDTLS_BYTE_2( len ); + *--(*p) = 0x83; + return( 4 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + if( len <= 0xFFFFFFFF ) +#endif + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = MBEDTLS_BYTE_0( len ); + *--(*p) = MBEDTLS_BYTE_1( len ); + *--(*p) = MBEDTLS_BYTE_2( len ); + *--(*p) = MBEDTLS_BYTE_3( len ); + *--(*p) = 0x84; + return( 5 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif +} + +int mbedtls_asn1_write_tag( unsigned char **p, const unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, const unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, const unsigned char *start, const mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, const unsigned char *start ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, const unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, const unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, const unsigned char *start, int boolean ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +static int asn1_write_tagged_int( unsigned char **p, const unsigned char *start, int val, int tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + do + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + len += 1; + *--(*p) = val & 0xff; + val >>= 8; + } + while( val > 0 ); + + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, const unsigned char *start, int val ) +{ + return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) ); +} + +int mbedtls_asn1_write_enum( unsigned char **p, const unsigned char *start, int val ) +{ + return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) ); +} + +int mbedtls_asn1_write_tagged_string( unsigned char **p, const unsigned char *start, int tag, + const char *text, size_t text_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_utf8_string( unsigned char **p, const unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, const unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, const unsigned char *start, + const char *text, size_t text_len ) +{ + return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); +} + +int mbedtls_asn1_write_named_bitstring( unsigned char **p, + const unsigned char *start, + const unsigned char *buf, + size_t bits ) +{ + size_t unused_bits, byte_len; + const unsigned char *cur_byte; + unsigned char cur_byte_shifted; + unsigned char bit; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + /* + * Named bitstrings require that trailing 0s are excluded in the encoding + * of the bitstring. Trailing 0s are considered part of the 'unused' bits + * when encoding this value in the first content octet + */ + if( bits != 0 ) + { + cur_byte = buf + byte_len - 1; + cur_byte_shifted = *cur_byte >> unused_bits; + + for( ; ; ) + { + bit = cur_byte_shifted & 0x1; + cur_byte_shifted >>= 1; + + if( bit != 0 ) + break; + + bits--; + if( bits == 0 ) + break; + + if( bits % 8 == 0 ) + cur_byte_shifted = *--cur_byte; + } + } + + return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, const unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + size_t unused_bits, byte_len; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = byte_len + 1; + + /* Write the bitstring. Ensure the unused bits are zeroed */ + if( byte_len > 0 ) + { + byte_len--; + *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); + ( *p ) -= byte_len; + memcpy( *p, buf, byte_len ); + } + + /* Write unused bits */ + *--( *p ) = (unsigned char)unused_bits; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, const unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *asn1_find_named_data( + mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( + mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + if( val_len != 0 ) + { + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + } + + cur->next = *head; + *head = cur; + } + else if( val_len == 0 ) + { + mbedtls_free( cur->val.p ); + cur->val.p = NULL; + } + else if( cur->val.len != val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/base64.c b/component/common/network/ssl/mbedtls-3.1.0/library/base64.c new file mode 100644 index 00000000..83daa0bc --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/base64.c @@ -0,0 +1,277 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_BASE64_C) + +#include "mbedtls/base64.h" +#include "constant_time_internal.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) + & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) + & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( C3 & 0x3F ); + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) + & 0x3F ); + + if( ( i + 1 ) < slen ) + *p++ = mbedtls_ct_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F ); + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i; /* index in source */ + size_t n; /* number of digits or trailing = in source */ + uint32_t x; /* value accumulator */ + unsigned accumulated_digits = 0; + unsigned equals = 0; + int spaces_present = 0; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + spaces_present = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + spaces_present = 1; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( spaces_present ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' ) + { + if( ++equals > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + } + else + { + if( equals != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + if( mbedtls_ct_base64_dec_value( src[i] ) < 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + } + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= equals; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + equals = 0; + for( x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + x = x << 6; + if( *src == '=' ) + ++equals; + else + x |= mbedtls_ct_base64_dec_value( *src ); + + if( ++accumulated_digits == 4 ) + { + accumulated_digits = 0; + *p++ = MBEDTLS_BYTE_2( x ); + if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x ); + if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/bignum.c b/component/common/network/ssl/mbedtls-3.1.0/library/bignum.c new file mode 100644 index 00000000..8fcbf09f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/bignum.c @@ -0,0 +1,3074 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "bn_mul.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "constant_time_internal.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + MPI_VALIDATE( X != NULL ); + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + /* Actually resize up if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* Resize X to have exactly n limbs and set it to 0. */ +static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs ) +{ + if( limbs == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + else if( X->n == limbs ) + { + memset( X->p, 0, limbs * ciL ); + X->s = 1; + return( 0 ); + } + else + { + mbedtls_mpi_free( X ); + return( mbedtls_mpi_grow( X, limbs ) ); + } +} + +/* + * Copy the contents of Y into X. + * + * This function is not constant-time. Leading zeros in Y may be removed. + * + * Ensure that X does not shrink. This is not guaranteed by the public API, + * but some code in the bignum module relies on this property, for example + * in mbedtls_mpi_exp_mod(). + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + if( Y->n == 0 ) + { + if( X->n != 0 ) + { + X->s = 1; + memset( X->p, 0, X->n * ciL ); + } + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( X != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + MPI_VALIDATE_RET( X != NULL ); + + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j, slen, n; + int sign = 1; + mbedtls_mpi_uint d; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + if( s[0] == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + if( s[0] == '-' ) + { + ++s; + sign = -1; + } + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + } + + if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 ) + X->s = -1; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first. + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + unsigned char *x_ptr; + mbedtls_mpi_uint tmp = 0; + + for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) + { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *x_ptr; + } + + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } +#endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) +{ + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } +} + +/* + * Import X from unsigned binary data, little endian + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + + for( i = 0; i < buflen; i++ ) + X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3); + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + + /* Avoid calling `memcpy` with NULL source or destination argument, + * even if buflen is 0. */ + if( buflen != 0 ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Export X into unsigned binary data, little endian + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes = X->n * ciL; + size_t bytes_to_copy; + size_t i; + + if( stored_bytes < buflen ) + { + bytes_to_copy = stored_bytes; + } + else + { + bytes_to_copy = buflen; + + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + buf[i] = GET_BYTE( X, i ); + + if( stored_bytes < buflen ) + { + /* Write trailing 0 bytes */ + memset( buf + stored_bytes, 0, buflen - stored_bytes ); + } + + return( 0 ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + stored_bytes = X->n * ciL; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate l - r where l and r have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise). + * + * d may be aliased to l or r. + * + * \param n Number of limbs of \p d, \p l and \p r. + * \param[out] d The result of the subtraction. + * \param[in] l The left operand. + * \param[in] r The right operand. + * + * \return 1 if `l < r`. + * 0 if `l >= r`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *l, + const mbedtls_mpi_uint *r ) +{ + size_t i; + mbedtls_mpi_uint c = 0, t, z; + + for( i = 0; i < n; i++ ) + { + z = ( l[i] < c ); t = l[i] - c; + c = ( t < r[i] ) + z; d[i] = t - r[i]; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + mbedtls_mpi_uint carry; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) ); + + /* Set the high limbs of X to match A. Don't touch the lower limbs + * because X might be aliased to B, and we must not overwrite the + * significant digits of B. */ + if( A->n > n ) + memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL ); + if( X->n > A->n ) + memset( X->p + A->n, 0, ( X->n - A->n ) * ciL ); + + carry = mpi_sub_hlp( n, X->p, A->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + { + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + --X->p[n]; + } + + /* X should always be positive as a result of unsigned subtractions. */ + X->s = 1; + +cleanup: + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &B ) ); +} + +/** Helper for mbedtls_mpi multiplication. + * + * Add \p b * \p s to \p d. + * + * \param i The number of limbs of \p s. + * \param[in] s A bignum to multiply, of size \p i. + * It may overlap with \p d, but only if + * \p d <= \p s. + * Its leading limb must not be \c 0. + * \param[in,out] d The bignum to add to. + * It must be sufficiently large to store the + * result of the multiplication. This means + * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b + * is not known a priori. + * \param b A scalar to multiply. + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, + const mbedtls_mpi_uint *s, + mbedtls_mpi_uint *d, + mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + while( c != 0 ) + { + *d += c; c = ( *d < c ); d++; + } +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi TA, TB; + int result_is_zero = 0; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + if( i == 0 ) + result_is_zero = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + if( j == 0 ) + result_is_zero = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + /* If the result is 0, we don't shortcut the operation, which reduces + * but does not eliminate side channels leaking the zero-ness. We do + * need to take care to set the sign bit properly since the library does + * not fully support an MPI object with a value of 0 and s == -1. */ + if( result_is_zero ) + X->s = 1; + else + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + /* mpi_mul_hlp can't deal with a leading 0. */ + size_t n = A->n; + while( n > 0 && A->p[n - 1] == 0 ) + --n; + + /* The general method below doesn't work if n==0 or b==0. By chance + * calculating the result is trivial in those cases. */ + if( b == 0 || n == 0 ) + { + return( mbedtls_mpi_lset( X, 0 ) ); + } + + /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* In general, A * b requires 1 limb more than b. If + * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same + * number of limbs as A and the call to grow() is not required since + * copy() will take care of the growth if needed. However, experimentally, + * making the call to grow() unconditional causes slightly fewer + * calls to calloc() in ECP code, presumably because it reuses the + * same mpi for a while and this way the mpi is more likely to directly + * grow to its final size. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + mpi_mul_hlp( n, A->p, X->p, b - 1 ); + +cleanup: + return( ret ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + mbedtls_mpi_uint TP2[3]; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); + /* + * Avoid dynamic memory allocations for constant-size T2. + * + * T2 is used for comparison only and the 3 limbs are assigned explicitly, + * so nobody increase the size of the MPI and we're safe to use an on-stack + * buffer. + */ + T2.s = 1; + T2.n = sizeof( TP2 ) / sizeof( *TP2 ); + T2.p = TP2; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); + mbedtls_platform_zeroize( TP2, sizeof( TP2 ) ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + mpi_montmul( A, &U, N, mm, T ); +} + +/** + * Select an MPI from a table without leaking the index. + * + * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it + * reads the entire table in order to avoid leaking the value of idx to an + * attacker able to observe memory access patterns. + * + * \param[out] R Where to write the selected MPI. + * \param[in] T The table to read from. + * \param[in] T_size The number of elements in the table. + * \param[in] idx The index of the element to select; + * this must satisfy 0 <= idx < T_size. + * + * \return \c 0 on success, or a negative error code. + */ +static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( size_t i = 0; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i], + (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) ); + } + +cleanup: + return( ret ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *prec_RR ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || + mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) + return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + mbedtls_mpi_init( &WW ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + j = N->n + 1; + /* All W[i] and X must have at least N->n limbs for the mpi_montmul() + * and mpi_montred() calls later. Here we ensure that W[1] and X are + * large enough, and later we'll grow other W[i] to the same length. + * They must not be shrunk midway through this function! + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( prec_RR == NULL || prec_RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( prec_RR != NULL ) + memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + /* This should be a no-op because W[1] is already that large before + * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow + * in mpi_montmul() below, so let's make sure. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + /* Note that this is safe because W[1] always has at least N->n limbs + * (it grew above and was preserved by mbedtls_mpi_copy()). */ + mpi_montmul( &W[1], &RR, N, mm, &T ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) ); + mpi_montmul( X, &WW, N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + mbedtls_mpi_free( &WW ); + + if( prec_RR == NULL || prec_RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t lz, lzt; + mbedtls_mpi TA, TB; + + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + /* The loop below gives the correct result when A==0 but not when B==0. + * So have a special case for B==0. Leverage the fact that we just + * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test + * slightly more efficient than cmp_int(). */ + if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 ) + { + ret = mbedtls_mpi_copy( G, A ); + goto cleanup; + } + + if( lzt < lz ) + lz = lzt; + + TA.s = TB.s = 1; + + /* We mostly follow the procedure described in HAC 14.54, but with some + * minor differences: + * - Sequences of multiplications or divisions by 2 are grouped into a + * single shift operation. + * - The procedure in HAC assumes that 0 < TB <= TA. + * - The condition TB <= TA is not actually necessary for correctness. + * TA and TB have symmetric roles except for the loop termination + * condition, and the shifts at the beginning of the loop body + * remove any significance from the ordering of TA vs TB before + * the shifts. + * - If TA = 0, the loop goes through 0 iterations and the result is + * correctly TB. + * - The case TB = 0 was short-circuited above. + * + * For the correctness proof below, decompose the original values of + * A and B as + * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 + * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 + * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), + * and gcd(A',B') is odd or 0. + * + * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). + * The code maintains the following invariant: + * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) + */ + + /* Proof that the loop terminates: + * At each iteration, either the right-shift by 1 is made on a nonzero + * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases + * by at least 1, or the right-shift by 1 is made on zero and then + * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted + * since in that case TB is calculated from TB-TA with the condition TB>TA). + */ + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + /* Divisions by 2 preserve the invariant (I). */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, + * TA-TB is even so the division by 2 has an integer result. + * Invariant (I) is preserved since any odd divisor of both TA and TB + * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 + * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also + * divides TA. + */ + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + /* Note that one of TA or TB is still odd. */ + } + + /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. + * At the loop exit, TA = 0, so gcd(TA,TB) = TB. + * - If there was at least one loop iteration, then one of TA or TB is odd, + * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, + * lz = min(a,b) so gcd(A,B) = 2^lz * TB. + * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. + * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* Fill X with n_bytes random bytes. + * X must already have room for those bytes. + * The ordering of the bytes returned from the RNG is suitable for + * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()). + * The size and sign of X are unchanged. + * n_bytes must not be 0. + */ +static int mpi_fill_random_internal( + mbedtls_mpi *X, size_t n_bytes, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t limbs = CHARS_TO_LIMBS( n_bytes ); + const size_t overhead = ( limbs * ciL ) - n_bytes; + + if( X->n < limbs ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( X->p, 0, overhead ); + memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL ); + MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) ); + mpi_bigendian_to_host( X->p, limbs ); + +cleanup: + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( size ); + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + if( size == 0 ) + return( 0 ); + + ret = mpi_fill_random_internal( X, size, f_rng, p_rng ); + +cleanup: + return( ret ); +} + +int mbedtls_mpi_random( mbedtls_mpi *X, + mbedtls_mpi_sint min, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + int count; + unsigned lt_lower = 1, lt_upper = 0; + size_t n_bits = mbedtls_mpi_bitlen( N ); + size_t n_bytes = ( n_bits + 7 ) / 8; + mbedtls_mpi lower_bound; + + if( min < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + if( mbedtls_mpi_cmp_int( N, min ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * When min == 0, each try has at worst a probability 1/2 of failing + * (the msb has a probability 1/2 of being 0, and then the result will + * be < N), so after 30 tries failure probability is a most 2**(-30). + * + * When N is just below a power of 2, as is the case when generating + * a random scalar on most elliptic curves, 1 try is enough with + * overwhelming probability. When N is just above a power of 2, + * as when generating a random scalar on secp224k1, each try has + * a probability of failing that is almost 1/2. + * + * The probabilities are almost the same if min is nonzero but negligible + * compared to N. This is always the case when N is crypto-sized, but + * it's convenient to support small N for testing purposes. When N + * is small, use a higher repeat count, otherwise the probability of + * failure is macroscopic. + */ + count = ( n_bytes > 4 ? 30 : 250 ); + + mbedtls_mpi_init( &lower_bound ); + + /* Ensure that target MPI has exactly the same number of limbs + * as the upper bound, even if the upper bound has leading zeros. + * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) ); + + /* + * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) + * when f_rng is a suitably parametrized instance of HMAC_DRBG: + * - use the same byte ordering; + * - keep the leftmost n_bits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any bias, which is especially important for ECDSA. + */ + + do + { + MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) ); + + if( --count == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, <_lower ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, <_upper ) ); + } + while( lt_lower != 0 || lt_upper == 0 ); + +cleanup: + mbedtls_mpi_free( &lower_bound ); + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, s; + mbedtls_mpi W, R, T, A, RR; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + for( i = 0; i < rounds; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } + + if (count++ > 30) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +/* + * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + int rounds; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) + { + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } + + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) + { + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/bn_mul.h b/component/common/network/ssl/mbedtls-3.1.0/library/bn_mul.h new file mode 100644 index 00000000..b71ddd88 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/bn_mul.h @@ -0,0 +1,974 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/bignum.h" + + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) + +#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \ + MBEDTLS_BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ), \ + MBEDTLS_BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) | \ + ( (mbedtls_mpi_uint) (e) << 32 ) | \ + ( (mbedtls_mpi_uint) (f) << 40 ) | \ + ( (mbedtls_mpi_uint) (g) << 48 ) | \ + ( (mbedtls_mpi_uint) (h) << 56 ) + +#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \ + MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \ + MBEDTLS_BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "b" (b), "m" (*(const uint64_t (*)[16]) s) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__aarch64__) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr x4, [%2], #8 \n\t" \ + "ldr x5, [%1] \n\t" \ + "mul x6, x4, %4 \n\t" \ + "umulh x7, x4, %4 \n\t" \ + "adds x5, x5, x6 \n\t" \ + "adc x7, x7, xzr \n\t" \ + "adds x5, x5, %0 \n\t" \ + "adc %0, x7, xzr \n\t" \ + "str x5, [%1], #8 \n\t" + +#define MULADDC_STOP \ + : "+r" (c), "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ + : "x4", "x5", "x6", "x7", "cc" \ + ); + +#endif /* Aarch64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#elif (__ARM_ARCH >= 6) && \ + defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/camellia.c b/component/common/network/ssl/mbedtls-3.1.0/library/camellia.c new file mode 100644 index 00000000..29d730ab --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/camellia.c @@ -0,0 +1,1087 @@ +/* + * Camellia implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* Parameter validation macros */ +#define CAMELLIA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ) +#define CAMELLIA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1( MBEDTLS_BYTE_3( I0 )) << 24) | + ((uint32_t) SBOX2( MBEDTLS_BYTE_2( I0 )) << 16) | + ((uint32_t) SBOX3( MBEDTLS_BYTE_1( I0 )) << 8) | + ((uint32_t) SBOX4( MBEDTLS_BYTE_0( I0 )) ); + I1 = ((uint32_t) SBOX2( MBEDTLS_BYTE_3( I1 )) << 24) | + ((uint32_t) SBOX3( MBEDTLS_BYTE_2( I1 )) << 16) | + ((uint32_t) SBOX4( MBEDTLS_BYTE_1( I1 )) << 8) | + ((uint32_t) SBOX1( MBEDTLS_BYTE_0( I1 )) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + CAMELLIA_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + SIGMA[i][0] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 0 ); + SIGMA[i][1] = MBEDTLS_GET_UINT32_BE( SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + KC[i] = MBEDTLS_GET_UINT32_BE( t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, + const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( key != NULL ); + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( input != NULL ); + CAMELLIA_VALIDATE_RET( output != NULL ); + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + X[0] = MBEDTLS_GET_UINT32_BE( input, 0 ); + X[1] = MBEDTLS_GET_UINT32_BE( input, 4 ); + X[2] = MBEDTLS_GET_UINT32_BE( input, 8 ); + X[3] = MBEDTLS_GET_UINT32_BE( input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + MBEDTLS_PUT_UINT32_BE( X[2], output, 0 ); + MBEDTLS_PUT_UINT32_BE( X[3], output, 4 ); + MBEDTLS_PUT_UINT32_BE( X[0], output, 8 ); + MBEDTLS_PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( mode == MBEDTLS_CAMELLIA_ENCRYPT || + mode == MBEDTLS_CAMELLIA_DECRYPT ); + CAMELLIA_VALIDATE_RET( iv != NULL ); + CAMELLIA_VALIDATE_RET( iv_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *iv_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n; + CAMELLIA_VALIDATE_RET( ctx != NULL ); + CAMELLIA_VALIDATE_RET( nonce_counter != NULL ); + CAMELLIA_VALIDATE_RET( stream_block != NULL ); + CAMELLIA_VALIDATE_RET( nc_off != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || input != NULL ); + CAMELLIA_VALIDATE_RET( length == 0 || output != NULL ); + + n = *nc_off; + if( n >= 16 ) + return( MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, + { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, + { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + int ret = 1; + + mbedtls_camellia_context ctx; + + mbedtls_camellia_init( &ctx ); + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + ret = 0; + +exit: + mbedtls_camellia_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ccm.c b/component/common/network/ssl/mbedtls-3.1.0/library/ccm.c new file mode 100644 index 00000000..e0626785 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ccm.c @@ -0,0 +1,737 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +#include "common.h" + +#if defined(MBEDTLS_CCM_C) + +#include "mbedtls/ccm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CCM_ALT) + + +/* + * Initialize context + */ +void mbedtls_ccm_init( mbedtls_ccm_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ccm_context ) ); +} + +int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); +} + +#define CCM_STATE__CLEAR 0 +#define CCM_STATE__STARTED (1 << 0) +#define CCM_STATE__LENGHTS_SET (1 << 1) +#define CCM_STATE__AUTH_DATA_STARTED (1 << 2) +#define CCM_STATE__AUTH_DATA_FINISHED (1 << 3) +#define CCM_STATE__ERROR (1 << 4) + +/* + * Encrypt or decrypt a partial block with CTR + */ +static int mbedtls_ccm_crypt( mbedtls_ccm_context *ctx, + size_t offset, size_t use_len, + const unsigned char *input, + unsigned char *output ) +{ + size_t i; + size_t olen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp_buf[16] = {0}; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, + &olen ) ) != 0 ) + { + ctx->state |= CCM_STATE__ERROR; + mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); + return ret; + } + + for( i = 0; i < use_len; i++ ) + output[i] = input[i] ^ tmp_buf[offset + i]; + + mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf)); + return ret; +} + +static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx) { + ctx->state = CCM_STATE__CLEAR; + memset( ctx->y, 0, 16); + memset( ctx->ctr, 0, 16); +} + +static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t len_left, olen; + + /* length calulcation can be done only after both + * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed + */ + if( !(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGHTS_SET) ) + return 0; + + /* CCM expects non-empty tag. + * CCM* allows empty tag. For CCM* without tag, ignore plaintext length. + */ + if( ctx->tag_len == 0 ) + { + if( ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT ) + { + ctx->plaintext_len = 0; + } + else + { + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + } + } + + /* + * First block: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts() + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + ctx->y[0] |= ( ctx->add_len > 0 ) << 6; + ctx->y[0] |= ( ( ctx->tag_len - 2 ) / 2 ) << 3; + ctx->y[0] |= ctx->q - 1; + + for( i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8 ) + ctx->y[15-i] = MBEDTLS_BYTE_0( len_left ); + + if( len_left > 0 ) + { + ctx->state |= CCM_STATE__ERROR; + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + } + + /* Start CBC-MAC with first block*/ + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 ) + { + ctx->state |= CCM_STATE__ERROR; + return( ret ); + } + + return (0); +} + +int mbedtls_ccm_starts( mbedtls_ccm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len ) +{ + /* Also implies q is within bounds */ + if( iv_len < 7 || iv_len > 13 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + ctx->mode = mode; + ctx->q = 16 - 1 - (unsigned char) iv_len; + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + memset( ctx->ctr, 0, 16); + ctx->ctr[0] = ctx->q - 1; + memcpy( ctx->ctr + 1, iv, iv_len ); + memset( ctx->ctr + 1 + iv_len, 0, ctx->q ); + ctx->ctr[15] = 1; + + /* + * See ccm_calculate_first_block_if_ready() for block layout description + */ + memcpy( ctx->y + 1, iv, iv_len ); + + ctx->state |= CCM_STATE__STARTED; + return ccm_calculate_first_block_if_ready(ctx); +} + +int mbedtls_ccm_set_lengths( mbedtls_ccm_context *ctx, + size_t total_ad_len, + size_t plaintext_len, + size_t tag_len ) +{ + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). + */ + if( tag_len == 2 || tag_len > 16 || tag_len % 2 != 0 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + if( total_ad_len >= 0xFF00 ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + + ctx->plaintext_len = plaintext_len; + ctx->add_len = total_ad_len; + ctx->tag_len = tag_len; + ctx->processed = 0; + + ctx->state |= CCM_STATE__LENGHTS_SET; + return ccm_calculate_first_block_if_ready(ctx); +} + +int mbedtls_ccm_update_ad( mbedtls_ccm_context *ctx, + const unsigned char *add, + size_t add_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t olen, use_len, offset; + + if( ctx->state & CCM_STATE__ERROR ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if( add_len > 0 ) + { + if( ctx->state & CCM_STATE__AUTH_DATA_FINISHED ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if( !(ctx->state & CCM_STATE__AUTH_DATA_STARTED) ) + { + if ( add_len > ctx->add_len ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + ctx->y[0] ^= (unsigned char)( ( ctx->add_len >> 8 ) & 0xFF ); + ctx->y[1] ^= (unsigned char)( ( ctx->add_len ) & 0xFF ); + + ctx->state |= CCM_STATE__AUTH_DATA_STARTED; + } + else if ( ctx->processed + add_len > ctx->add_len ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + while( add_len > 0 ) + { + offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1] + * holding total auth data length */ + use_len = 16 - offset; + + if( use_len > add_len ) + use_len = add_len; + + for( i = 0; i < use_len; i++ ) + ctx->y[i + offset] ^= add[i]; + + ctx->processed += use_len; + add_len -= use_len; + add += use_len; + + if( use_len + offset == 16 || ctx->processed == ctx->add_len ) + { + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 ) + { + ctx->state |= CCM_STATE__ERROR; + return( ret ); + } + } + } + + if( ctx->processed == ctx->add_len ) + { + ctx->state |= CCM_STATE__AUTH_DATA_FINISHED; + ctx->processed = 0; // prepare for mbedtls_ccm_update() + } + } + + return (0); +} + +int mbedtls_ccm_update( mbedtls_ccm_context *ctx, + const unsigned char *input, size_t input_len, + unsigned char *output, size_t output_size, + size_t *output_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t use_len, offset, olen; + + unsigned char local_output[16]; + + if( ctx->state & CCM_STATE__ERROR ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + /* Check against plaintext length only if performing operation with + * authentication + */ + if( ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if( output_size < input_len ) + return( MBEDTLS_ERR_CCM_BAD_INPUT ); + *output_len = input_len; + + ret = 0; + + while ( input_len > 0 ) + { + offset = ctx->processed % 16; + + use_len = 16 - offset; + + if( use_len > input_len ) + use_len = input_len; + + ctx->processed += use_len; + + if( ctx->mode == MBEDTLS_CCM_ENCRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT ) + { + for( i = 0; i < use_len; i++ ) + ctx->y[i + offset] ^= input[i]; + + if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len ) + { + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 ) + { + ctx->state |= CCM_STATE__ERROR; + goto exit; + } + } + + ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, output ); + if( ret != 0 ) + goto exit; + } + + if( ctx->mode == MBEDTLS_CCM_DECRYPT || \ + ctx->mode == MBEDTLS_CCM_STAR_DECRYPT ) + { + /* Since output may be in shared memory, we cannot be sure that + * it will contain what we wrote to it. Therefore, we should avoid using + * it as input to any operations. + * Write decrypted data to local_output to avoid using output variable as + * input in the XOR operation for Y. + */ + ret = mbedtls_ccm_crypt( ctx, offset, use_len, input, local_output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < use_len; i++ ) + ctx->y[i + offset] ^= local_output[i]; + + memcpy( output, local_output, use_len ); + mbedtls_platform_zeroize( local_output, 16 ); + + if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len ) + { + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen ) ) != 0 ) + { + ctx->state |= CCM_STATE__ERROR; + goto exit; + } + } + } + + if( use_len + offset == 16 || ctx->processed == ctx->plaintext_len ) + { + for( i = 0; i < ctx->q; i++ ) + if( ++(ctx->ctr)[15-i] != 0 ) + break; + } + + input_len -= use_len; + input += use_len; + output += use_len; + } + +exit: + mbedtls_platform_zeroize( local_output, 16 ); + + return ret; +} + +int mbedtls_ccm_finish( mbedtls_ccm_context *ctx, + unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + + if( ctx->state & CCM_STATE__ERROR ) + { + return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + } + + if( ctx->add_len > 0 && !( ctx->state & CCM_STATE__AUTH_DATA_FINISHED ) ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + if( ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len ) + { + return MBEDTLS_ERR_CCM_BAD_INPUT; + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for( i = 0; i < ctx->q; i++ ) + ctx->ctr[15-i] = 0; + + ret = mbedtls_ccm_crypt( ctx, 0, 16, ctx->y, ctx->y ); + if( ret != 0 ) + return ret; + if( tag != NULL ) + memcpy( tag, ctx->y, tag_len ); + mbedtls_ccm_clear_state(ctx); + + return( 0 ); +} + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + if( ( ret = mbedtls_ccm_starts( ctx, mode, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_ccm_set_lengths( ctx, add_len, length, tag_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_ccm_update_ad( ctx, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_ccm_update( ctx, input, length, + output, length, &olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_ccm_finish( ctx, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + return( ccm_auth_crypt( ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len ) +{ + return( ccm_auth_crypt( ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len ) ); +} + +/* + * Authenticated decryption + */ +static int mbedtls_ccm_compare_tags(const unsigned char *tag1, const unsigned char *tag2, size_t tag_len) +{ + unsigned char i; + int diff; + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag1[i] ^ tag2[i]; + + if( diff != 0 ) + { + return( MBEDTLS_ERR_CCM_AUTH_FAILED ); + } + + return( 0 ); +} + +static int ccm_auth_decrypt( mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + + if( ( ret = ccm_auth_crypt( ctx, mode, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_ccm_compare_tags( tag, check_tag, tag_len ) ) != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + return ccm_auth_decrypt( ctx, MBEDTLS_CCM_STAR_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag, tag_len ); +} + +int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len ) +{ + return ccm_auth_decrypt( ctx, MBEDTLS_CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag, tag_len ); +} +#endif /* !MBEDTLS_CCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * Examples 1 to 3 from SP800-38C Appendix C + */ + +#define NB_TESTS 3 +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 +/* + * The data is the same for all tests, only the used length changes + */ +static const unsigned char key_test_data[] = { + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f +}; + +static const unsigned char iv_test_data[] = { + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b +}; + +static const unsigned char ad_test_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = { + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, +}; + +static const size_t iv_len_test_data [NB_TESTS] = { 7, 8, 12 }; +static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 }; +static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 }; +static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 }; + +static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = { + { 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d }, + { 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62, + 0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d, + 0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd }, + { 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a, + 0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b, + 0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5, + 0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 } +}; + +int mbedtls_ccm_self_test( int verbose ) +{ + mbedtls_ccm_context ctx; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; + size_t i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_ccm_init( &ctx ); + + if( mbedtls_ccm_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, key_test_data, + 8 * sizeof key_test_data ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM: setup failed" ); + + return( 1 ); + } + + for( i = 0; i < NB_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " CCM-AES #%u: ", (unsigned int) i + 1 ); + + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg_test_data, msg_len_test_data[i] ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len_test_data[i], + iv_test_data, iv_len_test_data[i], + ad_test_data, add_len_test_data[i], + plaintext, ciphertext, + ciphertext + msg_len_test_data[i], + tag_len_test_data[i] ); + + if( ret != 0 || + memcmp( ciphertext, res_test_data[i], + msg_len_test_data[i] + tag_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len_test_data[i], + iv_test_data, iv_len_test_data[i], + ad_test_data, add_len_test_data[i], + ciphertext, plaintext, + ciphertext + msg_len_test_data[i], + tag_len_test_data[i] ); + + if( ret != 0 || + memcmp( plaintext, msg_test_data, msg_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + mbedtls_ccm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_CCM_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/chacha20.c b/component/common/network/ssl/mbedtls-3.1.0/library/chacha20.c new file mode 100644 index 00000000..658f0469 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/chacha20.c @@ -0,0 +1,558 @@ +/** + * \file chacha20.c + * + * \brief ChaCha20 cipher. + * + * \author Daniel King + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_CHACHA20_C) + +#include "mbedtls/chacha20.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHA20_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define CHACHA20_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) +#define CHACHA20_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ROTL32( value, amount ) \ + ( (uint32_t) ( (value) << (amount) ) | ( (value) >> ( 32 - (amount) ) ) ) + +#define CHACHA20_CTR_INDEX ( 12U ) + +#define CHACHA20_BLOCK_SIZE_BYTES ( 4U * 16U ) + +/** + * \brief ChaCha20 quarter round operation. + * + * The quarter round is defined as follows (from RFC 7539): + * 1. a += b; d ^= a; d <<<= 16; + * 2. c += d; b ^= c; b <<<= 12; + * 3. a += b; d ^= a; d <<<= 8; + * 4. c += d; b ^= c; b <<<= 7; + * + * \param state ChaCha20 state to modify. + * \param a The index of 'a' in the state. + * \param b The index of 'b' in the state. + * \param c The index of 'c' in the state. + * \param d The index of 'd' in the state. + */ +static inline void chacha20_quarter_round( uint32_t state[16], + size_t a, + size_t b, + size_t c, + size_t d ) +{ + /* a += b; d ^= a; d <<<= 16; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 16 ); + + /* c += d; b ^= c; b <<<= 12 */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 12 ); + + /* a += b; d ^= a; d <<<= 8; */ + state[a] += state[b]; + state[d] ^= state[a]; + state[d] = ROTL32( state[d], 8 ); + + /* c += d; b ^= c; b <<<= 7; */ + state[c] += state[d]; + state[b] ^= state[c]; + state[b] = ROTL32( state[b], 7 ); +} + +/** + * \brief Perform the ChaCha20 inner block operation. + * + * This function performs two rounds: the column round and the + * diagonal round. + * + * \param state The ChaCha20 state to update. + */ +static void chacha20_inner_block( uint32_t state[16] ) +{ + chacha20_quarter_round( state, 0, 4, 8, 12 ); + chacha20_quarter_round( state, 1, 5, 9, 13 ); + chacha20_quarter_round( state, 2, 6, 10, 14 ); + chacha20_quarter_round( state, 3, 7, 11, 15 ); + + chacha20_quarter_round( state, 0, 5, 10, 15 ); + chacha20_quarter_round( state, 1, 6, 11, 12 ); + chacha20_quarter_round( state, 2, 7, 8, 13 ); + chacha20_quarter_round( state, 3, 4, 9, 14 ); +} + +/** + * \brief Generates a keystream block. + * + * \param initial_state The initial ChaCha20 state (key, nonce, counter). + * \param keystream Generated keystream bytes are written to this buffer. + */ +static void chacha20_block( const uint32_t initial_state[16], + unsigned char keystream[64] ) +{ + uint32_t working_state[16]; + size_t i; + + memcpy( working_state, + initial_state, + CHACHA20_BLOCK_SIZE_BYTES ); + + for( i = 0U; i < 10U; i++ ) + chacha20_inner_block( working_state ); + + working_state[ 0] += initial_state[ 0]; + working_state[ 1] += initial_state[ 1]; + working_state[ 2] += initial_state[ 2]; + working_state[ 3] += initial_state[ 3]; + working_state[ 4] += initial_state[ 4]; + working_state[ 5] += initial_state[ 5]; + working_state[ 6] += initial_state[ 6]; + working_state[ 7] += initial_state[ 7]; + working_state[ 8] += initial_state[ 8]; + working_state[ 9] += initial_state[ 9]; + working_state[10] += initial_state[10]; + working_state[11] += initial_state[11]; + working_state[12] += initial_state[12]; + working_state[13] += initial_state[13]; + working_state[14] += initial_state[14]; + working_state[15] += initial_state[15]; + + for( i = 0U; i < 16; i++ ) + { + size_t offset = i * 4U; + + MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset); + } + + mbedtls_platform_zeroize( working_state, sizeof( working_state ) ); +} + +void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx ) +{ + CHACHA20_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx->state, sizeof( ctx->state ) ); + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; +} + +void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx ) +{ + if( ctx != NULL ) + { + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_chacha20_context ) ); + } +} + +int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx, + const unsigned char key[32] ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( key != NULL ); + + /* ChaCha20 constants - the string "expand 32-byte k" */ + ctx->state[0] = 0x61707865; + ctx->state[1] = 0x3320646e; + ctx->state[2] = 0x79622d32; + ctx->state[3] = 0x6b206574; + + /* Set key */ + ctx->state[4] = MBEDTLS_GET_UINT32_LE( key, 0 ); + ctx->state[5] = MBEDTLS_GET_UINT32_LE( key, 4 ); + ctx->state[6] = MBEDTLS_GET_UINT32_LE( key, 8 ); + ctx->state[7] = MBEDTLS_GET_UINT32_LE( key, 12 ); + ctx->state[8] = MBEDTLS_GET_UINT32_LE( key, 16 ); + ctx->state[9] = MBEDTLS_GET_UINT32_LE( key, 20 ); + ctx->state[10] = MBEDTLS_GET_UINT32_LE( key, 24 ); + ctx->state[11] = MBEDTLS_GET_UINT32_LE( key, 28 ); + + return( 0 ); +} + +int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx, + const unsigned char nonce[12], + uint32_t counter ) +{ + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + + /* Counter */ + ctx->state[12] = counter; + + /* Nonce */ + ctx->state[13] = MBEDTLS_GET_UINT32_LE( nonce, 0 ); + ctx->state[14] = MBEDTLS_GET_UINT32_LE( nonce, 4 ); + ctx->state[15] = MBEDTLS_GET_UINT32_LE( nonce, 8 ); + + mbedtls_platform_zeroize( ctx->keystream8, sizeof( ctx->keystream8 ) ); + + /* Initially, there's no keystream bytes available */ + ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES; + + return( 0 ); +} + +int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx, + size_t size, + const unsigned char *input, + unsigned char *output ) +{ + size_t offset = 0U; + size_t i; + + CHACHA20_VALIDATE_RET( ctx != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( size == 0 || output != NULL ); + + /* Use leftover keystream bytes, if available */ + while( size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES ) + { + output[offset] = input[offset] + ^ ctx->keystream8[ctx->keystream_bytes_used]; + + ctx->keystream_bytes_used++; + offset++; + size--; + } + + /* Process full blocks */ + while( size >= CHACHA20_BLOCK_SIZE_BYTES ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < 64U; i += 8U ) + { + output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ]; + output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1]; + output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2]; + output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3]; + output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4]; + output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5]; + output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6]; + output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7]; + } + + offset += CHACHA20_BLOCK_SIZE_BYTES; + size -= CHACHA20_BLOCK_SIZE_BYTES; + } + + /* Last (partial) block */ + if( size > 0U ) + { + /* Generate new keystream block and increment counter */ + chacha20_block( ctx->state, ctx->keystream8 ); + ctx->state[CHACHA20_CTR_INDEX]++; + + for( i = 0U; i < size; i++) + { + output[offset + i] = input[offset + i] ^ ctx->keystream8[i]; + } + + ctx->keystream_bytes_used = size; + + } + + return( 0 ); +} + +int mbedtls_chacha20_crypt( const unsigned char key[32], + const unsigned char nonce[12], + uint32_t counter, + size_t data_len, + const unsigned char* input, + unsigned char* output ) +{ + mbedtls_chacha20_context ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + CHACHA20_VALIDATE_RET( key != NULL ); + CHACHA20_VALIDATE_RET( nonce != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL ); + CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL ); + + mbedtls_chacha20_init( &ctx ); + + ret = mbedtls_chacha20_setkey( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_starts( &ctx, nonce, counter ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chacha20_update( &ctx, data_len, input, output ); + +cleanup: + mbedtls_chacha20_free( &ctx ); + return( ret ); +} + +#endif /* !MBEDTLS_CHACHA20_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + } +}; + +static const unsigned char test_nonces[2][12] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02 + } +}; + +static const uint32_t test_counters[2] = +{ + 0U, + 1U +}; + +static const unsigned char test_input[2][375] = +{ + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, + 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72, + 0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66, + 0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46, + 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20, + 0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73, + 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, + 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72, + 0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49, + 0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45, + 0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20, + 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, + 0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63, + 0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63, + 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61, + 0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e, + 0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f, + 0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c, + 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61, + 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f + } +}; + +static const unsigned char test_output[2][375] = +{ + { + 0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90, + 0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28, + 0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a, + 0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7, + 0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d, + 0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37, + 0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c, + 0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86 + }, + { + 0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde, + 0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70, + 0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd, + 0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec, + 0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15, + 0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05, + 0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f, + 0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d, + 0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa, + 0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e, + 0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7, + 0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50, + 0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05, + 0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c, + 0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05, + 0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a, + 0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0, + 0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66, + 0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4, + 0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d, + 0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91, + 0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28, + 0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87, + 0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b, + 0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2, + 0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f, + 0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76, + 0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c, + 0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b, + 0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84, + 0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd, + 0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b, + 0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe, + 0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0, + 0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80, + 0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f, + 0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3, + 0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62, + 0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91, + 0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6, + 0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64, + 0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85, + 0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41, + 0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab, + 0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba, + 0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd, + 0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21 + } +}; + +static const size_t test_lengths[2] = +{ + 64U, + 375U +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chacha20_self_test( int verbose ) +{ + unsigned char output[381]; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20 test %u ", i ); + + ret = mbedtls_chacha20_crypt( test_keys[i], + test_nonces[i], + test_counters[i], + test_lengths[i], + test_input[i], + output ); + + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_lengths[i] ), + ( "failed (output)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_CHACHA20_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/chachapoly.c b/component/common/network/ssl/mbedtls-3.1.0/library/chachapoly.c new file mode 100644 index 00000000..dc75b203 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/chachapoly.c @@ -0,0 +1,524 @@ +/** + * \file chachapoly.c + * + * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539. + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) + +#include "mbedtls/chachapoly.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_CHACHAPOLY_ALT) + +/* Parameter validation macros */ +#define CHACHAPOLY_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define CHACHAPOLY_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define CHACHAPOLY_STATE_INIT ( 0 ) +#define CHACHAPOLY_STATE_AAD ( 1 ) +#define CHACHAPOLY_STATE_CIPHERTEXT ( 2 ) /* Encrypting or decrypting */ +#define CHACHAPOLY_STATE_FINISHED ( 3 ) + +/** + * \brief Adds nul bytes to pad the AAD for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_aad( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->aad_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +/** + * \brief Adds nul bytes to pad the ciphertext for Poly1305. + * + * \param ctx The ChaCha20-Poly1305 context. + */ +static int chachapoly_pad_ciphertext( mbedtls_chachapoly_context *ctx ) +{ + uint32_t partial_block_len = (uint32_t) ( ctx->ciphertext_len % 16U ); + unsigned char zeroes[15]; + + if( partial_block_len == 0U ) + return( 0 ); + + memset( zeroes, 0, sizeof( zeroes ) ); + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, + zeroes, + 16U - partial_block_len ) ); +} + +void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx ) +{ + CHACHAPOLY_VALIDATE( ctx != NULL ); + + mbedtls_chacha20_init( &ctx->chacha20_ctx ); + mbedtls_poly1305_init( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_chacha20_free( &ctx->chacha20_ctx ); + mbedtls_poly1305_free( &ctx->poly1305_ctx ); + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_INIT; + ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT; +} + +int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx, + const unsigned char key[32] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( key != NULL ); + + ret = mbedtls_chacha20_setkey( &ctx->chacha20_ctx, key ); + + return( ret ); +} + +int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx, + const unsigned char nonce[12], + mbedtls_chachapoly_mode_t mode ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char poly1305_key[64]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + + /* Set counter = 0, will be update to 1 when generating Poly1305 key */ + ret = mbedtls_chacha20_starts( &ctx->chacha20_ctx, nonce, 0U ); + if( ret != 0 ) + goto cleanup; + + /* Generate the Poly1305 key by getting the ChaCha20 keystream output with + * counter = 0. This is the same as encrypting a buffer of zeroes. + * Only the first 256-bits (32 bytes) of the key is used for Poly1305. + * The other 256 bits are discarded. + */ + memset( poly1305_key, 0, sizeof( poly1305_key ) ); + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, sizeof( poly1305_key ), + poly1305_key, poly1305_key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_starts( &ctx->poly1305_ctx, poly1305_key ); + + if( ret == 0 ) + { + ctx->aad_len = 0U; + ctx->ciphertext_len = 0U; + ctx->state = CHACHAPOLY_STATE_AAD; + ctx->mode = mode; + } + +cleanup: + mbedtls_platform_zeroize( poly1305_key, 64U ); + return( ret ); +} + +int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx, + const unsigned char *aad, + size_t aad_len ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + + if( ctx->state != CHACHAPOLY_STATE_AAD ) + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + + ctx->aad_len += aad_len; + + return( mbedtls_poly1305_update( &ctx->poly1305_ctx, aad, aad_len ) ); +} + +int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx, + size_t len, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL ); + + if( ( ctx->state != CHACHAPOLY_STATE_AAD ) && + ( ctx->state != CHACHAPOLY_STATE_CIPHERTEXT ) ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; + + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->ciphertext_len += len; + + if( ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT ) + { + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, output, len ); + if( ret != 0 ) + return( ret ); + } + else /* DECRYPT */ + { + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, input, len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_chacha20_update( &ctx->chacha20_ctx, len, input, output ); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx, + unsigned char mac[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char len_block[16]; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( mac != NULL ); + + if( ctx->state == CHACHAPOLY_STATE_INIT ) + { + return( MBEDTLS_ERR_CHACHAPOLY_BAD_STATE ); + } + + if( ctx->state == CHACHAPOLY_STATE_AAD ) + { + ret = chachapoly_pad_aad( ctx ); + if( ret != 0 ) + return( ret ); + } + else if( ctx->state == CHACHAPOLY_STATE_CIPHERTEXT ) + { + ret = chachapoly_pad_ciphertext( ctx ); + if( ret != 0 ) + return( ret ); + } + + ctx->state = CHACHAPOLY_STATE_FINISHED; + + /* The lengths of the AAD and ciphertext are processed by + * Poly1305 as the final 128-bit block, encoded as little-endian integers. + */ + MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0); + MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8); + + ret = mbedtls_poly1305_update( &ctx->poly1305_ctx, len_block, 16U ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_poly1305_finish( &ctx->poly1305_ctx, mac ); + + return( ret ); +} + +static int chachapoly_crypt_and_tag( mbedtls_chachapoly_context *ctx, + mbedtls_chachapoly_mode_t mode, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_chachapoly_starts( ctx, nonce, mode ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update_aad( ctx, aad, aad_len ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_update( ctx, length, input, output ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_chachapoly_finish( ctx, tag ); + +cleanup: + return( ret ); +} + +int mbedtls_chachapoly_encrypt_and_tag( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char *input, + unsigned char *output, + unsigned char tag[16] ) +{ + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + return( chachapoly_crypt_and_tag( ctx, MBEDTLS_CHACHAPOLY_ENCRYPT, + length, nonce, aad, aad_len, + input, output, tag ) ); +} + +int mbedtls_chachapoly_auth_decrypt( mbedtls_chachapoly_context *ctx, + size_t length, + const unsigned char nonce[12], + const unsigned char *aad, + size_t aad_len, + const unsigned char tag[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + size_t i; + int diff; + CHACHAPOLY_VALIDATE_RET( ctx != NULL ); + CHACHAPOLY_VALIDATE_RET( nonce != NULL ); + CHACHAPOLY_VALIDATE_RET( tag != NULL ); + CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL ); + CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = chachapoly_crypt_and_tag( ctx, + MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce, + aad, aad_len, input, output, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < sizeof( check_tag ); i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_CHACHAPOLY_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_key[1][32] = +{ + { + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f + } +}; + +static const unsigned char test_nonce[1][12] = +{ + { + 0x07, 0x00, 0x00, 0x00, /* 32-bit common part */ + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */ + } +}; + +static const unsigned char test_aad[1][12] = +{ + { + 0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7 + } +}; + +static const size_t test_aad_len[1] = +{ + 12U +}; + +static const unsigned char test_input[1][114] = +{ + { + 0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, + 0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39, + 0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63, + 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66, + 0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f, + 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20, + 0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75, + 0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73, + 0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f, + 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, + 0x74, 0x2e + } +}; + +static const unsigned char test_output[1][114] = +{ + { + 0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb, + 0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2, + 0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe, + 0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6, + 0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12, + 0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b, + 0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29, + 0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36, + 0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c, + 0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58, + 0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94, + 0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc, + 0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d, + 0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b, + 0x61, 0x16 + } +}; + +static const size_t test_input_len[1] = +{ + 114U +}; + +static const unsigned char test_mac[1][16] = +{ + { + 0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a, + 0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91 + } +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_chachapoly_self_test( int verbose ) +{ + mbedtls_chachapoly_context ctx; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output[200]; + unsigned char mac[16]; + + for( i = 0U; i < 1U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ChaCha20-Poly1305 test %u ", i ); + + mbedtls_chachapoly_init( &ctx ); + + ret = mbedtls_chachapoly_setkey( &ctx, test_key[i] ); + ASSERT( 0 == ret, ( "setkey() error code: %i\n", ret ) ); + + ret = mbedtls_chachapoly_encrypt_and_tag( &ctx, + test_input_len[i], + test_nonce[i], + test_aad[i], + test_aad_len[i], + test_input[i], + output, + mac ); + + ASSERT( 0 == ret, ( "crypt_and_tag() error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( output, test_output[i], test_input_len[i] ), + ( "failure (wrong output)\n" ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), + ( "failure (wrong MAC)\n" ) ); + + mbedtls_chachapoly_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CHACHAPOLY_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/check_crypto_config.h b/component/common/network/ssl/mbedtls-3.1.0/library/check_crypto_config.h new file mode 100644 index 00000000..d7ad16a6 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/check_crypto_config.h @@ -0,0 +1,91 @@ +/** + * \file check_crypto_config.h + * + * \brief Consistency checks for PSA configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * It is recommended to include this file from your crypto_config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H +#define MBEDTLS_CHECK_CRYPTO_CONFIG_H + +#if defined(PSA_WANT_ALG_CCM) && \ + !( defined(PSA_WANT_KEY_TYPE_AES) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) ) +#error "PSA_WANT_ALG_CCM defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_CMAC) && \ + !( defined(PSA_WANT_KEY_TYPE_AES) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \ + defined(PSA_WANT_KEY_TYPE_DES) ) +#error "PSA_WANT_ALG_CMAC defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \ + !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_ECDSA) && \ + !( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_GCM) && \ + !( defined(PSA_WANT_KEY_TYPE_AES) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) ) +#error "PSA_WANT_ALG_GCM defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_OAEP) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_ALG_RSA_PSS) && \ + !( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ) +#error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites" +#endif + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \ + !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites" +#endif + +#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/cipher.c b/component/common/network/ssl/mbedtls-3.1.0/library/cipher.c new file mode 100644 index 00000000..03e84c6c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/cipher.c @@ -0,0 +1,1633 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "cipher_wrap.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/constant_time.h" + +#include +#include + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_NIST_KW_C) +#include "mbedtls/nist_kw.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define CIPHER_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ) +#define CIPHER_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( + const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( + const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( + const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + if( ctx->cipher_ctx != NULL ) + { + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + if( cipher_psa->slot_state == MBEDTLS_CIPHER_PSA_KEY_OWNED ) + { + /* xxx_free() doesn't allow to return failures. */ + (void) psa_destroy_key( cipher_psa->slot ); + } + + mbedtls_platform_zeroize( cipher_psa, sizeof( *cipher_psa ) ); + mbedtls_free( cipher_psa ); + } + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); + return; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ) +{ + psa_algorithm_t alg; + mbedtls_cipher_context_psa *cipher_psa; + + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* Check that the underlying cipher mode and cipher type are + * supported by the underlying PSA Crypto implementation. */ + alg = mbedtls_psa_translate_cipher_mode( cipher_info->mode, taglen ); + if( alg == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + if( mbedtls_psa_translate_cipher_type( cipher_info->type ) == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + cipher_psa = mbedtls_calloc( 1, sizeof(mbedtls_cipher_context_psa ) ); + if( cipher_psa == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + cipher_psa->alg = alg; + ctx->cipher_ctx = cipher_psa; + ctx->cipher_info = cipher_info; + ctx->psa_enabled = 1; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( key != NULL ); + CIPHER_VALIDATE_RET( operation == MBEDTLS_ENCRYPT || + operation == MBEDTLS_DECRYPT ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + size_t const key_bytelen = ( (size_t) key_bitlen + 7 ) / 8; + + psa_status_t status; + psa_key_type_t key_type; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* PSA Crypto API only accepts byte-aligned keys. */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* Don't allow keys to be set multiple times. */ + if( cipher_psa->slot_state != MBEDTLS_CIPHER_PSA_KEY_UNSET ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + key_type = mbedtls_psa_translate_cipher_type( + ctx->cipher_info->type ); + if( key_type == 0 ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + psa_set_key_type( &attributes, key_type ); + + /* Mbed TLS' cipher layer doesn't enforce the mode of operation + * (encrypt vs. decrypt): it is possible to setup a key for encryption + * and use it for AEAD decryption. Until tests relying on this + * are changed, allow any usage in PSA. */ + psa_set_key_usage_flags( &attributes, + /* mbedtls_psa_translate_cipher_operation( operation ); */ + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, cipher_psa->alg ); + + status = psa_import_key( &attributes, key, key_bytelen, + &cipher_psa->slot ); + switch( status ) + { + case PSA_SUCCESS: + break; + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + default: + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + } + /* Indicate that we own the key slot and need to + * destroy it in mbedtls_cipher_free(). */ + cipher_psa->slot_state = MBEDTLS_CIPHER_PSA_KEY_OWNED; + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For OFB, CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return( ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + } + + if( MBEDTLS_DECRYPT == operation ) + return( ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ) ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ) +{ + size_t actual_iv_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return( mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, + ctx->operation, + iv, iv_len ) ); + } +#endif + +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode ) + { + int set_lengths_result; + int ccm_star_mode; + + set_lengths_result = mbedtls_ccm_set_lengths( + (mbedtls_ccm_context *) ctx->cipher_ctx, + 0, 0, 0 ); + if( set_lengths_result != 0 ) + return set_lengths_result; + + if( ctx->operation == MBEDTLS_DECRYPT ) + ccm_star_mode = MBEDTLS_CCM_STAR_DECRYPT; + else if( ctx->operation == MBEDTLS_ENCRYPT ) + ccm_star_mode = MBEDTLS_CCM_STAR_ENCRYPT; + else + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + + return( mbedtls_ccm_starts( (mbedtls_ccm_context *) ctx->cipher_ctx, + ccm_star_mode, + iv, iv_len ) ); + } +#endif + + if ( actual_iv_size != 0 ) + { + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + } + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* We don't support resetting PSA-based + * cipher contexts, yet. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return( mbedtls_gcm_update_ad( (mbedtls_gcm_context *) ctx->cipher_ctx, + ad, ad_len ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return( mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ) ); + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t block_size; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + if ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + return( mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, + input, ilen, + output, ilen, olen ) ); + } +#endif + +#if defined(MBEDTLS_CCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CCM_STAR_NO_TAG ) + { + return( mbedtls_ccm_update( (mbedtls_ccm_context *) ctx->cipher_ctx, + input, ilen, + output, ilen, olen ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return( mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ) ); + } +#endif + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ + copy_len = ilen % block_size; + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { + copy_len = block_size; + } + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i - 1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return( ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ) ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + + if( NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto knows about CBC padding + * schemes, we currently don't make them + * accessible through the cipher layer. */ + if( mode != MBEDTLS_PADDING_NONE ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + size_t output_length; + /* The code here doesn't yet support alternative implementations + * that can delay up to a block of output. */ + return( mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + NULL, 0, &output_length, + tag, tag_len ) ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_chachapoly_finish( + (mbedtls_chachapoly_context*) ctx->cipher_ctx, tag ) ); + } +#endif + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + unsigned char check_tag[16]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( tag_len == 0 || tag != NULL ); + if( ctx->cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* While PSA Crypto has an API for multipart + * operations, we currently don't make it + * accessible through the cipher layer. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Status to return on a non-authenticated algorithm. It would make sense + * to return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT or perhaps + * MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA, but at the time I write this our + * unit tests assume 0. */ + ret = 0; + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + size_t output_length; + /* The code here doesn't yet support alternative implementations + * that can delay up to a block of output. */ + + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( + (mbedtls_gcm_context *) ctx->cipher_ctx, + NULL, 0, &output_length, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto exit; + } + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ret = mbedtls_chachapoly_finish( + (mbedtls_chachapoly_context*) ctx->cipher_ctx, check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_ct_memcmp( tag, check_tag, tag_len ) != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto exit; + } + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + +exit: + mbedtls_platform_zeroize( check_tag, tag_len ); + return( ret ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t finish_olen; + + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + psa_cipher_operation_t cipher_op = PSA_CIPHER_OPERATION_INIT; + size_t part_len; + + if( ctx->operation == MBEDTLS_DECRYPT ) + { + status = psa_cipher_decrypt_setup( &cipher_op, + cipher_psa->slot, + cipher_psa->alg ); + } + else if( ctx->operation == MBEDTLS_ENCRYPT ) + { + status = psa_cipher_encrypt_setup( &cipher_op, + cipher_psa->slot, + cipher_psa->alg ); + } + else + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* In the following, we can immediately return on an error, + * because the PSA Crypto API guarantees that cipher operations + * are terminated by unsuccessful calls to psa_cipher_update(), + * and by any call to psa_cipher_finish(). */ + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + if( ctx->cipher_info->mode != MBEDTLS_MODE_ECB ) + { + status = psa_cipher_set_iv( &cipher_op, iv, iv_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + } + + status = psa_cipher_update( &cipher_op, + input, ilen, + output, ilen, olen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + status = psa_cipher_finish( &cipher_op, + output + *olen, ilen - *olen, + &part_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + *olen += part_len; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, + output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, + &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes: internal function used by + * mbedtls_cipher_auth_encrypt_ext(). + */ +static int mbedtls_cipher_aead_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + + /* PSA Crypto API always writes the authentication tag + * at the end of the encrypted message. */ + if( output == NULL || tag != output + ilen ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + status = psa_aead_encrypt( cipher_psa->slot, + cipher_psa->alg, + iv, iv_len, + ad, ad_len, + input, ilen, + output, ilen + tag_len, olen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + *olen -= tag_len; + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, + ilen, iv, iv_len, ad, ad_len, + input, output, tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented encryption for AEAD modes: internal function used by + * mbedtls_cipher_auth_encrypt_ext(). + */ +static int mbedtls_cipher_aead_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ctx->psa_enabled == 1 ) + { + /* As in the non-PSA case, we don't check that + * a key has been set. If not, the key slot will + * still be in its default state of 0, which is + * guaranteed to be invalid, hence the PSA-call + * below will gracefully fail. */ + mbedtls_cipher_context_psa * const cipher_psa = + (mbedtls_cipher_context_psa *) ctx->cipher_ctx; + + psa_status_t status; + + /* PSA Crypto API always writes the authentication tag + * at the end of the encrypted message. */ + if( input == NULL || tag != input + ilen ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + status = psa_aead_decrypt( cipher_psa->slot, + cipher_psa->alg, + iv, iv_len, + ad, ad_len, + input, ilen + tag_len, + output, ilen, olen ); + if( status == PSA_ERROR_INVALID_SIGNATURE ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + else if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) +/* + * Packet-oriented encryption for AEAD/NIST_KW: public function. + */ +int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_NIST_KW_C) + if( +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->psa_enabled == 0 && +#endif + ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || + MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) + { + mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + + /* There is no iv, tag or ad associated with KW and KWP, + * so these length should be 0 as documented. */ + if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + (void) iv; + (void) ad; + + return( mbedtls_nist_kw_wrap( ctx->cipher_ctx, mode, input, ilen, + output, olen, output_len ) ); + } +#endif /* MBEDTLS_NIST_KW_C */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) + /* AEAD case: check length before passing on to shared function */ + if( output_len < ilen + tag_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + int ret = mbedtls_cipher_aead_encrypt( ctx, iv, iv_len, ad, ad_len, + input, ilen, output, olen, + output + ilen, tag_len ); + *olen += tag_len; + return( ret ); +#else + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ +} + +/* + * Packet-oriented decryption for AEAD/NIST_KW: public function. + */ +int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ) +{ + CIPHER_VALIDATE_RET( ctx != NULL ); + CIPHER_VALIDATE_RET( iv_len == 0 || iv != NULL ); + CIPHER_VALIDATE_RET( ad_len == 0 || ad != NULL ); + CIPHER_VALIDATE_RET( ilen == 0 || input != NULL ); + CIPHER_VALIDATE_RET( output_len == 0 || output != NULL ); + CIPHER_VALIDATE_RET( olen != NULL ); + +#if defined(MBEDTLS_NIST_KW_C) + if( +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ctx->psa_enabled == 0 && +#endif + ( MBEDTLS_MODE_KW == ctx->cipher_info->mode || + MBEDTLS_MODE_KWP == ctx->cipher_info->mode ) ) + { + mbedtls_nist_kw_mode_t mode = ( MBEDTLS_MODE_KW == ctx->cipher_info->mode ) ? + MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP; + + /* There is no iv, tag or ad associated with KW and KWP, + * so these length should be 0 as documented. */ + if( iv_len != 0 || tag_len != 0 || ad_len != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + (void) iv; + (void) ad; + + return( mbedtls_nist_kw_unwrap( ctx->cipher_ctx, mode, input, ilen, + output, olen, output_len ) ); + } +#endif /* MBEDTLS_NIST_KW_C */ + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) + /* AEAD case: check length before passing on to shared function */ + if( ilen < tag_len || output_len < ilen - tag_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( mbedtls_cipher_aead_decrypt( ctx, iv, iv_len, ad, ad_len, + input, ilen - tag_len, output, olen, + input + ilen - tag_len, tag_len ) ); +#else + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.c b/component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.c new file mode 100644 index 00000000..7da7d9d5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.c @@ -0,0 +1,2270 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_CIPHER_C) + +#include "cipher_wrap.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_NIST_KW_C) +#include "mbedtls/nist_kw.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 0, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 0, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 128, + "AES-128-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 192, + "AES-192-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 256, + "AES-256-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 0, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 0, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 128, + "CAMELLIA-128-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 192, + "CAMELLIA-192-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 256, + "CAMELLIA-256-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 0, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 0, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 128, + "ARIA-128-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 192, + "ARIA-192-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = { + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, + MBEDTLS_MODE_CCM_STAR_NO_TAG, + 256, + "ARIA-256-CCM*-NO-TAG", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 0, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 0, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 0, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +#if defined(MBEDTLS_NIST_KW_C) +static void *kw_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_nist_kw_context ) ); + + if( ctx != NULL ) + mbedtls_nist_kw_init( (mbedtls_nist_kw_context *) ctx ); + + return( ctx ); +} + +static void kw_ctx_free( void *ctx ) +{ + mbedtls_nist_kw_free( ctx ); + mbedtls_free( ctx ); +} + +static int kw_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx, + MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 1 ); +} + +static int kw_aes_setkey_unwrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_nist_kw_setkey( (mbedtls_nist_kw_context *) ctx, + MBEDTLS_CIPHER_ID_AES, key, key_bitlen, 0 ); +} + +static const mbedtls_cipher_base_t kw_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + kw_aes_setkey_wrap, + kw_aes_setkey_unwrap, + kw_ctx_alloc, + kw_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_nist_kw_info = { + MBEDTLS_CIPHER_AES_128_KW, + MBEDTLS_MODE_KW, + 128, + "AES-128-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_nist_kw_info = { + MBEDTLS_CIPHER_AES_192_KW, + MBEDTLS_MODE_KW, + 192, + "AES-192-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_nist_kw_info = { + MBEDTLS_CIPHER_AES_256_KW, + MBEDTLS_MODE_KW, + 256, + "AES-256-KW", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_128_nist_kwp_info = { + MBEDTLS_CIPHER_AES_128_KWP, + MBEDTLS_MODE_KWP, + 128, + "AES-128-KWP", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_nist_kwp_info = { + MBEDTLS_CIPHER_AES_192_KWP, + MBEDTLS_MODE_KWP, + 192, + "AES-192-KWP", + 0, + 0, + 16, + &kw_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_nist_kwp_info = { + MBEDTLS_CIPHER_AES_256_KWP, + MBEDTLS_MODE_KWP, + 256, + "AES-256-KWP", + 0, + 0, + 16, + &kw_aes_info +}; +#endif /* MBEDTLS_NIST_KW_C */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, + { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, &aes_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, &aes_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, &aes_256_ccm_star_no_tag_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, &camellia_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, &camellia_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, &camellia_256_ccm_star_no_tag_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, + { MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, &aria_128_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, &aria_192_ccm_star_no_tag_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, &aria_256_ccm_star_no_tag_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + +#if defined(MBEDTLS_NIST_KW_C) + { MBEDTLS_CIPHER_AES_128_KW, &aes_128_nist_kw_info }, + { MBEDTLS_CIPHER_AES_192_KW, &aes_192_nist_kw_info }, + { MBEDTLS_CIPHER_AES_256_KW, &aes_256_nist_kw_info }, + { MBEDTLS_CIPHER_AES_128_KWP, &aes_128_nist_kwp_info }, + { MBEDTLS_CIPHER_AES_192_KWP, &aes_192_nist_kwp_info }, + { MBEDTLS_CIPHER_AES_256_KWP, &aes_256_nist_kwp_info }, +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS ( sizeof(mbedtls_cipher_definitions) / \ + sizeof(mbedtls_cipher_definitions[0]) ) +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.h b/component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.h new file mode 100644 index 00000000..90563d85 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/cipher_wrap.h @@ -0,0 +1,146 @@ +/** + * \file cipher_wrap.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +typedef enum +{ + MBEDTLS_CIPHER_PSA_KEY_UNSET = 0, + MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */ + /* use raw key material internally imported */ + /* as a volatile key, and which hence need */ + /* to destroy that key when the context is */ + /* freed. */ + MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */ + /* which use a key provided by the */ + /* user, and which hence will not be */ + /* destroyed when the context is freed. */ +} mbedtls_cipher_psa_key_ownership; + +typedef struct +{ + psa_algorithm_t alg; + psa_key_id_t slot; + mbedtls_cipher_psa_key_ownership slot_state; +} mbedtls_cipher_context_psa; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/cmac.c b/component/common/network/ssl/mbedtls-3.1.0/library/cmac.c new file mode 100644 index 00000000..3cc49d10 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/cmac.c @@ -0,0 +1,1087 @@ +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_platform_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%d: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + /* When CMAC is implemented by an alternative implementation, or + * the underlying primitive itself is implemented alternatively, + * AES-192 may be unavailable. This should not cause the selftest + * function to fail. */ + if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || + ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) && + cipher_type == MBEDTLS_CIPHER_AES_192_ECB ) { + if( verbose != 0 ) + mbedtls_printf( "skipped\n" ); + goto next_test; + } + + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +next_test: + mbedtls_cipher_free( &ctx ); + } + + ret = 0; + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%d: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + /* When CMAC is implemented by an alternative implementation, or + * the underlying primitive itself is implemented alternatively, + * AES-192 and/or 3DES may be unavailable. This should not cause + * the selftest function to fail. */ + if( ( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED || + ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) && + ( cipher_type == MBEDTLS_CIPHER_AES_192_ECB || + cipher_type == MBEDTLS_CIPHER_DES_EDE3_ECB ) ) { + if( verbose != 0 ) + mbedtls_printf( "skipped\n" ); + continue; + } + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + ret = 0; + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%d: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/common.h b/component/common/network/ssl/mbedtls-3.1.0/library/common.h new file mode 100644 index 00000000..a630fcc4 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/common.h @@ -0,0 +1,401 @@ +/** + * \file common.h + * + * \brief Utility macros for internal use in the library + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_LIBRARY_COMMON_H +#define MBEDTLS_LIBRARY_COMMON_H + +#include "mbedtls/build_info.h" + +#include + +/** Helper to define a function as static except when building invasive tests. + * + * If a function is only used inside its own source file and should be + * declared `static` to allow the compiler to optimize for code size, + * but that function has unit tests, define it with + * ``` + * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } + * ``` + * and declare it in a header in the `library/` directory with + * ``` + * #if defined(MBEDTLS_TEST_HOOKS) + * int mbedtls_foo(...); + * #endif + * ``` + */ +#if defined(MBEDTLS_TEST_HOOKS) +#define MBEDTLS_STATIC_TESTABLE +#else +#define MBEDTLS_STATIC_TESTABLE static +#endif + +#if defined(MBEDTLS_TEST_HOOKS) +extern void (*mbedtls_test_hook_test_fail)( const char * test, int line, const char * file ); +#define MBEDTLS_TEST_HOOK_TEST_ASSERT( TEST ) \ + do { \ + if( ( ! ( TEST ) ) && ( ( *mbedtls_test_hook_test_fail ) != NULL ) ) \ + { \ + ( *mbedtls_test_hook_test_fail )( #TEST, __LINE__, __FILE__ ); \ + } \ + } while( 0 ) +#else +#define MBEDTLS_TEST_HOOK_TEST_ASSERT( TEST ) +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +/** Allow library to access its structs' private members. + * + * Although structs defined in header files are publicly available, + * their members are private and should not be accessed by the user. + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +/** Byte Reading Macros + * + * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th + * byte from x, where byte 0 is the least significant byte. + */ +#define MBEDTLS_BYTE_0( x ) ( (uint8_t) ( ( x ) & 0xff ) ) +#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8 ) & 0xff ) ) +#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) ) +#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) ) +#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) ) +#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) ) +#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) ) +#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) ) + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT32_BE +#define MBEDTLS_GET_UINT32_BE( data , offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] << 24 ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 3] ) \ + ) +#endif + +/** + * Put in memory a 32 bits unsigned integer in big-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 32 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT32_BE +#define MBEDTLS_PUT_UINT32_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT32_LE +#define MBEDTLS_GET_UINT32_LE( data, offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 3] << 24 ) \ + ) +#endif + +/** + * Put in memory a 32 bits unsigned integer in little-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 32 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT32_LE +#define MBEDTLS_PUT_UINT32_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \ +} +#endif + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT16_LE +#define MBEDTLS_GET_UINT16_LE( data, offset ) \ + ( \ + ( (uint16_t) ( data )[( offset ) ] ) \ + | ( (uint16_t) ( data )[( offset ) + 1] << 8 ) \ + ) +#endif + +/** + * Put in memory a 16 bits unsigned integer in little-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 16 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT16_LE +#define MBEDTLS_PUT_UINT16_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ +} +#endif + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT16_BE +#define MBEDTLS_GET_UINT16_BE( data, offset ) \ + ( \ + ( (uint16_t) ( data )[( offset ) ] << 8 ) \ + | ( (uint16_t) ( data )[( offset ) + 1] ) \ + ) +#endif + +/** + * Put in memory a 16 bits unsigned integer in big-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 16 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT16_BE +#define MBEDTLS_PUT_UINT16_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT24_BE +#define MBEDTLS_GET_UINT24_BE( data , offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] ) \ + ) +#endif + +/** + * Put in memory a 24 bits unsigned integer in big-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 24 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT24_BE +#define MBEDTLS_PUT_UINT24_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT24_LE +#define MBEDTLS_GET_UINT24_LE( data, offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \ + ) +#endif + +/** + * Put in memory a 24 bits unsigned integer in little-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 24 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT24_LE +#define MBEDTLS_PUT_UINT24_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ +} +#endif + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT64_BE +#define MBEDTLS_GET_UINT64_BE( data, offset ) \ + ( \ + ( (uint64_t) ( data )[( offset ) ] << 56 ) \ + | ( (uint64_t) ( data )[( offset ) + 1] << 48 ) \ + | ( (uint64_t) ( data )[( offset ) + 2] << 40 ) \ + | ( (uint64_t) ( data )[( offset ) + 3] << 32 ) \ + | ( (uint64_t) ( data )[( offset ) + 4] << 24 ) \ + | ( (uint64_t) ( data )[( offset ) + 5] << 16 ) \ + | ( (uint64_t) ( data )[( offset ) + 6] << 8 ) \ + | ( (uint64_t) ( data )[( offset ) + 7] ) \ + ) +#endif + +/** + * Put in memory a 64 bits unsigned integer in big-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 64 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT64_BE +#define MBEDTLS_PUT_UINT64_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_7( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n ); \ + ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT64_LE +#define MBEDTLS_GET_UINT64_LE( data, offset ) \ + ( \ + ( (uint64_t) ( data )[( offset ) + 7] << 56 ) \ + | ( (uint64_t) ( data )[( offset ) + 6] << 48 ) \ + | ( (uint64_t) ( data )[( offset ) + 5] << 40 ) \ + | ( (uint64_t) ( data )[( offset ) + 4] << 32 ) \ + | ( (uint64_t) ( data )[( offset ) + 3] << 24 ) \ + | ( (uint64_t) ( data )[( offset ) + 2] << 16 ) \ + | ( (uint64_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint64_t) ( data )[( offset ) ] ) \ + ) +#endif + +/** + * Put in memory a 64 bits unsigned integer in little-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 64 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT64_LE +#define MBEDTLS_PUT_UINT64_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n ); \ + ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n ); \ + ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n ); \ + ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n ); \ +} +#endif + +/* Fix MSVC C99 compatible issue + * MSVC support __func__ from visual studio 2015( 1900 ) + * Use MSVC predefine macro to avoid name check fail. + */ +#if (defined(_MSC_VER) && ( _MSC_VER <= 1900 )) +#define /*no-check-names*/ __func__ __FUNCTION__ +#endif + +#endif /* MBEDTLS_LIBRARY_COMMON_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/constant_time.c b/component/common/network/ssl/mbedtls-3.1.0/library/constant_time.c new file mode 100644 index 00000000..d8870ae7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/constant_time.c @@ -0,0 +1,801 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + + /* + * The following functions are implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ + +#include "common.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "ssl_misc.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "constant_time_invasive.h" +#endif + +#include + +int mbedtls_ct_memcmp( const void *a, + const void *b, + size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + return( (int)diff ); +} + +unsigned mbedtls_ct_uint_mask( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +size_t mbedtls_ct_size_mask( size_t value ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Constant-flow mask generation for "less than" comparison: + * - if \p x < \p y, return all-bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return All-bits-one if \p x is less than \p y, otherwise zero. + */ +static size_t mbedtls_ct_size_mask_lt( size_t x, + size_t y ) +{ + /* This has the most significant bit set if and only if x < y */ + const size_t sub = x - y; + + /* sub1 = (x < y) ? 1 : 0 */ + const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 ); + + /* mask = (x < y) ? 0xff... : 0x00... */ + const size_t mask = mbedtls_ct_size_mask( sub1 ); + + return( mask ); +} + +size_t mbedtls_ct_size_mask_ge( size_t x, + size_t y ) +{ + return( ~mbedtls_ct_size_mask_lt( x, y ) ); +} + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BASE64_C) + +/* Return 0xff if low <= c <= high, 0 otherwise. + * + * Constant flow with respect to c. + */ +MBEDTLS_STATIC_TESTABLE +unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low, + unsigned char high, + unsigned char c ) +{ + /* low_mask is: 0 if low <= c, 0x...ff if low > c */ + unsigned low_mask = ( (unsigned) c - low ) >> 8; + /* high_mask is: 0 if c <= high, 0x...ff if c > high */ + unsigned high_mask = ( (unsigned) high - c ) >> 8; + return( ~( low_mask | high_mask ) & 0xff ); +} + +#endif /* MBEDTLS_BASE64_C */ + +unsigned mbedtls_ct_size_bool_eq( size_t x, + size_t y ) +{ + /* diff = 0 if x == y, non-zero otherwise */ + const size_t diff = x ^ y; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* diff_msb's most significant bit is equal to x != y */ + const size_t diff_msb = ( diff | (size_t) -diff ); + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* diff1 = (x != y) ? 1 : 0 */ + const unsigned diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); + + return( 1 ^ diff1 ); +} + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** Constant-flow "greater than" comparison: + * return x > y + * + * This is equivalent to \p x > \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x greater than \p y, otherwise 0. + */ +static unsigned mbedtls_ct_size_gt( size_t x, + size_t y ) +{ + /* Return the sign bit (1 for negative) of (y - x). */ + return( ( y - x ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_BIGNUM_C) + +unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 ); + + return (unsigned) ret; +} + +#endif /* MBEDTLS_BIGNUM_C */ + +unsigned mbedtls_ct_uint_if( unsigned condition, + unsigned if1, + unsigned if0 ) +{ + unsigned mask = mbedtls_ct_uint_mask( condition ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +#if defined(MBEDTLS_BIGNUM_C) + +/** Select between two sign values without branches. + * + * This is functionally equivalent to `condition ? if1 : if0` but uses only bit + * operations in order to avoid branches. + * + * \note if1 and if0 must be either 1 or -1, otherwise the result + * is undefined. + * + * \param condition Condition to test. + * \param if1 The first sign; must be either +1 or -1. + * \param if0 The second sign; must be either +1 or -1. + * + * \return \c if1 if \p condition is nonzero, otherwise \c if0. + * */ +static int mbedtls_ct_cond_select_sign( unsigned char condition, + int if1, + int if0 ) +{ + /* In order to avoid questions about what we can reasonably assume about + * the representations of signed integers, move everything to unsigned + * by taking advantage of the fact that if1 and if0 are either +1 or -1. */ + unsigned uif1 = if1 + 1; + unsigned uif0 = if0 + 1; + + /* condition was 0 or 1, mask is 0 or 2 as are uif1 and uif0 */ + const unsigned mask = condition << 1; + + /* select uif1 or uif0 */ + unsigned ur = ( uif0 & ~mask ) | ( uif1 & mask ); + + /* ur is now 0 or 2, convert back to -1 or +1 */ + return( (int) ur - 1 ); +} + +void mbedtls_ct_mpi_uint_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char condition ) +{ + size_t i; + + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + + /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */ + const mbedtls_mpi_uint mask = -condition; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + for( i = 0; i < n; i++ ) + dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask ); +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BASE64_C) + +unsigned char mbedtls_ct_base64_enc_char( unsigned char value ) +{ + unsigned char digit = 0; + /* For each range of values, if value is in that range, mask digit with + * the corresponding value. Since value can only be in a single range, + * only at most one masking will change digit. */ + digit |= mbedtls_ct_uchar_mask_of_range( 0, 25, value ) & ( 'A' + value ); + digit |= mbedtls_ct_uchar_mask_of_range( 26, 51, value ) & ( 'a' + value - 26 ); + digit |= mbedtls_ct_uchar_mask_of_range( 52, 61, value ) & ( '0' + value - 52 ); + digit |= mbedtls_ct_uchar_mask_of_range( 62, 62, value ) & '+'; + digit |= mbedtls_ct_uchar_mask_of_range( 63, 63, value ) & '/'; + return( digit ); +} + +signed char mbedtls_ct_base64_dec_value( unsigned char c ) +{ + unsigned char val = 0; + /* For each range of digits, if c is in that range, mask val with + * the corresponding value. Since c can only be in a single range, + * only at most one masking will change val. Set val to one plus + * the desired value so that it stays 0 if c is in none of the ranges. */ + val |= mbedtls_ct_uchar_mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 ); + /* At this point, val is 0 if c is an invalid digit and v+1 if c is + * a digit with the value v. */ + return( val - 1 ); +} + +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** Shift some data towards the left inside a buffer. + * + * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally + * equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mbedtls_ct_mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = mbedtls_ct_size_gt( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = mbedtls_ct_uint_if( no_op, current, next ); + } + buf[total-1] = mbedtls_ct_uint_if( no_op, buf[total-1], 0 ); + } +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +void mbedtls_ct_memcpy_if_eq( unsigned char *dest, + const unsigned char *src, + size_t len, + size_t c1, + size_t c2 ) +{ + /* mask = c1 == c2 ? 0xff : 0x00 */ + const size_t equal = mbedtls_ct_size_bool_eq( c1, c2 ); + const unsigned char mask = (unsigned char) mbedtls_ct_size_mask( equal ); + + /* dest[i] = c1 == c2 ? src[i] : dest[i] */ + for( size_t i = 0; i < len; i++ ) + dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask ); +} + +void mbedtls_ct_memcpy_offset( unsigned char *dest, + const unsigned char *src, + size_t offset, + size_t offset_min, + size_t offset_max, + size_t len ) +{ + size_t offsetval; + + for( offsetval = offset_min; offsetval <= offset_max; offsetval++ ) + { + mbedtls_ct_memcpy_if_eq( dest, src + offsetval, len, + offsetval, offset ); + } +} + +int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ct_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } + + /* The context needs to finish() before it starts() again */ + MD_CHK( mbedtls_md_finish( ctx, aux_out ) ); + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); + + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); + +#undef MD_CHK + +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned char assign ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint limb_mask; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ + limb_mask = mbedtls_ct_mpi_uint_mask( assign );; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s ); + + mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign ); + + for( i = Y->n; i < X->n; i++ ) + X->p[i] &= ~limb_mask; + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, + mbedtls_mpi *Y, + unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint limb_mask; + mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ + limb_mask = mbedtls_ct_mpi_uint_mask( swap ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s ); + Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s ); + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask ); + Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask ); + } + +cleanup: + return( ret ); +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +int mbedtls_ct_rsaes_pkcs1_v15_unpadding( unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, plaintext_max_size; + + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + plaintext_max_size = ( output_max_len > ilen - 11 ) ? ilen - 11 + : output_max_len; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= input[0]; + + + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= input[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= ((input[i] | (unsigned char)-input[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= mbedtls_ct_uint_if( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= mbedtls_ct_size_gt( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = mbedtls_ct_uint_if( + bad, (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = mbedtls_ct_size_gt( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) mbedtls_ct_uint_if( + bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + mbedtls_ct_uint_if( output_too_large, + - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = mbedtls_ct_uint_mask( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + input[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = mbedtls_ct_uint_if( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mbedtls_ct_mem_move_to_left( input + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros into the output + * buffer. If output_max_len is 0, then output may be an invalid pointer + * and the result of memcpy() would be undefined; prevent undefined + * behavior making sure to depend only on output_max_len (the size of the + * user-provided output buffer), which is independent from plaintext + * length, validity of padding, success of the decryption, and other + * secrets. */ + if( output_max_len != 0 ) + memcpy( output, input + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + + return( ret ); +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/constant_time_internal.h b/component/common/network/ssl/mbedtls-3.1.0/library/constant_time_internal.h new file mode 100644 index 00000000..053cf123 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/constant_time_internal.h @@ -0,0 +1,326 @@ +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H +#define MBEDTLS_CONSTANT_TIME_INTERNAL_H + +#include "common.h" + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "ssl_misc.h" +#endif + +#include + + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (unsigned) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +unsigned mbedtls_ct_uint_mask( unsigned value ); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (size_t) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +size_t mbedtls_ct_size_mask( size_t value ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (mbedtls_mpi_uint) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value ); + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Constant-flow mask generation for "greater or equal" comparison: + * - if \p x >= \p y, return all-bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return All-bits-one if \p x is greater or equal than \p y, + * otherwise zero. + */ +size_t mbedtls_ct_size_mask_ge( size_t x, + size_t y ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +/** Constant-flow boolean "equal" comparison: + * return x == y + * + * This is equivalent to \p x == \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x equals to \p y, otherwise 0. + */ +unsigned mbedtls_ct_size_bool_eq( size_t x, + size_t y ); + +#if defined(MBEDTLS_BIGNUM_C) + +/** Decide if an integer is less than the other, without branches. + * + * This is equivalent to \p x < \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x is less than \p y, otherwise 0. + */ +unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ); + +#endif /* MBEDTLS_BIGNUM_C */ + +/** Choose between two integer values without branches. + * + * This is equivalent to `condition ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition is nonzero. + * \param if0 Value to use if \p condition is zero. + * + * \return \c if1 if \p condition is nonzero, otherwise \c if0. + */ +unsigned mbedtls_ct_uint_if( unsigned condition, + unsigned if1, + unsigned if0 ); + +#if defined(MBEDTLS_BIGNUM_C) + +/** Conditionally assign a value without branches. + * + * This is equivalent to `if ( condition ) dest = src`, but is likely + * to be compiled to code using bitwise operation rather than a branch. + * + * \param n \p dest and \p src must be arrays of limbs of size n. + * \param dest The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param src The MPI to be assigned from. This must point to an + * initialized MPI. + * \param condition Condition to test, must be 0 or 1. + */ +void mbedtls_ct_mpi_uint_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char condition ); + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BASE64_C) + +/** Given a value in the range 0..63, return the corresponding Base64 digit. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param value A value in the range 0..63. + * + * \return A base64 digit converted from \p value. + */ +unsigned char mbedtls_ct_base64_enc_char( unsigned char value ); + +/** Given a Base64 digit, return its value. + * + * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), + * return -1. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param c A base64 digit. + * + * \return The value of the base64 digit \p c. + */ +signed char mbedtls_ct_base64_dec_value( unsigned char c ); + +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Conditional memcpy without branches. + * + * This is equivalent to `if ( c1 == c2 ) memcpy(dest, src, len)`, but is likely + * to be compiled to code using bitwise operation rather than a branch. + * + * \param dest The pointer to conditionally copy to. + * \param src The pointer to copy from. Shouldn't overlap with \p dest. + * \param len The number of bytes to copy. + * \param c1 The first value to analyze in the condition. + * \param c2 The second value to analyze in the condition. + */ +void mbedtls_ct_memcpy_if_eq( unsigned char *dest, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ); + +/** Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * Functionally equivalent to `memcpy(dst, src + offset_secret, len)`. + * + * \param dest The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. Shouldn't overlap with \p dest. + * \param offset The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset. + * \param offset_max The maximal value of \p offset. + * \param len The number of bytes to copy. + */ +void mbedtls_ct_memcpy_offset( unsigned char *dest, + const unsigned char *src, + size_t offset, + size_t offset_min, + size_t offset_max, + size_t len ); + +/** Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The first part of the message whose HMAC is being + * calculated. This must point to a readable buffer + * of \p add_data_len bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The buffer containing the second part of the + * message. This must point to a readable buffer + * of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of the second part of the + * message, read from \p data. + * \param max_data_len The maximal length of the second part of the + * message, read from \p data. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 on success. + * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** This function performs the unpadding part of a PKCS#1 v1.5 decryption + * operation (EME-PKCS1-v1_5 decoding). + * + * \note The return value from this function is a sensitive value + * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen + * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING + * is often a situation that an attacker can provoke and leaking which + * one is the result is precisely the information the attacker wants. + * + * \param input The input buffer which is the payload inside PKCS#1v1.5 + * encryption padding, called the "encoded message EM" + * by the terminology. + * \param ilen The length of the payload in the \p input buffer. + * \param output The buffer for the payload, called "message M" by the + * PKCS#1 terminology. This must be a writable buffer of + * length \p output_max_len bytes. + * \param olen The address at which to store the length of + * the payload. This must not be \c NULL. + * \param output_max_len The length in bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE + * The output buffer is too small for the unpadded payload. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING + * The input doesn't contain properly formatted padding. + */ +int mbedtls_ct_rsaes_pkcs1_v15_unpadding( unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen ); + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/constant_time_invasive.h b/component/common/network/ssl/mbedtls-3.1.0/library/constant_time_invasive.h new file mode 100644 index 00000000..4620ca13 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/constant_time_invasive.h @@ -0,0 +1,51 @@ +/** + * \file constant_time_invasive.h + * + * \brief Constant-time module: interfaces for invasive testing only. + * + * The interfaces in this file are intended for testing purposes only. + * They SHOULD NOT be made available in library integrations except when + * building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H +#define MBEDTLS_CONSTANT_TIME_INVASIVE_H + +#include "common.h" + +#if defined(MBEDTLS_TEST_HOOKS) + +/** Turn a value into a mask: + * - if \p low <= \p c <= \p high, + * return the all-bits 1 mask, aka (unsigned) -1 + * - otherwise, return the all-bits 0 mask, aka 0 + * + * \param low The value to analyze. + * \param high The value to analyze. + * \param c The value to analyze. + * + * \return All-bits-one if \p low <= \p c <= \p high, otherwise zero. + */ +unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low, + unsigned char high, + unsigned char c ); + +#endif /* MBEDTLS_TEST_HOOKS */ + +#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ctr_drbg.c b/component/common/network/ssl/mbedtls-3.1.0/library/ctr_drbg.c new file mode 100644 index 00000000..cfe4dad4 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ctr_drbg.c @@ -0,0 +1,903 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#include "common.h" +#include "mbedtls/entropy.h" + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + /* Indicate that the entropy nonce length is not set explicitly. + * See mbedtls_ctr_drbg_set_nonce_len(). */ + ctx->reseed_counter = -1; + + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; +} + +/* + * This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff f_entropy is set. */ + if( ctx->f_entropy != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + ctx->reseed_counter = -1; +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ) +{ + ctx->entropy_len = len; +} + +int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx, + size_t len ) +{ + /* If mbedtls_ctr_drbg_seed() has already been called, it's + * too late. Return the error code that's closest to making sense. */ + if( ctx->f_entropy != NULL ) + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + + if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); +#if SIZE_MAX > INT_MAX + /* This shouldn't be an issue because + * MBEDTLS_CTR_DRBG_MAX_SEED_INPUT < INT_MAX in any sensible + * configuration, but make sure anyway. */ + if( len > INT_MAX ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); +#endif + + /* For backward compatibility with Mbed TLS <= 2.19, store the + * entropy nonce length in a field that already exists, but isn't + * used until after the initial seeding. */ + /* Due to the capping of len above, the value fits in an int. */ + ctx->reseed_counter = (int) len; + return( 0 ); +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + int ret = 0; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + MBEDTLS_PUT_UINT32_BE( data_len, p, 0); + p += 4 + 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, + chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, + iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +/* CTR_DRBG_Update (SP 800-90A §10.2.1.2) + * ctr_drbg_update_internal(ctx, provided_data) + * implements + * CTR_DRBG_Update(provided_data, Key, V) + * with inputs and outputs + * ctx->aes_ctx = Key + * ctx->counter = V + */ +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + int ret = 0; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, + ctx->counter, p ) ) != 0 ) + { + goto exit; + } + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, + MBEDTLS_CTR_DRBG_BLOCKSIZE ); + +exit: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_update(ctx, additional, add_len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * ctx->counter = all-bits-0 + * ctx->aes_ctx = context from all-bits-0 key + * additional[:add_len] = entropy_input || nonce || personalization_string + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( add_len == 0 ) + return( 0 ); + + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + return( ret ); +} + +/* CTR_DRBG_Reseed with derivation function (SP 800-90A §10.2.1.4.2) + * mbedtls_ctr_drbg_reseed(ctx, additional, len, nonce_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional_input) + * -> new_working_state + * with inputs + * ctx contains working_state + * additional[:len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * for (ctx->entropy_len + nonce_len) bytes + * and with output + * ctx contains new_working_state + */ + +static int mbedtls_ctr_drbg_reseed_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t len, + size_t nonce_len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + if( nonce_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + if( len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len - nonce_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + + /* Gather entropy_len bytes of entropy to seed state. */ + + /* + if (ctx->f_entropy == NULL) { + printf("ctx->f_entropy is NULL ------------ cl\r\n"); + ctx->p_entropy = (mbedtls_entropy_context *)malloc(sizeof(mbedtls_entropy_context)); + mbedtls_entropy_init(ctx->p_entropy); + ctx->f_entropy = mbedtls_entropy_func; + } + */ + + //printf("source_count addr is %x ------------ cl\r\n",&(((mbedtls_entropy_context *)(ctx->p_entropy))->source_count)); + + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + //printf("mbedtls_ctr_drbg_reseed_internal: line is %d ------ cl \r\n", __LINE__); + seedlen += ctx->entropy_len; + + /* Gather entropy for a nonce if requested. */ + if( nonce_len != 0 ) + { + if( 0 != ctx->f_entropy( ctx->p_entropy, seed + seedlen, nonce_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += nonce_len; + } + + + /* Add additional data if provided. */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* Reduce to 384 bits. */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + goto exit; + + /* Update state. */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + goto exit; + ctx->reseed_counter = 1; + +exit: + mbedtls_platform_zeroize( seed, sizeof( seed ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( mbedtls_ctr_drbg_reseed_internal( ctx, additional, len, 0 ) ); +} + +/* Return a "good" nonce length for CTR_DRBG. The chosen nonce length + * is sufficient to achieve the maximum security strength given the key + * size and entropy length. If there is enough entropy in the initial + * call to the entropy function to serve as both the entropy input and + * the nonce, don't make a second call to get a nonce. */ +static size_t good_nonce_len( size_t entropy_len ) +{ + if( entropy_len >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 ) + return( 0 ); + else + return( ( entropy_len + 1 ) / 2 ); +} + +/* CTR_DRBG_Instantiate with derivation function (SP 800-90A §10.2.1.3.2) + * mbedtls_ctr_drbg_seed(ctx, f_entropy, p_entropy, custom, len) + * implements + * CTR_DRBG_Instantiate(entropy_input, nonce, personalization_string, + * security_strength) -> initial_working_state + * with inputs + * custom[:len] = nonce || personalization_string + * where entropy_input comes from f_entropy for ctx->entropy_len bytes + * and with outputs + * ctx = initial_working_state + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + printf("mbedtls_ctr_drbg_seed: line is %d ---- cl\r\n", __LINE__); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + size_t nonce_len; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + /* The mutex is initialized iff f_entropy is set. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + /* ctx->reseed_counter contains the desired amount of entropy to + * grab for a nonce (see mbedtls_ctr_drbg_set_nonce_len()). + * If it's -1, indicating that the entropy nonce length was not set + * explicitly, use a sufficiently large nonce for security. */ + nonce_len = ( ctx->reseed_counter >= 0 ? + (size_t) ctx->reseed_counter : + good_nonce_len( ctx->entropy_len ) ); + + /* Initialize with an empty key. */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, + MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + /* Do the initial seeding. */ + if( ( ret = mbedtls_ctr_drbg_reseed_internal( ctx, custom, len, + nonce_len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +/* CTR_DRBG_Generate with derivation function (SP 800-90A §10.2.1.5.2) + * mbedtls_ctr_drbg_random_with_add(ctx, output, output_len, additional, add_len) + * implements + * CTR_DRBG_Reseed(working_state, entropy_input, additional[:add_len]) + * -> working_state_after_reseed + * if required, then + * CTR_DRBG_Generate(working_state_after_reseed, + * requested_number_of_bits, additional_input) + * -> status, returned_bits, new_working_state + * with inputs + * ctx contains working_state + * requested_number_of_bits = 8 * output_len + * additional[:add_len] = additional_input + * and entropy_input comes from calling ctx->f_entropy + * and with outputs + * status = SUCCESS (this function does the reseed internally) + * returned_bits = output[:output_len] + * ctx contains new_working_state + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { + return( ret ); + } + add_len = 0; + } + + if( add_len > 0 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, + ctx->counter, tmp ) ) != 0 ) + { + goto exit; + } + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) + ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + + ctx->reseed_counter++; + +exit: + mbedtls_platform_zeroize( add_input, sizeof( add_input ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, + size_t output_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, + const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, + MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != + MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + } + else + { + ret = 0; + } + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, + const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_ctr_drbg_update( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +/* The CTR_DRBG NIST test vectors used here are available at + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/drbg/drbgtestvectors.zip + * + * The parameters used to derive the test data are: + * + * [AES-128 use df] + * [PredictionResistance = True/False] + * [EntropyInputLen = 128] + * [NonceLen = 64] + * [PersonalizationStringLen = 128] + * [AdditionalInputLen = 0] + * [ReturnedBitsLen = 512] + * + * [AES-256 use df] + * [PredictionResistance = True/False] + * [EntropyInputLen = 256] + * [NonceLen = 128] + * [PersonalizationStringLen = 256] + * [AdditionalInputLen = 0] + * [ReturnedBitsLen = 512] + * + */ + +#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) +static const unsigned char entropy_source_pr[] = + { 0x04, 0xd9, 0x49, 0xa6, 0xdc, 0xe8, 0x6e, 0xbb, + 0xf1, 0x08, 0x77, 0x2b, 0x9e, 0x08, 0xca, 0x92, + 0x65, 0x16, 0xda, 0x99, 0xa2, 0x59, 0xf3, 0xe8, + 0x38, 0x7e, 0x3f, 0x6b, 0x51, 0x70, 0x7b, 0x20, + 0xec, 0x53, 0xd0, 0x66, 0xc3, 0x0f, 0xe3, 0xb0, + 0xe0, 0x86, 0xa6, 0xaa, 0x5f, 0x72, 0x2f, 0xad, + 0xf7, 0xef, 0x06, 0xb8, 0xd6, 0x9c, 0x9d, 0xe8 }; + +static const unsigned char entropy_source_nopr[] = + { 0x07, 0x0d, 0x59, 0x63, 0x98, 0x73, 0xa5, 0x45, + 0x27, 0x38, 0x22, 0x7b, 0x76, 0x85, 0xd1, 0xa9, + 0x74, 0x18, 0x1f, 0x3c, 0x22, 0xf6, 0x49, 0x20, + 0x4a, 0x47, 0xc2, 0xf3, 0x85, 0x16, 0xb4, 0x6f, + 0x00, 0x2e, 0x71, 0xda, 0xed, 0x16, 0x9b, 0x5c }; + +static const unsigned char pers_pr[] = + { 0xbf, 0xa4, 0x9a, 0x8f, 0x7b, 0xd8, 0xb1, 0x7a, + 0x9d, 0xfa, 0x45, 0xed, 0x21, 0x52, 0xb3, 0xad }; + +static const unsigned char pers_nopr[] = + { 0x4e, 0x61, 0x79, 0xd4, 0xc2, 0x72, 0xa1, 0x4c, + 0xf1, 0x3d, 0xf6, 0x5e, 0xa3, 0xa6, 0xe5, 0x0f }; + +static const unsigned char result_pr[] = + { 0xc9, 0x0a, 0xaf, 0x85, 0x89, 0x71, 0x44, 0x66, + 0x4f, 0x25, 0x0b, 0x2b, 0xde, 0xd8, 0xfa, 0xff, + 0x52, 0x5a, 0x1b, 0x32, 0x5e, 0x41, 0x7a, 0x10, + 0x1f, 0xef, 0x1e, 0x62, 0x23, 0xe9, 0x20, 0x30, + 0xc9, 0x0d, 0xad, 0x69, 0xb4, 0x9c, 0x5b, 0xf4, + 0x87, 0x42, 0xd5, 0xae, 0x5e, 0x5e, 0x43, 0xcc, + 0xd9, 0xfd, 0x0b, 0x93, 0x4a, 0xe3, 0xd4, 0x06, + 0x37, 0x36, 0x0f, 0x3f, 0x72, 0x82, 0x0c, 0xcf }; + +static const unsigned char result_nopr[] = + { 0x31, 0xc9, 0x91, 0x09, 0xf8, 0xc5, 0x10, 0x13, + 0x3c, 0xd3, 0x96, 0xf9, 0xbc, 0x2c, 0x12, 0xc0, + 0x7c, 0xc1, 0x61, 0x5f, 0xa3, 0x09, 0x99, 0xaf, + 0xd7, 0xf2, 0x36, 0xfd, 0x40, 0x1a, 0x8b, 0xf2, + 0x33, 0x38, 0xee, 0x1d, 0x03, 0x5f, 0x83, 0xb7, + 0xa2, 0x53, 0xdc, 0xee, 0x18, 0xfc, 0xa7, 0xf2, + 0xee, 0x96, 0xc6, 0xc2, 0xcd, 0x0c, 0xff, 0x02, + 0x76, 0x70, 0x69, 0xaa, 0x69, 0xd1, 0x3b, 0xe8 }; +#else /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + +static const unsigned char entropy_source_pr[] = + { 0xca, 0x58, 0xfd, 0xf2, 0xb9, 0x77, 0xcb, 0x49, + 0xd4, 0xe0, 0x5b, 0xe2, 0x39, 0x50, 0xd9, 0x8a, + 0x6a, 0xb3, 0xc5, 0x2f, 0xdf, 0x74, 0xd5, 0x85, + 0x8f, 0xd1, 0xba, 0x64, 0x54, 0x7b, 0xdb, 0x1e, + 0xc5, 0xea, 0x24, 0xc0, 0xfa, 0x0c, 0x90, 0x15, + 0x09, 0x20, 0x92, 0x42, 0x32, 0x36, 0x45, 0x45, + 0x7d, 0x20, 0x76, 0x6b, 0xcf, 0xa2, 0x15, 0xc8, + 0x2f, 0x9f, 0xbc, 0x88, 0x3f, 0x80, 0xd1, 0x2c, + 0xb7, 0x16, 0xd1, 0x80, 0x9e, 0xe1, 0xc9, 0xb3, + 0x88, 0x1b, 0x21, 0x45, 0xef, 0xa1, 0x7f, 0xce, + 0xc8, 0x92, 0x35, 0x55, 0x2a, 0xd9, 0x1d, 0x8e, + 0x12, 0x38, 0xac, 0x01, 0x4e, 0x38, 0x18, 0x76, + 0x9c, 0xf2, 0xb6, 0xd4, 0x13, 0xb6, 0x2c, 0x77, + 0xc0, 0xe7, 0xe6, 0x0c, 0x47, 0x44, 0x95, 0xbe }; + +static const unsigned char entropy_source_nopr[] = + { 0x4c, 0xfb, 0x21, 0x86, 0x73, 0x34, 0x6d, 0x9d, + 0x50, 0xc9, 0x22, 0xe4, 0x9b, 0x0d, 0xfc, 0xd0, + 0x90, 0xad, 0xf0, 0x4f, 0x5c, 0x3b, 0xa4, 0x73, + 0x27, 0xdf, 0xcd, 0x6f, 0xa6, 0x3a, 0x78, 0x5c, + 0x01, 0x69, 0x62, 0xa7, 0xfd, 0x27, 0x87, 0xa2, + 0x4b, 0xf6, 0xbe, 0x47, 0xef, 0x37, 0x83, 0xf1, + 0xb7, 0xec, 0x46, 0x07, 0x23, 0x63, 0x83, 0x4a, + 0x1b, 0x01, 0x33, 0xf2, 0xc2, 0x38, 0x91, 0xdb, + 0x4f, 0x11, 0xa6, 0x86, 0x51, 0xf2, 0x3e, 0x3a, + 0x8b, 0x1f, 0xdc, 0x03, 0xb1, 0x92, 0xc7, 0xe7 }; + +static const unsigned char pers_pr[] = + { 0x5a, 0x70, 0x95, 0xe9, 0x81, 0x40, 0x52, 0x33, + 0x91, 0x53, 0x7e, 0x75, 0xd6, 0x19, 0x9d, 0x1e, + 0xad, 0x0d, 0xc6, 0xa7, 0xde, 0x6c, 0x1f, 0xe0, + 0xea, 0x18, 0x33, 0xa8, 0x7e, 0x06, 0x20, 0xe9 }; + +static const unsigned char pers_nopr[] = + { 0x88, 0xee, 0xb8, 0xe0, 0xe8, 0x3b, 0xf3, 0x29, + 0x4b, 0xda, 0xcd, 0x60, 0x99, 0xeb, 0xe4, 0xbf, + 0x55, 0xec, 0xd9, 0x11, 0x3f, 0x71, 0xe5, 0xeb, + 0xcb, 0x45, 0x75, 0xf3, 0xd6, 0xa6, 0x8a, 0x6b }; + +static const unsigned char result_pr[] = + { 0xce, 0x2f, 0xdb, 0xb6, 0xd9, 0xb7, 0x39, 0x85, + 0x04, 0xc5, 0xc0, 0x42, 0xc2, 0x31, 0xc6, 0x1d, + 0x9b, 0x5a, 0x59, 0xf8, 0x7e, 0x0d, 0xcc, 0x62, + 0x7b, 0x65, 0x11, 0x55, 0x10, 0xeb, 0x9e, 0x3d, + 0xa4, 0xfb, 0x1c, 0x6a, 0x18, 0xc0, 0x74, 0xdb, + 0xdd, 0xe7, 0x02, 0x23, 0x63, 0x21, 0xd0, 0x39, + 0xf9, 0xa7, 0xc4, 0x52, 0x84, 0x3b, 0x49, 0x40, + 0x72, 0x2b, 0xb0, 0x6c, 0x9c, 0xdb, 0xc3, 0x43 }; + +static const unsigned char result_nopr[] = + { 0xa5, 0x51, 0x80, 0xa1, 0x90, 0xbe, 0xf3, 0xad, + 0xaf, 0x28, 0xf6, 0xb7, 0x95, 0xe9, 0xf1, 0xf3, + 0xd6, 0xdf, 0xa1, 0xb2, 0x7d, 0xd0, 0x46, 0x7b, + 0x0c, 0x75, 0xf5, 0xfa, 0x93, 0x1e, 0x97, 0x14, + 0x75, 0xb2, 0x7c, 0xae, 0x03, 0xa2, 0x96, 0x54, + 0xe2, 0xf4, 0x09, 0x66, 0xea, 0x33, 0x64, 0x30, + 0x40, 0xd1, 0x40, 0x0f, 0xe6, 0x77, 0x87, 0x3a, + 0xf8, 0x09, 0x7c, 0x1f, 0xe9, 0xf0, 0x02, 0x98 }; +#endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */ + +static size_t test_offset; +static int ctr_drbg_self_test_entropy( void *data, unsigned char *buf, + size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +#define SELF_TEST_OUPUT_DISCARD_LENGTH 64 + +/* + * Checkup routine + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[ sizeof( result_pr ) ]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE ); + mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + pers_pr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_pr ) ) ); + CHK( memcmp( buf, result_pr, sizeof( result_pr ) ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + mbedtls_ctr_drbg_set_entropy_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE); + mbedtls_ctr_drbg_set_nonce_len( &ctx, MBEDTLS_CTR_DRBG_KEYSIZE / 2 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + pers_nopr, MBEDTLS_CTR_DRBG_KEYSIZE ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, SELF_TEST_OUPUT_DISCARD_LENGTH ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, sizeof( result_nopr ) ) ); + CHK( memcmp( buf, result_nopr, sizeof( result_nopr ) ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/debug.c b/component/common/network/ssl/mbedtls-3.1.0/library/debug.c new file mode 100644 index 00000000..fa60d13f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/debug.c @@ -0,0 +1,422 @@ +/* + * Debugging routines + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#define mbedtls_vsnprintf vsnprintf +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define DEBUG_BUF_SIZE 512 + +static int debug_threshold = 0; + +void mbedtls_debug_set_threshold( int threshold ) +{ + debug_threshold = threshold; +} + +/* + * All calls to f_dbg must be made via this function + */ +static inline void debug_send_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *str ) +{ + /* + * If in a threaded environment, we need a thread identifier. + * Since there is no portable way to get one, use the address of the ssl + * context instead, as it shouldn't be shared between threads. + */ +#if defined(MBEDTLS_THREADING_C) + char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */ + mbedtls_snprintf( idstr, sizeof( idstr ), "%p: %s", (void*)ssl, str ); + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, idstr ); +#else + ssl->conf->f_dbg( ssl->conf->p_dbg, level, file, line, str ); +#endif +} + +MBEDTLS_PRINTF_ATTRIBUTE(5, 6) +void mbedtls_debug_print_msg( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *format, ... ) +{ + va_list argp; + char str[DEBUG_BUF_SIZE]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + va_start( argp, format ); + ret = mbedtls_vsnprintf( str, DEBUG_BUF_SIZE, format, argp ); + va_end( argp ); + + if( ret >= 0 && ret < DEBUG_BUF_SIZE - 1 ) + { + str[ret] = '\n'; + str[ret + 1] = '\0'; + } + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_ret( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, int ret ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + /* + * With non-blocking I/O and examples that just retry immediately, + * the logs would be quickly flooded with WANT_READ, so ignore that. + * Don't ignore WANT_WRITE however, since is is usually rare. + */ + if( ret == MBEDTLS_ERR_SSL_WANT_READ ) + return; + + mbedtls_snprintf( str, sizeof( str ), "%s() returned %d (-0x%04x)\n", + text, ret, (unsigned int) -ret ); + + debug_send_line( ssl, level, file, line, str ); +} + +void mbedtls_debug_print_buf( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text, + const unsigned char *buf, size_t len ) +{ + char str[DEBUG_BUF_SIZE]; + char txt[17]; + size_t i, idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "dumping '%s' (%u bytes)\n", + text, (unsigned int) len ); + + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + for( i = 0; i < len; i++ ) + { + if( i >= 4096 ) + break; + + if( i % 16 == 0 ) + { + if( i > 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + + idx = 0; + memset( txt, 0, sizeof( txt ) ); + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, "%04x: ", + (unsigned int) i ); + + } + + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", + (unsigned int) buf[i] ); + txt[i % 16] = ( buf[i] > 31 && buf[i] < 127 ) ? buf[i] : '.' ; + } + + if( len > 0 ) + { + for( /* i = i */; i % 16 != 0; i++ ) + idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " " ); + + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %s\n", txt ); + debug_send_line( ssl, level, file, line, str ); + } +} + +#if defined(MBEDTLS_ECP_C) +void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_ecp_point *X ) +{ + char str[DEBUG_BUF_SIZE]; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + level > debug_threshold ) + { + return; + } + + mbedtls_snprintf( str, sizeof( str ), "%s(X)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->X ); + + mbedtls_snprintf( str, sizeof( str ), "%s(Y)", text ); + mbedtls_debug_print_mpi( ssl, level, file, line, str, &X->Y ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_BIGNUM_C) +void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_mpi *X ) +{ + char str[DEBUG_BUF_SIZE]; + size_t bitlen; + size_t idx = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == X || + level > debug_threshold ) + { + return; + } + + bitlen = mbedtls_mpi_bitlen( X ); + + mbedtls_snprintf( str, sizeof( str ), "value of '%s' (%u bits) is:\n", + text, (unsigned) bitlen ); + debug_send_line( ssl, level, file, line, str ); + + if( bitlen == 0 ) + { + str[0] = ' '; str[1] = '0'; str[2] = '0'; + idx = 3; + } + else + { + int n; + for( n = (int) ( ( bitlen - 1 ) / 8 ); n >= 0; n-- ) + { + size_t limb_offset = n / sizeof( mbedtls_mpi_uint ); + size_t offset_in_limb = n % sizeof( mbedtls_mpi_uint ); + unsigned char octet = + ( X->p[limb_offset] >> ( offset_in_limb * 8 ) ) & 0xff; + mbedtls_snprintf( str + idx, sizeof( str ) - idx, " %02x", octet ); + idx += 3; + /* Wrap lines after 16 octets that each take 3 columns */ + if( idx >= 3 * 16 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + idx = 0; + } + } + } + + if( idx != 0 ) + { + mbedtls_snprintf( str + idx, sizeof( str ) - idx, "\n" ); + debug_send_line( ssl, level, file, line, str ); + } +} +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO) +static void debug_print_pk( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_pk_context *pk ) +{ + size_t i; + mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS]; + char name[16]; + + memset( items, 0, sizeof( items ) ); + + if( mbedtls_pk_debug( pk, items ) != 0 ) + { + debug_send_line( ssl, level, file, line, + "invalid PK context\n" ); + return; + } + + for( i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++ ) + { + if( items[i].type == MBEDTLS_PK_DEBUG_NONE ) + return; + + mbedtls_snprintf( name, sizeof( name ), "%s%s", text, items[i].name ); + name[sizeof( name ) - 1] = '\0'; + + if( items[i].type == MBEDTLS_PK_DEBUG_MPI ) + mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value ); + else +#if defined(MBEDTLS_ECP_C) + if( items[i].type == MBEDTLS_PK_DEBUG_ECP ) + mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value ); + else +#endif + debug_send_line( ssl, level, file, line, + "should not happen\n" ); + } +} + +static void debug_print_line_by_line( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, const char *text ) +{ + char str[DEBUG_BUF_SIZE]; + const char *start, *cur; + + start = text; + for( cur = text; *cur != '\0'; cur++ ) + { + if( *cur == '\n' ) + { + size_t len = cur - start + 1; + if( len > DEBUG_BUF_SIZE - 1 ) + len = DEBUG_BUF_SIZE - 1; + + memcpy( str, start, len ); + str[len] = '\0'; + + debug_send_line( ssl, level, file, line, str ); + + start = cur + 1; + } + } +} + +void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const char *text, const mbedtls_x509_crt *crt ) +{ + char str[DEBUG_BUF_SIZE]; + int i = 0; + + if( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == crt || + level > debug_threshold ) + { + return; + } + + while( crt != NULL ) + { + char buf[1024]; + + mbedtls_snprintf( str, sizeof( str ), "%s #%d:\n", text, ++i ); + debug_send_line( ssl, level, file, line, str ); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + debug_print_line_by_line( ssl, level, file, line, buf ); + + debug_print_pk( ssl, level, file, line, "crt->", &crt->pk ); + + crt = crt->next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */ + +#if defined(MBEDTLS_ECDH_C) +static void mbedtls_debug_printf_ecdh_internal( const mbedtls_ssl_context *ssl, + int level, const char *file, + int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + const mbedtls_ecdh_context* ctx = ecdh; +#else + const mbedtls_ecdh_context_mbed* ctx = &ecdh->ctx.mbed_ecdh; +#endif + + switch( attr ) + { + case MBEDTLS_DEBUG_ECDH_Q: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Q", + &ctx->Q ); + break; + case MBEDTLS_DEBUG_ECDH_QP: + mbedtls_debug_print_ecp( ssl, level, file, line, "ECDH: Qp", + &ctx->Qp ); + break; + case MBEDTLS_DEBUG_ECDH_Z: + mbedtls_debug_print_mpi( ssl, level, file, line, "ECDH: z", + &ctx->z ); + break; + default: + break; + } +} + +void mbedtls_debug_printf_ecdh( const mbedtls_ssl_context *ssl, int level, + const char *file, int line, + const mbedtls_ecdh_context *ecdh, + mbedtls_debug_ecdh_attr attr ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, attr ); +#else + switch( ecdh->var ) + { + default: + mbedtls_debug_printf_ecdh_internal( ssl, level, file, line, ecdh, + attr ); + } +#endif +} +#endif /* MBEDTLS_ECDH_C */ + +#endif /* MBEDTLS_DEBUG_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/des.c b/component/common/network/ssl/mbedtls-3.1.0/library/des.c new file mode 100644 index 00000000..91d22b5d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/des.c @@ -0,0 +1,1062 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_DES_ALT) + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ + do \ + { \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + (Y) = (((Y) << 1) | ((Y) >> 31)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (Y) ^= T; (X) ^= T; \ + (X) = (((X) << 1) | ((X) >> 31)) & 0xFFFFFFFF; \ + } while( 0 ) + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ + do \ + { \ + (X) = (((X) << 31) | ((X) >> 1)) & 0xFFFFFFFF; \ + T = ((X) ^ (Y)) & 0xAAAAAAAA; (X) ^= T; (Y) ^= T; \ + (Y) = (((Y) << 31) | ((Y) >> 1)) & 0xFFFFFFFF; \ + T = (((Y) >> 8) ^ (X)) & 0x00FF00FF; (X) ^= T; (Y) ^= (T << 8); \ + T = (((Y) >> 2) ^ (X)) & 0x33333333; (X) ^= T; (Y) ^= (T << 2); \ + T = (((X) >> 16) ^ (Y)) & 0x0000FFFF; (Y) ^= T; (X) ^= (T << 16); \ + T = (((X) >> 4) ^ (Y)) & 0x0F0F0F0F; (Y) ^= T; (X) ^= (T << 4); \ + } while( 0 ) + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ + do \ + { \ + T = *SK++ ^ (X); \ + (Y) ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ (((X) << 28) | ((X) >> 4)); \ + (Y) ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ + } while( 0 ) + +#define SWAP(a,b) \ + do \ + { \ + uint32_t t = (a); (a) = (b); (b) = t; t = 0; \ + } while( 0 ) + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + X = MBEDTLS_GET_UINT32_BE( key, 0 ); + Y = MBEDTLS_GET_UINT32_BE( key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + X = MBEDTLS_GET_UINT32_BE( input, 0 ); + Y = MBEDTLS_GET_UINT32_BE( input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + MBEDTLS_PUT_UINT32_BE( Y, output, 0 ); + MBEDTLS_PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + ret = mbedtls_des_crypt_ecb( ctx, output, output ); + if( ret != 0 ) + goto exit; + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + ret = mbedtls_des_crypt_ecb( ctx, input, output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + X = MBEDTLS_GET_UINT32_BE( input, 0 ); + Y = MBEDTLS_GET_UINT32_BE( input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + MBEDTLS_PUT_UINT32_BE( Y, output, 0 ); + MBEDTLS_PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + ret = mbedtls_des3_crypt_ecb( ctx, output, output ); + if( ret != 0 ) + goto exit; + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + ret = mbedtls_des3_crypt_ecb( ctx, input, output ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + ret = 0; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0x37, 0x2B, 0x98, 0xBF, 0x52, 0x65, 0xB0, 0x59 }, + { 0xC2, 0x10, 0x19, 0x9C, 0x38, 0x5A, 0x65, 0xA1 }, + { 0xA2, 0x70, 0x56, 0x68, 0x69, 0xE5, 0x15, 0x1D } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x1C, 0xD5, 0x97, 0xEA, 0x84, 0x26, 0x73, 0xFB }, + { 0xB3, 0x92, 0x4D, 0xF3, 0xC5, 0xB5, 0x42, 0x93 }, + { 0xDA, 0x37, 0x64, 0x41, 0xBA, 0x6F, 0x62, 0x6F } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x58, 0xD9, 0x48, 0xEF, 0x85, 0x14, 0x65, 0x9A }, + { 0x5F, 0xC8, 0x78, 0xD4, 0xD7, 0x92, 0xD9, 0x54 }, + { 0x25, 0xF9, 0x75, 0x85, 0xA8, 0x1E, 0x48, 0xBF } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x91, 0x1C, 0x6D, 0xCF, 0x48, 0xA7, 0xC3, 0x4D }, + { 0x60, 0x1A, 0x76, 0x8F, 0xA1, 0xF9, 0x66, 0xF1 }, + { 0xA1, 0x50, 0x0F, 0x99, 0xB2, 0xCD, 0x64, 0x76 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + if( ret != 0 ) + goto exit; + + for( j = 0; j < 100; j++ ) + { + if( u == 0 ) + ret = mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + ret = mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + ret = mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + ret = mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + ret = mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + ret = mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + ret = mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + ret = mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + if( ret != 0 ) + goto exit; + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 100; j++ ) + { + if( u == 0 ) + ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + if( ret != 0 ) + goto exit; + } + } + else + { + for( j = 0; j < 100; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + ret = mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + ret = mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + if( ret != 0 ) + ret = 1; + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/dhm.c b/component/common/network/ssl/mbedtls-3.1.0/library/dhm.c new file mode 100644 index 00000000..2ce0ed4f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/dhm.c @@ -0,0 +1,748 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The following sources were referenced in the design of this implementation + * of the Diffie-Hellman-Merkle algorithm: + * + * [1] Handbook of Applied Cryptography - 1997, Chapter 12 + * Menezes, van Oorschot and Vanstone + * + */ + +#include "common.h" + +#if defined(MBEDTLS_DHM_C) + +#include "mbedtls/dhm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_DHM_ALT) + +#define DHM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) +#define DHM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * helper to validate the mbedtls_mpi size and import it + */ +static int dhm_read_bignum( mbedtls_mpi *X, + unsigned char **p, + const unsigned char *end ) +{ + int ret, n; + + if( end - *p < 2 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + n = ( (*p)[0] << 8 ) | (*p)[1]; + (*p) += 2; + + if( (int)( end - *p ) < n ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret ) ); + + (*p) += n; + + return( 0 ); +} + +/* + * Verify sanity of parameter with regards to P + * + * Parameter should be: 2 <= public_param <= P - 2 + * + * This means that we need to return an error if + * public_param < 2 or public_param > P-2 + * + * For more information on the attack, see: + * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf + * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 + */ +static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) +{ + mbedtls_mpi U; + int ret = 0; + + mbedtls_mpi_init( &U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); + + if( mbedtls_mpi_cmp_int( param, 2 ) < 0 || + mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) + { + ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; + } + +cleanup: + mbedtls_mpi_free( &U ); + return( ret ); +} + +void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) +{ + DHM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); +} + +size_t mbedtls_dhm_get_bitlen( const mbedtls_dhm_context *ctx ) +{ + return( mbedtls_mpi_bitlen( &ctx->P ) ); +} + +size_t mbedtls_dhm_get_len( const mbedtls_dhm_context *ctx ) +{ + return( mbedtls_mpi_size( &ctx->P ) ); +} + +int mbedtls_dhm_get_value( const mbedtls_dhm_context *ctx, + mbedtls_dhm_parameter param, + mbedtls_mpi *dest ) +{ + const mbedtls_mpi *src = NULL; + switch( param ) + { + case MBEDTLS_DHM_PARAM_P: + src = &ctx->P; + break; + case MBEDTLS_DHM_PARAM_G: + src = &ctx->G; + break; + case MBEDTLS_DHM_PARAM_X: + src = &ctx->X; + break; + case MBEDTLS_DHM_PARAM_GX: + src = &ctx->GX; + break; + case MBEDTLS_DHM_PARAM_GY: + src = &ctx->GY; + break; + case MBEDTLS_DHM_PARAM_K: + src = &ctx->K; + break; + default: + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + } + return( mbedtls_mpi_copy( dest, src ) ); +} + +/* + * Parse the ServerKeyExchange parameters + */ +int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, + unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( p != NULL && *p != NULL ); + DHM_VALIDATE_RET( end != NULL ); + + if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || + ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) + return( ret ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Pick a random R in the range [2, M-2] for blinding or key generation. + */ +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_random( R, 3, M, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( R, R, 1 ) ); + +cleanup: + return( ret ); +} + +static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + + if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + if( x_size < 0 ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); + } + else + { + /* Generate X as large as possible ( <= P - 2 ) */ + ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng ); + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); + if( ret != 0 ) + return( ret ); + } + + /* + * Calculate GX = G^X mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, + &ctx->P , &ctx->RP ) ); + + if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) + return( ret ); + +cleanup: + return( ret ); +} + +/* + * Setup and write the ServerKeyExchange parameters + */ +int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n1, n2, n3; + unsigned char *p; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + ret = dhm_make_common( ctx, x_size, f_rng, p_rng ); + if( ret != 0 ) + goto cleanup; + + /* + * Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are + * not required". We omit leading zeros for compactness. + */ +#define DHM_MPI_EXPORT( X, n ) \ + do { \ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ + p + 2, \ + ( n ) ) ); \ + *p++ = MBEDTLS_BYTE_1( n ); \ + *p++ = MBEDTLS_BYTE_0( n ); \ + p += ( n ); \ + } while( 0 ) + + n1 = mbedtls_mpi_size( &ctx->P ); + n2 = mbedtls_mpi_size( &ctx->G ); + n3 = mbedtls_mpi_size( &ctx->GX ); + + p = output; + DHM_MPI_EXPORT( &ctx->P , n1 ); + DHM_MPI_EXPORT( &ctx->G , n2 ); + DHM_MPI_EXPORT( &ctx->GX, n3 ); + + *olen = p - output; + +cleanup: + if( ret != 0 && ret > -128 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret ); + return( ret ); +} + +/* + * Set prime modulus and generator + */ +int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, + const mbedtls_mpi *P, + const mbedtls_mpi *G ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( P != NULL ); + DHM_VALIDATE_RET( G != NULL ); + + if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret ) ); + } + + return( 0 ); +} + +/* + * Import the peer's public value G^Y + */ +int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, + const unsigned char *input, size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( input != NULL ); + + if( ilen < 1 || ilen > mbedtls_dhm_get_len( ctx ) ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Create own private value X and export G^X + */ +int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, + unsigned char *output, size_t olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( f_rng != NULL ); + + if( olen < 1 || olen > mbedtls_dhm_get_len( ctx ) ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + ret = dhm_make_common( ctx, x_size, f_rng, p_rng ); + if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ) + return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); + if( ret != 0 ) + goto cleanup; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); + +cleanup: + if( ret != 0 && ret > -128 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret ); + return( ret ); +} + + +/* + * Use the blinding method and optimisation suggested in section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int dhm_update_blinding( mbedtls_dhm_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + /* + * Don't use any blinding the first time a particular X is used, + * but remember it to use blinding next time. + */ + if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); + + return( 0 ); + } + + /* + * Ok, we need blinding. Can we re-use existing values? + * If yes, just update them by squaring them. + */ + if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + return( 0 ); + } + + /* + * We need to generate blinding values from scratch + */ + + /* Vi = random( 2, P-2 ) */ + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); + + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Derive and export the shared secret (G^Y)^X mod P + */ +int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, + unsigned char *output, size_t output_size, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi GYb; + DHM_VALIDATE_RET( ctx != NULL ); + DHM_VALIDATE_RET( output != NULL ); + DHM_VALIDATE_RET( olen != NULL ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( output_size < mbedtls_dhm_get_len( ctx ) ) + return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); + + if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) + return( ret ); + + mbedtls_mpi_init( &GYb ); + + /* Blind peer's value */ + MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); + + /* Do modular exponentiation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, + &ctx->P, &ctx->RP ) ); + + /* Unblind secret value */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); + + /* Output the secret without any leading zero byte. This is mandatory + * for TLS per RFC 5246 §8.1.2. */ + *olen = mbedtls_mpi_size( &ctx->K ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); + +cleanup: + mbedtls_mpi_free( &GYb ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Free the components of a DHM key + */ +void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->pX ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->K ); + mbedtls_mpi_free( &ctx->GY ); + mbedtls_mpi_free( &ctx->GX ); + mbedtls_mpi_free( &ctx->X ); + mbedtls_mpi_free( &ctx->G ); + mbedtls_mpi_free( &ctx->P ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +/* + * Parse DHM parameters + */ +int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, + size_t dhminlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end; +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_context pem; +#endif /* MBEDTLS_PEM_PARSE_C */ + + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( dhmin != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN DH PARAMETERS-----", + "-----END DH PARAMETERS-----", + dhmin, NULL, 0, &dhminlen ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + dhminlen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + goto exit; + + p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; +#else + p = (unsigned char *) dhmin; +#endif /* MBEDTLS_PEM_PARSE_C */ + end = p + dhminlen; + + /* + * DHParams ::= SEQUENCE { + * prime INTEGER, -- P + * generator INTEGER, -- g + * privateValueLength INTEGER OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret ); + goto exit; + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret ); + goto exit; + } + + if( p != end ) + { + /* This might be the optional privateValueLength. + * If so, we can cleanly discard it */ + mbedtls_mpi rec; + mbedtls_mpi_init( &rec ); + ret = mbedtls_asn1_get_mpi( &p, end, &rec ); + mbedtls_mpi_free( &rec ); + if ( ret != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, ret ); + goto exit; + } + if ( p != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_DHM_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + goto exit; + } + } + + ret = 0; + +exit: +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + if( ret != 0 ) + mbedtls_dhm_free( dhm ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +static int load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n + 1 ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse DHM parameters + */ +int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + DHM_VALIDATE_RET( dhm != NULL ); + DHM_VALIDATE_RET( path != NULL ); + + if( ( ret = load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_ASN1_PARSE_C */ +#endif /* MBEDTLS_DHM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PEM_PARSE_C) +static const char mbedtls_test_dhm_params[] = +"-----BEGIN DH PARAMETERS-----\r\n" +"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" +"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" +"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" +"-----END DH PARAMETERS-----\r\n"; +#else /* MBEDTLS_PEM_PARSE_C */ +static const char mbedtls_test_dhm_params[] = { + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, + 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, + 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, + 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, + 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, + 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, + 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, + 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, + 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, + 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, + 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, + 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; +#endif /* MBEDTLS_PEM_PARSE_C */ + +static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); + +/* + * Checkup routine + */ +int mbedtls_dhm_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_dhm_context dhm; + + mbedtls_dhm_init( &dhm ); + + if( verbose != 0 ) + mbedtls_printf( " DHM parameter load: " ); + + if( ( ret = mbedtls_dhm_parse_dhm( &dhm, + (const unsigned char *) mbedtls_test_dhm_params, + mbedtls_test_dhm_params_len ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + +exit: + mbedtls_dhm_free( &dhm ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DHM_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecdh.c b/component/common/network/ssl/mbedtls-3.1.0/library/ecdh.c new file mode 100644 index 00000000..d1680b5c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecdh.c @@ -0,0 +1,866 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#include "common.h" + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/ecdh.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "ecdh_misc.h" + +#include + +/* Parameter validation macros based on platform_util.h */ +#define ECDH_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDH_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) +typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; +#endif + +static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( + const mbedtls_ecdh_context *ctx ) +{ +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ctx->grp.id ); +#else + return( ctx->grp_id ); +#endif +} + +int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ) +{ + /* At this time, all groups support ECDH. */ + (void) gid; + return( 1 ); +} + +#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) +/* + * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' across continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key + */ +int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ + +#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) +/* + * Compute shared secret (SEC1 3.3.1) + */ +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point P; + + mbedtls_ecp_point_init( &P ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); + + if( mbedtls_ecp_is_zero( &P ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); + +cleanup: + mbedtls_ecp_point_free( &P ); + + return( ret ); +} + +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDH_VALIDATE_RET( grp != NULL ); + ECDH_VALIDATE_RET( Q != NULL ); + ECDH_VALIDATE_RET( d != NULL ); + ECDH_VALIDATE_RET( z != NULL ); + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ + +static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif +} + +/* + * Initialize context + */ +void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + ecdh_init_internal( ctx ); + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); +#else + memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; +#endif + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; +#endif +} + +static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, + mbedtls_ecp_group_id grp_id ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); + if( ret != 0 ) + { + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +/* + * Setup context + */ +int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + switch( grp_id ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; + ctx->grp_id = grp_id; + return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) ); +#endif + default: + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); + } +#endif +} + +static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) +{ + mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); + mbedtls_ecp_point_free( &ctx->Q ); + mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_mpi_free( &ctx->z ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Enable restartable operations for context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ECDH_VALIDATE( ctx != NULL ); + + ctx->restart_enabled = 1; +} +#endif + +/* + * Free context + */ +void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + mbedtls_ecp_point_free( &ctx->Vi ); + mbedtls_ecp_point_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->_d ); + ecdh_free_internal( ctx ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + mbedtls_everest_free( &ctx->ctx.everest_ecdh ); + break; +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + ecdh_free_internal( &ctx->ctx.mbed_ecdh ); + break; + default: + break; + } + + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_NONE; + ctx->grp_id = MBEDTLS_ECP_DP_NONE; +#endif +} + +static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t grp_len, pt_len; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, + blen ) ) != 0 ) + return( ret ); + + buf += grp_len; + blen -= grp_len; + + if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, + &pt_len, buf, blen ) ) != 0 ) + return( ret ); + + *olen = grp_len + pt_len; + return( 0 ); +} + +/* + * Setup and write the ServerKeyExchange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, + end - *buf ) ); +} + +/* + * Read the ServerKeyExhange parameters (RFC 4492) + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ +int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, + const unsigned char **buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( *buf != NULL ); + ECDH_VALIDATE_RET( end != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) + != 0 ) + return( ret ); + + if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_params_internal( ctx, buf, end ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh, + buf, end) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, + buf, end ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* If it's not our key, just import the public part as Qp */ + if( side == MBEDTLS_ECDH_THEIRS ) + return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); + + /* Our key: import public (as Q) and private parts */ + if( side != MBEDTLS_ECDH_OURS ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Get parameters from a keypair + */ +int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, + const mbedtls_ecp_keypair *key, + mbedtls_ecdh_side side ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( key != NULL ); + ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || + side == MBEDTLS_ECDH_THEIRS ); + + if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) + { + /* This is the first call to get_params(). Set up the context + * for use with the group. */ + if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) + return( ret ); + } + else + { + /* This is not the first call to get_params(). Check that the + * current key's group is the same as the context's, which was set + * from the first key's group. */ + if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_get_params_internal( ctx, key, side ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + { + mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? + MBEDTLS_EVEREST_ECDH_OURS : + MBEDTLS_EVEREST_ECDH_THEIRS; + return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh, + key, s) ); + } +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, + key, side ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, int point_format, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) + return( ret ); +#else + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, + buf, blen ); +} + +/* + * Setup and export the client public value + */ +int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, + f_rng, p_rng, restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, + ctx->point_format, buf, blen, + f_rng, p_rng, + restart_enabled ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + + if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, + blen ) ) != 0 ) + return( ret ); + + if( (size_t)( p - buf ) != blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Parse and import the client's public value + */ +int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, size_t blen ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_read_public_internal( ctx, buf, blen ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh, + buf, blen ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, blen ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *olen, unsigned char *buf, + size_t blen, + int (*f_rng)(void *, + unsigned char *, + size_t), + void *p_rng, + int restart_enabled ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx *rs_ctx = NULL; +#endif + + if( ctx == NULL || ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( restart_enabled ) + rs_ctx = &ctx->rs; +#else + (void) restart_enabled; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng, + rs_ctx ) ) != 0 ) + { + return( ret ); + } +#else + if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, + &ctx->d, f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + if( mbedtls_mpi_size( &ctx->z ) > blen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); + + if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen ); + + return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); +} + +/* + * Derive and export the shared secret + */ +int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int restart_enabled = 0; + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( olen != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + restart_enabled = ctx->restart_enabled; +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, + restart_enabled ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen, + buf, blen, f_rng, p_rng ) ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, + blen, f_rng, p_rng, + restart_enabled ) ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +#endif +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx, + size_t *out_len, int point_format, + unsigned char *buf, size_t buf_len, + int ( *f_rng )( void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ctx->grp.pbits == 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng ) ) != 0 ) + return( ret ); + + ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format, + out_len, buf, buf_len ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *out_len, + unsigned char *buf, size_t buf_len, + int ( *f_rng )( void *, unsigned char *, size_t ), + void *p_rng ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( out_len != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + ECDH_VALIDATE_RET( f_rng != NULL ); + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ctx-> restart_enabled ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_tls13_make_params_internal( ctx, out_len, ctx->point_format, + buf, buf_len, f_rng, p_rng ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_tls13_make_params_internal( &ctx->ctx.mbed_ecdh, + out_len, ctx->point_format, + buf, buf_len, f_rng, p_rng ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +/* + * Setup context without Everest + */ +int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_setup_internal( ctx, grp_id ) ); +#else + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; + ctx->grp_id = grp_id; + ecdh_init_internal( &ctx->ctx.mbed_ecdh ); + return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); +#endif +} + +static int ecdh_tls13_read_public_internal( mbedtls_ecdh_context_mbed *ctx, + const unsigned char *buf, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t data_len; + + if( buf_len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + if( data_len < 1 || data_len != ( buf_len - 2 ) ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_read_binary( &ctx->grp, + &ctx->Qp, p, data_len ) ) != 0) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Parse and import the client's TLS 1.3 public value + */ +int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, + size_t buf_len ) +{ + ECDH_VALIDATE_RET( ctx != NULL ); + ECDH_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + return( ecdh_tls13_read_public_internal( ctx, buf, buf_len ) ); +#else + switch( ctx->var ) + { +#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) + case MBEDTLS_ECDH_VARIANT_EVEREST: + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif + case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: + return( ecdh_tls13_read_public_internal( &ctx->ctx.mbed_ecdh, + buf, buf_len ) ); + default: + return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + } +#endif +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#endif /* MBEDTLS_ECDH_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecdh_misc.h b/component/common/network/ssl/mbedtls-3.1.0/library/ecdh_misc.h new file mode 100644 index 00000000..37cb6d8e --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecdh_misc.h @@ -0,0 +1,57 @@ +/** + * \file ecdh_misc.h + * + * \brief Internal functions shared by the ECDH module + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#if !defined(MBEDTLS_ECDH_MISC_H) +#define MBEDTLS_ECDH_MISC_H + +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_ECDH_C) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +/* + * Setup context without Everest + */ +int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx, + mbedtls_ecp_group_id grp_id ); + +/* + * TLS 1.3 version of mbedtls_ecdh_make_params + */ +int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen, + unsigned char *buf, size_t buf_len, + int ( *f_rng )( void *, unsigned char *, size_t ), + void *p_rng ); + +/* + * TLS 1.3 version of mbedtls_ecdh_read_public + */ +int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx, + const unsigned char *buf, + size_t buf_len ); + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#endif /* MBEDTLS_ECDH_C */ + +#endif /* !MBEDTLS_ECDH_MISC_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecdsa.c b/component/common/network/ssl/mbedtls-3.1.0/library/ecdsa.c new file mode 100644 index 00000000..0b612ce8 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecdsa.c @@ -0,0 +1,929 @@ +/* + * Elliptic curve DSA + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#include "common.h" + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* Parameter validation macros based on platform_util.h */ +#define ECDSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECDSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/* + * Sub-context for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + + ecdsa_restart_ver_init( ctx ); +} + +/* + * Sub-context for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + ctx->sign_tries = 0; + ctx->key_tries = 0; + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-context for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + + ecdsa_restart_det_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#define ECDSA_RS_ECP ( rs_ctx == NULL ? NULL : &rs_ctx->ecp ) + +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) ); + +/* Call this when entering a function that needs its own sub-context */ +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \ + !defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} +#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */ + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + + /* jump to current step */ + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + *p_sign_tries = 0; + do + { + if( (*p_sign_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + *p_key_tries = 0; + do + { + if( (*p_key_tries)++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_mul; + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng_blind, + p_rng_blind, + ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state = ecdsa_sig_modn; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind, + p_rng_blind ) ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); +#endif + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + ECDSA_RS_LEAVE( sig ); + + return( ret ); +} + +int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid ) +{ + switch( gid ) + { +#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED + case MBEDTLS_ECP_DP_CURVE25519: return 0; +#endif +#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED + case MBEDTLS_ECP_DP_CURVE448: return 0; +#endif + default: return 1; + } +} + +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + /* Use the same RNG for both blinding and ephemeral key generation */ + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, f_rng, p_rng, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + * + * note: The f_rng_blind parameter must not be NULL. + * + */ +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, size_t), + void *p_rng_blind, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + p_rng = &rs_ctx->det->rng_ctx; + + /* jump to current step */ + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state = ecdsa_det_sign; + +sign: +#endif +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) f_rng_blind; + (void) p_rng_blind; + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng ); +#else + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, p_rng, + f_rng_blind, p_rng_blind, rs_ctx ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + ECDSA_RS_LEAVE( det ); + + return( ret ); +} + +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r, + mbedtls_mpi *s, const mbedtls_mpi *d, + const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg, + int (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( d != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + ECDSA_VALIDATE_RET( f_rng_blind != NULL ); + + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, + f_rng_blind, p_rng_blind, NULL ) ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + ECDSA_RS_ENTER( ver ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state = ecdsa_ver_muladd; + +muladd: +#endif + /* + * Step 5: R = u1 G + u2 Q + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + ECDSA_RS_LEAVE( ver ); + + return( ret ); +} + +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, + const mbedtls_mpi *s) +{ + ECDSA_VALIDATE_RET( grp != NULL ); + ECDSA_VALIDATE_RET( Q != NULL ); + ECDSA_VALIDATE_RET( r != NULL ); + ECDSA_VALIDATE_RET( s != NULL ); + ECDSA_VALIDATE_RET( buf != NULL || blen == 0 ); + + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} +#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t sig_size, + size_t *slen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = {0}; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + if( len > sig_size ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, f_rng, + p_rng, rs_ctx ) ); +#else + (void) md_alg; + +#if defined(MBEDTLS_ECDSA_SIGN_ALT) + (void) rs_ctx; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#else + /* Use the same RNG for both blinding and ephemeral key generation */ + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, f_rng, + p_rng, rs_ctx ) ); +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, sig_size, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t sig_size, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + ECDSA_VALIDATE_RET( slen != NULL ); + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, sig_size, slen, + f_rng, p_rng, NULL ) ); +} + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( hash != NULL ); + ECDSA_VALIDATE_RET( sig != NULL ); + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_ECP_BAD_INPUT_DATA, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } +#if defined(MBEDTLS_ECDSA_VERIFY_ALT) + (void) rs_ctx; + + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; +#else + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = 0; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( f_rng != NULL ); + + ret = mbedtls_ecp_group_load( &ctx->grp, gid ); + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, + &ctx->Q, f_rng, p_rng ) ); +} +#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECDSA_VALIDATE_RET( ctx != NULL ); + ECDSA_VALIDATE_RET( key != NULL ); + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_keypair_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + ECDSA_VALIDATE( ctx != NULL ); + + mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_ECDSA_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecjpake.c b/component/common/network/ssl/mbedtls-3.1.0/library/ecjpake.c new file mode 100644 index 00000000..738a9771 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecjpake.c @@ -0,0 +1,1177 @@ +/* + * Elliptic curve J-PAKE + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * References in the code are to the Thread v1.0 Specification, + * available to members of the Thread Group http://threadgroup.org/ + */ + +#include "common.h" + +#if defined(MBEDTLS_ECJPAKE_C) + +#include "mbedtls/ecjpake.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECJPAKE_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECJPAKE_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Convert a mbedtls_ecjpake_role to identifier string + */ +static const char * const ecjpake_id[] = { + "client", + "server" +}; + +#define ID_MINE ( ecjpake_id[ ctx->role ] ) +#define ID_PEER ( ecjpake_id[ 1 - ctx->role ] ) + +/* + * Initialize context + */ +void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE( ctx != NULL ); + + ctx->md_info = NULL; + mbedtls_ecp_group_init( &ctx->grp ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + + mbedtls_ecp_point_init( &ctx->Xm1 ); + mbedtls_ecp_point_init( &ctx->Xm2 ); + mbedtls_ecp_point_init( &ctx->Xp1 ); + mbedtls_ecp_point_init( &ctx->Xp2 ); + mbedtls_ecp_point_init( &ctx->Xp ); + + mbedtls_mpi_init( &ctx->xm1 ); + mbedtls_mpi_init( &ctx->xm2 ); + mbedtls_mpi_init( &ctx->s ); +} + +/* + * Free context + */ +void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->md_info = NULL; + mbedtls_ecp_group_free( &ctx->grp ); + + mbedtls_ecp_point_free( &ctx->Xm1 ); + mbedtls_ecp_point_free( &ctx->Xm2 ); + mbedtls_ecp_point_free( &ctx->Xp1 ); + mbedtls_ecp_point_free( &ctx->Xp2 ); + mbedtls_ecp_point_free( &ctx->Xp ); + + mbedtls_mpi_free( &ctx->xm1 ); + mbedtls_mpi_free( &ctx->xm2 ); + mbedtls_mpi_free( &ctx->s ); +} + +/* + * Setup context + */ +int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx, + mbedtls_ecjpake_role role, + mbedtls_md_type_t hash, + mbedtls_ecp_group_id curve, + const unsigned char *secret, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( role == MBEDTLS_ECJPAKE_CLIENT || + role == MBEDTLS_ECJPAKE_SERVER ); + ECJPAKE_VALIDATE_RET( secret != NULL || len == 0 ); + + ctx->role = role; + + if( ( ctx->md_info = mbedtls_md_info_from_type( hash ) ) == NULL ) + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, curve ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->s, secret, len ) ); + +cleanup: + if( ret != 0 ) + mbedtls_ecjpake_free( ctx ); + + return( ret ); +} + +int mbedtls_ecjpake_set_point_format( mbedtls_ecjpake_context *ctx, + int point_format ) +{ + switch( point_format ) + { + case MBEDTLS_ECP_PF_UNCOMPRESSED: + case MBEDTLS_ECP_PF_COMPRESSED: + ctx->point_format = point_format; + return( 0 ); + default: + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } +} + +/* + * Check if context is ready for use + */ +int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + + if( ctx->md_info == NULL || + ctx->grp.id == MBEDTLS_ECP_DP_NONE || + ctx->s.p == NULL ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Write a point plus its length to a buffer + */ +static int ecjpake_write_len_point( unsigned char **p, + const unsigned char *end, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *P ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Need at least 4 for length plus 1 for point */ + if( end < *p || end - *p < 5 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + ret = mbedtls_ecp_point_write_binary( grp, P, pf, + &len, *p + 4, end - ( *p + 4 ) ); + if( ret != 0 ) + return( ret ); + + MBEDTLS_PUT_UINT32_BE( len, *p, 0 ); + + *p += 4 + len; + + return( 0 ); +} + +/* + * Size of the temporary buffer for ecjpake_hash: + * 3 EC points plus their length, plus ID and its length (4 + 6 bytes) + */ +#define ECJPAKE_HASH_BUF_LEN ( 3 * ( 4 + MBEDTLS_ECP_MAX_PT_LEN ) + 4 + 6 ) + +/* + * Compute hash for ZKP (7.4.2.2.2.1) + */ +static int ecjpake_hash( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *V, + const mbedtls_ecp_point *X, + const char *id, + mbedtls_mpi *h ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[ECJPAKE_HASH_BUF_LEN]; + unsigned char *p = buf; + const unsigned char *end = buf + sizeof( buf ); + const size_t id_len = strlen( id ); + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Write things to temporary buffer */ + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, G ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, V ) ); + MBEDTLS_MPI_CHK( ecjpake_write_len_point( &p, end, grp, pf, X ) ); + + if( end - p < 4 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + MBEDTLS_PUT_UINT32_BE( id_len, p, 0 ); + p += 4; + + if( end < p || (size_t)( end - p ) < id_len ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + memcpy( p, id, id_len ); + p += id_len; + + /* Compute hash */ + MBEDTLS_MPI_CHK( mbedtls_md( md_info, buf, p - buf, hash ) ); + + /* Turn it into an integer mod n */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( h, hash, + mbedtls_md_get_size( md_info ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( h, h, &grp->N ) ); + +cleanup: + return( ret ); +} + +/* + * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3) + */ +static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point V, VV; + mbedtls_mpi r, h; + size_t r_len; + + mbedtls_ecp_point_init( &V ); + mbedtls_ecp_point_init( &VV ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &h ); + + /* + * struct { + * ECPoint V; + * opaque r<1..2^8-1>; + * } ECSchnorrZKP; + */ + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V, p, end - *p ) ); + + if( end < *p || (size_t)( end - *p ) < 1 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + r_len = *(*p)++; + + if( end < *p || (size_t)( end - *p ) < r_len || r_len == 0 ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) ); + *p += r_len; + + /* + * Verification + */ + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp, + &VV, &h, X, &r, G ) ); + + if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_ecp_point_free( &VV ); + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2) + */ +static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + const mbedtls_mpi *x, + const mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point V; + mbedtls_mpi v; + mbedtls_mpi h; /* later recycled to hold r */ + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &V ); + mbedtls_mpi_init( &v ); + mbedtls_mpi_init( &h ); + + /* Compute signature */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, + G, &v, &V, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, pf, G, &V, X, id, &h ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &h, &h, x ) ); /* x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &h, &v, &h ) ); /* v - x*h */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &h, &h, &grp->N ) ); /* r */ + + /* Write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, &V, + pf, &len, *p, end - *p ) ); + *p += len; + + len = mbedtls_mpi_size( &h ); /* actually r */ + if( end < *p || (size_t)( end - *p ) < 1 + len || len > 255 ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + *(*p)++ = MBEDTLS_BYTE_0( len ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, *p, len ) ); /* r */ + *p += len; + +cleanup: + mbedtls_ecp_point_free( &V ); + mbedtls_mpi_free( &v ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Parse a ECJPAKEKeyKP (7.4.2.2.1) and check proof + * Output: verified public key X + */ +static int ecjpake_kkp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *X, + const char *id, + const unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * struct { + * ECPoint X; + * ECSchnorrZKP zkp; + * } ECJPAKEKeyKP; + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, X, p, end - *p ) ); + if( mbedtls_ecp_is_zero( X ) ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, grp, pf, G, X, id, p, end ) ); + +cleanup: + return( ret ); +} + +/* + * Generate an ECJPAKEKeyKP + * Output: the serialized structure, plus private/public key pair + */ +static int ecjpake_kkp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *x, + mbedtls_ecp_point *X, + const char *id, + unsigned char **p, + const unsigned char *end, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( end < *p ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* Generate key (7.4.2.3.1) and write it out */ + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( (mbedtls_ecp_group *) grp, G, x, X, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( grp, X, + pf, &len, *p, end - *p ) ); + *p += len; + + /* Generate and write proof */ + MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, grp, pf, G, x, X, id, + p, end, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Read a ECJPAKEKeyKPPairList (7.4.2.3) and check proofs + * Ouputs: verified peer public keys Xa, Xb + */ +static int ecjpake_kkpp_read( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_ecp_point *Xa, + mbedtls_ecp_point *Xb, + const char *id, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + + /* + * struct { + * ECJPAKEKeyKP ecjpake_key_kp_pair_list[2]; + * } ECJPAKEKeyKPPairList; + */ + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xa, id, &p, end ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_read( md_info, grp, pf, G, Xb, id, &p, end ) ); + + if( p != end ) + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + +cleanup: + return( ret ); +} + +/* + * Generate a ECJPAKEKeyKPPairList + * Outputs: the serialized structure, plus two private/public key pairs + */ +static int ecjpake_kkpp_write( const mbedtls_md_info_t *md_info, + const mbedtls_ecp_group *grp, + const int pf, + const mbedtls_ecp_point *G, + mbedtls_mpi *xm1, + mbedtls_ecp_point *Xa, + mbedtls_mpi *xm2, + mbedtls_ecp_point *Xb, + const char *id, + unsigned char *buf, + size_t len, + size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + const unsigned char *end = buf + len; + + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm1, Xa, id, + &p, end, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecjpake_kkp_write( md_info, grp, pf, G, xm2, Xb, id, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + return( ret ); +} + +/* + * Read and process the first round message + */ +int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + return( ecjpake_kkpp_read( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->Xp1, &ctx->Xp2, ID_PEER, + buf, len ) ); +} + +/* + * Generate and write the first round message + */ +int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + return( ecjpake_kkpp_write( ctx->md_info, &ctx->grp, ctx->point_format, + &ctx->grp.G, + &ctx->xm1, &ctx->Xm1, &ctx->xm2, &ctx->Xm2, + ID_MINE, buf, len, olen, f_rng, p_rng ) ); +} + +/* + * Compute the sum of three points R = A + B + C + */ +static int ecjpake_ecp_add3( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *A, + const mbedtls_ecp_point *B, + const mbedtls_ecp_point *C ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi one; + + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, A, &one, B ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, R, &one, R, &one, C ) ); + +cleanup: + mbedtls_mpi_free( &one ); + + return( ret ); +} + +/* + * Read and process second round message (C: 7.4.2.5, S: 7.4.2.6) + */ +int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + const unsigned char *end = buf + len; + mbedtls_ecp_group grp; + mbedtls_ecp_point G; /* C: GB, S: GA */ + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &G ); + + /* + * Server: GA = X3 + X4 + X1 (7.4.2.6.1) + * Client: GB = X1 + X2 + X3 (7.4.2.5.1) + * Unified: G = Xm1 + Xm2 + Xp1 + * We need that before parsing in order to check Xp as we read it + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xm1, &ctx->Xm2, &ctx->Xp1 ) ); + + /* + * struct { + * ECParameters curve_params; // only client reading server msg + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_CLIENT ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_group( &grp, &p, len ) ); + if( grp.id != ctx->grp.id ) + { + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( ecjpake_kkp_read( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &ctx->Xp, ID_PEER, &p, end ) ); + + if( p != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &G ); + + return( ret ); +} + +/* + * Compute R = +/- X * S mod N, taking care not to leak S + */ +static int ecjpake_mul_secret( mbedtls_mpi *R, int sign, + const mbedtls_mpi *X, + const mbedtls_mpi *S, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi b; /* Blinding value, then s + N * blinding */ + + mbedtls_mpi_init( &b ); + + /* b = s + rnd-128-bit * N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &b, 16, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &b, &b, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &b, &b, S ) ); + + /* R = sign * X * b mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( R, X, &b ) ); + R->s *= sign; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( R, R, N ) ); + +cleanup: + mbedtls_mpi_free( &b ); + + return( ret ); +} + +/* + * Generate and write the second round message (S: 7.4.2.5, C: 7.4.2.6) + */ +int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point G; /* C: GA, S: GB */ + mbedtls_ecp_point Xm; /* C: Xc, S: Xs */ + mbedtls_mpi xm; /* C: xc, S: xs */ + unsigned char *p = buf; + const unsigned char *end = buf + len; + size_t ec_len; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + mbedtls_ecp_point_init( &G ); + mbedtls_ecp_point_init( &Xm ); + mbedtls_mpi_init( &xm ); + + /* + * First generate private/public key pair (S: 7.4.2.5.1, C: 7.4.2.6.1) + * + * Client: GA = X1 + X3 + X4 | xs = x2 * s | Xc = xc * GA + * Server: GB = X3 + X1 + X2 | xs = x4 * s | Xs = xs * GB + * Unified: G = Xm1 + Xp1 + Xp2 | xm = xm2 * s | Xm = xm * G + */ + MBEDTLS_MPI_CHK( ecjpake_ecp_add3( &ctx->grp, &G, + &ctx->Xp1, &ctx->Xp2, &ctx->Xm1 ) ); + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &xm, 1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &Xm, &xm, &G, f_rng, p_rng ) ); + + /* + * Now write things out + * + * struct { + * ECParameters curve_params; // only server writing its message + * ECJPAKEKeyKP ecjpake_key_kp; + * } Client/ServerECJPAKEParams; + */ + if( ctx->role == MBEDTLS_ECJPAKE_SERVER ) + { + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_group( &ctx->grp, &ec_len, + p, end - p ) ); + p += ec_len; + } + + if( end < p ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + MBEDTLS_MPI_CHK( mbedtls_ecp_tls_write_point( &ctx->grp, &Xm, + ctx->point_format, &ec_len, p, end - p ) ); + p += ec_len; + + MBEDTLS_MPI_CHK( ecjpake_zkp_write( ctx->md_info, &ctx->grp, + ctx->point_format, + &G, &xm, &Xm, ID_MINE, + &p, end, f_rng, p_rng ) ); + + *olen = p - buf; + +cleanup: + mbedtls_ecp_point_free( &G ); + mbedtls_ecp_point_free( &Xm ); + mbedtls_mpi_free( &xm ); + + return( ret ); +} + +/* + * Derive PMS (7.4.2.7 / 7.4.2.8) + */ +int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx, + unsigned char *buf, size_t len, size_t *olen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point K; + mbedtls_mpi m_xm2_s, one; + unsigned char kx[MBEDTLS_ECP_MAX_BYTES]; + size_t x_bytes; + + ECJPAKE_VALIDATE_RET( ctx != NULL ); + ECJPAKE_VALIDATE_RET( buf != NULL ); + ECJPAKE_VALIDATE_RET( olen != NULL ); + ECJPAKE_VALIDATE_RET( f_rng != NULL ); + + *olen = mbedtls_md_get_size( ctx->md_info ); + if( len < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + mbedtls_ecp_point_init( &K ); + mbedtls_mpi_init( &m_xm2_s ); + mbedtls_mpi_init( &one ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &one, 1 ) ); + + /* + * Client: K = ( Xs - X4 * x2 * s ) * x2 + * Server: K = ( Xc - X2 * x4 * s ) * x4 + * Unified: K = ( Xp - Xp2 * xm2 * s ) * xm2 + */ + MBEDTLS_MPI_CHK( ecjpake_mul_secret( &m_xm2_s, -1, &ctx->xm2, &ctx->s, + &ctx->grp.N, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( &ctx->grp, &K, + &one, &ctx->Xp, + &m_xm2_s, &ctx->Xp2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &K, &ctx->xm2, &K, + f_rng, p_rng ) ); + + /* PMS = SHA-256( K.X ) */ + x_bytes = ( ctx->grp.pbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &K.X, kx, x_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_md( ctx->md_info, kx, x_bytes, buf ) ); + +cleanup: + mbedtls_ecp_point_free( &K ); + mbedtls_mpi_free( &m_xm2_s ); + mbedtls_mpi_free( &one ); + + return( ret ); +} + +#undef ID_MINE +#undef ID_PEER + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + !defined(MBEDTLS_SHA256_C) +int mbedtls_ecjpake_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +static const unsigned char ecjpake_test_password[] = { + 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x6a, 0x70, 0x61, 0x6b, 0x65, 0x74, + 0x65, 0x73, 0x74 +}; + +#if !defined(MBEDTLS_ECJPAKE_ALT) + +static const unsigned char ecjpake_test_x1[] = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, + 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x21 +}; + +static const unsigned char ecjpake_test_x2[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x3[] = { + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x81 +}; + +static const unsigned char ecjpake_test_x4[] = { + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, + 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, + 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe1 +}; + +static const unsigned char ecjpake_test_cli_one[] = { + 0x41, 0x04, 0xac, 0xcf, 0x01, 0x06, 0xef, 0x85, 0x8f, 0xa2, 0xd9, 0x19, + 0x33, 0x13, 0x46, 0x80, 0x5a, 0x78, 0xb5, 0x8b, 0xba, 0xd0, 0xb8, 0x44, + 0xe5, 0xc7, 0x89, 0x28, 0x79, 0x14, 0x61, 0x87, 0xdd, 0x26, 0x66, 0xad, + 0xa7, 0x81, 0xbb, 0x7f, 0x11, 0x13, 0x72, 0x25, 0x1a, 0x89, 0x10, 0x62, + 0x1f, 0x63, 0x4d, 0xf1, 0x28, 0xac, 0x48, 0xe3, 0x81, 0xfd, 0x6e, 0xf9, + 0x06, 0x07, 0x31, 0xf6, 0x94, 0xa4, 0x41, 0x04, 0x1d, 0xd0, 0xbd, 0x5d, + 0x45, 0x66, 0xc9, 0xbe, 0xd9, 0xce, 0x7d, 0xe7, 0x01, 0xb5, 0xe8, 0x2e, + 0x08, 0xe8, 0x4b, 0x73, 0x04, 0x66, 0x01, 0x8a, 0xb9, 0x03, 0xc7, 0x9e, + 0xb9, 0x82, 0x17, 0x22, 0x36, 0xc0, 0xc1, 0x72, 0x8a, 0xe4, 0xbf, 0x73, + 0x61, 0x0d, 0x34, 0xde, 0x44, 0x24, 0x6e, 0xf3, 0xd9, 0xc0, 0x5a, 0x22, + 0x36, 0xfb, 0x66, 0xa6, 0x58, 0x3d, 0x74, 0x49, 0x30, 0x8b, 0xab, 0xce, + 0x20, 0x72, 0xfe, 0x16, 0x66, 0x29, 0x92, 0xe9, 0x23, 0x5c, 0x25, 0x00, + 0x2f, 0x11, 0xb1, 0x50, 0x87, 0xb8, 0x27, 0x38, 0xe0, 0x3c, 0x94, 0x5b, + 0xf7, 0xa2, 0x99, 0x5d, 0xda, 0x1e, 0x98, 0x34, 0x58, 0x41, 0x04, 0x7e, + 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, 0xd7, 0x92, 0x62, + 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, 0x40, 0x9a, 0xc5, + 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, 0x79, 0x0a, 0xeb, + 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, 0xd1, 0xc3, 0x35, + 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, 0xe3, 0x2b, 0xb0, + 0x13, 0xbb, 0x2b, 0x41, 0x04, 0xa4, 0x95, 0x58, 0xd3, 0x2e, 0xd1, 0xeb, + 0xfc, 0x18, 0x16, 0xaf, 0x4f, 0xf0, 0x9b, 0x55, 0xfc, 0xb4, 0xca, 0x47, + 0xb2, 0xa0, 0x2d, 0x1e, 0x7c, 0xaf, 0x11, 0x79, 0xea, 0x3f, 0xe1, 0x39, + 0x5b, 0x22, 0xb8, 0x61, 0x96, 0x40, 0x16, 0xfa, 0xba, 0xf7, 0x2c, 0x97, + 0x56, 0x95, 0xd9, 0x3d, 0x4d, 0xf0, 0xe5, 0x19, 0x7f, 0xe9, 0xf0, 0x40, + 0x63, 0x4e, 0xd5, 0x97, 0x64, 0x93, 0x77, 0x87, 0xbe, 0x20, 0xbc, 0x4d, + 0xee, 0xbb, 0xf9, 0xb8, 0xd6, 0x0a, 0x33, 0x5f, 0x04, 0x6c, 0xa3, 0xaa, + 0x94, 0x1e, 0x45, 0x86, 0x4c, 0x7c, 0xad, 0xef, 0x9c, 0xf7, 0x5b, 0x3d, + 0x8b, 0x01, 0x0e, 0x44, 0x3e, 0xf0 +}; + +static const unsigned char ecjpake_test_srv_one[] = { + 0x41, 0x04, 0x7e, 0xa6, 0xe3, 0xa4, 0x48, 0x70, 0x37, 0xa9, 0xe0, 0xdb, + 0xd7, 0x92, 0x62, 0xb2, 0xcc, 0x27, 0x3e, 0x77, 0x99, 0x30, 0xfc, 0x18, + 0x40, 0x9a, 0xc5, 0x36, 0x1c, 0x5f, 0xe6, 0x69, 0xd7, 0x02, 0xe1, 0x47, + 0x79, 0x0a, 0xeb, 0x4c, 0xe7, 0xfd, 0x65, 0x75, 0xab, 0x0f, 0x6c, 0x7f, + 0xd1, 0xc3, 0x35, 0x93, 0x9a, 0xa8, 0x63, 0xba, 0x37, 0xec, 0x91, 0xb7, + 0xe3, 0x2b, 0xb0, 0x13, 0xbb, 0x2b, 0x41, 0x04, 0x09, 0xf8, 0x5b, 0x3d, + 0x20, 0xeb, 0xd7, 0x88, 0x5c, 0xe4, 0x64, 0xc0, 0x8d, 0x05, 0x6d, 0x64, + 0x28, 0xfe, 0x4d, 0xd9, 0x28, 0x7a, 0xa3, 0x65, 0xf1, 0x31, 0xf4, 0x36, + 0x0f, 0xf3, 0x86, 0xd8, 0x46, 0x89, 0x8b, 0xc4, 0xb4, 0x15, 0x83, 0xc2, + 0xa5, 0x19, 0x7f, 0x65, 0xd7, 0x87, 0x42, 0x74, 0x6c, 0x12, 0xa5, 0xec, + 0x0a, 0x4f, 0xfe, 0x2f, 0x27, 0x0a, 0x75, 0x0a, 0x1d, 0x8f, 0xb5, 0x16, + 0x20, 0x93, 0x4d, 0x74, 0xeb, 0x43, 0xe5, 0x4d, 0xf4, 0x24, 0xfd, 0x96, + 0x30, 0x6c, 0x01, 0x17, 0xbf, 0x13, 0x1a, 0xfa, 0xbf, 0x90, 0xa9, 0xd3, + 0x3d, 0x11, 0x98, 0xd9, 0x05, 0x19, 0x37, 0x35, 0x14, 0x41, 0x04, 0x19, + 0x0a, 0x07, 0x70, 0x0f, 0xfa, 0x4b, 0xe6, 0xae, 0x1d, 0x79, 0xee, 0x0f, + 0x06, 0xae, 0xb5, 0x44, 0xcd, 0x5a, 0xdd, 0xaa, 0xbe, 0xdf, 0x70, 0xf8, + 0x62, 0x33, 0x21, 0x33, 0x2c, 0x54, 0xf3, 0x55, 0xf0, 0xfb, 0xfe, 0xc7, + 0x83, 0xed, 0x35, 0x9e, 0x5d, 0x0b, 0xf7, 0x37, 0x7a, 0x0f, 0xc4, 0xea, + 0x7a, 0xce, 0x47, 0x3c, 0x9c, 0x11, 0x2b, 0x41, 0xcc, 0xd4, 0x1a, 0xc5, + 0x6a, 0x56, 0x12, 0x41, 0x04, 0x36, 0x0a, 0x1c, 0xea, 0x33, 0xfc, 0xe6, + 0x41, 0x15, 0x64, 0x58, 0xe0, 0xa4, 0xea, 0xc2, 0x19, 0xe9, 0x68, 0x31, + 0xe6, 0xae, 0xbc, 0x88, 0xb3, 0xf3, 0x75, 0x2f, 0x93, 0xa0, 0x28, 0x1d, + 0x1b, 0xf1, 0xfb, 0x10, 0x60, 0x51, 0xdb, 0x96, 0x94, 0xa8, 0xd6, 0xe8, + 0x62, 0xa5, 0xef, 0x13, 0x24, 0xa3, 0xd9, 0xe2, 0x78, 0x94, 0xf1, 0xee, + 0x4f, 0x7c, 0x59, 0x19, 0x99, 0x65, 0xa8, 0xdd, 0x4a, 0x20, 0x91, 0x84, + 0x7d, 0x2d, 0x22, 0xdf, 0x3e, 0xe5, 0x5f, 0xaa, 0x2a, 0x3f, 0xb3, 0x3f, + 0xd2, 0xd1, 0xe0, 0x55, 0xa0, 0x7a, 0x7c, 0x61, 0xec, 0xfb, 0x8d, 0x80, + 0xec, 0x00, 0xc2, 0xc9, 0xeb, 0x12 +}; + +static const unsigned char ecjpake_test_srv_two[] = { + 0x03, 0x00, 0x17, 0x41, 0x04, 0x0f, 0xb2, 0x2b, 0x1d, 0x5d, 0x11, 0x23, + 0xe0, 0xef, 0x9f, 0xeb, 0x9d, 0x8a, 0x2e, 0x59, 0x0a, 0x1f, 0x4d, 0x7c, + 0xed, 0x2c, 0x2b, 0x06, 0x58, 0x6e, 0x8f, 0x2a, 0x16, 0xd4, 0xeb, 0x2f, + 0xda, 0x43, 0x28, 0xa2, 0x0b, 0x07, 0xd8, 0xfd, 0x66, 0x76, 0x54, 0xca, + 0x18, 0xc5, 0x4e, 0x32, 0xa3, 0x33, 0xa0, 0x84, 0x54, 0x51, 0xe9, 0x26, + 0xee, 0x88, 0x04, 0xfd, 0x7a, 0xf0, 0xaa, 0xa7, 0xa6, 0x41, 0x04, 0x55, + 0x16, 0xea, 0x3e, 0x54, 0xa0, 0xd5, 0xd8, 0xb2, 0xce, 0x78, 0x6b, 0x38, + 0xd3, 0x83, 0x37, 0x00, 0x29, 0xa5, 0xdb, 0xe4, 0x45, 0x9c, 0x9d, 0xd6, + 0x01, 0xb4, 0x08, 0xa2, 0x4a, 0xe6, 0x46, 0x5c, 0x8a, 0xc9, 0x05, 0xb9, + 0xeb, 0x03, 0xb5, 0xd3, 0x69, 0x1c, 0x13, 0x9e, 0xf8, 0x3f, 0x1c, 0xd4, + 0x20, 0x0f, 0x6c, 0x9c, 0xd4, 0xec, 0x39, 0x22, 0x18, 0xa5, 0x9e, 0xd2, + 0x43, 0xd3, 0xc8, 0x20, 0xff, 0x72, 0x4a, 0x9a, 0x70, 0xb8, 0x8c, 0xb8, + 0x6f, 0x20, 0xb4, 0x34, 0xc6, 0x86, 0x5a, 0xa1, 0xcd, 0x79, 0x06, 0xdd, + 0x7c, 0x9b, 0xce, 0x35, 0x25, 0xf5, 0x08, 0x27, 0x6f, 0x26, 0x83, 0x6c +}; + +static const unsigned char ecjpake_test_cli_two[] = { + 0x41, 0x04, 0x69, 0xd5, 0x4e, 0xe8, 0x5e, 0x90, 0xce, 0x3f, 0x12, 0x46, + 0x74, 0x2d, 0xe5, 0x07, 0xe9, 0x39, 0xe8, 0x1d, 0x1d, 0xc1, 0xc5, 0xcb, + 0x98, 0x8b, 0x58, 0xc3, 0x10, 0xc9, 0xfd, 0xd9, 0x52, 0x4d, 0x93, 0x72, + 0x0b, 0x45, 0x54, 0x1c, 0x83, 0xee, 0x88, 0x41, 0x19, 0x1d, 0xa7, 0xce, + 0xd8, 0x6e, 0x33, 0x12, 0xd4, 0x36, 0x23, 0xc1, 0xd6, 0x3e, 0x74, 0x98, + 0x9a, 0xba, 0x4a, 0xff, 0xd1, 0xee, 0x41, 0x04, 0x07, 0x7e, 0x8c, 0x31, + 0xe2, 0x0e, 0x6b, 0xed, 0xb7, 0x60, 0xc1, 0x35, 0x93, 0xe6, 0x9f, 0x15, + 0xbe, 0x85, 0xc2, 0x7d, 0x68, 0xcd, 0x09, 0xcc, 0xb8, 0xc4, 0x18, 0x36, + 0x08, 0x91, 0x7c, 0x5c, 0x3d, 0x40, 0x9f, 0xac, 0x39, 0xfe, 0xfe, 0xe8, + 0x2f, 0x72, 0x92, 0xd3, 0x6f, 0x0d, 0x23, 0xe0, 0x55, 0x91, 0x3f, 0x45, + 0xa5, 0x2b, 0x85, 0xdd, 0x8a, 0x20, 0x52, 0xe9, 0xe1, 0x29, 0xbb, 0x4d, + 0x20, 0x0f, 0x01, 0x1f, 0x19, 0x48, 0x35, 0x35, 0xa6, 0xe8, 0x9a, 0x58, + 0x0c, 0x9b, 0x00, 0x03, 0xba, 0xf2, 0x14, 0x62, 0xec, 0xe9, 0x1a, 0x82, + 0xcc, 0x38, 0xdb, 0xdc, 0xae, 0x60, 0xd9, 0xc5, 0x4c +}; + +static const unsigned char ecjpake_test_pms[] = { + 0xf3, 0xd4, 0x7f, 0x59, 0x98, 0x44, 0xdb, 0x92, 0xa5, 0x69, 0xbb, 0xe7, + 0x98, 0x1e, 0x39, 0xd9, 0x31, 0xfd, 0x74, 0x3b, 0xf2, 0x2e, 0x98, 0xf9, + 0xb4, 0x38, 0xf7, 0x19, 0xd3, 0xc4, 0xf3, 0x51 +}; + +/* + * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! + * + * This is the linear congruential generator from numerical recipes, + * except we only use the low byte as the output. See + * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + */ +static int self_test_rng( void *ctx, unsigned char *out, size_t len ) +{ + static uint32_t state = 42; + + (void) ctx; + + for( size_t i = 0; i < len; i++ ) + { + state = state * 1664525u + 1013904223u; + out[i] = (unsigned char) state; + } + + return( 0 ); +} + +/* Load my private keys and generate the corresponding public keys */ +static int ecjpake_test_load( mbedtls_ecjpake_context *ctx, + const unsigned char *xm1, size_t len1, + const unsigned char *xm2, size_t len2 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm1, xm1, len1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->xm2, xm2, len2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm1, &ctx->xm1, + &ctx->grp.G, self_test_rng, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &ctx->grp, &ctx->Xm2, &ctx->xm2, + &ctx->grp.G, self_test_rng, NULL ) ); + +cleanup: + return( ret ); +} + +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +/* For tests we don't need a secure RNG; + * use the LGC from Numerical Recipes for simplicity */ +static int ecjpake_lgc( void *p, unsigned char *out, size_t len ) +{ + static uint32_t x = 42; + (void) p; + + while( len > 0 ) + { + size_t use_len = len > 4 ? 4 : len; + x = 1664525 * x + 1013904223; + memcpy( out, &x, use_len ); + out += use_len; + len -= use_len; + } + + return( 0 ); +} + +#define TEST_ASSERT( x ) \ + do { \ + if( x ) \ + ret = 0; \ + else \ + { \ + ret = 1; \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * Checkup routine + */ +int mbedtls_ecjpake_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecjpake_context cli; + mbedtls_ecjpake_context srv; + unsigned char buf[512], pms[32]; + size_t len, pmslen; + + mbedtls_ecjpake_init( &cli ); + mbedtls_ecjpake_init( &srv ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #0 (setup): " ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &cli, MBEDTLS_ECJPAKE_CLIENT, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_setup( &srv, MBEDTLS_ECJPAKE_SERVER, + MBEDTLS_MD_SHA256, MBEDTLS_ECP_DP_SECP256R1, + ecjpake_test_password, + sizeof( ecjpake_test_password ) ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #1 (random handshake): " ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_one( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + pms, sizeof( pms ), &pmslen, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_write_round_two( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, buf, len ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == pmslen ); + TEST_ASSERT( memcmp( buf, pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if !defined(MBEDTLS_ECJPAKE_ALT) + /* 'reference handshake' tests can only be run against implementations + * for which we have 100% control over how the random ephemeral keys + * are generated. This is only the case for the internal mbed TLS + * implementation, so these tests are skipped in case the internal + * implementation is swapped out for an alternative one. */ + if( verbose != 0 ) + mbedtls_printf( " ECJPAKE test #2 (reference handshake): " ); + + /* Simulate generation of round one */ + MBEDTLS_MPI_CHK( ecjpake_test_load( &cli, + ecjpake_test_x1, sizeof( ecjpake_test_x1 ), + ecjpake_test_x2, sizeof( ecjpake_test_x2 ) ) ); + + MBEDTLS_MPI_CHK( ecjpake_test_load( &srv, + ecjpake_test_x3, sizeof( ecjpake_test_x3 ), + ecjpake_test_x4, sizeof( ecjpake_test_x4 ) ) ); + + /* Read round one */ + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &srv, + ecjpake_test_cli_one, + sizeof( ecjpake_test_cli_one ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_one( &cli, + ecjpake_test_srv_one, + sizeof( ecjpake_test_srv_one ) ) == 0 ); + + /* Skip generation of round two, read round two */ + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &cli, + ecjpake_test_srv_two, + sizeof( ecjpake_test_srv_two ) ) == 0 ); + + TEST_ASSERT( mbedtls_ecjpake_read_round_two( &srv, + ecjpake_test_cli_two, + sizeof( ecjpake_test_cli_two ) ) == 0 ); + + /* Server derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &srv, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + memset( buf, 0, len ); /* Avoid interferences with next step */ + + /* Client derives PMS */ + TEST_ASSERT( mbedtls_ecjpake_derive_secret( &cli, + buf, sizeof( buf ), &len, ecjpake_lgc, NULL ) == 0 ); + + TEST_ASSERT( len == sizeof( ecjpake_test_pms ) ); + TEST_ASSERT( memcmp( buf, ecjpake_test_pms, len ) == 0 ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* ! MBEDTLS_ECJPAKE_ALT */ + +cleanup: + mbedtls_ecjpake_free( &cli ); + mbedtls_ecjpake_free( &srv ); + + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#undef TEST_ASSERT + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ECJPAKE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecp.c b/component/common/network/ssl/mbedtls-3.1.0/library/ecp.c new file mode 100644 index 00000000..d85f9932 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecp.c @@ -0,0 +1,3466 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#include "common.h" + +/** + * \brief Function level alternative implementation. + * + * The MBEDTLS_ECP_INTERNAL_ALT macro enables alternative implementations to + * replace certain functions in this module. The alternative implementations are + * typically hardware accelerators and need to activate the hardware before the + * computation starts and deactivate it after it finishes. The + * mbedtls_internal_ecp_init() and mbedtls_internal_ecp_free() functions serve + * this purpose. + * + * To preserve the correct functionality the following conditions must hold: + * + * - The alternative implementation must be activated by + * mbedtls_internal_ecp_init() before any of the replaceable functions is + * called. + * - mbedtls_internal_ecp_free() must \b only be called when the alternative + * implementation is activated. + * - mbedtls_internal_ecp_init() must \b not be called when the alternative + * implementation is activated. + * - Public functions must not return while the alternative implementation is + * activated. + * - Replaceable functions are guarded by \c MBEDTLS_ECP_XXX_ALT macros and + * before calling them an \code if( mbedtls_internal_ecp_grp_capable( grp ) ) + * \endcode ensures that the alternative implementation supports the current + * group. + */ +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "bn_mul.h" +#include "ecp_invasive.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "ecp_internal_alt.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} + +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_is_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + +/* + * Restart sub-context for ecp_mul_comb() + */ +struct mbedtls_ecp_restart_mul +{ + mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ + ecp_rsm_final_norm, /* do the final normalization */ + } state; +}; + +/* + * Init restart_mul sub-context + */ +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; +} + +/* + * Free the components of a restart_mul sub-context + */ +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) +{ + unsigned char i; + + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->R ); + + if( ctx->T != NULL ) + { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + + ecp_restart_rsm_init( ctx ); +} + +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + + ecp_restart_ma_init( ctx ); +} + +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + ECP_VALIDATE( ctx != NULL ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_rsm_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + + ecp_restart_ma_free( ctx->ma ); + mbedtls_free( ctx->ma ); + + mbedtls_ecp_restart_init( ctx ); +} + +/* + * Check if we can do the next step + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) +{ + ECP_VALIDATE_RET( grp != NULL ); + + if( rs_ctx != NULL && ecp_max_ops != 0 ) + { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + + /* Avoid infinite loops: always allow first step. + * Because of that, however, it's not generally true + * that ops_done <= ecp_max_ops, so the check + * ops_done > ecp_max_ops below is mandatory. */ + if( ( rs_ctx->ops_done != 0 ) && + ( rs_ctx->ops_done > ecp_max_ops || + ops > ecp_max_ops - rs_ctx->ops_done ) ) + { + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + + /* update running count */ + rs_ctx->ops_done += ops; + } + + return( 0 ); +} + +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2, RFC 8446 sec. 4.2.7) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. + * + * Reminder: update profiles in x509_crt.c and ssl_tls.c when adding a new curve! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + { MBEDTLS_ECP_DP_CURVE25519, 29, 256, "x25519" }, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + { MBEDTLS_ECP_DP_CURVE448, 30, 448, "x448" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( name == NULL ) + return( NULL ); + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +mbedtls_ecp_curve_type mbedtls_ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( MBEDTLS_ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( MBEDTLS_ECP_TYPE_MONTGOMERY ); + else + return( MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE( pt != NULL ); + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + ECP_VALIDATE( grp != NULL ); + + grp->id = MBEDTLS_ECP_DP_NONE; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + ECP_VALIDATE( key != NULL ); + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Check that the comb table (grp->T) is static initialized. + */ +static int ecp_group_is_static_comb_table( const mbedtls_ecp_group *grp ) { +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + return grp->T != NULL && grp->T_size == 0; +#else + (void) grp; + return 0; +#endif +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( !ecp_group_is_static_comb_table(grp) && grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + ECP_VALIDATE_RET( dst != NULL ); + ECP_VALIDATE_RET( src != NULL ); + + return( mbedtls_ecp_group_load( dst, src->id ) ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( pt != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( pt != NULL ); + + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazily + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( x != NULL ); + ECP_VALIDATE_RET( y != NULL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3 and RFC7748) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + plen = mbedtls_mpi_size( &grp->P ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + (void) format; /* Montgomery curves always use the same point format */ + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + *olen = plen; + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &P->X, buf, plen ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + } +#endif + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4 and RFC7748) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + size_t plen; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + plen = mbedtls_mpi_size( &grp->P ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + if( plen != ilen ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &pt->X, buf, plen ) ); + mbedtls_mpi_free( &pt->Y ); + + if( grp->id == MBEDTLS_ECP_DP_CURVE25519 ) + /* Set most significant bit to 0 as prescribed in RFC7748 §5 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &pt->X, plen * 8 - 1, 0 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, + buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + } +#endif + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return( mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ) ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( format == MBEDTLS_ECP_PF_UNCOMPRESSED || + format == MBEDTLS_ECP_PF_COMPRESSED ); + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, + const unsigned char **buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, len ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_group_load( grp, grp_id ) ); +} + +/* + * Read a group id from an ECParameters record (RFC 4492) and convert it to + * mbedtls_ecp_group_id. + */ +int mbedtls_ecp_tls_read_group_id( mbedtls_ecp_group_id *grp, + const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( *buf != NULL ); + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + *grp = curve_info->grp_id; + + return( 0 ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + ECP_VALIDATE_RET( olen != NULL ); + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + MBEDTLS_PUT_UINT16_BE( curve_info->tls_id, buf, 0 ); + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) \ + do \ + { \ + MBEDTLS_MPI_CHK( ecp_modp( &(N), grp ) ); \ + INC_MUL_COUNT \ + } while( 0 ) + +static inline int mbedtls_mpi_mul_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( X, A, B ) ); + MOD_MUL( *X ); +cleanup: + return( ret ); +} + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( (N).s < 0 && mbedtls_mpi_cmp_int( &(N), 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &(N), &(N), &grp->P ) ) + +#if ( defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \ + !( defined(MBEDTLS_ECP_NO_FALLBACK) && \ + defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \ + defined(MBEDTLS_ECP_ADD_MIXED_ALT) ) ) || \ + ( defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \ + !( defined(MBEDTLS_ECP_NO_FALLBACK) && \ + defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) ) ) +static inline int mbedtls_mpi_sub_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( X, A, B ) ); + MOD_SUB( *X ); +cleanup: + return( ret ); +} +#endif /* All functions referencing mbedtls_mpi_sub_mod() are alt-implemented without fallback */ + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &(N), &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &(N), &(N), &grp->P ) ) + +static inline int mbedtls_mpi_add_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + const mbedtls_mpi *A, + const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, A, B ) ); + MOD_ADD( *X ); +cleanup: + return( ret ); +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \ + !( defined(MBEDTLS_ECP_NO_FALLBACK) && \ + defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \ + defined(MBEDTLS_ECP_ADD_MIXED_ALT) ) +static inline int mbedtls_mpi_shift_l_mod( const mbedtls_ecp_group *grp, + mbedtls_mpi *X, + size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( X, count ) ); + MOD_ADD( *X ); +cleanup: + return( ret ); +} +#endif /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi Zi, ZZi; + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ZZi ) ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &Zi ) ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) */ +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t T_size ) +{ + if( T_size < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); +#endif + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &c[i], &c[i-1], &T[i]->Z ) ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); + + for( i = T_size - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Zi, &u, &c[i-1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &u, &u, &T[i]->Z ) ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ZZi, &Zi, &Zi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->X, &T[i]->X, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &ZZi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T[i]->Y, &T[i]->Y, &Zi ) ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) */ +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi M, S, T, U; + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &T, &P->X, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &U, &P->X, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &U ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &S, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &T, &grp->A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &M, &M, &S ) ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &P->Y, &P->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &P->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &S, 1 ) ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &T, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T, &M, &M ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T, &T, &S ) ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S, &S, &M ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S, &S, &U ) ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &U, &P->Y, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &U, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) */ +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_ADD_MIXED_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &P->Z, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T1, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T1, &T1, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T2, &T2, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T1, &T1, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T2, &T2, &P->Y ) ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &Z, &P->Z, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T1, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T3, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &T3 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l_mod( grp, &T1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &X, &T2, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &X, &X, &T4 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &T3, &T3, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T3, &T3, &T2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &T4, &T4, &P->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &Y, &T3, &T4 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_ADD_MIXED_ALT) */ +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi l, ll; + + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) ); + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Z, &pt->Z, &l ) ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &l, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->X, &pt->X, &ll ) ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &ll, &ll, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &pt->Y, &pt->Y, &ll ) ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) */ +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. + * + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the sign (s_i in the paper): it is set if and only if + * if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the adapted comb method + * + * Assumption: T must be able to hold 2^{w - 1} elements. + * + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char i; + size_t j = 0; + const unsigned char T_size = 1U << ( w - 1 ); + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) + goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; + } +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; + else +#endif + j = 0; + + for( ; j < d * ( w - 1 ); j++ ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); + + i = 1U << ( j / d ); + cur = T + i; + + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; + +norm_dbl: +#endif + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < T_size; i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + +add: +#endif + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); + + for( i = 1; i < T_size; i <<= 1 ) + { + j = i; + while( j-- ) + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + +norm_add: +#endif + /* + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < T_size; j++ ) + TT[j] = T + j + 1; + + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); + +cleanup: +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + rs_ctx->rsm->i = j; + } +#endif + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + unsigned char i ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < T_size; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char T_size, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) + { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + { + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } + + while( i != 0 ) + { + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + rs_ctx->rsm->i = i; + /* no need to save R, already pointing to rs_ctx->rsm->R */ + } +#endif + + return( ret ); +} + +/* + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. + * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * + * See ecp_comb_recode_core() for background. + */ +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* N is always odd (see above), just make extra sure */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); + +cleanup: + mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); + + return( ret ); +} + +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char T_size, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char parity_trick; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } +#endif + + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_final_norm; + +final_norm: + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); +#endif + /* + * Knowledge of the jacobian coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, RR, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif + +cleanup: + //printf("ecp_mul_comb_after_precomp: ret is %d ---- cl\r\n", ret); + return( ret ); +} + +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ + if( p_eq_g ) + w++; + + /* + * If static comb table may not be used (!p_eq_g) or static comb table does + * not exists, make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + * + * The user reduces MBEDTLS_ECP_WINDOW_SIZE does not changes the size of + * static comb table, because the size of static comb table is fixed when + * it is generated. + */ +#if( MBEDTLS_ECP_WINDOW_SIZE < 6 ) + if( (!p_eq_g || !ecp_group_is_static_comb_table(grp)) && w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; +#endif + if( w >= grp->nbits ) + w = 2; + + return( w ); +} + +/* + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the below two + * functions): allocation, computation, ownership tranfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char w, p_eq_g, i; + size_t d; + unsigned char T_size = 0, T_ok = 0; + mbedtls_ecp_point *T = NULL; + + ECP_RS_ENTER( rsm ); + + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + + /* Pick window size and deduce related sizes */ + w = ecp_pick_window_size( grp, p_eq_g ); + T_size = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) + { + /* second pointer to the same table, will be deleted on exit */ + T = grp->T; + T_ok = 1; + } + else +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* Pre-computed table: do we have one in progress? complete? */ + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) + { + /* transfer ownership of T from rsm to local function */ + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; + + /* This effectively jumps to the call to mul_comb_after_precomp() */ + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; + } + else +#endif + /* Allocate table if we didn't have any */ + { + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; + } + + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); + + if( p_eq_g ) + { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for calling the next function more easily */ + grp->T = T; + grp->T_size = T_size; + } + } + + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, T_size, w, d, + f_rng, p_rng, rs_ctx ) ); + + +cleanup: + + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; + + /* does T belong to the restart context? */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + { + /* transfer ownership of T from local function to rsm */ + rs_ctx->rsm->T_size = T_size; + rs_ctx->rsm->T = T; + T = NULL; + } +#endif + + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) + { + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + /* prevent caller from using invalid value */ + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + ECP_RS_LEAVE( rsm ); + + return( ret ); +} + +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) */ +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi l; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + MBEDTLS_MPI_CHK( mbedtls_mpi_random( &l, 2, &grp->P, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->X, &P->X, &l ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &P->Z, &P->Z, &l ) ); + +cleanup: + mbedtls_mpi_free( &l ); + + if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) */ +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#else + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &A, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &AA, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &B, &P->X, &P->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &BB, &B, &B ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &E, &AA, &BB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &C, &Q->X, &Q->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &D, &Q->X, &Q->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &DA, &D, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &CB, &C, &B ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &S->X, &DA, &CB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->X, &S->X, &S->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mod( grp, &S->Z, &DA, &CB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, &S->Z, &S->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &S->Z, d, &S->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->X, &AA, &BB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &grp->A, &E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &R->Z, &BB, &R->Z ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &R->Z, &E, &R->Z ) ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +#endif /* !defined(MBEDTLS_ECP_NO_FALLBACK) || !defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) */ +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + /* + * Knowledge of the projective coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Restartable multiplication R = m * P + * + * This internal function can be called without an RNG in case where we know + * the inputs are not sensitive. + */ +static int ecp_mul_restartable_internal( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#else + (void) rs_ctx; +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* skip argument check when restarting */ + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + } + + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +#endif + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + + return( ret ); +} + +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + + if( f_rng == NULL ) { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + + return( ecp_mul_restartable_internal( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +} + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); +} + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &YY, &pt->Y, &pt->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &pt->X, &pt->X ) ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->A ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mod( grp, &RHS, &RHS, &pt->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mod( grp, &RHS, &RHS, &grp->B ) ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +/* + * R = m * P with shortcuts for m == 0, m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( mbedtls_mpi_cmp_int( m, 0 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_set_zero( R ) ); + } + else if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( ecp_mul_restartable_internal( grp, R, m, P, + NULL, NULL, rs_ctx ) ); + } + +cleanup: + return( ret ); +} + +/* + * Restartable linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + + if( mbedtls_ecp_get_type( grp ) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + ECP_RS_ENTER( ma ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + { + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_mul2; + +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_add; + +add: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state = ecp_rsma_norm; + +norm: +#endif + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif + +cleanup: +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if( is_grp_capable ) + mbedtls_internal_ecp_free( grp ); +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + + mbedtls_ecp_point_free( &mP ); + + ECP_RS_LEAVE( ma ); + + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( R != NULL ); + ECP_VALIDATE_RET( m != NULL ); + ECP_VALIDATE_RET( P != NULL ); + ECP_VALIDATE_RET( n != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)} +#define ECP_MPI_INIT_ARRAY(x) \ + ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x) +/* + * Constants for the two points other than 0, 1, -1 (mod p) in + * https://cr.yp.to/ecdh.html#validate + * See ecp_check_pubkey_x25519(). + */ +static const mbedtls_mpi_uint x25519_bad_point_1[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 ), +}; +static const mbedtls_mpi_uint x25519_bad_point_2[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 ), +}; +static const mbedtls_mpi ecp_x25519_bad_point_1 = ECP_MPI_INIT_ARRAY( + x25519_bad_point_1 ); +static const mbedtls_mpi ecp_x25519_bad_point_2 = ECP_MPI_INIT_ARRAY( + x25519_bad_point_2 ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +/* + * Check that the input point is not one of the low-order points. + * This is recommended by the "May the Fourth" paper: + * https://eprint.iacr.org/2017/806.pdf + * Those points are never sent by an honest peer. + */ +static int ecp_check_bad_points_mx( const mbedtls_mpi *X, const mbedtls_mpi *P, + const mbedtls_ecp_group_id grp_id ) +{ + int ret; + mbedtls_mpi XmP; + + mbedtls_mpi_init( &XmP ); + + /* Reduce X mod P so that we only need to check values less than P. + * We know X < 2^256 so we can proceed by subtraction. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &XmP, X ) ); + while( mbedtls_mpi_cmp_mpi( &XmP, P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &XmP, &XmP, P ) ); + + /* Check against the known bad values that are less than P. For Curve448 + * these are 0, 1 and -1. For Curve25519 we check the values less than P + * from the following list: https://cr.yp.to/ecdh.html#validate */ + if( mbedtls_mpi_cmp_int( &XmP, 1 ) <= 0 ) /* takes care of 0 and 1 */ + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + if( grp_id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_1 ) == 0 ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + if( mbedtls_mpi_cmp_mpi( &XmP, &ecp_x25519_bad_point_2 ) == 0 ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + } +#else + (void) grp_id; +#endif + + /* Final check: check if XmP + 1 is P (final because it changes XmP!) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &XmP, &XmP, 1 ) ); + if( mbedtls_mpi_cmp_mpi( &XmP, P ) == 0 ) + { + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + goto cleanup; + } + + ret = 0; + +cleanup: + mbedtls_mpi_free( &XmP ); + + return( ret ); +} + +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* Implicit in all standards (as they don't consider negative numbers): + * X must be non-negative. This is normally ensured by the way it's + * encoded for transmission, but let's be extra sure. */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( ecp_check_bad_points_mx( &pt->X, &grp->P, grp->id ) ); +} +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, + const mbedtls_ecp_point *pt ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( pt != NULL ); + + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, + const mbedtls_mpi *d ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* see RFC 7748 sec. 5 para. 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); + } +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +MBEDTLS_STATIC_TESTABLE +int mbedtls_ecp_gen_privkey_mx( size_t high_bit, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + size_t n_random_bytes = high_bit / 8 + 1; + + /* [Curve25519] page 5 */ + /* Generate a (high_bit+1)-bit random number by generating just enough + * random bytes, then shifting out extra bits from the top (necessary + * when (high_bit+1) is not a multiple of 8). */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_random_bytes, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_random_bytes - high_bit - 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, high_bit, 1 ) ); + + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + if( high_bit == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) +static int mbedtls_ecp_gen_privkey_sw( + const mbedtls_mpi *N, mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = mbedtls_mpi_random( d, 1, N, f_rng, p_rng ); + switch( ret ) + { + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + default: + return( ret ); + } +} +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +/* + * Generate a private key + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + return( mbedtls_ecp_gen_privkey_mx( grp->nbits, d, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + return( mbedtls_ecp_gen_privkey_sw( &grp->N, d, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( G != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + ECP_VALIDATE_RET( grp != NULL ); + ECP_VALIDATE_RET( d != NULL ); + ECP_VALIDATE_RET( Q != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( f_rng != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +#define ECP_CURVE25519_KEY_SIZE 32 +#define ECP_CURVE448_KEY_SIZE 56 +/* + * Read a private key. + */ +int mbedtls_ecp_read_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + const unsigned char *buf, size_t buflen ) +{ + int ret = 0; + + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + /* + * Mask the key as mandated by RFC7748 for Curve25519 and Curve448. + */ + if( grp_id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( buflen != ECP_CURVE25519_KEY_SIZE ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) ); + + /* Set the three least significant bits to 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 2, 0 ) ); + + /* Set the most significant bit to 0 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE25519_KEY_SIZE * 8 - 1, 0 ) + ); + + /* Set the second most significant bit to 1 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE25519_KEY_SIZE * 8 - 2, 1 ) + ); + } + else if( grp_id == MBEDTLS_ECP_DP_CURVE448 ) + { + if( buflen != ECP_CURVE448_KEY_SIZE ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary_le( &key->d, buf, buflen ) ); + + /* Set the two least significant bits to 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &key->d, 1, 0 ) ); + + /* Set the most significant bit to 1 */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( &key->d, + ECP_CURVE448_KEY_SIZE * 8 - 1, 1 ) + ); + } + } + +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &key->d, buf, buflen ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( &key->grp, &key->d ) ); + } + +#endif +cleanup: + + if( ret != 0 ) + mbedtls_mpi_free( &key->d ); + + return( ret ); +} + +/* + * Write a private key. + */ +int mbedtls_ecp_write_key( mbedtls_ecp_keypair *key, + unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + ECP_VALIDATE_RET( key != NULL ); + ECP_VALIDATE_RET( buf != NULL ); + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) + { + if( key->grp.id == MBEDTLS_ECP_DP_CURVE25519 ) + { + if( buflen < ECP_CURVE25519_KEY_SIZE ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + } + else if( key->grp.id == MBEDTLS_ECP_DP_CURVE448 ) + { + if( buflen < ECP_CURVE448_KEY_SIZE ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary_le( &key->d, buf, buflen ) ); + } +#endif +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + if( mbedtls_ecp_get_type( &key->grp ) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &key->d, buf, buflen ) ); + } + +#endif +cleanup: + + return( ret ); +} + + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( + const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + ECP_VALIDATE_RET( pub != NULL ); + ECP_VALIDATE_RET( prv != NULL ); + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!! + * + * This is the linear congruential generator from numerical recipes, + * except we only use the low byte as the output. See + * https://en.wikipedia.org/wiki/Linear_congruential_generator#Parameters_in_common_use + */ +static int self_test_rng( void *ctx, unsigned char *out, size_t len ) +{ + static uint32_t state = 42; + + (void) ctx; + + for( size_t i = 0; i < len; i++ ) + { + state = state * 1664525u + 1013904223u; + out[i] = (unsigned char) state; + } + + return( 0 ); +} + +/* Adjust the exponent to be a valid private point for the specified curve. + * This is sometimes necessary because we use a single set of exponents + * for all curves but the validity of values depends on the curve. */ +static int self_test_adjust_exponent( const mbedtls_ecp_group *grp, + mbedtls_mpi *m ) +{ + int ret = 0; + switch( grp->id ) + { + /* If Curve25519 is available, then that's what we use for the + * Montgomery test, so we don't need the adjustment code. */ +#if ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + /* Move highest bit from 254 to N-1. Setting bit N-1 is + * necessary to enforce the highest-bit-set constraint. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, 254, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( m, grp->nbits, 1 ) ); + /* Copy second-highest bit from 253 to N-2. This is not + * necessary but improves the test variety a bit. */ + MBEDTLS_MPI_CHK( + mbedtls_mpi_set_bit( m, grp->nbits - 1, + mbedtls_mpi_get_bit( m, 253 ) ) ); + break; +#endif +#endif /* ! defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) */ + default: + /* Non-Montgomery curves and Curve25519 need no adjustment. */ + (void) grp; + (void) m; + goto cleanup; + } +cleanup: + return( ret ); +} + +/* Calculate R = m.P for each m in exponents. Check that the number of + * basic operations doesn't depend on the value of m. */ +static int self_test_point( int verbose, + mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + mbedtls_mpi *m, + const mbedtls_ecp_point *P, + const char *const *exponents, + size_t n_exponents ) +{ + int ret = 0; + size_t i = 0; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, self_test_rng, NULL ) ); + + for( i = 1; i < n_exponents; i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( self_test_adjust_exponent( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, self_test_rng, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + ret = 1; + break; + } + } + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + else + mbedtls_printf( "passed\n" ); + } + return( ret ); +} + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + /* Exponents especially adapted for secp192k1, which has the lowest + * order n of all supported curves (secp192r1 is in a slightly larger + * field but the order of its base point is slightly smaller). */ + const char *sw_exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8C", /* n - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + const char *m_exponents[] = + { + /* Valid private values for Curve25519. In a build with Curve448 + * but not Curve25519, they will be adjusted in + * self_test_adjust_exponent(). */ + "4000000000000000000000000000000000000000000000000000000000000000", + "5C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C3C30", + "5715ECCE24583F7A7023C24164390586842E816D7280A49EF6DF4EAE6B280BF8", + "41A2B017516F6D254E1F002BCCBADD54BE30F8CEC737A0E912B4963B6BA74460", + "5555555555555555555555555555555555555555555555555555555555555550", + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8", + }; +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP SW test #1 (constant op_count, base point G): " ); + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, self_test_rng, NULL ) ); + ret = self_test_point( verbose, + &grp, &R, &m, &grp.G, + sw_exponents, + sizeof( sw_exponents ) / sizeof( sw_exponents[0] )); + if( ret != 0 ) + goto cleanup; + + if( verbose != 0 ) + mbedtls_printf( " ECP SW test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + ret = self_test_point( verbose, + &grp, &R, &m, &P, + sw_exponents, + sizeof( sw_exponents ) / sizeof( sw_exponents[0] )); + if( ret != 0 ) + goto cleanup; + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + if( verbose != 0 ) + mbedtls_printf( " ECP Montgomery test (constant op_count): " ); +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE25519 ) ); +#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_CURVE448 ) ); +#else +#error "MBEDTLS_ECP_MONTGOMERY_ENABLED is defined, but no curve is supported for self-test" +#endif + ret = self_test_point( verbose, + &grp, &R, &m, &grp.G, + m_exponents, + sizeof( m_exponents ) / sizeof( m_exponents[0] )); + if( ret != 0 ) + goto cleanup; +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecp_curves.c b/component/common/network/ssl/mbedtls-3.1.0/library/ecp_curves.c new file mode 100644 index 00000000..421a067b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecp_curves.c @@ -0,0 +1,5459 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "bn_mul.h" +#include "ecp_invasive.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +/* Parameter validation macros based on platform_util.h */ +#define ECP_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) +#define ECP_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p)} + +#define ECP_MPI_INIT_ARRAY(x) \ + ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x) + +#define ECP_POINT_INIT_XY_Z0(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 0, NULL) } +#define ECP_POINT_INIT_XY_Z1(x, y) { \ + ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 1, mpi_one) } + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* For these curves, we build the group parameters dynamically. */ +#define ECP_LOAD_GROUP +static mbedtls_mpi_uint mpi_one[] = {1}; +#endif + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED ), +}; +static const mbedtls_mpi_uint secp192r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E ), +}; +static const mbedtls_mpi_uint secp192r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E ), +}; +static const mbedtls_mpi_uint secp192r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14 ), +}; +static const mbedtls_mpi_uint secp192r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2 ), +}; +static const mbedtls_mpi_uint secp192r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB ), +}; +static const mbedtls_mpi_uint secp192r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7 ), +}; +static const mbedtls_mpi_uint secp192r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2 ), +}; +static const mbedtls_mpi_uint secp192r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62 ), +}; +static const mbedtls_mpi_uint secp192r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC ), +}; +static const mbedtls_mpi_uint secp192r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F ), +}; +static const mbedtls_mpi_uint secp192r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55 ), +}; +static const mbedtls_mpi_uint secp192r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF ), +}; +static const mbedtls_mpi_uint secp192r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31 ), +}; +static const mbedtls_mpi_uint secp192r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC ), +}; +static const mbedtls_mpi_uint secp192r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83 ), +}; +static const mbedtls_mpi_uint secp192r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98 ), +}; +static const mbedtls_mpi_uint secp192r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5 ), +}; +static const mbedtls_mpi_uint secp192r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD ), +}; +static const mbedtls_mpi_uint secp192r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F ), +}; +static const mbedtls_mpi_uint secp192r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD ), +}; +static const mbedtls_mpi_uint secp192r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A ), +}; +static const mbedtls_mpi_uint secp192r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66 ), +}; +static const mbedtls_mpi_uint secp192r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7 ), +}; +static const mbedtls_mpi_uint secp192r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45 ), +}; +static const mbedtls_mpi_uint secp192r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71 ), +}; +static const mbedtls_mpi_uint secp192r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC ), +}; +static const mbedtls_mpi_uint secp192r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2 ), +}; +static const mbedtls_mpi_uint secp192r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48 ), +}; +static const mbedtls_mpi_uint secp192r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C ), +}; +static const mbedtls_ecp_point secp192r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y), +}; +#else +#define secp192r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_ecp_point secp224r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y), +}; +#else +#define secp224r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C ), +}; +static const mbedtls_mpi_uint secp256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4 ), +}; +static const mbedtls_mpi_uint secp256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6 ), +}; +static const mbedtls_mpi_uint secp256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20 ), +}; +static const mbedtls_mpi_uint secp256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62 ), +}; +static const mbedtls_mpi_uint secp256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7 ), +}; +static const mbedtls_mpi_uint secp256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00 ), +}; +static const mbedtls_mpi_uint secp256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03 ), +}; +static const mbedtls_mpi_uint secp256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C ), +}; +static const mbedtls_mpi_uint secp256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3 ), +}; +static const mbedtls_mpi_uint secp256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED ), +}; +static const mbedtls_mpi_uint secp256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3 ), +}; +static const mbedtls_mpi_uint secp256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95 ), +}; +static const mbedtls_mpi_uint secp256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68 ), +}; +static const mbedtls_mpi_uint secp256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54 ), +}; +static const mbedtls_mpi_uint secp256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6 ), +}; +static const mbedtls_mpi_uint secp256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE ), +}; +static const mbedtls_mpi_uint secp256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4 ), +}; +static const mbedtls_mpi_uint secp256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86 ), +}; +static const mbedtls_mpi_uint secp256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16 ), +}; +static const mbedtls_mpi_uint secp256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18 ), +}; +static const mbedtls_mpi_uint secp256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C ), +}; +static const mbedtls_mpi_uint secp256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6 ), +}; +static const mbedtls_mpi_uint secp256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E ), +}; +static const mbedtls_mpi_uint secp256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44 ), +}; +static const mbedtls_mpi_uint secp256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4 ), +}; +static const mbedtls_mpi_uint secp256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7 ), +}; +static const mbedtls_mpi_uint secp256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82 ), +}; +static const mbedtls_mpi_uint secp256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43 ), +}; +static const mbedtls_ecp_point secp256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y), +}; +#else +#define secp256r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp384r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD ), +}; +static const mbedtls_mpi_uint secp384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23 ), +}; +static const mbedtls_mpi_uint secp384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE ), +}; +static const mbedtls_mpi_uint secp384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3 ), +}; +static const mbedtls_mpi_uint secp384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD ), +}; +static const mbedtls_mpi_uint secp384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F ), +}; +static const mbedtls_mpi_uint secp384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48 ), +}; +static const mbedtls_mpi_uint secp384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A ), +}; +static const mbedtls_mpi_uint secp384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08 ), +}; +static const mbedtls_mpi_uint secp384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F ), +}; +static const mbedtls_mpi_uint secp384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74 ), +}; +static const mbedtls_mpi_uint secp384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03 ), +}; +static const mbedtls_mpi_uint secp384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB ), +}; +static const mbedtls_mpi_uint secp384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF ), +}; +static const mbedtls_mpi_uint secp384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97 ), +}; +static const mbedtls_mpi_uint secp384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71 ), +}; +static const mbedtls_mpi_uint secp384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5 ), +}; +static const mbedtls_mpi_uint secp384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91 ), +}; +static const mbedtls_mpi_uint secp384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5 ), +}; +static const mbedtls_mpi_uint secp384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15 ), +}; +static const mbedtls_mpi_uint secp384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98 ), +}; +static const mbedtls_mpi_uint secp384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F ), +}; +static const mbedtls_mpi_uint secp384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10 ), +}; +static const mbedtls_mpi_uint secp384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1 ), +}; +static const mbedtls_mpi_uint secp384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0 ), +}; +static const mbedtls_mpi_uint secp384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC ), +}; +static const mbedtls_mpi_uint secp384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6 ), +}; +static const mbedtls_mpi_uint secp384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A ), +}; +static const mbedtls_mpi_uint secp384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53 ), +}; +static const mbedtls_mpi_uint secp384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC ), +}; +static const mbedtls_mpi_uint secp384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85 ), +}; +static const mbedtls_mpi_uint secp384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23 ), +}; +static const mbedtls_mpi_uint secp384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3 ), +}; +static const mbedtls_mpi_uint secp384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6 ), +}; +static const mbedtls_mpi_uint secp384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67 ), +}; +static const mbedtls_mpi_uint secp384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC ), +}; +static const mbedtls_mpi_uint secp384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE ), +}; +static const mbedtls_mpi_uint secp384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05 ), +}; +static const mbedtls_mpi_uint secp384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA ), +}; +static const mbedtls_mpi_uint secp384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF ), +}; +static const mbedtls_mpi_uint secp384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63 ), +}; +static const mbedtls_mpi_uint secp384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1 ), +}; +static const mbedtls_mpi_uint secp384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D ), +}; +static const mbedtls_mpi_uint secp384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D ), +}; +static const mbedtls_mpi_uint secp384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF ), +}; +static const mbedtls_mpi_uint secp384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71 ), +}; +static const mbedtls_mpi_uint secp384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B ), +}; +static const mbedtls_mpi_uint secp384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F ), +}; +static const mbedtls_mpi_uint secp384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E ), +}; +static const mbedtls_mpi_uint secp384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2 ), +}; +static const mbedtls_mpi_uint secp384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7 ), +}; +static const mbedtls_mpi_uint secp384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21 ), +}; +static const mbedtls_mpi_uint secp384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6 ), +}; +static const mbedtls_mpi_uint secp384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E ), +}; +static const mbedtls_mpi_uint secp384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6 ), +}; +static const mbedtls_mpi_uint secp384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42 ), +}; +static const mbedtls_mpi_uint secp384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12 ), +}; +static const mbedtls_mpi_uint secp384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77 ), +}; +static const mbedtls_mpi_uint secp384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B ), +}; +static const mbedtls_mpi_uint secp384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41 ), +}; +static const mbedtls_ecp_point secp384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y), +}; +#else +#define secp384r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp521r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_ecp_point secp521r1_T[32] = { + ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y), +}; +#else +#define secp521r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp192k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E ), +}; +static const mbedtls_mpi_uint secp192k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7 ), +}; +static const mbedtls_mpi_uint secp192k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28 ), +}; +static const mbedtls_mpi_uint secp192k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4 ), +}; +static const mbedtls_mpi_uint secp192k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C ), +}; +static const mbedtls_mpi_uint secp192k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A ), +}; +static const mbedtls_mpi_uint secp192k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF ), +}; +static const mbedtls_mpi_uint secp192k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F ), +}; +static const mbedtls_mpi_uint secp192k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9 ), +}; +static const mbedtls_mpi_uint secp192k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D ), +}; +static const mbedtls_mpi_uint secp192k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5 ), +}; +static const mbedtls_mpi_uint secp192k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B ), +}; +static const mbedtls_mpi_uint secp192k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC ), +}; +static const mbedtls_mpi_uint secp192k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E ), +}; +static const mbedtls_mpi_uint secp192k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82 ), +}; +static const mbedtls_mpi_uint secp192k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22 ), +}; +static const mbedtls_mpi_uint secp192k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05 ), +}; +static const mbedtls_mpi_uint secp192k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96 ), +}; +static const mbedtls_mpi_uint secp192k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D ), +}; +static const mbedtls_mpi_uint secp192k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D ), +}; +static const mbedtls_mpi_uint secp192k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67 ), +}; +static const mbedtls_mpi_uint secp192k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C ), +}; +static const mbedtls_mpi_uint secp192k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD ), +}; +static const mbedtls_mpi_uint secp192k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8 ), +}; +static const mbedtls_mpi_uint secp192k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9 ), +}; +static const mbedtls_mpi_uint secp192k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76 ), +}; +static const mbedtls_mpi_uint secp192k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35 ), +}; +static const mbedtls_mpi_uint secp192k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63 ), +}; +static const mbedtls_mpi_uint secp192k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8 ), +}; +static const mbedtls_ecp_point secp192k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y), +}; +#else +#define secp192k1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp224k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_ecp_point secp224k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y), +}; +#else +#define secp224k1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint secp256k1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0 ), +}; +static const mbedtls_mpi_uint secp256k1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC ), +}; +static const mbedtls_mpi_uint secp256k1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF ), +}; +static const mbedtls_mpi_uint secp256k1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4 ), +}; +static const mbedtls_mpi_uint secp256k1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54 ), +}; +static const mbedtls_mpi_uint secp256k1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE ), +}; +static const mbedtls_mpi_uint secp256k1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E ), +}; +static const mbedtls_mpi_uint secp256k1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0 ), +}; +static const mbedtls_mpi_uint secp256k1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B ), +}; +static const mbedtls_mpi_uint secp256k1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1 ), +}; +static const mbedtls_mpi_uint secp256k1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15 ), +}; +static const mbedtls_mpi_uint secp256k1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05 ), +}; +static const mbedtls_mpi_uint secp256k1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72 ), +}; +static const mbedtls_mpi_uint secp256k1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22 ), +}; +static const mbedtls_mpi_uint secp256k1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16 ), +}; +static const mbedtls_mpi_uint secp256k1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E ), +}; +static const mbedtls_mpi_uint secp256k1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E ), +}; +static const mbedtls_mpi_uint secp256k1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D ), +}; +static const mbedtls_mpi_uint secp256k1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0 ), +}; +static const mbedtls_mpi_uint secp256k1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01 ), +}; +static const mbedtls_mpi_uint secp256k1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12 ), +}; +static const mbedtls_mpi_uint secp256k1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25 ), +}; +static const mbedtls_mpi_uint secp256k1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B ), +}; +static const mbedtls_mpi_uint secp256k1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B ), +}; +static const mbedtls_mpi_uint secp256k1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64 ), +}; +static const mbedtls_mpi_uint secp256k1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F ), +}; +static const mbedtls_mpi_uint secp256k1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07 ), +}; +static const mbedtls_mpi_uint secp256k1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9 ), +}; +static const mbedtls_mpi_uint secp256k1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89 ), +}; +static const mbedtls_mpi_uint secp256k1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB ), +}; +static const mbedtls_ecp_point secp256k1_T[16] = { + ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y), + ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y), +}; +#else +#define secp256k1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F ), +}; +static const mbedtls_ecp_point brainpoolP256r1_T[16] = { + ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y), +}; +#else +#define brainpoolP256r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F ), +}; +static const mbedtls_ecp_point brainpoolP384r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y), +}; +#else +#define brainpoolP384r1_T NULL +#endif + +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; + +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 +static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4 ), + MBEDTLS_BYTES_TO_T_UINT_8( 0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42 ), +}; +static const mbedtls_ecp_point brainpoolP512r1_T[32] = { + ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y), + ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y), +}; +#else +#define brainpoolP512r1_T NULL +#endif +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(ECP_LOAD_GROUP) +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + X->s = 1; + X->n = 1; + X->p = mpi_one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen, + const mbedtls_ecp_point *T) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + grp->T = (mbedtls_ecp_point *) T; + /* + * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free. + */ + grp->T_size = 0; + + return( 0 ); +} +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#if defined(ECP_LOAD_GROUP) +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ), \ + G ## _T \ + ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ), \ + G ## _T \ + ) +#endif /* ECP_LOAD_GROUP */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* Constants used by ecp_use_curve25519() */ +static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42; +static const unsigned char curve25519_part_of_n[] = { + 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, + 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED, +}; + +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve25519_a24 ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &grp->N, + curve25519_part_of_n, sizeof( curve25519_part_of_n ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* Constants used by ecp_use_curve448() */ +static const mbedtls_mpi_sint curve448_a24 = 0x98AA; +static const unsigned char curve448_part_of_n[] = { + 0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24, + 0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93, + 0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC, + 0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D, +}; + +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->A, curve448_a24 ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &Ns, + curve448_part_of_n, sizeof( curve448_part_of_n ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + ECP_VALIDATE_RET( grp != NULL ); + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + + default: + grp->id = MBEDTLS_ECP_DP_NONE; + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + (i) * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) (j) % 2 ? (uint32_t)( N->p[(j)/2] >> 32 ) : \ + (uint32_t)( N->p[(j)/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ + +/* + * Helpers for the main 'loop' + */ +#define INIT( b ) \ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = (b); \ + /* N is the size of the product of two b-bit numbers, plus one */ \ + /* limb for fix_negative */ \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, ( b ) * 2 / biL + 1 ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) mbedtls_ecp_fix_negative( N, c, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^bits + N, with c negative and N positive shorter than 'bits' + */ +MBEDTLS_STATIC_TESTABLE +void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits ) +{ + size_t i; + + /* Set N := 2^bits - 1 - N. We know that 0 <= N < 2^bits, so + * set the absolute value to 0xfff...fff - N. There is no carry + * since we're subtracting from all-bits-one. */ + for( i = 0; i <= bits / 8 / sizeof( mbedtls_mpi_uint ); i++ ) + { + N->p[i] = ~(mbedtls_mpi_uint)0 - N->p[i]; + } + /* Add 1, taking care of the carry. */ + i = 0; + do + ++N->p[i]; + while( N->p[i++] == 0 && i <= bits / 8 / sizeof( mbedtls_mpi_uint ) ); + /* Invert the sign. + * Now N = N0 - 2^bits where N0 is the initial value of N. */ + N->s = -1; + + /* Add |c| * 2^bits to the absolute value. Since c and N are + * negative, this adds c * 2^bits. */ + mbedtls_mpi_uint msw = (mbedtls_mpi_uint) -c; +#if defined(MBEDTLS_HAVE_INT64) + if( bits == 224 ) + msw <<= 32; +#endif + N->p[bits / 8 / sizeof( mbedtls_mpi_uint)] += msw; +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, + 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, + 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + MBEDTLS_BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, + 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecp_internal_alt.h b/component/common/network/ssl/mbedtls-3.1.0/library/ecp_internal_alt.h new file mode 100644 index 00000000..a7544aaf --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecp_internal_alt.h @@ -0,0 +1,293 @@ +/** + * \file ecp_internal_alt.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#include "mbedtls/build_info.h" + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal_alt.h */ + diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ecp_invasive.h b/component/common/network/ssl/mbedtls-3.1.0/library/ecp_invasive.h new file mode 100644 index 00000000..71c77027 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ecp_invasive.h @@ -0,0 +1,81 @@ +/** + * \file ecp_invasive.h + * + * \brief ECP module: interfaces for invasive testing only. + * + * The interfaces in this file are intended for testing purposes only. + * They SHOULD NOT be made available in library integrations except when + * building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ECP_INVASIVE_H +#define MBEDTLS_ECP_INVASIVE_H + +#include "common.h" +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C) + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* Preconditions: + * - bits is a multiple of 64 or is 224 + * - c is -1 or -2 + * - 0 <= N < 2^bits + * - N has room for bits plus one limb + * + * Behavior: + * Set N to c * 2^bits + old_value_of_N. + */ +void mbedtls_ecp_fix_negative( mbedtls_mpi *N, signed char c, size_t bits ); +#endif + +#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) +/** Generate a private key on a Montgomery curve (Curve25519 or Curve448). + * + * This function implements key generation for the set of secret keys + * specified in [Curve25519] p. 5 and in [Curve448]. The resulting value + * has the lower bits masked but is not necessarily canonical. + * + * \note - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * - [RFC7748] https://tools.ietf.org/html/rfc7748 + * + * \p high_bit The position of the high-order bit of the key to generate. + * This is the bit-size of the key minus 1: + * 254 for Curve25519 or 447 for Curve448. + * \param d The randomly generated key. This is a number of size + * exactly \p n_bits + 1 bits, with the least significant bits + * masked as specified in [Curve25519] and in [RFC7748] §5. + * \param f_rng The RNG function. + * \param p_rng The RNG context to be passed to \p f_rng. + * + * \return \c 0 on success. + * \return \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure. + */ +int mbedtls_ecp_gen_privkey_mx( size_t n_bits, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ + +#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */ + +#endif /* MBEDTLS_ECP_INVASIVE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/entropy.c b/component/common/network/ssl/mbedtls-3.1.0/library/entropy.c new file mode 100644 index 00000000..18a05f48 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/entropy.c @@ -0,0 +1,713 @@ +/* + * Entropy accumulator implementation + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "entropy_poll.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ + /* If the context was already free, don't call free() again. + * This is important for mutexes which don't allow double-free. */ + if( ctx->accumulator_started == -1 ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = -1; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + //printf("mbedtls_entropy_add_source ctx->source_count addr is %x,line is %d------------- cl\r\n",&(ctx->source_count), __LINE__); + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + int i; + int have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + //printf("entropy_gather_internal line is %d --------- cl\r\n",__LINE__); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + + + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + //printf("entropy_gather_internal ret is %d,line is %d --------- cl\r\n",ret,__LINE__); + return( ret ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, thresholds_reached; + size_t strong_size; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + thresholds_reached = 1; + strong_size = 0; + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].size < ctx->source[i].threshold ) + thresholds_reached = 0; + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + strong_size += ctx->source[i].size; + } + } + while( ! thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE ); + + //printf("mbedtls_entropy_func ret is %d, line is %d --------- cl\r\n", ret, __LINE__); + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: + //printf("mbedtls_entropy_func ret is %d, line is %d --------- cl\r\n", ret, __LINE__); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f = NULL; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( f = fopen( path, "wb" ) ) == NULL ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( f != NULL ) + fclose( f ); + + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.c b/component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.c new file mode 100644 index 00000000..32f1c9cd --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.c @@ -0,0 +1,250 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +#if defined(__linux__) && !defined(_GNU_SOURCE) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#include "common.h" + +#include + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "entropy_poll.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/* +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h" +#endif +*/ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__)) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM +#include + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} +#endif /* SYS_getrandom */ +#endif /* __linux__ || __midipix__ */ + +#if defined(__FreeBSD__) || defined(__DragonFly__) +#include +#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \ + (defined(__DragonFly__) && __DragonFly_version >= 500700) +#include +#include +#define HAVE_GETRANDOM +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + return getrandom( buf, buflen, flags ); +} +#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) || + (__DragonFly__ && __DragonFly_version >= 500700) */ +#endif /* __FreeBSD__ || __DragonFly__ */ + +/* + * Some BSD systems provide KERN_ARND. + * This is equivalent to reading from /dev/urandom, only it doesn't require an + * open file descriptor, and provides up to 256 bytes per call (basically the + * same as getentropy(), but with a longer history). + * + * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7 + */ +#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM) +#include +#include +#if defined(KERN_ARND) +#define HAVE_SYSCTL_ARND + +static int sysctl_arnd_wrapper( unsigned char *buf, size_t buflen ) +{ + int name[2]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_ARND; + + while( buflen > 0 ) + { + len = buflen > 256 ? 256 : buflen; + if( sysctl(name, 2, buf, &len, NULL, 0) == -1 ) + return( -1 ); + buflen -= len; + buf += len; + } + return( 0 ); +} +#endif /* KERN_ARND */ +#endif /* __FreeBSD__ || __NetBSD__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) data); + + +#if defined(HAVE_GETRANDOM) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) + { + *olen = ret; + return( 0 ); + } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); +#endif /* HAVE_GETRANDOM */ + + //printf("mbedtls_platform_entropy_poll line is %d ----------- cl\r\n", __LINE__); +#if defined(HAVE_SYSCTL_ARND) + ((void) file); + ((void) read_len); + if( sysctl_arnd_wrapper( output, len ) == -1 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + *olen = len; + return( 0 ); +#else + + *olen = 0; + + /* + if(crypto_random_generate(output, len) != 0) + { + printf("crypto_random_generate failed ------------ cl\r\n"); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + */ + //printf("mbedtls_platform_entropy_poll line is %d ----------- cl\r\n", __LINE__); + + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + printf("mbedtls_platform_entropy_poll line is %d ----------- cl\r\n", __LINE__); + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + + *olen = len; + return( 0 ); +#endif /* HAVE_SYSCTL_ARND */ +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.h b/component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.h new file mode 100644 index 00000000..aef1a097 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/entropy_poll.h @@ -0,0 +1,76 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#include "mbedtls/build_info.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/gcm.c b/component/common/network/ssl/mbedtls-3.1.0/library/gcm.c new file mode 100644 index 00000000..8505cf4e --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/gcm.c @@ -0,0 +1,1161 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf + * + * See also: + * [MGV] http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf + * + * We use the algorithm described as Shoup's method with 4-bit tables in + * [MGV] 4.1, pp. 12-13, to enhance speed without using too much memory. + */ + +#include "common.h" + +#if defined(MBEDTLS_GCM_C) + +#include "mbedtls/gcm.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_GCM_ALT) + +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Initialize a context + */ +void mbedtls_gcm_init( mbedtls_gcm_context *ctx ) +{ + GCM_VALIDATE( ctx != NULL ); + memset( ctx, 0, sizeof( mbedtls_gcm_context ) ); +} + +/* + * Precompute small multiples of H, that is set + * HH[i] || HL[i] = H times i, + * where i is seen as a field element as in [MGV], ie high-order bits + * correspond to low powers of P. The result is stored in the same way, that + * is the high-order bit of HH corresponds to P^0 and the low-order bit of HL + * corresponds to P^127. + */ +static int gcm_gen_table( mbedtls_gcm_context *ctx ) +{ + int ret, i, j; + uint64_t hi, lo; + uint64_t vl, vh; + unsigned char h[16]; + size_t olen = 0; + + memset( h, 0, 16 ); + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 ) + return( ret ); + + /* pack h as two 64-bits ints, big-endian */ + hi = MBEDTLS_GET_UINT32_BE( h, 0 ); + lo = MBEDTLS_GET_UINT32_BE( h, 4 ); + vh = (uint64_t) hi << 32 | lo; + + hi = MBEDTLS_GET_UINT32_BE( h, 8 ); + lo = MBEDTLS_GET_UINT32_BE( h, 12 ); + vl = (uint64_t) hi << 32 | lo; + + /* 8 = 1000 corresponds to 1 in GF(2^128) */ + ctx->HL[8] = vl; + ctx->HH[8] = vh; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + /* With CLMUL support, we need only h, not the rest of the table */ + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) + return( 0 ); +#endif + + /* 0 corresponds to 0 in GF(2^128) */ + ctx->HH[0] = 0; + ctx->HL[0] = 0; + + for( i = 4; i > 0; i >>= 1 ) + { + uint32_t T = ( vl & 1 ) * 0xe1000000U; + vl = ( vh << 63 ) | ( vl >> 1 ); + vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32); + + ctx->HL[i] = vl; + ctx->HH[i] = vh; + } + + for( i = 2; i <= 8; i *= 2 ) + { + uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i; + vh = *HiH; + vl = *HiL; + for( j = 1; j < i; j++ ) + { + HiH[j] = vh ^ ctx->HH[j]; + HiL[j] = vl ^ ctx->HL[j]; + } + } + + return( 0 ); +} + +int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( key != NULL ); + GCM_VALIDATE_RET( keybits == 128 || keybits == 192 || keybits == 256 ); + + cipher_info = mbedtls_cipher_info_from_values( cipher, keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = gcm_gen_table( ctx ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Shoup's method for multiplication use this table with + * last4[x] = x times P^128 + * where x and last4[x] are seen as elements of GF(2^128) as in [MGV] + */ +static const uint64_t last4[16] = +{ + 0x0000, 0x1c20, 0x3840, 0x2460, + 0x7080, 0x6ca0, 0x48c0, 0x54e0, + 0xe100, 0xfd20, 0xd940, 0xc560, + 0x9180, 0x8da0, 0xa9c0, 0xb5e0 +}; + +/* + * Sets output to x times H using the precomputed tables. + * x and output are seen as elements of GF(2^128) as in [MGV]. + */ +static void gcm_mult( mbedtls_gcm_context *ctx, const unsigned char x[16], + unsigned char output[16] ) +{ + int i = 0; + unsigned char lo, hi, rem; + uint64_t zh, zl; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_CLMUL ) ) { + unsigned char h[16]; + + MBEDTLS_PUT_UINT32_BE( ctx->HH[8] >> 32, h, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->HH[8], h, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->HL[8] >> 32, h, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->HL[8], h, 12 ); + + mbedtls_aesni_gcm_mult( output, x, h ); + return; + } +#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */ + + lo = x[15] & 0xf; + + zh = ctx->HH[lo]; + zl = ctx->HL[lo]; + + for( i = 15; i >= 0; i-- ) + { + lo = x[i] & 0xf; + hi = ( x[i] >> 4 ) & 0xf; + + if( i != 15 ) + { + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[lo]; + zl ^= ctx->HL[lo]; + + } + + rem = (unsigned char) zl & 0xf; + zl = ( zh << 60 ) | ( zl >> 4 ); + zh = ( zh >> 4 ); + zh ^= (uint64_t) last4[rem] << 48; + zh ^= ctx->HH[hi]; + zl ^= ctx->HL[hi]; + } + + MBEDTLS_PUT_UINT32_BE( zh >> 32, output, 0 ); + MBEDTLS_PUT_UINT32_BE( zh, output, 4 ); + MBEDTLS_PUT_UINT32_BE( zl >> 32, output, 8 ); + MBEDTLS_PUT_UINT32_BE( zl, output, 12 ); +} + +int mbedtls_gcm_starts( mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, size_t iv_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char work_buf[16]; + size_t i; + const unsigned char *p; + size_t use_len, olen = 0; + uint64_t iv_bits; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + + /* IV is limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if( iv_len == 0 || (uint64_t) iv_len >> 61 != 0 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + memset( ctx->y, 0x00, sizeof(ctx->y) ); + memset( ctx->buf, 0x00, sizeof(ctx->buf) ); + + ctx->mode = mode; + ctx->len = 0; + ctx->add_len = 0; + + if( iv_len == 12 ) + { + memcpy( ctx->y, iv, iv_len ); + ctx->y[15] = 1; + } + else + { + memset( work_buf, 0x00, 16 ); + iv_bits = (uint64_t)iv_len * 8; + MBEDTLS_PUT_UINT64_BE( iv_bits, work_buf, 8 ); + + p = iv; + while( iv_len > 0 ) + { + use_len = ( iv_len < 16 ) ? iv_len : 16; + + for( i = 0; i < use_len; i++ ) + ctx->y[i] ^= p[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + + iv_len -= use_len; + p += use_len; + } + + for( i = 0; i < 16; i++ ) + ctx->y[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->y, ctx->y ); + } + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, + ctx->base_ectr, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/** + * mbedtls_gcm_context::buf contains the partial state of the computation of + * the authentication tag. + * mbedtls_gcm_context::add_len and mbedtls_gcm_context::len indicate + * different stages of the computation: + * * len == 0 && add_len == 0: initial state + * * len == 0 && add_len % 16 != 0: the first `add_len % 16` bytes have + * a partial block of AD that has been + * xored in but not yet multiplied in. + * * len == 0 && add_len % 16 == 0: the authentication tag is correct if + * the data ends now. + * * len % 16 != 0: the first `len % 16` bytes have + * a partial block of ciphertext that has + * been xored in but not yet multiplied in. + * * len > 0 && len % 16 == 0: the authentication tag is correct if + * the data ends now. + */ +int mbedtls_gcm_update_ad( mbedtls_gcm_context *ctx, + const unsigned char *add, size_t add_len ) +{ + const unsigned char *p; + size_t use_len, i, offset; + + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + + /* IV is limited to 2^64 bits, so 2^61 bytes */ + if( (uint64_t) add_len >> 61 != 0 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + offset = ctx->add_len % 16; + p = add; + + if( offset != 0 ) + { + use_len = 16 - offset; + if( use_len > add_len ) + use_len = add_len; + + for( i = 0; i < use_len; i++ ) + ctx->buf[i+offset] ^= p[i]; + + if( offset + use_len == 16 ) + gcm_mult( ctx, ctx->buf, ctx->buf ); + + ctx->add_len += use_len; + add_len -= use_len; + p += use_len; + } + + ctx->add_len += add_len; + + while( add_len >= 16 ) + { + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= p[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + add_len -= 16; + p += 16; + } + + if( add_len > 0 ) + { + for( i = 0; i < add_len; i++ ) + ctx->buf[i] ^= p[i]; + } + + return( 0 ); +} + +/* Increment the counter. */ +static void gcm_incr( unsigned char y[16] ) +{ + size_t i; + for( i = 16; i > 12; i-- ) + if( ++y[i - 1] != 0 ) + break; +} + +/* Calculate and apply the encryption mask. Process use_len bytes of data, + * starting at position offset in the mask block. */ +static int gcm_mask( mbedtls_gcm_context *ctx, + unsigned char ectr[16], + size_t offset, size_t use_len, + const unsigned char *input, + unsigned char *output ) +{ + size_t i; + size_t olen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr, + &olen ) ) != 0 ) + { + mbedtls_platform_zeroize( ectr, 16 ); + return( ret ); + } + + for( i = 0; i < use_len; i++ ) + { + if( ctx->mode == MBEDTLS_GCM_DECRYPT ) + ctx->buf[offset + i] ^= input[i]; + output[i] = ectr[offset + i] ^ input[i]; + if( ctx->mode == MBEDTLS_GCM_ENCRYPT ) + ctx->buf[offset + i] ^= output[i]; + } + return( 0 ); +} + +int mbedtls_gcm_update( mbedtls_gcm_context *ctx, + const unsigned char *input, size_t input_length, + unsigned char *output, size_t output_size, + size_t *output_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = input; + unsigned char *out_p = output; + size_t offset; + unsigned char ectr[16]; + + if( output_size < input_length ) + return( MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL ); + GCM_VALIDATE_RET( output_length != NULL ); + *output_length = input_length; + + /* Exit early if input_length==0 so that we don't do any pointer arithmetic + * on a potentially null pointer. + * Returning early also means that the last partial block of AD remains + * untouched for mbedtls_gcm_finish */ + if( input_length == 0 ) + return( 0 ); + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( input != NULL ); + GCM_VALIDATE_RET( output != NULL ); + + if( output > input && (size_t) ( output - input ) < input_length ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if( ctx->len + input_length < ctx->len || + (uint64_t) ctx->len + input_length > 0xFFFFFFFE0ull ) + { + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + } + + if( ctx->len == 0 && ctx->add_len % 16 != 0 ) + { + gcm_mult( ctx, ctx->buf, ctx->buf ); + } + + offset = ctx->len % 16; + if( offset != 0 ) + { + size_t use_len = 16 - offset; + if( use_len > input_length ) + use_len = input_length; + + if( ( ret = gcm_mask( ctx, ectr, offset, use_len, p, out_p ) ) != 0 ) + return( ret ); + + if( offset + use_len == 16 ) + gcm_mult( ctx, ctx->buf, ctx->buf ); + + ctx->len += use_len; + input_length -= use_len; + p += use_len; + out_p += use_len; + } + + ctx->len += input_length; + + while( input_length >= 16 ) + { + gcm_incr( ctx->y ); + if( ( ret = gcm_mask( ctx, ectr, 0, 16, p, out_p ) ) != 0 ) + return( ret ); + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + input_length -= 16; + p += 16; + out_p += 16; + } + + if( input_length > 0 ) + { + gcm_incr( ctx->y ); + if( ( ret = gcm_mask( ctx, ectr, 0, input_length, p, out_p ) ) != 0 ) + return( ret ); + } + + mbedtls_platform_zeroize( ectr, sizeof( ectr ) ); + return( 0 ); +} + +int mbedtls_gcm_finish( mbedtls_gcm_context *ctx, + unsigned char *output, size_t output_size, + size_t *output_length, + unsigned char *tag, size_t tag_len ) +{ + unsigned char work_buf[16]; + size_t i; + uint64_t orig_len; + uint64_t orig_add_len; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + /* We never pass any output in finish(). The output parameter exists only + * for the sake of alternative implementations. */ + (void) output; + (void) output_size; + *output_length = 0; + + orig_len = ctx->len * 8; + orig_add_len = ctx->add_len * 8; + + if( ctx->len == 0 && ctx->add_len % 16 != 0 ) + { + gcm_mult( ctx, ctx->buf, ctx->buf ); + } + + if( tag_len > 16 || tag_len < 4 ) + return( MBEDTLS_ERR_GCM_BAD_INPUT ); + + if( ctx->len % 16 != 0 ) + gcm_mult( ctx, ctx->buf, ctx->buf ); + + memcpy( tag, ctx->base_ectr, tag_len ); + + if( orig_len || orig_add_len ) + { + memset( work_buf, 0x00, 16 ); + + MBEDTLS_PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 ); + MBEDTLS_PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 ); + MBEDTLS_PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 ); + MBEDTLS_PUT_UINT32_BE( ( orig_len ), work_buf, 12 ); + + for( i = 0; i < 16; i++ ) + ctx->buf[i] ^= work_buf[i]; + + gcm_mult( ctx, ctx->buf, ctx->buf ); + + for( i = 0; i < tag_len; i++ ) + tag[i] ^= ctx->buf[i]; + } + + return( 0 ); +} + +int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + + if( ( ret = mbedtls_gcm_starts( ctx, mode, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update_ad( ctx, add, add_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_update( ctx, input, length, + output, length, &olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_gcm_finish( ctx, NULL, 0, &olen, tag, tag_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char check_tag[16]; + size_t i; + int diff; + + GCM_VALIDATE_RET( ctx != NULL ); + GCM_VALIDATE_RET( iv != NULL ); + GCM_VALIDATE_RET( add_len == 0 || add != NULL ); + GCM_VALIDATE_RET( tag != NULL ); + GCM_VALIDATE_RET( length == 0 || input != NULL ); + GCM_VALIDATE_RET( length == 0 || output != NULL ); + + if( ( ret = mbedtls_gcm_crypt_and_tag( ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag ) ) != 0 ) + { + return( ret ); + } + + /* Check tag in "constant-time" */ + for( diff = 0, i = 0; i < tag_len; i++ ) + diff |= tag[i] ^ check_tag[i]; + + if( diff != 0 ) + { + mbedtls_platform_zeroize( output, length ); + return( MBEDTLS_ERR_GCM_AUTH_FAILED ); + } + + return( 0 ); +} + +void mbedtls_gcm_free( mbedtls_gcm_context *ctx ) +{ + if( ctx == NULL ) + return; + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_gcm_context ) ); +} + +#endif /* !MBEDTLS_GCM_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +/* + * AES-GCM test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip + */ +#define MAX_TESTS 6 + +static const int key_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char key_test_data[MAX_TESTS][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }, +}; + +static const size_t iv_len_test_data[MAX_TESTS] = + { 12, 12, 12, 12, 8, 60 }; + +static const int iv_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 2 }; + +static const unsigned char iv_test_data[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }, + { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }, + { 0x93, 0x13, 0x22, 0x5d, 0xf8, 0x84, 0x06, 0xe5, + 0x55, 0x90, 0x9c, 0x5a, 0xff, 0x52, 0x69, 0xaa, + 0x6a, 0x7a, 0x95, 0x38, 0x53, 0x4f, 0x7d, 0xa1, + 0xe4, 0xc3, 0x03, 0xd2, 0xa3, 0x18, 0xa7, 0x28, + 0xc3, 0xc0, 0xc9, 0x51, 0x56, 0x80, 0x95, 0x39, + 0xfc, 0xf0, 0xe2, 0x42, 0x9a, 0x6b, 0x52, 0x54, + 0x16, 0xae, 0xdb, 0xf5, 0xa0, 0xde, 0x6a, 0x57, + 0xa6, 0x37, 0xb3, 0x9b }, +}; + +static const size_t add_len_test_data[MAX_TESTS] = + { 0, 0, 0, 20, 20, 20 }; + +static const int add_index_test_data[MAX_TESTS] = + { 0, 0, 0, 1, 1, 1 }; + +static const unsigned char additional_test_data[MAX_TESTS][64] = +{ + { 0x00 }, + { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef, + 0xab, 0xad, 0xda, 0xd2 }, +}; + +static const size_t pt_len_test_data[MAX_TESTS] = + { 0, 16, 64, 60, 60, 60 }; + +static const int pt_index_test_data[MAX_TESTS] = + { 0, 0, 1, 1, 1, 1 }; + +static const unsigned char pt_test_data[MAX_TESTS][64] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }, +}; + +static const unsigned char ct_test_data[MAX_TESTS * 3][64] = +{ + { 0x00 }, + { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92, + 0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }, + { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91 }, + { 0x61, 0x35, 0x3b, 0x4c, 0x28, 0x06, 0x93, 0x4a, + 0x77, 0x7f, 0xf5, 0x1f, 0xa2, 0x2a, 0x47, 0x55, + 0x69, 0x9b, 0x2a, 0x71, 0x4f, 0xcd, 0xc6, 0xf8, + 0x37, 0x66, 0xe5, 0xf9, 0x7b, 0x6c, 0x74, 0x23, + 0x73, 0x80, 0x69, 0x00, 0xe4, 0x9f, 0x24, 0xb2, + 0x2b, 0x09, 0x75, 0x44, 0xd4, 0x89, 0x6b, 0x42, + 0x49, 0x89, 0xb5, 0xe1, 0xeb, 0xac, 0x0f, 0x07, + 0xc2, 0x3f, 0x45, 0x98 }, + { 0x8c, 0xe2, 0x49, 0x98, 0x62, 0x56, 0x15, 0xb6, + 0x03, 0xa0, 0x33, 0xac, 0xa1, 0x3f, 0xb8, 0x94, + 0xbe, 0x91, 0x12, 0xa5, 0xc3, 0xa2, 0x11, 0xa8, + 0xba, 0x26, 0x2a, 0x3c, 0xca, 0x7e, 0x2c, 0xa7, + 0x01, 0xe4, 0xa9, 0xa4, 0xfb, 0xa4, 0x3c, 0x90, + 0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f, + 0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03, + 0x4c, 0x34, 0xae, 0xe5 }, + { 0x00 }, + { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41, + 0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56 }, + { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41, + 0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57, + 0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84, + 0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c, + 0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25, + 0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47, + 0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9, + 0xcc, 0xda, 0x27, 0x10 }, + { 0x0f, 0x10, 0xf5, 0x99, 0xae, 0x14, 0xa1, 0x54, + 0xed, 0x24, 0xb3, 0x6e, 0x25, 0x32, 0x4d, 0xb8, + 0xc5, 0x66, 0x63, 0x2e, 0xf2, 0xbb, 0xb3, 0x4f, + 0x83, 0x47, 0x28, 0x0f, 0xc4, 0x50, 0x70, 0x57, + 0xfd, 0xdc, 0x29, 0xdf, 0x9a, 0x47, 0x1f, 0x75, + 0xc6, 0x65, 0x41, 0xd4, 0xd4, 0xda, 0xd1, 0xc9, + 0xe9, 0x3a, 0x19, 0xa5, 0x8e, 0x8b, 0x47, 0x3f, + 0xa0, 0xf0, 0x62, 0xf7 }, + { 0xd2, 0x7e, 0x88, 0x68, 0x1c, 0xe3, 0x24, 0x3c, + 0x48, 0x30, 0x16, 0x5a, 0x8f, 0xdc, 0xf9, 0xff, + 0x1d, 0xe9, 0xa1, 0xd8, 0xe6, 0xb4, 0x47, 0xef, + 0x6e, 0xf7, 0xb7, 0x98, 0x28, 0x66, 0x6e, 0x45, + 0x81, 0xe7, 0x90, 0x12, 0xaf, 0x34, 0xdd, 0xd9, + 0xe2, 0xf0, 0x37, 0x58, 0x9b, 0x29, 0x2d, 0xb3, + 0xe6, 0x7c, 0x03, 0x67, 0x45, 0xfa, 0x22, 0xe7, + 0xe9, 0xb7, 0x37, 0x3b }, + { 0x00 }, + { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e, + 0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18 }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }, + { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62 }, + { 0xc3, 0x76, 0x2d, 0xf1, 0xca, 0x78, 0x7d, 0x32, + 0xae, 0x47, 0xc1, 0x3b, 0xf1, 0x98, 0x44, 0xcb, + 0xaf, 0x1a, 0xe1, 0x4d, 0x0b, 0x97, 0x6a, 0xfa, + 0xc5, 0x2f, 0xf7, 0xd7, 0x9b, 0xba, 0x9d, 0xe0, + 0xfe, 0xb5, 0x82, 0xd3, 0x39, 0x34, 0xa4, 0xf0, + 0x95, 0x4c, 0xc2, 0x36, 0x3b, 0xc7, 0x3f, 0x78, + 0x62, 0xac, 0x43, 0x0e, 0x64, 0xab, 0xe4, 0x99, + 0xf4, 0x7c, 0x9b, 0x1f }, + { 0x5a, 0x8d, 0xef, 0x2f, 0x0c, 0x9e, 0x53, 0xf1, + 0xf7, 0x5d, 0x78, 0x53, 0x65, 0x9e, 0x2a, 0x20, + 0xee, 0xb2, 0xb2, 0x2a, 0xaf, 0xde, 0x64, 0x19, + 0xa0, 0x58, 0xab, 0x4f, 0x6f, 0x74, 0x6b, 0xf4, + 0x0f, 0xc0, 0xc3, 0xb7, 0x80, 0xf2, 0x44, 0x45, + 0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde, + 0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e, + 0x44, 0xae, 0x7e, 0x3f }, +}; + +static const unsigned char tag_test_data[MAX_TESTS * 3][16] = +{ + { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61, + 0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a }, + { 0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd, + 0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf }, + { 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }, + { 0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb, + 0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 }, + { 0x36, 0x12, 0xd2, 0xe7, 0x9e, 0x3b, 0x07, 0x85, + 0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb }, + { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa, + 0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 }, + { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b, + 0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 }, + { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab, + 0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb }, + { 0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf, + 0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 }, + { 0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f, + 0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c }, + { 0x65, 0xdc, 0xc5, 0x7f, 0xcf, 0x62, 0x3a, 0x24, + 0x09, 0x4f, 0xcc, 0xa4, 0x0d, 0x35, 0x33, 0xf8 }, + { 0xdc, 0xf5, 0x66, 0xff, 0x29, 0x1c, 0x25, 0xbb, + 0xb8, 0x56, 0x8f, 0xc3, 0xd3, 0x76, 0xa6, 0xd9 }, + { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9, + 0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b }, + { 0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0, + 0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 }, + { 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }, + { 0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68, + 0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b }, + { 0x3a, 0x33, 0x7d, 0xbf, 0x46, 0xa7, 0x92, 0xc4, + 0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 }, + { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0, + 0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a }, +}; + +int mbedtls_gcm_self_test( int verbose ) +{ + mbedtls_gcm_context ctx; + unsigned char buf[64]; + unsigned char tag_buf[16]; + int i, j, ret; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + size_t olen; + + for( j = 0; j < 3; j++ ) + { + int key_len = 128 + 64 * j; + + for( i = 0; i < MAX_TESTS; i++ ) + { + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && key_len == 192 ) + { + mbedtls_printf( "skipped\n" ); + break; + } + else if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_ENCRYPT, + pt_len_test_data[i], + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i], + pt_test_data[pt_index_test_data[i]], + buf, 16, tag_buf ); +#if defined(MBEDTLS_GCM_ALT) + /* Allow alternative implementations to only support 12-byte nonces. */ + if( ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && + iv_len_test_data[i] != 12 ) + { + mbedtls_printf( "skipped\n" ); + break; + } +#endif /* defined(MBEDTLS_GCM_ALT) */ + if( ret != 0 ) + goto exit; + + if ( memcmp( buf, ct_test_data[j * 6 + i], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_crypt_and_tag( &ctx, MBEDTLS_GCM_DECRYPT, + pt_len_test_data[i], + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i], + additional_test_data[add_index_test_data[i]], + add_len_test_data[i], + ct_test_data[j * 6 + i], buf, 16, tag_buf ); + + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "enc" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_ENCRYPT, + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_update_ad( &ctx, + additional_test_data[add_index_test_data[i]], + add_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len_test_data[i] > 32 ) + { + size_t rest_len = pt_len_test_data[i] - 32; + ret = mbedtls_gcm_update( &ctx, + pt_test_data[pt_index_test_data[i]], + 32, + buf, sizeof( buf ), &olen ); + if( ret != 0 ) + goto exit; + if( olen != 32 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, + pt_test_data[pt_index_test_data[i]] + 32, + rest_len, + buf + 32, sizeof( buf ) - 32, &olen ); + if( ret != 0 ) + goto exit; + if( olen != rest_len ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, + pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i], + buf, sizeof( buf ), &olen ); + if( ret != 0 ) + goto exit; + if( olen != pt_len_test_data[i] ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, ct_test_data[j * 6 + i], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_gcm_init( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( " AES-GCM-%3d #%d split (%s): ", + key_len, i, "dec" ); + + ret = mbedtls_gcm_setkey( &ctx, cipher, + key_test_data[key_index_test_data[i]], + key_len ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_gcm_starts( &ctx, MBEDTLS_GCM_DECRYPT, + iv_test_data[iv_index_test_data[i]], + iv_len_test_data[i] ); + if( ret != 0 ) + goto exit; + ret = mbedtls_gcm_update_ad( &ctx, + additional_test_data[add_index_test_data[i]], + add_len_test_data[i] ); + if( ret != 0 ) + goto exit; + + if( pt_len_test_data[i] > 32 ) + { + size_t rest_len = pt_len_test_data[i] - 32; + ret = mbedtls_gcm_update( &ctx, + ct_test_data[j * 6 + i], 32, + buf, sizeof( buf ), &olen ); + if( ret != 0 ) + goto exit; + if( olen != 32 ) + goto exit; + + ret = mbedtls_gcm_update( &ctx, + ct_test_data[j * 6 + i] + 32, + rest_len, + buf + 32, sizeof( buf ) - 32, &olen ); + if( ret != 0 ) + goto exit; + if( olen != rest_len ) + goto exit; + } + else + { + ret = mbedtls_gcm_update( &ctx, + ct_test_data[j * 6 + i], + pt_len_test_data[i], + buf, sizeof( buf ), &olen ); + if( ret != 0 ) + goto exit; + if( olen != pt_len_test_data[i] ) + goto exit; + } + + ret = mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf, 16 ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, pt_test_data[pt_index_test_data[i]], + pt_len_test_data[i] ) != 0 || + memcmp( tag_buf, tag_test_data[j * 6 + i], 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + mbedtls_gcm_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + ret = 0; + +exit: + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + mbedtls_gcm_free( &ctx ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_GCM_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/hkdf.c b/component/common/network/ssl/mbedtls-3.1.0/library/hkdf.c new file mode 100644 index 00000000..5013729d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/hkdf.c @@ -0,0 +1,189 @@ +/* + * HKDF implementation -- RFC 5869 + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_HKDF_C) + +#include +#include "mbedtls/hkdf.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +int mbedtls_hkdf( const mbedtls_md_info_t *md, const unsigned char *salt, + size_t salt_len, const unsigned char *ikm, size_t ikm_len, + const unsigned char *info, size_t info_len, + unsigned char *okm, size_t okm_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char prk[MBEDTLS_MD_MAX_SIZE]; + + ret = mbedtls_hkdf_extract( md, salt, salt_len, ikm, ikm_len, prk ); + + if( ret == 0 ) + { + ret = mbedtls_hkdf_expand( md, prk, mbedtls_md_get_size( md ), + info, info_len, okm, okm_len ); + } + + mbedtls_platform_zeroize( prk, sizeof( prk ) ); + + return( ret ); +} + +int mbedtls_hkdf_extract( const mbedtls_md_info_t *md, + const unsigned char *salt, size_t salt_len, + const unsigned char *ikm, size_t ikm_len, + unsigned char *prk ) +{ + unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' }; + + if( salt == NULL ) + { + size_t hash_len; + + if( salt_len != 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + hash_len = mbedtls_md_get_size( md ); + + if( hash_len == 0 ) + { + return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA; + } + + salt = null_salt; + salt_len = hash_len; + } + + return( mbedtls_md_hmac( md, salt, salt_len, ikm, ikm_len, prk ) ); +} + +int mbedtls_hkdf_expand( const mbedtls_md_info_t *md, const unsigned char *prk, + size_t prk_len, const unsigned char *info, + size_t info_len, unsigned char *okm, size_t okm_len ) +{ + size_t hash_len; + size_t where = 0; + size_t n; + size_t t_len = 0; + size_t i; + int ret = 0; + mbedtls_md_context_t ctx; + unsigned char t[MBEDTLS_MD_MAX_SIZE]; + + if( okm == NULL ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + hash_len = mbedtls_md_get_size( md ); + + if( prk_len < hash_len || hash_len == 0 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + if( info == NULL ) + { + info = (const unsigned char *) ""; + info_len = 0; + } + + n = okm_len / hash_len; + + if( okm_len % hash_len != 0 ) + { + n++; + } + + /* + * Per RFC 5869 Section 2.3, okm_len must not exceed + * 255 times the hash length + */ + if( n > 255 ) + { + return( MBEDTLS_ERR_HKDF_BAD_INPUT_DATA ); + } + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md, 1 ) ) != 0 ) + { + goto exit; + } + + memset( t, 0, hash_len ); + + /* + * Compute T = T(1) | T(2) | T(3) | ... | T(N) + * Where T(N) is defined in RFC 5869 Section 2.3 + */ + for( i = 1; i <= n; i++ ) + { + size_t num_to_copy; + unsigned char c = i & 0xff; + + ret = mbedtls_md_hmac_starts( &ctx, prk, prk_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, t, t_len ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_update( &ctx, info, info_len ); + if( ret != 0 ) + { + goto exit; + } + + /* The constant concatenated to the end of each T(n) is a single octet. + * */ + ret = mbedtls_md_hmac_update( &ctx, &c, 1 ); + if( ret != 0 ) + { + goto exit; + } + + ret = mbedtls_md_hmac_finish( &ctx, t ); + if( ret != 0 ) + { + goto exit; + } + + num_to_copy = i != n ? hash_len : okm_len - where; + memcpy( okm + where, t, num_to_copy ); + where += hash_len; + t_len = hash_len; + } + +exit: + mbedtls_md_free( &ctx ); + mbedtls_platform_zeroize( t, sizeof( t ) ); + + return( ret ); +} + +#endif /* MBEDTLS_HKDF_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/hmac_drbg.c b/component/common/network/ssl/mbedtls-3.1.0/library/hmac_drbg.c new file mode 100644 index 00000000..f4767200 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/hmac_drbg.c @@ -0,0 +1,622 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * The NIST SP 800-90A DRBGs are described in the following publication. + * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf + * References below are based on rev. 1 (January 2012). + */ + +#include "common.h" + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +int mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + unsigned char rounds = ( additional != NULL && add_len != 0 ) ? 2 : 1; + unsigned char sep[1]; + unsigned char K[MBEDTLS_MD_MAX_SIZE]; + int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; + if( rounds == 2 ) + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; + + /* Step 2 or 5 */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_platform_zeroize( K, sizeof( K ) ); + return( ret ); +} + +/* + * Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA) + */ +int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + const unsigned char *data, size_t data_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + if( ( ret = mbedtls_hmac_drbg_update( ctx, data, data_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Internal function used both for seeding and reseeding the DRBG. + * Comments starting with arabic numbers refer to section 10.1.2.4 + * of SP800-90A, while roman numbers refer to section 9.2. + */ +static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len, + int use_nonce ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + { + size_t total_entropy_len; + + if( use_nonce == 0 ) + total_entropy_len = ctx->entropy_len; + else + total_entropy_len = ctx->entropy_len * 3 / 2; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ) + { + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + } + } + + memset( seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT ); + + /* IV. Gather entropy_len bytes of entropy for the seed */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* For initial seeding, allow adding of nonce generated + * from the entropy source. See Sect 8.6.7 in SP800-90A. */ + if( use_nonce ) + { + /* Note: We don't merge the two calls to f_entropy() in order + * to avoid requesting too much entropy from f_entropy() + * at once. Specifically, if the underlying digest is not + * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which + * is larger than the maximum of 32 Bytes that our own + * entropy source implementation can emit in a single + * call in configurations disabling SHA-512. */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed + seedlen, + ctx->entropy_len / 2 ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len / 2; + } + + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + if( ( ret = mbedtls_hmac_drbg_update( ctx, seed, seedlen ) ) != 0 ) + goto exit; + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + +exit: + /* 4. Done */ + mbedtls_platform_zeroize( seed, seedlen ); + return( ret ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + * + * The nonce is not passed as a separate parameter but extracted + * from the entropy source as suggested in 8.6.7. + */ +int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx, + const mbedtls_md_info_t * md_info, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + + printf("mbedtls_hmac_drbg_seed: line is %d ---- cl\r\n", __LINE__); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* The mutex is initialized iff the md context is set up. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + md_size = mbedtls_md_get_size( md_info ); + + /* + * Set initial working state. + * Use the V memory location, which is currently all 0, to initialize the + * MD context with an all-zero key. Then set V to its initial value. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + { + /* + * See SP800-57 5.6.1 (p. 65-66) for the security strength provided by + * each hash function, then according to SP800-90A rev1 10.1 table 2, + * min_entropy_len (in bits) is security_strength. + * + * (This also matches the sizes used in the NIST test vectors.) + */ + ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */ + md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */ + 32; /* better (256+) -> 256 bits */ + } + + if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, + 1 /* add nonce */ ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Set prediction resistance + */ +void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx, + int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +/* + * Set entropy length grabbed for seeding + */ +void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +/* + * Set reseed interval + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +/* + * HMAC_DRBG random function with optional additional data: + * 10.1.2.5 (arabic) + 9.3 (Roman) + */ +int mbedtls_hmac_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t out_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + size_t md_len = mbedtls_md_get_size( ctx->md_ctx.md_info ); + size_t left = out_len; + unsigned char *out = output; + + /* II. Check request length */ + if( out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG ); + + /* III. Check input length */ + if( add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG ); + + /* 1. (aka VII and IX) Check reseed counter and PR */ + if( ctx->f_entropy != NULL && /* For no-reseeding instances */ + ( ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON || + ctx->reseed_counter > ctx->reseed_interval ) ) + { + if( ( ret = mbedtls_hmac_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + return( ret ); + + add_len = 0; /* VII.4 */ + } + + /* 2. Use additional data if any */ + if( additional != NULL && add_len != 0 ) + { + if( ( ret = mbedtls_hmac_drbg_update( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + if( ( ret = mbedtls_hmac_drbg_update( ctx, + additional, add_len ) ) != 0 ) + goto exit; + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + +exit: + /* 8. Done */ + return( ret ); +} + +/* + * HMAC_DRBG random function + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_hmac_drbg_random_with_add( ctx, output, out_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff the md context is set up. */ + if( ctx->md_ctx.md_info != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_hmac_drbg_random( ctx, buf, sizeof( buf ) ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, sizeof( buf ), f ) != sizeof( buf ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + fclose( f ); + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f = NULL; + size_t n; + unsigned char buf[ MBEDTLS_HMAC_DRBG_MAX_INPUT ]; + unsigned char c; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR ); + + n = fread( buf, 1, sizeof( buf ), f ); + if( fread( &c, 1, 1, f ) != 0 ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG; + goto exit; + } + if( n == 0 || ferror( f ) ) + { + ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR; + goto exit; + } + fclose( f ); + f = NULL; + + ret = mbedtls_hmac_drbg_update( ctx, buf, n ); + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + if( f != NULL ) + fclose( f ); + if( ret != 0 ) + return( ret ); + return( mbedtls_hmac_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +/* Dummy checkup routine */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + (void) verbose; + return( 0 ); +} +#else + +#define OUTPUT_LEN 80 + +/* From a NIST PR=true test vector */ +static const unsigned char entropy_pr[] = { + 0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f, + 0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11, + 0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42, + 0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3, + 0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4 }; +static const unsigned char result_pr[OUTPUT_LEN] = { + 0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39, + 0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94, + 0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54, + 0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e, + 0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab, + 0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3, + 0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44 }; + +/* From a NIST PR=false test vector */ +static const unsigned char entropy_nopr[] = { + 0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66, + 0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8, + 0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3, + 0xe9, 0x9d, 0xfe, 0xdf }; +static const unsigned char result_nopr[OUTPUT_LEN] = { + 0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f, + 0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6, + 0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a, + 0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec, + 0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd, + 0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49, + 0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7 }; + +/* "Entropy" from buffer */ +static size_t test_offset; +static int hmac_drbg_self_test_entropy( void *data, + unsigned char *buf, size_t len ) +{ + const unsigned char *p = data; + memcpy( buf, p + test_offset, len ); + test_offset += len; + return( 0 ); +} + +#define CHK( c ) if( (c) != 0 ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + return( 1 ); \ + } + +/* + * Checkup routine for HMAC_DRBG with SHA-1 + */ +int mbedtls_hmac_drbg_self_test( int verbose ) +{ + mbedtls_hmac_drbg_context ctx; + unsigned char buf[OUTPUT_LEN]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + + mbedtls_hmac_drbg_init( &ctx ); + + /* + * PR = True + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = True) : " ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_pr, + NULL, 0 ) ); + mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_pr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * PR = False + */ + if( verbose != 0 ) + mbedtls_printf( " HMAC_DRBG (PR = False) : " ); + + mbedtls_hmac_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_hmac_drbg_seed( &ctx, md_info, + hmac_drbg_self_test_entropy, (void *) entropy_nopr, + NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( mbedtls_hmac_drbg_random( &ctx, buf, OUTPUT_LEN ) ); + CHK( memcmp( buf, result_nopr, OUTPUT_LEN ) ); + mbedtls_hmac_drbg_free( &ctx ); + + mbedtls_hmac_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_HMAC_DRBG_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/md.c b/component/common/network/ssl/mbedtls-3.1.0/library/md.c new file mode 100644 index 00000000..a2287896 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/md.c @@ -0,0 +1,812 @@ +/** + * \file md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "md_wrap.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include "mbedtls/md5.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_MD5_C) +const mbedtls_md_info_t mbedtls_md5_info = { + "MD5", + MBEDTLS_MD_MD5, + 16, + 64, +}; +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +const mbedtls_md_info_t mbedtls_ripemd160_info = { + "RIPEMD160", + MBEDTLS_MD_RIPEMD160, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA1_C) +const mbedtls_md_info_t mbedtls_sha1_info = { + "SHA1", + MBEDTLS_MD_SHA1, + 20, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA224_C) +const mbedtls_md_info_t mbedtls_sha224_info = { + "SHA224", + MBEDTLS_MD_SHA224, + 28, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA256_C) +const mbedtls_md_info_t mbedtls_sha256_info = { + "SHA256", + MBEDTLS_MD_SHA256, + 32, + 64, +}; +#endif + +#if defined(MBEDTLS_SHA384_C) +const mbedtls_md_info_t mbedtls_sha384_info = { + "SHA384", + MBEDTLS_MD_SHA384, + 48, + 128, +}; +#endif + +#if defined(MBEDTLS_SHA512_C) +const mbedtls_md_info_t mbedtls_sha512_info = { + "SHA512", + MBEDTLS_MD_SHA512, + 64, + 128, +}; +#endif + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#endif + +#if defined(MBEDTLS_SHA384_C) + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, +#endif +#if defined(MBEDTLS_SHA224_C) + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA224_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA384_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + { + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + mbedtls_sha256_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + mbedtls_sha256_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif + default: + /* Shouldn't happen */ + break; + } + mbedtls_free( ctx->md_ctx ); + } + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + switch( src->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + mbedtls_sha256_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + mbedtls_sha256_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +#define ALLOC( type ) \ + do { \ + ctx->md_ctx = mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \ + if( ctx->md_ctx == NULL ) \ + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); \ + mbedtls_##type##_init( ctx->md_ctx ); \ + } \ + while( 0 ) + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ctx->md_info = md_info; + ctx->md_ctx = NULL; + ctx->hmac_ctx = NULL; + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + ALLOC( md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + ALLOC( ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + ALLOC( sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + ALLOC( sha512 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + ALLOC( sha512 ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + mbedtls_md_free( ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + return( 0 ); +} +#undef ALLOC + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_starts( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_starts( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_starts( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_starts( ctx->md_ctx, 1 ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_starts( ctx->md_ctx, 0 ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_starts( ctx->md_ctx, 1 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_starts( ctx->md_ctx, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_update( ctx->md_ctx, input, ilen ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_finish( ctx->md_ctx, output ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256( input, ilen, output, 1 ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256( input, ilen, output, 0 ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512( input, ilen, output, 1 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512( input, ilen, output, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = mbedtls_md_finish( &ctx, output ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( mbedtls_md_update( ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( mbedtls_md_finish( ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_internal_md5_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_internal_sha256_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/md5.c b/component/common/network/ssl/mbedtls-3.1.0/library/md5.c new file mode 100644 index 00000000..a9bbcb48 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/md5.c @@ -0,0 +1,435 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_MD5_ALT) + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + local.X[ 0] = MBEDTLS_GET_UINT32_LE( data, 0 ); + local.X[ 1] = MBEDTLS_GET_UINT32_LE( data, 4 ); + local.X[ 2] = MBEDTLS_GET_UINT32_LE( data, 8 ); + local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 ); + local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 ); + local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 ); + local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 ); + local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 ); + local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 ); + local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 ); + local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 ); + local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 ); + local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 ); + local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 ); + local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 ); + local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 ); + +#define S(x,n) \ + ( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) ) + +#define P(a,b,c,d,k,s,t) \ + do \ + { \ + (a) += F((b),(c),(d)) + local.X[(k)] + (t); \ + (a) = S((a),(s)) + (b); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + + P( local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478 ); + P( local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756 ); + P( local.C, local.D, local.A, local.B, 2, 17, 0x242070DB ); + P( local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE ); + P( local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF ); + P( local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A ); + P( local.C, local.D, local.A, local.B, 6, 17, 0xA8304613 ); + P( local.B, local.C, local.D, local.A, 7, 22, 0xFD469501 ); + P( local.A, local.B, local.C, local.D, 8, 7, 0x698098D8 ); + P( local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF ); + P( local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1 ); + P( local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE ); + P( local.A, local.B, local.C, local.D, 12, 7, 0x6B901122 ); + P( local.D, local.A, local.B, local.C, 13, 12, 0xFD987193 ); + P( local.C, local.D, local.A, local.B, 14, 17, 0xA679438E ); + P( local.B, local.C, local.D, local.A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y)))) + + P( local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562 ); + P( local.D, local.A, local.B, local.C, 6, 9, 0xC040B340 ); + P( local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51 ); + P( local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA ); + P( local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D ); + P( local.D, local.A, local.B, local.C, 10, 9, 0x02441453 ); + P( local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681 ); + P( local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8 ); + P( local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6 ); + P( local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6 ); + P( local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87 ); + P( local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED ); + P( local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905 ); + P( local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8 ); + P( local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9 ); + P( local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) + + P( local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942 ); + P( local.D, local.A, local.B, local.C, 8, 11, 0x8771F681 ); + P( local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122 ); + P( local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C ); + P( local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44 ); + P( local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9 ); + P( local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60 ); + P( local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70 ); + P( local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6 ); + P( local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA ); + P( local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085 ); + P( local.B, local.C, local.D, local.A, 6, 23, 0x04881D05 ); + P( local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039 ); + P( local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5 ); + P( local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8 ); + P( local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) ((y) ^ ((x) | ~(z))) + + P( local.A, local.B, local.C, local.D, 0, 6, 0xF4292244 ); + P( local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97 ); + P( local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7 ); + P( local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039 ); + P( local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3 ); + P( local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92 ); + P( local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D ); + P( local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1 ); + P( local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F ); + P( local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0 ); + P( local.C, local.D, local.A, local.B, 6, 15, 0xA3014314 ); + P( local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1 ); + P( local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82 ); + P( local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235 ); + P( local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB ); + P( local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +/* + * MD5 final digest + */ +int mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_LE( low, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_LE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/md_wrap.h b/component/common/network/ssl/mbedtls-3.1.0/library/md_wrap.h new file mode 100644 index 00000000..90c79573 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/md_wrap.h @@ -0,0 +1,82 @@ +/** + * \file md_wrap.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Name of the message digest */ + const char * name; + + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Output length of the digest function in bytes */ + unsigned char size; + + /** Block length of the digest function in bytes */ + unsigned char block_size; +}; + +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA224_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA384_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/memory_buffer_alloc.c b/component/common/network/ssl/mbedtls-3.1.0/library/memory_buffer_alloc.c new file mode 100644 index 00000000..0d5d27d3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/memory_buffer_alloc.c @@ -0,0 +1,744 @@ +/* + * Buffer-based memory allocator + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#define MAGIC1 0xFF00AA55 +#define MAGIC2 0xEE119966 +#define MAX_BT 20 + +typedef struct _memory_header memory_header; +struct _memory_header +{ + size_t magic1; + size_t size; + size_t alloc; + memory_header *prev; + memory_header *next; + memory_header *prev_free; + memory_header *next_free; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + char **trace; + size_t trace_count; +#endif + size_t magic2; +}; + +typedef struct +{ + unsigned char *buf; + size_t len; + memory_header *first; + memory_header *first_free; + int verify; +#if defined(MBEDTLS_MEMORY_DEBUG) + size_t alloc_count; + size_t free_count; + size_t total_used; + size_t maximum_used; + size_t header_count; + size_t maximum_header_count; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +buffer_alloc_ctx; + +static buffer_alloc_ctx heap; + +#if defined(MBEDTLS_MEMORY_DEBUG) +static void debug_header( memory_header *hdr ) +{ +#if defined(MBEDTLS_MEMORY_BACKTRACE) + size_t i; +#endif + + mbedtls_fprintf( stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), " + "ALLOC(%zu), SIZE(%10zu)\n", + (size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next, + hdr->alloc, hdr->size ); + mbedtls_fprintf( stderr, " FPREV(%10zu), FNEXT(%10zu)\n", + (size_t) hdr->prev_free, (size_t) hdr->next_free ); + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + mbedtls_fprintf( stderr, "TRACE: \n" ); + for( i = 0; i < hdr->trace_count; i++ ) + mbedtls_fprintf( stderr, "%s\n", hdr->trace[i] ); + mbedtls_fprintf( stderr, "\n" ); +#endif +} + +static void debug_chain( void ) +{ + memory_header *cur = heap.first; + + mbedtls_fprintf( stderr, "\nBlock list\n" ); + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next; + } + + mbedtls_fprintf( stderr, "Free list\n" ); + cur = heap.first_free; + + while( cur != NULL ) + { + debug_header( cur ); + cur = cur->next_free; + } +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +static int verify_header( memory_header *hdr ) +{ + if( hdr->magic1 != MAGIC1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC1 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->magic2 != MAGIC2 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: MAGIC2 mismatch\n" ); +#endif + return( 1 ); + } + + if( hdr->alloc > 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: alloc has illegal value\n" ); +#endif + return( 1 ); + } + + if( hdr->prev != NULL && hdr->prev == hdr->next ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev == next\n" ); +#endif + return( 1 ); + } + + if( hdr->prev_free != NULL && hdr->prev_free == hdr->next_free ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: prev_free == next_free\n" ); +#endif + return( 1 ); + } + + return( 0 ); +} + +static int verify_chain( void ) +{ + memory_header *prv = heap.first, *cur; + + if( prv == NULL || verify_header( prv ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of first header " + "failed\n" ); +#endif + return( 1 ); + } + + if( heap.first->prev != NULL ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "first->prev != NULL\n" ); +#endif + return( 1 ); + } + + cur = heap.first->next; + + while( cur != NULL ) + { + if( verify_header( cur ) != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification of header " + "failed\n" ); +#endif + return( 1 ); + } + + if( cur->prev != prv ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: verification failed: " + "cur->prev != prv\n" ); +#endif + return( 1 ); + } + + prv = cur; + cur = cur->next; + } + + return( 0 ); +} + +static void *buffer_alloc_calloc( size_t n, size_t size ) +{ + memory_header *new, *cur = heap.first_free; + unsigned char *p; + void *ret; + size_t original_len, len; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + void *trace_buffer[MAX_BT]; + size_t trace_cnt; +#endif + + if( heap.buf == NULL || heap.first == NULL ) + return( NULL ); + + original_len = len = n * size; + + if( n == 0 || size == 0 || len / n != size ) + return( NULL ); + else if( len > (size_t)-MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return( NULL ); + + if( len % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + len += MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + // Find block that fits + // + while( cur != NULL ) + { + if( cur->size >= len ) + break; + + cur = cur->next_free; + } + + if( cur == NULL ) + return( NULL ); + + if( cur->alloc != 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: block in free_list but allocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.alloc_count++; +#endif + + // Found location, split block if > memory_header + 4 room left + // + if( cur->size - len < sizeof(memory_header) + + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + cur->alloc = 1; + + // Remove from free_list + // + if( cur->prev_free != NULL ) + cur->prev_free->next_free = cur->next_free; + else + heap.first_free = cur->next_free; + + if( cur->next_free != NULL ) + cur->next_free->prev_free = cur->prev_free; + + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); + } + + p = ( (unsigned char *) cur ) + sizeof(memory_header) + len; + new = (memory_header *) p; + + new->size = cur->size - len - sizeof(memory_header); + new->alloc = 0; + new->prev = cur; + new->next = cur->next; +#if defined(MBEDTLS_MEMORY_BACKTRACE) + new->trace = NULL; + new->trace_count = 0; +#endif + new->magic1 = MAGIC1; + new->magic2 = MAGIC2; + + if( new->next != NULL ) + new->next->prev = new; + + // Replace cur with new in free_list + // + new->prev_free = cur->prev_free; + new->next_free = cur->next_free; + if( new->prev_free != NULL ) + new->prev_free->next_free = new; + else + heap.first_free = new; + + if( new->next_free != NULL ) + new->next_free->prev_free = new; + + cur->alloc = 1; + cur->size = len; + cur->next = new; + cur->prev_free = NULL; + cur->next_free = NULL; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count++; + if( heap.header_count > heap.maximum_header_count ) + heap.maximum_header_count = heap.header_count; + heap.total_used += cur->size; + if( heap.total_used > heap.maximum_used ) + heap.maximum_used = heap.total_used; +#endif +#if defined(MBEDTLS_MEMORY_BACKTRACE) + trace_cnt = backtrace( trace_buffer, MAX_BT ); + cur->trace = backtrace_symbols( trace_buffer, trace_cnt ); + cur->trace_count = trace_cnt; +#endif + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); + + ret = (unsigned char *) cur + sizeof( memory_header ); + memset( ret, 0, original_len ); + + return( ret ); +} + +static void buffer_alloc_free( void *ptr ) +{ + memory_header *hdr, *old = NULL; + unsigned char *p = (unsigned char *) ptr; + + if( ptr == NULL || heap.buf == NULL || heap.first == NULL ) + return; + + if( p < heap.buf || p >= heap.buf + heap.len ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() outside of managed " + "space\n" ); +#endif + mbedtls_exit( 1 ); + } + + p -= sizeof(memory_header); + hdr = (memory_header *) p; + + if( verify_header( hdr ) != 0 ) + mbedtls_exit( 1 ); + + if( hdr->alloc != 1 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_fprintf( stderr, "FATAL: mbedtls_free() on unallocated " + "data\n" ); +#endif + mbedtls_exit( 1 ); + } + + hdr->alloc = 0; + +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.free_count++; + heap.total_used -= hdr->size; +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) + free( hdr->trace ); + hdr->trace = NULL; + hdr->trace_count = 0; +#endif + + // Regroup with block before + // + if( hdr->prev != NULL && hdr->prev->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->prev->size += sizeof(memory_header) + hdr->size; + hdr->prev->next = hdr->next; + old = hdr; + hdr = hdr->prev; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Regroup with block after + // + if( hdr->next != NULL && hdr->next->alloc == 0 ) + { +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.header_count--; +#endif + hdr->size += sizeof(memory_header) + hdr->next->size; + old = hdr->next; + hdr->next = hdr->next->next; + + if( hdr->prev_free != NULL || hdr->next_free != NULL ) + { + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr->next_free; + else + heap.first_free = hdr->next_free; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr->prev_free; + } + + hdr->prev_free = old->prev_free; + hdr->next_free = old->next_free; + + if( hdr->prev_free != NULL ) + hdr->prev_free->next_free = hdr; + else + heap.first_free = hdr; + + if( hdr->next_free != NULL ) + hdr->next_free->prev_free = hdr; + + if( hdr->next != NULL ) + hdr->next->prev = hdr; + + memset( old, 0, sizeof(memory_header) ); + } + + // Prepend to free_list if we have not merged + // (Does not have to stay in same order as prev / next list) + // + if( old == NULL ) + { + hdr->next_free = heap.first_free; + if( heap.first_free != NULL ) + heap.first_free->prev_free = hdr; + heap.first_free = hdr; + } + + if( ( heap.verify & MBEDTLS_MEMORY_VERIFY_FREE ) && verify_chain() != 0 ) + mbedtls_exit( 1 ); +} + +void mbedtls_memory_buffer_set_verify( int verify ) +{ + heap.verify = verify; +} + +int mbedtls_memory_buffer_alloc_verify( void ) +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status( void ) +{ + mbedtls_fprintf( stderr, + "Current use: %zu blocks / %zu bytes, max: %zu blocks / " + "%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n", + heap.header_count, heap.total_used, + heap.maximum_header_count, heap.maximum_used, + heap.maximum_header_count * sizeof( memory_header ) + + heap.maximum_used, + heap.alloc_count, heap.free_count ); + + if( heap.first->next == NULL ) + { + mbedtls_fprintf( stderr, "All memory de-allocated in stack buffer\n" ); + } + else + { + mbedtls_fprintf( stderr, "Memory currently allocated:\n" ); + debug_chain(); + } +} + +void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks ) +{ + *max_used = heap.maximum_used; + *max_blocks = heap.maximum_header_count; +} + +void mbedtls_memory_buffer_alloc_max_reset( void ) +{ + heap.maximum_used = 0; + heap.maximum_header_count = 0; +} + +void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks ) +{ + *cur_used = heap.total_used; + *cur_blocks = heap.header_count; +} +#endif /* MBEDTLS_MEMORY_DEBUG */ + +#if defined(MBEDTLS_THREADING_C) +static void *buffer_alloc_calloc_mutexed( size_t n, size_t size ) +{ + void *buf; + if( mbedtls_mutex_lock( &heap.mutex ) != 0 ) + return( NULL ); + buf = buffer_alloc_calloc( n, size ); + if( mbedtls_mutex_unlock( &heap.mutex ) ) + return( NULL ); + return( buf ); +} + +static void buffer_alloc_free_mutexed( void *ptr ) +{ + /* We have to good option here, but corrupting the heap seems + * worse than loosing memory. */ + if( mbedtls_mutex_lock( &heap.mutex ) ) + return; + buffer_alloc_free( ptr ); + (void) mbedtls_mutex_unlock( &heap.mutex ); +} +#endif /* MBEDTLS_THREADING_C */ + +void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len ) +{ + memset( &heap, 0, sizeof( buffer_alloc_ctx ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &heap.mutex ); + mbedtls_platform_set_calloc_free( buffer_alloc_calloc_mutexed, + buffer_alloc_free_mutexed ); +#else + mbedtls_platform_set_calloc_free( buffer_alloc_calloc, buffer_alloc_free ); +#endif + + if( len < sizeof( memory_header ) + MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + return; + else if( (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE ) + { + /* Adjust len first since buf is used in the computation */ + len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE + - (size_t)buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE; + } + + memset( buf, 0, len ); + + heap.buf = buf; + heap.len = len; + + heap.first = (memory_header *)buf; + heap.first->size = len - sizeof( memory_header ); + heap.first->magic1 = MAGIC1; + heap.first->magic2 = MAGIC2; + heap.first_free = heap.first; +} + +void mbedtls_memory_buffer_alloc_free( void ) +{ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &heap.mutex ); +#endif + mbedtls_platform_zeroize( &heap, sizeof(buffer_alloc_ctx) ); +} + +#if defined(MBEDTLS_SELF_TEST) +static int check_pointer( void *p ) +{ + if( p == NULL ) + return( -1 ); + + if( (size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0 ) + return( -1 ); + + return( 0 ); +} + +static int check_all_free( void ) +{ + if( +#if defined(MBEDTLS_MEMORY_DEBUG) + heap.total_used != 0 || +#endif + heap.first != heap.first_free || + (void *) heap.first != (void *) heap.buf ) + { + return( -1 ); + } + + return( 0 ); +} + +#define TEST_ASSERT( condition ) \ + if( ! (condition) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf( "failed\n" ); \ + \ + ret = 1; \ + goto cleanup; \ + } + +int mbedtls_memory_buffer_alloc_self_test( int verbose ) +{ + unsigned char buf[1024]; + unsigned char *p, *q, *r, *end; + int ret = 0; + + if( verbose != 0 ) + mbedtls_printf( " MBA test #1 (basic alloc-free cycle): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + /* Memorize end to compare with the next test */ + end = heap.buf + heap.len; + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #2 (buf not aligned): " ); + + mbedtls_memory_buffer_alloc_init( buf + 1, sizeof( buf ) - 1 ); + + TEST_ASSERT( heap.buf + heap.len == end ); + + p = mbedtls_calloc( 1, 1 ); + q = mbedtls_calloc( 1, 128 ); + r = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && + check_pointer( q ) == 0 && + check_pointer( r ) == 0 ); + + mbedtls_free( r ); + mbedtls_free( q ); + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MBA test #3 (full): " ); + + mbedtls_memory_buffer_alloc_init( buf, sizeof( buf ) ); + + p = mbedtls_calloc( 1, sizeof( buf ) - sizeof( memory_header ) ); + + TEST_ASSERT( check_pointer( p ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( p ); + + p = mbedtls_calloc( 1, sizeof( buf ) - 2 * sizeof( memory_header ) - 16 ); + q = mbedtls_calloc( 1, 16 ); + + TEST_ASSERT( check_pointer( p ) == 0 && check_pointer( q ) == 0 ); + TEST_ASSERT( mbedtls_calloc( 1, 1 ) == NULL ); + + mbedtls_free( q ); + + TEST_ASSERT( mbedtls_calloc( 1, 17 ) == NULL ); + + mbedtls_free( p ); + + TEST_ASSERT( check_all_free( ) == 0 ); + + mbedtls_memory_buffer_alloc_free( ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + mbedtls_memory_buffer_alloc_free( ); + + return( ret ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/mps_common.h b/component/common/network/ssl/mbedtls-3.1.0/library/mps_common.h new file mode 100644 index 00000000..d20776f1 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/mps_common.h @@ -0,0 +1,195 @@ +/* + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/** + * \file mps_common.h + * + * \brief Common functions and macros used by MPS + */ + +#ifndef MBEDTLS_MPS_COMMON_H +#define MBEDTLS_MPS_COMMON_H + +#include "mps_error.h" + +#include + +/** + * \name SECTION: MPS Configuration + * + * \{ + */ + +/*! This flag controls whether the MPS-internal components + * (reader, writer, Layer 1-3) perform validation of the + * expected abstract state at the entry of API calls. + * + * Context: All MPS API functions impose assumptions/preconditions on the + * context on which they operate. For example, every structure has a notion of + * state integrity which is established by `xxx_init()` and preserved by any + * calls to the MPS API which satisfy their preconditions and either succeed, + * or fail with an error code which is explicitly documented to not corrupt + * structure integrity (such as WANT_READ and WANT_WRITE); + * apart from `xxx_init()` any function assumes state integrity as a + * precondition (but usually more). If any of the preconditions is violated, + * the function's behavior is entirely undefined. + * In addition to state integrity, all MPS structures have a more refined + * notion of abstract state that the API operates on. For example, all layers + * have a notion of 'abtract read state' which indicates if incoming data has + * been passed to the user, e.g. through mps_l2_read_start() for Layer 2 + * or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to + * call these reading functions again until the incoming data has been + * explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or + * mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense, + * it's a design choice whether the API should fail gracefully on such + * non-sensical calls or not, and that's what this option is about: + * + * This option determines whether the expected abstract state + * is part of the API preconditions or not: If the option is set, + * then the abstract state is not part of the precondition and is + * thus required to be validated by the implementation. If an unexpected + * abstract state is encountered, the implementation must fail gracefully + * with error #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED. + * Conversely, if this option is not set, then the expected abstract state + * is included in the preconditions of the respective API calls, and + * an implementation's behaviour is undefined if the abstract state is + * not as expected. + * + * For example: Enabling this makes mps_l2_read_done() fail if + * no incoming record is currently open; disabling this would + * lead to undefined behavior in this case. + * + * Comment this to remove state validation. + */ +#define MBEDTLS_MPS_STATE_VALIDATION + +/*! This flag enables/disables assertions on the internal state of MPS. + * + * Assertions are sanity checks that should never trigger when MPS + * is used within the bounds of its API and preconditions. + * + * Enabling this increases security by limiting the scope of + * potential bugs, but comes at the cost of increased code size. + * + * Note: So far, there is no guiding principle as to what + * expected conditions merit an assertion, and which don't. + * + * Comment this to disable assertions. + */ +#define MBEDTLS_MPS_ENABLE_ASSERTIONS + +/*! This flag controls whether tracing for MPS should be enabled. */ +//#define MBEDTLS_MPS_ENABLE_TRACE + +#if defined(MBEDTLS_MPS_STATE_VALIDATION) + +#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string ) \ + do \ + { \ + if( !(cond) ) \ + { \ + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, string ); \ + MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED ); \ + } \ + } while( 0 ) + +#else /* MBEDTLS_MPS_STATE_VALIDATION */ + +#define MBEDTLS_MPS_STATE_VALIDATE_RAW( cond, string ) \ + do \ + { \ + ( cond ); \ + } while( 0 ) + +#endif /* MBEDTLS_MPS_STATE_VALIDATION */ + +#if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS) + +#define MBEDTLS_MPS_ASSERT_RAW( cond, string ) \ + do \ + { \ + if( !(cond) ) \ + { \ + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, string ); \ + MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_INTERNAL_ERROR ); \ + } \ + } while( 0 ) + +#else /* MBEDTLS_MPS_ENABLE_ASSERTIONS */ + +#define MBEDTLS_MPS_ASSERT_RAW( cond, string ) do {} while( 0 ) + +#endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */ + + +/* \} name SECTION: MPS Configuration */ + +/** + * \name SECTION: Common types + * + * Various common types used throughout MPS. + * \{ + */ + +/** \brief The type of buffer sizes and offsets used in MPS structures. + * + * This is an unsigned integer type that should be large enough to + * hold the length of any buffer or message processed by MPS. + * + * The reason to pick a value as small as possible here is + * to reduce the size of MPS structures. + * + * \warning Care has to be taken when using a narrower type + * than ::mbedtls_mps_size_t here because of + * potential truncation during conversion. + * + * \warning Handshake messages in TLS may be up to 2^24 ~ 16Mb in size. + * If mbedtls_mps_[opt_]stored_size_t is smaller than that, the + * maximum handshake message is restricted accordingly. + * + * For now, we use the default type of size_t throughout, and the use of + * smaller types or different types for ::mbedtls_mps_size_t and + * ::mbedtls_mps_stored_size_t is not yet supported. + * + */ +typedef size_t mbedtls_mps_stored_size_t; +#define MBEDTLS_MPS_STORED_SIZE_MAX ( (mbedtls_mps_stored_size_t) -1 ) + +/** \brief The type of buffer sizes and offsets used in the MPS API + * and implementation. + * + * This must be at least as wide as ::mbedtls_stored_size_t but + * may be chosen to be strictly larger if more suitable for the + * target architecture. + * + * For example, in a test build for ARM Thumb, using uint_fast16_t + * instead of uint16_t reduced the code size from 1060 Byte to 962 Byte, + * so almost 10%. + */ +typedef size_t mbedtls_mps_size_t; +#define MBEDTLS_MPS_SIZE_MAX ( (mbedtls_mps_size_t) -1 ) + +#if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX +#error "Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t." +#endif + +/* \} SECTION: Common types */ + + +#endif /* MBEDTLS_MPS_COMMON_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/mps_error.h b/component/common/network/ssl/mbedtls-3.1.0/library/mps_error.h new file mode 100644 index 00000000..f78d9a05 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/mps_error.h @@ -0,0 +1,103 @@ +/* + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/** + * \file mps_error.h + * + * \brief Error codes used by MPS + */ + +#ifndef MBEDTLS_MPS_ERROR_H +#define MBEDTLS_MPS_ERROR_H + + +/* TODO: The error code allocation needs to be revisited: + * + * - Should we make (some of) the MPS Reader error codes public? + * If so, we need to adjust MBEDTLS_MPS_READER_MAKE_ERROR() to hit + * a gap in the Mbed TLS public error space. + * If not, we have to make sure we don't forward those errors + * at the level of the public API -- no risk at the moment as + * long as MPS is an experimental component not accessible from + * public API. + */ + +/** + * \name SECTION: MPS general error codes + * + * \{ + */ + +#ifndef MBEDTLS_MPS_ERR_BASE +#define MBEDTLS_MPS_ERR_BASE ( 0 ) +#endif + +#define MBEDTLS_MPS_MAKE_ERROR(code) \ + ( -( MBEDTLS_MPS_ERR_BASE | (code) ) ) + +#define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED MBEDTLS_MPS_MAKE_ERROR( 0x1 ) +#define MBEDTLS_ERR_MPS_INTERNAL_ERROR MBEDTLS_MPS_MAKE_ERROR( 0x2 ) + +/* \} name SECTION: MPS general error codes */ + +/** + * \name SECTION: MPS Reader error codes + * + * \{ + */ + +#ifndef MBEDTLS_MPS_READER_ERR_BASE +#define MBEDTLS_MPS_READER_ERR_BASE ( 1 << 8 ) +#endif + +#define MBEDTLS_MPS_READER_MAKE_ERROR(code) \ + ( -( MBEDTLS_MPS_READER_ERR_BASE | (code) ) ) + +/*! An attempt to reclaim the data buffer from a reader failed because + * the user hasn't yet read and committed all of it. */ +#define MBEDTLS_ERR_MPS_READER_DATA_LEFT MBEDTLS_MPS_READER_MAKE_ERROR( 0x1 ) + +/*! An invalid argument was passed to the reader. */ +#define MBEDTLS_ERR_MPS_READER_INVALID_ARG MBEDTLS_MPS_READER_MAKE_ERROR( 0x2 ) + +/*! An attempt to move a reader to consuming mode through mbedtls_mps_reader_feed() + * after pausing failed because the provided data is not sufficient to serve the + * read requests that led to the pausing. */ +#define MBEDTLS_ERR_MPS_READER_NEED_MORE MBEDTLS_MPS_READER_MAKE_ERROR( 0x3 ) + +/*! A get request failed because not enough data is available in the reader. */ +#define MBEDTLS_ERR_MPS_READER_OUT_OF_DATA MBEDTLS_MPS_READER_MAKE_ERROR( 0x4 ) + +/*!< A get request after pausing and reactivating the reader failed because + * the request is not in line with the request made prior to pausing. The user + * must not change it's 'strategy' after pausing and reactivating a reader. */ +#define MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS MBEDTLS_MPS_READER_MAKE_ERROR( 0x5 ) + +/*! An attempt to reclaim the data buffer from a reader failed because the reader + * has no accumulator it can use to backup the data that hasn't been processed. */ +#define MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR MBEDTLS_MPS_READER_MAKE_ERROR( 0x6 ) + +/*! An attempt to reclaim the data buffer from a reader failed because the + * accumulator passed to the reader is not large enough to hold both the + * data that hasn't been processed and the excess of the last read-request. */ +#define MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL MBEDTLS_MPS_READER_MAKE_ERROR( 0x7 ) + +/* \} name SECTION: MPS Reader error codes */ + +#endif /* MBEDTLS_MPS_ERROR_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.c b/component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.c new file mode 100644 index 00000000..36958b46 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.c @@ -0,0 +1,564 @@ +/* + * Message Processing Stack, Reader implementation + * + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include "mps_reader.h" +#include "mps_common.h" +#include "mps_trace.h" + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_MPS_ENABLE_TRACE) +static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER; +#endif /* MBEDTLS_MPS_ENABLE_TRACE */ + +/* + * GENERAL NOTE ON CODING STYLE + * + * The following code intentionally separates memory loads + * and stores from other operations (arithmetic or branches). + * This leads to the introduction of many local variables + * and significantly increases the C-code line count, but + * should not increase the size of generated assembly. + * + * The reason for this is twofold: + * (1) It will ease verification efforts using the VST + * (Verified Software Toolchain) + * whose program logic cannot directly reason + * about instructions containing a load or store in + * addition to other operations (e.g. *p = *q or + * tmp = *p + 42). + * (2) Operating on local variables and writing the results + * back to the target contexts on success only + * allows to maintain structure invariants even + * on failure - this in turn has two benefits: + * (2.a) If for some reason an error code is not caught + * and operation continues, functions are nonetheless + * called with sane contexts, reducing the risk + * of dangerous behavior. + * (2.b) Randomized testing is easier if structures + * remain intact even in the face of failing + * and/or non-sensical calls. + * Moreover, it might even reduce code-size because + * the compiler need not write back temporary results + * to memory in case of failure. + * + */ + +static inline int mps_reader_is_accumulating( + mbedtls_mps_reader const *rd ) +{ + mbedtls_mps_size_t acc_remaining; + if( rd->acc == NULL ) + return( 0 ); + + acc_remaining = rd->acc_share.acc_remaining; + return( acc_remaining > 0 ); +} + +static inline int mps_reader_is_producing( + mbedtls_mps_reader const *rd ) +{ + unsigned char *frag = rd->frag; + return( frag == NULL ); +} + +static inline int mps_reader_is_consuming( + mbedtls_mps_reader const *rd ) +{ + return( !mps_reader_is_producing( rd ) ); +} + +static inline mbedtls_mps_size_t mps_reader_get_fragment_offset( + mbedtls_mps_reader const *rd ) +{ + unsigned char *acc = rd->acc; + mbedtls_mps_size_t frag_offset; + + if( acc == NULL ) + return( 0 ); + + frag_offset = rd->acc_share.frag_offset; + return( frag_offset ); +} + +static inline mbedtls_mps_size_t mps_reader_serving_from_accumulator( + mbedtls_mps_reader const *rd ) +{ + mbedtls_mps_size_t frag_offset, end; + + frag_offset = mps_reader_get_fragment_offset( rd ); + end = rd->end; + + return( end < frag_offset ); +} + +static inline void mps_reader_zero( mbedtls_mps_reader *rd ) +{ + /* A plain memset() would likely be more efficient, + * but the current way of zeroing makes it harder + * to overlook fields which should not be zero-initialized. + * It's also more suitable for FV efforts since it + * doesn't require reasoning about structs being + * interpreted as unstructured binary blobs. */ + static mbedtls_mps_reader const zero = + { .frag = NULL, + .frag_len = 0, + .commit = 0, + .end = 0, + .pending = 0, + .acc = NULL, + .acc_len = 0, + .acc_available = 0, + .acc_share = { .acc_remaining = 0 } + }; + *rd = zero; +} + +int mbedtls_mps_reader_init( mbedtls_mps_reader *rd, + unsigned char *acc, + mbedtls_mps_size_t acc_len ) +{ + MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_init" ); + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "* Accumulator size: %u bytes", (unsigned) acc_len ); + mps_reader_zero( rd ); + rd->acc = acc; + rd->acc_len = acc_len; + MBEDTLS_MPS_TRACE_RETURN( 0 ); +} + +int mbedtls_mps_reader_free( mbedtls_mps_reader *rd ) +{ + MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_free" ); + mps_reader_zero( rd ); + MBEDTLS_MPS_TRACE_RETURN( 0 ); +} + +int mbedtls_mps_reader_feed( mbedtls_mps_reader *rd, + unsigned char *new_frag, + mbedtls_mps_size_t new_frag_len ) +{ + mbedtls_mps_size_t copy_to_acc; + MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_feed" ); + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "* Fragment length: %u bytes", (unsigned) new_frag_len ); + + if( new_frag == NULL ) + MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_INVALID_ARG ); + + MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_producing( rd ), + "mbedtls_mps_reader_feed() requires reader to be in producing mode" ); + + if( mps_reader_is_accumulating( rd ) ) + { + unsigned char *acc = rd->acc; + mbedtls_mps_size_t acc_remaining = rd->acc_share.acc_remaining; + mbedtls_mps_size_t acc_available = rd->acc_available; + + /* Skip over parts of the accumulator that have already been filled. */ + acc += acc_available; + + copy_to_acc = acc_remaining; + if( copy_to_acc > new_frag_len ) + copy_to_acc = new_frag_len; + + /* Copy new contents to accumulator. */ + memcpy( acc, new_frag, copy_to_acc ); + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Copy new data of size %u of %u into accumulator at offset %u", + (unsigned) copy_to_acc, (unsigned) new_frag_len, (unsigned) acc_available ); + + /* Check if, with the new fragment, we have enough data. */ + acc_remaining -= copy_to_acc; + if( acc_remaining > 0 ) + { + /* We need to accumulate more data. Stay in producing mode. */ + acc_available += copy_to_acc; + rd->acc_share.acc_remaining = acc_remaining; + rd->acc_available = acc_available; + MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_NEED_MORE ); + } + + /* We have filled the accumulator: Move to consuming mode. */ + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Enough data available to serve user request" ); + + /* Remember overlap of accumulator and fragment. */ + rd->acc_share.frag_offset = acc_available; + acc_available += copy_to_acc; + rd->acc_available = acc_available; + } + else /* Not accumulating */ + { + rd->acc_share.frag_offset = 0; + } + + rd->frag = new_frag; + rd->frag_len = new_frag_len; + rd->commit = 0; + rd->end = 0; + MBEDTLS_MPS_TRACE_RETURN( 0 ); +} + + +int mbedtls_mps_reader_get( mbedtls_mps_reader *rd, + mbedtls_mps_size_t desired, + unsigned char **buffer, + mbedtls_mps_size_t *buflen ) +{ + unsigned char *frag; + mbedtls_mps_size_t frag_len, frag_offset, end, frag_fetched, frag_remaining; + MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_get" ); + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "* Bytes requested: %u", (unsigned) desired ); + + MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ), + "mbedtls_mps_reader_get() requires reader to be in consuming mode" ); + + end = rd->end; + frag_offset = mps_reader_get_fragment_offset( rd ); + + /* Check if we're still serving from the accumulator. */ + if( mps_reader_serving_from_accumulator( rd ) ) + { + /* Illustration of supported and unsupported cases: + * + * - Allowed #1 + * + * +-----------------------------------+ + * | frag | + * +-----------------------------------+ + * + * end end+desired + * | | + * +-----v-------v-------------+ + * | acc | + * +---------------------------+ + * | | + * frag_offset acc_available + * + * - Allowed #2 + * + * +-----------------------------------+ + * | frag | + * +-----------------------------------+ + * + * end end+desired + * | | + * +----------v----------------v + * | acc | + * +---------------------------+ + * | | + * frag_offset acc_available + * + * - Not allowed #1 (could be served, but we don't actually use it): + * + * +-----------------------------------+ + * | frag | + * +-----------------------------------+ + * + * end end+desired + * | | + * +------v-------------v------+ + * | acc | + * +---------------------------+ + * | | + * frag_offset acc_available + * + * + * - Not allowed #2 (can't be served with a contiguous buffer): + * + * +-----------------------------------+ + * | frag | + * +-----------------------------------+ + * + * end end + desired + * | | + * +------v--------------------+ v + * | acc | + * +---------------------------+ + * | | + * frag_offset acc_available + * + * In case of Allowed #2 we're switching to serve from + * `frag` starting from the next call to mbedtls_mps_reader_get(). + */ + + unsigned char *acc; + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Serve the request from the accumulator" ); + if( frag_offset - end < desired ) + { + mbedtls_mps_size_t acc_available; + acc_available = rd->acc_available; + if( acc_available - end != desired ) + { + /* It might be possible to serve some of these situations by + * making additional space in the accumulator, removing those + * parts that have already been committed. + * On the other hand, this brings additional complexity and + * enlarges the code size, while there doesn't seem to be a use + * case where we don't attempt exactly the same `get` calls when + * resuming on a reader than what we tried before pausing it. + * If we believe we adhere to this restricted usage throughout + * the library, this check is a good opportunity to + * validate this. */ + MBEDTLS_MPS_TRACE_RETURN( + MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS ); + } + } + + acc = rd->acc; + acc += end; + + *buffer = acc; + if( buflen != NULL ) + *buflen = desired; + + end += desired; + rd->end = end; + rd->pending = 0; + + MBEDTLS_MPS_TRACE_RETURN( 0 ); + } + + /* Attempt to serve the request from the current fragment */ + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Serve the request from the current fragment." ); + + frag_len = rd->frag_len; + frag_fetched = end - frag_offset; /* The amount of data from the current + * fragment that has already been passed + * to the user. */ + frag_remaining = frag_len - frag_fetched; /* Remaining data in fragment */ + + /* Check if we can serve the read request from the fragment. */ + if( frag_remaining < desired ) + { + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "There's not enough data in the current fragment " + "to serve the request." ); + /* There's not enough data in the current fragment, + * so either just RETURN what we have or fail. */ + if( buflen == NULL ) + { + if( frag_remaining > 0 ) + { + rd->pending = desired - frag_remaining; + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Remember to collect %u bytes before re-opening", + (unsigned) rd->pending ); + } + MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_OUT_OF_DATA ); + } + + desired = frag_remaining; + } + + /* There's enough data in the current fragment to serve the + * (potentially modified) read request. */ + + frag = rd->frag; + frag += frag_fetched; + + *buffer = frag; + if( buflen != NULL ) + *buflen = desired; + + end += desired; + rd->end = end; + rd->pending = 0; + MBEDTLS_MPS_TRACE_RETURN( 0 ); +} + +int mbedtls_mps_reader_commit( mbedtls_mps_reader *rd ) +{ + mbedtls_mps_size_t end; + MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_commit" ); + MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ), + "mbedtls_mps_reader_commit() requires reader to be in consuming mode" ); + + end = rd->end; + rd->commit = end; + + MBEDTLS_MPS_TRACE_RETURN( 0 ); +} + +int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *rd, + int *paused ) +{ + unsigned char *frag, *acc; + mbedtls_mps_size_t pending, commit; + mbedtls_mps_size_t acc_len, frag_offset, frag_len; + MBEDTLS_MPS_TRACE_INIT( "mbedtls_mps_reader_reclaim" ); + + if( paused != NULL ) + *paused = 0; + + MBEDTLS_MPS_STATE_VALIDATE_RAW( mps_reader_is_consuming( rd ), + "mbedtls_mps_reader_reclaim() requires reader to be in consuming mode" ); + + frag = rd->frag; + acc = rd->acc; + pending = rd->pending; + commit = rd->commit; + frag_len = rd->frag_len; + + frag_offset = mps_reader_get_fragment_offset( rd ); + + if( pending == 0 ) + { + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "No unsatisfied read-request has been logged." ); + + /* Check if there's data left to be consumed. */ + if( commit < frag_offset || commit - frag_offset < frag_len ) + { + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "There is data left to be consumed." ); + rd->end = commit; + MBEDTLS_MPS_TRACE_RETURN( MBEDTLS_ERR_MPS_READER_DATA_LEFT ); + } + + rd->acc_available = 0; + rd->acc_share.acc_remaining = 0; + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Fragment has been fully processed and committed." ); + } + else + { + int overflow; + + mbedtls_mps_size_t acc_backup_offset; + mbedtls_mps_size_t acc_backup_len; + mbedtls_mps_size_t frag_backup_offset; + mbedtls_mps_size_t frag_backup_len; + + mbedtls_mps_size_t backup_len; + mbedtls_mps_size_t acc_len_needed; + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "There has been an unsatisfied read with %u bytes overhead.", + (unsigned) pending ); + + if( acc == NULL ) + { + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "No accumulator present" ); + MBEDTLS_MPS_TRACE_RETURN( + MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR ); + } + acc_len = rd->acc_len; + + /* Check if the upper layer has already fetched + * and committed the contents of the accumulator. */ + if( commit < frag_offset ) + { + /* No, accumulator is still being processed. */ + frag_backup_offset = 0; + frag_backup_len = frag_len; + acc_backup_offset = commit; + acc_backup_len = frag_offset - commit; + } + else + { + /* Yes, the accumulator is already processed. */ + frag_backup_offset = commit - frag_offset; + frag_backup_len = frag_len - frag_backup_offset; + acc_backup_offset = 0; + acc_backup_len = 0; + } + + backup_len = acc_backup_len + frag_backup_len; + acc_len_needed = backup_len + pending; + + overflow = 0; + overflow |= ( backup_len < acc_backup_len ); + overflow |= ( acc_len_needed < backup_len ); + + if( overflow || acc_len < acc_len_needed ) + { + /* Except for the different return code, we behave as if + * there hadn't been a call to mbedtls_mps_reader_get() + * since the last commit. */ + rd->end = commit; + rd->pending = 0; + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, + "The accumulator is too small to handle the backup." ); + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, + "* Size: %u", (unsigned) acc_len ); + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_ERROR, + "* Needed: %u (%u + %u)", + (unsigned) acc_len_needed, + (unsigned) backup_len, (unsigned) pending ); + MBEDTLS_MPS_TRACE_RETURN( + MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL ); + } + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Fragment backup: %u", (unsigned) frag_backup_len ); + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Accumulator backup: %u", (unsigned) acc_backup_len ); + + /* Move uncommitted parts from the accumulator to the front + * of the accumulator. */ + memmove( acc, acc + acc_backup_offset, acc_backup_len ); + + /* Copy uncmmitted parts of the current fragment to the + * accumulator. */ + memcpy( acc + acc_backup_len, + frag + frag_backup_offset, frag_backup_len ); + + rd->acc_available = backup_len; + rd->acc_share.acc_remaining = pending; + + if( paused != NULL ) + *paused = 1; + } + + rd->frag = NULL; + rd->frag_len = 0; + + rd->commit = 0; + rd->end = 0; + rd->pending = 0; + + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_COMMENT, + "Final state: aa %u, al %u, ar %u", + (unsigned) rd->acc_available, (unsigned) rd->acc_len, + (unsigned) rd->acc_share.acc_remaining ); + MBEDTLS_MPS_TRACE_RETURN( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.h b/component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.h new file mode 100644 index 00000000..427c1bd2 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/mps_reader.h @@ -0,0 +1,382 @@ +/* + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/** + * \file mps_reader.h + * + * \brief This file defines reader objects, which together with their + * sibling writer objects form the basis for the communication + * between the various layers of the Mbed TLS messaging stack, + * as well as the communication between the messaging stack and + * the (D)TLS handshake protocol implementation. + * + * Readers provide a means of transferring incoming data from + * a 'producer' providing it in chunks of arbitrary size, to + * a 'consumer' which fetches and processes it in chunks of + * again arbitrary, and potentially different, size. + * + * Readers can thus be seen as datagram-to-stream converters, + * and they abstract away the following two tasks from the user: + * 1. The pointer arithmetic of stepping through a producer- + * provided chunk in smaller chunks. + * 2. The merging of incoming data chunks in case the + * consumer requests data in larger chunks than what the + * producer provides. + * + * The basic abstract flow of operation is the following: + * - Initially, the reader is in 'producing mode'. + * - The producer hands an incoming data buffer to the reader, + * moving it from 'producing' to 'consuming' mode. + * - The consumer subsequently fetches and processes the buffer + * content. Once that's done -- or partially done and a consumer's + * request can't be fulfilled -- the producer revokes the reader's + * access to the incoming data buffer, putting the reader back to + * producing mode. + * - The producer subsequently gathers more incoming data and hands + * it to the reader until it switches back to consuming mode + * if enough data is available for the last consumer request to + * be satisfiable. + * - Repeat the above. + * + * The abstract states of the reader from the producer's and + * consumer's perspective are as follows: + * + * - From the perspective of the consumer, the state of the + * reader consists of the following: + * - A byte stream representing (concatenation of) the data + * received through calls to mbedtls_mps_reader_get(), + * - A marker within that byte stream indicating which data + * can be considered processed, and hence need not be retained, + * when the reader is passed back to the producer via + * mbedtls_mps_reader_reclaim(). + * The marker is set via mbedtls_mps_reader_commit() + * which places it at the end of the current byte stream. + * The consumer need not be aware of the distinction between consumer + * and producer mode, because it only interfaces with the reader + * when the latter is in consuming mode. + * + * - From the perspective of the producer, the reader's state is one of: + * - Attached: The reader is in consuming mode. + * - Unset: No incoming data buffer is currently managed by the reader, + * and all previously handed incoming data buffers have been + * fully processed. More data needs to be fed into the reader + * via mbedtls_mps_reader_feed(). + * + * - Accumulating: No incoming data buffer is currently managed by the + * reader, but some data from the previous incoming data + * buffer hasn't been processed yet and is internally + * held back. + * The Attached state belongs to consuming mode, while the Unset and + * Accumulating states belong to producing mode. + * + * Transitioning from the Unset or Accumulating state to Attached is + * done via successful calls to mbedtls_mps_reader_feed(), while + * transitioning from Attached to either Unset or Accumulating (depending + * on what has been processed) is done via mbedtls_mps_reader_reclaim(). + * + * The following diagram depicts the producer-state progression: + * + * +------------------+ reclaim + * | Unset +<-------------------------------------+ get + * +--------|---------+ | +------+ + * | | | | + * | | | | + * | feed +---------+---+--+ | + * +--------------------------------------> <---+ + * | Attached | + * +--------------------------------------> <---+ + * | feed, enough data available +---------+---+--+ | + * | to serve previous consumer request | | | + * | | | | + * +--------+---------+ | +------+ + * +----> Accumulating |<-------------------------------------+ commit + * | +---+--------------+ reclaim, previous read request + * | | couldn't be fulfilled + * | | + * +--------+ + * feed, need more data to serve + * previous consumer request + * | + * | + * producing mode | consuming mode + * | + * + */ + +#ifndef MBEDTLS_READER_H +#define MBEDTLS_READER_H + +#include + +#include "mps_common.h" +#include "mps_error.h" + +struct mbedtls_mps_reader; +typedef struct mbedtls_mps_reader mbedtls_mps_reader; + +/* + * Structure definitions + */ + +struct mbedtls_mps_reader +{ + unsigned char *frag; /*!< The fragment of incoming data managed by + * the reader; it is provided to the reader + * through mbedtls_mps_reader_feed(). The reader + * does not own the fragment and does not + * perform any allocation operations on it, + * but does have read and write access to it. + * + * The reader is in consuming mode if + * and only if \c frag is not \c NULL. */ + mbedtls_mps_stored_size_t frag_len; + /*!< The length of the current fragment. + * Must be 0 if \c frag == \c NULL. */ + mbedtls_mps_stored_size_t commit; + /*!< The offset of the last commit, relative + * to the first byte in the fragment, if + * no accumulator is present. If an accumulator + * is present, it is viewed as a prefix to the + * current fragment, and this variable contains + * an offset from the beginning of the accumulator. + * + * This is only used when the reader is in + * consuming mode, i.e. \c frag != \c NULL; + * otherwise, its value is \c 0. */ + mbedtls_mps_stored_size_t end; + /*!< The offset of the end of the last chunk + * passed to the user through a call to + * mbedtls_mps_reader_get(), relative to the first + * byte in the fragment, if no accumulator is + * present. If an accumulator is present, it is + * viewed as a prefix to the current fragment, and + * this variable contains an offset from the + * beginning of the accumulator. + * + * This is only used when the reader is in + * consuming mode, i.e. \c frag != \c NULL; + * otherwise, its value is \c 0. */ + mbedtls_mps_stored_size_t pending; + /*!< The amount of incoming data missing on the + * last call to mbedtls_mps_reader_get(). + * In particular, it is \c 0 if the last call + * was successful. + * If a reader is reclaimed after an + * unsuccessful call to mbedtls_mps_reader_get(), + * this variable is used to have the reader + * remember how much data should be accumulated + * so that the call to mbedtls_mps_reader_get() + * succeeds next time. + * This is only used when the reader is in + * consuming mode, i.e. \c frag != \c NULL; + * otherwise, its value is \c 0. */ + + /* The accumulator is only needed if we need to be able to pause + * the reader. A few bytes could be saved by moving this to a + * separate struct and using a pointer here. */ + + unsigned char *acc; /*!< The accumulator is used to gather incoming + * data if a read-request via mbedtls_mps_reader_get() + * cannot be served from the current fragment. */ + mbedtls_mps_stored_size_t acc_len; + /*!< The total size of the accumulator. */ + mbedtls_mps_stored_size_t acc_available; + /*!< The number of bytes currently gathered in + * the accumulator. This is both used in + * producing and in consuming mode: + * While producing, it is increased until + * it reaches the value of \c acc_remaining below. + * While consuming, it is used to judge if a + * get request can be served from the + * accumulator or not. + * Must not be larger than \c acc_len. */ + union + { + mbedtls_mps_stored_size_t acc_remaining; + /*!< This indicates the amount of data still + * to be gathered in the accumulator. It is + * only used in producing mode. + * Must be at most acc_len - acc_available. */ + mbedtls_mps_stored_size_t frag_offset; + /*!< If an accumulator is present and in use, this + * field indicates the offset of the current + * fragment from the beginning of the + * accumulator. If no accumulator is present + * or the accumulator is not in use, this is \c 0. + * It is only used in consuming mode. + * Must not be larger than \c acc_available. */ + } acc_share; +}; + +/* + * API organization: + * A reader object is usually prepared and maintained + * by some lower layer and passed for usage to an upper + * layer, and the API naturally splits according to which + * layer is supposed to use the respective functions. + */ + +/* + * Maintenance API (Lower layer) + */ + +/** + * \brief Initialize a reader object + * + * \param reader The reader to be initialized. + * \param acc The buffer to be used as a temporary accumulator + * in case get requests through mbedtls_mps_reader_get() + * exceed the buffer provided by mbedtls_mps_reader_feed(). + * This buffer is owned by the caller and exclusive use + * for reading and writing is given to the reader for the + * duration of the reader's lifetime. It is thus the caller's + * responsibility to maintain (and not touch) the buffer for + * the lifetime of the reader, and to properly zeroize and + * free the memory after the reader has been destroyed. + * \param acc_len The size in Bytes of \p acc. + * + * \return \c 0 on success. + * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. + */ +int mbedtls_mps_reader_init( mbedtls_mps_reader *reader, + unsigned char *acc, + mbedtls_mps_size_t acc_len ); + +/** + * \brief Free a reader object + * + * \param reader The reader to be freed. + * + * \return \c 0 on success. + * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. + */ +int mbedtls_mps_reader_free( mbedtls_mps_reader *reader ); + +/** + * \brief Pass chunk of data for the reader to manage. + * + * \param reader The reader context to use. The reader must be + * in producing mode. + * \param buf The buffer to be managed by the reader. + * \param buflen The size in Bytes of \p buffer. + * + * \return \c 0 on success. In this case, the reader will be + * moved to consuming mode and obtains read access + * of \p buf until mbedtls_mps_reader_reclaim() + * is called. It is the responsibility of the caller + * to ensure that the \p buf persists and is not changed + * between successful calls to mbedtls_mps_reader_feed() + * and mbedtls_mps_reader_reclaim(). + * \return \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is + * required to fulfill a previous request to mbedtls_mps_reader_get(). + * In this case, the reader remains in producing mode and + * takes no ownership of the provided buffer (an internal copy + * is made instead). + * \return Another negative \c MBEDTLS_ERR_READER_XXX error code on + * different kinds of failures. + */ +int mbedtls_mps_reader_feed( mbedtls_mps_reader *reader, + unsigned char *buf, + mbedtls_mps_size_t buflen ); + +/** + * \brief Reclaim reader's access to the current input buffer. + * + * \param reader The reader context to use. The reader must be + * in consuming mode. + * \param paused If not \c NULL, the integer at address \p paused will be + * modified to indicate whether the reader has been paused + * (value \c 1) or not (value \c 0). Pausing happens if there + * is uncommitted data and a previous request to + * mbedtls_mps_reader_get() has exceeded the bounds of the + * input buffer. + * + * \return \c 0 on success. + * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. + */ +int mbedtls_mps_reader_reclaim( mbedtls_mps_reader *reader, + int *paused ); + +/* + * Usage API (Upper layer) + */ + +/** + * \brief Request data from the reader. + * + * \param reader The reader context to use. The reader must + * be in consuming mode. + * \param desired The desired amount of data to be read, in Bytes. + * \param buffer The address to store the buffer pointer in. + * This must not be \c NULL. + * \param buflen The address to store the actual buffer + * length in, or \c NULL. + * + * \return \c 0 on success. In this case, \c *buf holds the + * address of a buffer of size \c *buflen + * (if \c buflen != \c NULL) or \c desired + * (if \c buflen == \c NULL). The user has read access + * to the buffer and guarantee of stability of the data + * until the next call to mbedtls_mps_reader_reclaim(). + * \return #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough + * data available to serve the get request. In this case, the + * reader remains intact and in consuming mode, and the consumer + * should retry the call after a successful cycle of + * mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed(). + * If, after such a cycle, the consumer requests a different + * amount of data, the result is implementation-defined; + * progress is guaranteed only if the same amount of data + * is requested after a mbedtls_mps_reader_reclaim() and + * mbedtls_mps_reader_feed() cycle. + * \return Another negative \c MBEDTLS_ERR_READER_XXX error + * code for different kinds of failure. + * + * \note Passing \c NULL as \p buflen is a convenient way to + * indicate that fragmentation is not tolerated. + * It's functionally equivalent to passing a valid + * address as buflen and checking \c *buflen == \c desired + * afterwards. + */ +int mbedtls_mps_reader_get( mbedtls_mps_reader *reader, + mbedtls_mps_size_t desired, + unsigned char **buffer, + mbedtls_mps_size_t *buflen ); + +/** + * \brief Mark data obtained from mbedtls_mps_reader_get() as processed. + * + * This call indicates that all data received from prior calls to + * mbedtls_mps_reader_get() has been or will have been + * processed when mbedtls_mps_reader_reclaim() is called, + * and thus need not be backed up. + * + * This function has no user observable effect until + * mbedtls_mps_reader_reclaim() is called. In particular, + * buffers received from mbedtls_mps_reader_get() remain + * valid until mbedtls_mps_reader_reclaim() is called. + * + * \param reader The reader context to use. + * + * \return \c 0 on success. + * \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure. + * + */ +int mbedtls_mps_reader_commit( mbedtls_mps_reader *reader ); + +#endif /* MBEDTLS_READER_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.c b/component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.c new file mode 100644 index 00000000..e8b4e1b9 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.c @@ -0,0 +1,127 @@ +/* + * Message Processing Stack, Trace module + * + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include "mps_common.h" + +#if defined(MBEDTLS_MPS_ENABLE_TRACE) + +#include "mps_trace.h" +#include + +static int trace_depth = 0; + +#define color_default "\x1B[0m" +#define color_red "\x1B[1;31m" +#define color_green "\x1B[1;32m" +#define color_yellow "\x1B[1;33m" +#define color_blue "\x1B[1;34m" +#define color_magenta "\x1B[1;35m" +#define color_cyan "\x1B[1;36m" +#define color_white "\x1B[1;37m" + +static char const * colors[] = +{ + color_default, + color_green, + color_yellow, + color_magenta, + color_cyan, + color_blue, + color_white +}; + +#define MPS_TRACE_BUF_SIZE 100 + +void mbedtls_mps_trace_print_msg( int id, int line, const char *format, ... ) +{ + int ret; + char str[MPS_TRACE_BUF_SIZE]; + va_list argp; + va_start( argp, format ); + ret = mbedtls_vsnprintf( str, MPS_TRACE_BUF_SIZE, format, argp ); + va_end( argp ); + + if( ret >= 0 && ret < MPS_TRACE_BUF_SIZE ) + { + str[ret] = '\0'; + mbedtls_printf( "[%d|L%d]: %s\n", id, line, str ); + } +} + +int mbedtls_mps_trace_get_depth() +{ + return trace_depth; +} +void mbedtls_mps_trace_dec_depth() +{ + trace_depth--; +} +void mbedtls_mps_trace_inc_depth() +{ + trace_depth++; +} + +void mbedtls_mps_trace_color( int id ) +{ + if( id > (int) ( sizeof( colors ) / sizeof( *colors ) ) ) + return; + printf( "%s", colors[ id ] ); +} + +void mbedtls_mps_trace_indent( int level, mbedtls_mps_trace_type ty ) +{ + if( level > 0 ) + { + while( --level ) + printf( "| " ); + + printf( "| " ); + } + + switch( ty ) + { + case MBEDTLS_MPS_TRACE_TYPE_COMMENT: + mbedtls_printf( "@ " ); + break; + + case MBEDTLS_MPS_TRACE_TYPE_CALL: + mbedtls_printf( "+--> " ); + break; + + case MBEDTLS_MPS_TRACE_TYPE_ERROR: + mbedtls_printf( "E " ); + break; + + case MBEDTLS_MPS_TRACE_TYPE_RETURN: + mbedtls_printf( "< " ); + break; + + default: + break; + } +} + +#endif /* MBEDTLS_MPS_ENABLE_TRACE */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.h b/component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.h new file mode 100644 index 00000000..7c236011 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/mps_trace.h @@ -0,0 +1,175 @@ +/* + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/** + * \file mps_trace.h + * + * \brief Tracing module for MPS + */ + +#ifndef MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H +#define MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H + +#include "common.h" +#include "mps_common.h" +#include "mps_trace.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_vsnprintf vsnprintf +#endif /* MBEDTLS_PLATFORM_C */ + +#if defined(MBEDTLS_MPS_ENABLE_TRACE) + +/* + * Adapt this to enable/disable tracing output + * from the various layers of the MPS. + */ + +#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_1 +#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_2 +#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_3 +#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_4 +#define MBEDTLS_MPS_TRACE_ENABLE_READER +#define MBEDTLS_MPS_TRACE_ENABLE_WRITER + +/* + * To use the existing trace module, only change + * MBEDTLS_MPS_TRACE_ENABLE_XXX above, but don't modify the + * rest of this file. + */ + +typedef enum +{ + MBEDTLS_MPS_TRACE_TYPE_COMMENT, + MBEDTLS_MPS_TRACE_TYPE_CALL, + MBEDTLS_MPS_TRACE_TYPE_ERROR, + MBEDTLS_MPS_TRACE_TYPE_RETURN +} mbedtls_mps_trace_type; + +#define MBEDTLS_MPS_TRACE_BIT_LAYER_1 1 +#define MBEDTLS_MPS_TRACE_BIT_LAYER_2 2 +#define MBEDTLS_MPS_TRACE_BIT_LAYER_3 3 +#define MBEDTLS_MPS_TRACE_BIT_LAYER_4 4 +#define MBEDTLS_MPS_TRACE_BIT_WRITER 5 +#define MBEDTLS_MPS_TRACE_BIT_READER 6 + +#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_1) +#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_1 ) +#else +#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 0 +#endif + +#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_2) +#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_2 ) +#else +#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 0 +#endif + +#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_3) +#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_3 ) +#else +#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 0 +#endif + +#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_4) +#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_4 ) +#else +#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 0 +#endif + +#if defined(MBEDTLS_MPS_TRACE_ENABLE_READER) +#define MBEDTLS_MPS_TRACE_MASK_READER (1u << MBEDTLS_MPS_TRACE_BIT_READER ) +#else +#define MBEDTLS_MPS_TRACE_MASK_READER 0 +#endif + +#if defined(MBEDTLS_MPS_TRACE_ENABLE_WRITER) +#define MBEDTLS_MPS_TRACE_MASK_WRITER (1u << MBEDTLS_MPS_TRACE_BIT_WRITER ) +#else +#define MBEDTLS_MPS_TRACE_MASK_WRITER 0 +#endif + +#define MBEDTLS_MPS_TRACE_MASK ( MBEDTLS_MPS_TRACE_MASK_LAYER_1 | \ + MBEDTLS_MPS_TRACE_MASK_LAYER_2 | \ + MBEDTLS_MPS_TRACE_MASK_LAYER_3 | \ + MBEDTLS_MPS_TRACE_MASK_LAYER_4 | \ + MBEDTLS_MPS_TRACE_MASK_READER | \ + MBEDTLS_MPS_TRACE_MASK_WRITER ) + +/* We have to avoid globals because E-ACSL chokes on them... + * Wrap everything in stub functions. */ +int mbedtls_mps_trace_get_depth( void ); +void mbedtls_mps_trace_inc_depth( void ); +void mbedtls_mps_trace_dec_depth( void ); + +void mbedtls_mps_trace_color( int id ); +void mbedtls_mps_trace_indent( int level, mbedtls_mps_trace_type ty ); + +void mbedtls_mps_trace_print_msg( int id, int line, const char *format, ... ); + +#define MBEDTLS_MPS_TRACE( type, ... ) \ + do { \ + if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \ + break; \ + mbedtls_mps_trace_indent( mbedtls_mps_trace_get_depth(), type ); \ + mbedtls_mps_trace_color( mbedtls_mps_trace_id ); \ + mbedtls_mps_trace_print_msg( mbedtls_mps_trace_id, __LINE__, __VA_ARGS__ ); \ + mbedtls_mps_trace_color( 0 ); \ + } while( 0 ) + +#define MBEDTLS_MPS_TRACE_INIT( ... ) \ + do { \ + if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \ + break; \ + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_CALL, __VA_ARGS__ ); \ + mbedtls_mps_trace_inc_depth(); \ + } while( 0 ) + +#define MBEDTLS_MPS_TRACE_END( val ) \ + do { \ + if( ! ( MBEDTLS_MPS_TRACE_MASK & ( 1u << mbedtls_mps_trace_id ) ) ) \ + break; \ + MBEDTLS_MPS_TRACE( MBEDTLS_MPS_TRACE_TYPE_RETURN, "%d (-%#04x)", \ + (int) (val), -((unsigned)(val)) ); \ + mbedtls_mps_trace_dec_depth(); \ + } while( 0 ) + +#define MBEDTLS_MPS_TRACE_RETURN( val ) \ + do { \ + /* Breaks tail recursion. */ \ + int ret__ = val; \ + MBEDTLS_MPS_TRACE_END( ret__ ); \ + return( ret__ ); \ + } while( 0 ) + +#else /* MBEDTLS_MPS_TRACE */ + +#define MBEDTLS_MPS_TRACE( type, ... ) do { } while( 0 ) +#define MBEDTLS_MPS_TRACE_INIT( ... ) do { } while( 0 ) +#define MBEDTLS_MPS_TRACE_END do { } while( 0 ) + +#define MBEDTLS_MPS_TRACE_RETURN( val ) return( val ); + +#endif /* MBEDTLS_MPS_TRACE */ + +#endif /* MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/net_sockets.c b/component/common/network/ssl/mbedtls-3.1.0/library/net_sockets.c new file mode 100644 index 00000000..99dbffea --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/net_sockets.c @@ -0,0 +1,803 @@ +/* + * TCP/IP or UDP/IP networking functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must + * be set before mbedtls_config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#ifndef _POSIX_C_SOURCE +//#define _POSIX_C_SOURCE 200112L +#endif +#ifndef _XOPEN_SOURCE +//#define _XOPEN_SOURCE 600 /* sockaddr_storage */ +#endif + +#include "common.h" + +#if defined(MBEDTLS_NET_C) +/* +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h" +#endif +*/ +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR ) + +#if !defined(_WIN32_WINNT) +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#endif + +#include + +#include +#include +#if (_WIN32_WINNT < 0x0501) +#include +#endif + +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ + +#define read(fd,buf,len) recv( fd, (char*)( buf ), (int)( len ), 0 ) +#define write(fd,buf,len) send( fd, (char*)( buf ), (int)( len ), 0 ) +#define close(fd) closesocket(fd) + +static int wsa_init_done = 0; + +#elif defined(__ICCARM__) || defined(__CC_ARM) || defined ( __GNUC__ ) + +#include "lwip/sockets.h" +#include "lwip/inet.h" +#if LWIP_DNS +#include "lwip/netdb.h" +#endif +#include + +#define net_htons(n) htons(n) +#define net_htonl(n) htonl(n) + +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IS_EINTR( ret ) ( ( ret ) == EINTR ) + +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard functions use socklen_t, so cast only for MSVC */ +#if defined(_MSC_VER) +#define MSVC_INT_CAST (int) +#else +#define MSVC_INT_CAST +#endif + +#include + +#include + +#include + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + WSADATA wsaData; + + if( wsa_init_done == 0 ) + { + if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + wsa_init_done = 1; + } +#else +#if !defined(EFIX64) && !defined(EFI32) && !defined(__ICCARM__) && !defined(__CC_ARM) && !defined ( __GNUC__ ) + signal( SIGPIPE, SIG_IGN ); +#endif +#endif + return( 0 ); +} + +/* + * Return 0 if the file descriptor is valid, an error otherwise. + * If for_select != 0, check whether the file descriptor is within the range + * allowed for fd_set used for the FD_xxx macros and the select() function. + */ +static int check_fd( int fd, int for_select ) +{ + if( fd < 0 ) + return( MBEDTLS_ERR_NET_INVALID_CONTEXT ); + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + (void) for_select; +#else + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( for_select && fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); +#endif + + return( 0 ); +} + +/* + * Initialize a context + */ +void mbedtls_net_init( mbedtls_net_context *ctx ) +{ + ctx->fd = -1; +} + +/* + * Initiate a TCP connection with host:port and the given protocol + */ +int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, + const char *port, int proto ) +{ +#if defined(MBEDTLS_HAVE_IPV6) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Do name resolution with both IPv6 and IPv4 */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + + if( getaddrinfo( host, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a connection succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_CONNECT_FAILED; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +#else + /* Legacy IPv4-only version */ + + int ret; + int type, protocol; + struct sockaddr_in server_addr; +#if LWIP_DNS + struct hostent *server_host; +#endif + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + type = ( proto == MBEDTLS_NET_PROTO_UDP ) ? SOCK_DGRAM : SOCK_STREAM; + protocol = ( proto == MBEDTLS_NET_PROTO_UDP ) ? IPPROTO_UDP : IPPROTO_TCP; + +#if LWIP_DNS + if( ( server_host = gethostbyname( host ) ) == NULL ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + if( ( ctx->fd = (int) socket( AF_INET, type, protocol ) ) < 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + memcpy( (void *) &server_addr.sin_addr, + (void *) server_host->h_addr, + 4 ); +#else + if( ( ctx->fd = (int) socket( AF_INET, type, protocol ) ) < 0 ) + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + + server_addr.sin_len = sizeof(server_addr); + server_addr.sin_addr.s_addr = inet_addr(host); +#endif + + server_addr.sin_family = AF_INET; + server_addr.sin_port = net_htons( atoi(port) ); + + if( connect( ctx->fd, (struct sockaddr *) &server_addr, + sizeof( server_addr ) ) < 0 ) + { + close( ctx->fd ); + return( MBEDTLS_ERR_NET_CONNECT_FAILED ); + } + + return( 0 ); +#endif /* MBEDTLS_HAVE_IPV6 */ +} + +/* + * Create a listening socket on bind_ip:port + */ +int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto ) +{ + int n, ret; + struct addrinfo hints, *addr_list, *cur; + + if( ( ret = net_prepare() ) != 0 ) + return( ret ); + + /* Bind to IPv6 and/or IPv4, but only in the desired protocol */ + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP; + if( bind_ip == NULL ) + hints.ai_flags = AI_PASSIVE; + + if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 ) + return( MBEDTLS_ERR_NET_UNKNOWN_HOST ); + + /* Try the sockaddrs until a binding succeeds */ + ret = MBEDTLS_ERR_NET_UNKNOWN_HOST; + for( cur = addr_list; cur != NULL; cur = cur->ai_next ) + { + ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype, + cur->ai_protocol ); + if( ctx->fd < 0 ) + { + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + n = 1; + if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &n, sizeof( n ) ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_BIND_FAILED; + continue; + } + + /* Listen only makes sense for TCP */ + if( proto == MBEDTLS_NET_PROTO_TCP ) + { + if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 ) + { + close( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* Bind was successful */ + ret = 0; + break; + } + + freeaddrinfo( addr_list ); + + return( ret ); + +} + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + ((void) ctx); + return( WSAGetLastError() == WSAEWOULDBLOCK ); +} +#else +/* + * Check if the requested operation would be blocking on a non-blocking socket + * and thus 'failed' with a negative return value. + * + * Note: on a blocking socket this function always returns 0! + */ +static int net_would_block( const mbedtls_net_context *ctx ) +{ + int err = errno; + + /* + * Never return 'WOULD BLOCK' on a blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL, 0 ) & O_NONBLOCK ) != O_NONBLOCK ) + { + errno = err; + return( 0 ); + } + + switch( errno = err ) + { +#if defined EAGAIN + case EAGAIN: +#endif +#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN + case EWOULDBLOCK: +#endif + return( 1 ); + } + return( 0 ); +} +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +/* + * Accept a connection from a remote client + */ +int mbedtls_net_accept( mbedtls_net_context *bind_ctx, + mbedtls_net_context *client_ctx, + void *client_ip, size_t buf_size, size_t *ip_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int type; + +#if defined(MBEDTLS_HAVE_IPV6) + struct sockaddr_storage client_addr; +#else + struct sockaddr_in client_addr; +#endif + +#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \ + defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \ + defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) + socklen_t n = (socklen_t) sizeof( client_addr ); + socklen_t type_len = (socklen_t) sizeof( type ); +#else + int n = (int) sizeof( client_addr ); + int type_len = (int) sizeof( type ); +#endif + + /* Is this a TCP or UDP socket? */ + if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE, + (void *) &type, &type_len ) != 0 || + ( type != SOCK_STREAM && type != SOCK_DGRAM ) ) + { + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + if( type == SOCK_STREAM ) + { + /* TCP: actual accept() */ + ret = client_ctx->fd = (int) accept( bind_ctx->fd, + (struct sockaddr *) &client_addr, &n ); + } + else + { + /* UDP: wait for a message, but keep it in the queue */ + char buf[1] = { 0 }; + + ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK, + (struct sockaddr *) &client_addr, &n ); + +#if defined(_WIN32) + if( ret == SOCKET_ERROR && + WSAGetLastError() == WSAEMSGSIZE ) + { + /* We know buf is too small, thanks, just peeking here */ + ret = 0; + } +#endif + } + + if( ret < 0 ) + { + if( net_would_block( bind_ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + } + + /* UDP: hijack the listening socket to communicate with the client, + * then bind a new socket to accept new connections */ + if( type != SOCK_STREAM ) + { +#if defined(MBEDTLS_HAVE_IPV6) + struct sockaddr_storage local_addr; +#else + struct sockaddr_in local_addr; +#endif + + int one = 1; + + if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 ) + return( MBEDTLS_ERR_NET_ACCEPT_FAILED ); + + client_ctx->fd = bind_ctx->fd; + bind_ctx->fd = -1; /* In case we exit early */ + +#if defined(MBEDTLS_HAVE_IPV6) + n = sizeof( struct sockaddr_storage ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.ss_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } +#else + n = sizeof( struct sockaddr_in ); + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, (u32_t*)&n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.sin_family, + SOCK_DGRAM, IPPROTO_UDP ) ) < 0 || + setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR, + (const char *) &one, sizeof( one ) ) != 0 ) + { + return( MBEDTLS_ERR_NET_SOCKET_FAILED ); + } +#endif + + if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 ) + { + return( MBEDTLS_ERR_NET_BIND_FAILED ); + } + } + + if( client_ip != NULL ) + { +#if defined(MBEDTLS_HAVE_IPV6) + if( client_addr.ss_family == AF_INET ) + { + struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr; + *ip_len = sizeof( addr4->sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len ); + } + else + { + struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr; + *ip_len = sizeof( addr6->sin6_addr.s6_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len); + } +#else + *ip_len = sizeof( client_addr.sin_addr.s_addr ); + + if( buf_size < *ip_len ) + return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL ); + + memcpy( client_ip, &client_addr.sin_addr.s_addr, *ip_len ); +#endif /* MBEDTLS_HAVE_IPV6 */ + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int mbedtls_net_set_block( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) || defined(__ICCARM__) || defined(__CC_ARM) || defined ( __GNUC__ ) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 0; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) ); +#endif +} + +int mbedtls_net_set_nonblock( mbedtls_net_context *ctx ) +{ +#if ( defined(_WIN32) || defined(_WIN32_WCE) || defined(__ICCARM__) || defined(__CC_ARM) || defined ( __GNUC__ ) ) && !defined(EFIX64) && \ + !defined(EFI32) + u_long n = 1; + return( ioctlsocket( ctx->fd, FIONBIO, &n ) ); +#else + return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) ); +#endif +} + +/* + * Check if data is available on the socket + */ + +int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct timeval tv; + + fd_set read_fds; + fd_set write_fds; + + int fd = ctx->fd; + + ret = check_fd( fd, 1 ); + if( ret != 0 ) + return( ret ); + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + /* Ensure that memory sanitizers consider read_fds and write_fds as + * initialized even on platforms such as Glibc/x86_64 where FD_ZERO + * is implemented in assembly. */ + memset( &read_fds, 0, sizeof( read_fds ) ); + memset( &write_fds, 0, sizeof( write_fds ) ); +#endif +#endif + + FD_ZERO( &read_fds ); + if( rw & MBEDTLS_NET_POLL_READ ) + { + rw &= ~MBEDTLS_NET_POLL_READ; + FD_SET( fd, &read_fds ); + } + + FD_ZERO( &write_fds ); + if( rw & MBEDTLS_NET_POLL_WRITE ) + { + rw &= ~MBEDTLS_NET_POLL_WRITE; + FD_SET( fd, &write_fds ); + } + + if( rw != 0 ) + return( MBEDTLS_ERR_NET_BAD_INPUT_DATA ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + do + { + ret = select( fd + 1, &read_fds, &write_fds, NULL, + timeout == (uint32_t) -1 ? NULL : &tv ); + } + while( IS_EINTR( ret ) ); + + if( ret < 0 ) + return( MBEDTLS_ERR_NET_POLL_FAILED ); + + ret = 0; + if( FD_ISSET( fd, &read_fds ) ) + ret |= MBEDTLS_NET_POLL_READ; + if( FD_ISSET( fd, &write_fds ) ) + ret |= MBEDTLS_NET_POLL_WRITE; + + return( ret ); +} + +/* + * Portable usleep helper + */ +void mbedtls_net_usleep( unsigned long usec ) +{ +#if defined(_WIN32) + Sleep( ( usec + 999 ) / 1000 ); +#else + struct timeval tv; + tv.tv_sec = usec / 1000000; +#if defined(__unix__) || defined(__unix) || \ + ( defined(__APPLE__) && defined(__MACH__) ) + tv.tv_usec = (suseconds_t) usec % 1000000; +#else + tv.tv_usec = usec % 1000000; +#endif + select( 0, NULL, NULL, NULL, &tv ); +#endif +} + +/* + * Read at most 'len' characters + */ +int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int fd = ((mbedtls_net_context *) ctx)->fd; + + ret = check_fd( fd, 0 ); + if( ret != 0 ) + return( ret ); + + ret = (int) read( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_READ ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + return( ret ); +} + +/* + * Read at most 'len' characters, blocking for at most 'timeout' ms + */ +int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, + size_t len, uint32_t timeout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + struct timeval tv; + fd_set read_fds; + int fd = ((mbedtls_net_context *) ctx)->fd; + + ret = check_fd( fd, 1 ); + if( ret != 0 ) + return( ret ); + + FD_ZERO( &read_fds ); + FD_SET( fd, &read_fds ); + + tv.tv_sec = timeout / 1000; + tv.tv_usec = ( timeout % 1000 ) * 1000; + + ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv ); + + /* Zero fds ready means we timed out */ + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_TIMEOUT ); + + if( ret < 0 ) + { +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAEINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#else + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_READ ); +#endif + + return( MBEDTLS_ERR_NET_RECV_FAILED ); + } + + /* This call will not block */ + return( mbedtls_net_recv( ctx, buf, len ) ); +} + +/* + * Write at most 'len' characters + */ +int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int fd = ((mbedtls_net_context *) ctx)->fd; + + ret = check_fd( fd, 0 ); + if( ret != 0 ) + return( ret ); + + ret = (int) write( fd, buf, len ); + + if( ret < 0 ) + { + if( net_would_block( ctx ) != 0 ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); + +#if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \ + !defined(EFI32) + if( WSAGetLastError() == WSAECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); +#else + if( errno == EPIPE || errno == ECONNRESET ) + return( MBEDTLS_ERR_NET_CONN_RESET ); + + if( errno == EINTR ) + return( MBEDTLS_ERR_SSL_WANT_WRITE ); +#endif + + return( MBEDTLS_ERR_NET_SEND_FAILED ); + } + + return( ret ); +} + +/* + * Close the connection + */ +void mbedtls_net_close( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + close( ctx->fd ); + + ctx->fd = -1; +} + +/* + * Gracefully close the connection + */ +void mbedtls_net_free( mbedtls_net_context *ctx ) +{ + if( ctx->fd == -1 ) + return; + + shutdown( ctx->fd, 2 ); + close( ctx->fd ); + + ctx->fd = -1; +} + +#endif /* MBEDTLS_NET_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/nist_kw.c b/component/common/network/ssl/mbedtls-3.1.0/library/nist_kw.c new file mode 100644 index 00000000..1aea0b63 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/nist_kw.c @@ -0,0 +1,713 @@ +/* + * Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes + * only + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * Definition of Key Wrapping: + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf + * RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm" + * RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm" + * + * Note: RFC 3394 defines different methodology for intermediate operations for + * the wrapping and unwrapping operation than the definition in NIST SP 800-38F. + */ + +#include "common.h" + +#if defined(MBEDTLS_NIST_KW_C) + +#include "mbedtls/nist_kw.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/constant_time.h" + +#include +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#if !defined(MBEDTLS_NIST_KW_ALT) + +#define KW_SEMIBLOCK_LENGTH 8 +#define MIN_SEMIBLOCKS_COUNT 3 + +/*! The 64-bit default integrity check value (ICV) for KW mode. */ +static const unsigned char NIST_KW_ICV1[] = {0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6}; +/*! The 32-bit default integrity check value (ICV) for KWP mode. */ +static const unsigned char NIST_KW_ICV2[] = {0xA6, 0x59, 0x59, 0xA6}; + +/* + * Initialize context + */ +void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_nist_kw_context ) ); +} + +int mbedtls_nist_kw_setkey( mbedtls_nist_kw_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits, + const int is_wrap ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + cipher_info = mbedtls_cipher_info_from_values( cipher, + keybits, + MBEDTLS_MODE_ECB ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( cipher_info->block_size != 16 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* + * SP 800-38F currently defines AES cipher as the only block cipher allowed: + * "For KW and KWP, the underlying block cipher shall be approved, and the + * block size shall be 128 bits. Currently, the AES block cipher, with key + * lengths of 128, 192, or 256 bits, is the only block cipher that fits + * this profile." + * Currently we don't support other 128 bit block ciphers for key wrapping, + * such as Camellia and Aria. + */ + if( cipher != MBEDTLS_CIPHER_ID_AES ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + mbedtls_cipher_free( &ctx->cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx->cipher_ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_setkey( &ctx->cipher_ctx, key, keybits, + is_wrap ? MBEDTLS_ENCRYPT : + MBEDTLS_DECRYPT ) + ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Free context + */ +void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx ) +{ + mbedtls_cipher_free( &ctx->cipher_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_nist_kw_context ) ); +} + +/* + * Helper function for Xoring the uint64_t "t" with the encrypted A. + * Defined in NIST SP 800-38F section 6.1 + */ +static void calc_a_xor_t( unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t ) +{ + size_t i = 0; + for( i = 0; i < sizeof( t ); i++ ) + { + A[i] ^= ( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) ) & 0xff; + } +} + +/* + * KW-AE as defined in SP 800-38F section 6.2 + * KWP-AE as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t semiblocks = 0; + size_t s; + size_t olen, padlen = 0; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + + *out_len = 0; + /* + * Generate the String to work on + */ + if( mode == MBEDTLS_KW_MODE_KW ) + { + if( out_size < in_len + KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KW + * must be between 2 to 2^54-1 semiblocks inclusive. + */ + if( in_len < 16 || +#if SIZE_MAX > 0x1FFFFFFFFFFFFF8 + in_len > 0x1FFFFFFFFFFFFF8 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH ); + memmove( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + } + else + { + if( in_len % 8 != 0 ) + { + padlen = ( 8 - ( in_len % 8 ) ); + } + + if( out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* + * According to SP 800-38F Table 1, the plaintext length for KWP + * must be between 1 and 2^32-1 octets inclusive. + */ + if( in_len < 1 +#if SIZE_MAX > 0xFFFFFFFF + || in_len > 0xFFFFFFFF +#endif + ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2 ); + MBEDTLS_PUT_UINT32_BE( ( in_len & 0xffffffff ), output, + KW_SEMIBLOCK_LENGTH / 2 ); + + memcpy( output + KW_SEMIBLOCK_LENGTH, input, in_len ); + memset( output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen ); + } + semiblocks = ( ( in_len + padlen ) / KW_SEMIBLOCK_LENGTH ) + 1; + + s = 6 * ( semiblocks - 1 ); + + if( mode == MBEDTLS_KW_MODE_KWP + && in_len <= KW_SEMIBLOCK_LENGTH ) + { + memcpy( inbuff, output, 16 ); + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, output, &olen ); + if( ret != 0 ) + goto cleanup; + } + else + { + unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH; + unsigned char *A = output; + + /* + * Do the wrapping function W, as defined in RFC 3394 section 2.2.1 + */ + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + goto cleanup; + } + + /* Calculate intermediate values */ + for( t = 1; t <= s; t++ ) + { + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + calc_a_xor_t( A, t ); + + memcpy( R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + R2 += KW_SEMIBLOCK_LENGTH; + if( R2 >= output + ( semiblocks * KW_SEMIBLOCK_LENGTH ) ) + R2 = output + KW_SEMIBLOCK_LENGTH; + } + } + + *out_len = semiblocks * KW_SEMIBLOCK_LENGTH; + +cleanup: + + if( ret != 0) + { + memset( output, 0, semiblocks * KW_SEMIBLOCK_LENGTH ); + } + mbedtls_platform_zeroize( inbuff, KW_SEMIBLOCK_LENGTH * 2 ); + mbedtls_platform_zeroize( outbuff, KW_SEMIBLOCK_LENGTH * 2 ); + + return( ret ); +} + +/* + * W-1 function as defined in RFC 3394 section 2.2.2 + * This function assumes the following: + * 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH. + * 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH. + * 3. Minimal number of semiblocks is 3. + * 4. A is a buffer to hold the first semiblock of the input buffer. + */ +static int unwrap( mbedtls_nist_kw_context *ctx, + const unsigned char *input, size_t semiblocks, + unsigned char A[KW_SEMIBLOCK_LENGTH], + unsigned char *output, size_t* out_len ) +{ + int ret = 0; + const size_t s = 6 * ( semiblocks - 1 ); + size_t olen; + uint64_t t = 0; + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2]; + unsigned char *R = NULL; + *out_len = 0; + + if( semiblocks < MIN_SEMIBLOCKS_COUNT ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + memcpy( A, input, KW_SEMIBLOCK_LENGTH ); + memmove( output, input + KW_SEMIBLOCK_LENGTH, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + + /* Calculate intermediate values */ + for( t = s; t >= 1; t-- ) + { + calc_a_xor_t( A, t ); + + memcpy( inbuff, A, KW_SEMIBLOCK_LENGTH ); + memcpy( inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH ); + + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + inbuff, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + + /* Set R as LSB64 of outbuff */ + memcpy( R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + + if( R == output ) + R = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH; + else + R -= KW_SEMIBLOCK_LENGTH; + } + + *out_len = ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH; + +cleanup: + if( ret != 0) + memset( output, 0, ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( inbuff, sizeof( inbuff ) ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + + return( ret ); +} + +/* + * KW-AD as defined in SP 800-38F section 6.2 + * KWP-AD as defined in SP 800-38F section 6.3 + */ +int mbedtls_nist_kw_unwrap( mbedtls_nist_kw_context *ctx, + mbedtls_nist_kw_mode_t mode, + const unsigned char *input, size_t in_len, + unsigned char *output, size_t *out_len, size_t out_size ) +{ + int ret = 0; + size_t i, olen; + unsigned char A[KW_SEMIBLOCK_LENGTH]; + unsigned char diff, bad_padding = 0; + + *out_len = 0; + if( out_size < in_len - KW_SEMIBLOCK_LENGTH ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( mode == MBEDTLS_KW_MODE_KW ) + { + /* + * According to SP 800-38F Table 1, the ciphertext length for KW + * must be between 3 to 2^54 semiblocks inclusive. + */ + if( in_len < 24 || +#if SIZE_MAX > 0x200000000000000 + in_len > 0x200000000000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + + /* Check ICV in "constant-time" */ + diff = mbedtls_ct_memcmp( NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + goto cleanup; + } + + } + else if( mode == MBEDTLS_KW_MODE_KWP ) + { + size_t padlen = 0; + uint32_t Plen; + /* + * According to SP 800-38F Table 1, the ciphertext length for KWP + * must be between 2 to 2^29 semiblocks inclusive. + */ + if( in_len < KW_SEMIBLOCK_LENGTH * 2 || +#if SIZE_MAX > 0x100000000 + in_len > 0x100000000 || +#endif + in_len % KW_SEMIBLOCK_LENGTH != 0 ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + if( in_len == KW_SEMIBLOCK_LENGTH * 2 ) + { + unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2]; + ret = mbedtls_cipher_update( &ctx->cipher_ctx, + input, 16, outbuff, &olen ); + if( ret != 0 ) + goto cleanup; + + memcpy( A, outbuff, KW_SEMIBLOCK_LENGTH ); + memcpy( output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH ); + mbedtls_platform_zeroize( outbuff, sizeof( outbuff ) ); + *out_len = KW_SEMIBLOCK_LENGTH; + } + else + { + /* in_len >= KW_SEMIBLOCK_LENGTH * 3 */ + ret = unwrap( ctx, input, in_len / KW_SEMIBLOCK_LENGTH, + A, output, out_len ); + if( ret != 0 ) + goto cleanup; + } + + /* Check ICV in "constant-time" */ + diff = mbedtls_ct_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 ); + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + Plen = MBEDTLS_GET_UINT32_BE( A, KW_SEMIBLOCK_LENGTH / 2 ); + + /* + * Plen is the length of the plaintext, when the input is valid. + * If Plen is larger than the plaintext and padding, padlen will be + * larger than 8, because of the type wrap around. + */ + padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; + if ( padlen > 7 ) + { + padlen &= 7; + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + /* Check padding in "constant-time" */ + for( diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++ ) + { + if( i >= KW_SEMIBLOCK_LENGTH - padlen ) + diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + else + bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i]; + } + + if( diff != 0 ) + { + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + } + + if( ret != 0 ) + { + goto cleanup; + } + memset( output + Plen, 0, padlen ); + *out_len = Plen; + } + else + { + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + +cleanup: + if( ret != 0 ) + { + memset( output, 0, *out_len ); + *out_len = 0; + } + + mbedtls_platform_zeroize( &bad_padding, sizeof( bad_padding) ); + mbedtls_platform_zeroize( &diff, sizeof( diff ) ); + mbedtls_platform_zeroize( A, sizeof( A ) ); + + return( ret ); +} + +#endif /* !MBEDTLS_NIST_KW_ALT */ + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) + +#define KW_TESTS 3 + +/* + * Test vectors taken from NIST + * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW + */ +static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 }; + +static const unsigned char kw_key[KW_TESTS][32] = { + { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2, + 0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 }, + { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b, + 0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d, + 0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 }, + { 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25, + 0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33, + 0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d, + 0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 } +}; + +static const unsigned char kw_msg[KW_TESTS][40] = { + { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea, + 0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f }, + { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb, + 0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d, + 0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45, + 0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d, + 0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c }, + { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7, + 0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8, + 0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 } +}; + +static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 }; +static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 }; +static const unsigned char kw_res[KW_TESTS][48] = { + { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d, + 0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3, + 0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb }, + { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91, + 0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec, + 0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d, + 0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8, + 0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19, + 0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d }, + { 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d, + 0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87, + 0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9, + 0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 } +}; + +static const unsigned char kwp_key[KW_TESTS][32] = { + { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a, + 0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 }, + { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98, + 0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7, + 0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 }, + { 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5, + 0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f, + 0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae, + 0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a } +}; + +static const unsigned char kwp_msg[KW_TESTS][31] = { + { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8, + 0x96 }, + { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb, + 0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19, + 0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66, + 0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f }, + { 0xd1 } +}; +static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 }; + +static const unsigned char kwp_res[KW_TESTS][48] = { + { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e, + 0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7, + 0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 }, + { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13, + 0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88, + 0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63, + 0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90, + 0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 }, + { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd, + 0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 } +}; +static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 }; + +int mbedtls_nist_kw_self_test( int verbose ) +{ + mbedtls_nist_kw_context ctx; + unsigned char out[48]; + size_t olen; + int i; + int ret = 0; + mbedtls_nist_kw_init( &ctx ); + + for( i = 0; i < KW_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " KW-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed " ); + + goto end; + } + + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KW, kw_msg[i], + kw_msg_len[i], out, &olen, sizeof( out ) ); + if( ret != 0 || kw_out_len[i] != olen || + memcmp( out, kw_res[i], kw_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kw_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KW: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KW, + out, olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kw_msg_len[i] || + memcmp( out, kw_msg[i], kw_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } + + for( i = 0; i < KW_TESTS; i++ ) + { + olen = sizeof( out ); + if( verbose != 0 ) + mbedtls_printf( " KWP-AES-%u ", (unsigned int) key_len[i] * 8 ); + + ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i], + key_len[i] * 8, 1 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed " ); + + goto end; + } + ret = mbedtls_nist_kw_wrap( &ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i], + kwp_msg_len[i], out, &olen, sizeof( out ) ); + + if( ret != 0 || kwp_out_len[i] != olen || + memcmp( out, kwp_res[i], kwp_out_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( ( ret = mbedtls_nist_kw_setkey( &ctx, MBEDTLS_CIPHER_ID_AES, + kwp_key[i], key_len[i] * 8, 0 ) ) + != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( " KWP: setup failed "); + + goto end; + } + + ret = mbedtls_nist_kw_unwrap( &ctx, MBEDTLS_KW_MODE_KWP, out, + olen, out, &olen, sizeof( out ) ); + + if( ret != 0 || olen != kwp_msg_len[i] || + memcmp( out, kwp_msg[i], kwp_msg_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed. "); + + ret = 1; + goto end; + } + + if( verbose != 0 ) + mbedtls_printf( " passed\n" ); + } +end: + mbedtls_nist_kw_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */ + +#endif /* MBEDTLS_NIST_KW_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/oid.c b/component/common/network/ssl/mbedtls-3.1.0/library/oid.c new file mode 100644 index 00000000..f70ceea5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/oid.c @@ -0,0 +1,782 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" +#include "mbedtls/error.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate mbedtls_oid_descriptor_t + */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } +#define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } +#else +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } +#define NULL_OID_DESCRIPTOR { NULL, 0 } +#endif + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name" ), + "CN", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country" ), + "C", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality" ), + "L", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_STATE, "id-at-state", "State" ), + "ST", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_ORGANIZATION,"id-at-organizationName", "Organization" ), + "O", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit" ), + "OU", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS9_EMAIL, "emailAddress", "E-mail address" ), + "emailAddress", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_SERIAL_NUMBER,"id-at-serialNumber", "Serial number" ), + "serialNumber", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_POSTAL_ADDRESS,"id-at-postalAddress", "Postal address" ), + "postalAddress", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code" ), + "postalCode", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname" ), + "SN", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name" ), + "GN", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials" ), + "initials", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_GENERATION_QUALIFIER, "id-at-generationQualifier", "Generation qualifier" ), + "generationQualifier", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_TITLE, "id-at-title", "Title" ), + "title", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_DN_QUALIFIER,"id-at-dnQualifier", "Distinguished Name qualifier" ), + "dnQualifier", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym" ), + "pseudonym", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_UID, "id-uid", "User Id" ), + "uid", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_DOMAIN_COMPONENT, "id-domainComponent", "Domain component" ), + "DC", + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, "id-at-uniqueIdentifier", "Unique Identifier" ), + "uniqueIdentifier", + }, + { + NULL_OID_DESCRIPTOR, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + OID_DESCRIPTOR( MBEDTLS_OID_BASIC_CONSTRAINTS, "id-ce-basicConstraints", "Basic Constraints" ), + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage" ), + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_EXTENDED_KEY_USAGE, "id-ce-extKeyUsage", "Extended Key Usage" ), + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_SUBJECT_ALT_NAME, "id-ce-subjectAltName", "Subject Alt Name" ), + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_NS_CERT_TYPE, "id-netscape-certtype", "Netscape Certificate Type" ), + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_CERTIFICATE_POLICIES, "id-ce-certificatePolicies", "Certificate Policies" ), + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, + { + NULL_OID_DESCRIPTOR, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + OID_DESCRIPTOR( MBEDTLS_OID_SERVER_AUTH, "id-kp-serverAuth", "TLS Web Server Authentication" ), + OID_DESCRIPTOR( MBEDTLS_OID_CLIENT_AUTH, "id-kp-clientAuth", "TLS Web Client Authentication" ), + OID_DESCRIPTOR( MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing" ), + OID_DESCRIPTOR( MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection" ), + OID_DESCRIPTOR( MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping" ), + OID_DESCRIPTOR( MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing" ), + OID_DESCRIPTOR( MBEDTLS_OID_WISUN_FAN, "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" ), + NULL_OID_DESCRIPTOR, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) + +static const mbedtls_oid_descriptor_t oid_certificate_policies[] = +{ + OID_DESCRIPTOR( MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy" ), + NULL_OID_DESCRIPTOR, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) +FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD5_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5" ), + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1" ), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", "RSA with SHA-224" ), + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, +#endif +#if defined(MBEDTLS_SHA256_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", "RSA with SHA-256" ), + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", "RSA with SHA-384" ), + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", "RSA with SHA-512" ), + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1" ), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1" ), + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224" ), + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, +#endif +#if defined(MBEDTLS_SHA256_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256" ), + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384" ), + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512" ), + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS" ), + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +#endif + +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA" ), + MBEDTLS_PK_RSA, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key" ), + MBEDTLS_PK_ECKEY, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH" ), + MBEDTLS_PK_ECKEY_DH, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1" ), + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1" ), + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1" ), + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1" ), + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1" ), + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1" ), + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1" ), + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1" ), + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1","brainpool256r1" ), + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1","brainpool384r1" ), + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1","brainpool512r1" ), + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + OID_DESCRIPTOR( MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC" ), + MBEDTLS_CIPHER_DES_CBC, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC" ), + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD5_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5" ), + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1" ), + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224" ), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_SHA256_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256" ), + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384" ), + MBEDTLS_MD_SHA384, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512" ), + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_RIPEMD160_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160" ), + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_RIPEMD160_C */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1" ), + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224" ), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_SHA256_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256" ), + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384" ), + MBEDTLS_MD_SHA384, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512" ), + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" ), + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" ), + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%u", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/padlock.c b/component/common/network/ssl/mbedtls-3.1.0/library/padlock.c new file mode 100644 index 00000000..b8ba1058 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/padlock.c @@ -0,0 +1,164 @@ +/* + * VIA PadLock support functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * This implementation is based on the VIA PadLock Programming Guide: + * + * http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/ + * programming_guide.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_PADLOCK_C) + +#include "padlock.h" + +#include + +#ifndef asm +#define asm __asm +#endif + +#if defined(MBEDTLS_HAVE_X86) + +/* + * PadLock detection routine + */ +int mbedtls_padlock_has_support( int feature ) +{ + static int flags = -1; + int ebx = 0, edx = 0; + + if( flags == -1 ) + { + asm( "movl %%ebx, %0 \n\t" + "movl $0xC0000000, %%eax \n\t" + "cpuid \n\t" + "cmpl $0xC0000001, %%eax \n\t" + "movl $0, %%edx \n\t" + "jb 1f \n\t" + "movl $0xC0000001, %%eax \n\t" + "cpuid \n\t" + "1: \n\t" + "movl %%edx, %1 \n\t" + "movl %2, %%ebx \n\t" + : "=m" (ebx), "=m" (edx) + : "m" (ebx) + : "eax", "ecx", "edx" ); + + flags = edx; + } + + return( flags & feature ); +} + +/* + * PadLock AES-ECB block en(de)cryption + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int ebx = 0; + uint32_t *rk; + uint32_t *blk; + uint32_t *ctrl; + unsigned char buf[256]; + + rk = ctx->rk; + blk = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( blk, input, 16 ); + + ctrl = blk + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode^1 ) - 10 ) << 9 ); + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl $1, %%ecx \n\t" + "movl %2, %%edx \n\t" + "movl %3, %%ebx \n\t" + "movl %4, %%esi \n\t" + "movl %4, %%edi \n\t" + ".byte 0xf3,0x0f,0xa7,0xc8 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk) + : "memory", "ecx", "edx", "esi", "edi" ); + + memcpy( output, blk, 16 ); + + return( 0 ); +} + +/* + * PadLock AES-CBC buffer en(de)cryption + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ebx = 0; + size_t count; + uint32_t *rk; + uint32_t *iw; + uint32_t *ctrl; + unsigned char buf[256]; + + if( ( (long) input & 15 ) != 0 || + ( (long) output & 15 ) != 0 ) + return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED ); + + rk = ctx->rk; + iw = MBEDTLS_PADLOCK_ALIGN16( buf ); + memcpy( iw, iv, 16 ); + + ctrl = iw + 4; + *ctrl = 0x80 | ctx->nr | ( ( ctx->nr + ( mode ^ 1 ) - 10 ) << 9 ); + + count = ( length + 15 ) >> 4; + + asm( "pushfl \n\t" + "popfl \n\t" + "movl %%ebx, %0 \n\t" + "movl %2, %%ecx \n\t" + "movl %3, %%edx \n\t" + "movl %4, %%ebx \n\t" + "movl %5, %%esi \n\t" + "movl %6, %%edi \n\t" + "movl %7, %%eax \n\t" + ".byte 0xf3,0x0f,0xa7,0xd0 \n\t" + "movl %1, %%ebx \n\t" + : "=m" (ebx) + : "m" (ebx), "m" (count), "m" (ctrl), + "m" (rk), "m" (input), "m" (output), "m" (iw) + : "memory", "eax", "ecx", "edx", "esi", "edi" ); + + memcpy( iv, iw, 16 ); + + return( 0 ); +} + +#endif /* MBEDTLS_HAVE_X86 */ + +#endif /* MBEDTLS_PADLOCK_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/padlock.h b/component/common/network/ssl/mbedtls-3.1.0/library/padlock.h new file mode 100644 index 00000000..1506ee0c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/padlock.h @@ -0,0 +1,120 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + * + * \warning These functions are only for internal use by other library + * functions; you must not call them directly. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/aes.h" + +#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */ + +#if defined(__has_feature) +#if __has_feature(address_sanitizer) +#define MBEDTLS_HAVE_ASAN +#endif +#endif + +/* Some versions of ASan result in errors about not enough registers */ +#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \ + !defined(MBEDTLS_HAVE_ASAN) + +#ifndef MBEDTLS_HAVE_X86 +#define MBEDTLS_HAVE_X86 +#endif + +#include + +#define MBEDTLS_PADLOCK_RNG 0x000C +#define MBEDTLS_PADLOCK_ACE 0x00C0 +#define MBEDTLS_PADLOCK_PHE 0x0C00 +#define MBEDTLS_PADLOCK_PMM 0x3000 + +#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15)) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Internal PadLock detection routine + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param feature The feature to detect + * + * \return non-zero if CPU has support for the feature, 0 otherwise + */ +int mbedtls_padlock_has_support( int feature ); + +/** + * \brief Internal PadLock AES-ECB block en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal PadLock AES-CBC buffer en(de)cryption + * + * \note This function is only for internal use by other library + * functions; you must not call it directly. + * + * \param ctx AES context + * \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if success, 1 if operation failed + */ +int mbedtls_padlock_xcryptcbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pem.c b/component/common/network/ssl/mbedtls-3.1.0/library/pem.c new file mode 100644 index 00000000..1b40e5e5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pem.c @@ -0,0 +1,489 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_platform_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_platform_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_platform_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_platform_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as a heuristic to try to detect password mismatches. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if ( ctx->buf != NULL ) + { + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + } + mbedtls_free( ctx->info ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + /* Clean any remaining data previously written to the buffer */ + memset( buf + *olen, 0, buf_len - *olen ); + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pk.c b/component/common/network/ssl/mbedtls-3.1.0/library/pk.c new file mode 100644 index 00000000..ea4869c1 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pk.c @@ -0,0 +1,649 @@ +/* + * Public Key abstraction layer + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "pk_wrap.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#endif + +#include +#include + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { + return; + } + + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Initialise a PSA-wrapping context + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, + const psa_key_id_t key ) +{ + const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t *pk_ctx; + psa_key_type_t type; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + type = psa_get_key_type( &attributes ); + psa_reset_key_attributes( &attributes ); + + /* Current implementation of can_do() relies on this. */ + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ; + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + pk_ctx = (psa_key_id_t *) ctx->pk_ctx; + *pk_ctx = key; + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, NULL ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); + + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); + + if( pub->pk_info == NULL || + prv->pk_info == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( f_rng == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( prv->pk_info->check_pair_func == NULL ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx, f_rng, p_rng ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Load the key to a PSA key slot, + * then turn the PK context into a wrapper for that key slot. + * + * Currently only works for EC private keys. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_id_t *key, + psa_algorithm_t hash_alg ) +{ +#if !defined(MBEDTLS_ECP_C) + ((void) pk); + ((void) key); + ((void) hash_alg); + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + const mbedtls_ecp_keypair *ec; + unsigned char d[MBEDTLS_ECP_MAX_BYTES]; + size_t d_len; + psa_ecc_family_t curve_id; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + size_t bits; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* export the private key material in the format PSA wants */ + if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ec = mbedtls_pk_ec( *pk ); + d_len = ( ec->grp.nbits + 7 ) / 8; + if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 ) + return( ret ); + + curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits ); + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id ); + + /* prepare the key attributes */ + psa_set_key_type( &attributes, key_type ); + psa_set_key_bits( &attributes, bits ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) ); + + /* import private key into PSA */ + if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, key ) ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + /* make PK context wrap the key slot */ + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + return( mbedtls_pk_setup_opaque( pk, *key ) ); +#endif /* MBEDTLS_ECP_C */ +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.c b/component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.c new file mode 100644 index 00000000..80c0aad2 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.c @@ -0,0 +1,1080 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PK_C) +#include "pk_wrap.h" +#include "mbedtls/error.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/asn1write.h" +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, md_alg, + (unsigned int) hash_len, + hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + if( sig_size < *sig_len ) + return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, + md_alg, (unsigned int) hash_len, + hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + (void) f_rng; + (void) p_rng; + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ +#if defined(MBEDTLS_RSA_ALT) + /* Not supported */ + (void) ctx; + (void) items; +#else + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +#endif +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; + + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_size, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv, + f_rng, p_rng ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of + * those integers and convert it to the fixed-length encoding expected by PSA. + */ +static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end, + unsigned char *to, size_t to_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len; + + if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len, + MBEDTLS_ASN1_INTEGER ) ) != 0 ) + { + return( ret ); + } + + while( unpadded_len > 0 && **from == 0x00 ) + { + ( *from )++; + unpadded_len--; + } + + if( unpadded_len > to_len || unpadded_len == 0 ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + padding_len = to_len - unpadded_len; + memset( to, 0x00, padding_len ); + memcpy( to + padding_len, *from, unpadded_len ); + ( *from ) += unpadded_len; + + return( 0 ); +} + +/* + * Convert a signature from an ASN.1 sequence of two integers + * to a raw {r,s} buffer. Note: the provided sig buffer must be at least + * twice as big as int_size. + */ +static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, + unsigned char *sig, size_t int_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tmp_size; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + /* Extract r */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 ) + return( ret ); + /* Extract s */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + mbedtls_ecdsa_context *ctx = ctx_arg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ + unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; + unsigned char *p; + mbedtls_pk_info_t pk_info = mbedtls_eckey_info; + psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits ); + const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8; + ((void) md_alg); + + if( curve == 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* mbedtls_pk_write_pubkey() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &pk_info; + key.pk_ctx = ctx; + p = buf + sizeof( buf ); + key_len = mbedtls_pk_write_pubkey( &p, buf, &key ); + if( key_len <= 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &attributes, psa_sig_md ); + + status = psa_import_key( &attributes, + buf + sizeof( buf ) - key_len, key_len, + &key_id ); + if( status != PSA_SUCCESS ) + { + ret = mbedtls_psa_err_translate_pk( status ); + goto cleanup; + } + + /* We don't need the exported key anymore and can + * reuse its buffer for signature extraction. */ + if( 2 * signature_part_size > sizeof( buf ) ) + { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } + + p = (unsigned char*) sig; + if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf, + signature_part_size ) ) != 0 ) + { + goto cleanup; + } + + if( psa_verify_hash( key_id, psa_sig_md, + hash, hash_len, + buf, 2 * signature_part_size ) + != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + if( p != sig + sig_len ) + { + ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + goto cleanup; + } + ret = 0; + +cleanup: + psa_destroy_key( key_id ); + return( ret ); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng ) ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + if( *sig_len > sig_size ) + return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, sizeof( sig ), &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static void *pk_opaque_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) ); + + /* no _init() function to call, an calloc() already zeroized */ + + return( ctx ); +} + +static void pk_opaque_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( psa_key_id_t ) ); + mbedtls_free( ctx ); +} + +static size_t pk_opaque_get_bitlen( const void *ctx ) +{ + const psa_key_id_t *key = (const psa_key_id_t *) ctx; + size_t bits; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) ) + return( 0 ); + + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + return( bits ); +} + +static int pk_opaque_can_do( mbedtls_pk_type_t type ) +{ + /* For now opaque PSA keys can only wrap ECC keypairs, + * as checked by setup_psa(). + * Also, ECKEY_DH does not really make sense with the current API. */ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_ECDSA_C) + +/* + * Simultaneously convert and move raw MPI from the beginning of a buffer + * to an ASN.1 MPI at the end of the buffer. + * See also mbedtls_asn1_write_mpi(). + * + * p: pointer to the end of the output buffer + * start: start of the output buffer, and also of the mpi to write at the end + * n_len: length of the mpi to read from start + */ +static int asn1_write_mpibuf( unsigned char **p, unsigned char *start, + size_t n_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( (size_t)( *p - start ) < n_len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = n_len; + *p -= len; + memmove( *p, start, len ); + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Neither r nor s should be 0, but as a failsafe measure, still detect + * that rather than overflowing the buffer in case of a PSA error. */ + while( len > 0 && **p == 0x00 ) + { + ++(*p); + --len; + } + + /* this is only reached if the signature was invalid */ + if( len == 0 ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + /* if the msb is 1, ASN.1 requires that we prepend a 0. + * Neither r nor s can be 0, so we can assume len > 0 at all times. */ + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +/* Transcode signature from PSA format to ASN.1 sequence. + * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of + * MPIs, and in-place. + * + * [in/out] sig: the signature pre- and post-transcoding + * [in/out] sig_len: signature length pre- and post-transcoding + * [int] buf_len: the available size the in/out buffer + */ +static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const size_t rs_len = *sig_len / 2; + unsigned char *p = sig + buf_len; + + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memmove( sig, p, len ); + *sig_len = len; + + return( 0 ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if !defined(MBEDTLS_ECDSA_C) + ((void) ctx); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_size); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#else /* !MBEDTLS_ECDSA_C */ + const psa_key_id_t *key = (const psa_key_id_t *) ctx; + psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) ); + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + /* make the signature */ + status = psa_sign_hash( *key, alg, hash, hash_len, + sig, sig_size, sig_len ); + if( status != PSA_SUCCESS ) + return( mbedtls_psa_err_translate_pk( status ) ); + + /* transcode it to ASN.1 sequence */ + return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, sig_size ) ); +#endif /* !MBEDTLS_ECDSA_C */ +} + +const mbedtls_pk_info_t mbedtls_pk_opaque_info = { + MBEDTLS_PK_OPAQUE, + "Opaque", + pk_opaque_get_bitlen, + pk_opaque_can_do, + NULL, /* verify - will be done later */ + pk_opaque_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restartable verify - not relevant */ + NULL, /* restartable sign - not relevant */ +#endif + NULL, /* decrypt - will be done later */ + NULL, /* encrypt - will be done later */ + NULL, /* check_pair - could be done later or left NULL */ + pk_opaque_alloc_wrap, + pk_opaque_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restart alloc - not relevant */ + NULL, /* restart free - not relevant */ +#endif + NULL, /* debug - could be done later, or even left NULL */ +}; + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PK_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.h b/component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.h new file mode 100644 index 00000000..6f5addf7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pk_wrap.h @@ -0,0 +1,138 @@ +/** + * \file pk_wrap.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pkcs12.c b/component/common/network/ssl/mbedtls-3.1.0/library/pkcs12.c new file mode 100644 index 00000000..a90d1f90 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pkcs12.c @@ -0,0 +1,359 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#include "common.h" + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret ) ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + if( pwd == NULL && pwdlen != 0 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + if( filler != NULL && fill_len != 0 ) + { + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } + } + else + { + /* If either of the above are not true then clearly there is nothing + * that this function can do. The function should *not* be called + * under either of those circumstances, as you could end up with an + * incorrect output but for safety's sake, leaving the check in as + * otherwise we could end up with memory corruption.*/ + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + int use_password = 0; + int use_salt = 0; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + if( pwd == NULL && pwdlen != 0 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + if( salt == NULL && saltlen != 0 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + use_password = ( pwd && pwdlen != 0 ); + use_salt = ( salt && saltlen != 0 ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + if( use_salt != 0 ) + { + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + } + + if( use_password != 0 ) + { + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + } + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( use_salt != 0 ) + { + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v )) != 0 ) + goto exit; + } + + if( use_password != 0) + { + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v )) != 0 ) + goto exit; + } + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + if( use_salt != 0 ) + { + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = MBEDTLS_BYTE_1( j ); + salt_block[i - 1] = MBEDTLS_BYTE_0( j ); + } + } + + if( use_password != 0 ) + { + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = MBEDTLS_BYTE_1( j ); + pwd_block[i - 1] = MBEDTLS_BYTE_0( j ); + } + } + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pkcs5.c b/component/common/network/ssl/mbedtls-3.1.0/library/pkcs5.c new file mode 100644 index 00000000..2b014d91 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pkcs5.c @@ -0,0 +1,420 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#include "common.h" + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, + &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret ) ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, + (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, + const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + +#if UINT_MAX > 0xFFFFFFFF + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif + + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 ) + goto cleanup; + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_reset( ctx ) ) != 0 ) + goto cleanup; + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + +cleanup: + /* Zeroise buffers to clear sensitive data from memory. */ + mbedtls_platform_zeroize( work, MBEDTLS_MD_MAX_SIZE ); + mbedtls_platform_zeroize( md1, MBEDTLS_MD_MAX_SIZE ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen_test_data[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password_test_data[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen_test_data[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt_test_data[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt_test_data[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len_test_data[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key_test_data[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password_test_data[i], + plen_test_data[i], salt_test_data[i], + slen_test_data[i], it_cnt_test_data[i], + key_len_test_data[i], key ); + if( ret != 0 || + memcmp( result_key_test_data[i], key, key_len_test_data[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pkparse.c b/component/common/network/ssl/mbedtls-3.1.0/library/pkparse.c new file mode 100644 index 00000000..b2d3bb07 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pkparse.c @@ -0,0 +1,1529 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0, f_rng, p_rng ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ), f_rng, p_rng ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ( end - *p < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); + + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + return( 0 ); +} + +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import E */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) + goto cleanup; + + /* Import D */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) + goto cleanup; + + /* Import P */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import Q */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) + goto cleanup; + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existance of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + { + goto cleanup; + } + + if( p != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ); + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + } + + if( p != end ) + { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( p + len != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + f_rng, p_rng ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + +#if !defined(MBEDTLS_ECP_C) + (void) f_rng; + (void) p_rng; +#endif + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( version != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret ) ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( len < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len, f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len, f_rng, p_rng ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_info_t *pk_info; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen, + f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen, f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, pem.buf, pem.buflen, + pwd, pwdlen, f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen, f_rng, p_rng ); + + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen, f_rng, p_rng ); + if( ret == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen, f_rng, p_rng ) == 0 ) + { + return( 0 ); + } + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/pkwrite.c b/component/common/network/ssl/mbedtls-3.1.0/library/pkwrite.c new file mode 100644 index 00000000..71cc0f0c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/pkwrite.c @@ -0,0 +1,623 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#include "mbedtls/platform_util.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +static int pk_write_ec_private( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t byte_length = ( ec->grp.pbits + 7 ) / 8; + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + + ret = mbedtls_ecp_write_key( ec, tmp, byte_length ); + if( ret != 0 ) + goto exit; + ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); + +exit: + mbedtls_platform_zeroize( tmp, byte_length ); + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( start != NULL ); + PK_VALIDATE_RET( key != NULL ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_OPAQUE ) + { + size_t buffer_size; + psa_key_id_t* key_id = (psa_key_id_t*) key->pk_ctx; + + if ( *p < start ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + buffer_size = (size_t)( *p - start ); + if ( psa_export_public_key( *key_id, start, buffer_size, &len ) + != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + else + { + *p -= len; + memmove( *p, start, len ); + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( const mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + mbedtls_pk_type_t pk_type; + const char *oid; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + pk_type = mbedtls_pk_get_type( key ); +#if defined(MBEDTLS_ECP_C) + if( pk_type == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( pk_type == MBEDTLS_PK_OPAQUE ) + { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + psa_key_id_t key_id; + psa_ecc_family_t curve; + size_t bits; + + key_id = *((psa_key_id_t*) key->pk_ctx ); + if( PSA_SUCCESS != psa_get_key_attributes( key_id, &attributes ) ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + key_type = psa_get_key_type( &attributes ); + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + + curve = PSA_KEY_TYPE_ECC_GET_FAMILY( key_type ); + if( curve == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + ret = mbedtls_psa_get_ecc_oid_from_id( curve, bits, &oid, &oid_len ); + if( ret != 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + /* Write EC algorithm parameters; that's akin + * to pk_write_ec_param() above. */ + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_oid( &c, buf, + oid, oid_len ) ); + + /* The rest of the function works as for legacy EC contexts. */ + pk_type = MBEDTLS_PK_ECKEY; + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( pk_type, &oid, + &oid_len ) ) != 0 ) + { + return( ret ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( const mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *c; + size_t len = 0; + + PK_VALIDATE_RET( key != NULL ); + if( size == 0 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + PK_VALIDATE_RET( buf != NULL ); + + c = buf + size; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey */ + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES ( 38 + 2 * MBEDTLS_MPI_MAX_SIZE ) + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 ( MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 ) +#define RSA_PRV_DER_MAX_BYTES ( 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 ) + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES ( RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES ) +#define PRV_DER_MAX_BYTES ( RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES ) + +int mbedtls_pk_write_pubkey_pem( const mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( const mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + PK_VALIDATE_RET( key != NULL ); + PK_VALIDATE_RET( buf != NULL || size == 0 ); + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/platform.c b/component/common/network/ssl/mbedtls-3.1.0/library/platform.c new file mode 100644 index 00000000..e742fde7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/platform.c @@ -0,0 +1,386 @@ +/* + * Platform abstraction layer + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + va_list argp; + + va_start( argp, fmt ); + ret = mbedtls_vsnprintf( s, n, fmt, argp ); + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + +#if defined(_TRUNCATE) + ret = vsnprintf_s( s, n, _TRUNCATE, fmt, arg ); +#else + ret = vsnprintf( s, n, fmt, arg ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_vsnprintf_uninit( char * s, size_t n, + const char * format, va_list arg ) +{ + ((void) s); + ((void) n); + ((void) format); + ((void) arg); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ + +int (*mbedtls_vsnprintf)( char * s, size_t n, + const char * format, + va_list arg ) = MBEDTLS_PLATFORM_STD_VSNPRINTF; + +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, + va_list arg ) ) +{ + mbedtls_vsnprintf = vsnprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/platform_util.c b/component/common/network/ssl/mbedtls-3.1.0/library/platform_util.c new file mode 100644 index 00000000..3d5cb5ba --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/platform_util.c @@ -0,0 +1,138 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" +#include "mbedtls/threading.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); + + if( len > 0 ) + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ + +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); +#else + struct tm *lt; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + lt = gmtime( tt ); + + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ + + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_test_fail)( const char *, int, const char *); +#endif /* MBEDTLS_TEST_HOOKS */ + diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/poly1305.c b/component/common/network/ssl/mbedtls-3.1.0/library/poly1305.c new file mode 100644 index 00000000..7375a0c5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/poly1305.c @@ -0,0 +1,538 @@ +/** + * \file poly1305.c + * + * \brief Poly1305 authentication algorithm. + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_POLY1305_C) + +#include "mbedtls/poly1305.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_POLY1305_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Parameter validation macros */ +#define POLY1305_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA ) +#define POLY1305_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define POLY1305_BLOCK_SIZE_BYTES ( 16U ) + +/* + * Our implementation is tuned for 32-bit platforms with a 64-bit multiplier. + * However we provided an alternative for platforms without such a multiplier. + */ +#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION) +static uint64_t mul64( uint32_t a, uint32_t b ) +{ + /* a = al + 2**16 ah, b = bl + 2**16 bh */ + const uint16_t al = (uint16_t) a; + const uint16_t bl = (uint16_t) b; + const uint16_t ah = a >> 16; + const uint16_t bh = b >> 16; + + /* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */ + const uint32_t lo = (uint32_t) al * bl; + const uint64_t me = (uint64_t)( (uint32_t) ah * bl ) + (uint32_t) al * bh; + const uint32_t hi = (uint32_t) ah * bh; + + return( lo + ( me << 16 ) + ( (uint64_t) hi << 32 ) ); +} +#else +static inline uint64_t mul64( uint32_t a, uint32_t b ) +{ + return( (uint64_t) a * b ); +} +#endif + + +/** + * \brief Process blocks with Poly1305. + * + * \param ctx The Poly1305 context. + * \param nblocks Number of blocks to process. Note that this + * function only processes full blocks. + * \param input Buffer containing the input block(s). + * \param needs_padding Set to 0 if the padding bit has already been + * applied to the input data before calling this + * function. Otherwise, set this parameter to 1. + */ +static void poly1305_process( mbedtls_poly1305_context *ctx, + size_t nblocks, + const unsigned char *input, + uint32_t needs_padding ) +{ + uint64_t d0, d1, d2, d3; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t r0, r1, r2, r3; + uint32_t rs1, rs2, rs3; + size_t offset = 0U; + size_t i; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + + rs1 = r1 + ( r1 >> 2U ); + rs2 = r2 + ( r2 >> 2U ); + rs3 = r3 + ( r3 >> 2U ); + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Process full blocks */ + for( i = 0U; i < nblocks; i++ ) + { + /* The input block is treated as a 128-bit little-endian integer */ + d0 = MBEDTLS_GET_UINT32_LE( input, offset + 0 ); + d1 = MBEDTLS_GET_UINT32_LE( input, offset + 4 ); + d2 = MBEDTLS_GET_UINT32_LE( input, offset + 8 ); + d3 = MBEDTLS_GET_UINT32_LE( input, offset + 12 ); + + /* Compute: acc += (padded) block as a 130-bit integer */ + d0 += (uint64_t) acc0; + d1 += (uint64_t) acc1 + ( d0 >> 32U ); + d2 += (uint64_t) acc2 + ( d1 >> 32U ); + d3 += (uint64_t) acc3 + ( d2 >> 32U ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 += (uint32_t) ( d3 >> 32U ) + needs_padding; + + /* Compute: acc *= r */ + d0 = mul64( acc0, r0 ) + + mul64( acc1, rs3 ) + + mul64( acc2, rs2 ) + + mul64( acc3, rs1 ); + d1 = mul64( acc0, r1 ) + + mul64( acc1, r0 ) + + mul64( acc2, rs3 ) + + mul64( acc3, rs2 ) + + mul64( acc4, rs1 ); + d2 = mul64( acc0, r2 ) + + mul64( acc1, r1 ) + + mul64( acc2, r0 ) + + mul64( acc3, rs3 ) + + mul64( acc4, rs2 ); + d3 = mul64( acc0, r3 ) + + mul64( acc1, r2 ) + + mul64( acc2, r1 ) + + mul64( acc3, r0 ) + + mul64( acc4, rs3 ); + acc4 *= r0; + + /* Compute: acc %= (2^130 - 5) (partial remainder) */ + d1 += ( d0 >> 32 ); + d2 += ( d1 >> 32 ); + d3 += ( d2 >> 32 ); + acc0 = (uint32_t) d0; + acc1 = (uint32_t) d1; + acc2 = (uint32_t) d2; + acc3 = (uint32_t) d3; + acc4 = (uint32_t) ( d3 >> 32 ) + acc4; + + d0 = (uint64_t) acc0 + ( acc4 >> 2 ) + ( acc4 & 0xFFFFFFFCU ); + acc4 &= 3U; + acc0 = (uint32_t) d0; + d0 = (uint64_t) acc1 + ( d0 >> 32U ); + acc1 = (uint32_t) d0; + d0 = (uint64_t) acc2 + ( d0 >> 32U ); + acc2 = (uint32_t) d0; + d0 = (uint64_t) acc3 + ( d0 >> 32U ); + acc3 = (uint32_t) d0; + d0 = (uint64_t) acc4 + ( d0 >> 32U ); + acc4 = (uint32_t) d0; + + offset += POLY1305_BLOCK_SIZE_BYTES; + } + + ctx->acc[0] = acc0; + ctx->acc[1] = acc1; + ctx->acc[2] = acc2; + ctx->acc[3] = acc3; + ctx->acc[4] = acc4; +} + +/** + * \brief Compute the Poly1305 MAC + * + * \param ctx The Poly1305 context. + * \param mac The buffer to where the MAC is written. Must be + * big enough to contain the 16-byte MAC. + */ +static void poly1305_compute_mac( const mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + uint64_t d; + uint32_t g0, g1, g2, g3, g4; + uint32_t acc0, acc1, acc2, acc3, acc4; + uint32_t mask; + uint32_t mask_inv; + + acc0 = ctx->acc[0]; + acc1 = ctx->acc[1]; + acc2 = ctx->acc[2]; + acc3 = ctx->acc[3]; + acc4 = ctx->acc[4]; + + /* Before adding 's' we ensure that the accumulator is mod 2^130 - 5. + * We do this by calculating acc - (2^130 - 5), then checking if + * the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5) + */ + + /* Calculate acc + -(2^130 - 5) */ + d = ( (uint64_t) acc0 + 5U ); + g0 = (uint32_t) d; + d = ( (uint64_t) acc1 + ( d >> 32 ) ); + g1 = (uint32_t) d; + d = ( (uint64_t) acc2 + ( d >> 32 ) ); + g2 = (uint32_t) d; + d = ( (uint64_t) acc3 + ( d >> 32 ) ); + g3 = (uint32_t) d; + g4 = acc4 + (uint32_t) ( d >> 32U ); + + /* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */ + mask = (uint32_t) 0U - ( g4 >> 2U ); + mask_inv = ~mask; + + /* If 131st bit is set then acc=g, otherwise, acc is unmodified */ + acc0 = ( acc0 & mask_inv ) | ( g0 & mask ); + acc1 = ( acc1 & mask_inv ) | ( g1 & mask ); + acc2 = ( acc2 & mask_inv ) | ( g2 & mask ); + acc3 = ( acc3 & mask_inv ) | ( g3 & mask ); + + /* Add 's' */ + d = (uint64_t) acc0 + ctx->s[0]; + acc0 = (uint32_t) d; + d = (uint64_t) acc1 + ctx->s[1] + ( d >> 32U ); + acc1 = (uint32_t) d; + d = (uint64_t) acc2 + ctx->s[2] + ( d >> 32U ); + acc2 = (uint32_t) d; + acc3 += ctx->s[3] + (uint32_t) ( d >> 32U ); + + /* Compute MAC (128 least significant bits of the accumulator) */ + MBEDTLS_PUT_UINT32_LE( acc0, mac, 0 ); + MBEDTLS_PUT_UINT32_LE( acc1, mac, 4 ); + MBEDTLS_PUT_UINT32_LE( acc2, mac, 8 ); + MBEDTLS_PUT_UINT32_LE( acc3, mac, 12 ); +} + +void mbedtls_poly1305_init( mbedtls_poly1305_context *ctx ) +{ + POLY1305_VALIDATE( ctx != NULL ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +void mbedtls_poly1305_free( mbedtls_poly1305_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_poly1305_context ) ); +} + +int mbedtls_poly1305_starts( mbedtls_poly1305_context *ctx, + const unsigned char key[32] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( key != NULL ); + + /* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = MBEDTLS_GET_UINT32_LE( key, 0 ) & 0x0FFFFFFFU; + ctx->r[1] = MBEDTLS_GET_UINT32_LE( key, 4 ) & 0x0FFFFFFCU; + ctx->r[2] = MBEDTLS_GET_UINT32_LE( key, 8 ) & 0x0FFFFFFCU; + ctx->r[3] = MBEDTLS_GET_UINT32_LE( key, 12 ) & 0x0FFFFFFCU; + + ctx->s[0] = MBEDTLS_GET_UINT32_LE( key, 16 ); + ctx->s[1] = MBEDTLS_GET_UINT32_LE( key, 20 ); + ctx->s[2] = MBEDTLS_GET_UINT32_LE( key, 24 ); + ctx->s[3] = MBEDTLS_GET_UINT32_LE( key, 28 ); + + /* Initial accumulator state */ + ctx->acc[0] = 0U; + ctx->acc[1] = 0U; + ctx->acc[2] = 0U; + ctx->acc[3] = 0U; + ctx->acc[4] = 0U; + + /* Queue initially empty */ + mbedtls_platform_zeroize( ctx->queue, sizeof( ctx->queue ) ); + ctx->queue_len = 0U; + + return( 0 ); +} + +int mbedtls_poly1305_update( mbedtls_poly1305_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + size_t offset = 0U; + size_t remaining = ilen; + size_t queue_free_len; + size_t nblocks; + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ( remaining > 0U ) && ( ctx->queue_len > 0U ) ) + { + queue_free_len = ( POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + if( ilen < queue_free_len ) + { + /* Not enough data to complete the block. + * Store this data with the other leftovers. + */ + memcpy( &ctx->queue[ctx->queue_len], + input, + ilen ); + + ctx->queue_len += ilen; + + remaining = 0U; + } + else + { + /* Enough data to produce a complete block */ + memcpy( &ctx->queue[ctx->queue_len], + input, + queue_free_len ); + + ctx->queue_len = 0U; + + poly1305_process( ctx, 1U, ctx->queue, 1U ); /* add padding bit */ + + offset += queue_free_len; + remaining -= queue_free_len; + } + } + + if( remaining >= POLY1305_BLOCK_SIZE_BYTES ) + { + nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES; + + poly1305_process( ctx, nblocks, &input[offset], 1U ); + + offset += nblocks * POLY1305_BLOCK_SIZE_BYTES; + remaining %= POLY1305_BLOCK_SIZE_BYTES; + } + + if( remaining > 0U ) + { + /* Store partial block */ + ctx->queue_len = remaining; + memcpy( ctx->queue, &input[offset], remaining ); + } + + return( 0 ); +} + +int mbedtls_poly1305_finish( mbedtls_poly1305_context *ctx, + unsigned char mac[16] ) +{ + POLY1305_VALIDATE_RET( ctx != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + + /* Process any leftover data */ + if( ctx->queue_len > 0U ) + { + /* Add padding bit */ + ctx->queue[ctx->queue_len] = 1U; + ctx->queue_len++; + + /* Pad with zeroes */ + memset( &ctx->queue[ctx->queue_len], + 0, + POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len ); + + poly1305_process( ctx, 1U, /* Process 1 block */ + ctx->queue, 0U ); /* Already padded above */ + } + + poly1305_compute_mac( ctx, mac ); + + return( 0 ); +} + +int mbedtls_poly1305_mac( const unsigned char key[32], + const unsigned char *input, + size_t ilen, + unsigned char mac[16] ) +{ + mbedtls_poly1305_context ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + POLY1305_VALIDATE_RET( key != NULL ); + POLY1305_VALIDATE_RET( mac != NULL ); + POLY1305_VALIDATE_RET( ilen == 0 || input != NULL ); + + mbedtls_poly1305_init( &ctx ); + + ret = mbedtls_poly1305_starts( &ctx, key ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_update( &ctx, input, ilen ); + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_poly1305_finish( &ctx, mac ); + +cleanup: + mbedtls_poly1305_free( &ctx ); + return( ret ); +} + +#endif /* MBEDTLS_POLY1305_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char test_keys[2][32] = +{ + { + 0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33, + 0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8, + 0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd, + 0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b + }, + { + 0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a, + 0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0, + 0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09, + 0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0 + } +}; + +static const unsigned char test_data[2][127] = +{ + { + 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72, + 0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f, + 0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65, + 0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f, + 0x75, 0x70 + }, + { + 0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72, + 0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61, + 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, + 0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f, + 0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20, + 0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64, + 0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20, + 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, + 0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c, + 0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77, + 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65, + 0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20, + 0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75, + 0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e + } +}; + +static const size_t test_data_len[2] = +{ + 34U, + 127U +}; + +static const unsigned char test_mac[2][16] = +{ + { + 0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6, + 0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9 + }, + { + 0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61, + 0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62 + } +}; + +/* Make sure no other definition is already present. */ +#undef ASSERT + +#define ASSERT( cond, args ) \ + do \ + { \ + if( ! ( cond ) ) \ + { \ + if( verbose != 0 ) \ + mbedtls_printf args; \ + \ + return( -1 ); \ + } \ + } \ + while( 0 ) + +int mbedtls_poly1305_self_test( int verbose ) +{ + unsigned char mac[16]; + unsigned i; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + for( i = 0U; i < 2U; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " Poly1305 test %u ", i ); + + ret = mbedtls_poly1305_mac( test_keys[i], + test_data[i], + test_data_len[i], + mac ); + ASSERT( 0 == ret, ( "error code: %i\n", ret ) ); + + ASSERT( 0 == memcmp( mac, test_mac[i], 16U ), ( "failed (mac)\n" ) ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_POLY1305_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto.c new file mode 100644 index 00000000..829ed452 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto.c @@ -0,0 +1,5966 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) +#include "check_crypto_config.h" +#endif + +#include "psa/crypto.h" + +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_invasive.h" +#include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_ecp.h" +#include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" +#include "psa_crypto_rsa.h" +#include "psa_crypto_ecp.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif +#include "psa_crypto_slot_management.h" +/* Include internal declarations that are useful for implementing persistently + * stored keys. */ +#include "psa_crypto_storage.h" + +#include "psa_crypto_random_impl.h" + +#include +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/aes.h" +#include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/bignum.h" +#include "mbedtls/camellia.h" +#include "mbedtls/chacha20.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/ccm.h" +#include "mbedtls/cmac.h" +#include "mbedtls/des.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/error.h" +#include "mbedtls/gcm.h" +#include "mbedtls/md5.h" +#include "mbedtls/md.h" +#include "md_wrap.h" +#include "mbedtls/pk.h" +#include "pk_wrap.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "mbedtls/ripemd160.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +/****************************************************************/ +/* Global data, support functions and library management */ +/****************************************************************/ + +static int key_type_is_raw_bytes( psa_key_type_t type ) +{ + return( PSA_KEY_TYPE_IS_UNSTRUCTURED( type ) ); +} + +/* Values for psa_global_data_t::rng_state */ +#define RNG_NOT_INITIALIZED 0 +#define RNG_INITIALIZED 1 +#define RNG_SEEDED 2 + +typedef struct +{ + unsigned initialized : 1; + unsigned rng_state : 2; + mbedtls_psa_random_context_t rng; +} psa_global_data_t; + +static psa_global_data_t global_data; + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state = + &global_data.rng.drbg; +#endif + +#define GUARD_MODULE_INITIALIZED \ + if( global_data.initialized == 0 ) \ + return( PSA_ERROR_BAD_STATE ); + +psa_status_t mbedtls_to_psa_error( int ret ) +{ + /* Mbed TLS error codes can combine a high-level error code and a + * low-level error code. The low-level error usually reflects the + * root cause better, so dispatch on that preferably. */ + int low_level_ret = - ( -ret & 0x007f ); + switch( low_level_ret != 0 ? low_level_ret : ret ) + { + case 0: + return( PSA_SUCCESS ); + + case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH: + case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_ASN1_OUT_OF_DATA: + case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG: + case MBEDTLS_ERR_ASN1_INVALID_LENGTH: + case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH: + case MBEDTLS_ERR_ASN1_INVALID_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_ASN1_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) + case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: +#endif + case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + + case MBEDTLS_ERR_CCM_BAD_INPUT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CCM_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + + case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + + case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE: + return( PSA_ERROR_BAD_STATE ); + case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + + case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CIPHER_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_CIPHER_INVALID_PADDING: + return( PSA_ERROR_INVALID_PADDING ); + case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_CIPHER_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT: + return( PSA_ERROR_CORRUPTION_DETECTED ); + +#if !( defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) || \ + defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) ) + /* Only check CTR_DRBG error codes if underlying mbedtls_xxx + * functions are passed a CTR_DRBG instance. */ + case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG: + case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); +#endif + + case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH: + return( PSA_ERROR_NOT_SUPPORTED ); + + case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED: + case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE: + case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_GCM_AUTH_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_GCM_BAD_INPUT: + return( PSA_ERROR_INVALID_ARGUMENT ); + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \ + defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) + /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx + * functions are passed a HMAC_DRBG instance. */ + case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG: + case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); +#endif + + case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_MD_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MD_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_MD_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + + case MBEDTLS_ERR_MPI_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_MPI_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_INVALID_CHARACTER: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_MPI_NEGATIVE_VALUE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_MPI_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + case MBEDTLS_ERR_PK_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_PK_TYPE_MISMATCH: + case MBEDTLS_ERR_PK_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_FILE_IO_ERROR: + return( PSA_ERROR_STORAGE_FAILURE ); + case MBEDTLS_ERR_PK_KEY_INVALID_VERSION: + case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_PASSWORD_REQUIRED: + case MBEDTLS_ERR_PK_PASSWORD_MISMATCH: + return( PSA_ERROR_NOT_PERMITTED ); + case MBEDTLS_ERR_PK_INVALID_PUBKEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_PK_INVALID_ALG: + case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE: + case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED: + return( PSA_ERROR_NOT_SUPPORTED ); + + case MBEDTLS_ERR_RSA_BAD_INPUT_DATA: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_RSA_INVALID_PADDING: + return( PSA_ERROR_INVALID_PADDING ); + case MBEDTLS_ERR_RSA_KEY_GEN_FAILED: + return( PSA_ERROR_HARDWARE_FAILURE ); + case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_RSA_PUBLIC_FAILED: + case MBEDTLS_ERR_RSA_PRIVATE_FAILED: + return( PSA_ERROR_CORRUPTION_DETECTED ); + case MBEDTLS_ERR_RSA_VERIFY_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_RSA_RNG_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_ECP_BAD_INPUT_DATA: + case MBEDTLS_ERR_ECP_INVALID_KEY: + return( PSA_ERROR_INVALID_ARGUMENT ); + case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL: + return( PSA_ERROR_BUFFER_TOO_SMALL ); + case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE: + return( PSA_ERROR_NOT_SUPPORTED ); + case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH: + case MBEDTLS_ERR_ECP_VERIFY_FAILED: + return( PSA_ERROR_INVALID_SIGNATURE ); + case MBEDTLS_ERR_ECP_ALLOC_FAILED: + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + case MBEDTLS_ERR_ECP_RANDOM_FAILED: + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + + case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED: + return( PSA_ERROR_CORRUPTION_DETECTED ); + + default: + return( PSA_ERROR_GENERIC_ERROR ); + } +} + + + + +/****************************************************************/ +/* Key management */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +mbedtls_ecp_group_id mbedtls_ecc_group_of_psa( psa_ecc_family_t curve, + size_t bits, + int bits_is_sloppy ) +{ + switch( curve ) + { + case PSA_ECC_FAMILY_SECP_R1: + switch( bits ) + { +#if defined(PSA_WANT_ECC_SECP_R1_192) + case 192: + return( MBEDTLS_ECP_DP_SECP192R1 ); +#endif +#if defined(PSA_WANT_ECC_SECP_R1_224) + case 224: + return( MBEDTLS_ECP_DP_SECP224R1 ); +#endif +#if defined(PSA_WANT_ECC_SECP_R1_256) + case 256: + return( MBEDTLS_ECP_DP_SECP256R1 ); +#endif +#if defined(PSA_WANT_ECC_SECP_R1_384) + case 384: + return( MBEDTLS_ECP_DP_SECP384R1 ); +#endif +#if defined(PSA_WANT_ECC_SECP_R1_521) + case 521: + return( MBEDTLS_ECP_DP_SECP521R1 ); + case 528: + if( bits_is_sloppy ) + return( MBEDTLS_ECP_DP_SECP521R1 ); + break; +#endif + } + break; + + case PSA_ECC_FAMILY_BRAINPOOL_P_R1: + switch( bits ) + { +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) + case 256: + return( MBEDTLS_ECP_DP_BP256R1 ); +#endif +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) + case 384: + return( MBEDTLS_ECP_DP_BP384R1 ); +#endif +#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) + case 512: + return( MBEDTLS_ECP_DP_BP512R1 ); +#endif + } + break; + + case PSA_ECC_FAMILY_MONTGOMERY: + switch( bits ) + { +#if defined(PSA_WANT_ECC_MONTGOMERY_255) + case 255: + return( MBEDTLS_ECP_DP_CURVE25519 ); + case 256: + if( bits_is_sloppy ) + return( MBEDTLS_ECP_DP_CURVE25519 ); + break; +#endif +#if defined(PSA_WANT_ECC_MONTGOMERY_448) + case 448: + return( MBEDTLS_ECP_DP_CURVE448 ); +#endif + } + break; + + case PSA_ECC_FAMILY_SECP_K1: + switch( bits ) + { +#if defined(PSA_WANT_ECC_SECP_K1_192) + case 192: + return( MBEDTLS_ECP_DP_SECP192K1 ); +#endif +#if defined(PSA_WANT_ECC_SECP_K1_224) + case 224: + return( MBEDTLS_ECP_DP_SECP224K1 ); +#endif +#if defined(PSA_WANT_ECC_SECP_K1_256) + case 256: + return( MBEDTLS_ECP_DP_SECP256K1 ); +#endif + } + break; + } + + (void) bits_is_sloppy; + return( MBEDTLS_ECP_DP_NONE ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ + +psa_status_t psa_validate_unstructured_key_bit_size( psa_key_type_t type, + size_t bits ) +{ + /* Check that the bit size is acceptable for the key type */ + switch( type ) + { + case PSA_KEY_TYPE_RAW_DATA: + case PSA_KEY_TYPE_HMAC: + case PSA_KEY_TYPE_DERIVE: + break; +#if defined(PSA_WANT_KEY_TYPE_AES) + case PSA_KEY_TYPE_AES: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_ARIA) + case PSA_KEY_TYPE_ARIA: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_CAMELLIA) + case PSA_KEY_TYPE_CAMELLIA: + if( bits != 128 && bits != 192 && bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_DES) + case PSA_KEY_TYPE_DES: + if( bits != 64 && bits != 128 && bits != 192 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif +#if defined(PSA_WANT_KEY_TYPE_CHACHA20) + case PSA_KEY_TYPE_CHACHA20: + if( bits != 256 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + break; +#endif + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + if( bits % 8 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Check whether a given key type is valid for use with a given MAC algorithm + * + * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH + * when called with the validated \p algorithm and \p key_type is well-defined. + * + * \param[in] algorithm The specific MAC algorithm (can be wildcard). + * \param[in] key_type The key type of the key to be used with the + * \p algorithm. + * + * \retval #PSA_SUCCESS + * The \p key_type is valid for use with the \p algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The \p key_type is not valid for use with the \p algorithm + */ +MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do( + psa_algorithm_t algorithm, + psa_key_type_t key_type ) +{ + if( PSA_ALG_IS_HMAC( algorithm ) ) + { + if( key_type == PSA_KEY_TYPE_HMAC ) + return( PSA_SUCCESS ); + } + + if( PSA_ALG_IS_BLOCK_CIPHER_MAC( algorithm ) ) + { + /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher + * key. */ + if( ( key_type & PSA_KEY_TYPE_CATEGORY_MASK ) == + PSA_KEY_TYPE_CATEGORY_SYMMETRIC ) + { + /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and + * the block length (larger than 1) for block ciphers. */ + if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) > 1 ) + return( PSA_SUCCESS ); + } + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot, + size_t buffer_length ) +{ + if( slot->key.data != NULL ) + return( PSA_ERROR_ALREADY_EXISTS ); + + slot->key.data = mbedtls_calloc( 1, buffer_length ); + if( slot->key.data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + slot->key.bytes = buffer_length; + return( PSA_SUCCESS ); +} + +psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, + const uint8_t* data, + size_t data_length ) +{ + psa_status_t status = psa_allocate_buffer_to_slot( slot, + data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + memcpy( slot->key.data, data, data_length ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_import_key_into_slot( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->core.type; + + /* zero-length keys are never supported. */ + if( data_length == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( key_type_is_raw_bytes( type ) ) + { + *bits = PSA_BYTES_TO_BITS( data_length ); + + status = psa_validate_unstructured_key_bit_size( attributes->core.type, + *bits ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Copy the key material. */ + memcpy( key_buffer, data, data_length ); + *key_buffer_length = data_length; + (void)key_buffer_size; + + return( PSA_SUCCESS ); + } + else if( PSA_KEY_TYPE_IS_ASYMMETRIC( type ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + if( PSA_KEY_TYPE_IS_ECC( type ) ) + { + return( mbedtls_psa_ecp_import_key( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits ) ); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + if( PSA_KEY_TYPE_IS_RSA( type ) ) + { + return( mbedtls_psa_rsa_import_key( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, + bits ) ); + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + } + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +/** Calculate the intersection of two algorithm usage policies. + * + * Return 0 (which allows no operation) on incompatibility. + */ +static psa_algorithm_t psa_key_policy_algorithm_intersection( + psa_key_type_t key_type, + psa_algorithm_t alg1, + psa_algorithm_t alg2 ) +{ + /* Common case: both sides actually specify the same policy. */ + if( alg1 == alg2 ) + return( alg1 ); + /* If the policies are from the same hash-and-sign family, check + * if one is a wildcard. If so the other has the specific algorithm. */ + if( PSA_ALG_IS_SIGN_HASH( alg1 ) && + PSA_ALG_IS_SIGN_HASH( alg2 ) && + ( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) ) + { + if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH ) + return( alg2 ); + if( PSA_ALG_SIGN_GET_HASH( alg2 ) == PSA_ALG_ANY_HASH ) + return( alg1 ); + } + /* If the policies are from the same AEAD family, check whether + * one of them is a minimum-tag-length wildcard. Calculate the most + * restrictive tag length. */ + if( PSA_ALG_IS_AEAD( alg1 ) && PSA_ALG_IS_AEAD( alg2 ) && + ( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg1, 0 ) == + PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg2, 0 ) ) ) + { + size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH( alg1 ); + size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH( alg2 ); + size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; + + /* If both are wildcards, return most restrictive wildcard */ + if( ( ( alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) && + ( ( alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) ) + { + return( PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG( + alg1, restricted_len ) ); + } + /* If only one is a wildcard, return specific algorithm if compatible. */ + if( ( ( alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) && + ( alg1_len <= alg2_len ) ) + { + return( alg2 ); + } + if( ( ( alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) && + ( alg2_len <= alg1_len ) ) + { + return( alg1 ); + } + } + /* If the policies are from the same MAC family, check whether one + * of them is a minimum-MAC-length policy. Calculate the most + * restrictive tag length. */ + if( PSA_ALG_IS_MAC( alg1 ) && PSA_ALG_IS_MAC( alg2 ) && + ( PSA_ALG_FULL_LENGTH_MAC( alg1 ) == + PSA_ALG_FULL_LENGTH_MAC( alg2 ) ) ) + { + /* Validate the combination of key type and algorithm. Since the base + * algorithm of alg1 and alg2 are the same, we only need this once. */ + if( PSA_SUCCESS != psa_mac_key_can_do( alg1, key_type ) ) + return( 0 ); + + /* Get the (exact or at-least) output lengths for both sides of the + * requested intersection. None of the currently supported algorithms + * have an output length dependent on the actual key size, so setting it + * to a bogus value of 0 is currently OK. + * + * Note that for at-least-this-length wildcard algorithms, the output + * length is set to the shortest allowed length, which allows us to + * calculate the most restrictive tag length for the intersection. */ + size_t alg1_len = PSA_MAC_LENGTH( key_type, 0, alg1 ); + size_t alg2_len = PSA_MAC_LENGTH( key_type, 0, alg2 ); + size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len; + + /* If both are wildcards, return most restrictive wildcard */ + if( ( ( alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) && + ( ( alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) ) + { + return( PSA_ALG_AT_LEAST_THIS_LENGTH_MAC( alg1, restricted_len ) ); + } + + /* If only one is an at-least-this-length policy, the intersection would + * be the other (fixed-length) policy as long as said fixed length is + * equal to or larger than the shortest allowed length. */ + if( ( alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) + { + return( ( alg1_len <= alg2_len ) ? alg2 : 0 ); + } + if( ( alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) + { + return( ( alg2_len <= alg1_len ) ? alg1 : 0 ); + } + + /* If none of them are wildcards, check whether they define the same tag + * length. This is still possible here when one is default-length and + * the other specific-length. Ensure to always return the + * specific-length version for the intersection. */ + if( alg1_len == alg2_len ) + return( PSA_ALG_TRUNCATED_MAC( alg1, alg1_len ) ); + } + /* If the policies are incompatible, allow nothing. */ + return( 0 ); +} + +static int psa_key_algorithm_permits( psa_key_type_t key_type, + psa_algorithm_t policy_alg, + psa_algorithm_t requested_alg ) +{ + /* Common case: the policy only allows requested_alg. */ + if( requested_alg == policy_alg ) + return( 1 ); + /* If policy_alg is a hash-and-sign with a wildcard for the hash, + * and requested_alg is the same hash-and-sign family with any hash, + * then requested_alg is compliant with policy_alg. */ + if( PSA_ALG_IS_SIGN_HASH( requested_alg ) && + PSA_ALG_SIGN_GET_HASH( policy_alg ) == PSA_ALG_ANY_HASH ) + { + return( ( policy_alg & ~PSA_ALG_HASH_MASK ) == + ( requested_alg & ~PSA_ALG_HASH_MASK ) ); + } + /* If policy_alg is a wildcard AEAD algorithm of the same base as + * the requested algorithm, check the requested tag length to be + * equal-length or longer than the wildcard-specified length. */ + if( PSA_ALG_IS_AEAD( policy_alg ) && + PSA_ALG_IS_AEAD( requested_alg ) && + ( PSA_ALG_AEAD_WITH_SHORTENED_TAG( policy_alg, 0 ) == + PSA_ALG_AEAD_WITH_SHORTENED_TAG( requested_alg, 0 ) ) && + ( ( policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) ) + { + return( PSA_ALG_AEAD_GET_TAG_LENGTH( policy_alg ) <= + PSA_ALG_AEAD_GET_TAG_LENGTH( requested_alg ) ); + } + /* If policy_alg is a MAC algorithm of the same base as the requested + * algorithm, check whether their MAC lengths are compatible. */ + if( PSA_ALG_IS_MAC( policy_alg ) && + PSA_ALG_IS_MAC( requested_alg ) && + ( PSA_ALG_FULL_LENGTH_MAC( policy_alg ) == + PSA_ALG_FULL_LENGTH_MAC( requested_alg ) ) ) + { + /* Validate the combination of key type and algorithm. Since the policy + * and requested algorithms are the same, we only need this once. */ + if( PSA_SUCCESS != psa_mac_key_can_do( policy_alg, key_type ) ) + return( 0 ); + + /* Get both the requested output length for the algorithm which is to be + * verified, and the default output length for the base algorithm. + * Note that none of the currently supported algorithms have an output + * length dependent on actual key size, so setting it to a bogus value + * of 0 is currently OK. */ + size_t requested_output_length = PSA_MAC_LENGTH( + key_type, 0, requested_alg ); + size_t default_output_length = PSA_MAC_LENGTH( + key_type, 0, + PSA_ALG_FULL_LENGTH_MAC( requested_alg ) ); + + /* If the policy is default-length, only allow an algorithm with + * a declared exact-length matching the default. */ + if( PSA_MAC_TRUNCATED_LENGTH( policy_alg ) == 0 ) + return( requested_output_length == default_output_length ); + + /* If the requested algorithm is default-length, allow it if the policy + * length exactly matches the default length. */ + if( PSA_MAC_TRUNCATED_LENGTH( requested_alg ) == 0 && + PSA_MAC_TRUNCATED_LENGTH( policy_alg ) == default_output_length ) + { + return( 1 ); + } + + /* If policy_alg is an at-least-this-length wildcard MAC algorithm, + * check for the requested MAC length to be equal to or longer than the + * minimum allowed length. */ + if( ( policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG ) != 0 ) + { + return( PSA_MAC_TRUNCATED_LENGTH( policy_alg ) <= + requested_output_length ); + } + } + /* If policy_alg is a generic key agreement operation, then using it for + * a key derivation with that key agreement should also be allowed. This + * behaviour is expected to be defined in a future specification version. */ + if( PSA_ALG_IS_RAW_KEY_AGREEMENT( policy_alg ) && + PSA_ALG_IS_KEY_AGREEMENT( requested_alg ) ) + { + return( PSA_ALG_KEY_AGREEMENT_GET_BASE( requested_alg ) == + policy_alg ); + } + /* If it isn't explicitly permitted, it's forbidden. */ + return( 0 ); +} + +/** Test whether a policy permits an algorithm. + * + * The caller must test usage flags separately. + * + * \note This function requires providing the key type for which the policy is + * being validated, since some algorithm policy definitions (e.g. MAC) + * have different properties depending on what kind of cipher it is + * combined with. + * + * \retval PSA_SUCCESS When \p alg is a specific algorithm + * allowed by the \p policy. + * \retval PSA_ERROR_INVALID_ARGUMENT When \p alg is not a specific algorithm + * \retval PSA_ERROR_NOT_PERMITTED When \p alg is a specific algorithm, but + * the \p policy does not allow it. + */ +static psa_status_t psa_key_policy_permits( const psa_key_policy_t *policy, + psa_key_type_t key_type, + psa_algorithm_t alg ) +{ + /* '0' is not a valid algorithm */ + if( alg == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* A requested algorithm cannot be a wildcard. */ + if( PSA_ALG_IS_WILDCARD( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( psa_key_algorithm_permits( key_type, policy->alg, alg ) || + psa_key_algorithm_permits( key_type, policy->alg2, alg ) ) + return( PSA_SUCCESS ); + else + return( PSA_ERROR_NOT_PERMITTED ); +} + +/** Restrict a key policy based on a constraint. + * + * \note This function requires providing the key type for which the policy is + * being restricted, since some algorithm policy definitions (e.g. MAC) + * have different properties depending on what kind of cipher it is + * combined with. + * + * \param[in] key_type The key type for which to restrict the policy + * \param[in,out] policy The policy to restrict. + * \param[in] constraint The policy constraint to apply. + * + * \retval #PSA_SUCCESS + * \c *policy contains the intersection of the original value of + * \c *policy and \c *constraint. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key_type, \c *policy and \c *constraint are incompatible. + * \c *policy is unchanged. + */ +static psa_status_t psa_restrict_key_policy( + psa_key_type_t key_type, + psa_key_policy_t *policy, + const psa_key_policy_t *constraint ) +{ + psa_algorithm_t intersection_alg = + psa_key_policy_algorithm_intersection( key_type, policy->alg, + constraint->alg ); + psa_algorithm_t intersection_alg2 = + psa_key_policy_algorithm_intersection( key_type, policy->alg2, + constraint->alg2 ); + if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + policy->usage &= constraint->usage; + policy->alg = intersection_alg; + policy->alg2 = intersection_alg2; + return( PSA_SUCCESS ); +} + +/** Get the description of a key given its identifier and policy constraints + * and lock it. + * + * The key must have allow all the usage flags set in \p usage. If \p alg is + * nonzero, the key must allow operations with this algorithm. If \p alg is + * zero, the algorithm is not checked. + * + * In case of a persistent key, the function loads the description of the key + * into a key slot if not already done. + * + * On success, the returned key slot is locked. It is the responsibility of + * the caller to unlock the key slot when it does not access it anymore. + */ +static psa_status_t psa_get_and_lock_key_slot_with_policy( + mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + status = psa_get_and_lock_key_slot( key, p_slot ); + if( status != PSA_SUCCESS ) + return( status ); + slot = *p_slot; + + /* Enforce that usage policy for the key slot contains all the flags + * required by the usage parameter. There is one exception: public + * keys can always be exported, so we treat public key objects as + * if they had the export flag. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) ) + usage &= ~PSA_KEY_USAGE_EXPORT; + + if( ( slot->attr.policy.usage & usage ) != usage ) + { + status = PSA_ERROR_NOT_PERMITTED; + goto error; + } + + /* Enforce that the usage policy permits the requested algortihm. */ + if( alg != 0 ) + { + status = psa_key_policy_permits( &slot->attr.policy, + slot->attr.type, + alg ); + if( status != PSA_SUCCESS ) + goto error; + } + + return( PSA_SUCCESS ); + +error: + *p_slot = NULL; + psa_unlock_key_slot( slot ); + + return( status ); +} + +/** Get a key slot containing a transparent key and lock it. + * + * A transparent key is a key for which the key material is directly + * available, as opposed to a key in a secure element and/or to be used + * by a secure element. + * + * This is a temporary function that may be used instead of + * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support + * for a cryptographic operation. + * + * On success, the returned key slot is locked. It is the responsibility of the + * caller to unlock the key slot when it does not access it anymore. + */ +static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( + mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot, + psa_key_usage_t usage, + psa_algorithm_t alg ) +{ + psa_status_t status = psa_get_and_lock_key_slot_with_policy( key, p_slot, + usage, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( psa_key_lifetime_is_external( (*p_slot)->attr.lifetime ) ) + { + psa_unlock_key_slot( *p_slot ); + *p_slot = NULL; + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) +{ + /* Data pointer will always be either a valid pointer or NULL in an + * initialized slot, so we can just free it. */ + if( slot->key.data != NULL ) + mbedtls_platform_zeroize( slot->key.data, slot->key.bytes); + + mbedtls_free( slot->key.data ); + slot->key.data = NULL; + slot->key.bytes = 0; + + return( PSA_SUCCESS ); +} + +/** Completely wipe a slot in memory, including its policy. + * Persistent storage is not affected. */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = psa_remove_key_data_from_memory( slot ); + + /* + * As the return error code may not be handled in case of multiple errors, + * do our best to report an unexpected lock counter. Assert with + * MBEDTLS_TEST_HOOK_TEST_ASSERT that the lock counter is equal to one: + * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the + * function is called as part of the execution of a test suite, the + * execution of the test suite is stopped in error if the assertion fails. + */ + if( slot->lock_count != 1 ) + { + MBEDTLS_TEST_HOOK_TEST_ASSERT( slot->lock_count == 1 ); + status = PSA_ERROR_CORRUPTION_DETECTED; + } + + /* Multipart operations may still be using the key. This is safe + * because all multipart operation objects are independent from + * the key slot: if they need to access the key after the setup + * phase, they have a copy of the key. Note that this means that + * key material can linger until all operations are completed. */ + /* At this point, key material and other type-specific content has + * been wiped. Clear remaining metadata. We can call memset and not + * zeroize because the metadata is not particularly sensitive. */ + memset( slot, 0, sizeof( *slot ) ); + return( status ); +} + +psa_status_t psa_destroy_key( mbedtls_svc_key_id_t key ) +{ + psa_key_slot_t *slot; + psa_status_t status; /* status of the last operation */ + psa_status_t overall_status = PSA_SUCCESS; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_se_drv_table_entry_t *driver; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( mbedtls_svc_key_id_is_null( key ) ) + return( PSA_SUCCESS ); + + /* + * Get the description of the key in a key slot. In case of a persistent + * key, this will load the key description from persistent memory if not + * done yet. We cannot avoid this loading as without it we don't know if + * the key is operated by an SE or not and this information is needed by + * the current implementation. + */ + status = psa_get_and_lock_key_slot( key, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + /* + * If the key slot containing the key description is under access by the + * library (apart from the present access), the key cannot be destroyed + * yet. For the time being, just return in error. Eventually (to be + * implemented), the key should be destroyed when all accesses have + * stopped. + */ + if( slot->lock_count > 1 ) + { + psa_unlock_key_slot( slot ); + return( PSA_ERROR_GENERIC_ERROR ); + } + + if( PSA_KEY_LIFETIME_IS_READ_ONLY( slot->attr.lifetime ) ) + { + /* Refuse the destruction of a read-only key (which may or may not work + * if we attempt it, depending on whether the key is merely read-only + * by policy or actually physically read-only). + * Just do the best we can, which is to wipe the copy in memory + * (done in this function's cleanup code). */ + overall_status = PSA_ERROR_NOT_PERMITTED; + goto exit; + } + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + driver = psa_get_se_driver_entry( slot->attr.lifetime ); + if( driver != NULL ) + { + /* For a key in a secure element, we need to do three things: + * remove the key file in internal storage, destroy the + * key inside the secure element, and update the driver's + * persistent data. Start a transaction that will encompass these + * three actions. */ + psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_DESTROY_KEY ); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number( slot ); + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction( ); + if( status != PSA_SUCCESS ) + { + (void) psa_crypto_stop_transaction( ); + /* We should still try to destroy the key in the secure + * element and the key metadata in storage. This is especially + * important if the error is that the storage is full. + * But how to do it exactly without risking an inconsistent + * state after a reset? + * https://github.com/ARMmbed/mbed-crypto/issues/215 + */ + overall_status = status; + goto exit; + } + + status = psa_destroy_se_key( driver, + psa_key_slot_get_slot_number( slot ) ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) + { + status = psa_destroy_persistent_key( slot->attr.id ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + + /* TODO: other slots may have a copy of the same key. We should + * invalidate them. + * https://github.com/ARMmbed/mbed-crypto/issues/214 + */ + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + status = psa_save_se_persistent_data( driver ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + status = psa_crypto_stop_transaction( ); + if( overall_status == PSA_SUCCESS ) + overall_status = status; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +exit: + status = psa_wipe_key_slot( slot ); + /* Prioritize CORRUPTION_DETECTED from wiping over a storage error */ + if( status != PSA_SUCCESS ) + overall_status = status; + return( overall_status ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) +static psa_status_t psa_get_rsa_public_exponent( + const mbedtls_rsa_context *rsa, + psa_key_attributes_t *attributes ) +{ + mbedtls_mpi mpi; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint8_t *buffer = NULL; + size_t buflen; + mbedtls_mpi_init( &mpi ); + + ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &mpi ); + if( ret != 0 ) + goto exit; + if( mbedtls_mpi_cmp_int( &mpi, 65537 ) == 0 ) + { + /* It's the default value, which is reported as an empty string, + * so there's nothing to do. */ + goto exit; + } + + buflen = mbedtls_mpi_size( &mpi ); + buffer = mbedtls_calloc( 1, buflen ); + if( buffer == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto exit; + } + ret = mbedtls_mpi_write_binary( &mpi, buffer, buflen ); + if( ret != 0 ) + goto exit; + attributes->domain_parameters = buffer; + attributes->domain_parameters_size = buflen; + +exit: + mbedtls_mpi_free( &mpi ); + if( ret != 0 ) + mbedtls_free( buffer ); + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +/** Retrieve all the publicly-accessible attributes of a key. + */ +psa_status_t psa_get_key_attributes( mbedtls_svc_key_id_t key, + psa_key_attributes_t *attributes ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + psa_reset_key_attributes( attributes ); + + status = psa_get_and_lock_key_slot_with_policy( key, &slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + + attributes->core = slot->attr; + attributes->core.flags &= ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | + MBEDTLS_PSA_KA_MASK_DUAL_USE ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( psa_get_se_driver_entry( slot->attr.lifetime ) != NULL ) + psa_set_key_slot_number( attributes, + psa_key_slot_get_slot_number( slot ) ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( slot->attr.type ) + { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + case PSA_KEY_TYPE_RSA_KEY_PAIR: + case PSA_KEY_TYPE_RSA_PUBLIC_KEY: + /* TODO: reporting the public exponent for opaque keys + * is not yet implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/216 + */ + if( ! psa_key_lifetime_is_external( slot->attr.lifetime ) ) + { + mbedtls_rsa_context *rsa = NULL; + + status = mbedtls_psa_rsa_load_representation( + slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + break; + + status = psa_get_rsa_public_exponent( rsa, + attributes ); + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + } + break; +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + default: + /* Nothing else to do. */ + break; + } + + if( status != PSA_SUCCESS ) + psa_reset_key_attributes( attributes ); + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t psa_get_key_slot_number( + const psa_key_attributes_t *attributes, + psa_key_slot_number_t *slot_number ) +{ + if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER ) + { + *slot_number = attributes->slot_number; + return( PSA_SUCCESS ); + } + else + return( PSA_ERROR_INVALID_ARGUMENT ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +static psa_status_t psa_export_key_buffer_internal( const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + if( key_buffer_size > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + memcpy( data, key_buffer, key_buffer_size ); + memset( data + key_buffer_size, 0, + data_size - key_buffer_size ); + *data_length = key_buffer_size; + return( PSA_SUCCESS ); +} + +psa_status_t psa_export_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + psa_key_type_t type = attributes->core.type; + + if( key_type_is_raw_bytes( type ) || + PSA_KEY_TYPE_IS_RSA( type ) || + PSA_KEY_TYPE_IS_ECC( type ) ) + { + return( psa_export_key_buffer_internal( + key_buffer, key_buffer_size, + data, data_size, data_length ) ); + } + else + { + /* This shouldn't happen in the reference implementation, but + it is valid for a special-purpose implementation to omit + support for exporting certain key types. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +psa_status_t psa_export_key( mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Export requires the EXPORT flag. There is an exception for public keys, + * which don't require any flag, but + * psa_get_and_lock_key_slot_with_policy() takes care of this. + */ + status = psa_get_and_lock_key_slot_with_policy( key, &slot, + PSA_KEY_USAGE_EXPORT, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + status = psa_driver_wrapper_export_key( &attributes, + slot->key.data, slot->key.bytes, + data, data_size, data_length ); + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +psa_status_t psa_export_public_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_key_type_t type = attributes->core.type; + + if( PSA_KEY_TYPE_IS_RSA( type ) || PSA_KEY_TYPE_IS_ECC( type ) ) + { + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Exporting public -> public */ + return( psa_export_key_buffer_internal( + key_buffer, key_buffer_size, + data, data_size, data_length ) ); + } + + if( PSA_KEY_TYPE_IS_RSA( type ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + return( mbedtls_psa_rsa_export_public_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); +#else + /* We don't know how to convert a private RSA key to public. */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + } + else + { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + return( mbedtls_psa_ecp_export_public_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); +#else + /* We don't know how to convert a private ECC key to public */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ + } + } + else + { + /* This shouldn't happen in the reference implementation, but + it is valid for a special-purpose implementation to omit + support for exporting certain key types. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +psa_status_t psa_export_public_key( mbedtls_svc_key_id_t key, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + /* Reject a zero-length output buffer now, since this can never be a + * valid key representation. This way we know that data must be a valid + * pointer and we can do things like memset(data, ..., data_size). */ + if( data_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + /* Set the key to empty now, so that even when there are errors, we always + * set data_length to a value between 0 and data_size. On error, setting + * the key to empty is a good choice because an empty key representation is + * unlikely to be accepted anywhere. */ + *data_length = 0; + + /* Exporting a public key doesn't require a usage flag. */ + status = psa_get_and_lock_key_slot_with_policy( key, &slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + + if( ! PSA_KEY_TYPE_IS_ASYMMETRIC( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + status = psa_driver_wrapper_export_public_key( + &attributes, slot->key.data, slot->key.bytes, + data, data_size, data_length ); + +exit: + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +#if defined(static_assert) +static_assert( ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, + "One or more key attribute flag is listed as both external-only and dual-use" ); +static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0, + "One or more key attribute flag is listed as both internal-only and dual-use" ); +static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ) == 0, + "One or more key attribute flag is listed as both internal-only and external-only" ); +#endif + +/** Validate that a key policy is internally well-formed. + * + * This function only rejects invalid policies. It does not validate the + * consistency of the policy with respect to other attributes of the key + * such as the key type. + */ +static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy ) +{ + if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT | + PSA_KEY_USAGE_COPY | + PSA_KEY_USAGE_ENCRYPT | + PSA_KEY_USAGE_DECRYPT | + PSA_KEY_USAGE_SIGN_MESSAGE | + PSA_KEY_USAGE_VERIFY_MESSAGE | + PSA_KEY_USAGE_SIGN_HASH | + PSA_KEY_USAGE_VERIFY_HASH | + PSA_KEY_USAGE_VERIFY_DERIVATION | + PSA_KEY_USAGE_DERIVE ) ) != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Validate the internal consistency of key attributes. + * + * This function only rejects invalid attribute values. If does not + * validate the consistency of the attributes with any key data that may + * be involved in the creation of the key. + * + * Call this function early in the key creation process. + * + * \param[in] attributes Key attributes for the new key. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + */ +static psa_status_t psa_validate_key_attributes( + const psa_key_attributes_t *attributes, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_lifetime_t lifetime = psa_get_key_lifetime( attributes ); + mbedtls_svc_key_id_t key = psa_get_key_id( attributes ); + + status = psa_validate_key_location( lifetime, p_drv ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_validate_key_persistence( lifetime ); + if( status != PSA_SUCCESS ) + return( status ); + + if ( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) ) + { + if( MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ) != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else + { + if( !psa_is_valid_key_id( psa_get_key_id( attributes ), 0 ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + status = psa_validate_key_policy( &attributes->core.policy ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Refuse to create overly large keys. + * Note that this doesn't trigger on import if the attributes don't + * explicitly specify a size (so psa_get_key_bits returns 0), so + * psa_import_key() needs its own checks. */ + if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Reject invalid flags. These should not be reachable through the API. */ + if( attributes->core.flags & ~ ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY | + MBEDTLS_PSA_KA_MASK_DUAL_USE ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/** Prepare a key slot to receive key material. + * + * This function allocates a key slot and sets its metadata. + * + * If this function fails, call psa_fail_key_creation(). + * + * This function is intended to be used as follows: + * -# Call psa_start_key_creation() to allocate a key slot, prepare + * it with the specified attributes, and in case of a volatile key assign it + * a volatile key identifier. + * -# Populate the slot with the key material. + * -# Call psa_finish_key_creation() to finalize the creation of the slot. + * In case of failure at any step, stop the sequence and call + * psa_fail_key_creation(). + * + * On success, the key slot is locked. It is the responsibility of the caller + * to unlock the key slot when it does not access it anymore. + * + * \param method An identification of the calling function. + * \param[in] attributes Key attributes for the new key. + * \param[out] p_slot On success, a pointer to the prepared slot. + * \param[out] p_drv On any return, the driver for the key, if any. + * NULL for a transparent key. + * + * \retval #PSA_SUCCESS + * The key slot is ready to receive key material. + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_start_key_creation( + psa_key_creation_method_t method, + const psa_key_attributes_t *attributes, + psa_key_slot_t **p_slot, + psa_se_drv_table_entry_t **p_drv ) +{ + psa_status_t status; + psa_key_id_t volatile_key_id; + psa_key_slot_t *slot; + + (void) method; + *p_drv = NULL; + + status = psa_validate_key_attributes( attributes, p_drv ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_get_empty_key_slot( &volatile_key_id, p_slot ); + if( status != PSA_SUCCESS ) + return( status ); + slot = *p_slot; + + /* We're storing the declared bit-size of the key. It's up to each + * creation mechanism to verify that this information is correct. + * It's automatically correct for mechanisms that use the bit-size as + * an input (generate, device) but not for those where the bit-size + * is optional (import, copy). In case of a volatile key, assign it the + * volatile key identifier associated to the slot returned to contain its + * definition. */ + + slot->attr = attributes->core; + if( PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) + { +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + slot->attr.id = volatile_key_id; +#else + slot->attr.id.key_id = volatile_key_id; +#endif + } + + /* Erase external-only flags from the internal copy. To access + * external-only flags, query `attributes`. Thanks to the check + * in psa_validate_key_attributes(), this leaves the dual-use + * flags and any internal flag that psa_get_empty_key_slot() + * may have set. */ + slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* For a key in a secure element, we need to do three things + * when creating or registering a persistent key: + * create the key file in internal storage, create the + * key inside the secure element, and update the driver's + * persistent data. This is done by starting a transaction that will + * encompass these three actions. + * For registering a volatile key, we just need to find an appropriate + * slot number inside the SE. Since the key is designated volatile, creating + * a transaction is not required. */ + /* The first thing to do is to find a slot number for the new key. + * We save the slot number in persistent storage as part of the + * transaction data. It will be needed to recover if the power + * fails during the key creation process, to clean up on the secure + * element side after restarting. Obtaining a slot number from the + * secure element driver updates its persistent state, but we do not yet + * save the driver's persistent state, so that if the power fails, + * we can roll back to a state where the key doesn't exist. */ + if( *p_drv != NULL ) + { + psa_key_slot_number_t slot_number; + status = psa_find_se_slot_for_key( attributes, method, *p_drv, + &slot_number ); + if( status != PSA_SUCCESS ) + return( status ); + + if( ! PSA_KEY_LIFETIME_IS_VOLATILE( attributes->core.lifetime ) ) + { + psa_crypto_prepare_transaction( PSA_CRYPTO_TRANSACTION_CREATE_KEY ); + psa_crypto_transaction.key.lifetime = slot->attr.lifetime; + psa_crypto_transaction.key.slot = slot_number; + psa_crypto_transaction.key.id = slot->attr.id; + status = psa_crypto_save_transaction( ); + if( status != PSA_SUCCESS ) + { + (void) psa_crypto_stop_transaction( ); + return( status ); + } + } + + status = psa_copy_key_material_into_slot( + slot, (uint8_t *)( &slot_number ), sizeof( slot_number ) ); + } + + if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER ) + { + /* Key registration only makes sense with a secure element. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + return( PSA_SUCCESS ); +} + +/** Finalize the creation of a key once its key material has been set. + * + * This entails writing the key to persistent storage. + * + * If this function fails, call psa_fail_key_creation(). + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * If the finalization succeeds, the function unlocks the key slot (it was + * locked by psa_start_key_creation()) and the key slot cannot be accessed + * anymore as part of the key creation process. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + * \param[out] key On success, identifier of the key. Note that the + * key identifier is also stored in the key slot. + * + * \retval #PSA_SUCCESS + * The key was successfully created. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_ALREADY_EXISTS + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_STORAGE_FAILURE + * + * \return If this function fails, the key slot is an invalid state. + * You must call psa_fail_key_creation() to wipe and free the slot. + */ +static psa_status_t psa_finish_key_creation( + psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver, + mbedtls_svc_key_id_t *key) +{ + psa_status_t status = PSA_SUCCESS; + (void) slot; + (void) driver; + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) + { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + psa_se_key_data_storage_t data; + psa_key_slot_number_t slot_number = + psa_key_slot_get_slot_number( slot ) ; + +#if defined(static_assert) + static_assert( sizeof( slot_number ) == + sizeof( data.slot_number ), + "Slot number size does not match psa_se_key_data_storage_t" ); +#endif + memcpy( &data.slot_number, &slot_number, sizeof( slot_number ) ); + status = psa_save_persistent_key( &slot->attr, + (uint8_t*) &data, + sizeof( data ) ); + } + else +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + { + /* Key material is saved in export representation in the slot, so + * just pass the slot buffer for storage. */ + status = psa_save_persistent_key( &slot->attr, + slot->key.data, + slot->key.bytes ); + } + } +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Finish the transaction for a key creation. This does not + * happen when registering an existing key. Detect this case + * by checking whether a transaction is in progress (actual + * creation of a persistent key in a secure element requires a transaction, + * but registration or volatile key creation doesn't use one). */ + if( driver != NULL && + psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY ) + { + status = psa_save_se_persistent_data( driver ); + if( status != PSA_SUCCESS ) + { + psa_destroy_persistent_key( slot->attr.id ); + return( status ); + } + status = psa_crypto_stop_transaction( ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + if( status == PSA_SUCCESS ) + { + *key = slot->attr.id; + status = psa_unlock_key_slot( slot ); + if( status != PSA_SUCCESS ) + *key = MBEDTLS_SVC_KEY_ID_INIT; + } + + return( status ); +} + +/** Abort the creation of a key. + * + * You may call this function after calling psa_start_key_creation(), + * or after psa_finish_key_creation() fails. In other circumstances, this + * function may not clean up persistent storage. + * See the documentation of psa_start_key_creation() for the intended use + * of this function. + * + * \param[in,out] slot Pointer to the slot with key material. + * \param[in] driver The secure element driver for the key, + * or NULL for a transparent key. + */ +static void psa_fail_key_creation( psa_key_slot_t *slot, + psa_se_drv_table_entry_t *driver ) +{ + (void) driver; + + if( slot == NULL ) + return; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* TODO: If the key has already been created in the secure + * element, and the failure happened later (when saving metadata + * to internal storage), we need to destroy the key in the secure + * element. + * https://github.com/ARMmbed/mbed-crypto/issues/217 + */ + + /* Abort the ongoing transaction if any (there may not be one if + * the creation process failed before starting one, or if the + * key creation is a registration of a key in a secure element). + * Earlier functions must already have done what it takes to undo any + * partial creation. All that's left is to update the transaction data + * itself. */ + (void) psa_crypto_stop_transaction( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + psa_wipe_key_slot( slot ); +} + +/** Validate optional attributes during key creation. + * + * Some key attributes are optional during key creation. If they are + * specified in the attributes structure, check that they are consistent + * with the data in the slot. + * + * This function should be called near the end of key creation, after + * the slot in memory is fully populated but before saving persistent data. + */ +static psa_status_t psa_validate_optional_attributes( + const psa_key_slot_t *slot, + const psa_key_attributes_t *attributes ) +{ + if( attributes->core.type != 0 ) + { + if( attributes->core.type != slot->attr.type ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + if( attributes->domain_parameters_size != 0 ) + { +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { + mbedtls_rsa_context *rsa = NULL; + mbedtls_mpi actual, required; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + psa_status_t status = mbedtls_psa_rsa_load_representation( + slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + mbedtls_mpi_init( &actual ); + mbedtls_mpi_init( &required ); + ret = mbedtls_rsa_export( rsa, + NULL, NULL, NULL, NULL, &actual ); + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + if( ret != 0 ) + goto rsa_exit; + ret = mbedtls_mpi_read_binary( &required, + attributes->domain_parameters, + attributes->domain_parameters_size ); + if( ret != 0 ) + goto rsa_exit; + if( mbedtls_mpi_cmp_mpi( &actual, &required ) != 0 ) + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + rsa_exit: + mbedtls_mpi_free( &actual ); + mbedtls_mpi_free( &required ); + if( ret != 0) + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + + if( attributes->core.bits != 0 ) + { + if( attributes->core.bits != slot->attr.bits ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_import_key( const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + mbedtls_svc_key_id_t *key ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + size_t bits; + size_t storage_size = data_length; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject zero-length symmetric keys (including raw data key objects). + * This also rejects any key which might be encoded as an empty string, + * which is never valid. */ + if( data_length == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Ensure that the bytes-to-bits conversion cannot overflow. */ + if( data_length > SIZE_MAX / 8 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_IMPORT, attributes, + &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + + /* In the case of a transparent key or an opaque key stored in local + * storage ( thus not in the case of importing a key in a secure element + * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a + * buffer to hold the imported key material. */ + if( slot->key.data == NULL ) + { + if( psa_key_lifetime_is_external( attributes->core.lifetime ) ) + { + status = psa_driver_wrapper_get_key_buffer_size_from_key_data( + attributes, data, data_length, &storage_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + status = psa_allocate_buffer_to_slot( slot, storage_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + + bits = slot->attr.bits; + status = psa_driver_wrapper_import_key( attributes, + data, data_length, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits ); + if( status != PSA_SUCCESS ) + goto exit; + + if( slot->attr.bits == 0 ) + slot->attr.bits = (psa_key_bits_t) bits; + else if( bits != slot->attr.bits ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Enforce a size limit, and in particular ensure that the bit + * size fits in its representation type.*/ + if( bits > PSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_validate_optional_attributes( slot, attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot, driver, key ); +exit: + if( status != PSA_SUCCESS ) + psa_fail_key_creation( slot, driver ); + + return( status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +psa_status_t mbedtls_psa_register_se_key( + const psa_key_attributes_t *attributes ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Leaving attributes unspecified is not currently supported. + * It could make sense to query the key type and size from the + * secure element, but not all secure elements support this + * and the driver HAL doesn't currently support it. */ + if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_NONE ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_REGISTER, attributes, + &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_finish_key_creation( slot, driver, &key ); + +exit: + if( status != PSA_SUCCESS ) + psa_fail_key_creation( slot, driver ); + + /* Registration doesn't keep the key in RAM. */ + psa_close_key( key ); + return( status ); +} +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +psa_status_t psa_copy_key( mbedtls_svc_key_id_t source_key, + const psa_key_attributes_t *specified_attributes, + mbedtls_svc_key_id_t *target_key ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *source_slot = NULL; + psa_key_slot_t *target_slot = NULL; + psa_key_attributes_t actual_attributes = *specified_attributes; + psa_se_drv_table_entry_t *driver = NULL; + size_t storage_size = 0; + + *target_key = MBEDTLS_SVC_KEY_ID_INIT; + + status = psa_get_and_lock_key_slot_with_policy( + source_key, &source_slot, PSA_KEY_USAGE_COPY, 0 ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_validate_optional_attributes( source_slot, + specified_attributes ); + if( status != PSA_SUCCESS ) + goto exit; + + /* The target key type and number of bits have been validated by + * psa_validate_optional_attributes() to be either equal to zero or + * equal to the ones of the source key. So it is safe to inherit + * them from the source key now." + * */ + actual_attributes.core.bits = source_slot->attr.bits; + actual_attributes.core.type = source_slot->attr.type; + + + status = psa_restrict_key_policy( source_slot->attr.type, + &actual_attributes.core.policy, + &source_slot->attr.policy ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_start_key_creation( PSA_KEY_CREATION_COPY, &actual_attributes, + &target_slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + if( PSA_KEY_LIFETIME_GET_LOCATION( target_slot->attr.lifetime ) != + PSA_KEY_LIFETIME_GET_LOCATION( source_slot->attr.lifetime ) ) + { + /* + * If the source and target keys are stored in different locations, + * the source key would need to be exported as plaintext and re-imported + * in the other location. This has security implications which have not + * been fully mapped. For now, this can be achieved through + * appropriate API invocations from the application, if needed. + * */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + /* + * When the source and target keys are within the same location, + * - For transparent keys it is a blind copy without any driver invocation, + * - For opaque keys this translates to an invocation of the drivers' + * copy_key entry point through the dispatch layer. + * */ + if( psa_key_lifetime_is_external( actual_attributes.core.lifetime ) ) + { + status = psa_driver_wrapper_get_key_buffer_size( &actual_attributes, + &storage_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_allocate_buffer_to_slot( target_slot, storage_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_driver_wrapper_copy_key( &actual_attributes, + source_slot->key.data, + source_slot->key.bytes, + target_slot->key.data, + target_slot->key.bytes, + &target_slot->key.bytes ); + if( status != PSA_SUCCESS ) + goto exit; + } + else + { + status = psa_copy_key_material_into_slot( target_slot, + source_slot->key.data, + source_slot->key.bytes ); + if( status != PSA_SUCCESS ) + goto exit; + } + status = psa_finish_key_creation( target_slot, driver, target_key ); +exit: + if( status != PSA_SUCCESS ) + psa_fail_key_creation( target_slot, driver ); + + unlock_status = psa_unlock_key_slot( source_slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + + + +/****************************************************************/ +/* Message digests */ +/****************************************************************/ + +psa_status_t psa_hash_abort( psa_hash_operation_t *operation ) +{ + /* Aborting a non-active operation is allowed */ + if( operation->id == 0 ) + return( PSA_SUCCESS ); + + psa_status_t status = psa_driver_wrapper_hash_abort( operation ); + operation->id = 0; + + return( status ); +} + +psa_status_t psa_hash_setup( psa_hash_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if( operation->id != 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( !PSA_ALG_IS_HASH( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only + * directly zeroes the int-sized dummy member of the context union. */ + memset( &operation->ctx, 0, sizeof( operation->ctx ) ); + + status = psa_driver_wrapper_hash_setup( operation, alg ); + +exit: + if( status != PSA_SUCCESS ) + psa_hash_abort( operation ); + + return status; +} + +psa_status_t psa_hash_update( psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* Don't require hash implementations to behave correctly on a + * zero-length input, which may have an invalid pointer. */ + if( input_length == 0 ) + return( PSA_SUCCESS ); + + status = psa_driver_wrapper_hash_update( operation, input, input_length ); + +exit: + if( status != PSA_SUCCESS ) + psa_hash_abort( operation ); + + return( status ); +} + +psa_status_t psa_hash_finish( psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ) +{ + *hash_length = 0; + if( operation->id == 0 ) + return( PSA_ERROR_BAD_STATE ); + + psa_status_t status = psa_driver_wrapper_hash_finish( + operation, hash, hash_size, hash_length ); + psa_hash_abort( operation ); + return( status ); +} + +psa_status_t psa_hash_verify( psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length ) +{ + uint8_t actual_hash[PSA_HASH_MAX_SIZE]; + size_t actual_hash_length; + psa_status_t status = psa_hash_finish( + operation, + actual_hash, sizeof( actual_hash ), + &actual_hash_length ); + + if( status != PSA_SUCCESS ) + goto exit; + + if( actual_hash_length != hash_length ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + + if( mbedtls_psa_safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + +exit: + mbedtls_platform_zeroize( actual_hash, sizeof( actual_hash ) ); + if( status != PSA_SUCCESS ) + psa_hash_abort(operation); + + return( status ); +} + +psa_status_t psa_hash_compute( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + uint8_t *hash, size_t hash_size, + size_t *hash_length ) +{ + *hash_length = 0; + if( !PSA_ALG_IS_HASH( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( psa_driver_wrapper_hash_compute( alg, input, input_length, + hash, hash_size, hash_length ) ); +} + +psa_status_t psa_hash_compare( psa_algorithm_t alg, + const uint8_t *input, size_t input_length, + const uint8_t *hash, size_t hash_length ) +{ + uint8_t actual_hash[PSA_HASH_MAX_SIZE]; + size_t actual_hash_length; + + if( !PSA_ALG_IS_HASH( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + psa_status_t status = psa_driver_wrapper_hash_compute( + alg, input, input_length, + actual_hash, sizeof(actual_hash), + &actual_hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + if( actual_hash_length != hash_length ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + if( mbedtls_psa_safer_memcmp( hash, actual_hash, actual_hash_length ) != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + +exit: + mbedtls_platform_zeroize( actual_hash, sizeof( actual_hash ) ); + return( status ); +} + +psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation ) +{ + if( source_operation->id == 0 || + target_operation->id != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + psa_status_t status = psa_driver_wrapper_hash_clone( source_operation, + target_operation ); + if( status != PSA_SUCCESS ) + psa_hash_abort( target_operation ); + + return( status ); +} + + +/****************************************************************/ +/* MAC */ +/****************************************************************/ + +psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) +{ + /* Aborting a non-active operation is allowed */ + if( operation->id == 0 ) + return( PSA_SUCCESS ); + + psa_status_t status = psa_driver_wrapper_mac_abort( operation ); + operation->mac_size = 0; + operation->is_sign = 0; + operation->id = 0; + + return( status ); +} + +static psa_status_t psa_mac_finalize_alg_and_key_validation( + psa_algorithm_t alg, + const psa_key_attributes_t *attributes, + uint8_t *mac_size ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t key_type = psa_get_key_type( attributes ); + size_t key_bits = psa_get_key_bits( attributes ); + + if( ! PSA_ALG_IS_MAC( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Validate the combination of key type and algorithm */ + status = psa_mac_key_can_do( alg, key_type ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Get the output length for the algorithm and key combination */ + *mac_size = PSA_MAC_LENGTH( key_type, key_bits, alg ); + + if( *mac_size < 4 ) + { + /* A very short MAC is too short for security since it can be + * brute-forced. Ancient protocols with 32-bit MACs do exist, + * so we make this our minimum, even though 32 bits is still + * too small for security. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( *mac_size > PSA_MAC_LENGTH( key_type, key_bits, + PSA_ALG_FULL_LENGTH_MAC( alg ) ) ) + { + /* It's impossible to "truncate" to a larger length than the full length + * of the algorithm. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + int is_sign ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + /* A context must be freshly initialized before it can be set up. */ + if( operation->id != 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy( + key, + &slot, + is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + status = psa_mac_finalize_alg_and_key_validation( alg, &attributes, + &operation->mac_size ); + if( status != PSA_SUCCESS ) + goto exit; + + operation->is_sign = is_sign; + /* Dispatch the MAC setup call with validated input */ + if( is_sign ) + { + status = psa_driver_wrapper_mac_sign_setup( operation, + &attributes, + slot->key.data, + slot->key.bytes, + alg ); + } + else + { + status = psa_driver_wrapper_mac_verify_setup( operation, + &attributes, + slot->key.data, + slot->key.bytes, + alg ); + } + +exit: + if( status != PSA_SUCCESS ) + psa_mac_abort( operation ); + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, key, alg, 1 ) ); +} + +psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, key, alg, 0 ) ); +} + +psa_status_t psa_mac_update( psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + if( operation->id == 0 ) + return( PSA_ERROR_BAD_STATE ); + + /* Don't require hash implementations to behave correctly on a + * zero-length input, which may have an invalid pointer. */ + if( input_length == 0 ) + return( PSA_SUCCESS ); + + psa_status_t status = psa_driver_wrapper_mac_update( operation, + input, input_length ); + if( status != PSA_SUCCESS ) + psa_mac_abort( operation ); + + return( status ); +} + +psa_status_t psa_mac_sign_finish( psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( ! operation->is_sign ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL) + * once all the error checks are done. */ + if( operation->mac_size == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( mac_size < operation->mac_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_driver_wrapper_mac_sign_finish( operation, + mac, operation->mac_size, + mac_length ); + +exit: + /* In case of success, set the potential excess room in the output buffer + * to an invalid value, to avoid potentially leaking a longer MAC. + * In case of error, set the output length and content to a safe default, + * such that in case the caller misses an error check, the output would be + * an unachievable MAC. + */ + if( status != PSA_SUCCESS ) + { + *mac_length = mac_size; + operation->mac_size = 0; + } + + if( mac_size > operation->mac_size ) + memset( &mac[operation->mac_size], '!', + mac_size - operation->mac_size ); + + abort_status = psa_mac_abort( operation ); + + return( status == PSA_SUCCESS ? abort_status : status ); +} + +psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->is_sign ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->mac_size != mac_length ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + + status = psa_driver_wrapper_mac_verify_finish( operation, + mac, mac_length ); + +exit: + abort_status = psa_mac_abort( operation ); + + return( status == PSA_SUCCESS ? abort_status : status ); +} + +static psa_status_t psa_mac_compute_internal( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length, + int is_sign ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + uint8_t operation_mac_size = 0; + + status = psa_get_and_lock_key_slot_with_policy( + key, + &slot, + is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + status = psa_mac_finalize_alg_and_key_validation( alg, &attributes, + &operation_mac_size ); + if( status != PSA_SUCCESS ) + goto exit; + + if( mac_size < operation_mac_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_driver_wrapper_mac_compute( + &attributes, + slot->key.data, slot->key.bytes, + alg, + input, input_length, + mac, operation_mac_size, mac_length ); + +exit: + /* In case of success, set the potential excess room in the output buffer + * to an invalid value, to avoid potentially leaking a longer MAC. + * In case of error, set the output length and content to a safe default, + * such that in case the caller misses an error check, the output would be + * an unachievable MAC. + */ + if( status != PSA_SUCCESS ) + { + *mac_length = mac_size; + operation_mac_size = 0; + } + if( mac_size > operation_mac_size ) + memset( &mac[operation_mac_size], '!', mac_size - operation_mac_size ); + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +psa_status_t psa_mac_compute( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + return( psa_mac_compute_internal( key, alg, + input, input_length, + mac, mac_size, mac_length, 1 ) ); +} + +psa_status_t psa_mac_verify( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + size_t mac_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t actual_mac[PSA_MAC_MAX_SIZE]; + size_t actual_mac_length; + + status = psa_mac_compute_internal( key, alg, + input, input_length, + actual_mac, sizeof( actual_mac ), + &actual_mac_length, 0 ); + if( status != PSA_SUCCESS ) + goto exit; + + if( mac_length != actual_mac_length ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + if( mbedtls_psa_safer_memcmp( mac, actual_mac, actual_mac_length ) != 0 ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + +exit: + mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); + + return ( status ); +} + +/****************************************************************/ +/* Asymmetric cryptography */ +/****************************************************************/ + +static psa_status_t psa_sign_verify_check_alg( int input_is_message, + psa_algorithm_t alg ) +{ + if( input_is_message ) + { + if( ! PSA_ALG_IS_SIGN_MESSAGE( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if ( PSA_ALG_IS_SIGN_HASH( alg ) ) + { + if( ! PSA_ALG_IS_HASH( PSA_ALG_SIGN_GET_HASH( alg ) ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + else + { + if( ! PSA_ALG_IS_SIGN_HASH( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_sign_internal( mbedtls_svc_key_id_t key, + int input_is_message, + psa_algorithm_t alg, + const uint8_t * input, + size_t input_length, + uint8_t * signature, + size_t signature_size, + size_t * signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + *signature_length = 0; + + status = psa_sign_verify_check_alg( input_is_message, alg ); + if( status != PSA_SUCCESS ) + return status; + + /* Immediately reject a zero-length signature buffer. This guarantees + * that signature must be a valid pointer. (On the other hand, the input + * buffer can in principle be empty since it doesn't actually have + * to be a hash.) */ + if( signature_size == 0 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, + input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE : + PSA_KEY_USAGE_SIGN_HASH, + alg ); + + if( status != PSA_SUCCESS ) + goto exit; + + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + if( input_is_message ) + { + status = psa_driver_wrapper_sign_message( + &attributes, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_size, signature_length ); + } + else + { + + status = psa_driver_wrapper_sign_hash( + &attributes, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_size, signature_length ); + } + + +exit: + /* Fill the unused part of the output buffer (the whole buffer on error, + * the trailing part on success) with something that isn't a valid signature + * (barring an attack on the signature and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + if( status == PSA_SUCCESS ) + memset( signature + *signature_length, '!', + signature_size - *signature_length ); + else + memset( signature, '!', signature_size ); + /* If signature_size is 0 then we have nothing to do. We must not call + * memset because signature may be NULL in this case. */ + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +static psa_status_t psa_verify_internal( mbedtls_svc_key_id_t key, + int input_is_message, + psa_algorithm_t alg, + const uint8_t * input, + size_t input_length, + const uint8_t * signature, + size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + status = psa_sign_verify_check_alg( input_is_message, alg ); + if( status != PSA_SUCCESS ) + return status; + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, + input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE : + PSA_KEY_USAGE_VERIFY_HASH, + alg ); + + if( status != PSA_SUCCESS ) + return( status ); + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + if( input_is_message ) + { + status = psa_driver_wrapper_verify_message( + &attributes, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_length ); + } + else + { + status = psa_driver_wrapper_verify_hash( + &attributes, slot->key.data, slot->key.bytes, + alg, input, input_length, + signature, signature_length ); + } + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); + +} + +psa_status_t psa_sign_message_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if ( PSA_ALG_IS_SIGN_HASH( alg ) ) + { + size_t hash_length; + uint8_t hash[PSA_HASH_MAX_SIZE]; + + status = psa_driver_wrapper_hash_compute( + PSA_ALG_SIGN_GET_HASH( alg ), + input, input_length, + hash, sizeof( hash ), &hash_length ); + + if( status != PSA_SUCCESS ) + return status; + + return psa_driver_wrapper_sign_hash( + attributes, key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_size, signature_length ); + } + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_sign_message( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t * input, + size_t input_length, + uint8_t * signature, + size_t signature_size, + size_t * signature_length ) +{ + return psa_sign_internal( + key, 1, alg, input, input_length, + signature, signature_size, signature_length ); +} + +psa_status_t psa_verify_message_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if ( PSA_ALG_IS_SIGN_HASH( alg ) ) + { + size_t hash_length; + uint8_t hash[PSA_HASH_MAX_SIZE]; + + status = psa_driver_wrapper_hash_compute( + PSA_ALG_SIGN_GET_HASH( alg ), + input, input_length, + hash, sizeof( hash ), &hash_length ); + + if( status != PSA_SUCCESS ) + return status; + + return psa_driver_wrapper_verify_hash( + attributes, key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length ); + } + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_verify_message( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t * input, + size_t input_length, + const uint8_t * signature, + size_t signature_length ) +{ + return psa_verify_internal( + key, 1, alg, input, input_length, + signature, signature_length ); +} + +psa_status_t psa_sign_hash_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + if( attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) || + PSA_ALG_IS_RSA_PSS( alg) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + return( mbedtls_psa_rsa_sign_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_size, signature_length ) ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ + } + else + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + else if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) ) + { + if( PSA_ALG_IS_ECDSA( alg ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + return( mbedtls_psa_ecdsa_sign_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_size, signature_length ) ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } + else + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + + (void)key_buffer; + (void)key_buffer_size; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_size; + (void)signature_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_sign_hash( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + return psa_sign_internal( + key, 0, alg, hash, hash_length, + signature, signature_size, signature_length ); +} + +psa_status_t psa_verify_hash_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + if( PSA_KEY_TYPE_IS_RSA( attributes->core.type ) ) + { + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) || + PSA_ALG_IS_RSA_PSS( alg) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + return( mbedtls_psa_rsa_verify_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length ) ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ + } + else + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + else if( PSA_KEY_TYPE_IS_ECC( attributes->core.type ) ) + { + if( PSA_ALG_IS_ECDSA( alg ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + return( mbedtls_psa_ecdsa_verify_hash( + attributes, + key_buffer, key_buffer_size, + alg, hash, hash_length, + signature, signature_length ) ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } + else + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + } + + (void)key_buffer; + (void)key_buffer_size; + (void)hash; + (void)hash_length; + (void)signature; + (void)signature_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_verify_hash( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ) +{ + return psa_verify_internal( + key, 0, alg, hash, hash_length, + signature, signature_length ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +static int psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg, + mbedtls_rsa_context *rsa ) +{ + psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + + return( mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ) ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + +psa_status_t psa_asymmetric_encrypt( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_and_lock_transparent_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->attr.type ) || + PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if( PSA_KEY_TYPE_IS_RSA( slot->attr.type ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + mbedtls_rsa_context *rsa = NULL; + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + goto rsa_exit; + + if( output_size < mbedtls_rsa_get_len( rsa ) ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto rsa_exit; + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_encrypt( rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + input_length, + input, + output ) ); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ + } + else + if( PSA_ALG_IS_RSA_OAEP( alg ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + status = mbedtls_to_psa_error( + psa_rsa_oaep_set_padding_mode( alg, rsa ) ); + if( status != PSA_SUCCESS ) + goto rsa_exit; + + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_encrypt( rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + salt, salt_length, + input_length, + input, + output ) ); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ + } + else + { + status = PSA_ERROR_INVALID_ARGUMENT; + } +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +rsa_exit: + if( status == PSA_SUCCESS ) + *output_length = mbedtls_rsa_get_len( rsa ); + + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + } + else + { + status = PSA_ERROR_NOT_SUPPORTED; + } + +exit: + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +psa_status_t psa_asymmetric_decrypt( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + (void) input; + (void) input_length; + (void) salt; + (void) output; + (void) output_size; + + *output_length = 0; + + if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_and_lock_transparent_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DECRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + if( ! PSA_KEY_TYPE_IS_KEY_PAIR( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if( slot->attr.type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + mbedtls_rsa_context *rsa = NULL; + status = mbedtls_psa_rsa_load_representation( slot->attr.type, + slot->key.data, + slot->key.bytes, + &rsa ); + if( status != PSA_SUCCESS ) + goto exit; + + if( input_length != mbedtls_rsa_get_len( rsa ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto rsa_exit; + } +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + + if( alg == PSA_ALG_RSA_PKCS1V15_CRYPT ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) + status = mbedtls_to_psa_error( + mbedtls_rsa_pkcs1_decrypt( rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + output_length, + input, + output, + output_size ) ); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */ + } + else + if( PSA_ALG_IS_RSA_OAEP( alg ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) + status = mbedtls_to_psa_error( + psa_rsa_oaep_set_padding_mode( alg, rsa ) ); + if( status != PSA_SUCCESS ) + goto rsa_exit; + + status = mbedtls_to_psa_error( + mbedtls_rsa_rsaes_oaep_decrypt( rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + salt, salt_length, + output_length, + input, + output, + output_size ) ); +#else + status = PSA_ERROR_NOT_SUPPORTED; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */ + } + else + { + status = PSA_ERROR_INVALID_ARGUMENT; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) +rsa_exit: + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */ + } + else + { + status = PSA_ERROR_NOT_SUPPORTED; + } + +exit: + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + + + +/****************************************************************/ +/* Symmetric cryptography */ +/****************************************************************/ + +static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ? + PSA_KEY_USAGE_ENCRYPT : + PSA_KEY_USAGE_DECRYPT ); + + /* A context must be freshly initialized before it can be set up. */ + if( operation->id != 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( ! PSA_ALG_IS_CIPHER( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy( key, &slot, usage, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Initialize the operation struct members, except for id. The id member + * is used to indicate to psa_cipher_abort that there are resources to free, + * so we only set it (in the driver wrapper) after resources have been + * allocated/initialized. */ + operation->iv_set = 0; + if( alg == PSA_ALG_ECB_NO_PADDING ) + operation->iv_required = 0; + else + operation->iv_required = 1; + operation->default_iv_length = PSA_CIPHER_IV_LENGTH( slot->attr.type, alg ); + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + /* Try doing the operation through a driver before using software fallback. */ + if( cipher_operation == MBEDTLS_ENCRYPT ) + status = psa_driver_wrapper_cipher_encrypt_setup( operation, + &attributes, + slot->key.data, + slot->key.bytes, + alg ); + else + status = psa_driver_wrapper_cipher_decrypt_setup( operation, + &attributes, + slot->key.data, + slot->key.bytes, + alg ); + +exit: + if( status != PSA_SUCCESS ) + psa_cipher_abort( operation ); + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, key, alg, MBEDTLS_ENCRYPT ) ); +} + +psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, key, alg, MBEDTLS_DECRYPT ) ); +} + +psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; + size_t default_iv_length; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->iv_set || ! operation->iv_required ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + default_iv_length = operation->default_iv_length; + if( iv_size < default_iv_length ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + if( default_iv_length > PSA_CIPHER_IV_MAX_SIZE ) + { + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + status = psa_generate_random( local_iv, default_iv_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_driver_wrapper_cipher_set_iv( operation, + local_iv, default_iv_length ); + +exit: + if( status == PSA_SUCCESS ) + { + memcpy( iv, local_iv, default_iv_length ); + *iv_length = default_iv_length; + operation->iv_set = 1; + } + else + { + *iv_length = 0; + psa_cipher_abort( operation ); + } + + return( status ); +} + +psa_status_t psa_cipher_set_iv( psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->iv_set || ! operation->iv_required ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( iv_length > PSA_CIPHER_IV_MAX_SIZE ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_driver_wrapper_cipher_set_iv( operation, + iv, + iv_length ); + +exit: + if( status == PSA_SUCCESS ) + operation->iv_set = 1; + else + psa_cipher_abort( operation ); + return( status ); +} + +psa_status_t psa_cipher_update( psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->iv_required && ! operation->iv_set ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_cipher_update( operation, + input, + input_length, + output, + output_size, + output_length ); + +exit: + if( status != PSA_SUCCESS ) + psa_cipher_abort( operation ); + + return( status ); +} + +psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->iv_required && ! operation->iv_set ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_cipher_finish( operation, + output, + output_size, + output_length ); + +exit: + if( status == PSA_SUCCESS ) + return( psa_cipher_abort( operation ) ); + else + { + *output_length = 0; + (void) psa_cipher_abort( operation ); + + return( status ); + } +} + +psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) +{ + if( operation->id == 0 ) + { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + + psa_driver_wrapper_cipher_abort( operation ); + + operation->id = 0; + operation->iv_set = 0; + operation->iv_required = 0; + + return( PSA_SUCCESS ); +} + +psa_status_t psa_cipher_encrypt( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE]; + size_t default_iv_length = 0; + + if( ! PSA_ALG_IS_CIPHER( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy( key, &slot, + PSA_KEY_USAGE_ENCRYPT, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + default_iv_length = PSA_CIPHER_IV_LENGTH( slot->attr.type, alg ); + if( default_iv_length > PSA_CIPHER_IV_MAX_SIZE ) + { + status = PSA_ERROR_GENERIC_ERROR; + goto exit; + } + + if( default_iv_length > 0 ) + { + if( output_size < default_iv_length ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_generate_random( local_iv, default_iv_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = psa_driver_wrapper_cipher_encrypt( + &attributes, slot->key.data, slot->key.bytes, + alg, local_iv, default_iv_length, input, input_length, + output + default_iv_length, output_size - default_iv_length, + output_length ); + +exit: + unlock_status = psa_unlock_key_slot( slot ); + if( status == PSA_SUCCESS ) + status = unlock_status; + + if( status == PSA_SUCCESS ) + { + if( default_iv_length > 0 ) + memcpy( output, local_iv, default_iv_length ); + *output_length += default_iv_length; + } + else + *output_length = 0; + + return( status ); +} + +psa_status_t psa_cipher_decrypt( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + if( ! PSA_ALG_IS_CIPHER( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_get_and_lock_key_slot_with_policy( key, &slot, + PSA_KEY_USAGE_DECRYPT, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + if( alg == PSA_ALG_CCM_STAR_NO_TAG && input_length < PSA_BLOCK_CIPHER_BLOCK_LENGTH( slot->attr.type ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + else if ( input_length < PSA_CIPHER_IV_LENGTH( slot->attr.type, alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_driver_wrapper_cipher_decrypt( + &attributes, slot->key.data, slot->key.bytes, + alg, input, input_length, + output, output_size, output_length ); + +exit: + unlock_status = psa_unlock_key_slot( slot ); + if( status == PSA_SUCCESS ) + status = unlock_status; + + if( status != PSA_SUCCESS ) + *output_length = 0; + + return( status ); +} + + +/****************************************************************/ +/* AEAD */ +/****************************************************************/ + +/* Helper function to get the base algorithm from its variants. */ +static psa_algorithm_t psa_aead_get_base_algorithm( psa_algorithm_t alg ) +{ + return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG( alg ); +} + +/* Helper function to perform common nonce length checks. */ +static psa_status_t psa_aead_check_nonce_length( psa_algorithm_t alg, + size_t nonce_length ) +{ + psa_algorithm_t base_alg = psa_aead_get_base_algorithm( alg ); + + switch(base_alg) + { +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_GCM: + /* Not checking max nonce size here as GCM spec allows almost + * arbitrarily large nonces. Please note that we do not generally + * recommend the usage of nonces of greater length than + * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter + * size, which can then lead to collisions if you encrypt a very + * large number of messages.*/ + if( nonce_length != 0 ) + return( PSA_SUCCESS ); + break; +#endif /* PSA_WANT_ALG_GCM */ +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_CCM: + if( nonce_length >= 7 && nonce_length <= 13 ) + return( PSA_SUCCESS ); + break; +#endif /* PSA_WANT_ALG_CCM */ +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + if( nonce_length == 12 ) + return( PSA_SUCCESS ); + else if( nonce_length == 8 ) + return( PSA_ERROR_NOT_SUPPORTED ); + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_aead_encrypt( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + *ciphertext_length = 0; + + if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + status = psa_aead_check_nonce_length( alg, nonce_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_driver_wrapper_aead_encrypt( + &attributes, slot->key.data, slot->key.bytes, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length ); + + if( status != PSA_SUCCESS && ciphertext_size != 0 ) + memset( ciphertext, 0, ciphertext_size ); + +exit: + psa_unlock_key_slot( slot ); + + return( status ); +} + +psa_status_t psa_aead_decrypt( mbedtls_svc_key_id_t key, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + *plaintext_length = 0; + + if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + + status = psa_get_and_lock_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DECRYPT, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + status = psa_aead_check_nonce_length( alg, nonce_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_driver_wrapper_aead_decrypt( + &attributes, slot->key.data, slot->key.bytes, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length ); + + if( status != PSA_SUCCESS && plaintext_size != 0 ) + memset( plaintext, 0, plaintext_size ); + +exit: + psa_unlock_key_slot( slot ); + + return( status ); +} + +/* Set the key for a multipart authenticated operation. */ +static psa_status_t psa_aead_setup( psa_aead_operation_t *operation, + int is_encrypt, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + psa_key_usage_t key_usage = 0; + + if( !PSA_ALG_IS_AEAD( alg ) || PSA_ALG_IS_WILDCARD( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if( operation->id != 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->nonce_set || operation->lengths_set || + operation->ad_started || operation->body_started ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( is_encrypt ) + key_usage = PSA_KEY_USAGE_ENCRYPT; + else + key_usage = PSA_KEY_USAGE_DECRYPT; + + status = psa_get_and_lock_key_slot_with_policy( key, &slot, key_usage, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + if( is_encrypt ) + status = psa_driver_wrapper_aead_encrypt_setup( operation, + &attributes, + slot->key.data, + slot->key.bytes, + alg ); + else + status = psa_driver_wrapper_aead_decrypt_setup( operation, + &attributes, + slot->key.data, + slot->key.bytes, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + operation->key_type = psa_get_key_type( &attributes ); + +exit: + unlock_status = psa_unlock_key_slot( slot ); + + if( status == PSA_SUCCESS ) + { + status = unlock_status; + operation->alg = psa_aead_get_base_algorithm( alg ); + operation->is_encrypt = is_encrypt; + } + else + psa_aead_abort( operation ); + + return( status ); +} + +/* Set the key for a multipart authenticated encryption operation. */ +psa_status_t psa_aead_encrypt_setup( psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + return( psa_aead_setup( operation, 1, key, alg ) ); +} + +/* Set the key for a multipart authenticated decryption operation. */ +psa_status_t psa_aead_decrypt_setup( psa_aead_operation_t *operation, + mbedtls_svc_key_id_t key, + psa_algorithm_t alg ) +{ + return( psa_aead_setup( operation, 0, key, alg ) ); +} + +/* Generate a random nonce / IV for multipart AEAD operation */ +psa_status_t psa_aead_generate_nonce( psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE]; + size_t required_nonce_size; + + *nonce_length = 0; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->nonce_set || !operation->is_encrypt ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + /* For CCM, this size may not be correct according to the PSA + * specification. The PSA Crypto 1.0.1 specification states: + * + * CCM encodes the plaintext length pLen in L octets, with L the smallest + * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes. + * + * However this restriction that L has to be the smallest integer is not + * applied in practice, and it is not implementable here since the + * plaintext length may or may not be known at this time. */ + required_nonce_size = PSA_AEAD_NONCE_LENGTH( operation->key_type, + operation->alg ); + if( nonce_size < required_nonce_size ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + status = psa_generate_random( local_nonce, required_nonce_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_aead_set_nonce( operation, local_nonce, required_nonce_size ); + +exit: + if( status == PSA_SUCCESS ) + { + memcpy( nonce, local_nonce, required_nonce_size ); + *nonce_length = required_nonce_size; + } + else + psa_aead_abort( operation ); + + return( status ); +} + +/* Set the nonce for a multipart authenticated encryption or decryption + operation.*/ +psa_status_t psa_aead_set_nonce( psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->nonce_set ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_aead_check_nonce_length( operation->alg, nonce_length ); + if( status != PSA_SUCCESS ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + status = psa_driver_wrapper_aead_set_nonce( operation, nonce, + nonce_length ); + +exit: + if( status == PSA_SUCCESS ) + operation->nonce_set = 1; + else + psa_aead_abort( operation ); + + return( status ); +} + +/* Declare the lengths of the message and additional data for multipart AEAD. */ +psa_status_t psa_aead_set_lengths( psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->lengths_set || operation->ad_started || + operation->body_started ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + switch(operation->alg) + { +#if defined(PSA_WANT_ALG_GCM) + case PSA_ALG_GCM: + /* Lengths can only be too large for GCM if size_t is bigger than 32 + * bits. Without the guard this code will generate warnings on 32bit + * builds. */ +#if SIZE_MAX > UINT32_MAX + if( (( uint64_t ) ad_length ) >> 61 != 0 || + (( uint64_t ) plaintext_length ) > 0xFFFFFFFE0ull ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } +#endif + break; +#endif /* PSA_WANT_ALG_GCM */ +#if defined(PSA_WANT_ALG_CCM) + case PSA_ALG_CCM: + if( ad_length > 0xFF00 ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + break; +#endif /* PSA_WANT_ALG_CCM */ +#if defined(PSA_WANT_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + /* No length restrictions for ChaChaPoly. */ + break; +#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */ + default: + break; + } + + status = psa_driver_wrapper_aead_set_lengths( operation, ad_length, + plaintext_length ); + +exit: + if( status == PSA_SUCCESS ) + { + operation->ad_remaining = ad_length; + operation->body_remaining = plaintext_length; + operation->lengths_set = 1; + } + else + psa_aead_abort( operation ); + + return( status ); +} + +/* Pass additional data to an active multipart AEAD operation. */ +psa_status_t psa_aead_update_ad( psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( !operation->nonce_set || operation->body_started ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->lengths_set ) + { + if( operation->ad_remaining < input_length ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->ad_remaining -= input_length; + } +#if defined(PSA_WANT_ALG_CCM) + else if( operation->alg == PSA_ALG_CCM ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ + + status = psa_driver_wrapper_aead_update_ad( operation, input, + input_length ); + +exit: + if( status == PSA_SUCCESS ) + operation->ad_started = 1; + else + psa_aead_abort( operation ); + + return( status ); +} + +/* Encrypt or decrypt a message fragment in an active multipart AEAD + operation.*/ +psa_status_t psa_aead_update( psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *output_length = 0; + + if( operation->id == 0 ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( !operation->nonce_set ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + if( operation->lengths_set ) + { + /* Additional data length was supplied, but not all the additional + data was supplied.*/ + if( operation->ad_remaining != 0 ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Too much data provided. */ + if( operation->body_remaining < input_length ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + operation->body_remaining -= input_length; + } +#if defined(PSA_WANT_ALG_CCM) + else if( operation->alg == PSA_ALG_CCM ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } +#endif /* PSA_WANT_ALG_CCM */ + + status = psa_driver_wrapper_aead_update( operation, input, input_length, + output, output_size, + output_length ); + +exit: + if( status == PSA_SUCCESS ) + operation->body_started = 1; + else + psa_aead_abort( operation ); + + return( status ); +} + +static psa_status_t psa_aead_final_checks( const psa_aead_operation_t *operation ) +{ + if( operation->id == 0 || !operation->nonce_set ) + return( PSA_ERROR_BAD_STATE ); + + if( operation->lengths_set && ( operation->ad_remaining != 0 || + operation->body_remaining != 0 ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( PSA_SUCCESS ); +} + +/* Finish encrypting a message in a multipart AEAD operation. */ +psa_status_t psa_aead_finish( psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *ciphertext_length = 0; + *tag_length = tag_size; + + status = psa_aead_final_checks( operation ); + if( status != PSA_SUCCESS ) + goto exit; + + if( !operation->is_encrypt ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_aead_finish( operation, ciphertext, + ciphertext_size, + ciphertext_length, + tag, tag_size, tag_length ); + +exit: + /* In case the operation fails and the user fails to check for failure or + * the zero tag size, make sure the tag is set to something implausible. + * Even if the operation succeeds, make sure we clear the rest of the + * buffer to prevent potential leakage of anything previously placed in + * the same buffer.*/ + if( tag != NULL ) + { + if( status != PSA_SUCCESS ) + memset( tag, '!', tag_size ); + else if( *tag_length < tag_size ) + memset( tag + *tag_length, '!', ( tag_size - *tag_length ) ); + } + + psa_aead_abort( operation ); + + return( status ); +} + +/* Finish authenticating and decrypting a message in a multipart AEAD + operation.*/ +psa_status_t psa_aead_verify( psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *plaintext_length = 0; + + status = psa_aead_final_checks( operation ); + if( status != PSA_SUCCESS ) + goto exit; + + if( operation->is_encrypt ) + { + status = PSA_ERROR_BAD_STATE; + goto exit; + } + + status = psa_driver_wrapper_aead_verify( operation, plaintext, + plaintext_size, + plaintext_length, + tag, tag_length ); + +exit: + psa_aead_abort( operation ); + + return( status ); +} + +/* Abort an AEAD operation. */ +psa_status_t psa_aead_abort( psa_aead_operation_t *operation ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->id == 0 ) + { + /* The object has (apparently) been initialized but it is not (yet) + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + + status = psa_driver_wrapper_aead_abort( operation ); + + memset( operation, 0, sizeof( *operation ) ); + + return( status ); +} + +/****************************************************************/ +/* Generators */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +#define AT_LEAST_ONE_BUILTIN_KDF +#endif /* At least one builtin KDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_key_derivation_start_hmac( + psa_mac_operation_t *operation, + psa_algorithm_t hash_alg, + const uint8_t *hmac_key, + size_t hmac_key_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_set_key_type( &attributes, PSA_KEY_TYPE_HMAC ); + psa_set_key_bits( &attributes, PSA_BYTES_TO_BITS( hmac_key_length ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + + operation->is_sign = 1; + operation->mac_size = PSA_HASH_LENGTH( hash_alg ); + + status = psa_driver_wrapper_mac_sign_setup( operation, + &attributes, + hmac_key, hmac_key_length, + PSA_ALG_HMAC( hash_alg ) ); + + psa_reset_key_attributes( &attributes ); + return( status ); +} +#endif /* KDF algorithms reliant on HMAC */ + +#define HKDF_STATE_INIT 0 /* no input yet */ +#define HKDF_STATE_STARTED 1 /* got salt */ +#define HKDF_STATE_KEYED 2 /* got key */ +#define HKDF_STATE_OUTPUT 3 /* output started */ + +static psa_algorithm_t psa_key_derivation_get_kdf_alg( + const psa_key_derivation_operation_t *operation ) +{ + if ( PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) + return( PSA_ALG_KEY_AGREEMENT_GET_KDF( operation->alg ) ); + else + return( operation->alg ); +} + +psa_status_t psa_key_derivation_abort( psa_key_derivation_operation_t *operation ) +{ + psa_status_t status = PSA_SUCCESS; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + if( kdf_alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + } + else +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + mbedtls_free( operation->ctx.hkdf.info ); + status = psa_mac_abort( &operation->ctx.hkdf.hmac ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */ + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + if( operation->ctx.tls12_prf.secret != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.secret, + operation->ctx.tls12_prf.secret_length ); + mbedtls_free( operation->ctx.tls12_prf.secret ); + } + + if( operation->ctx.tls12_prf.seed != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.seed, + operation->ctx.tls12_prf.seed_length ); + mbedtls_free( operation->ctx.tls12_prf.seed ); + } + + if( operation->ctx.tls12_prf.label != NULL ) + { + mbedtls_platform_zeroize( operation->ctx.tls12_prf.label, + operation->ctx.tls12_prf.label_length ); + mbedtls_free( operation->ctx.tls12_prf.label ); + } + + status = PSA_SUCCESS; + + /* We leave the fields Ai and output_block to be erased safely by the + * mbedtls_platform_zeroize() in the end of this function. */ + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */ + { + status = PSA_ERROR_BAD_STATE; + } + mbedtls_platform_zeroize( operation, sizeof( *operation ) ); + return( status ); +} + +psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ + if( operation->alg == 0 ) + { + /* This is a blank key derivation operation. */ + return( PSA_ERROR_BAD_STATE ); + } + + *capacity = operation->capacity; + return( PSA_SUCCESS ); +} + +psa_status_t psa_key_derivation_set_capacity( psa_key_derivation_operation_t *operation, + size_t capacity ) +{ + if( operation->alg == 0 ) + return( PSA_ERROR_BAD_STATE ); + if( capacity > operation->capacity ) + return( PSA_ERROR_INVALID_ARGUMENT ); + operation->capacity = capacity; + return( PSA_SUCCESS ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) +/* Read some bytes from an HKDF-based operation. This performs a chunk + * of the expand phase of the HKDF algorithm. */ +static psa_status_t psa_key_derivation_hkdf_read( psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t hash_alg, + uint8_t *output, + size_t output_length ) +{ + uint8_t hash_length = PSA_HASH_LENGTH( hash_alg ); + size_t hmac_output_length; + psa_status_t status; + + if( hkdf->state < HKDF_STATE_KEYED || ! hkdf->info_set ) + return( PSA_ERROR_BAD_STATE ); + hkdf->state = HKDF_STATE_OUTPUT; + + while( output_length != 0 ) + { + /* Copy what remains of the current block */ + uint8_t n = hash_length - hkdf->offset_in_block; + if( n > output_length ) + n = (uint8_t) output_length; + memcpy( output, hkdf->output_block + hkdf->offset_in_block, n ); + output += n; + output_length -= n; + hkdf->offset_in_block += n; + if( output_length == 0 ) + break; + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if( hkdf->block_number == 0xff ) + return( PSA_ERROR_BAD_STATE ); + + /* We need a new block */ + ++hkdf->block_number; + hkdf->offset_in_block = 0; + + status = psa_key_derivation_start_hmac( &hkdf->hmac, + hash_alg, + hkdf->prk, + hash_length ); + if( status != PSA_SUCCESS ) + return( status ); + + if( hkdf->block_number != 1 ) + { + status = psa_mac_update( &hkdf->hmac, + hkdf->output_block, + hash_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + status = psa_mac_update( &hkdf->hmac, + hkdf->info, + hkdf->info_length ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_mac_update( &hkdf->hmac, + &hkdf->block_number, 1 ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_mac_sign_finish( &hkdf->hmac, + hkdf->output_block, + sizeof( hkdf->output_block ), + &hmac_output_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_key_derivation_tls12_prf_generate_next_block( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_LENGTH( hash_alg ); + psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT; + size_t hmac_output_length; + psa_status_t status, cleanup_status; + + /* We can't be wanting more output after block 0xff, otherwise + * the capacity check in psa_key_derivation_output_bytes() would have + * prevented this call. It could happen only if the operation + * object was corrupted or if this function is called directly + * inside the library. */ + if( tls12_prf->block_number == 0xff ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + /* We need a new block */ + ++tls12_prf->block_number; + tls12_prf->left_in_block = hash_length; + + /* Recall the definition of the TLS-1.2-PRF from RFC 5246: + * + * PRF(secret, label, seed) = P_(secret, label + seed) + * + * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + + * HMAC_hash(secret, A(2) + seed) + + * HMAC_hash(secret, A(3) + seed) + ... + * + * A(0) = seed + * A(i) = HMAC_hash(secret, A(i-1)) + * + * The `psa_tls12_prf_key_derivation` structure saves the block + * `HMAC_hash(secret, A(i) + seed)` from which the output + * is currently extracted as `output_block` and where i is + * `block_number`. + */ + + status = psa_key_derivation_start_hmac( &hmac, + hash_alg, + tls12_prf->secret, + tls12_prf->secret_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + + /* Calculate A(i) where i = tls12_prf->block_number. */ + if( tls12_prf->block_number == 1 ) + { + /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads + * the variable seed and in this instance means it in the context of the + * P_hash function, where seed = label + seed.) */ + status = psa_mac_update( &hmac, + tls12_prf->label, + tls12_prf->label_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_mac_update( &hmac, + tls12_prf->seed, + tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + else + { + /* A(i) = HMAC_hash(secret, A(i-1)) */ + status = psa_mac_update( &hmac, tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + + status = psa_mac_sign_finish( &hmac, + tls12_prf->Ai, hash_length, + &hmac_output_length ); + if( hmac_output_length != hash_length ) + status = PSA_ERROR_CORRUPTION_DETECTED; + if( status != PSA_SUCCESS ) + goto cleanup; + + /* Calculate HMAC_hash(secret, A(i) + label + seed). */ + status = psa_key_derivation_start_hmac( &hmac, + hash_alg, + tls12_prf->secret, + tls12_prf->secret_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_mac_update( &hmac, tls12_prf->Ai, hash_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_mac_update( &hmac, tls12_prf->label, tls12_prf->label_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_mac_update( &hmac, tls12_prf->seed, tls12_prf->seed_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + status = psa_mac_sign_finish( &hmac, + tls12_prf->output_block, hash_length, + &hmac_output_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + + +cleanup: + cleanup_status = psa_mac_abort( &hmac ); + if( status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS ) + status = cleanup_status; + + return( status ); +} + +static psa_status_t psa_key_derivation_tls12_prf_read( + psa_tls12_prf_key_derivation_t *tls12_prf, + psa_algorithm_t alg, + uint8_t *output, + size_t output_length ) +{ + psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); + uint8_t hash_length = PSA_HASH_LENGTH( hash_alg ); + psa_status_t status; + uint8_t offset, length; + + switch( tls12_prf->state ) + { + case PSA_TLS12_PRF_STATE_LABEL_SET: + tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT; + break; + case PSA_TLS12_PRF_STATE_OUTPUT: + break; + default: + return( PSA_ERROR_BAD_STATE ); + } + + while( output_length != 0 ) + { + /* Check if we have fully processed the current block. */ + if( tls12_prf->left_in_block == 0 ) + { + status = psa_key_derivation_tls12_prf_generate_next_block( tls12_prf, + alg ); + if( status != PSA_SUCCESS ) + return( status ); + + continue; + } + + if( tls12_prf->left_in_block > output_length ) + length = (uint8_t) output_length; + else + length = tls12_prf->left_in_block; + + offset = hash_length - tls12_prf->left_in_block; + memcpy( output, tls12_prf->output_block + offset, length ); + output += length; + output_length -= length; + tls12_prf->left_in_block -= length; + } + + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length ) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + + if( operation->alg == 0 ) + { + /* This is a blank operation. */ + return( PSA_ERROR_BAD_STATE ); + } + + if( output_length > operation->capacity ) + { + operation->capacity = 0; + /* Go through the error path to wipe all confidential data now + * that the operation object is useless. */ + status = PSA_ERROR_INSUFFICIENT_DATA; + goto exit; + } + if( output_length == 0 && operation->capacity == 0 ) + { + /* Edge case: this is a finished operation, and 0 bytes + * were requested. The right error in this case could + * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return + * INSUFFICIENT_CAPACITY, which is right for a finished + * operation, for consistency with the case when + * output_length > 0. */ + return( PSA_ERROR_INSUFFICIENT_DATA ); + } + operation->capacity -= output_length; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); + status = psa_key_derivation_hkdf_read( &operation->ctx.hkdf, hash_alg, + output, output_length ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + status = psa_key_derivation_tls12_prf_read( &operation->ctx.tls12_prf, + kdf_alg, output, + output_length ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + { + (void) kdf_alg; + return( PSA_ERROR_BAD_STATE ); + } + +exit: + if( status != PSA_SUCCESS ) + { + /* Preserve the algorithm upon errors, but clear all sensitive state. + * This allows us to differentiate between exhausted operations and + * blank operations, so we can return PSA_ERROR_BAD_STATE on blank + * operations. */ + psa_algorithm_t alg = operation->alg; + psa_key_derivation_abort( operation ); + operation->alg = alg; + memset( output, '!', output_length ); + } + return( status ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) +static void psa_des_set_key_parity( uint8_t *data, size_t data_size ) +{ + if( data_size >= 8 ) + mbedtls_des_key_set_parity( data ); + if( data_size >= 16 ) + mbedtls_des_key_set_parity( data + 8 ); + if( data_size >= 24 ) + mbedtls_des_key_set_parity( data + 16 ); +} +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + +static psa_status_t psa_generate_derived_key_internal( + psa_key_slot_t *slot, + size_t bits, + psa_key_derivation_operation_t *operation ) +{ + uint8_t *data = NULL; + size_t bytes = PSA_BITS_TO_BYTES( bits ); + size_t storage_size = bytes; + psa_status_t status; + + if( ! key_type_is_raw_bytes( slot->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( bits % 8 != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + data = mbedtls_calloc( 1, bytes ); + if( data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = psa_key_derivation_output_bytes( operation, data, bytes ); + if( status != PSA_SUCCESS ) + goto exit; +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if( slot->attr.type == PSA_KEY_TYPE_DES ) + psa_des_set_key_parity( data, bytes ); +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + + slot->attr.bits = (psa_key_bits_t) bits; + psa_key_attributes_t attributes = { + .core = slot->attr + }; + + if( psa_key_lifetime_is_external( attributes.core.lifetime ) ) + { + status = psa_driver_wrapper_get_key_buffer_size( &attributes, + &storage_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + status = psa_allocate_buffer_to_slot( slot, storage_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_driver_wrapper_import_key( &attributes, + data, bytes, + slot->key.data, + slot->key.bytes, + &slot->key.bytes, &bits ); + if( bits != slot->attr.bits ) + status = PSA_ERROR_INVALID_ARGUMENT; + +exit: + mbedtls_free( data ); + return( status ); +} + +psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + mbedtls_svc_key_id_t *key ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( operation->alg == PSA_ALG_NONE ) + return( PSA_ERROR_BAD_STATE ); + + if( ! operation->can_output_key ) + return( PSA_ERROR_NOT_PERMITTED ); + + status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE, attributes, + &slot, &driver ); +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + if( driver != NULL ) + { + /* Deriving a key in a secure element is not implemented yet. */ + status = PSA_ERROR_NOT_SUPPORTED; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + if( status == PSA_SUCCESS ) + { + status = psa_generate_derived_key_internal( slot, + attributes->core.bits, + operation ); + } + if( status == PSA_SUCCESS ) + status = psa_finish_key_creation( slot, driver, key ); + if( status != PSA_SUCCESS ) + psa_fail_key_creation( slot, driver ); + + return( status ); +} + + + +/****************************************************************/ +/* Key derivation */ +/****************************************************************/ + +#if defined(AT_LEAST_ONE_BUILTIN_KDF) +static psa_status_t psa_key_derivation_setup_kdf( + psa_key_derivation_operation_t *operation, + psa_algorithm_t kdf_alg ) +{ + int is_kdf_alg_supported; + + /* Make sure that operation->ctx is properly zero-initialised. (Macro + * initialisers for this union leave some bytes unspecified.) */ + memset( &operation->ctx, 0, sizeof( operation->ctx ) ); + + /* Make sure that kdf_alg is a supported key derivation algorithm. */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + is_kdf_alg_supported = 1; + else +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) + if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ) + is_kdf_alg_supported = 1; + else +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + is_kdf_alg_supported = 1; + else +#endif + is_kdf_alg_supported = 0; + + if( is_kdf_alg_supported ) + { + psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( kdf_alg ); + size_t hash_size = PSA_HASH_LENGTH( hash_alg ); + if( hash_size == 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( ( PSA_ALG_IS_TLS12_PRF( kdf_alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) && + ! ( hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384 ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + operation->capacity = 255 * hash_size; + return( PSA_SUCCESS ); + } + + return( PSA_ERROR_NOT_SUPPORTED ); +} +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + +psa_status_t psa_key_derivation_setup( psa_key_derivation_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status; + + if( operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + if( PSA_ALG_IS_RAW_KEY_AGREEMENT( alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + else if( PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { +#if defined(AT_LEAST_ONE_BUILTIN_KDF) + psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF( alg ); + status = psa_key_derivation_setup_kdf( operation, kdf_alg ); +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + } + else if( PSA_ALG_IS_KEY_DERIVATION( alg ) ) + { +#if defined(AT_LEAST_ONE_BUILTIN_KDF) + status = psa_key_derivation_setup_kdf( operation, alg ); +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* AT_LEAST_ONE_BUILTIN_KDF */ + } + else + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( status == PSA_SUCCESS ) + operation->alg = alg; + return( status ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) +static psa_status_t psa_hkdf_input( psa_hkdf_key_derivation_t *hkdf, + psa_algorithm_t hash_alg, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SALT: + if( hkdf->state != HKDF_STATE_INIT ) + return( PSA_ERROR_BAD_STATE ); + else + { + status = psa_key_derivation_start_hmac( &hkdf->hmac, + hash_alg, + data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->state = HKDF_STATE_STARTED; + return( PSA_SUCCESS ); + } + case PSA_KEY_DERIVATION_INPUT_SECRET: + /* If no salt was provided, use an empty salt. */ + if( hkdf->state == HKDF_STATE_INIT ) + { + status = psa_key_derivation_start_hmac( &hkdf->hmac, + hash_alg, + NULL, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->state = HKDF_STATE_STARTED; + } + if( hkdf->state != HKDF_STATE_STARTED ) + return( PSA_ERROR_BAD_STATE ); + status = psa_mac_update( &hkdf->hmac, + data, data_length ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_mac_sign_finish( &hkdf->hmac, + hkdf->prk, + sizeof( hkdf->prk ), + &data_length ); + if( status != PSA_SUCCESS ) + return( status ); + hkdf->offset_in_block = PSA_HASH_LENGTH( hash_alg ); + hkdf->block_number = 0; + hkdf->state = HKDF_STATE_KEYED; + return( PSA_SUCCESS ); + case PSA_KEY_DERIVATION_INPUT_INFO: + if( hkdf->state == HKDF_STATE_OUTPUT ) + return( PSA_ERROR_BAD_STATE ); + if( hkdf->info_set ) + return( PSA_ERROR_BAD_STATE ); + hkdf->info_length = data_length; + if( data_length != 0 ) + { + hkdf->info = mbedtls_calloc( 1, data_length ); + if( hkdf->info == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( hkdf->info, data, data_length ); + } + hkdf->info_set = 1; + return( PSA_SUCCESS ); + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_tls12_prf_set_seed( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != PSA_TLS12_PRF_STATE_INIT ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->seed = mbedtls_calloc( 1, data_length ); + if( prf->seed == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->seed, data, data_length ); + prf->seed_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_SEED_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_set_key( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != PSA_TLS12_PRF_STATE_SEED_SET ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->secret = mbedtls_calloc( 1, data_length ); + if( prf->secret == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->secret, data, data_length ); + prf->secret_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_KEY_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_set_label( psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + if( prf->state != PSA_TLS12_PRF_STATE_KEY_SET ) + return( PSA_ERROR_BAD_STATE ); + + if( data_length != 0 ) + { + prf->label = mbedtls_calloc( 1, data_length ); + if( prf->label == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + memcpy( prf->label, data, data_length ); + prf->label_length = data_length; + } + + prf->state = PSA_TLS12_PRF_STATE_LABEL_SET; + + return( PSA_SUCCESS ); +} + +static psa_status_t psa_tls12_prf_input( psa_tls12_prf_key_derivation_t *prf, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SEED: + return( psa_tls12_prf_set_seed( prf, data, data_length ) ); + case PSA_KEY_DERIVATION_INPUT_SECRET: + return( psa_tls12_prf_set_key( prf, data, data_length ) ); + case PSA_KEY_DERIVATION_INPUT_LABEL: + return( psa_tls12_prf_set_label( prf, data, data_length ) ); + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || + * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) +static psa_status_t psa_tls12_prf_psk_to_ms_set_key( + psa_tls12_prf_key_derivation_t *prf, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + uint8_t pms[ 4 + 2 * PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE ]; + uint8_t *cur = pms; + + if( data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Quoting RFC 4279, Section 2: + * + * The premaster secret is formed as follows: if the PSK is N octets + * long, concatenate a uint16 with the value N, N zero octets, a second + * uint16 with the value N, and the PSK itself. + */ + + *cur++ = MBEDTLS_BYTE_1( data_length ); + *cur++ = MBEDTLS_BYTE_0( data_length ); + memset( cur, 0, data_length ); + cur += data_length; + *cur++ = pms[0]; + *cur++ = pms[1]; + memcpy( cur, data, data_length ); + cur += data_length; + + status = psa_tls12_prf_set_key( prf, pms, cur - pms ); + + mbedtls_platform_zeroize( pms, sizeof( pms ) ); + return( status ); +} + +static psa_status_t psa_tls12_prf_psk_to_ms_input( + psa_tls12_prf_key_derivation_t *prf, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + { + return( psa_tls12_prf_psk_to_ms_set_key( prf, + data, data_length ) ); + } + + return( psa_tls12_prf_input( prf, step, data, data_length ) ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + +/** Check whether the given key type is acceptable for the given + * input step of a key derivation. + * + * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE. + * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA. + * Both secret and non-secret inputs can alternatively have the type + * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning + * that the input was passed as a buffer rather than via a key object. + */ +static int psa_key_derivation_check_input_type( + psa_key_derivation_step_t step, + psa_key_type_t key_type ) +{ + switch( step ) + { + case PSA_KEY_DERIVATION_INPUT_SECRET: + if( key_type == PSA_KEY_TYPE_DERIVE ) + return( PSA_SUCCESS ); + if( key_type == PSA_KEY_TYPE_NONE ) + return( PSA_SUCCESS ); + break; + case PSA_KEY_DERIVATION_INPUT_LABEL: + case PSA_KEY_DERIVATION_INPUT_SALT: + case PSA_KEY_DERIVATION_INPUT_INFO: + case PSA_KEY_DERIVATION_INPUT_SEED: + if( key_type == PSA_KEY_TYPE_RAW_DATA ) + return( PSA_SUCCESS ); + if( key_type == PSA_KEY_TYPE_NONE ) + return( PSA_SUCCESS ); + break; + } + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +static psa_status_t psa_key_derivation_input_internal( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_type_t key_type, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg( operation ); + + status = psa_key_derivation_check_input_type( step, key_type ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) + if( PSA_ALG_IS_HKDF( kdf_alg ) ) + { + status = psa_hkdf_input( &operation->ctx.hkdf, + PSA_ALG_HKDF_GET_HASH( kdf_alg ), + step, data, data_length ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) + if( PSA_ALG_IS_TLS12_PRF( kdf_alg ) ) + { + status = psa_tls12_prf_input( &operation->ctx.tls12_prf, + step, data, data_length ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) + if( PSA_ALG_IS_TLS12_PSK_TO_MS( kdf_alg ) ) + { + status = psa_tls12_prf_psk_to_ms_input( &operation->ctx.tls12_prf, + step, data, data_length ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */ + { + /* This can't happen unless the operation object was not initialized */ + (void) data; + (void) data_length; + (void) kdf_alg; + return( PSA_ERROR_BAD_STATE ); + } + +exit: + if( status != PSA_SUCCESS ) + psa_key_derivation_abort( operation ); + return( status ); +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length ) +{ + return( psa_key_derivation_input_internal( operation, step, + PSA_KEY_TYPE_NONE, + data, data_length ) ); +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t key ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + status = psa_get_and_lock_transparent_key_slot_with_policy( + key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( operation ); + return( status ); + } + + /* Passing a key object as a SECRET input unlocks the permission + * to output to a key object. */ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + operation->can_output_key = 1; + + status = psa_key_derivation_input_internal( operation, + step, slot->attr.type, + slot->key.data, + slot->key.bytes ); + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + + + +/****************************************************************/ +/* Key agreement */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, + size_t peer_key_length, + const mbedtls_ecp_keypair *our_key, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + mbedtls_ecp_keypair *their_key = NULL; + mbedtls_ecdh_context ecdh; + psa_status_t status; + size_t bits = 0; + psa_ecc_family_t curve = mbedtls_ecc_group_to_psa( our_key->grp.id, &bits ); + mbedtls_ecdh_init( &ecdh ); + + status = mbedtls_psa_ecp_load_representation( + PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve), + bits, + peer_key, + peer_key_length, + &their_key ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) ); + if( status != PSA_SUCCESS ) + goto exit; + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_to_psa_error( + mbedtls_ecdh_calc_secret( &ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ) ); + if( status != PSA_SUCCESS ) + goto exit; + if( PSA_BITS_TO_BYTES( bits ) != *shared_secret_length ) + status = PSA_ERROR_CORRUPTION_DETECTED; + +exit: + if( status != PSA_SUCCESS ) + mbedtls_platform_zeroize( shared_secret, shared_secret_size ); + mbedtls_ecdh_free( &ecdh ); + mbedtls_ecp_keypair_free( their_key ); + mbedtls_free( their_key ); + + return( status ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + +#define PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE MBEDTLS_ECP_MAX_BYTES + +static psa_status_t psa_key_agreement_raw_internal( psa_algorithm_t alg, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *shared_secret, + size_t shared_secret_size, + size_t *shared_secret_length ) +{ + switch( alg ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) + case PSA_ALG_ECDH: + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( private_key->attr.type ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + mbedtls_ecp_keypair *ecp = NULL; + psa_status_t status = mbedtls_psa_ecp_load_representation( + private_key->attr.type, + private_key->attr.bits, + private_key->key.data, + private_key->key.bytes, + &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_key_agreement_ecdh( peer_key, peer_key_length, + ecp, + shared_secret, shared_secret_size, + shared_secret_length ); + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */ + default: + (void) private_key; + (void) peer_key; + (void) peer_key_length; + (void) shared_secret; + (void) shared_secret_size; + (void) shared_secret_length; + return( PSA_ERROR_NOT_SUPPORTED ); + } +} + +/* Note that if this function fails, you must call psa_key_derivation_abort() + * to potentially free embedded data structures and wipe confidential data. + */ +static psa_status_t psa_key_agreement_internal( psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_slot_t *private_key, + const uint8_t *peer_key, + size_t peer_key_length ) +{ + psa_status_t status; + uint8_t shared_secret[PSA_KEY_AGREEMENT_MAX_SHARED_SECRET_SIZE]; + size_t shared_secret_length = 0; + psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE( operation->alg ); + + /* Step 1: run the secret agreement algorithm to generate the shared + * secret. */ + status = psa_key_agreement_raw_internal( ka_alg, + private_key, + peer_key, peer_key_length, + shared_secret, + sizeof( shared_secret ), + &shared_secret_length ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Step 2: set up the key derivation to generate key material from + * the shared secret. A shared secret is permitted wherever a key + * of type DERIVE is permitted. */ + status = psa_key_derivation_input_internal( operation, step, + PSA_KEY_TYPE_DERIVE, + shared_secret, + shared_secret_length ); +exit: + mbedtls_platform_zeroize( shared_secret, shared_secret_length ); + return( status ); +} + +psa_status_t psa_key_derivation_key_agreement( psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot; + + if( ! PSA_ALG_IS_KEY_AGREEMENT( operation->alg ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_key_agreement_internal( operation, step, + slot, + peer_key, peer_key_length ); + if( status != PSA_SUCCESS ) + psa_key_derivation_abort( operation ); + else + { + /* If a private key has been added as SECRET, we allow the derived + * key material to be used as a key in PSA Crypto. */ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + operation->can_output_key = 1; + } + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + +psa_status_t psa_raw_key_agreement( psa_algorithm_t alg, + mbedtls_svc_key_id_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_slot_t *slot = NULL; + + if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + status = psa_get_and_lock_transparent_key_slot_with_policy( + private_key, &slot, PSA_KEY_USAGE_DERIVE, alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_key_agreement_raw_internal( alg, slot, + peer_key, peer_key_length, + output, output_size, + output_length ); + +exit: + if( status != PSA_SUCCESS ) + { + /* If an error happens and is not handled properly, the output + * may be used as a key to protect sensitive data. Arrange for such + * a key to be random, which is likely to result in decryption or + * verification errors. This is better than filling the buffer with + * some constant data such as zeros, which would result in the data + * being protected with a reproducible, easily knowable key. + */ + psa_generate_random( output, output_size ); + *output_length = output_size; + } + + unlock_status = psa_unlock_key_slot( slot ); + + return( ( status == PSA_SUCCESS ) ? unlock_status : status ); +} + + + +/****************************************************************/ +/* Random generation */ +/****************************************************************/ + +/** Initialize the PSA random generator. + */ +static void mbedtls_psa_random_init( mbedtls_psa_random_context_t *rng ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset( rng, 0, sizeof( *rng ) ); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if( rng->entropy_init == NULL ) + rng->entropy_init = mbedtls_entropy_init; + if( rng->entropy_free == NULL ) + rng->entropy_free = mbedtls_entropy_free; + + rng->entropy_init( &rng->entropy ); +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) + /* The PSA entropy injection feature depends on using NV seed as an entropy + * source. Add NV seed as an entropy source for PSA entropy injection. */ + mbedtls_entropy_add_source( &rng->entropy, + mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + + mbedtls_psa_drbg_init( MBEDTLS_PSA_RANDOM_STATE ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/** Deinitialize the PSA random generator. + */ +static void mbedtls_psa_random_free( mbedtls_psa_random_context_t *rng ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + memset( rng, 0, sizeof( *rng ) ); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + mbedtls_psa_drbg_free( MBEDTLS_PSA_RANDOM_STATE ); + rng->entropy_free( &rng->entropy ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/** Seed the PSA random generator. + */ +static psa_status_t mbedtls_psa_random_seed( mbedtls_psa_random_context_t *rng ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + /* Do nothing: the external RNG seeds itself. */ + (void) rng; + return( PSA_SUCCESS ); +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + const unsigned char drbg_seed[] = "PSA"; + int ret = mbedtls_psa_drbg_seed( &rng->entropy, + drbg_seed, sizeof( drbg_seed ) - 1 ); + return mbedtls_to_psa_error( ret ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +psa_status_t psa_generate_random( uint8_t *output, + size_t output_size ) +{ + GUARD_MODULE_INITIALIZED; + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + + size_t output_length = 0; + psa_status_t status = mbedtls_psa_external_get_random( &global_data.rng, + output, output_size, + &output_length ); + if( status != PSA_SUCCESS ) + return( status ); + /* Breaking up a request into smaller chunks is currently not supported + * for the extrernal RNG interface. */ + if( output_length != output_size ) + return( PSA_ERROR_INSUFFICIENT_ENTROPY ); + return( PSA_SUCCESS ); + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + + while( output_size > 0 ) + { + size_t request_size = + ( output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ? + MBEDTLS_PSA_RANDOM_MAX_REQUEST : + output_size ); + int ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE, + output, request_size ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + output_size -= request_size; + output += request_size; + } + return( PSA_SUCCESS ); +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ +} + +/* Wrapper function allowing the classic API to use the PSA RNG. + * + * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls + * `psa_generate_random(...)`. The state parameter is ignored since the + * PSA API doesn't support passing an explicit state. + * + * In the non-external case, psa_generate_random() calls an + * `mbedtls_xxx_drbg_random` function which has exactly the same signature + * and semantics as mbedtls_psa_get_random(). As an optimization, + * instead of doing this back-and-forth between the PSA API and the + * classic API, psa_crypto_random_impl.h defines `mbedtls_psa_get_random` + * as a constant function pointer to `mbedtls_xxx_drbg_random`. + */ +#if defined (MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +int mbedtls_psa_get_random( void *p_rng, + unsigned char *output, + size_t output_size ) +{ + /* This function takes a pointer to the RNG state because that's what + * classic mbedtls functions using an RNG expect. The PSA RNG manages + * its own state internally and doesn't let the caller access that state. + * So we just ignore the state parameter, and in practice we'll pass + * NULL. */ + (void) p_rng; + psa_status_t status = psa_generate_random( output, output_size ); + if( status == PSA_SUCCESS ) + return( 0 ); + else + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); +} +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +#include "entropy_poll.h" + +psa_status_t mbedtls_psa_inject_entropy( const uint8_t *seed, + size_t seed_size ) +{ + if( global_data.initialized ) + return( PSA_ERROR_NOT_PERMITTED ); + + if( ( ( seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM ) || + ( seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE ) ) || + ( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( mbedtls_psa_storage_inject_entropy( seed, seed_size ) ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +/** Validate the key type and size for key generation + * + * \param type The key type + * \param bits The number of bits of the key + * + * \retval #PSA_SUCCESS + * The key type and size are valid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + */ +static psa_status_t psa_validate_key_type_and_size_for_key_generation( + psa_key_type_t type, size_t bits ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( key_type_is_raw_bytes( type ) ) + { + status = psa_validate_unstructured_key_bit_size( type, bits ); + if( status != PSA_SUCCESS ) + return( status ); + } + else +#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) + if( PSA_KEY_TYPE_IS_RSA( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Accept only byte-aligned keys, for the same reasons as + * in psa_import_rsa_key(). */ + if( bits % 8 != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + } + else +#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) */ + +#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) + if( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + /* To avoid empty block, return successfully here. */ + return( PSA_SUCCESS ); + } + else +#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) */ + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_generate_key_internal( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_type_t type = attributes->core.type; + + if( ( attributes->domain_parameters == NULL ) && + ( attributes->domain_parameters_size != 0 ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( key_type_is_raw_bytes( type ) ) + { + status = psa_generate_random( key_buffer, key_buffer_size ); + if( status != PSA_SUCCESS ) + return( status ); + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if( type == PSA_KEY_TYPE_DES ) + psa_des_set_key_parity( key_buffer, key_buffer_size ); +#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */ + } + else + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) && \ + defined(MBEDTLS_GENPRIME) + if ( type == PSA_KEY_TYPE_RSA_KEY_PAIR ) + { + return( mbedtls_psa_rsa_generate_key( attributes, + key_buffer, + key_buffer_size, + key_buffer_length ) ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) + * defined(MBEDTLS_GENPRIME) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) + if ( PSA_KEY_TYPE_IS_ECC( type ) && PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + { + return( mbedtls_psa_ecp_generate_key( attributes, + key_buffer, + key_buffer_size, + key_buffer_length ) ); + } + else +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ + { + (void)key_buffer_length; + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t psa_generate_key( const psa_key_attributes_t *attributes, + mbedtls_svc_key_id_t *key ) +{ + psa_status_t status; + psa_key_slot_t *slot = NULL; + psa_se_drv_table_entry_t *driver = NULL; + size_t key_buffer_size; + + *key = MBEDTLS_SVC_KEY_ID_INIT; + + /* Reject any attempt to create a zero-length key so that we don't + * risk tripping up later, e.g. on a malloc(0) that returns NULL. */ + if( psa_get_key_bits( attributes ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Reject any attempt to create a public key. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->core.type) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_start_key_creation( PSA_KEY_CREATION_GENERATE, attributes, + &slot, &driver ); + if( status != PSA_SUCCESS ) + goto exit; + + /* In the case of a transparent key or an opaque key stored in local + * storage ( thus not in the case of generating a key in a secure element + * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a + * buffer to hold the generated key material. */ + if( slot->key.data == NULL ) + { + if ( PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ) == + PSA_KEY_LOCATION_LOCAL_STORAGE ) + { + status = psa_validate_key_type_and_size_for_key_generation( + attributes->core.type, attributes->core.bits ); + if( status != PSA_SUCCESS ) + goto exit; + + key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE( + attributes->core.type, + attributes->core.bits ); + } + else + { + status = psa_driver_wrapper_get_key_buffer_size( + attributes, &key_buffer_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = psa_allocate_buffer_to_slot( slot, key_buffer_size ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = psa_driver_wrapper_generate_key( attributes, + slot->key.data, slot->key.bytes, &slot->key.bytes ); + + if( status != PSA_SUCCESS ) + psa_remove_key_data_from_memory( slot ); + +exit: + if( status == PSA_SUCCESS ) + status = psa_finish_key_creation( slot, driver, key ); + if( status != PSA_SUCCESS ) + psa_fail_key_creation( slot, driver ); + + return( status ); +} + +/****************************************************************/ +/* Module setup */ +/****************************************************************/ + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ) +{ + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + return( PSA_ERROR_BAD_STATE ); + global_data.rng.entropy_init = entropy_init; + global_data.rng.entropy_free = entropy_free; + return( PSA_SUCCESS ); +} +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +void mbedtls_psa_crypto_free( void ) +{ + psa_wipe_all_key_slots( ); + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + { + mbedtls_psa_random_free( &global_data.rng ); + } + /* Wipe all remaining data, including configuration. + * In particular, this sets all state indicator to the value + * indicating "uninitialized". */ + mbedtls_platform_zeroize( &global_data, sizeof( global_data ) ); + + /* Terminate drivers */ + psa_driver_wrapper_free( ); +} + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) +/** Recover a transaction that was interrupted by a power failure. + * + * This function is called during initialization, before psa_crypto_init() + * returns. If this function returns a failure status, the initialization + * fails. + */ +static psa_status_t psa_crypto_recover_transaction( + const psa_crypto_transaction_t *transaction ) +{ + switch( transaction->unknown.type ) + { + case PSA_CRYPTO_TRANSACTION_CREATE_KEY: + case PSA_CRYPTO_TRANSACTION_DESTROY_KEY: + /* TODO - fall through to the failure case until this + * is implemented. + * https://github.com/ARMmbed/mbed-crypto/issues/218 + */ + default: + /* We found an unsupported transaction in the storage. + * We don't know what state the storage is in. Give up. */ + return( PSA_ERROR_DATA_INVALID ); + } +} +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +psa_status_t psa_crypto_init( void ) +{ + psa_status_t status; + + /* Double initialization is explicitly allowed. */ + if( global_data.initialized != 0 ) + return( PSA_SUCCESS ); + + /* Initialize and seed the random generator. */ + mbedtls_psa_random_init( &global_data.rng ); + global_data.rng_state = RNG_INITIALIZED; + status = mbedtls_psa_random_seed( &global_data.rng ); + if( status != PSA_SUCCESS ) + goto exit; + global_data.rng_state = RNG_SEEDED; + + status = psa_initialize_key_slots( ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Init drivers */ + status = psa_driver_wrapper_init( ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + status = psa_crypto_load_transaction( ); + if( status == PSA_SUCCESS ) + { + status = psa_crypto_recover_transaction( &psa_crypto_transaction ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_crypto_stop_transaction( ); + } + else if( status == PSA_ERROR_DOES_NOT_EXIST ) + { + /* There's no transaction to complete. It's all good. */ + status = PSA_SUCCESS; + } +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + /* All done. */ + global_data.initialized = 1; + +exit: + if( status != PSA_SUCCESS ) + mbedtls_psa_crypto_free( ); + return( status ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.c new file mode 100644 index 00000000..714d950a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.c @@ -0,0 +1,701 @@ +/* + * PSA AEAD entry points + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_aead.h" +#include "psa_crypto_core.h" + +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ccm.h" +#include "mbedtls/chachapoly.h" +#include "mbedtls/cipher.h" +#include "mbedtls/gcm.h" +#include "mbedtls/error.h" + +static psa_status_t psa_aead_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t key_bits; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_id_t cipher_id; + size_t full_tag_length = 0; + + ( void ) key_buffer_size; + + key_bits = attributes->core.bits; + + cipher_info = mbedtls_cipher_info_from_psa( alg, + attributes->core.type, key_bits, + &cipher_id ); + if( cipher_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + switch( PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ): + operation->alg = PSA_ALG_CCM; + full_tag_length = 16; + /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16. + * The call to mbedtls_ccm_encrypt_and_tag or + * mbedtls_ccm_auth_decrypt will validate the tag length. */ + if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + mbedtls_ccm_init( &operation->ctx.ccm ); + status = mbedtls_to_psa_error( + mbedtls_ccm_setkey( &operation->ctx.ccm, cipher_id, + key_buffer, (unsigned int) key_bits ) ); + if( status != PSA_SUCCESS ) + return( status ); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ): + operation->alg = PSA_ALG_GCM; + full_tag_length = 16; + /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. + * The call to mbedtls_gcm_crypt_and_tag or + * mbedtls_gcm_auth_decrypt will validate the tag length. */ + if( PSA_BLOCK_CIPHER_BLOCK_LENGTH( attributes->core.type ) != 16 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + mbedtls_gcm_init( &operation->ctx.gcm ); + status = mbedtls_to_psa_error( + mbedtls_gcm_setkey( &operation->ctx.gcm, cipher_id, + key_buffer, (unsigned int) key_bits ) ); + if( status != PSA_SUCCESS ) + return( status ); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ): + operation->alg = PSA_ALG_CHACHA20_POLY1305; + full_tag_length = 16; + /* We only support the default tag length. */ + if( alg != PSA_ALG_CHACHA20_POLY1305 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + mbedtls_chachapoly_init( &operation->ctx.chachapoly ); + status = mbedtls_to_psa_error( + mbedtls_chachapoly_setkey( &operation->ctx.chachapoly, + key_buffer ) ); + if( status != PSA_SUCCESS ) + return( status ); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + + default: + (void) status; + (void) key_buffer; + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( PSA_AEAD_TAG_LENGTH( attributes->core.type, + key_bits, alg ) + > full_tag_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + operation->key_type = psa_get_key_type( attributes ); + + operation->tag_length = PSA_AEAD_TAG_LENGTH( operation->key_type, + key_bits, + alg ); + + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_aead_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *plaintext, size_t plaintext_length, + uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; + uint8_t *tag; + + status = psa_aead_setup( &operation, attributes, key_buffer, + key_buffer_size, alg ); + + if( status != PSA_SUCCESS ) + goto exit; + + /* For all currently supported modes, the tag is at the end of the + * ciphertext. */ + if( ciphertext_size < ( plaintext_length + operation.tag_length ) ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + tag = ciphertext + plaintext_length; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation.alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_encrypt_and_tag( &operation.ctx.ccm, + plaintext_length, + nonce, nonce_length, + additional_data, + additional_data_length, + plaintext, ciphertext, + tag, operation.tag_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if( operation.alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_crypt_and_tag( &operation.ctx.gcm, + MBEDTLS_GCM_ENCRYPT, + plaintext_length, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, ciphertext, + operation.tag_length, tag ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if( operation.alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( operation.tag_length != 16 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_encrypt_and_tag( &operation.ctx.chachapoly, + plaintext_length, + nonce, + additional_data, + additional_data_length, + plaintext, + ciphertext, + tag ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) tag; + (void) nonce; + (void) nonce_length; + (void) additional_data; + (void) additional_data_length; + (void) plaintext; + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status == PSA_SUCCESS ) + *ciphertext_length = plaintext_length + operation.tag_length; + +exit: + mbedtls_psa_aead_abort( &operation ); + + return( status ); +} + +/* Locate the tag in a ciphertext buffer containing the encrypted data + * followed by the tag. Return the length of the part preceding the tag in + * *plaintext_length. This is the size of the plaintext in modes where + * the encrypted data has the same size as the plaintext, such as + * CCM and GCM. */ +static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + size_t plaintext_size, + const uint8_t **p_tag ) +{ + size_t payload_length; + if( tag_length > ciphertext_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + payload_length = ciphertext_length - tag_length; + if( payload_length > plaintext_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + *p_tag = ciphertext + payload_length; + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_aead_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *ciphertext, size_t ciphertext_length, + uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT; + const uint8_t *tag = NULL; + + status = psa_aead_setup( &operation, attributes, key_buffer, + key_buffer_size, alg ); + + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_aead_unpadded_locate_tag( operation.tag_length, + ciphertext, ciphertext_length, + plaintext_size, &tag ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation.alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_auth_decrypt( &operation.ctx.ccm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + ciphertext, plaintext, + tag, operation.tag_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if( operation.alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_auth_decrypt( &operation.ctx.gcm, + ciphertext_length - operation.tag_length, + nonce, nonce_length, + additional_data, + additional_data_length, + tag, operation.tag_length, + ciphertext, plaintext ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if( operation.alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( operation.tag_length != 16 ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = mbedtls_to_psa_error( + mbedtls_chachapoly_auth_decrypt( &operation.ctx.chachapoly, + ciphertext_length - operation.tag_length, + nonce, + additional_data, + additional_data_length, + tag, + ciphertext, + plaintext ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + (void) nonce; + (void) nonce_length; + (void) additional_data; + (void) additional_data_length; + (void) plaintext; + return( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status == PSA_SUCCESS ) + *plaintext_length = ciphertext_length - operation.tag_length; + +exit: + mbedtls_psa_aead_abort( &operation ); + + if( status == PSA_SUCCESS ) + *plaintext_length = ciphertext_length - operation.tag_length; + return( status ); +} + +/* Set the key and algorithm for a multipart authenticated encryption + * operation. */ +psa_status_t mbedtls_psa_aead_encrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_aead_setup( operation, attributes, key_buffer, + key_buffer_size, alg ); + + if( status == PSA_SUCCESS ) + operation->is_encrypt = 1; + + return ( status ); +} + +/* Set the key and algorithm for a multipart authenticated decryption + * operation. */ +psa_status_t mbedtls_psa_aead_decrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + status = psa_aead_setup( operation, attributes, key_buffer, + key_buffer_size, alg ); + + if( status == PSA_SUCCESS ) + operation->is_encrypt = 0; + + return ( status ); +} + +/* Set a nonce for the multipart AEAD operation*/ +psa_status_t mbedtls_psa_aead_set_nonce( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if( operation->alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_starts( &operation->ctx.gcm, + operation->is_encrypt ? + MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT, + nonce, + nonce_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_starts( &operation->ctx.ccm, + operation->is_encrypt ? + MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT, + nonce, + nonce_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) + { + /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to + * allocate a buffer in the operation, copy the nonce to it and pad + * it, so for now check the nonce is 12 bytes, as + * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the + * passed in buffer. */ + if( nonce_length != 12 ) + { + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_starts( &operation->ctx.chachapoly, + nonce, + operation->is_encrypt ? + MBEDTLS_CHACHAPOLY_ENCRYPT : + MBEDTLS_CHACHAPOLY_DECRYPT ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + ( void ) operation; + ( void ) nonce; + ( void ) nonce_length; + + return ( PSA_ERROR_NOT_SUPPORTED ); + } + + return( status ); +} + + /* Declare the lengths of the message and additional data for AEAD. */ +psa_status_t mbedtls_psa_aead_set_lengths( + mbedtls_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length ) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + return( mbedtls_to_psa_error( + mbedtls_ccm_set_lengths( &operation->ctx.ccm, + ad_length, + plaintext_length, + operation->tag_length ) ) ); + + } +#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + ( void ) operation; + ( void ) ad_length; + ( void ) plaintext_length; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ + + return ( PSA_SUCCESS ); +} + +/* Pass additional data to an active multipart AEAD operation. */ +psa_status_t mbedtls_psa_aead_update_ad( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if( operation->alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_update_ad( &operation->ctx.gcm, input, input_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + status = mbedtls_to_psa_error( + mbedtls_ccm_update_ad( &operation->ctx.ccm, input, input_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) + { + status = mbedtls_to_psa_error( + mbedtls_chachapoly_update_aad( &operation->ctx.chachapoly, + input, + input_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + ( void ) operation; + ( void ) input; + ( void ) input_length; + + return ( PSA_ERROR_NOT_SUPPORTED ); + } + + return ( status ); +} + +/* Encrypt or decrypt a message fragment in an active multipart AEAD + * operation.*/ +psa_status_t mbedtls_psa_aead_update( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + size_t update_output_length; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + update_output_length = input_length; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if( operation->alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_update( &operation->ctx.gcm, + input, input_length, + output, output_size, + &update_output_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + if( output_size < input_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ccm_update( &operation->ctx.ccm, + input, input_length, + output, output_size, + &update_output_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) + { + if( output_size < input_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_update( &operation->ctx.chachapoly, + input_length, + input, + output ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + ( void ) operation; + ( void ) input; + ( void ) output; + ( void ) output_size; + + return ( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status == PSA_SUCCESS ) + *output_length = update_output_length; + + return( status ); +} + +/* Finish encrypting a message in a multipart AEAD operation. */ +psa_status_t mbedtls_psa_aead_finish( + mbedtls_psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t finish_output_size = 0; + + if( tag_size < operation->tag_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + if( operation->alg == PSA_ALG_GCM ) + { + status = mbedtls_to_psa_error( + mbedtls_gcm_finish( &operation->ctx.gcm, + ciphertext, ciphertext_size, ciphertext_length, + tag, operation->tag_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + if( operation->alg == PSA_ALG_CCM ) + { + /* tag must be big enough to store a tag of size passed into set + * lengths. */ + if( tag_size < operation->tag_length ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ccm_finish( &operation->ctx.ccm, + tag, operation->tag_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + if( operation->alg == PSA_ALG_CHACHA20_POLY1305 ) + { + /* Belt and braces. Although the above tag_size check should have + * already done this, if we later start supporting smaller tag sizes + * for chachapoly, then passing a tag buffer smaller than 16 into here + * could cause a buffer overflow, so better safe than sorry. */ + if( tag_size < 16 ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_chachapoly_finish( &operation->ctx.chachapoly, + tag ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + { + ( void ) ciphertext; + ( void ) ciphertext_size; + ( void ) ciphertext_length; + ( void ) tag; + ( void ) tag_size; + ( void ) tag_length; + + return ( PSA_ERROR_NOT_SUPPORTED ); + } + + if( status == PSA_SUCCESS ) + { + /* This will be zero for all supported algorithms currently, but left + * here for future support. */ + *ciphertext_length = finish_output_size; + *tag_length = operation->tag_length; + } + + return ( status ); +} + +/* Abort an AEAD operation */ +psa_status_t mbedtls_psa_aead_abort( + mbedtls_psa_aead_operation_t *operation ) +{ + switch( operation->alg ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM) + case PSA_ALG_CCM: + mbedtls_ccm_free( &operation->ctx.ccm ); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM) + case PSA_ALG_GCM: + mbedtls_gcm_free( &operation->ctx.gcm ); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305) + case PSA_ALG_CHACHA20_POLY1305: + mbedtls_chachapoly_free( &operation->ctx.chachapoly ); + break; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */ + } + + operation->is_encrypt = 0; + + return( PSA_SUCCESS ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ + diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.h new file mode 100644 index 00000000..e82e1cc0 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_aead.h @@ -0,0 +1,511 @@ +/* + * PSA AEAD driver entry points + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_AEAD_H +#define PSA_CRYPTO_AEAD_H + +#include + +/** + * \brief Process an authenticated encryption operation. + * + * \note The signature of this function is that of a PSA driver + * aead_encrypt entry point. This function behaves as an aead_encrypt + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param alg The AEAD algorithm to compute. + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the nonce buffer in bytes. This must + * be appropriate for the selected algorithm. + * The default nonce size is + * PSA_AEAD_NONCE_LENGTH(key_type, alg) where + * key_type is the type of key. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and encrypted. + * \param plaintext_length Size of plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag are + * defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the ciphertext buffer in bytes. This + * must be appropriate for the selected algorithm + * and key: + * - A sufficient output size is + * PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, + * plaintext_length) where key_type is the type + * of key. + * - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE( + * plaintext_length) evaluates to the maximum + * ciphertext size of any supported AEAD + * encryption. + * \param[out] ciphertext_length On success, the size of the output in the + * ciphertext buffer. + * + * \retval #PSA_SUCCESS Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * ciphertext_size is too small. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_aead_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *plaintext, size_t plaintext_length, + uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ); + +/** + * \brief Process an authenticated decryption operation. + * + * \note The signature of this function is that of a PSA driver + * aead_decrypt entry point. This function behaves as an aead_decrypt + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param alg The AEAD algorithm to compute. + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the nonce buffer in bytes. This must + * be appropriate for the selected algorithm. + * The default nonce size is + * PSA_AEAD_NONCE_LENGTH(key_type, alg) where + * key_type is the type of key. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the encrypted + * data and the authentication tag are defined + * as separate inputs, the buffer contains + * encrypted data followed by the authentication + * tag. + * \param ciphertext_length Size of ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the plaintext buffer in bytes. This + * must be appropriate for the selected algorithm + * and key: + * - A sufficient output size is + * PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, + * ciphertext_length) where key_type is the + * type of key. + * - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE( + * ciphertext_length) evaluates to the maximum + * plaintext size of any supported AEAD + * decryption. + * \param[out] plaintext_length On success, the size of the output in the + * plaintext buffer. + * + * \retval #PSA_SUCCESS Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The cipher is not authentic. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * plaintext_size is too small. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_aead_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *ciphertext, size_t ciphertext_length, + uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ); + +/** Set the key for a multipart authenticated encryption operation. + * + * \note The signature of this function is that of a PSA driver + * aead_encrypt_setup entry point. This function behaves as an + * aead_encrypt_setup entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * If an error occurs at any step after a call to + * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a + * call to mbedtls_psa_aead_abort(). The PSA core may call + * mbedtls_psa_aead_abort() at any time after the operation has been + * initialized, and is required to when the operation is no longer needed. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #mbedtls_psa_aead_operation_t and not yet in + * use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + It must be consistent with the size in bits + recorded in \p attributes. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An invalid block length was supplied. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Failed to allocate memory for key material + */ +psa_status_t mbedtls_psa_aead_encrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ); + +/** Set the key for a multipart authenticated decryption operation. + * + * \note The signature of this function is that of a PSA driver + * aead_decrypt_setup entry point. This function behaves as an + * aead_decrypt_setup entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * If an error occurs at any step after a call to + * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a + * call to mbedtls_psa_aead_abort(). The PSA core may call + * mbedtls_psa_aead_abort() at any time after the operation has been + * initialized, and is required to when the operation is no longer needed. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #mbedtls_psa_aead_operation_t and not yet in + * use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + It must be consistent with the size in bits + recorded in \p attributes. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * An invalid block length was supplied. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Failed to allocate memory for key material + */ +psa_status_t mbedtls_psa_aead_decrypt_setup( + mbedtls_psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * \note The signature of this function is that of a PSA driver aead_set_nonce + * entry point. This function behaves as an aead_set_nonce entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The PSA core calls mbedtls_psa_aead_encrypt_setup() or + * mbedtls_psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the PSA core will call + * mbedtls_psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Algorithm previously set is not supported in this configuration of + * the library. + */ +psa_status_t mbedtls_psa_aead_set_nonce( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length ); + +/** Declare the lengths of the message and additional data for AEAD. + * + * \note The signature of this function is that of a PSA driver aead_set_lengths + * entry point. This function behaves as an aead_set_lengths entry point + * as defined in the PSA driver interface specification for transparent + * drivers. + * + * The PSA core calls this function before calling mbedtls_psa_aead_update_ad() + * or mbedtls_psa_aead_update() if the algorithm for the operation requires it. + * If the algorithm does not require it, calling this function is optional, but + * if this function is called then the implementation must enforce the lengths. + * + * The PSA core may call this function before or after setting the nonce with + * mbedtls_psa_aead_set_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * + * If this function returns an error status, the PSA core calls + * mbedtls_psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Algorithm previously set is not supported in this configuration of + * the library. + */ +psa_status_t mbedtls_psa_aead_set_lengths( + mbedtls_psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length ); + +/** Pass additional data to an active AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_update_ad entry point. This function behaves as an aead_update_ad + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * Additional data is authenticated, but not encrypted. + * + * The PSA core can call this function multiple times to pass successive + * fragments of the additional data. It will not call this function after + * passing data to encrypt or decrypt with mbedtls_psa_aead_update(). + * + * Before calling this function, the PSA core will: + * 1. Call either mbedtls_psa_aead_encrypt_setup() or + * mbedtls_psa_aead_decrypt_setup(). + * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). + * + * If this function returns an error status, the PSA core will call + * mbedtls_psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Algorithm previously set is not supported in this configuration of + * the library. + */ +psa_status_t mbedtls_psa_aead_update_ad( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length ); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_update entry point. This function behaves as an aead_update entry + * point as defined in the PSA driver interface specification for + * transparent drivers. + * + * Before calling this function, the PSA core will: + * 1. Call either mbedtls_psa_aead_encrypt_setup() or + * mbedtls_psa_aead_decrypt_setup(). The choice of setup function + * determines whether this function encrypts or decrypts its input. + * 2. Set the nonce with mbedtls_psa_aead_set_nonce(). + * 3. Call mbedtls_psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the PSA core will call + * mbedtls_psa_aead_abort(). + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides + * sufficient input. The amount of data that can be delayed in this way is + * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, + * \c alg, \p input_length) where + * \c key_type is the type of key and \c alg is + * the algorithm that were used to set up the + * operation. + * - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p + * input_length) evaluates to the maximum + * output size of any supported AEAD + * algorithm. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or + * #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to + * determine the required buffer size. + */ +psa_status_t mbedtls_psa_aead_update( + mbedtls_psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +/** Finish encrypting a message in an AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_finish entry point. This function behaves as an aead_finish entry + * point as defined in the PSA driver interface specification for + * transparent drivers. + * + * The operation must have been set up by the PSA core with + * mbedtls_psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to mbedtls_psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to mbedtls_psa_aead_update(). + * - \p tag contains the authentication tag. + * + * Whether or not this function returns successfuly, the PSA core subsequently + * calls mbedtls_psa_aead_abort() to deactivate the operation. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - A sufficient output size is + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type, + * \c alg) where \c key_type is the type of key + * and \c alg is the algorithm that were used to + * set up the operation. + * - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to + * the maximum output size of any supported AEAD + * algorithm. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be appropriate for the selected + * algorithm and key: + * - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c + * key_type, \c key_bits, \c alg) where + * \c key_type and \c key_bits are the type and + * bit-size of the key, and \c alg are the + * algorithm that were used in the call to + * mbedtls_psa_aead_encrypt_setup(). + * - #PSA_AEAD_TAG_MAX_SIZE evaluates to the + * maximum tag size of any supported AEAD + * algorithm. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p tag buffer is too small. + * #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or + * #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag + * buffer size. + */ +psa_status_t mbedtls_psa_aead_finish( + mbedtls_psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length ); + +/** Abort an AEAD operation. + * + * \note The signature of this function is that of a PSA driver + * aead_abort entry point. This function behaves as an aead_abort entry + * point as defined in the PSA driver interface specification for + * transparent drivers. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by the PSA core by it calling + * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again. + * + * The PSA core may call this function any time after the operation object has + * been initialized as described in #mbedtls_psa_aead_operation_t. + * + * In particular, calling mbedtls_psa_aead_abort() after the operation has been + * terminated by a call to mbedtls_psa_aead_abort() or + * mbedtls_psa_aead_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * Success. + */ +psa_status_t mbedtls_psa_aead_abort( + mbedtls_psa_aead_operation_t *operation ); + +#endif /* PSA_CRYPTO_AEAD */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.c new file mode 100644 index 00000000..852070c0 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.c @@ -0,0 +1,556 @@ +/* + * PSA cipher driver entry points + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_random_impl.h" + +#include "mbedtls/cipher.h" +#include "mbedtls/error.h" + +#include + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, + psa_key_type_t key_type, + size_t key_bits, + mbedtls_cipher_id_t* cipher_id ) +{ + mbedtls_cipher_mode_t mode; + mbedtls_cipher_id_t cipher_id_tmp; + + if( PSA_ALG_IS_AEAD( alg ) ) + alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 ); + + if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) ) + { + switch( alg ) + { + case PSA_ALG_STREAM_CIPHER: + mode = MBEDTLS_MODE_STREAM; + break; + case PSA_ALG_CTR: + mode = MBEDTLS_MODE_CTR; + break; + case PSA_ALG_CFB: + mode = MBEDTLS_MODE_CFB; + break; + case PSA_ALG_OFB: + mode = MBEDTLS_MODE_OFB; + break; + case PSA_ALG_ECB_NO_PADDING: + mode = MBEDTLS_MODE_ECB; + break; + case PSA_ALG_CBC_NO_PADDING: + mode = MBEDTLS_MODE_CBC; + break; + case PSA_ALG_CBC_PKCS7: + mode = MBEDTLS_MODE_CBC; + break; + case PSA_ALG_CCM_STAR_NO_TAG: + mode = MBEDTLS_MODE_CCM_STAR_NO_TAG; + break; + case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ): + mode = MBEDTLS_MODE_CCM; + break; + case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ): + mode = MBEDTLS_MODE_GCM; + break; + case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ): + mode = MBEDTLS_MODE_CHACHAPOLY; + break; + default: + return( NULL ); + } + } + else if( alg == PSA_ALG_CMAC ) + mode = MBEDTLS_MODE_ECB; + else + return( NULL ); + + switch( key_type ) + { + case PSA_KEY_TYPE_AES: + cipher_id_tmp = MBEDTLS_CIPHER_ID_AES; + break; + case PSA_KEY_TYPE_ARIA: + cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA; + break; + case PSA_KEY_TYPE_DES: + /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES, + * and 192 for three-key Triple-DES. */ + if( key_bits == 64 ) + cipher_id_tmp = MBEDTLS_CIPHER_ID_DES; + else + cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES; + /* mbedtls doesn't recognize two-key Triple-DES as an algorithm, + * but two-key Triple-DES is functionally three-key Triple-DES + * with K1=K3, so that's how we present it to mbedtls. */ + if( key_bits == 128 ) + key_bits = 192; + break; + case PSA_KEY_TYPE_CAMELLIA: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA; + break; + case PSA_KEY_TYPE_CHACHA20: + cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20; + break; + default: + return( NULL ); + } + if( cipher_id != NULL ) + *cipher_id = cipher_id_tmp; + + return( mbedtls_cipher_info_from_values( cipher_id_tmp, + (int) key_bits, mode ) ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + +static psa_status_t psa_cipher_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + mbedtls_operation_t cipher_operation ) +{ + int ret = 0; + size_t key_bits; + const mbedtls_cipher_info_t *cipher_info = NULL; + psa_key_type_t key_type = attributes->core.type; + + (void)key_buffer_size; + + mbedtls_cipher_init( &operation->ctx.cipher ); + + operation->alg = alg; + key_bits = attributes->core.bits; + cipher_info = mbedtls_cipher_info_from_psa( alg, key_type, + key_bits, NULL ); + if( cipher_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + ret = mbedtls_cipher_setup( &operation->ctx.cipher, cipher_info ); + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) + if( key_type == PSA_KEY_TYPE_DES && key_bits == 128 ) + { + /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */ + uint8_t keys[24]; + memcpy( keys, key_buffer, 16 ); + memcpy( keys + 16, key_buffer, 8 ); + ret = mbedtls_cipher_setkey( &operation->ctx.cipher, + keys, + 192, cipher_operation ); + } + else +#endif + { + ret = mbedtls_cipher_setkey( &operation->ctx.cipher, key_buffer, + (int) key_bits, cipher_operation ); + } + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) + switch( alg ) + { + case PSA_ALG_CBC_NO_PADDING: + ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + MBEDTLS_PADDING_NONE ); + break; + case PSA_ALG_CBC_PKCS7: + ret = mbedtls_cipher_set_padding_mode( &operation->ctx.cipher, + MBEDTLS_PADDING_PKCS7 ); + break; + default: + /* The algorithm doesn't involve padding. */ + ret = 0; + break; + } + if( ret != 0 ) + goto exit; +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING || + MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */ + + operation->block_length = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 : + PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) ); + operation->iv_length = PSA_CIPHER_IV_LENGTH( key_type, alg ); + +exit: + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t mbedtls_psa_cipher_encrypt_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, attributes, + key_buffer, key_buffer_size, + alg, MBEDTLS_ENCRYPT ) ); +} + +psa_status_t mbedtls_psa_cipher_decrypt_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + return( psa_cipher_setup( operation, attributes, + key_buffer, key_buffer_size, + alg, MBEDTLS_DECRYPT ) ); +} + +psa_status_t mbedtls_psa_cipher_set_iv( + mbedtls_psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length ) +{ + if( iv_length != operation->iv_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + return( mbedtls_to_psa_error( + mbedtls_cipher_set_iv( &operation->ctx.cipher, + iv, iv_length ) ) ); +} + +/** Process input for which the algorithm is set to ECB mode. + * + * This requires manual processing, since the PSA API is defined as being + * able to process arbitrary-length calls to psa_cipher_update() with ECB mode, + * but the underlying mbedtls_cipher_update only takes full blocks. + * + * \param ctx The mbedtls cipher context to use. It must have been + * set up for ECB. + * \param[in] input The input plaintext or ciphertext to process. + * \param input_length The number of bytes to process from \p input. + * This does not need to be aligned to a block boundary. + * If there is a partial block at the end of the input, + * it is stored in \p ctx for future processing. + * \param output The buffer where the output is written. It must be + * at least `BS * floor((p + input_length) / BS)` bytes + * long, where `p` is the number of bytes in the + * unprocessed partial block in \p ctx (with + * `0 <= p <= BS - 1`) and `BS` is the block size. + * \param output_length On success, the number of bytes written to \p output. + * \c 0 on error. + * + * \return #PSA_SUCCESS or an error from a hardware accelerator + */ +static psa_status_t psa_cipher_update_ecb( + mbedtls_cipher_context_t *ctx, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t block_size = ctx->cipher_info->block_size; + size_t internal_output_length = 0; + *output_length = 0; + + if( input_length == 0 ) + { + status = PSA_SUCCESS; + goto exit; + } + + if( ctx->unprocessed_len > 0 ) + { + /* Fill up to block size, and run the block if there's a full one. */ + size_t bytes_to_copy = block_size - ctx->unprocessed_len; + + if( input_length < bytes_to_copy ) + bytes_to_copy = input_length; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), + input, bytes_to_copy ); + input_length -= bytes_to_copy; + input += bytes_to_copy; + ctx->unprocessed_len += bytes_to_copy; + + if( ctx->unprocessed_len == block_size ) + { + status = mbedtls_to_psa_error( + mbedtls_cipher_update( ctx, + ctx->unprocessed_data, + block_size, + output, &internal_output_length ) ); + + if( status != PSA_SUCCESS ) + goto exit; + + output += internal_output_length; + *output_length += internal_output_length; + ctx->unprocessed_len = 0; + } + } + + while( input_length >= block_size ) + { + /* Run all full blocks we have, one by one */ + status = mbedtls_to_psa_error( + mbedtls_cipher_update( ctx, input, + block_size, + output, &internal_output_length ) ); + + if( status != PSA_SUCCESS ) + goto exit; + + input_length -= block_size; + input += block_size; + + output += internal_output_length; + *output_length += internal_output_length; + } + + if( input_length > 0 ) + { + /* Save unprocessed bytes for later processing */ + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), + input, input_length ); + ctx->unprocessed_len += input_length; + } + + status = PSA_SUCCESS; + +exit: + return( status ); +} + +psa_status_t mbedtls_psa_cipher_update( + mbedtls_psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t expected_output_size; + + if( ! PSA_ALG_IS_STREAM_CIPHER( operation->alg ) ) + { + /* Take the unprocessed partial block left over from previous + * update calls, if any, plus the input to this call. Remove + * the last partial block, if any. You get the data that will be + * output in this call. */ + expected_output_size = + ( operation->ctx.cipher.unprocessed_len + input_length ) + / operation->block_length * operation->block_length; + } + else + { + expected_output_size = input_length; + } + + if( output_size < expected_output_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + if( operation->alg == PSA_ALG_ECB_NO_PADDING ) + { + /* mbedtls_cipher_update has an API inconsistency: it will only + * process a single block at a time in ECB mode. Abstract away that + * inconsistency here to match the PSA API behaviour. */ + status = psa_cipher_update_ecb( &operation->ctx.cipher, + input, + input_length, + output, + output_length ); + } + else + { + status = mbedtls_to_psa_error( + mbedtls_cipher_update( &operation->ctx.cipher, input, + input_length, output, output_length ) ); + + if( *output_length > output_size ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + } + + return( status ); +} + +psa_status_t mbedtls_psa_cipher_finish( + mbedtls_psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_GENERIC_ERROR; + uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; + + if( operation->ctx.cipher.unprocessed_len != 0 ) + { + if( operation->alg == PSA_ALG_ECB_NO_PADDING || + operation->alg == PSA_ALG_CBC_NO_PADDING ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + } + + status = mbedtls_to_psa_error( + mbedtls_cipher_finish( &operation->ctx.cipher, + temp_output_buffer, + output_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + if( *output_length == 0 ) + ; /* Nothing to copy. Note that output may be NULL in this case. */ + else if( output_size >= *output_length ) + memcpy( output, temp_output_buffer, *output_length ); + else + status = PSA_ERROR_BUFFER_TOO_SMALL; + +exit: + mbedtls_platform_zeroize( temp_output_buffer, + sizeof( temp_output_buffer ) ); + + return( status ); +} + +psa_status_t mbedtls_psa_cipher_abort( + mbedtls_psa_cipher_operation_t *operation ) +{ + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + if( ! PSA_ALG_IS_CIPHER( operation->alg ) ) + return( PSA_ERROR_BAD_STATE ); + + mbedtls_cipher_free( &operation->ctx.cipher ); + + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *iv, + size_t iv_length, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; + size_t update_output_length, finish_output_length; + + status = mbedtls_psa_cipher_encrypt_setup( &operation, attributes, + key_buffer, key_buffer_size, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + if( iv_length > 0 ) + { + status = mbedtls_psa_cipher_set_iv( &operation, iv, iv_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = mbedtls_psa_cipher_update( &operation, input, input_length, + output, output_size, + &update_output_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = mbedtls_psa_cipher_finish( &operation, + output + update_output_length, + output_size - update_output_length, + &finish_output_length ); + if( status != PSA_SUCCESS ) + goto exit; + + *output_length = update_output_length + finish_output_length; + +exit: + if( status == PSA_SUCCESS ) + status = mbedtls_psa_cipher_abort( &operation ); + else + mbedtls_psa_cipher_abort( &operation ); + + return( status ); +} + +psa_status_t mbedtls_psa_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT; + size_t olength, accumulated_length; + + status = mbedtls_psa_cipher_decrypt_setup( &operation, attributes, + key_buffer, key_buffer_size, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + if( operation.iv_length > 0 ) + { + status = mbedtls_psa_cipher_set_iv( &operation, + input, operation.iv_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = mbedtls_psa_cipher_update( &operation, input + operation.iv_length, + input_length - operation.iv_length, + output, output_size, &olength ); + if( status != PSA_SUCCESS ) + goto exit; + + accumulated_length = olength; + + status = mbedtls_psa_cipher_finish( &operation, output + accumulated_length, + output_size - accumulated_length, + &olength ); + if( status != PSA_SUCCESS ) + goto exit; + + *output_length = accumulated_length + olength; + +exit: + if ( status == PSA_SUCCESS ) + status = mbedtls_psa_cipher_abort( &operation ); + else + mbedtls_psa_cipher_abort( &operation ); + + return( status ); +} +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.h new file mode 100644 index 00000000..fae98473 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_cipher.h @@ -0,0 +1,305 @@ +/* + * PSA cipher driver entry points + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_CIPHER_H +#define PSA_CRYPTO_CIPHER_H + +#include +#include + +/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier + * as well as the PSA type and size of the key to be used with the cipher + * algorithm. + * + * \param alg PSA cipher algorithm identifier + * \param key_type PSA key type + * \param key_bits Size of the key in bits + * \param[out] cipher_id Mbed TLS cipher algorithm identifier + * + * \return The Mbed TLS cipher information of the cipher algorithm. + * \c NULL if the PSA cipher algorithm is not supported. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, + mbedtls_cipher_id_t *cipher_id ); + +/** + * \brief Set the key for a multipart symmetric encryption operation. + * + * \note The signature of this function is that of a PSA driver + * cipher_encrypt_setup entry point. This function behaves as a + * cipher_encrypt_setup entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation The operation object to set up. It has been + * initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_cipher_encrypt_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ); + +/** + * \brief Set the key for a multipart symmetric decryption operation. + * + * \note The signature of this function is that of a PSA driver + * cipher_decrypt_setup entry point. This function behaves as a + * cipher_decrypt_setup entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation The operation object to set up. It has been + * initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_cipher_decrypt_setup( + mbedtls_psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * \note The signature of this function is that of a PSA driver + * cipher_set_iv entry point. This function behaves as a + * cipher_set_iv entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param[in] iv_length Size of the IV in bytes. It is guaranteed by + * the core to be less or equal to + * PSA_CIPHER_IV_MAX_SIZE. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_cipher_set_iv( + mbedtls_psa_cipher_operation_t *operation, + const uint8_t *iv, size_t iv_length ); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * \note The signature of this function is that of a PSA driver + * cipher_update entry point. This function behaves as a + * cipher_update entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param[in] output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_cipher_update( + mbedtls_psa_cipher_operation_t *operation, + const uint8_t *input, size_t input_length, + uint8_t *output, size_t output_size, size_t *output_length ); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * \note The signature of this function is that of a PSA driver + * cipher_finish entry point. This function behaves as a + * cipher_finish entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param[in] output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_cipher_finish( + mbedtls_psa_cipher_operation_t *operation, + uint8_t *output, size_t output_size, size_t *output_length ); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation. + * + * \note The signature of this function is that of a PSA driver + * cipher_abort entry point. This function behaves as a + * cipher_abort entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + */ +psa_status_t mbedtls_psa_cipher_abort( mbedtls_psa_cipher_operation_t *operation ); + +/** Encrypt a message using a symmetric cipher. + * + * \note The signature of this function is that of a PSA driver + * cipher_encrypt entry point. This function behaves as a + * cipher_encrypt entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] iv Buffer containing the IV for encryption. The + * IV has been generated by the core. + * \param[in] iv_length Size of the \p iv in bytes. + * \param[in] input Buffer containing the message to encrypt. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[in,out] output Buffer where the output is to be written. + * \param[in] output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes that make up + * the returned output. Initialized to zero + * by the core. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size \p iv_length is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + */ +psa_status_t mbedtls_psa_cipher_encrypt( const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *iv, + size_t iv_length, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +/** Decrypt a message using a symmetric cipher. + * + * \note The signature of this function is that of a PSA driver + * cipher_decrypt entry point. This function behaves as a + * cipher_decrypt entry point as defined in the PSA driver + * interface specification for transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the iv and the ciphertext. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param[in] output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes that make up + * the returned output. Initialized to zero + * by the core. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p iv is not acceptable for the chosen algorithm, + * or the chosen algorithm does not use an IV. + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + */ +psa_status_t mbedtls_psa_cipher_decrypt( const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +#endif /* PSA_CRYPTO_CIPHER_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_client.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_client.c new file mode 100644 index 00000000..629feb7d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_client.c @@ -0,0 +1,82 @@ +/* + * PSA crypto client code + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" +#include "psa/crypto.h" + +#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) + +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +void psa_reset_key_attributes( psa_key_attributes_t *attributes ) +{ + mbedtls_free( attributes->domain_parameters ); + memset( attributes, 0, sizeof( *attributes ) ); +} + +psa_status_t psa_set_key_domain_parameters( psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length ) +{ + uint8_t *copy = NULL; + + if( data_length != 0 ) + { + copy = mbedtls_calloc( 1, data_length ); + if( copy == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( copy, data, data_length ); + } + /* After this point, this function is guaranteed to succeed, so it + * can start modifying `*attributes`. */ + + if( attributes->domain_parameters != NULL ) + { + mbedtls_free( attributes->domain_parameters ); + attributes->domain_parameters = NULL; + attributes->domain_parameters_size = 0; + } + + attributes->domain_parameters = copy; + attributes->domain_parameters_size = data_length; + attributes->core.type = type; + return( PSA_SUCCESS ); +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + if( attributes->domain_parameters_size > data_size ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + *data_length = attributes->domain_parameters_size; + if( attributes->domain_parameters_size != 0 ) + memcpy( data, attributes->domain_parameters, + attributes->domain_parameters_size ); + return( PSA_SUCCESS ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_core.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_core.h new file mode 100644 index 00000000..8c91b04d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_core.h @@ -0,0 +1,550 @@ +/* + * PSA crypto core internal interfaces + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_CORE_H +#define PSA_CRYPTO_CORE_H + +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +/** Constant-time buffer comparison + * + * \param[in] a Left-hand buffer for comparison. + * \param[in] b Right-hand buffer for comparison. + * \param n Amount of bytes to compare. + * + * \return 0 if the buffer contents are equal, non-zero otherwise + */ +static inline int mbedtls_psa_safer_memcmp( + const uint8_t *a, const uint8_t *b, size_t n ) +{ + size_t i; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= a[i] ^ b[i]; + + return( diff ); +} + +/** The data structure representing a key slot, containing key material + * and metadata for one key. + */ +typedef struct +{ + psa_core_key_attributes_t attr; + + /* + * Number of locks on the key slot held by the library. + * + * This counter is incremented by one each time a library function + * retrieves through one of the dedicated internal API a pointer to the + * key slot. + * + * This counter is decremented by one each time a library function stops + * accessing the key slot and states it by calling the + * psa_unlock_key_slot() API. + * + * This counter is used to prevent resetting the key slot while the library + * may access it. For example, such control is needed in the following + * scenarios: + * . In case of key slot starvation, all key slots contain the description + * of a key, and the library asks for the description of a persistent + * key not present in the key slots, the key slots currently accessed by + * the library cannot be reclaimed to free a key slot to load the + * persistent key. + * . In case of a multi-threaded application where one thread asks to close + * or purge or destroy a key while it is in used by the library through + * another thread. + */ + size_t lock_count; + + /* Dynamically allocated key data buffer. + * Format as specified in psa_export_key(). */ + struct key_data + { + uint8_t *data; + size_t bytes; + } key; +} psa_key_slot_t; + +/* A mask of key attribute flags used only internally. + * Currently there aren't any. */ +#define PSA_KA_MASK_INTERNAL_ONLY ( \ + 0 ) + +/** Test whether a key slot is occupied. + * + * A key slot is occupied iff the key type is nonzero. This works because + * no valid key can have 0 as its key type. + * + * \param[in] slot The key slot to test. + * + * \return 1 if the slot is occupied, 0 otherwise. + */ +static inline int psa_is_key_slot_occupied( const psa_key_slot_t *slot ) +{ + return( slot->attr.type != 0 ); +} + +/** Test whether a key slot is locked. + * + * A key slot is locked iff its lock counter is strictly greater than 0. + * + * \param[in] slot The key slot to test. + * + * \return 1 if the slot is locked, 0 otherwise. + */ +static inline int psa_is_key_slot_locked( const psa_key_slot_t *slot ) +{ + return( slot->lock_count > 0 ); +} + +/** Retrieve flags from psa_key_slot_t::attr::core::flags. + * + * \param[in] slot The key slot to query. + * \param mask The mask of bits to extract. + * + * \return The key attribute flags in the given slot, + * bitwise-anded with \p mask. + */ +static inline uint16_t psa_key_slot_get_flags( const psa_key_slot_t *slot, + uint16_t mask ) +{ + return( slot->attr.flags & mask ); +} + +/** Set flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to modify. + * \param value The new value of the selected bits. + */ +static inline void psa_key_slot_set_flags( psa_key_slot_t *slot, + uint16_t mask, + uint16_t value ) +{ + slot->attr.flags = ( ( ~mask & slot->attr.flags ) | + ( mask & value ) ); +} + +/** Turn on flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to set. + */ +static inline void psa_key_slot_set_bits_in_flags( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags |= mask; +} + +/** Turn off flags in psa_key_slot_t::attr::core::flags. + * + * \param[in,out] slot The key slot to modify. + * \param mask The mask of bits to clear. + */ +static inline void psa_key_slot_clear_bits( psa_key_slot_t *slot, + uint16_t mask ) +{ + slot->attr.flags &= ~mask; +} + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/** Get the SE slot number of a key from the key slot storing its description. + * + * \param[in] slot The key slot to query. This must be a key slot storing + * the description of a key of a dynamically registered + * secure element, otherwise the behaviour is undefined. + */ +static inline psa_key_slot_number_t psa_key_slot_get_slot_number( + const psa_key_slot_t *slot ) +{ + return( *( (psa_key_slot_number_t *)( slot->key.data ) ) ); +} +#endif + +/** Completely wipe a slot in memory, including its policy. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to wipe. + * + * \retval #PSA_SUCCESS + * Success. This includes the case of a key slot that was + * already fully wiped. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); + +/** Try to allocate a buffer to an empty key slot. + * + * \param[in,out] slot Key slot to attach buffer to. + * \param[in] buffer_length Requested size of the buffer. + * + * \retval #PSA_SUCCESS + * The buffer has been successfully allocated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Not enough memory was available for allocation. + * \retval #PSA_ERROR_ALREADY_EXISTS + * Trying to allocate a buffer to a non-empty key slot. + */ +psa_status_t psa_allocate_buffer_to_slot( psa_key_slot_t *slot, + size_t buffer_length ); + +/** Wipe key data from a slot. Preserves metadata such as the policy. */ +psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ); + +/** Copy key data (in export format) into an empty key slot. + * + * This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. + * + * \param[in,out] slot Key slot to copy the key into. + * \param[in] data Buffer containing the key material. + * \param data_length Size of the key buffer. + * + * \retval #PSA_SUCCESS + * The key has been copied successfully. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * Not enough memory was available for allocation of the + * copy buffer. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There was other key material already present in the slot. + */ +psa_status_t psa_copy_key_material_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ); + +/** Convert an mbed TLS error code to a PSA error code + * + * \note This function is provided solely for the convenience of + * Mbed TLS and may be removed at any time without notice. + * + * \param ret An mbed TLS-thrown error code + * + * \return The corresponding PSA error code + */ +psa_status_t mbedtls_to_psa_error( int ret ); + +/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier + * as well as the PSA type and size of the key to be used with the cipher + * algorithm. + * + * \param alg PSA cipher algorithm identifier + * \param key_type PSA key type + * \param key_bits Size of the key in bits + * \param[out] cipher_id Mbed TLS cipher algorithm identifier + * + * \return The Mbed TLS cipher information of the cipher algorithm. + * \c NULL if the PSA cipher algorithm is not supported. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa( + psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits, + mbedtls_cipher_id_t *cipher_id ); + +/** Import a key in binary format. + * + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer to contain the key data in output + * format upon successful return. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t psa_import_key_into_slot( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + +/** Export a key in binary format + * + * \note The signature of this function is that of a PSA driver export_key + * entry point. This function behaves as an export_key entry point as + * defined in the PSA driver interface specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_export_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +/** Export a public key or the public part of a key pair in binary format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_export_public_key_internal( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +/** + * \brief Generate a key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was generated successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key size in bits or type not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t psa_generate_key_internal( const psa_key_attributes_t *attributes, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length ); + +/** Sign a message with a private key. For hash-and-sign algorithms, + * this includes the hashing step. + * + * \note The signature of this function is that of a PSA driver + * sign_message entry point. This function behaves as a sign_message + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \note This function will call the driver for psa_sign_hash + * and go through driver dispatch again. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * the type of the key. + * \param[in] input The input message to sign. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of the key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_sign_message_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *input, size_t input_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +/** Verify the signature of a message with a public key, using + * a hash-and-sign verification algorithm. + * + * \note The signature of this function is that of a PSA driver + * verify_message entry point. This function behaves as a verify_message + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \note This function will call the driver for psa_verify_hash + * and go through driver dispatch again. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * the type of the key. + * \param[in] input The message whose signature is to be verified. + * \param[in] input_length Size of the \p input buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_verify_message_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *input, size_t input_length, + const uint8_t *signature, size_t signature_length ); + +/** Sign an already-calculated hash with a private key. + * + * \note The signature of this function is that of a PSA driver + * sign_hash entry point. This function behaves as a sign_hash + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * the type of the key. + * \param[in] hash The hash or message to sign. + * \param[in] hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of the key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_sign_hash_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +/** + * \brief Verify the signature a hash or short message using a public key. + * + * \note The signature of this function is that of a PSA driver + * verify_hash entry point. This function behaves as a verify_hash + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key context. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * the type of the key. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param[in] hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_verify_hash_builtin( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ); + +/** + * \brief Validate the key bit size for unstructured keys. + * + * \note Check that the bit size is acceptable for a given key type for + * unstructured keys. + * + * \param[in] type The key type + * \param[in] bits The number of bits of the key + * + * \retval #PSA_SUCCESS + * The key type and size are valid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in bits of the key is not valid. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + */ +psa_status_t psa_validate_unstructured_key_bit_size( psa_key_type_t type, + size_t bits ); +#endif /* PSA_CRYPTO_CORE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.c new file mode 100644 index 00000000..8d864786 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.c @@ -0,0 +1,2335 @@ +/* + * Functions to delegate cryptographic operations to an available + * and appropriate accelerator. + * Warning: This file will be auto-generated in the future. + */ +/* Copyright The Mbed TLS Contributors + * 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 "common.h" +#include "psa_crypto_aead.h" +#include "psa_crypto_cipher.h" +#include "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_hash.h" +#include "psa_crypto_mac.h" + +#include "mbedtls/platform.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + +/* Include test driver definition when running tests */ +#if defined(PSA_CRYPTO_DRIVER_TEST) +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#ifndef PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#define PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT +#endif +#include "test/drivers/test_driver.h" +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Repeat above block for each JSON-declared driver during autogeneration */ +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ + +/* Auto-generated values depending on which drivers are registered. + * ID 0 is reserved for unallocated operations. + * ID 1 is reserved for the Mbed TLS software driver. */ +#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1) + +#if defined(PSA_CRYPTO_DRIVER_TEST) +#define PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID (2) +#define PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID (3) +#endif /* PSA_CRYPTO_DRIVER_TEST */ + +/* Support the 'old' SE interface when asked to */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style + * SE driver is present, to avoid unused argument errors at compile time. */ +#ifndef PSA_CRYPTO_DRIVER_PRESENT +#define PSA_CRYPTO_DRIVER_PRESENT +#endif +#include "psa_crypto_se.h" +#endif + +psa_status_t psa_driver_wrapper_init( void ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + status = psa_init_all_se_drivers( ); + if( status != PSA_SUCCESS ) + return( status ); +#endif + +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_init( ); + if( status != PSA_SUCCESS ) + return( status ); + + status = mbedtls_test_opaque_init( ); + if( status != PSA_SUCCESS ) + return( status ); +#endif + + (void) status; + return( PSA_SUCCESS ); +} + +void psa_driver_wrapper_free( void ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Unregister all secure element drivers, so that we restart from + * a pristine state. */ + psa_unregister_all_se_drivers( ); +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(PSA_CRYPTO_DRIVER_TEST) + mbedtls_test_transparent_free( ); + mbedtls_test_opaque_free( ); +#endif +} + +/* Start delegation functions */ +psa_status_t psa_driver_wrapper_sign_message( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_sign_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_size, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + break; + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_signature_sign_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_size, + signature_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + break; + } + + return( psa_sign_message_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_size, + signature_length ) ); +} + +psa_status_t psa_driver_wrapper_verify_message( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_verify_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + break; + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_signature_verify_message( + attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_length ) ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + break; + } + + return( psa_verify_message_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + signature, + signature_length ) ); +} + +psa_status_t psa_driver_wrapper_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_sign == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_sign( + drv_context, *( (psa_key_slot_number_t *)key_buffer ), + alg, hash, hash_length, + signature, signature_size, signature_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_sign_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_sign_hash_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_signature_sign_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_size, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( drv->asymmetric == NULL || + drv->asymmetric->p_verify == NULL ) + { + /* Key is defined in SE, but we have no way to exercise it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->asymmetric->p_verify( + drv_context, *( (psa_key_slot_number_t *)key_buffer ), + alg, hash, hash_length, + signature, signature_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_signature_verify_hash( + attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + return( psa_verify_hash_builtin( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_signature_verify_hash( attributes, + key_buffer, + key_buffer_size, + alg, + hash, + hash_length, + signature, + signature_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +/** Calculate the key buffer size required to store the key material of a key + * associated with an opaque driver from input key data. + * + * \param[in] attributes The key attributes + * \param[in] data The input key data. + * \param[in] data_length The input data length. + * \param[out] key_buffer_size Minimum buffer size to contain the key material. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_NOT_SUPPORTED + */ +psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *key_buffer_size ) +{ + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + psa_key_type_t key_type = attributes->core.type; + + *key_buffer_size = 0; + switch( location ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + *key_buffer_size = mbedtls_test_opaque_size_function( key_type, + PSA_BYTES_TO_BITS( data_length ) ); + return( ( *key_buffer_size != 0 ) ? + PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + default: + (void)key_type; + (void)data; + (void)data_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +/** Get the key buffer size required to store the key material of a key + * associated with an opaque driver. + * + * \param[in] attributes The key attributes. + * \param[out] key_buffer_size Minimum buffer size to contain the key material + * + * \retval #PSA_SUCCESS + * The minimum size for a buffer to contain the key material has been + * returned successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The type and/or the size in bits of the key or the combination of + * the two is not supported. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is declared with a lifetime not known to us. + */ +psa_status_t psa_driver_wrapper_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size ) +{ + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + psa_key_type_t key_type = attributes->core.type; + size_t key_bits = attributes->core.bits; + + *key_buffer_size = 0; + switch( location ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + /* Emulate property 'builtin_key_size' */ + if( psa_key_id_is_builtin( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( + psa_get_key_id( attributes ) ) ) ) + { + *key_buffer_size = sizeof( psa_drv_slot_number_t ); + return( PSA_SUCCESS ); + } +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + *key_buffer_size = mbedtls_test_opaque_size_function( key_type, + key_bits ); + return( ( *key_buffer_size != 0 ) ? + PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + + default: + (void)key_type; + (void)key_bits; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + size_t pubkey_length = 0; /* We don't support this feature yet */ + if( drv->key_management == NULL || + drv->key_management->p_generate == NULL ) + { + /* Key is defined as being in SE, but we have no way to generate it */ + return( PSA_ERROR_NOT_SUPPORTED ); + } + return( drv->key_management->p_generate( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + attributes, NULL, 0, &pubkey_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) + /* Transparent drivers are limited to generating asymmetric keys */ + if( PSA_KEY_TYPE_IS_ASYMMETRIC( attributes->core.type ) ) + { + /* Cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_generate_key( + attributes, key_buffer, key_buffer_size, + key_buffer_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ + } +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Software fallback */ + status = psa_generate_key_internal( + attributes, key_buffer, key_buffer_size, key_buffer_length ); + break; + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_generate_key( + attributes, key_buffer, key_buffer_size, key_buffer_length ); + break; +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + status = PSA_ERROR_INVALID_ARGUMENT; + break; + } + + return( status ); +} + +psa_status_t psa_driver_wrapper_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + uint8_t *key_buffer, + size_t key_buffer_size, + size_t *key_buffer_length, + size_t *bits ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( drv->key_management == NULL || + drv->key_management->p_import == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + /* The driver should set the number of key bits, however in + * case it doesn't, we initialize bits to an invalid value. */ + *bits = PSA_MAX_KEY_BITS + 1; + status = drv->key_management->p_import( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + attributes, data, data_length, bits ); + + if( status != PSA_SUCCESS ) + return( status ); + + if( (*bits) > PSA_MAX_KEY_BITS ) + return( PSA_ERROR_NOT_SUPPORTED ); + + return( PSA_SUCCESS ); + } +#endif /* PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_import_key( + attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_import_key_into_slot( attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_import_key( + attributes, + data, data_length, + key_buffer, key_buffer_size, + key_buffer_length, bits ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } + +} + +psa_status_t psa_driver_wrapper_export_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) + +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export == NULL ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( drv->key_management->p_export( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + return( psa_export_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_export_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +} + +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) + +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( + psa_get_key_lifetime( attributes ) ); + + /* Try dynamically-registered SE interface first */ +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + if( ( drv->key_management == NULL ) || + ( drv->key_management->p_export_public == NULL ) ) + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + return( drv->key_management->p_export_public( + drv_context, + *( (psa_key_slot_number_t *)key_buffer ), + data, data_size, data_length ) ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_export_public_key( + attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + /* Fell through, meaning no accelerator supports this operation */ + return( psa_export_public_key_internal( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_export_public_key( attributes, + key_buffer, + key_buffer_size, + data, + data_size, + data_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + return( status ); + } +} + +psa_status_t psa_driver_wrapper_get_builtin_key( + psa_drv_slot_number_t slot_number, + psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + switch( location ) + { +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_get_builtin_key( + slot_number, + attributes, + key_buffer, key_buffer_size, key_buffer_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ + default: + (void) slot_number; + (void) key_buffer; + (void) key_buffer_size; + (void) key_buffer_length; + return( PSA_ERROR_DOES_NOT_EXIST ); + } +} + +psa_status_t psa_driver_wrapper_copy_key( + psa_key_attributes_t *attributes, + const uint8_t *source_key, size_t source_key_length, + uint8_t *target_key_buffer, size_t target_key_buffer_size, + size_t *target_key_buffer_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + + if( psa_get_se_driver( attributes->core.lifetime, &drv, &drv_context ) ) + { + /* Copying to a secure element is not implemented yet. */ + return( PSA_ERROR_NOT_SUPPORTED ); + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + switch( location ) + { +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_copy_key( attributes, source_key, + source_key_length, + target_key_buffer, + target_key_buffer_size, + target_key_buffer_length) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void)source_key; + (void)source_key_length; + (void)target_key_buffer; + (void)target_key_buffer_size; + (void)target_key_buffer_length; + status = PSA_ERROR_INVALID_ARGUMENT; + } + return( status ); +} + +/* + * Cipher functions + */ +psa_status_t psa_driver_wrapper_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *iv, + size_t iv_length, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_encrypt( attributes, + key_buffer, + key_buffer_size, + alg, + iv, + iv_length, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + return( mbedtls_psa_cipher_encrypt( attributes, + key_buffer, + key_buffer_size, + alg, + iv, + iv_length, + input, + input_length, + output, + output_size, + output_length ) ); +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_cipher_encrypt( attributes, + key_buffer, + key_buffer_size, + alg, + iv, + iv_length, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + (void)iv; + (void)iv_length; + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_decrypt( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + output, + output_size, + output_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + return( mbedtls_psa_cipher_decrypt( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#else + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + return( mbedtls_test_opaque_cipher_decrypt( attributes, + key_buffer, + key_buffer_size, + alg, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_cipher_encrypt_setup( + psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_encrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_cipher_encrypt_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_cipher_encrypt_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)operation; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_INVALID_ARGUMENT; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_cipher_decrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_cipher_decrypt_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, + key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_cipher_decrypt_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + (void)operation; + (void)key_buffer; + (void)key_buffer_size; + (void)alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_cipher_set_iv( + psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_set_iv( &operation->ctx.mbedtls_ctx, + iv, + iv_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_cipher_set_iv( + &operation->ctx.transparent_test_driver_ctx, + iv, iv_length ) ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_cipher_set_iv( + &operation->ctx.opaque_test_driver_ctx, + iv, iv_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)iv; + (void)iv_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_cipher_update( + psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_update( &operation->ctx.mbedtls_ctx, + input, + input_length, + output, + output_size, + output_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_cipher_update( + &operation->ctx.transparent_test_driver_ctx, + input, input_length, + output, output_size, output_length ) ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_cipher_update( + &operation->ctx.opaque_test_driver_ctx, + input, input_length, + output, output_size, output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_cipher_finish( + psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_finish( &operation->ctx.mbedtls_ctx, + output, + output_size, + output_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_cipher_finish( + &operation->ctx.transparent_test_driver_ctx, + output, output_size, output_length ) ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_cipher_finish( + &operation->ctx.opaque_test_driver_ctx, + output, output_size, output_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)output; + (void)output_size; + (void)output_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_cipher_abort( + psa_cipher_operation_t *operation ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_cipher_abort( &operation->ctx.mbedtls_ctx ) ); +#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + status = mbedtls_test_transparent_cipher_abort( + &operation->ctx.transparent_test_driver_ctx ); + mbedtls_platform_zeroize( + &operation->ctx.transparent_test_driver_ctx, + sizeof( operation->ctx.transparent_test_driver_ctx ) ); + return( status ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + status = mbedtls_test_opaque_cipher_abort( + &operation->ctx.opaque_test_driver_ctx ); + mbedtls_platform_zeroize( + &operation->ctx.opaque_test_driver_ctx, + sizeof( operation->ctx.opaque_test_driver_ctx ) ); + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +/* + * Hashing functions + */ +psa_status_t psa_driver_wrapper_hash_compute( + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Try accelerators first */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_hash_compute( + alg, input, input_length, hash, hash_size, hash_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + + /* If software fallback is compiled in, try fallback */ +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + status = mbedtls_psa_hash_compute( alg, input, input_length, + hash, hash_size, hash_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + (void) status; + (void) alg; + (void) input; + (void) input_length; + (void) hash; + (void) hash_size; + (void) hash_length; + + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_driver_wrapper_hash_setup( + psa_hash_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* Try setup on accelerators first */ +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_hash_setup( + &operation->ctx.test_driver_ctx, alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + + /* If software fallback is compiled in, try fallback */ +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + status = mbedtls_psa_hash_setup( &operation->ctx.mbedtls_ctx, alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif + /* Nothing left to try if we fall through here */ + (void) status; + (void) operation; + (void) alg; + return( PSA_ERROR_NOT_SUPPORTED ); +} + +psa_status_t psa_driver_wrapper_hash_clone( + const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation ) +{ + switch( source_operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + return( mbedtls_psa_hash_clone( &source_operation->ctx.mbedtls_ctx, + &target_operation->ctx.mbedtls_ctx ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + target_operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + return( mbedtls_test_transparent_hash_clone( + &source_operation->ctx.test_driver_ctx, + &target_operation->ctx.test_driver_ctx ) ); +#endif + default: + (void) target_operation; + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t psa_driver_wrapper_hash_update( + psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_hash_update( &operation->ctx.mbedtls_ctx, + input, input_length ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_hash_update( + &operation->ctx.test_driver_ctx, + input, input_length ) ); +#endif + default: + (void) input; + (void) input_length; + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t psa_driver_wrapper_hash_finish( + psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_hash_finish( &operation->ctx.mbedtls_ctx, + hash, hash_size, hash_length ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_hash_finish( + &operation->ctx.test_driver_ctx, + hash, hash_size, hash_length ) ); +#endif + default: + (void) hash; + (void) hash_size; + (void) hash_length; + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t psa_driver_wrapper_hash_abort( + psa_hash_operation_t *operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_HASH) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_hash_abort( &operation->ctx.mbedtls_ctx ) ); +#endif +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_hash_abort( + &operation->ctx.test_driver_ctx ) ); +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t psa_driver_wrapper_aead_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *plaintext, size_t plaintext_length, + uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_aead_encrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + return( mbedtls_psa_aead_encrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + plaintext, plaintext_length, + ciphertext, ciphertext_size, ciphertext_length ) ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_aead_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *ciphertext, size_t ciphertext_length, + uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_aead_decrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + return( mbedtls_psa_aead_decrypt( + attributes, key_buffer, key_buffer_size, + alg, + nonce, nonce_length, + additional_data, additional_data_length, + ciphertext, ciphertext_length, + plaintext, plaintext_size, plaintext_length ) ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_aead_encrypt_setup( + psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + status = mbedtls_test_transparent_aead_encrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, key_buffer, key_buffer_size, + alg ); + + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + status = mbedtls_psa_aead_encrypt_setup( + &operation->ctx.mbedtls_ctx, attributes, + key_buffer, key_buffer_size, + alg ); + + return( status ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_aead_decrypt_setup( + psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + status = mbedtls_test_transparent_aead_decrypt_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + + /* Fell through, meaning no accelerator supports this operation */ + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + status = mbedtls_psa_aead_decrypt_setup( + &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + return( status ); + + /* Add cases for opaque driver here */ + + default: + /* Key is declared with a lifetime not known to us */ + (void)status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_aead_set_nonce( + psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx, + nonce, + nonce_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_set_nonce( + &operation->ctx.transparent_test_driver_ctx, + nonce, nonce_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)nonce; + (void)nonce_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_aead_set_lengths( + psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx, + ad_length, + plaintext_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_set_lengths( + &operation->ctx.transparent_test_driver_ctx, + ad_length, plaintext_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)ad_length; + (void)plaintext_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_aead_update_ad( + psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx, + input, + input_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_update_ad( + &operation->ctx.transparent_test_driver_ctx, + input, input_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)input; + (void)input_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_aead_update( + psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx, + input, input_length, + output, output_size, + output_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_update( + &operation->ctx.transparent_test_driver_ctx, + input, input_length, output, output_size, + output_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)input; + (void)input_length; + (void)output; + (void)output_size; + (void)output_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_aead_finish( + psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, + ciphertext, + ciphertext_size, + ciphertext_length, tag, + tag_size, tag_length ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_finish( + &operation->ctx.transparent_test_driver_ctx, + ciphertext, ciphertext_size, + ciphertext_length, tag, tag_size, tag_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)ciphertext; + (void)ciphertext_size; + (void)ciphertext_length; + (void)tag; + (void)tag_size; + (void)tag_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_aead_verify( + psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + { + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE]; + size_t check_tag_length; + + status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx, + plaintext, + plaintext_size, + plaintext_length, + check_tag, + sizeof( check_tag ), + &check_tag_length ); + + if( status == PSA_SUCCESS ) + { + if( tag_length != check_tag_length || + mbedtls_psa_safer_memcmp( tag, check_tag, tag_length ) + != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + } + + mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) ); + + return( status ); + } + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_verify( + &operation->ctx.transparent_test_driver_ctx, + plaintext, plaintext_size, + plaintext_length, tag, tag_length ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + (void)plaintext; + (void)plaintext_size; + (void)plaintext_length; + (void)tag; + (void)tag_length; + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +psa_status_t psa_driver_wrapper_aead_abort( + psa_aead_operation_t *operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_AEAD) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) ); + +#endif /* MBEDTLS_PSA_BUILTIN_AEAD */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_aead_abort( + &operation->ctx.transparent_test_driver_ctx ) ); + + /* Add cases for opaque driver here */ + +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + } + + return( PSA_ERROR_INVALID_ARGUMENT ); +} + +/* + * MAC functions + */ +psa_status_t psa_driver_wrapper_mac_compute( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_mac_compute( + attributes, key_buffer, key_buffer_size, alg, + input, input_length, + mac, mac_size, mac_length ); + /* Declared with fallback == true */ + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_mac_compute( + attributes, key_buffer, key_buffer_size, alg, + input, input_length, + mac, mac_size, mac_length ); + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_mac_compute( + attributes, key_buffer, key_buffer_size, alg, + input, input_length, + mac, mac_size, mac_length ); + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + (void) input; + (void) input_length; + (void) mac; + (void) mac_size; + (void) mac_length; + (void) status; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_mac_sign_setup( + psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_mac_sign_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_mac_sign_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void) status; + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_mac_verify_setup( + psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_location_t location = + PSA_KEY_LIFETIME_GET_LOCATION( attributes->core.lifetime ); + + switch( location ) + { + case PSA_KEY_LOCATION_LOCAL_STORAGE: + /* Key is stored in the slot in export representation, so + * cycle through all known transparent accelerators */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + status = mbedtls_test_transparent_mac_verify_setup( + &operation->ctx.transparent_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + /* Declared with fallback == true */ + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + /* Fell through, meaning no accelerator supports this operation */ + status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID; + + if( status != PSA_ERROR_NOT_SUPPORTED ) + return( status ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + return( PSA_ERROR_NOT_SUPPORTED ); + + /* Add cases for opaque driver here */ +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TEST_DRIVER_LOCATION: + status = mbedtls_test_opaque_mac_verify_setup( + &operation->ctx.opaque_test_driver_ctx, + attributes, + key_buffer, key_buffer_size, + alg ); + + if( status == PSA_SUCCESS ) + operation->id = PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID; + + return( status ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + /* Key is declared with a lifetime not known to us */ + (void) status; + (void) operation; + (void) key_buffer; + (void) key_buffer_size; + (void) alg; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_mac_update( + psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx, + input, input_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_mac_update( + &operation->ctx.transparent_test_driver_ctx, + input, input_length ) ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_mac_update( + &operation->ctx.opaque_test_driver_ctx, + input, input_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) input; + (void) input_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_mac_sign_finish( + psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx, + mac, mac_size, mac_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_mac_sign_finish( + &operation->ctx.transparent_test_driver_ctx, + mac, mac_size, mac_length ) ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_mac_sign_finish( + &operation->ctx.opaque_test_driver_ctx, + mac, mac_size, mac_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) mac; + (void) mac_size; + (void) mac_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_mac_verify_finish( + psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx, + mac, mac_length ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_mac_verify_finish( + &operation->ctx.transparent_test_driver_ctx, + mac, mac_length ) ); + + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_mac_verify_finish( + &operation->ctx.opaque_test_driver_ctx, + mac, mac_length ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + (void) mac; + (void) mac_length; + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +psa_status_t psa_driver_wrapper_mac_abort( + psa_mac_operation_t *operation ) +{ + switch( operation->id ) + { +#if defined(MBEDTLS_PSA_BUILTIN_MAC) + case PSA_CRYPTO_MBED_TLS_DRIVER_ID: + return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) ); +#endif /* MBEDTLS_PSA_BUILTIN_MAC */ + +#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT) +#if defined(PSA_CRYPTO_DRIVER_TEST) + case PSA_CRYPTO_TRANSPARENT_TEST_DRIVER_ID: + return( mbedtls_test_transparent_mac_abort( + &operation->ctx.transparent_test_driver_ctx ) ); + case PSA_CRYPTO_OPAQUE_TEST_DRIVER_ID: + return( mbedtls_test_opaque_mac_abort( + &operation->ctx.opaque_test_driver_ctx ) ); +#endif /* PSA_CRYPTO_DRIVER_TEST */ +#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */ + default: + return( PSA_ERROR_INVALID_ARGUMENT ); + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.h new file mode 100644 index 00000000..e09e4ed7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_driver_wrappers.h @@ -0,0 +1,334 @@ +/* + * Function signatures for functionality that can be provided by + * cryptographic accelerators. + * Warning: This file will be auto-generated in the future. + */ +/* Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_H +#define PSA_CRYPTO_DRIVER_WRAPPERS_H + +#include "psa/crypto.h" +#include "psa/crypto_driver_common.h" + +/* + * Initialization and termination functions + */ +psa_status_t psa_driver_wrapper_init( void ); +void psa_driver_wrapper_free( void ); + +/* + * Signature functions + */ +psa_status_t psa_driver_wrapper_sign_message( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ); + +psa_status_t psa_driver_wrapper_verify_message( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *signature, + size_t signature_length ); + +psa_status_t psa_driver_wrapper_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +psa_status_t psa_driver_wrapper_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ); + +/* + * Key handling functions + */ + +psa_status_t psa_driver_wrapper_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + +psa_status_t psa_driver_wrapper_export_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +psa_status_t psa_driver_wrapper_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +psa_status_t psa_driver_wrapper_get_key_buffer_size( + const psa_key_attributes_t *attributes, + size_t *key_buffer_size ); + +psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data( + const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + size_t *key_buffer_size ); + +psa_status_t psa_driver_wrapper_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); + +psa_status_t psa_driver_wrapper_get_builtin_key( + psa_drv_slot_number_t slot_number, + psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); + +psa_status_t psa_driver_wrapper_copy_key( + psa_key_attributes_t *attributes, + const uint8_t *source_key, size_t source_key_length, + uint8_t *target_key_buffer, size_t target_key_buffer_size, + size_t *target_key_buffer_length ); +/* + * Cipher functions + */ +psa_status_t psa_driver_wrapper_cipher_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *iv, + size_t iv_length, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_encrypt_setup( + psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_cipher_decrypt_setup( + psa_cipher_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_cipher_set_iv( + psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length ); + +psa_status_t psa_driver_wrapper_cipher_update( + psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_finish( + psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_cipher_abort( + psa_cipher_operation_t *operation ); + +/* + * Hashing functions + */ +psa_status_t psa_driver_wrapper_hash_compute( + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +psa_status_t psa_driver_wrapper_hash_setup( + psa_hash_operation_t *operation, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_hash_clone( + const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation ); + +psa_status_t psa_driver_wrapper_hash_update( + psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ); + +psa_status_t psa_driver_wrapper_hash_finish( + psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ); + +psa_status_t psa_driver_wrapper_hash_abort( + psa_hash_operation_t *operation ); + +/* + * AEAD functions + */ + +psa_status_t psa_driver_wrapper_aead_encrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *plaintext, size_t plaintext_length, + uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length ); + +psa_status_t psa_driver_wrapper_aead_decrypt( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *nonce, size_t nonce_length, + const uint8_t *additional_data, size_t additional_data_length, + const uint8_t *ciphertext, size_t ciphertext_length, + uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length ); + +psa_status_t psa_driver_wrapper_aead_encrypt_setup( + psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_aead_decrypt_setup( + psa_aead_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_aead_set_nonce( + psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length ); + +psa_status_t psa_driver_wrapper_aead_set_lengths( + psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length ); + +psa_status_t psa_driver_wrapper_aead_update_ad( + psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length ); + +psa_status_t psa_driver_wrapper_aead_update( + psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length ); + +psa_status_t psa_driver_wrapper_aead_finish( + psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length ); + +psa_status_t psa_driver_wrapper_aead_verify( + psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length ); + +psa_status_t psa_driver_wrapper_aead_abort( + psa_aead_operation_t *operation ); + +/* + * MAC functions + */ +psa_status_t psa_driver_wrapper_mac_compute( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ); + +psa_status_t psa_driver_wrapper_mac_sign_setup( + psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_mac_verify_setup( + psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ); + +psa_status_t psa_driver_wrapper_mac_update( + psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ); + +psa_status_t psa_driver_wrapper_mac_sign_finish( + psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ); + +psa_status_t psa_driver_wrapper_mac_verify_finish( + psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ); + +psa_status_t psa_driver_wrapper_mac_abort( + psa_mac_operation_t *operation ); + +#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_H */ + +/* End of automatically generated file. */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.c new file mode 100644 index 00000000..db6682c6 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.c @@ -0,0 +1,472 @@ +/* + * PSA ECP layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_ecp.h" +#include "psa_crypto_random_impl.h" +#include "psa_crypto_hash.h" + +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include +#include + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) +psa_status_t mbedtls_psa_ecp_load_representation( + psa_key_type_t type, size_t curve_bits, + const uint8_t *data, size_t data_length, + mbedtls_ecp_keypair **p_ecp ) +{ + mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + size_t curve_bytes = data_length; + int explicit_bits = ( curve_bits != 0 ); + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) && + PSA_KEY_TYPE_ECC_GET_FAMILY( type ) != PSA_ECC_FAMILY_MONTGOMERY ) + { + /* A Weierstrass public key is represented as: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * So its data length is 2m+1 where m is the curve size in bits. + */ + if( ( data_length & 1 ) == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + curve_bytes = data_length / 2; + + /* Montgomery public keys are represented in compressed format, meaning + * their curve_bytes is equal to the amount of input. */ + + /* Private keys are represented in uncompressed private random integer + * format, meaning their curve_bytes is equal to the amount of input. */ + } + + if( explicit_bits ) + { + /* With an explicit bit-size, the data must have the matching length. */ + if( curve_bytes != PSA_BITS_TO_BYTES( curve_bits ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else + { + /* We need to infer the bit-size from the data. Since the only + * information we have is the length in bytes, the value of curve_bits + * at this stage is rounded up to the nearest multiple of 8. */ + curve_bits = PSA_BYTES_TO_BITS( curve_bytes ); + } + + /* Allocate and initialize a key representation. */ + ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); + + /* Load the group. */ + grp_id = mbedtls_ecc_group_of_psa( PSA_KEY_TYPE_ECC_GET_FAMILY( type ), + curve_bits, !explicit_bits ); + if( grp_id == MBEDTLS_ECP_DP_NONE ) + { + /* We can't distinguish between a nonsensical family/size combination + * (which would warrant PSA_ERROR_INVALID_ARGUMENT) and a + * well-regarded curve that Mbed TLS just doesn't know about (which + * would warrant PSA_ERROR_NOT_SUPPORTED). For uniformity with how + * curves that Mbed TLS knows about but for which support is disabled + * at build time, return NOT_SUPPORTED. */ + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load( &ecp->grp, grp_id ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Load the key material. */ + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Load the public value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_point_read_binary( &ecp->grp, &ecp->Q, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Check that the point is on the curve. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_check_pubkey( &ecp->grp, &ecp->Q ) ); + if( status != PSA_SUCCESS ) + goto exit; + } + else + { + /* Load and validate the secret value. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_read_key( ecp->grp.id, + ecp, + data, + data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + } + + *p_ecp = ecp; +exit: + if( status != PSA_SUCCESS ) + { + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + } + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) + +psa_status_t mbedtls_psa_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + psa_status_t status; + mbedtls_ecp_keypair *ecp = NULL; + + /* Parse input */ + status = mbedtls_psa_ecp_load_representation( attributes->core.type, + attributes->core.bits, + data, + data_length, + &ecp ); + if( status != PSA_SUCCESS ) + goto exit; + + if( PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) == + PSA_ECC_FAMILY_MONTGOMERY ) + *bits = ecp->grp.nbits + 1; + else + *bits = ecp->grp.nbits; + + /* Re-export the data to PSA export format. There is currently no support + * for other input formats then the export format, so this is a 1-1 + * copy operation. */ + status = mbedtls_psa_ecp_export_key( attributes->core.type, + ecp, + key_buffer, + key_buffer_size, + key_buffer_length ); +exit: + /* Always free the PK object (will also free contained ECP context) */ + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + return( status ); +} + +psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ + psa_status_t status; + + if( PSA_KEY_TYPE_IS_PUBLIC_KEY( type ) ) + { + /* Check whether the public part is loaded */ + if( mbedtls_ecp_is_zero( &ecp->Q ) ) + { + /* Calculate the public key */ + status = mbedtls_to_psa_error( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ) ); + if( status != PSA_SUCCESS ) + return( status ); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_point_write_binary( &ecp->grp, &ecp->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + data_length, + data, + data_size ) ); + if( status != PSA_SUCCESS ) + memset( data, 0, data_size ); + + return( status ); + } + else + { + if( data_size < PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) + return( PSA_ERROR_BUFFER_TOO_SMALL ); + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key( ecp, + data, + PSA_BITS_TO_BYTES( ecp->grp.nbits ) ) ); + if( status == PSA_SUCCESS ) + *data_length = PSA_BITS_TO_BYTES( ecp->grp.nbits ); + else + memset( data, 0, data_size ); + + return( status ); + } +} + +psa_status_t mbedtls_psa_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + + status = mbedtls_psa_ecp_load_representation( + attributes->core.type, attributes->core.bits, + key_buffer, key_buffer_size, &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + + status = mbedtls_psa_ecp_export_key( + PSA_KEY_TYPE_ECC_PUBLIC_KEY( + PSA_KEY_TYPE_ECC_GET_FAMILY( attributes->core.type ) ), + ecp, data, data_size, data_length ); + + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) +psa_status_t mbedtls_psa_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY( + attributes->core.type ); + mbedtls_ecp_group_id grp_id = + mbedtls_ecc_group_of_psa( curve, attributes->core.bits, 0 ); + + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_grp_id( grp_id ); + mbedtls_ecp_keypair ecp; + + if( attributes->domain_parameters_size != 0 ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + mbedtls_ecp_keypair_init( &ecp ); + ret = mbedtls_ecp_gen_key( grp_id, &ecp, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ); + if( ret != 0 ) + { + mbedtls_ecp_keypair_free( &ecp ); + return( mbedtls_to_psa_error( ret ) ); + } + + status = mbedtls_to_psa_error( + mbedtls_ecp_write_key( &ecp, key_buffer, key_buffer_size ) ); + + mbedtls_ecp_keypair_free( &ecp ); + + if( status == PSA_SUCCESS ) + *key_buffer_length = key_buffer_size; + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR) */ + +/****************************************************************/ +/* ECDSA sign/verify */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) +psa_status_t mbedtls_psa_ecdsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t curve_bytes; + mbedtls_mpi r, s; + + status = mbedtls_psa_ecp_load_representation( attributes->core.type, + attributes->core.bits, + key_buffer, + key_buffer_size, + &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + + curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_size < 2 * curve_bytes ) + { + ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL; + goto cleanup; + } + + if( PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + mbedtls_md_type_t md_alg = mbedtls_md_get_type( md_info ); + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det_ext( + &ecp->grp, &r, &s, + &ecp->d, hash, + hash_length, md_alg, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ) ); +#else + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + goto cleanup; +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + } + else + { + (void) alg; + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ecp->grp, &r, &s, &ecp->d, + hash, hash_length, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &s, + signature + curve_bytes, + curve_bytes ) ); +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + if( ret == 0 ) + *signature_length = 2 * curve_bytes; + + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t mbedtls_psa_ecdsa_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t curve_bytes; + mbedtls_mpi r, s; + + (void)alg; + + status = mbedtls_psa_ecp_load_representation( attributes->core.type, + attributes->core.bits, + key_buffer, + key_buffer_size, + &ecp ); + if( status != PSA_SUCCESS ) + return( status ); + + curve_bytes = PSA_BITS_TO_BYTES( ecp->grp.pbits ); + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( signature_length != 2 * curve_bytes ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, + signature, + curve_bytes ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &s, + signature + curve_bytes, + curve_bytes ) ); + + /* Check whether the public part is loaded. If not, load it. */ + if( mbedtls_ecp_is_zero( &ecp->Q ) ) + { + MBEDTLS_MPI_CHK( + mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G, + mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) ); + } + + ret = mbedtls_ecdsa_verify( &ecp->grp, hash, hash_length, + &ecp->Q, &r, &s ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); + + return( mbedtls_to_psa_error( ret ) ); +} + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \ + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.h new file mode 100644 index 00000000..429c0627 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_ecp.h @@ -0,0 +1,221 @@ +/* + * PSA ECP layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_ECP_H +#define PSA_CRYPTO_ECP_H + +#include +#include + +/** Load the contents of a key buffer into an internal ECP representation + * + * \param[in] type The type of key contained in \p data. + * \param[in] curve_bits The nominal bit-size of the curve. + * It must be consistent with the representation + * passed in \p data. + * This can be 0, in which case the bit-size + * is inferred from \p data_length (which is possible + * for all key types and representation formats + * formats that are currently supported or will + * be in the foreseeable future). + * \param[in] data The buffer from which to load the representation. + * \param[in] data_length The size in bytes of \p data. + * \param[out] p_ecp Returns a pointer to an ECP context on success. + * The caller is responsible for freeing both the + * contents of the context and the context itself + * when done. + */ +psa_status_t mbedtls_psa_ecp_load_representation( psa_key_type_t type, + size_t curve_bits, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ); + +/** Import an ECP key in binary format. + * + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The ECP key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_ecp_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + +/** Export an ECP key to export representation + * + * \param[in] type The type of key (public/private) to export + * \param[in] ecp The internal ECP representation from which to export + * \param[out] data The buffer to export to + * \param[in] data_size The length of the buffer to export to + * \param[out] data_length The amount of bytes written to \p data + */ +psa_status_t mbedtls_psa_ecp_export_key( psa_key_type_t type, + mbedtls_ecp_keypair *ecp, + uint8_t *data, + size_t data_size, + size_t *data_length ); + +/** Export an ECP public key or the public part of an ECP key pair in binary + * format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data + * + * \retval #PSA_SUCCESS The ECP public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_ecp_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +/** + * \brief Generate an ECP key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the ECP key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was successfully generated. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key length or type not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t mbedtls_psa_ecp_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); + +/** Sign an already-calculated hash with ECDSA. + * + * \note The signature of this function is that of a PSA driver + * sign_hash entry point. This function behaves as a sign_hash + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the ECC key to use for the + * operation. + * \param[in] key_buffer The buffer containing the ECC key context. + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg Randomized or deterministic ECDSA algorithm. + * \param[in] hash The hash or message to sign. + * \param[in] hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_ECC_KEY_PAIR, \c key_bits, + * \p alg) where \c key_bits is the bit-size of the ECC key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t mbedtls_psa_ecdsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +/** + * \brief Verify an ECDSA hash or short message signature. + * + * \note The signature of this function is that of a PSA driver + * verify_hash entry point. This function behaves as a verify_hash + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the ECC key to use for the + * operation. + * \param[in] key_buffer The buffer containing the ECC key context. + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg Randomized or deterministic ECDSA algorithm. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param[in] hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_ecdsa_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ); +#endif /* PSA_CRYPTO_ECP_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.c new file mode 100644 index 00000000..536c6c11 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.c @@ -0,0 +1,425 @@ +/* + * PSA hashing layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_hash.h" + +#include +#include + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) +const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ) +{ + switch( alg ) + { +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA224_C) + case PSA_ALG_SHA_224: + return( &mbedtls_sha224_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA384_C) + case PSA_ALG_SHA_384: + return( &mbedtls_sha384_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case PSA_ALG_SHA_512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ + +#if defined(MBEDTLS_PSA_BUILTIN_HASH) +psa_status_t mbedtls_psa_hash_abort( + mbedtls_psa_hash_operation_t *operation ) +{ + switch( operation->alg ) + { + case 0: + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + break; +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + mbedtls_md5_free( &operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_free( &operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + mbedtls_sha1_free( &operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + mbedtls_sha256_free( &operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + mbedtls_sha256_free( &operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + mbedtls_sha512_free( &operation->ctx.sha512 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + mbedtls_sha512_free( &operation->ctx.sha512 ); + break; +#endif + default: + return( PSA_ERROR_BAD_STATE ); + } + operation->alg = 0; + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_hash_setup( + mbedtls_psa_hash_operation_t *operation, + psa_algorithm_t alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + { + return( PSA_ERROR_BAD_STATE ); + } + + switch( alg ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + mbedtls_md5_init( &operation->ctx.md5 ); + ret = mbedtls_md5_starts( &operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_init( &operation->ctx.ripemd160 ); + ret = mbedtls_ripemd160_starts( &operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + mbedtls_sha1_init( &operation->ctx.sha1 ); + ret = mbedtls_sha1_starts( &operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + mbedtls_sha256_init( &operation->ctx.sha256 ); + ret = mbedtls_sha256_starts( &operation->ctx.sha256, 1 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + mbedtls_sha256_init( &operation->ctx.sha256 ); + ret = mbedtls_sha256_starts( &operation->ctx.sha256, 0 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + mbedtls_sha512_init( &operation->ctx.sha512 ); + ret = mbedtls_sha512_starts( &operation->ctx.sha512, 1 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + mbedtls_sha512_init( &operation->ctx.sha512 ); + ret = mbedtls_sha512_starts( &operation->ctx.sha512, 0 ); + break; +#endif + default: + return( PSA_ALG_IS_HASH( alg ) ? + PSA_ERROR_NOT_SUPPORTED : + PSA_ERROR_INVALID_ARGUMENT ); + } + if( ret == 0 ) + operation->alg = alg; + else + mbedtls_psa_hash_abort( operation ); + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t mbedtls_psa_hash_clone( + const mbedtls_psa_hash_operation_t *source_operation, + mbedtls_psa_hash_operation_t *target_operation ) +{ + switch( source_operation->alg ) + { + case 0: + return( PSA_ERROR_BAD_STATE ); +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + mbedtls_md5_clone( &target_operation->ctx.md5, + &source_operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160, + &source_operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + mbedtls_sha1_clone( &target_operation->ctx.sha1, + &source_operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + mbedtls_sha256_clone( &target_operation->ctx.sha256, + &source_operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + mbedtls_sha256_clone( &target_operation->ctx.sha256, + &source_operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + mbedtls_sha512_clone( &target_operation->ctx.sha512, + &source_operation->ctx.sha512 ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + mbedtls_sha512_clone( &target_operation->ctx.sha512, + &source_operation->ctx.sha512 ); + break; +#endif + default: + (void) source_operation; + (void) target_operation; + return( PSA_ERROR_NOT_SUPPORTED ); + } + + target_operation->alg = source_operation->alg; + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_hash_update( + mbedtls_psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + switch( operation->alg ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + ret = mbedtls_md5_update( &operation->ctx.md5, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_update( &operation->ctx.ripemd160, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_update( &operation->ctx.sha1, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + ret = mbedtls_sha256_update( &operation->ctx.sha256, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_update( &operation->ctx.sha256, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + ret = mbedtls_sha512_update( &operation->ctx.sha512, + input, input_length ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_update( &operation->ctx.sha512, + input, input_length ); + break; +#endif + default: + (void) input; + (void) input_length; + return( PSA_ERROR_BAD_STATE ); + } + + return( mbedtls_to_psa_error( ret ) ); +} + +psa_status_t mbedtls_psa_hash_finish( + mbedtls_psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ) +{ + psa_status_t status; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t actual_hash_length = PSA_HASH_LENGTH( operation->alg ); + + /* Fill the output buffer with something that isn't a valid hash + * (barring an attack on the hash and deliberately-crafted input), + * in case the caller doesn't check the return status properly. */ + *hash_length = hash_size; + /* If hash_size is 0 then hash may be NULL and then the + * call to memset would have undefined behavior. */ + if( hash_size != 0 ) + memset( hash, '!', hash_size ); + + if( hash_size < actual_hash_length ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + + switch( operation->alg ) + { +#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) + case PSA_ALG_MD5: + ret = mbedtls_md5_finish( &operation->ctx.md5, hash ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) + case PSA_ALG_RIPEMD160: + ret = mbedtls_ripemd160_finish( &operation->ctx.ripemd160, hash ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) + case PSA_ALG_SHA_1: + ret = mbedtls_sha1_finish( &operation->ctx.sha1, hash ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) + case PSA_ALG_SHA_224: + ret = mbedtls_sha256_finish( &operation->ctx.sha256, hash ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) + case PSA_ALG_SHA_256: + ret = mbedtls_sha256_finish( &operation->ctx.sha256, hash ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) + case PSA_ALG_SHA_384: + ret = mbedtls_sha512_finish( &operation->ctx.sha512, hash ); + break; +#endif +#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) + case PSA_ALG_SHA_512: + ret = mbedtls_sha512_finish( &operation->ctx.sha512, hash ); + break; +#endif + default: + (void) hash; + return( PSA_ERROR_BAD_STATE ); + } + status = mbedtls_to_psa_error( ret ); + +exit: + if( status == PSA_SUCCESS ) + *hash_length = actual_hash_length; + return( status ); +} + +psa_status_t mbedtls_psa_hash_compute( + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; + + *hash_length = hash_size; + status = mbedtls_psa_hash_setup( &operation, alg ); + if( status != PSA_SUCCESS ) + goto exit; + status = mbedtls_psa_hash_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = mbedtls_psa_hash_finish( &operation, hash, hash_size, hash_length ); + if( status != PSA_SUCCESS ) + goto exit; + +exit: + abort_status = mbedtls_psa_hash_abort( &operation ); + if( status == PSA_SUCCESS ) + return( abort_status ); + else + return( status ); + +} +#endif /* MBEDTLS_PSA_BUILTIN_HASH */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.h new file mode 100644 index 00000000..7091dc5a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_hash.h @@ -0,0 +1,234 @@ +/* + * PSA hashing layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_HASH_H +#define PSA_CRYPTO_HASH_H + +#include + +#include "md_wrap.h" + +/** Get Mbed TLS MD information of a hash algorithm given its PSA identifier + * + * \param[in] alg PSA hash algorithm identifier + * + * \return The Mbed TLS MD information of the hash algorithm. \c NULL if the + * PSA hash algorithm is not supported. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_psa( psa_algorithm_t alg ); + +/** Calculate the hash (digest) of a message using Mbed TLS routines. + * + * \note The signature of this function is that of a PSA driver hash_compute + * entry point. This function behaves as a hash_compute entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_LENGTH(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_hash_compute( + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Set up a multipart hash operation using Mbed TLS routines. + * + * \note The signature of this function is that of a PSA driver hash_setup + * entry point. This function behaves as a hash_setup entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * If an error occurs at any step after a call to mbedtls_psa_hash_setup(), the + * operation will need to be reset by a call to mbedtls_psa_hash_abort(). The + * core may call mbedtls_psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to mbedtls_psa_hash_setup(), the core must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to mbedtls_psa_hash_finish() or mbedtls_psa_hash_verify(). + * - A call to mbedtls_psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized to all-zero and not yet be in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_hash_setup( + mbedtls_psa_hash_operation_t *operation, + psa_algorithm_t alg ); + +/** Clone an Mbed TLS hash operation. + * + * \note The signature of this function is that of a PSA driver hash_clone + * entry point. This function behaves as a hash_clone entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling mbedtls_psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * mbedtls_psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_hash_clone( + const mbedtls_psa_hash_operation_t *source_operation, + mbedtls_psa_hash_operation_t *target_operation ); + +/** Add a message fragment to a multipart Mbed TLS hash operation. + * + * \note The signature of this function is that of a PSA driver hash_update + * entry point. This function behaves as a hash_update entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * The application must call mbedtls_psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling mbedtls_psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_hash_update( + mbedtls_psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length ); + +/** Finish the calculation of the Mbed TLS-calculated hash of a message. + * + * \note The signature of this function is that of a PSA driver hash_finish + * entry point. This function behaves as a hash_finish entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * The application must call mbedtls_psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to mbedtls_psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling mbedtls_psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_LENGTH(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p hash buffer is too small. You can determine a + * sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_hash_finish( + mbedtls_psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length ); + +/** Abort an Mbed TLS hash operation. + * + * \note The signature of this function is that of a PSA driver hash_abort + * entry point. This function behaves as a hash_abort entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * mbedtls_psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling mbedtls_psa_hash_abort() after the operation has been + * terminated by a call to mbedtls_psa_hash_abort(), mbedtls_psa_hash_finish() or + * mbedtls_psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_hash_abort( + mbedtls_psa_hash_operation_t *operation ); + +#endif /* PSA_CRYPTO_HASH_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_invasive.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_invasive.h new file mode 100644 index 00000000..1dd95793 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_invasive.h @@ -0,0 +1,82 @@ +/** + * \file psa_crypto_invasive.h + * + * \brief PSA cryptography module: invasive interfaces for test only. + * + * The interfaces in this file are intended for testing purposes only. + * They MUST NOT be made available to clients over IPC in integrations + * with isolation, and they SHOULD NOT be made available in library + * integrations except when building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_INVASIVE_H +#define PSA_CRYPTO_INVASIVE_H + +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" +#include "common.h" + +#include "mbedtls/entropy.h" + +#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/** \brief Configure entropy sources. + * + * This function may only be called before a call to psa_crypto_init(), + * or after a call to mbedtls_psa_crypto_free() and before any + * subsequent call to psa_crypto_init(). + * + * This function is only intended for test purposes. The functionality + * it provides is also useful for system integrators, but + * system integrators should configure entropy drivers instead of + * breaking through to the Mbed TLS API. + * + * \param entropy_init Function to initialize the entropy context + * and set up the desired entropy sources. + * It is called by psa_crypto_init(). + * By default this is mbedtls_entropy_init(). + * This function cannot report failures directly. + * To indicate a failure, set the entropy context + * to a state where mbedtls_entropy_func() will + * return an error. + * \param entropy_free Function to free the entropy context + * and associated resources. + * It is called by mbedtls_psa_crypto_free(). + * By default this is mbedtls_entropy_free(). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_PERMITTED + * The caller does not have the permission to configure + * entropy sources. + * \retval #PSA_ERROR_BAD_STATE + * The library has already been initialized. + */ +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ); +#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */ + +#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C) +psa_status_t psa_mac_key_can_do( + psa_algorithm_t algorithm, + psa_key_type_t key_type ); +#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */ + +#endif /* PSA_CRYPTO_INVASIVE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_its.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_its.h new file mode 100644 index 00000000..3a3f49a7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_its.h @@ -0,0 +1,149 @@ +/** \file psa_crypto_its.h + * \brief Interface of trusted storage that crypto is built on. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_ITS_H +#define PSA_CRYPTO_ITS_H + +#include +#include + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Flags used when creating a data entry + */ +typedef uint32_t psa_storage_create_flags_t; + +/** \brief A type for UIDs used for identifying data + */ +typedef uint64_t psa_storage_uid_t; + +#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ +#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ + +/** + * \brief A container for metadata associated with a specific uid + */ +struct psa_storage_info_t +{ + uint32_t size; /**< The size of the data associated with a uid **/ + psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ +}; + +/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) + +/** \brief PSA storage specific error codes + */ +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ + +/** + * \brief create a new or modify an existing uid/value pair + * + * \param[in] uid the identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval #PSA_ERROR_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_set(psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve the value associated with a provided uid + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) + * \param[out] p_data The buffer where the data will be placed upon successful completion + * \param[out] p_data_length The amount of data returned in the p_data buffer + * + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage + * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted + * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_data`, `p_data_length`) + * is invalid. For example is `NULL` or references memory the caller cannot access. + * In addition, this can also happen if an invalid offset was provided. + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length ); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] uid The uid value + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval #PSA_ERROR_DATA_CORRUPT The operation failed because stored data has been corrupted + * \retval #PSA_ERROR_INVALID_ARGUMENT The operation failed because one of the provided pointers(`p_info`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] uid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval #PSA_SUCCESS The operation completed successfully + * \retval #PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage + * \retval #PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval #PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ITS_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.c new file mode 100644 index 00000000..dcf065a6 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.c @@ -0,0 +1,499 @@ +/* + * PSA MAC layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_mac.h" +#include + +#include +#include + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) +static psa_status_t psa_hmac_abort_internal( + mbedtls_psa_hmac_operation_t *hmac ) +{ + mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); + return( psa_hash_abort( &hmac->hash_ctx ) ); +} + +static psa_status_t psa_hmac_setup_internal( + mbedtls_psa_hmac_operation_t *hmac, + const uint8_t *key, + size_t key_length, + psa_algorithm_t hash_alg ) +{ + uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE]; + size_t i; + size_t hash_size = PSA_HASH_LENGTH( hash_alg ); + size_t block_size = PSA_HASH_BLOCK_LENGTH( hash_alg ); + psa_status_t status; + + hmac->alg = hash_alg; + + /* Sanity checks on block_size, to guarantee that there won't be a buffer + * overflow below. This should never trigger if the hash algorithm + * is implemented correctly. */ + /* The size checks against the ipad and opad buffers cannot be written + * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )` + * because that triggers -Wlogical-op on GCC 7.3. */ + if( block_size > sizeof( ipad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size > sizeof( hmac->opad ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( block_size < hash_size ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( key_length > block_size ) + { + status = psa_hash_compute( hash_alg, key, key_length, + ipad, sizeof( ipad ), &key_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + } + /* A 0-length key is not commonly used in HMAC when used as a MAC, + * but it is permitted. It is common when HMAC is used in HKDF, for + * example. Don't call `memcpy` in the 0-length because `key` could be + * an invalid pointer which would make the behavior undefined. */ + else if( key_length != 0 ) + memcpy( ipad, key, key_length ); + + /* ipad contains the key followed by garbage. Xor and fill with 0x36 + * to create the ipad value. */ + for( i = 0; i < key_length; i++ ) + ipad[i] ^= 0x36; + memset( ipad + key_length, 0x36, block_size - key_length ); + + /* Copy the key material from ipad to opad, flipping the requisite bits, + * and filling the rest of opad with the requisite constant. */ + for( i = 0; i < key_length; i++ ) + hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C; + memset( hmac->opad + key_length, 0x5C, block_size - key_length ); + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto cleanup; + + status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); + +cleanup: + mbedtls_platform_zeroize( ipad, sizeof( ipad ) ); + + return( status ); +} + +static psa_status_t psa_hmac_update_internal( + mbedtls_psa_hmac_operation_t *hmac, + const uint8_t *data, + size_t data_length ) +{ + return( psa_hash_update( &hmac->hash_ctx, data, data_length ) ); +} + +static psa_status_t psa_hmac_finish_internal( + mbedtls_psa_hmac_operation_t *hmac, + uint8_t *mac, + size_t mac_size ) +{ + uint8_t tmp[PSA_HASH_MAX_SIZE]; + psa_algorithm_t hash_alg = hmac->alg; + size_t hash_size = 0; + size_t block_size = PSA_HASH_BLOCK_LENGTH( hash_alg ); + psa_status_t status; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + return( status ); + /* From here on, tmp needs to be wiped. */ + + status = psa_hash_setup( &hmac->hash_ctx, hash_alg ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, hmac->opad, block_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_update( &hmac->hash_ctx, tmp, hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_hash_finish( &hmac->hash_ctx, tmp, sizeof( tmp ), &hash_size ); + if( status != PSA_SUCCESS ) + goto exit; + + memcpy( mac, tmp, mac_size ); + +exit: + mbedtls_platform_zeroize( tmp, hash_size ); + return( status ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) +static psa_status_t cmac_setup( mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(PSA_WANT_KEY_TYPE_DES) + /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept + * to do CMAC with pure DES, so return NOT_SUPPORTED here. */ + if( psa_get_key_type( attributes ) == PSA_KEY_TYPE_DES && + ( psa_get_key_bits( attributes ) == 64 || + psa_get_key_bits( attributes ) == 128 ) ) + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + + const mbedtls_cipher_info_t * cipher_info = + mbedtls_cipher_info_from_psa( + PSA_ALG_CMAC, + psa_get_key_type( attributes ), + psa_get_key_bits( attributes ), + NULL ); + + if( cipher_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + ret = mbedtls_cipher_setup( &operation->ctx.cmac, cipher_info ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &operation->ctx.cmac, + key_buffer, + psa_get_key_bits( attributes ) ); +exit: + return( mbedtls_to_psa_error( ret ) ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + +/* Initialize this driver's MAC operation structure. Once this function has been + * called, mbedtls_psa_mac_abort can run and will do the right thing. */ +static psa_status_t mac_init( + mbedtls_psa_mac_operation_t *operation, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + operation->alg = alg; + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC ) + { + mbedtls_cipher_init( &operation->ctx.cmac ); + status = PSA_SUCCESS; + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + /* We'll set up the hash operation later in psa_hmac_setup_internal. */ + operation->ctx.hmac.alg = 0; + status = PSA_SUCCESS; + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + (void) operation; + status = PSA_ERROR_NOT_SUPPORTED; + } + + if( status != PSA_SUCCESS ) + memset( operation, 0, sizeof( *operation ) ); + return( status ); +} + +psa_status_t mbedtls_psa_mac_abort( mbedtls_psa_mac_operation_t *operation ) +{ + if( operation->alg == 0 ) + { + /* The object has (apparently) been initialized but it is not + * in use. It's ok to call abort on such an object, and there's + * nothing to do. */ + return( PSA_SUCCESS ); + } + else +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC ) + { + mbedtls_cipher_free( &operation->ctx.cmac ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + psa_hmac_abort_internal( &operation->ctx.hmac ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + /* Sanity check (shouldn't happen: operation->alg should + * always have been initialized to a valid value). */ + goto bad_state; + } + + operation->alg = 0; + + return( PSA_SUCCESS ); + +bad_state: + /* If abort is called on an uninitialized object, we can't trust + * anything. Wipe the object in case it contains confidential data. + * This may result in a memory leak if a pointer gets overwritten, + * but it's too late to do anything about this. */ + memset( operation, 0, sizeof( *operation ) ); + return( PSA_ERROR_BAD_STATE ); +} + +static psa_status_t psa_mac_setup( mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + /* A context must be freshly initialized before it can be set up. */ + if( operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + status = mac_init( operation, alg ); + if( status != PSA_SUCCESS ) + return( status ); + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if( PSA_ALG_FULL_LENGTH_MAC( alg ) == PSA_ALG_CMAC ) + { + /* Key buffer size for CMAC is dictated by the key bits set on the + * attributes, and previously validated by the core on key import. */ + (void) key_buffer_size; + status = cmac_setup( operation, attributes, key_buffer ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if( PSA_ALG_IS_HMAC( alg ) ) + { + status = psa_hmac_setup_internal( &operation->ctx.hmac, + key_buffer, + key_buffer_size, + PSA_ALG_HMAC_GET_HASH( alg ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + (void) attributes; + (void) key_buffer; + (void) key_buffer_size; + status = PSA_ERROR_NOT_SUPPORTED; + } + + if( status != PSA_SUCCESS ) + mbedtls_psa_mac_abort( operation ); + + return( status ); +} + +psa_status_t mbedtls_psa_mac_sign_setup( + mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, attributes, + key_buffer, key_buffer_size, alg ) ); +} + +psa_status_t mbedtls_psa_mac_verify_setup( + mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg ) +{ + return( psa_mac_setup( operation, attributes, + key_buffer, key_buffer_size, alg ) ); +} + +psa_status_t mbedtls_psa_mac_update( + mbedtls_psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ) +{ + if( operation->alg == 0 ) + return( PSA_ERROR_BAD_STATE ); + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC ) + { + return( mbedtls_to_psa_error( + mbedtls_cipher_cmac_update( &operation->ctx.cmac, + input, input_length ) ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + return( psa_hmac_update_internal( &operation->ctx.hmac, + input, input_length ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + (void) input; + (void) input_length; + return( PSA_ERROR_BAD_STATE ); + } +} + +static psa_status_t psa_mac_finish_internal( + mbedtls_psa_mac_operation_t *operation, + uint8_t *mac, size_t mac_size ) +{ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC) + if( PSA_ALG_FULL_LENGTH_MAC( operation->alg ) == PSA_ALG_CMAC ) + { + uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE]; + int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp ); + if( ret == 0 ) + memcpy( mac, tmp, mac_size ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + return( mbedtls_to_psa_error( ret ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) + if( PSA_ALG_IS_HMAC( operation->alg ) ) + { + return( psa_hmac_finish_internal( &operation->ctx.hmac, + mac, mac_size ) ); + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */ + { + /* This shouldn't happen if `operation` was initialized by + * a setup function. */ + (void) operation; + (void) mac; + (void) mac_size; + return( PSA_ERROR_BAD_STATE ); + } +} + +psa_status_t mbedtls_psa_mac_sign_finish( + mbedtls_psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->alg == 0 ) + return( PSA_ERROR_BAD_STATE ); + + status = psa_mac_finish_internal( operation, mac, mac_size ); + if( status == PSA_SUCCESS ) + *mac_length = mac_size; + + return( status ); +} + +psa_status_t mbedtls_psa_mac_verify_finish( + mbedtls_psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ) +{ + uint8_t actual_mac[PSA_MAC_MAX_SIZE]; + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + if( operation->alg == 0 ) + return( PSA_ERROR_BAD_STATE ); + + /* Consistency check: requested MAC length fits our local buffer */ + if( mac_length > sizeof( actual_mac ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_mac_finish_internal( operation, actual_mac, mac_length ); + if( status != PSA_SUCCESS ) + goto cleanup; + + if( mbedtls_psa_safer_memcmp( mac, actual_mac, mac_length ) != 0 ) + status = PSA_ERROR_INVALID_SIGNATURE; + +cleanup: + mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); + + return( status ); +} + +psa_status_t mbedtls_psa_mac_compute( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT; + + status = psa_mac_setup( &operation, + attributes, key_buffer, key_buffer_size, + alg ); + if( status != PSA_SUCCESS ) + goto exit; + + if( input_length > 0 ) + { + status = mbedtls_psa_mac_update( &operation, input, input_length ); + if( status != PSA_SUCCESS ) + goto exit; + } + + status = psa_mac_finish_internal( &operation, mac, mac_size ); + if( status == PSA_SUCCESS ) + *mac_length = mac_size; + +exit: + mbedtls_psa_mac_abort( &operation ); + + return( status ); +} + +#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.h new file mode 100644 index 00000000..a821e741 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_mac.h @@ -0,0 +1,276 @@ +/* + * PSA MAC layer on top of Mbed TLS software crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_MAC_H +#define PSA_CRYPTO_MAC_H + +#include + +/** Calculate the MAC (message authentication code) of a message using Mbed TLS. + * + * \note The signature of this function is that of a PSA driver mac_compute + * entry point. This function behaves as a mac_compute entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key to use for + * computing the MAC. This buffer contains the key + * in export representation as defined by + * psa_export_key() (i.e. the raw key bytes). + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_mac_compute( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Set up a multipart MAC calculation operation using Mbed TLS. + * + * \note The signature of this function is that of a PSA driver mac_sign_setup + * entry point. This function behaves as a mac_sign_setup entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized and not yet in use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key to use for + * computing the MAC. This buffer contains the key + * in export representation as defined by + * psa_export_key() (i.e. the raw key bytes). + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + */ +psa_status_t mbedtls_psa_mac_sign_setup( + mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg); + +/** Set up a multipart MAC verification operation using Mbed TLS. + * + * \note The signature of this function is that of a PSA driver mac_verify_setup + * entry point. This function behaves as a mac_verify_setup entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized and not yet in use. + * \param[in] attributes The attributes of the key to use for the + * operation. + * \param[in] key_buffer The buffer containing the key to use for + * computing the MAC. This buffer contains the key + * in export representation as defined by + * psa_export_key() (i.e. the raw key bytes). + * \param key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param alg The MAC algorithm to use (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + */ +psa_status_t mbedtls_psa_mac_verify_setup( + mbedtls_psa_mac_operation_t *operation, + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, + size_t key_buffer_size, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation using Mbed TLS. + * + * \note The signature of this function is that of a PSA driver mac_update + * entry point. This function behaves as a mac_update entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * The PSA core calls mbedtls_psa_mac_sign_setup() or + * mbedtls_psa_mac_verify_setup() before calling this function. + * + * If this function returns an error status, the PSA core aborts the + * operation by calling mbedtls_psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_mac_update( + mbedtls_psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length ); + +/** Finish the calculation of the MAC of a message using Mbed TLS. + * + * \note The signature of this function is that of a PSA driver mac_sign_finish + * entry point. This function behaves as a mac_sign_finish entry point as + * defined in the PSA driver interface specification for transparent + * drivers. + * + * The PSA core calls mbedtls_psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to mbedtls_psa_mac_update(). + * + * Whether this function returns successfully or not, the PSA core subsequently + * aborts the operation by calling mbedtls_psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Output size requested for the MAC algorithm. The PSA + * core guarantees this is a valid MAC length for the + * algorithm and key combination passed to + * mbedtls_psa_mac_sign_setup(). It also guarantees the + * \p mac buffer is large enough to contain the + * requested output size. + * \param[out] mac_length On success, the number of bytes output to buffer + * \p mac, which will be equal to the requested length + * \p mac_size. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p mac buffer is too small. A sufficient buffer size + * can be determined by calling PSA_MAC_LENGTH(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_mac_sign_finish( + mbedtls_psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length ); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value using Mbed TLS. + * + * \note The signature of this function is that of a PSA driver + * mac_verify_finish entry point. This function behaves as a + * mac_verify_finish entry point as defined in the PSA driver interface + * specification for transparent drivers. + * + * The PSA core calls mbedtls_psa_mac_verify_setup() before calling this + * function. This function calculates the MAC of the message formed by + * concatenating the inputs passed to preceding calls to + * mbedtls_psa_mac_update(). It then compares the calculated MAC with the + * expected MAC passed as a parameter to this function. + * + * Whether this function returns successfully or not, the PSA core subsequently + * aborts the operation by calling mbedtls_psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Length in bytes of the expected MAC value. The PSA + * core guarantees that this length is a valid MAC + * length for the algorithm and key combination passed + * to mbedtls_psa_mac_verify_setup(). + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected MAC. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_mac_verify_finish( + mbedtls_psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length ); + +/** Abort a MAC operation using Mbed TLS. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * mbedtls_psa_mac_sign_setup() or mbedtls_psa_mac_verify_setup() again. + * + * The PSA core may call this function any time after the operation object has + * been initialized by one of the methods described in + * #mbedtls_psa_mac_operation_t. + * + * In particular, calling mbedtls_psa_mac_abort() after the operation has been + * terminated by a call to mbedtls_psa_mac_abort(), + * mbedtls_psa_mac_sign_finish() or mbedtls_psa_mac_verify_finish() is safe and + * has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_mac_abort( + mbedtls_psa_mac_operation_t *operation ); + +#endif /* PSA_CRYPTO_MAC_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_random_impl.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_random_impl.h new file mode 100644 index 00000000..3c4c09a2 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_random_impl.h @@ -0,0 +1,205 @@ +/** \file psa_crypto_random_impl.h + * + * \brief PSA crypto random generator implementation abstraction. + * + * The definitions here need to be consistent with the declarations + * in include/mbedtls/psa_util.h. This file contains some redundant + * declarations to increase the chance that a compiler will detect + * inconsistencies if one file is changed without updating the other, + * but not all potential inconsistencies can be enforced, so make sure + * to check the public declarations and contracts in + * include/mbedtls/psa_util.h if you modify this file. + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_RANDOM_IMPL_H +#define PSA_CRYPTO_RANDOM_IMPL_H + +#include + +#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) + +#include +#include // only for error codes +#include + +typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t; + +/* Trivial wrapper around psa_generate_random(). */ +int mbedtls_psa_get_random( void *p_rng, + unsigned char *output, + size_t output_size ); + +/* The PSA RNG API doesn't need any externally maintained state. */ +#define MBEDTLS_PSA_RANDOM_STATE NULL + +#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +/* Choose a DRBG based on configuration and availability */ +#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE) + +#include "mbedtls/hmac_drbg.h" + +#elif defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" + +#elif defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA256_C) +#include +#if SIZE_MAX > 0xffffffff +/* Looks like a 64-bit system, so prefer SHA-512. */ +#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 +#else +/* Looks like a 32-bit system, so prefer SHA-256. */ +#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 +#endif +#elif defined(MBEDTLS_SHA512_C) +#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512 +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256 +#else +#error "No hash algorithm available for HMAC_DBRG." +#endif + +#else +#error "No DRBG module available for the psa_crypto module." +#endif + +#include "mbedtls/entropy.h" + +/** Initialize the PSA DRBG. + * + * \param p_rng Pointer to the Mbed TLS DRBG state. + */ +static inline void mbedtls_psa_drbg_init( mbedtls_psa_drbg_context_t *p_rng ) +{ +#if defined(MBEDTLS_CTR_DRBG_C) + mbedtls_ctr_drbg_init( p_rng ); +#elif defined(MBEDTLS_HMAC_DRBG_C) + mbedtls_hmac_drbg_init( p_rng ); +#endif +} + +/** Deinitialize the PSA DRBG. + * + * \param p_rng Pointer to the Mbed TLS DRBG state. + */ +static inline void mbedtls_psa_drbg_free( mbedtls_psa_drbg_context_t *p_rng ) +{ +#if defined(MBEDTLS_CTR_DRBG_C) + mbedtls_ctr_drbg_free( p_rng ); +#elif defined(MBEDTLS_HMAC_DRBG_C) + mbedtls_hmac_drbg_free( p_rng ); +#endif +} + +/** The type of the PSA random generator context. + * + * The random generator context is composed of an entropy context and + * a DRBG context. + */ +typedef struct +{ + void (* entropy_init )( mbedtls_entropy_context *ctx ); + void (* entropy_free )( mbedtls_entropy_context *ctx ); + mbedtls_entropy_context entropy; + mbedtls_psa_drbg_context_t drbg; +} mbedtls_psa_random_context_t; + +/* Defined in include/mbedtls/psa_util.h so that it's visible to + * application code. The declaration here is redundant, but included + * as a safety net to make it more likely that a future change that + * accidentally causes the implementation to diverge from the interface + * will be noticed. */ +/* Do not include the declaration under MSVC because it doesn't accept it + * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class"). + * Observed with Visual Studio 2013. A known bug apparently: + * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio + */ +#if !defined(_MSC_VER) +static mbedtls_f_rng_t *const mbedtls_psa_get_random; +#endif + +/** The maximum number of bytes that mbedtls_psa_get_random() is expected to + * return. + */ +#if defined(MBEDTLS_CTR_DRBG_C) +#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#elif defined(MBEDTLS_HMAC_DRBG_C) +#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif + +/** A pointer to the PSA DRBG state. + * + * This variable is only intended to be used through the macro + * #MBEDTLS_PSA_RANDOM_STATE. + */ +/* psa_crypto.c sets this variable to a pointer to the DRBG state in the + * global PSA crypto state. */ +/* The type `mbedtls_psa_drbg_context_t` is defined in + * include/mbedtls/psa_util.h so that `mbedtls_psa_random_state` can be + * declared there and be visible to application code. */ +extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state; + +/** A pointer to the PSA DRBG state. + * + * This macro expands to an expression that is suitable as the \c p_rng + * parameter to pass to mbedtls_psa_get_random(). + * + * This macro exists in all configurations where the psa_crypto module is + * enabled. Its expansion depends on the configuration. + */ +#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state + +/** Seed the PSA DRBG. + * + * \param entropy An entropy context to read the seed from. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * + * \return \c 0 on success. + * \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure. + */ +static inline int mbedtls_psa_drbg_seed( + mbedtls_entropy_context *entropy, + const unsigned char *custom, size_t len ) +{ +#if defined(MBEDTLS_CTR_DRBG_C) + return( mbedtls_ctr_drbg_seed( MBEDTLS_PSA_RANDOM_STATE, + mbedtls_entropy_func, + entropy, + custom, len ) ); +#elif defined(MBEDTLS_HMAC_DRBG_C) + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( MBEDTLS_PSA_HMAC_DRBG_MD_TYPE ); + return( mbedtls_hmac_drbg_seed( MBEDTLS_PSA_RANDOM_STATE, + md_info, + mbedtls_entropy_func, + entropy, + custom, len ) ); +#endif +} + +#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */ + +#endif /* PSA_CRYPTO_RANDOM_IMPL_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.c new file mode 100644 index 00000000..df524e1b --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.c @@ -0,0 +1,536 @@ +/* + * PSA RSA layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include +#include "psa_crypto_core.h" +#include "psa_crypto_random_impl.h" +#include "psa_crypto_rsa.h" +#include "psa_crypto_hash.h" + +#include +#include +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include +#include +#include "pk_wrap.h" + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + +/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes + * that are not a multiple of 8) well. For example, there is only + * mbedtls_rsa_get_len(), which returns a number of bytes, and no + * way to return the exact bit size of a key. + * To keep things simple, reject non-byte-aligned key sizes. */ +static psa_status_t psa_check_rsa_key_byte_aligned( + const mbedtls_rsa_context *rsa ) +{ + mbedtls_mpi n; + psa_status_t status; + mbedtls_mpi_init( &n ); + status = mbedtls_to_psa_error( + mbedtls_rsa_export( rsa, &n, NULL, NULL, NULL, NULL ) ); + if( status == PSA_SUCCESS ) + { + if( mbedtls_mpi_bitlen( &n ) % 8 != 0 ) + status = PSA_ERROR_NOT_SUPPORTED; + } + mbedtls_mpi_free( &n ); + return( status ); +} + +psa_status_t mbedtls_psa_rsa_load_representation( + psa_key_type_t type, const uint8_t *data, size_t data_length, + mbedtls_rsa_context **p_rsa ) +{ + psa_status_t status; + mbedtls_pk_context ctx; + size_t bits; + mbedtls_pk_init( &ctx ); + + /* Parse the data. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + status = mbedtls_to_psa_error( + mbedtls_pk_parse_key( &ctx, data, data_length, NULL, 0, + mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE ) ); + else + status = mbedtls_to_psa_error( + mbedtls_pk_parse_public_key( &ctx, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* We have something that the pkparse module recognizes. If it is a + * valid RSA key, store it. */ + if( mbedtls_pk_get_type( &ctx ) != MBEDTLS_PK_RSA ) + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS + * supports non-byte-aligned key sizes, but not well. For example, + * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */ + bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( mbedtls_pk_rsa( ctx ) ) ); + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_check_rsa_key_byte_aligned( mbedtls_pk_rsa( ctx ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Copy out the pointer to the RSA context, and reset the PK context + * such that pk_free doesn't free the RSA context we just grabbed. */ + *p_rsa = mbedtls_pk_rsa( ctx ); + ctx.pk_info = NULL; + +exit: + mbedtls_pk_free( &ctx ); + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || \ + defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) + +psa_status_t mbedtls_psa_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ) +{ + psa_status_t status; + mbedtls_rsa_context *rsa = NULL; + + /* Parse input */ + status = mbedtls_psa_rsa_load_representation( attributes->core.type, + data, + data_length, + &rsa ); + if( status != PSA_SUCCESS ) + goto exit; + + *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); + + /* Re-export the data to PSA export format, such that we can store export + * representation in the key slot. Export representation in case of RSA is + * the smallest representation that's allowed as input, so a straight-up + * allocation of the same size as the input buffer will be large enough. */ + status = mbedtls_psa_rsa_export_key( attributes->core.type, + rsa, + key_buffer, + key_buffer_size, + key_buffer_length ); +exit: + /* Always free the RSA object */ + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +} + +psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length ) +{ +#if defined(MBEDTLS_PK_WRITE_C) + int ret; + mbedtls_pk_context pk; + uint8_t *pos = data + data_size; + + mbedtls_pk_init( &pk ); + pk.pk_info = &mbedtls_rsa_info; + pk.pk_ctx = rsa; + + /* PSA Crypto API defines the format of an RSA key as a DER-encoded + * representation of the non-encrypted PKCS#1 RSAPrivateKey for a + * private key and of the RFC3279 RSAPublicKey for a public key. */ + if( PSA_KEY_TYPE_IS_KEY_PAIR( type ) ) + ret = mbedtls_pk_write_key_der( &pk, data, data_size ); + else + ret = mbedtls_pk_write_pubkey( &pos, data, &pk ); + + if( ret < 0 ) + { + /* Clean up in case pk_write failed halfway through. */ + memset( data, 0, data_size ); + return( mbedtls_to_psa_error( ret ) ); + } + + /* The mbedtls_pk_xxx functions write to the end of the buffer. + * Move the data to the beginning and erase remaining data + * at the original location. */ + if( 2 * (size_t) ret <= data_size ) + { + memcpy( data, data + data_size - ret, ret ); + memset( data + data_size - ret, 0, ret ); + } + else if( (size_t) ret < data_size ) + { + memmove( data, data + data_size - ret, ret ); + memset( data + ret, 0, data_size - ret ); + } + + *data_length = ret; + return( PSA_SUCCESS ); +#else + (void) type; + (void) rsa; + (void) data; + (void) data_size; + (void) data_length; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PK_WRITE_C */ +} + +psa_status_t mbedtls_psa_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + + status = mbedtls_psa_rsa_load_representation( + attributes->core.type, key_buffer, key_buffer_size, &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + status = mbedtls_psa_rsa_export_key( PSA_KEY_TYPE_RSA_PUBLIC_KEY, + rsa, + data, + data_size, + data_length ); + + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) || + * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */ + +#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) && \ + defined(MBEDTLS_GENPRIME) +static psa_status_t psa_rsa_read_exponent( const uint8_t *domain_parameters, + size_t domain_parameters_size, + int *exponent ) +{ + size_t i; + uint32_t acc = 0; + + if( domain_parameters_size == 0 ) + { + *exponent = 65537; + return( PSA_SUCCESS ); + } + + /* Mbed TLS encodes the public exponent as an int. For simplicity, only + * support values that fit in a 32-bit integer, which is larger than + * int on just about every platform anyway. */ + if( domain_parameters_size > sizeof( acc ) ) + return( PSA_ERROR_NOT_SUPPORTED ); + for( i = 0; i < domain_parameters_size; i++ ) + acc = ( acc << 8 ) | domain_parameters[i]; + if( acc > INT_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); + *exponent = acc; + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ) +{ + psa_status_t status; + mbedtls_rsa_context rsa; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int exponent; + + status = psa_rsa_read_exponent( attributes->domain_parameters, + attributes->domain_parameters_size, + &exponent ); + if( status != PSA_SUCCESS ) + return( status ); + + mbedtls_rsa_init( &rsa ); + ret = mbedtls_rsa_gen_key( &rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + (unsigned int)attributes->core.bits, + exponent ); + if( ret != 0 ) + return( mbedtls_to_psa_error( ret ) ); + + status = mbedtls_psa_rsa_export_key( attributes->core.type, + &rsa, key_buffer, key_buffer_size, + key_buffer_length ); + mbedtls_rsa_free( &rsa ); + + return( status ); +} +#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR) + * defined(MBEDTLS_GENPRIME) */ + +/****************************************************************/ +/* Sign/verify hashes */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ + defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + +/* Decode the hash algorithm from alg and store the mbedtls encoding in + * md_alg. Verify that the hash length is acceptable. */ +static psa_status_t psa_rsa_decode_md_type( psa_algorithm_t alg, + size_t hash_length, + mbedtls_md_type_t *md_alg ) +{ + psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH( alg ); + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_psa( hash_alg ); + *md_alg = mbedtls_md_get_type( md_info ); + + /* The Mbed TLS RSA module uses an unsigned int for hash length + * parameters. Validate that it fits so that we don't risk an + * overflow later. */ +#if SIZE_MAX > UINT_MAX + if( hash_length > UINT_MAX ) + return( PSA_ERROR_INVALID_ARGUMENT ); +#endif + + /* For signatures using a hash, the hash length must be correct. */ + if( alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW ) + { + if( md_info == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + if( mbedtls_md_get_size( md_info ) != hash_length ) + return( PSA_ERROR_INVALID_ARGUMENT ); + } + + return( PSA_SUCCESS ); +} + +psa_status_t mbedtls_psa_rsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = mbedtls_psa_rsa_load_representation( attributes->core.type, + key_buffer, + key_buffer_size, + &rsa ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + goto exit; + + if( signature_size < mbedtls_rsa_get_len( rsa ) ) + { + status = PSA_ERROR_BUFFER_TOO_SMALL; + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) + { + ret = mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE ); + if( ret == 0 ) + { + ret = mbedtls_rsa_pkcs1_sign( rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + md_alg, + (unsigned int) hash_length, + hash, + signature ); + } + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + ret = mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); + + if( ret == 0 ) + { + ret = mbedtls_rsa_rsassa_pss_sign( rsa, + mbedtls_psa_get_random, + MBEDTLS_PSA_RANDOM_STATE, + MBEDTLS_MD_NONE, + (unsigned int) hash_length, + hash, + signature ); + } + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + if( ret == 0 ) + *signature_length = mbedtls_rsa_get_len( rsa ); + status = mbedtls_to_psa_error( ret ); + +exit: + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +} + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) +static int rsa_pss_expected_salt_len( psa_algorithm_t alg, + const mbedtls_rsa_context *rsa, + size_t hash_length ) +{ + if( PSA_ALG_IS_RSA_PSS_ANY_SALT( alg ) ) + return( MBEDTLS_RSA_SALT_LEN_ANY ); + /* Otherwise: standard salt length, i.e. largest possible salt length + * up to the hash length. */ + int klen = (int) mbedtls_rsa_get_len( rsa ); // known to fit + int hlen = (int) hash_length; // known to fit + int room = klen - 2 - hlen; + if( room < 0 ) + return( 0 ); // there is no valid signature in this case anyway + else if( room > hlen ) + return( hlen ); + else + return( room ); +} +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ + +psa_status_t mbedtls_psa_rsa_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context *rsa = NULL; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_alg; + + status = mbedtls_psa_rsa_load_representation( attributes->core.type, + key_buffer, + key_buffer_size, + &rsa ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_rsa_decode_md_type( alg, hash_length, &md_alg ); + if( status != PSA_SUCCESS ) + goto exit; + + if( signature_length != mbedtls_rsa_get_len( rsa ) ) + { + status = PSA_ERROR_INVALID_SIGNATURE; + goto exit; + } + +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) + if( PSA_ALG_IS_RSA_PKCS1V15_SIGN( alg ) ) + { + ret = mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V15, + MBEDTLS_MD_NONE ); + if( ret == 0 ) + { + ret = mbedtls_rsa_pkcs1_verify( rsa, + md_alg, + (unsigned int) hash_length, + hash, + signature ); + } + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */ +#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) + if( PSA_ALG_IS_RSA_PSS( alg ) ) + { + ret = mbedtls_rsa_set_padding( rsa, MBEDTLS_RSA_PKCS_V21, md_alg ); + if( ret == 0 ) + { + int slen = rsa_pss_expected_salt_len( alg, rsa, hash_length ); + ret = mbedtls_rsa_rsassa_pss_verify_ext( rsa, + md_alg, + (unsigned) hash_length, + hash, + md_alg, + slen, + signature ); + } + } + else +#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */ + { + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; + } + + /* Mbed TLS distinguishes "invalid padding" from "valid padding but + * the rest of the signature is invalid". This has little use in + * practice and PSA doesn't report this distinction. */ + status = ( ret == MBEDTLS_ERR_RSA_INVALID_PADDING ) ? + PSA_ERROR_INVALID_SIGNATURE : + mbedtls_to_psa_error( ret ); + +exit: + mbedtls_rsa_free( rsa ); + mbedtls_free( rsa ); + + return( status ); +} + +#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || + * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */ + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.h new file mode 100644 index 00000000..bea762c7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_rsa.h @@ -0,0 +1,214 @@ +/* + * PSA RSA layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_RSA_H +#define PSA_CRYPTO_RSA_H + +#include +#include + +/** Load the contents of a key buffer into an internal RSA representation + * + * \param[in] type The type of key contained in \p data. + * \param[in] data The buffer from which to load the representation. + * \param[in] data_length The size in bytes of \p data. + * \param[out] p_rsa Returns a pointer to an RSA context on success. + * The caller is responsible for freeing both the + * contents of the context and the context itself + * when done. + */ +psa_status_t mbedtls_psa_rsa_load_representation( psa_key_type_t type, + const uint8_t *data, + size_t data_length, + mbedtls_rsa_context **p_rsa ); + +/** Import an RSA key in binary format. + * + * \note The signature of this function is that of a PSA driver + * import_key entry point. This function behaves as an import_key + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes for the key to import. + * \param[in] data The buffer containing the key data in import + * format. + * \param[in] data_length Size of the \p data buffer in bytes. + * \param[out] key_buffer The buffer containing the key data in output + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This + * size is greater or equal to \p data_length. + * \param[out] key_buffer_length The length of the data written in \p + * key_buffer in bytes. + * \param[out] bits The key size in number of bits. + * + * \retval #PSA_SUCCESS The RSA key was imported successfully. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + */ +psa_status_t mbedtls_psa_rsa_import_key( + const psa_key_attributes_t *attributes, + const uint8_t *data, size_t data_length, + uint8_t *key_buffer, size_t key_buffer_size, + size_t *key_buffer_length, size_t *bits ); + +/** Export an RSA key to export representation + * + * \param[in] type The type of key (public/private) to export + * \param[in] rsa The internal RSA representation from which to export + * \param[out] data The buffer to export to + * \param[in] data_size The length of the buffer to export to + * \param[out] data_length The amount of bytes written to \p data + */ +psa_status_t mbedtls_psa_rsa_export_key( psa_key_type_t type, + mbedtls_rsa_context *rsa, + uint8_t *data, + size_t data_size, + size_t *data_length ); + +/** Export a public RSA key or the public part of an RSA key pair in binary + * format. + * + * \note The signature of this function is that of a PSA driver + * export_public_key entry point. This function behaves as an + * export_public_key entry point as defined in the PSA driver interface + * specification. + * + * \param[in] attributes The attributes for the key to export. + * \param[in] key_buffer Material or context of the key to export. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[out] data Buffer where the key data is to be written. + * \param[in] data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes written in + * \p data. + * + * \retval #PSA_SUCCESS The RSA public key was exported successfully. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_rsa_export_public_key( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + uint8_t *data, size_t data_size, size_t *data_length ); + +/** + * \brief Generate an RSA key. + * + * \note The signature of the function is that of a PSA driver generate_key + * entry point. + * + * \param[in] attributes The attributes for the RSA key to generate. + * \param[out] key_buffer Buffer where the key data is to be written. + * \param[in] key_buffer_size Size of \p key_buffer in bytes. + * \param[out] key_buffer_length On success, the number of bytes written in + * \p key_buffer. + * + * \retval #PSA_SUCCESS + * The key was successfully generated. + * \retval #PSA_ERROR_NOT_SUPPORTED + * Key length or type not supported. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of \p key_buffer is too small. + */ +psa_status_t mbedtls_psa_rsa_generate_key( + const psa_key_attributes_t *attributes, + uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length ); + +/** Sign an already-calculated hash with an RSA private key. + * + * \note The signature of this function is that of a PSA driver + * sign_hash entry point. This function behaves as a sign_hash + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the RSA key to use for the + * operation. + * \param[in] key_buffer The buffer containing the RSA key context. + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * an RSA key. + * \param[in] hash The hash or message to sign. + * \param[in] hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param[in] signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits, + * \p alg) where \c key_bits is the bit-size of the RSA key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t mbedtls_psa_rsa_sign_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + uint8_t *signature, size_t signature_size, size_t *signature_length ); + +/** + * \brief Verify the signature a hash or short message using a public RSA key. + * + * \note The signature of this function is that of a PSA driver + * verify_hash entry point. This function behaves as a verify_hash + * entry point as defined in the PSA driver interface specification for + * transparent drivers. + * + * \param[in] attributes The attributes of the RSA key to use for the + * operation. + * \param[in] key_buffer The buffer containing the RSA key context. + * format. + * \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. + * \param[in] alg A signature algorithm that is compatible with + * an RSA key. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param[in] hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param[in] signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was performed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t mbedtls_psa_rsa_verify_hash( + const psa_key_attributes_t *attributes, + const uint8_t *key_buffer, size_t key_buffer_size, + psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, + const uint8_t *signature, size_t signature_length ); +#endif /* PSA_CRYPTO_RSA_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.c new file mode 100644 index 00000000..56678d6a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.c @@ -0,0 +1,383 @@ +/* + * PSA crypto support for secure element drivers + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + +#include +#include +#include + +#include "psa/crypto_se_driver.h" + +#include "psa_crypto_se.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#include "mbedtls/platform.h" +#if !defined(MBEDTLS_PLATFORM_C) +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +/****************************************************************/ +/* Driver lookup */ +/****************************************************************/ + +/* This structure is identical to psa_drv_se_context_t declared in + * `crypto_se_driver.h`, except that some parts are writable here + * (non-const, or pointer to non-const). */ +typedef struct +{ + void *persistent_data; + size_t persistent_data_size; + uintptr_t transient_data; +} psa_drv_se_internal_context_t; + +struct psa_se_drv_table_entry_s +{ + psa_key_location_t location; + const psa_drv_se_t *methods; + union + { + psa_drv_se_internal_context_t internal; + psa_drv_se_context_t context; + } u; +}; + +static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS]; + +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime ) +{ + size_t i; + psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( lifetime ); + /* In the driver table, location=0 means an entry that isn't used. + * No driver has a location of 0 because it's a reserved value + * (which designates transparent keys). Make sure we never return + * a driver entry for location 0. */ + if( location == 0 ) + return( NULL ); + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].location == location ) + return( &driver_table[i] ); + } + return( NULL ); +} + +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver ) +{ + return( driver->methods ); +} + +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver ) +{ + return( &driver->u.context ); +} + +int psa_get_se_driver( psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context) +{ + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); + if( p_methods != NULL ) + *p_methods = ( driver ? driver->methods : NULL ); + if( p_drv_context != NULL ) + *p_drv_context = ( driver ? &driver->u.context : NULL ); + return( driver != NULL ); +} + + + +/****************************************************************/ +/* Persistent data management */ +/****************************************************************/ + +static psa_status_t psa_get_se_driver_its_file_uid( + const psa_se_drv_table_entry_t *driver, + psa_storage_uid_t *uid ) +{ + if( driver->location > PSA_MAX_SE_LOCATION ) + return( PSA_ERROR_NOT_SUPPORTED ); + +#if SIZE_MAX > UINT32_MAX + /* ITS file sizes are limited to 32 bits. */ + if( driver->u.internal.persistent_data_size > UINT32_MAX ) + return( PSA_ERROR_NOT_SUPPORTED ); +#endif + + /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */ + *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location; + return( PSA_SUCCESS ); +} + +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status; + psa_storage_uid_t uid; + size_t length; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Read the amount of persistent data that the driver requests. + * If the data in storage is larger, it is truncated. If the data + * in storage is smaller, silently keep what is already at the end + * of the output buffer. */ + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return( psa_its_get( uid, 0, + (uint32_t) driver->u.internal.persistent_data_size, + driver->u.internal.persistent_data, + &length ) ); +} + +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver ) +{ + psa_status_t status; + psa_storage_uid_t uid; + + status = psa_get_se_driver_its_file_uid( driver, &uid ); + if( status != PSA_SUCCESS ) + return( status ); + + /* psa_get_se_driver_its_file_uid ensures that the size_t + * persistent_data_size is in range, but compilers don't know that, + * so cast to reassure them. */ + return( psa_its_set( uid, + (uint32_t) driver->u.internal.persistent_data_size, + driver->u.internal.persistent_data, + 0 ) ); +} + +psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location ) +{ + psa_storage_uid_t uid; + if( location > PSA_MAX_SE_LOCATION ) + return( PSA_ERROR_NOT_SUPPORTED ); + uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location; + return( psa_its_remove( uid ) ); +} + +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number ) +{ + psa_status_t status; + psa_key_location_t key_location = + PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( attributes ) ); + + /* If the location is wrong, it's a bug in the library. */ + if( driver->location != key_location ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + /* If the driver doesn't support key creation in any way, give up now. */ + if( driver->methods->key_management == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + + if( psa_get_key_slot_number( attributes, slot_number ) == PSA_SUCCESS ) + { + /* The application wants to use a specific slot. Allow it if + * the driver supports it. On a system with isolation, + * the crypto service must check that the application is + * permitted to request this slot. */ + psa_drv_se_validate_slot_number_t p_validate_slot_number = + driver->methods->key_management->p_validate_slot_number; + if( p_validate_slot_number == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = p_validate_slot_number( &driver->u.context, + driver->u.internal.persistent_data, + attributes, method, + *slot_number ); + } + else if( method == PSA_KEY_CREATION_REGISTER ) + { + /* The application didn't specify a slot number. This doesn't + * make sense when registering a slot. */ + return( PSA_ERROR_INVALID_ARGUMENT ); + } + else + { + /* The application didn't tell us which slot to use. Let the driver + * choose. This is the normal case. */ + psa_drv_se_allocate_key_t p_allocate = + driver->methods->key_management->p_allocate; + if( p_allocate == NULL ) + return( PSA_ERROR_NOT_SUPPORTED ); + status = p_allocate( &driver->u.context, + driver->u.internal.persistent_data, + attributes, method, + slot_number ); + } + return( status ); +} + +psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number ) +{ + psa_status_t status; + psa_status_t storage_status; + /* Normally a missing method would mean that the action is not + * supported. But psa_destroy_key() is not supposed to return + * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should + * be able to destroy it. The only use case for a driver that + * does not have a way to destroy keys at all is if the keys are + * locked in a read-only state: we can use the keys but not + * destroy them. Hence, if the driver doesn't support destroying + * keys, it's really a lack of permission. */ + if( driver->methods->key_management == NULL || + driver->methods->key_management->p_destroy == NULL ) + return( PSA_ERROR_NOT_PERMITTED ); + status = driver->methods->key_management->p_destroy( + &driver->u.context, + driver->u.internal.persistent_data, + slot_number ); + storage_status = psa_save_se_persistent_data( driver ); + return( status == PSA_SUCCESS ? storage_status : status ); +} + +psa_status_t psa_init_all_se_drivers( void ) +{ + size_t i; + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + psa_se_drv_table_entry_t *driver = &driver_table[i]; + if( driver->location == 0 ) + continue; /* skipping unused entry */ + const psa_drv_se_t *methods = psa_get_se_driver_methods( driver ); + if( methods->p_init != NULL ) + { + psa_status_t status = methods->p_init( + &driver->u.context, + driver->u.internal.persistent_data, + driver->location ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_save_se_persistent_data( driver ); + if( status != PSA_SUCCESS ) + return( status ); + } + } + return( PSA_SUCCESS ); +} + + + +/****************************************************************/ +/* Driver registration */ +/****************************************************************/ + +psa_status_t psa_register_se_driver( + psa_key_location_t location, + const psa_drv_se_t *methods) +{ + size_t i; + psa_status_t status; + + if( methods->hal_version != PSA_DRV_SE_HAL_VERSION ) + return( PSA_ERROR_NOT_SUPPORTED ); + /* Driver table entries are 0-initialized. 0 is not a valid driver + * location because it means a transparent key. */ +#if defined(static_assert) + static_assert( PSA_KEY_LOCATION_LOCAL_STORAGE == 0, + "Secure element support requires 0 to mean a local key" ); +#endif + if( location == PSA_KEY_LOCATION_LOCAL_STORAGE ) + return( PSA_ERROR_INVALID_ARGUMENT ); + if( location > PSA_MAX_SE_LOCATION ) + return( PSA_ERROR_NOT_SUPPORTED ); + + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].location == 0 ) + break; + /* Check that location isn't already in use up to the first free + * entry. Since entries are created in order and never deleted, + * there can't be a used entry after the first free entry. */ + if( driver_table[i].location == location ) + return( PSA_ERROR_ALREADY_EXISTS ); + } + if( i == PSA_MAX_SE_DRIVERS ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + driver_table[i].location = location; + driver_table[i].methods = methods; + driver_table[i].u.internal.persistent_data_size = + methods->persistent_data_size; + + if( methods->persistent_data_size != 0 ) + { + driver_table[i].u.internal.persistent_data = + mbedtls_calloc( 1, methods->persistent_data_size ); + if( driver_table[i].u.internal.persistent_data == NULL ) + { + status = PSA_ERROR_INSUFFICIENT_MEMORY; + goto error; + } + /* Load the driver's persistent data. On first use, the persistent + * data does not exist in storage, and is initialized to + * all-bits-zero by the calloc call just above. */ + status = psa_load_se_persistent_data( &driver_table[i] ); + if( status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST ) + goto error; + } + + return( PSA_SUCCESS ); + +error: + memset( &driver_table[i], 0, sizeof( driver_table[i] ) ); + return( status ); +} + +void psa_unregister_all_se_drivers( void ) +{ + size_t i; + for( i = 0; i < PSA_MAX_SE_DRIVERS; i++ ) + { + if( driver_table[i].u.internal.persistent_data != NULL ) + mbedtls_free( driver_table[i].u.internal.persistent_data ); + } + memset( driver_table, 0, sizeof( driver_table ) ); +} + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.h new file mode 100644 index 00000000..549dfb69 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_se.h @@ -0,0 +1,198 @@ +/* + * PSA crypto support for secure element drivers + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_SE_H +#define PSA_CRYPTO_SE_H + +#include "mbedtls/build_info.h" + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +/** The maximum location value that this implementation supports + * for a secure element. + * + * This is not a characteristic that each PSA implementation has, but a + * limitation of the current implementation due to the constraints imposed + * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. + * + * The minimum location value for a secure element is 1, like on any + * PSA implementation (0 means a transparent key). + */ +#define PSA_MAX_SE_LOCATION 255 + +/** The base of the range of ITS file identifiers for secure element + * driver persistent data. + * + * We use a slice of the implementation reserved range 0xffff0000..0xffffffff, + * specifically the range 0xfffffe00..0xfffffeff. The length of this range + * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is + * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE + * which doesn't have a driver. + */ +#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ( (psa_key_id_t) 0xfffffe00 ) + +/** The maximum number of registered secure element driver locations. */ +#define PSA_MAX_SE_DRIVERS 4 + +/** Unregister all secure element drivers. + * + * \warning Do not call this function while the library is in the initialized + * state. This function is only intended to be called at the end + * of mbedtls_psa_crypto_free(). + */ +void psa_unregister_all_se_drivers( void ); + +/** Initialize all secure element drivers. + * + * Called from psa_crypto_init(). + */ +psa_status_t psa_init_all_se_drivers( void ); + +/** A structure that describes a registered secure element driver. + * + * A secure element driver table entry contains a pointer to the + * driver's method table as well as the driver context structure. + */ +typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t; + +/** Return the secure element driver information for a lifetime value. + * + * \param lifetime The lifetime value to query. + * \param[out] p_methods On output, if there is a driver, + * \c *methods points to its method table. + * Otherwise \c *methods is \c NULL. + * \param[out] p_drv_context On output, if there is a driver, + * \c *drv_context points to its context + * structure. + * Otherwise \c *drv_context is \c NULL. + * + * \retval 1 + * \p lifetime corresponds to a registered driver. + * \retval 0 + * \p lifetime does not correspond to a registered driver. + */ +int psa_get_se_driver( psa_key_lifetime_t lifetime, + const psa_drv_se_t **p_methods, + psa_drv_se_context_t **p_drv_context); + +/** Return the secure element driver table entry for a lifetime value. + * + * \param lifetime The lifetime value to query. + * + * \return The driver table entry for \p lifetime, or + * \p NULL if \p lifetime does not correspond to a registered driver. + */ +psa_se_drv_table_entry_t *psa_get_se_driver_entry( + psa_key_lifetime_t lifetime ); + +/** Return the method table for a secure element driver. + * + * \param[in] driver The driver table entry to access, or \c NULL. + * + * \return The driver's method table. + * \c NULL if \p driver is \c NULL. + */ +const psa_drv_se_t *psa_get_se_driver_methods( + const psa_se_drv_table_entry_t *driver ); + +/** Return the context of a secure element driver. + * + * \param[in] driver The driver table entry to access, or \c NULL. + * + * \return A pointer to the driver context. + * \c NULL if \p driver is \c NULL. + */ +psa_drv_se_context_t *psa_get_se_driver_context( + psa_se_drv_table_entry_t *driver ); + +/** Find a free slot for a key that is to be created. + * + * This function calls the relevant method in the driver to find a suitable + * slot for a key with the given attributes. + * + * \param[in] attributes Metadata about the key that is about to be created. + * \param[in] driver The driver table entry to query. + * \param[out] slot_number On success, a slot number that is free in this + * secure element. + */ +psa_status_t psa_find_se_slot_for_key( + const psa_key_attributes_t *attributes, + psa_key_creation_method_t method, + psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t *slot_number ); + +/** Destoy a key in a secure element. + * + * This function calls the relevant driver method to destroy a key + * and updates the driver's persistent data. + */ +psa_status_t psa_destroy_se_key( psa_se_drv_table_entry_t *driver, + psa_key_slot_number_t slot_number ); + +/** Load the persistent data of a secure element driver. + * + * \param driver The driver table entry containing the persistent + * data to load from storage. + * + * \return #PSA_SUCCESS + * \return #PSA_ERROR_NOT_SUPPORTED + * \return #PSA_ERROR_DOES_NOT_EXIST + * \return #PSA_ERROR_STORAGE_FAILURE + * \return #PSA_ERROR_DATA_CORRUPT + * \return #PSA_ERROR_INVALID_ARGUMENT + */ +psa_status_t psa_load_se_persistent_data( + const psa_se_drv_table_entry_t *driver ); + +/** Save the persistent data of a secure element driver. + * + * \param[in] driver The driver table entry containing the persistent + * data to save to storage. + * + * \return #PSA_SUCCESS + * \return #PSA_ERROR_NOT_SUPPORTED + * \return #PSA_ERROR_NOT_PERMITTED + * \return #PSA_ERROR_NOT_SUPPORTED + * \return #PSA_ERROR_INSUFFICIENT_STORAGE + * \return #PSA_ERROR_STORAGE_FAILURE + * \return #PSA_ERROR_INVALID_ARGUMENT + */ +psa_status_t psa_save_se_persistent_data( + const psa_se_drv_table_entry_t *driver ); + +/** Destroy the persistent data of a secure element driver. + * + * This is currently only used for testing. + * + * \param[in] location The location identifier for the driver whose + * persistent data is to be erased. + */ +psa_status_t psa_destroy_se_persistent_data( psa_key_location_t location ); + + +/** The storage representation of a key whose data is in a secure element. + */ +typedef struct +{ + uint8_t slot_number[sizeof( psa_key_slot_number_t )]; +} psa_se_key_data_storage_t; + +#endif /* PSA_CRYPTO_SE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.c new file mode 100644 index 00000000..a18350ee --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.c @@ -0,0 +1,584 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_C) + +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_driver_wrappers.h" +#include "psa_crypto_slot_management.h" +#include "psa_crypto_storage.h" +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#include "psa_crypto_se.h" +#endif + +#include +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +typedef struct +{ + psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT]; + unsigned key_slots_initialized : 1; +} psa_global_data_t; + +static psa_global_data_t global_data; + +int psa_is_valid_key_id( mbedtls_svc_key_id_t key, int vendor_ok ) +{ + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ); + + if( ( PSA_KEY_ID_USER_MIN <= key_id ) && + ( key_id <= PSA_KEY_ID_USER_MAX ) ) + return( 1 ); + + if( vendor_ok && + ( PSA_KEY_ID_VENDOR_MIN <= key_id ) && + ( key_id <= PSA_KEY_ID_VENDOR_MAX ) ) + return( 1 ); + + return( 0 ); +} + +/** Get the description in memory of a key given its identifier and lock it. + * + * The descriptions of volatile keys and loaded persistent keys are + * stored in key slots. This function returns a pointer to the key slot + * containing the description of a key given its identifier. + * + * The function searches the key slots containing the description of the key + * with \p key identifier. The function does only read accesses to the key + * slots. The function does not load any persistent key thus does not access + * any storage. + * + * For volatile key identifiers, only one key slot is queried as a volatile + * key with identifier key_id can only be stored in slot of index + * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ). + * + * On success, the function locks the key slot. It is the responsibility of + * the caller to unlock the key slot when it does not access it anymore. + * + * \param key Key identifier to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot containing the description of the key + * identified by \p key. + * + * \retval #PSA_SUCCESS + * The pointer to the key slot containing the description of the key + * identified by \p key was returned. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no key with key identifier \p key in the key slots. + */ +static psa_status_t psa_get_and_lock_key_slot_in_memory( + mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ); + size_t slot_idx; + psa_key_slot_t *slot = NULL; + + if( psa_key_id_is_volatile( key_id ) ) + { + slot = &global_data.key_slots[ key_id - PSA_KEY_ID_VOLATILE_MIN ]; + + /* + * Check if both the PSA key identifier key_id and the owner + * identifier of key match those of the key slot. + * + * Note that, if the key slot is not occupied, its PSA key identifier + * is equal to zero. This is an invalid value for a PSA key identifier + * and thus cannot be equal to the valid PSA key identifier key_id. + */ + status = mbedtls_svc_key_id_equal( key, slot->attr.id ) ? + PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; + } + else + { + if ( !psa_is_valid_key_id( key, 1 ) ) + return( PSA_ERROR_INVALID_HANDLE ); + + for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ ) + { + slot = &global_data.key_slots[ slot_idx ]; + if( mbedtls_svc_key_id_equal( key, slot->attr.id ) ) + break; + } + status = ( slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT ) ? + PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST; + } + + if( status == PSA_SUCCESS ) + { + status = psa_lock_key_slot( slot ); + if( status == PSA_SUCCESS ) + *p_slot = slot; + } + + return( status ); +} + +psa_status_t psa_initialize_key_slots( void ) +{ + /* Nothing to do: program startup and psa_wipe_all_key_slots() both + * guarantee that the key slots are initialized to all-zero, which + * means that all the key slots are in a valid, empty state. */ + global_data.key_slots_initialized = 1; + return( PSA_SUCCESS ); +} + +void psa_wipe_all_key_slots( void ) +{ + size_t slot_idx; + + for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ ) + { + psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ]; + slot->lock_count = 1; + (void) psa_wipe_key_slot( slot ); + } + global_data.key_slots_initialized = 0; +} + +psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + size_t slot_idx; + psa_key_slot_t *selected_slot, *unlocked_persistent_key_slot; + + if( ! global_data.key_slots_initialized ) + { + status = PSA_ERROR_BAD_STATE; + goto error; + } + + selected_slot = unlocked_persistent_key_slot = NULL; + for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ ) + { + psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ]; + if( ! psa_is_key_slot_occupied( slot ) ) + { + selected_slot = slot; + break; + } + + if( ( unlocked_persistent_key_slot == NULL ) && + ( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) && + ( ! psa_is_key_slot_locked( slot ) ) ) + unlocked_persistent_key_slot = slot; + } + + /* + * If there is no unused key slot and there is at least one unlocked key + * slot containing the description of a persistent key, recycle the first + * such key slot we encountered. If we later need to operate on the + * persistent key we are evicting now, we will reload its description from + * storage. + */ + if( ( selected_slot == NULL ) && + ( unlocked_persistent_key_slot != NULL ) ) + { + selected_slot = unlocked_persistent_key_slot; + selected_slot->lock_count = 1; + psa_wipe_key_slot( selected_slot ); + } + + if( selected_slot != NULL ) + { + status = psa_lock_key_slot( selected_slot ); + if( status != PSA_SUCCESS ) + goto error; + + *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + + ( (psa_key_id_t)( selected_slot - global_data.key_slots ) ); + *p_slot = selected_slot; + + return( PSA_SUCCESS ); + } + status = PSA_ERROR_INSUFFICIENT_MEMORY; + +error: + *p_slot = NULL; + *volatile_key_id = 0; + + return( status ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *key_data = NULL; + size_t key_data_length = 0; + + status = psa_load_persistent_key( &slot->attr, + &key_data, &key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Special handling is required for loading keys associated with a + * dynamically registered SE interface. */ + const psa_drv_se_t *drv; + psa_drv_se_context_t *drv_context; + if( psa_get_se_driver( slot->attr.lifetime, &drv, &drv_context ) ) + { + psa_se_key_data_storage_t *data; + + if( key_data_length != sizeof( *data ) ) + { + status = PSA_ERROR_DATA_INVALID; + goto exit; + } + data = (psa_se_key_data_storage_t *) key_data; + status = psa_copy_key_material_into_slot( + slot, data->slot_number, sizeof( data->slot_number ) ); + goto exit; + } +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + + status = psa_copy_key_material_into_slot( slot, key_data, key_data_length ); + +exit: + psa_free_persistent_key_data( key_data, key_data_length ); + return( status ); +} +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + +static psa_status_t psa_load_builtin_key_into_slot( psa_key_slot_t *slot ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE; + psa_drv_slot_number_t slot_number = 0; + size_t key_buffer_size = 0; + size_t key_buffer_length = 0; + + if( ! psa_key_id_is_builtin( + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id ) ) ) + { + return( PSA_ERROR_DOES_NOT_EXIST ); + } + + /* Check the platform function to see whether this key actually exists */ + status = mbedtls_psa_platform_get_builtin_key( + slot->attr.id, &lifetime, &slot_number ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Set required key attributes to ensure get_builtin_key can retrieve the + * full attributes. */ + psa_set_key_id( &attributes, slot->attr.id ); + psa_set_key_lifetime( &attributes, lifetime ); + + /* Get the full key attributes from the driver in order to be able to + * calculate the required buffer size. */ + status = psa_driver_wrapper_get_builtin_key( + slot_number, &attributes, + NULL, 0, NULL ); + if( status != PSA_ERROR_BUFFER_TOO_SMALL ) + { + /* Builtin keys cannot be defined by the attributes alone */ + if( status == PSA_SUCCESS ) + status = PSA_ERROR_CORRUPTION_DETECTED; + return( status ); + } + + /* If the key should exist according to the platform, then ask the driver + * what its expected size is. */ + status = psa_driver_wrapper_get_key_buffer_size( &attributes, + &key_buffer_size ); + if( status != PSA_SUCCESS ) + return( status ); + + /* Allocate a buffer of the required size and load the builtin key directly + * into the (now properly sized) slot buffer. */ + status = psa_allocate_buffer_to_slot( slot, key_buffer_size ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_driver_wrapper_get_builtin_key( + slot_number, &attributes, + slot->key.data, slot->key.bytes, &key_buffer_length ); + if( status != PSA_SUCCESS ) + goto exit; + + /* Copy actual key length and core attributes into the slot on success */ + slot->key.bytes = key_buffer_length; + slot->attr = attributes.core; + +exit: + if( status != PSA_SUCCESS ) + psa_remove_key_data_from_memory( slot ); + return( status ); +} +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +psa_status_t psa_get_and_lock_key_slot( mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot ) +{ + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + + *p_slot = NULL; + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + /* + * On success, the pointer to the slot is passed directly to the caller + * thus no need to unlock the key slot here. + */ + status = psa_get_and_lock_key_slot_in_memory( key, p_slot ); + if( status != PSA_ERROR_DOES_NOT_EXIST ) + return( status ); + + /* Loading keys from storage requires support for such a mechanism */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ + defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + psa_key_id_t volatile_key_id; + + status = psa_get_empty_key_slot( &volatile_key_id, p_slot ); + if( status != PSA_SUCCESS ) + return( status ); + + (*p_slot)->attr.id = key; + (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT; + + status = PSA_ERROR_DOES_NOT_EXIST; +#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + /* Load keys in the 'builtin' range through their own interface */ + status = psa_load_builtin_key_into_slot( *p_slot ); +#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( status == PSA_ERROR_DOES_NOT_EXIST ) + status = psa_load_persistent_key_into_slot( *p_slot ); +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + + if( status != PSA_SUCCESS ) + { + psa_wipe_key_slot( *p_slot ); + if( status == PSA_ERROR_DOES_NOT_EXIST ) + status = PSA_ERROR_INVALID_HANDLE; + } + else + /* Add implicit usage flags. */ + psa_extend_key_usage_flags( &(*p_slot)->attr.policy.usage ); + + return( status ); +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + return( PSA_ERROR_INVALID_HANDLE ); +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ +} + +psa_status_t psa_unlock_key_slot( psa_key_slot_t *slot ) +{ + if( slot == NULL ) + return( PSA_SUCCESS ); + + if( slot->lock_count > 0 ) + { + slot->lock_count--; + return( PSA_SUCCESS ); + } + + /* + * As the return error code may not be handled in case of multiple errors, + * do our best to report if the lock counter is equal to zero. Assert with + * MBEDTLS_TEST_HOOK_TEST_ASSERT that the lock counter is strictly greater + * than zero: if the MBEDTLS_TEST_HOOKS configuration option is enabled and + * the function is called as part of the execution of a test suite, the + * execution of the test suite is stopped in error if the assertion fails. + */ + MBEDTLS_TEST_HOOK_TEST_ASSERT( slot->lock_count > 0 ); + return( PSA_ERROR_CORRUPTION_DETECTED ); +} + +psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime, + psa_se_drv_table_entry_t **p_drv ) +{ + if ( psa_key_lifetime_is_external( lifetime ) ) + { +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + /* Check whether a driver is registered against this lifetime */ + psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry( lifetime ); + if( driver != NULL ) + { + if (p_drv != NULL) + *p_drv = driver; + return( PSA_SUCCESS ); + } +#else /* MBEDTLS_PSA_CRYPTO_SE_C */ + (void) p_drv; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + +#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS) + /* Key location for external keys gets checked by the wrapper */ + return( PSA_SUCCESS ); +#else /* MBEDTLS_PSA_CRYPTO_DRIVERS */ + /* No support for external lifetimes at all, or dynamic interface + * did not find driver for requested lifetime. */ + return( PSA_ERROR_INVALID_ARGUMENT ); +#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */ + } + else + /* Local/internal keys are always valid */ + return( PSA_SUCCESS ); +} + +psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime ) +{ + if ( PSA_KEY_LIFETIME_IS_VOLATILE( lifetime ) ) + { + /* Volatile keys are always supported */ + return( PSA_SUCCESS ); + } + else + { + /* Persistent keys require storage support */ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + if( PSA_KEY_LIFETIME_IS_READ_ONLY( lifetime ) ) + return( PSA_ERROR_INVALID_ARGUMENT ); + else + return( PSA_SUCCESS ); +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ + } +} + +psa_status_t psa_open_key( mbedtls_svc_key_id_t key, psa_key_handle_t *handle ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \ + defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS) + psa_status_t status; + psa_key_slot_t *slot; + + status = psa_get_and_lock_key_slot( key, &slot ); + if( status != PSA_SUCCESS ) + { + *handle = PSA_KEY_HANDLE_INIT; + if( status == PSA_ERROR_INVALID_HANDLE ) + status = PSA_ERROR_DOES_NOT_EXIST; + + return( status ); + } + + *handle = key; + + return( psa_unlock_key_slot( slot ) ); + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ + (void) key; + *handle = PSA_KEY_HANDLE_INIT; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */ +} + +psa_status_t psa_close_key( psa_key_handle_t handle ) +{ + psa_status_t status; + psa_key_slot_t *slot; + + if( psa_key_handle_is_null( handle ) ) + return( PSA_SUCCESS ); + + status = psa_get_and_lock_key_slot_in_memory( handle, &slot ); + if( status != PSA_SUCCESS ) + { + if( status == PSA_ERROR_DOES_NOT_EXIST ) + status = PSA_ERROR_INVALID_HANDLE; + + return( status ); + } + if( slot->lock_count <= 1 ) + return( psa_wipe_key_slot( slot ) ); + else + return( psa_unlock_key_slot( slot ) ); +} + +psa_status_t psa_purge_key( mbedtls_svc_key_id_t key ) +{ + psa_status_t status; + psa_key_slot_t *slot; + + status = psa_get_and_lock_key_slot_in_memory( key, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + if( ( ! PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) && + ( slot->lock_count <= 1 ) ) + return( psa_wipe_key_slot( slot ) ); + else + return( psa_unlock_key_slot( slot ) ); +} + +void mbedtls_psa_get_stats( mbedtls_psa_stats_t *stats ) +{ + size_t slot_idx; + + memset( stats, 0, sizeof( *stats ) ); + + for( slot_idx = 0; slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT; slot_idx++ ) + { + const psa_key_slot_t *slot = &global_data.key_slots[ slot_idx ]; + if( psa_is_key_slot_locked( slot ) ) + { + ++stats->locked_slots; + } + if( ! psa_is_key_slot_occupied( slot ) ) + { + ++stats->empty_slots; + continue; + } + if( PSA_KEY_LIFETIME_IS_VOLATILE( slot->attr.lifetime ) ) + ++stats->volatile_slots; + else + { + psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id ); + ++stats->persistent_slots; + if( id > stats->max_open_internal_key_id ) + stats->max_open_internal_key_id = id; + } + if( PSA_KEY_LIFETIME_GET_LOCATION( slot->attr.lifetime ) != + PSA_KEY_LOCATION_LOCAL_STORAGE ) + { + psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID( slot->attr.id ); + ++stats->external_slots; + if( id > stats->max_open_external_key_id ) + stats->max_open_external_key_id = id; + } + } +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.h new file mode 100644 index 00000000..d539bdd8 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_slot_management.h @@ -0,0 +1,224 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H +#define PSA_CRYPTO_SLOT_MANAGEMENT_H + +#include "psa/crypto.h" +#include "psa_crypto_core.h" +#include "psa_crypto_se.h" + +/** Range of volatile key identifiers. + * + * The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation + * range of key identifiers are reserved for volatile key identifiers. + * A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the + * index of the key slot containing the volatile key definition. + */ + +/** The minimum value for a volatile key identifier. + */ +#define PSA_KEY_ID_VOLATILE_MIN ( PSA_KEY_ID_VENDOR_MAX - \ + MBEDTLS_PSA_KEY_SLOT_COUNT + 1 ) + +/** The maximum value for a volatile key identifier. + */ +#define PSA_KEY_ID_VOLATILE_MAX PSA_KEY_ID_VENDOR_MAX + +/** Test whether a key identifier is a volatile key identifier. + * + * \param key_id Key identifier to test. + * + * \retval 1 + * The key identifier is a volatile key identifier. + * \retval 0 + * The key identifier is not a volatile key identifier. + */ +static inline int psa_key_id_is_volatile( psa_key_id_t key_id ) +{ + return( ( key_id >= PSA_KEY_ID_VOLATILE_MIN ) && + ( key_id <= PSA_KEY_ID_VOLATILE_MAX ) ); +} + +/** Get the description of a key given its identifier and lock it. + * + * The descriptions of volatile keys and loaded persistent keys are stored in + * key slots. This function returns a pointer to the key slot containing the + * description of a key given its identifier. + * + * In case of a persistent key, the function loads the description of the key + * into a key slot if not already done. + * + * On success, the returned key slot is locked. It is the responsibility of + * the caller to unlock the key slot when it does not access it anymore. + * + * \param key Key identifier to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot containing the description of the key + * identified by \p key. + * + * \retval #PSA_SUCCESS + * \p *p_slot contains a pointer to the key slot containing the + * description of the key identified by \p key. + * The key slot counter has been incremented. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been initialized. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p key is not a valid key identifier. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \p key is a persistent key identifier. The implementation does not + * have sufficient resources to load the persistent key. This can be + * due to a lack of empty key slot, or available memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no key with key identifier \p key. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_CORRUPT + */ +psa_status_t psa_get_and_lock_key_slot( mbedtls_svc_key_id_t key, + psa_key_slot_t **p_slot ); + +/** Initialize the key slot structures. + * + * \retval #PSA_SUCCESS + * Currently this function always succeeds. + */ +psa_status_t psa_initialize_key_slots( void ); + +/** Delete all data from key slots in memory. + * + * This does not affect persistent storage. */ +void psa_wipe_all_key_slots( void ); + +/** Find a free key slot. + * + * This function returns a key slot that is available for use and is in its + * ground state (all-bits-zero). On success, the key slot is locked. It is + * the responsibility of the caller to unlock the key slot when it does not + * access it anymore. + * + * \param[out] volatile_key_id On success, volatile key identifier + * associated to the returned slot. + * \param[out] p_slot On success, a pointer to the slot. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BAD_STATE + */ +psa_status_t psa_get_empty_key_slot( psa_key_id_t *volatile_key_id, + psa_key_slot_t **p_slot ); + +/** Lock a key slot. + * + * This function increments the key slot lock counter by one. + * + * \param[in] slot The key slot. + * + * \retval #PSA_SUCCESS + The key slot lock counter was incremented. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * The lock counter already reached its maximum value and was not + * increased. + */ +static inline psa_status_t psa_lock_key_slot( psa_key_slot_t *slot ) +{ + if( slot->lock_count >= SIZE_MAX ) + return( PSA_ERROR_CORRUPTION_DETECTED ); + + slot->lock_count++; + + return( PSA_SUCCESS ); +} + +/** Unlock a key slot. + * + * This function decrements the key slot lock counter by one. + * + * \note To ease the handling of errors in retrieving a key slot + * a NULL input pointer is valid, and the function returns + * successfully without doing anything in that case. + * + * \param[in] slot The key slot. + * \retval #PSA_SUCCESS + * \p slot is NULL or the key slot lock counter has been + * decremented successfully. + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * The lock counter was equal to 0. + * + */ +psa_status_t psa_unlock_key_slot( psa_key_slot_t *slot ); + +/** Test whether a lifetime designates a key in an external cryptoprocessor. + * + * \param lifetime The lifetime to test. + * + * \retval 1 + * The lifetime designates an external key. There should be a + * registered driver for this lifetime, otherwise the key cannot + * be created or manipulated. + * \retval 0 + * The lifetime designates a key that is volatile or in internal + * storage. + */ +static inline int psa_key_lifetime_is_external( psa_key_lifetime_t lifetime ) +{ + return( PSA_KEY_LIFETIME_GET_LOCATION( lifetime ) + != PSA_KEY_LOCATION_LOCAL_STORAGE ); +} + +/** Validate a key's location. + * + * This function checks whether the key's attributes point to a location that + * is known to the PSA Core, and returns the driver function table if the key + * is to be found in an external location. + * + * \param[in] lifetime The key lifetime attribute. + * \param[out] p_drv On success, when a key is located in external + * storage, returns a pointer to the driver table + * associated with the key's storage location. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + */ +psa_status_t psa_validate_key_location( psa_key_lifetime_t lifetime, + psa_se_drv_table_entry_t **p_drv ); + +/** Validate the persistence of a key. + * + * \param[in] lifetime The key lifetime attribute. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys + * are not supported. + */ +psa_status_t psa_validate_key_persistence( psa_key_lifetime_t lifetime ); + +/** Validate a key identifier. + * + * \param[in] key The key identifier. + * \param[in] vendor_ok Non-zero to indicate that key identifiers in the + * vendor range are allowed, volatile key identifiers + * excepted \c 0 otherwise. + * + * \retval <> 0 if the key identifier is valid, 0 otherwise. + */ +int psa_is_valid_key_id( mbedtls_svc_key_id_t key, int vendor_ok ); + +#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.c new file mode 100644 index 00000000..c6660b95 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.c @@ -0,0 +1,490 @@ +/* + * PSA persistent key storage + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + +#include +#include + +#include "psa/crypto.h" +#include "psa_crypto_storage.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) +#include "psa_crypto_its.h" +#else /* Native ITS implementation */ +#include "psa/error.h" +#include "psa/internal_trusted_storage.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + + + +/****************************************************************/ +/* Key storage */ +/****************************************************************/ + +/* Determine a file name (ITS file identifier) for the given key identifier. + * The file name must be distinct from any file that is used for a purpose + * other than storing a key. Currently, the only such file is the random seed + * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is + * 0xFFFFFF52. */ +static psa_storage_uid_t psa_its_identifier_of_slot( mbedtls_svc_key_id_t key ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) + /* Encode the owner in the upper 32 bits. This means that if + * owner values are nonzero (as they are on a PSA platform), + * no key file will ever have a value less than 0x100000000, so + * the whole range 0..0xffffffff is available for non-key files. */ + uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID( key ); + return( ( (uint64_t) unsigned_owner_id << 32 ) | + MBEDTLS_SVC_KEY_ID_GET_KEY_ID( key ) ); +#else + /* Use the key id directly as a file name. + * psa_is_key_id_valid() in psa_crypto_slot_management.c + * is responsible for ensuring that key identifiers do not have a + * value that is reserved for non-key files. */ + return( key ); +#endif +} + +/** + * \brief Load persistent data for the given key slot number. + * + * This function reads data from a storage backend and returns the data in a + * buffer. + * + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. + * \param[out] data Buffer where the data is to be written. + * \param data_size Size of the \c data buffer in bytes. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DOES_NOT_EXIST + */ +static psa_status_t psa_crypto_storage_load( + const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + size_t data_length = 0; + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_its_get( data_identifier, 0, (uint32_t) data_size, data, &data_length ); + if( data_size != data_length ) + return( PSA_ERROR_DATA_INVALID ); + + return( status ); +} + +int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key ) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + + if( ret == PSA_ERROR_DOES_NOT_EXIST ) + return( 0 ); + return( 1 ); +} + +/** + * \brief Store persistent data for the given key slot number. + * + * This function stores the given data buffer to a persistent storage. + * + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. + * \param[in] data Buffer containing the data to be stored. + * \param data_length The number of bytes + * that make up the data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_ALREADY_EXISTS + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_INVALID + */ +static psa_status_t psa_crypto_storage_store( const mbedtls_svc_key_id_t key, + const uint8_t *data, + size_t data_length ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + if( psa_is_key_present_in_storage( key ) == 1 ) + return( PSA_ERROR_ALREADY_EXISTS ); + + status = psa_its_set( data_identifier, (uint32_t) data_length, data, 0 ); + if( status != PSA_SUCCESS ) + { + return( PSA_ERROR_DATA_INVALID ); + } + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + { + goto exit; + } + + if( data_identifier_info.size != data_length ) + { + status = PSA_ERROR_DATA_INVALID; + goto exit; + } + +exit: + if( status != PSA_SUCCESS ) + { + /* Remove the file in case we managed to create it but something + * went wrong. It's ok if the file doesn't exist. If the file exists + * but the removal fails, we're already reporting an error so there's + * nothing else we can do. */ + (void) psa_its_remove( data_identifier ); + } + return( status ); +} + +psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key ) +{ + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + if( ret == PSA_ERROR_DOES_NOT_EXIST ) + return( PSA_SUCCESS ); + + if( psa_its_remove( data_identifier ) != PSA_SUCCESS ) + return( PSA_ERROR_DATA_INVALID ); + + ret = psa_its_get_info( data_identifier, &data_identifier_info ); + if( ret != PSA_ERROR_DOES_NOT_EXIST ) + return( PSA_ERROR_DATA_INVALID ); + + return( PSA_SUCCESS ); +} + +/** + * \brief Get data length for given key slot number. + * + * \param key Persistent identifier whose stored data length + * is to be obtained. + * \param[out] data_length The number of bytes that make up the data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_DATA_CORRUPT + */ +static psa_status_t psa_crypto_storage_get_data_length( + const mbedtls_svc_key_id_t key, + size_t *data_length ) +{ + psa_status_t status; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; + + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) + return( status ); + + *data_length = (size_t) data_identifier_info.size; + + return( PSA_SUCCESS ); +} + +/** + * Persistent key storage magic header. + */ +#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY" +#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ( sizeof( PSA_KEY_STORAGE_MAGIC_HEADER ) ) + +typedef struct { + uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH]; + uint8_t version[4]; + uint8_t lifetime[sizeof( psa_key_lifetime_t )]; + uint8_t type[2]; + uint8_t bits[2]; + uint8_t policy[sizeof( psa_key_policy_t )]; + uint8_t data_len[4]; + uint8_t key_data[]; +} psa_persistent_key_storage_format; + +void psa_format_key_data_for_storage( const uint8_t *data, + const size_t data_length, + const psa_core_key_attributes_t *attr, + uint8_t *storage_data ) +{ + psa_persistent_key_storage_format *storage_format = + (psa_persistent_key_storage_format *) storage_data; + + memcpy( storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER, PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ); + MBEDTLS_PUT_UINT32_LE( 0, storage_format->version, 0 ); + MBEDTLS_PUT_UINT32_LE( attr->lifetime, storage_format->lifetime, 0 ); + MBEDTLS_PUT_UINT16_LE( (uint16_t) attr->type, storage_format->type, 0 ); + MBEDTLS_PUT_UINT16_LE( (uint16_t) attr->bits, storage_format->bits, 0 ); + MBEDTLS_PUT_UINT32_LE( attr->policy.usage, storage_format->policy, 0 ); + MBEDTLS_PUT_UINT32_LE( attr->policy.alg, storage_format->policy, sizeof( uint32_t ) ); + MBEDTLS_PUT_UINT32_LE( attr->policy.alg2, storage_format->policy, 2 * sizeof( uint32_t ) ); + MBEDTLS_PUT_UINT32_LE( data_length, storage_format->data_len, 0 ); + memcpy( storage_format->key_data, data, data_length ); +} + +static psa_status_t check_magic_header( const uint8_t *data ) +{ + if( memcmp( data, PSA_KEY_STORAGE_MAGIC_HEADER, + PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH ) != 0 ) + return( PSA_ERROR_DATA_INVALID ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_core_key_attributes_t *attr ) +{ + psa_status_t status; + const psa_persistent_key_storage_format *storage_format = + (const psa_persistent_key_storage_format *)storage_data; + uint32_t version; + + if( storage_data_length < sizeof(*storage_format) ) + return( PSA_ERROR_DATA_INVALID ); + + status = check_magic_header( storage_data ); + if( status != PSA_SUCCESS ) + return( status ); + + version = MBEDTLS_GET_UINT32_LE( storage_format->version, 0 ); + if( version != 0 ) + return( PSA_ERROR_DATA_INVALID ); + + *key_data_length = MBEDTLS_GET_UINT32_LE( storage_format->data_len, 0 ); + if( *key_data_length > ( storage_data_length - sizeof(*storage_format) ) || + *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) + return( PSA_ERROR_DATA_INVALID ); + + if( *key_data_length == 0 ) + { + *key_data = NULL; + } + else + { + *key_data = mbedtls_calloc( 1, *key_data_length ); + if( *key_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + memcpy( *key_data, storage_format->key_data, *key_data_length ); + } + + attr->lifetime = MBEDTLS_GET_UINT32_LE( storage_format->lifetime, 0 ); + attr->type = MBEDTLS_GET_UINT16_LE( storage_format->type, 0 ); + attr->bits = MBEDTLS_GET_UINT16_LE( storage_format->bits, 0 ); + attr->policy.usage = MBEDTLS_GET_UINT32_LE( storage_format->policy, 0 ); + attr->policy.alg = MBEDTLS_GET_UINT32_LE( storage_format->policy, sizeof( uint32_t ) ); + attr->policy.alg2 = MBEDTLS_GET_UINT32_LE( storage_format->policy, 2 * sizeof( uint32_t ) ); + + return( PSA_SUCCESS ); +} + +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length ) +{ + size_t storage_data_length; + uint8_t *storage_data; + psa_status_t status; + + /* All keys saved to persistent storage always have a key context */ + if( data == NULL || data_length == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + if( data_length > PSA_CRYPTO_MAX_STORAGE_SIZE ) + return( PSA_ERROR_INSUFFICIENT_STORAGE ); + storage_data_length = data_length + sizeof( psa_persistent_key_storage_format ); + + storage_data = mbedtls_calloc( 1, storage_data_length ); + if( storage_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + psa_format_key_data_for_storage( data, data_length, attr, storage_data ); + + status = psa_crypto_storage_store( attr->id, + storage_data, storage_data_length ); + + mbedtls_free( storage_data ); + + return( status ); +} + +void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) +{ + if( key_data != NULL ) + { + mbedtls_platform_zeroize( key_data, key_data_length ); + } + mbedtls_free( key_data ); +} + +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, + uint8_t **data, + size_t *data_length ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *loaded_data; + size_t storage_data_length = 0; + mbedtls_svc_key_id_t key = attr->id; + + status = psa_crypto_storage_get_data_length( key, &storage_data_length ); + if( status != PSA_SUCCESS ) + return( status ); + + loaded_data = mbedtls_calloc( 1, storage_data_length ); + + if( loaded_data == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + + status = psa_crypto_storage_load( key, loaded_data, storage_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + + status = psa_parse_key_data_from_storage( loaded_data, storage_data_length, + data, data_length, attr ); + + /* All keys saved to persistent storage always have a key context */ + if( status == PSA_SUCCESS && + ( *data == NULL || *data_length == 0 ) ) + status = PSA_ERROR_STORAGE_FAILURE; + +exit: + mbedtls_free( loaded_data ); + return( status ); +} + + + +/****************************************************************/ +/* Transactions */ +/****************************************************************/ + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +psa_crypto_transaction_t psa_crypto_transaction; + +psa_status_t psa_crypto_save_transaction( void ) +{ + struct psa_storage_info_t p_info; + psa_status_t status; + status = psa_its_get_info( PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info ); + if( status == PSA_SUCCESS ) + { + /* This shouldn't happen: we're trying to start a transaction while + * there is still a transaction that hasn't been replayed. */ + return( PSA_ERROR_CORRUPTION_DETECTED ); + } + else if( status != PSA_ERROR_DOES_NOT_EXIST ) + return( status ); + return( psa_its_set( PSA_CRYPTO_ITS_TRANSACTION_UID, + sizeof( psa_crypto_transaction ), + &psa_crypto_transaction, + 0 ) ); +} + +psa_status_t psa_crypto_load_transaction( void ) +{ + psa_status_t status; + size_t length; + status = psa_its_get( PSA_CRYPTO_ITS_TRANSACTION_UID, 0, + sizeof( psa_crypto_transaction ), + &psa_crypto_transaction, &length ); + if( status != PSA_SUCCESS ) + return( status ); + if( length != sizeof( psa_crypto_transaction ) ) + return( PSA_ERROR_DATA_INVALID ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_crypto_stop_transaction( void ) +{ + psa_status_t status = psa_its_remove( PSA_CRYPTO_ITS_TRANSACTION_UID ); + /* Whether or not updating the storage succeeded, the transaction is + * finished now. It's too late to go back, so zero out the in-memory + * data. */ + memset( &psa_crypto_transaction, 0, sizeof( psa_crypto_transaction ) ); + return( status ); +} + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + + + +/****************************************************************/ +/* Random generator state */ +/****************************************************************/ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ) +{ + psa_status_t status; + struct psa_storage_info_t p_info; + + status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); + + if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ + { + status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); + } + else if( PSA_SUCCESS == status ) + { + /* You should not be here. Seed needs to be injected only once */ + status = PSA_ERROR_NOT_PERMITTED; + } + return( status ); +} +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + + + +/****************************************************************/ +/* The end */ +/****************************************************************/ + +#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.h b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.h new file mode 100644 index 00000000..970e1083 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_crypto_storage.h @@ -0,0 +1,399 @@ +/** + * \file psa_crypto_storage.h + * + * \brief PSA cryptography module: Mbed TLS key storage + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ + +#ifndef PSA_CRYPTO_STORAGE_H +#define PSA_CRYPTO_STORAGE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "psa/crypto.h" +#include "psa/crypto_se_driver.h" + +#include +#include + +/* Limit the maximum key size in storage. This should have no effect + * since the key size is limited in memory. */ +#define PSA_CRYPTO_MAX_STORAGE_SIZE ( PSA_BITS_TO_BYTES( PSA_MAX_KEY_BITS ) ) +/* Sanity check: a file size must fit in 32 bits. Allow a generous + * 64kB of metadata. */ +#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#error PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000 +#endif + +/** The maximum permitted persistent slot number. + * + * In Mbed Crypto 0.1.0b: + * - Using the file backend, all key ids are ok except 0. + * - Using the ITS backend, all key ids are ok except 0xFFFFFF52 + * (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the + * device's random seed (if this feature is enabled). + * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used. + * + * Since we need to preserve the random seed, avoid using that key slot. + * Reserve a whole range of key slots just in case something else comes up. + * + * This limitation will probably become moot when we implement client + * separation for key storage. + */ +#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX + +/** + * \brief Checks if persistent data is stored for the given key slot number + * + * This function checks if any key data or metadata exists for the key slot in + * the persistent storage. + * + * \param key Persistent identifier to check. + * + * \retval 0 + * No persistent data present for slot number + * \retval 1 + * Persistent data present for slot number + */ +int psa_is_key_present_in_storage( const mbedtls_svc_key_id_t key ); + +/** + * \brief Format key data and metadata and save to a location for given key + * slot. + * + * This function formats the key data and metadata and saves it to a + * persistent storage backend. The storage location corresponding to the + * key slot must be empty, otherwise this function will fail. This function + * should be called after loading the key into an internal slot to ensure the + * persistent key is not saved into a storage location corresponding to an + * already occupied non-persistent key, as well as ensuring the key data is + * validated. + * + * Note: This function will only succeed for key buffers which are not + * empty. If passed a NULL pointer or zero-length, the function will fail + * with #PSA_ERROR_INVALID_ARGUMENT. + * + * \param[in] attr The attributes of the key to save. + * The key identifier field in the attributes + * determines the key's location. + * \param[in] data Buffer containing the key data. + * \param data_length The number of bytes that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_ALREADY_EXISTS + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + */ +psa_status_t psa_save_persistent_key( const psa_core_key_attributes_t *attr, + const uint8_t *data, + const size_t data_length ); + +/** + * \brief Parses key data and metadata and load persistent key for given + * key slot number. + * + * This function reads from a storage backend, parses the key data and + * metadata and writes them to the appropriate output parameters. + * + * Note: This function allocates a buffer and returns a pointer to it through + * the data parameter. On successful return, the pointer is guaranteed to be + * valid and the buffer contains at least one byte of data. + * psa_free_persistent_key_data() must be called on the data buffer + * afterwards to zeroize and free this buffer. + * + * \param[in,out] attr On input, the key identifier field identifies + * the key to load. Other fields are ignored. + * On success, the attribute structure contains + * the key metadata that was loaded from storage. + * \param[out] data Pointer to an allocated key data buffer on return. + * \param[out] data_length The number of bytes that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_DOES_NOT_EXIST + */ +psa_status_t psa_load_persistent_key( psa_core_key_attributes_t *attr, + uint8_t **data, + size_t *data_length ); + +/** + * \brief Remove persistent data for the given key slot number. + * + * \param key Persistent identifier of the key to remove + * from persistent storage. + * + * \retval #PSA_SUCCESS + * The key was successfully removed, + * or the key did not exist. + * \retval #PSA_ERROR_DATA_INVALID + */ +psa_status_t psa_destroy_persistent_key( const mbedtls_svc_key_id_t key ); + +/** + * \brief Free the temporary buffer allocated by psa_load_persistent_key(). + * + * This function must be called at some point after psa_load_persistent_key() + * to zeroize and free the memory allocated to the buffer in that function. + * + * \param key_data Buffer for the key data. + * \param key_data_length Size of the key data buffer. + * + */ +void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ); + +/** + * \brief Formats key data and metadata for persistent storage + * + * \param[in] data Buffer containing the key data. + * \param data_length Length of the key data buffer. + * \param[in] attr The core attributes of the key. + * \param[out] storage_data Output buffer for the formatted data. + * + */ +void psa_format_key_data_for_storage( const uint8_t *data, + const size_t data_length, + const psa_core_key_attributes_t *attr, + uint8_t *storage_data ); + +/** + * \brief Parses persistent storage data into key data and metadata + * + * \param[in] storage_data Buffer for the storage data. + * \param storage_data_length Length of the storage data buffer + * \param[out] key_data On output, pointer to a newly allocated buffer + * containing the key data. This must be freed + * using psa_free_persistent_key_data() + * \param[out] key_data_length Length of the key data buffer + * \param[out] attr On success, the attribute structure is filled + * with the loaded key metadata. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_DATA_INVALID + */ +psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, + size_t storage_data_length, + uint8_t **key_data, + size_t *key_data_length, + psa_core_key_attributes_t *attr ); + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +/** This symbol is defined if transaction support is required. */ +#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS +#endif + +#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) + +/** The type of transaction that is in progress. + */ +/* This is an integer type rather than an enum for two reasons: to support + * unknown values when loading a transaction file, and to ensure that the + * type has a known size. + */ +typedef uint16_t psa_crypto_transaction_type_t; + +/** No transaction is in progress. + * + * This has the value 0, so zero-initialization sets a transaction's type to + * this value. + */ +#define PSA_CRYPTO_TRANSACTION_NONE ( (psa_crypto_transaction_type_t) 0x0000 ) + +/** A key creation transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are created atomically in storage + * (simple file creation), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_CREATE_KEY ( (psa_crypto_transaction_type_t) 0x0001 ) + +/** A key destruction transaction. + * + * This is only used for keys in an external cryptoprocessor (secure element). + * Keys in RAM or in internal storage are destroyed atomically in storage + * (simple file deletion), so they do not need a transaction mechanism. + */ +#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY ( (psa_crypto_transaction_type_t) 0x0002 ) + +/** Transaction data. + * + * This type is designed to be serialized by writing the memory representation + * and reading it back on the same device. + * + * \note The transaction mechanism is designed for a single active transaction + * at a time. The transaction object is #psa_crypto_transaction. + * + * \note If an API call starts a transaction, it must complete this transaction + * before returning to the application. + * + * The lifetime of a transaction is the following (note that only one + * transaction may be active at a time): + * + * -# Call psa_crypto_prepare_transaction() to initialize the transaction + * object in memory and declare the type of transaction that is starting. + * -# Fill in the type-specific fields of #psa_crypto_transaction. + * -# Call psa_crypto_save_transaction() to start the transaction. This + * saves the transaction data to internal storage. + * -# Perform the work of the transaction by modifying files, contacting + * external entities, or whatever needs doing. Note that the transaction + * may be interrupted by a power failure, so you need to have a way + * recover from interruptions either by undoing what has been done + * so far or by resuming where you left off. + * -# If there are intermediate stages in the transaction, update + * the fields of #psa_crypto_transaction and call + * psa_crypto_save_transaction() again when each stage is reached. + * -# When the transaction is over, call psa_crypto_stop_transaction() to + * remove the transaction data in storage and in memory. + * + * If the system crashes while a transaction is in progress, psa_crypto_init() + * calls psa_crypto_load_transaction() and takes care of completing or + * rewinding the transaction. This is done in psa_crypto_recover_transaction() + * in psa_crypto.c. If you add a new type of transaction, be + * sure to add code for it in psa_crypto_recover_transaction(). + */ +typedef union +{ + /* Each element of this union must have the following properties + * to facilitate serialization and deserialization: + * + * - The element is a struct. + * - The first field of the struct is `psa_crypto_transaction_type_t type`. + * - Elements of the struct are arranged such a way that there is + * no padding. + */ + struct psa_crypto_transaction_unknown_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + uint32_t unused2; + uint64_t unused3; + uint64_t unused4; + } unknown; + /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or + * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */ + struct psa_crypto_transaction_key_s + { + psa_crypto_transaction_type_t type; + uint16_t unused1; + psa_key_lifetime_t lifetime; + psa_key_slot_number_t slot; + mbedtls_svc_key_id_t id; + } key; +} psa_crypto_transaction_t; + +/** The single active transaction. + */ +extern psa_crypto_transaction_t psa_crypto_transaction; + +/** Prepare for a transaction. + * + * There must not be an ongoing transaction. + * + * \param type The type of transaction to start. + */ +static inline void psa_crypto_prepare_transaction( + psa_crypto_transaction_type_t type ) +{ + psa_crypto_transaction.unknown.type = type; +} + +/** Save the transaction data to storage. + * + * You may call this function multiple times during a transaction to + * atomically update the transaction state. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_DATA_CORRUPT + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +psa_status_t psa_crypto_save_transaction( void ); + +/** Load the transaction data from storage, if any. + * + * This function is meant to be called from psa_crypto_init() to recover + * in case a transaction was interrupted by a system crash. + * + * \retval #PSA_SUCCESS + * The data about the ongoing transaction has been loaded to + * #psa_crypto_transaction. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no ongoing transaction. + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_DATA_INVALID + * \retval #PSA_ERROR_DATA_CORRUPT + */ +psa_status_t psa_crypto_load_transaction( void ); + +/** Indicate that the current transaction is finished. + * + * Call this function at the very end of transaction processing. + * This function does not "commit" or "abort" the transaction: the storage + * subsystem has no concept of "commit" and "abort", just saving and + * removing the transaction information in storage. + * + * This function erases the transaction data in storage (if any) and + * resets the transaction data in memory. + * + * \retval #PSA_SUCCESS + * There was transaction data in storage. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There was no transaction data in storage. + * \retval #PSA_ERROR_STORAGE_FAILURE + * It was impossible to determine whether there was transaction data + * in storage, or the transaction data could not be erased. + */ +psa_status_t psa_crypto_stop_transaction( void ); + +/** The ITS file identifier for the transaction data. + * + * 0xffffffNN = special file; 0x74 = 't' for transaction. + */ +#define PSA_CRYPTO_ITS_TRANSACTION_UID ( (psa_key_id_t) 0xffffff74 ) + +#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */ + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) +/** Backend side of mbedtls_psa_inject_entropy(). + * + * This function stores the supplied data into the entropy seed file. + * + * \retval #PSA_SUCCESS + * Success + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_NOT_PERMITTED + * The entropy seed file already exists. + */ +psa_status_t mbedtls_psa_storage_inject_entropy( const unsigned char *seed, + size_t seed_size ); +#endif /* MBEDTLS_PSA_INJECT_ENTROPY */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STORAGE_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/psa_its_file.c b/component/common/network/ssl/mbedtls-3.1.0/library/psa_its_file.c new file mode 100644 index 00000000..c4782cdb --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/psa_its_file.c @@ -0,0 +1,249 @@ +/* + * PSA ITS simulator over stdio files. + */ +/* + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_PSA_ITS_FILE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) +#include +#endif + +#include "psa_crypto_its.h" + +#include +#include +#include +#include + +#if !defined(PSA_ITS_STORAGE_PREFIX) +#define PSA_ITS_STORAGE_PREFIX "" +#endif + +#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x" +#define PSA_ITS_STORAGE_SUFFIX ".psa_its" +#define PSA_ITS_STORAGE_FILENAME_LENGTH \ + ( sizeof( PSA_ITS_STORAGE_PREFIX ) - 1 + /*prefix without terminating 0*/ \ + 16 + /*UID (64-bit number in hex)*/ \ + sizeof( PSA_ITS_STORAGE_SUFFIX ) - 1 + /*suffix without terminating 0*/ \ + 1 /*terminating null byte*/ ) +#define PSA_ITS_STORAGE_TEMP \ + PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX + +/* The maximum value of psa_storage_info_t.size */ +#define PSA_ITS_MAX_SIZE 0xffffffff + +#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0" +#define PSA_ITS_MAGIC_LENGTH 8 + +/* As rename fails on Windows if the new filepath already exists, + * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead. + * Returns 0 on success, nonzero on failure. */ +#if defined(_WIN32) +#define rename_replace_existing( oldpath, newpath ) \ + ( ! MoveFileExA( oldpath, newpath, MOVEFILE_REPLACE_EXISTING ) ) +#else +#define rename_replace_existing( oldpath, newpath ) rename( oldpath, newpath ) +#endif + +typedef struct +{ + uint8_t magic[PSA_ITS_MAGIC_LENGTH]; + uint8_t size[sizeof( uint32_t )]; + uint8_t flags[sizeof( psa_storage_create_flags_t )]; +} psa_its_file_header_t; + +static void psa_its_fill_filename( psa_storage_uid_t uid, char *filename ) +{ + /* Break up the UID into two 32-bit pieces so as not to rely on + * long long support in snprintf. */ + mbedtls_snprintf( filename, PSA_ITS_STORAGE_FILENAME_LENGTH, + "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s", + PSA_ITS_STORAGE_PREFIX, + (unsigned) ( uid >> 32 ), + (unsigned) ( uid & 0xffffffff ), + PSA_ITS_STORAGE_SUFFIX ); +} + +static psa_status_t psa_its_read_file( psa_storage_uid_t uid, + struct psa_storage_info_t *p_info, + FILE **p_stream ) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + psa_its_file_header_t header; + size_t n; + + *p_stream = NULL; + psa_its_fill_filename( uid, filename ); + *p_stream = fopen( filename, "rb" ); + if( *p_stream == NULL ) + return( PSA_ERROR_DOES_NOT_EXIST ); + + n = fread( &header, 1, sizeof( header ), *p_stream ); + if( n != sizeof( header ) ) + return( PSA_ERROR_DATA_CORRUPT ); + if( memcmp( header.magic, PSA_ITS_MAGIC_STRING, + PSA_ITS_MAGIC_LENGTH ) != 0 ) + return( PSA_ERROR_DATA_CORRUPT ); + + p_info->size = ( header.size[0] | + header.size[1] << 8 | + header.size[2] << 16 | + header.size[3] << 24 ); + p_info->flags = ( header.flags[0] | + header.flags[1] << 8 | + header.flags[2] << 16 | + header.flags[3] << 24 ); + return( PSA_SUCCESS ); +} + +psa_status_t psa_its_get_info( psa_storage_uid_t uid, + struct psa_storage_info_t *p_info ) +{ + psa_status_t status; + FILE *stream = NULL; + status = psa_its_read_file( uid, p_info, &stream ); + if( stream != NULL ) + fclose( stream ); + return( status ); +} + +psa_status_t psa_its_get( psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + void *p_data, + size_t *p_data_length ) +{ + psa_status_t status; + FILE *stream = NULL; + size_t n; + struct psa_storage_info_t info; + + status = psa_its_read_file( uid, &info, &stream ); + if( status != PSA_SUCCESS ) + goto exit; + status = PSA_ERROR_INVALID_ARGUMENT; + if( data_offset + data_length < data_offset ) + goto exit; +#if SIZE_MAX < 0xffffffff + if( data_offset + data_length > SIZE_MAX ) + goto exit; +#endif + if( data_offset + data_length > info.size ) + goto exit; + + status = PSA_ERROR_STORAGE_FAILURE; +#if LONG_MAX < 0xffffffff + while( data_offset > LONG_MAX ) + { + if( fseek( stream, LONG_MAX, SEEK_CUR ) != 0 ) + goto exit; + data_offset -= LONG_MAX; + } +#endif + if( fseek( stream, data_offset, SEEK_CUR ) != 0 ) + goto exit; + n = fread( p_data, 1, data_length, stream ); + if( n != data_length ) + goto exit; + status = PSA_SUCCESS; + if( p_data_length != NULL ) + *p_data_length = n; + +exit: + if( stream != NULL ) + fclose( stream ); + return( status ); +} + +psa_status_t psa_its_set( psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags ) +{ + psa_status_t status = PSA_ERROR_STORAGE_FAILURE; + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream = NULL; + psa_its_file_header_t header; + size_t n; + + memcpy( header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH ); + MBEDTLS_PUT_UINT32_LE( data_length, header.size, 0 ); + MBEDTLS_PUT_UINT32_LE( create_flags, header.flags, 0 ); + + psa_its_fill_filename( uid, filename ); + stream = fopen( PSA_ITS_STORAGE_TEMP, "wb" ); + if( stream == NULL ) + goto exit; + + status = PSA_ERROR_INSUFFICIENT_STORAGE; + n = fwrite( &header, 1, sizeof( header ), stream ); + if( n != sizeof( header ) ) + goto exit; + if( data_length != 0 ) + { + n = fwrite( p_data, 1, data_length, stream ); + if( n != data_length ) + goto exit; + } + status = PSA_SUCCESS; + +exit: + if( stream != NULL ) + { + int ret = fclose( stream ); + if( status == PSA_SUCCESS && ret != 0 ) + status = PSA_ERROR_INSUFFICIENT_STORAGE; + } + if( status == PSA_SUCCESS ) + { + if( rename_replace_existing( PSA_ITS_STORAGE_TEMP, filename ) != 0 ) + status = PSA_ERROR_STORAGE_FAILURE; + } + /* The temporary file may still exist, but only in failure cases where + * we're already reporting an error. So there's nothing we can do on + * failure. If the function succeeded, and in some error cases, the + * temporary file doesn't exist and so remove() is expected to fail. + * Thus we just ignore the return status of remove(). */ + (void) remove( PSA_ITS_STORAGE_TEMP ); + return( status ); +} + +psa_status_t psa_its_remove( psa_storage_uid_t uid ) +{ + char filename[PSA_ITS_STORAGE_FILENAME_LENGTH]; + FILE *stream; + psa_its_fill_filename( uid, filename ); + stream = fopen( filename, "rb" ); + if( stream == NULL ) + return( PSA_ERROR_DOES_NOT_EXIST ); + fclose( stream ); + if( remove( filename ) != 0 ) + return( PSA_ERROR_STORAGE_FAILURE ); + return( PSA_SUCCESS ); +} + +#endif /* MBEDTLS_PSA_ITS_FILE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ripemd160.c b/component/common/network/ssl/mbedtls-3.1.0/library/ripemd160.c new file mode 100644 index 00000000..41d83872 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ripemd160.c @@ -0,0 +1,496 @@ +/* + * RIPE MD-160 implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * The RIPEMD-160 algorithm was designed by RIPE in 1996 + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html + * http://ehash.iaik.tugraz.at/wiki/RIPEMD-160 + */ + +#include "common.h" + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_RIPEMD160_ALT) + +void mbedtls_ripemd160_init( mbedtls_ripemd160_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_free( mbedtls_ripemd160_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ripemd160_context ) ); +} + +void mbedtls_ripemd160_clone( mbedtls_ripemd160_context *dst, + const mbedtls_ripemd160_context *src ) +{ + *dst = *src; +} + +/* + * RIPEMD-160 context setup + */ +int mbedtls_ripemd160_starts( mbedtls_ripemd160_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_RIPEMD160_PROCESS_ALT) +/* + * Process one block + */ +int mbedtls_internal_ripemd160_process( mbedtls_ripemd160_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + } local; + + local.X[ 0] = MBEDTLS_GET_UINT32_LE( data, 0 ); + local.X[ 1] = MBEDTLS_GET_UINT32_LE( data, 4 ); + local.X[ 2] = MBEDTLS_GET_UINT32_LE( data, 8 ); + local.X[ 3] = MBEDTLS_GET_UINT32_LE( data, 12 ); + local.X[ 4] = MBEDTLS_GET_UINT32_LE( data, 16 ); + local.X[ 5] = MBEDTLS_GET_UINT32_LE( data, 20 ); + local.X[ 6] = MBEDTLS_GET_UINT32_LE( data, 24 ); + local.X[ 7] = MBEDTLS_GET_UINT32_LE( data, 28 ); + local.X[ 8] = MBEDTLS_GET_UINT32_LE( data, 32 ); + local.X[ 9] = MBEDTLS_GET_UINT32_LE( data, 36 ); + local.X[10] = MBEDTLS_GET_UINT32_LE( data, 40 ); + local.X[11] = MBEDTLS_GET_UINT32_LE( data, 44 ); + local.X[12] = MBEDTLS_GET_UINT32_LE( data, 48 ); + local.X[13] = MBEDTLS_GET_UINT32_LE( data, 52 ); + local.X[14] = MBEDTLS_GET_UINT32_LE( data, 56 ); + local.X[15] = MBEDTLS_GET_UINT32_LE( data, 60 ); + + local.A = local.Ap = ctx->state[0]; + local.B = local.Bp = ctx->state[1]; + local.C = local.Cp = ctx->state[2]; + local.D = local.Dp = ctx->state[3]; + local.E = local.Ep = ctx->state[4]; + +#define F1( x, y, z ) ( (x) ^ (y) ^ (z) ) +#define F2( x, y, z ) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) +#define F3( x, y, z ) ( ( (x) | ~(y) ) ^ (z) ) +#define F4( x, y, z ) ( ( (x) & (z) ) | ( (y) & ~(z) ) ) +#define F5( x, y, z ) ( (x) ^ ( (y) | ~(z) ) ) + +#define S( x, n ) ( ( (x) << (n) ) | ( (x) >> (32 - (n)) ) ) + +#define P( a, b, c, d, e, r, s, f, k ) \ + do \ + { \ + (a) += f( (b), (c), (d) ) + local.X[r] + (k); \ + (a) = S( (a), (s) ) + (e); \ + (c) = S( (c), 10 ); \ + } while( 0 ) + +#define P2( a, b, c, d, e, r, s, rp, sp ) \ + do \ + { \ + P( (a), (b), (c), (d), (e), (r), (s), F, K ); \ + P( a ## p, b ## p, c ## p, d ## p, e ## p, \ + (rp), (sp), Fp, Kp ); \ + } while( 0 ) + +#define F F1 +#define K 0x00000000 +#define Fp F5 +#define Kp 0x50A28BE6 + P2( local.A, local.B, local.C, local.D, local.E, 0, 11, 5, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 1, 14, 14, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 2, 15, 7, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 12, 0, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 4, 5, 9, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 5, 8, 2, 15 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 7, 11, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 7, 9, 4, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 11, 13, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 13, 6, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 14, 15, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 15, 8, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 6, 1, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 7, 10, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 9, 3, 12 ); + P2( local.A, local.B, local.C, local.D, local.E, 15, 8, 12, 6 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F2 +#define K 0x5A827999 +#define Fp F4 +#define Kp 0x5C4DD124 + P2( local.E, local.A, local.B, local.C, local.D, 7, 7, 6, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 4, 6, 11, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 8, 3, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 13, 7, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 11, 0, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 9, 13, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 7, 5, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 15, 10, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 7, 14, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 12, 15, 7 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 15, 8, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 5, 9, 12, 7 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 11, 4, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 7, 9, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 13, 1, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 8, 12, 2, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F3 +#define K 0x6ED9EBA1 +#define Fp F3 +#define Kp 0x6D703EF3 + P2( local.D, local.E, local.A, local.B, local.C, 3, 11, 15, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 10, 13, 5, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 6, 1, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 7, 3, 11 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 14, 7, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 9, 14, 6 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 13, 6, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 15, 9, 14 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 14, 11, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 7, 8, 8, 13 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 13, 12, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 6, 6, 2, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 5, 10, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 12, 0, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 7, 4, 7 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 5, 13, 5 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F4 +#define K 0x8F1BBCDC +#define Fp F2 +#define Kp 0x7A6D76E9 + P2( local.C, local.D, local.E, local.A, local.B, 1, 11, 8, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 12, 6, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 14, 4, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 15, 1, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 14, 3, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 15, 11, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 9, 15, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 8, 0, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 13, 9, 5, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 3, 14, 12, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 5, 2, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 15, 6, 13, 9 ); + P2( local.A, local.B, local.C, local.D, local.E, 14, 8, 9, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 6, 7, 5 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 5, 10, 15 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 12, 14, 8 ); +#undef F +#undef K +#undef Fp +#undef Kp + +#define F F5 +#define K 0xA953FD4E +#define Fp F1 +#define Kp 0x00000000 + P2( local.B, local.C, local.D, local.E, local.A, 4, 9, 12, 8 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 15, 15, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 5, 10, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 9, 11, 4, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 6, 1, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 8, 5, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 13, 8, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 12, 7, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 14, 5, 6, 8 ); + P2( local.C, local.D, local.E, local.A, local.B, 1, 12, 2, 13 ); + P2( local.B, local.C, local.D, local.E, local.A, 3, 13, 13, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 8, 14, 14, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 11, 0, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 8, 3, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 15, 5, 9, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + local.C = ctx->state[1] + local.C + local.Dp; + ctx->state[1] = ctx->state[2] + local.D + local.Ep; + ctx->state[2] = ctx->state[3] + local.E + local.Ap; + ctx->state[3] = ctx->state[4] + local.A + local.Bp; + ctx->state[4] = ctx->state[0] + local.B + local.Cp; + ctx->state[0] = local.C; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#endif /* !MBEDTLS_RIPEMD160_PROCESS_ALT */ + +/* + * RIPEMD-160 process buffer + */ +int mbedtls_ripemd160_update( mbedtls_ripemd160_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_ripemd160_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_ripemd160_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +static const unsigned char ripemd160_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * RIPEMD-160 final digest + */ +int mbedtls_ripemd160_finish( mbedtls_ripemd160_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t last, padn; + uint32_t high, low; + unsigned char msglen[8]; + + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_LE( low, msglen, 0 ); + MBEDTLS_PUT_UINT32_LE( high, msglen, 4 ); + + last = ctx->total[0] & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + ret = mbedtls_ripemd160_update( ctx, ripemd160_padding, padn ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ripemd160_update( ctx, msglen, 8 ); + if( ret != 0 ) + return( ret ); + + MBEDTLS_PUT_UINT32_LE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_LE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#endif /* ! MBEDTLS_RIPEMD160_ALT */ + +/* + * output = RIPEMD-160( input buffer ) + */ +int mbedtls_ripemd160( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ripemd160_context ctx; + + mbedtls_ripemd160_init( &ctx ); + + if( ( ret = mbedtls_ripemd160_starts( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_ripemd160_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_ripemd160_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * Test vectors from the RIPEMD-160 paper and + * http://homes.esat.kuleuven.be/~bosselae/mbedtls_ripemd160.html#HMAC + */ +#define TESTS 8 +static const unsigned char ripemd160_test_str[TESTS][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }, +}; + +static const size_t ripemd160_test_strlen[TESTS] = +{ + 0, 1, 3, 14, 26, 56, 62, 80 +}; + +static const unsigned char ripemd160_test_md[TESTS][20] = +{ + { 0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28, + 0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31 }, + { 0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae, + 0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe }, + { 0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04, + 0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc }, + { 0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8, + 0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36 }, + { 0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb, + 0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc }, + { 0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05, + 0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b }, + { 0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed, + 0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89 }, + { 0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb, + 0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb }, +}; + +/* + * Checkup routine + */ +int mbedtls_ripemd160_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char output[20]; + + memset( output, 0, sizeof output ); + + for( i = 0; i < TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " RIPEMD-160 test #%d: ", i + 1 ); + + ret = mbedtls_ripemd160( ripemd160_test_str[i], + ripemd160_test_strlen[i], output ); + if( ret != 0 ) + goto fail; + + if( memcmp( output, ripemd160_test_md[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RIPEMD160_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/rsa.c b/component/common/network/ssl/mbedtls-3.1.0/library/rsa.c new file mode 100644 index 00000000..36f487f3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/rsa.c @@ -0,0 +1,2511 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#include "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "rsa_alt_helpers.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif + int n_missing, pq_missing, d_missing, is_pub, is_priv; + + RSA_VALIDATE_RET( ctx != NULL ); + + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + ctx->padding = MBEDTLS_RSA_PKCS_V15; + ctx->hash_id = MBEDTLS_MD_NONE; + +#if defined(MBEDTLS_THREADING_C) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +int mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id ) +{ + switch( padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + break; +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + break; +#endif + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } + + if( ( padding == MBEDTLS_RSA_PKCS_V21 ) && + ( hash_id != MBEDTLS_MD_NONE ) ) + { + const mbedtls_md_info_t *md_info; + + md_info = mbedtls_md_info_from_type( hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } + + ctx->padding = padding; + ctx->hash_id = hash_id; + + return( 0 ); +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); + + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); + + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); + + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; + + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret ); + return( ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); + + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( rsa_check_context( ctx, 1 /* private key checks */, + 1 /* blinding on */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 && ret >= -0x007f ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret ) ); + + return( ret ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_rsa_public( ctx, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p++; + } + + *p++ = 0; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + return( mbedtls_rsa_public( ctx, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, + ilen, input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + /* + * Parameters sanity checks + */ + if( ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + if( *olen != 0 ) + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + + if( ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding( buf, ilen, + output, output_max_len, olen ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char *salt = NULL; + size_t slen, min_slen, hlen, offset = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) + { + /* Calculate the largest possible salt length, up to the hash size. + * Normally this is the hash length, which is the maximum salt length + * according to FIPS 185-4 §5.5 (e) and common practice. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; + } + else if ( (saltlen < 0) || (saltlen + hlen + 2 > olen) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + else + { + slen = (size_t) saltlen; + } + + memset( sig, 0, olen ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen - slen - 2; + *p++ = 0x01; + + /* Generate salt of length slen in place in the encoded message */ + salt = p; + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ); +} + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with + * the option to pass in the salt length. + */ +int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ) +{ + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, md_alg, + hashlen, hash, saltlen, sig ); +} + + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, md_alg, + hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash. Must match md_alg if that's not NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_ct_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_platform_zeroize( sig_try, ctx->len ); + mbedtls_platform_zeroize( verif, ctx->len ); + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + if( ret != 0 ) + memset( sig, '!', ctx->len ); + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, + md_alg, hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = mbedtls_rsa_public( ctx, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, + md_alg, hashlen, hash, + mgf1_hash_id, + MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = mbedtls_rsa_public( ctx, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_ct_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); + + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD && !NetBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_MD_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, MBEDTLS_MD_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.c b/component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.c new file mode 100644 index 00000000..dff2d934 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.c @@ -0,0 +1,486 @@ +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "rsa_alt_helpers.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.h b/component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.h new file mode 100644 index 00000000..d6fc8e59 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/rsa_alt_helpers.h @@ -0,0 +1,220 @@ +/** + * \file rsa_alt_helpers.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_alt_helpers.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/sha1.c b/component/common/network/ssl/mbedtls-3.1.0/library/sha1.c new file mode 100644 index 00000000..6fc93712 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/sha1.c @@ -0,0 +1,513 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) + +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE_RET( ctx != NULL ); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); +} + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp, W[16], A, B, C, D, E; + } local; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + + local.W[ 0] = MBEDTLS_GET_UINT32_BE( data, 0 ); + local.W[ 1] = MBEDTLS_GET_UINT32_BE( data, 4 ); + local.W[ 2] = MBEDTLS_GET_UINT32_BE( data, 8 ); + local.W[ 3] = MBEDTLS_GET_UINT32_BE( data, 12 ); + local.W[ 4] = MBEDTLS_GET_UINT32_BE( data, 16 ); + local.W[ 5] = MBEDTLS_GET_UINT32_BE( data, 20 ); + local.W[ 6] = MBEDTLS_GET_UINT32_BE( data, 24 ); + local.W[ 7] = MBEDTLS_GET_UINT32_BE( data, 28 ); + local.W[ 8] = MBEDTLS_GET_UINT32_BE( data, 32 ); + local.W[ 9] = MBEDTLS_GET_UINT32_BE( data, 36 ); + local.W[10] = MBEDTLS_GET_UINT32_BE( data, 40 ); + local.W[11] = MBEDTLS_GET_UINT32_BE( data, 44 ); + local.W[12] = MBEDTLS_GET_UINT32_BE( data, 48 ); + local.W[13] = MBEDTLS_GET_UINT32_BE( data, 52 ); + local.W[14] = MBEDTLS_GET_UINT32_BE( data, 56 ); + local.W[15] = MBEDTLS_GET_UINT32_BE( data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + +#define R(t) \ + ( \ + local.temp = local.W[( (t) - 3 ) & 0x0F] ^ \ + local.W[( (t) - 8 ) & 0x0F] ^ \ + local.W[( (t) - 14 ) & 0x0F] ^ \ + local.W[ (t) & 0x0F], \ + ( local.W[(t) & 0x0F] = S(local.temp,1) ) \ + ) + +#define P(a,b,c,d,e,x) \ + do \ + { \ + (e) += S((a),5) + F((b),(c),(d)) + K + (x); \ + (b) = S((b),30); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define K 0x5A827999 + + P( local.A, local.B, local.C, local.D, local.E, local.W[0] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[1] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[2] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[3] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[4] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[5] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[6] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[7] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[8] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[9] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[10] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[11] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[12] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[13] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[14] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[15] ); + P( local.E, local.A, local.B, local.C, local.D, R(16) ); + P( local.D, local.E, local.A, local.B, local.C, R(17) ); + P( local.C, local.D, local.E, local.A, local.B, R(18) ); + P( local.B, local.C, local.D, local.E, local.A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0x6ED9EBA1 + + P( local.A, local.B, local.C, local.D, local.E, R(20) ); + P( local.E, local.A, local.B, local.C, local.D, R(21) ); + P( local.D, local.E, local.A, local.B, local.C, R(22) ); + P( local.C, local.D, local.E, local.A, local.B, R(23) ); + P( local.B, local.C, local.D, local.E, local.A, R(24) ); + P( local.A, local.B, local.C, local.D, local.E, R(25) ); + P( local.E, local.A, local.B, local.C, local.D, R(26) ); + P( local.D, local.E, local.A, local.B, local.C, R(27) ); + P( local.C, local.D, local.E, local.A, local.B, R(28) ); + P( local.B, local.C, local.D, local.E, local.A, R(29) ); + P( local.A, local.B, local.C, local.D, local.E, R(30) ); + P( local.E, local.A, local.B, local.C, local.D, R(31) ); + P( local.D, local.E, local.A, local.B, local.C, R(32) ); + P( local.C, local.D, local.E, local.A, local.B, R(33) ); + P( local.B, local.C, local.D, local.E, local.A, R(34) ); + P( local.A, local.B, local.C, local.D, local.E, R(35) ); + P( local.E, local.A, local.B, local.C, local.D, R(36) ); + P( local.D, local.E, local.A, local.B, local.C, R(37) ); + P( local.C, local.D, local.E, local.A, local.B, R(38) ); + P( local.B, local.C, local.D, local.E, local.A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define K 0x8F1BBCDC + + P( local.A, local.B, local.C, local.D, local.E, R(40) ); + P( local.E, local.A, local.B, local.C, local.D, R(41) ); + P( local.D, local.E, local.A, local.B, local.C, R(42) ); + P( local.C, local.D, local.E, local.A, local.B, R(43) ); + P( local.B, local.C, local.D, local.E, local.A, R(44) ); + P( local.A, local.B, local.C, local.D, local.E, R(45) ); + P( local.E, local.A, local.B, local.C, local.D, R(46) ); + P( local.D, local.E, local.A, local.B, local.C, R(47) ); + P( local.C, local.D, local.E, local.A, local.B, R(48) ); + P( local.B, local.C, local.D, local.E, local.A, R(49) ); + P( local.A, local.B, local.C, local.D, local.E, R(50) ); + P( local.E, local.A, local.B, local.C, local.D, R(51) ); + P( local.D, local.E, local.A, local.B, local.C, R(52) ); + P( local.C, local.D, local.E, local.A, local.B, R(53) ); + P( local.B, local.C, local.D, local.E, local.A, R(54) ); + P( local.A, local.B, local.C, local.D, local.E, R(55) ); + P( local.E, local.A, local.B, local.C, local.D, R(56) ); + P( local.D, local.E, local.A, local.B, local.C, R(57) ); + P( local.C, local.D, local.E, local.A, local.B, R(58) ); + P( local.B, local.C, local.D, local.E, local.A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0xCA62C1D6 + + P( local.A, local.B, local.C, local.D, local.E, R(60) ); + P( local.E, local.A, local.B, local.C, local.D, R(61) ); + P( local.D, local.E, local.A, local.B, local.C, R(62) ); + P( local.C, local.D, local.E, local.A, local.B, R(63) ); + P( local.B, local.C, local.D, local.E, local.A, R(64) ); + P( local.A, local.B, local.C, local.D, local.E, R(65) ); + P( local.E, local.A, local.B, local.C, local.D, R(66) ); + P( local.D, local.E, local.A, local.B, local.C, R(67) ); + P( local.C, local.D, local.E, local.A, local.B, R(68) ); + P( local.B, local.C, local.D, local.E, local.A, R(69) ); + P( local.A, local.B, local.C, local.D, local.E, R(70) ); + P( local.E, local.A, local.B, local.C, local.D, R(71) ); + P( local.D, local.E, local.A, local.B, local.C, R(72) ); + P( local.C, local.D, local.E, local.A, local.B, R(73) ); + P( local.B, local.C, local.D, local.E, local.A, R(74) ); + P( local.A, local.B, local.C, local.D, local.E, R(75) ); + P( local.E, local.A, local.B, local.C, local.D, R(76) ); + P( local.D, local.E, local.A, local.B, local.C, R(77) ); + P( local.C, local.D, local.E, local.A, local.B, R(78) ); + P( local.B, local.C, local.D, local.E, local.A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_BE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha1_context ctx; + + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test( int verbose ) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init( &ctx ); + + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); + + if( ( ret = mbedtls_sha1_starts( &ctx ) ) != 0 ) + goto fail; + + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha1_finish( &ctx, sha1sum ) ) != 0 ) + goto fail; + + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/sha256.c b/component/common/network/ssl/mbedtls-3.1.0/library/sha256.c new file mode 100644 index 00000000..c3573f85 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/sha256.c @@ -0,0 +1,557 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA256_ALT) + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) +{ + SHA256_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + SHA256_VALIDATE_RET( ctx != NULL ); + +#if defined(MBEDTLS_SHA224_C) + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); +#else + SHA256_VALIDATE_RET( is224 == 0 ); +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { +#if defined(MBEDTLS_SHA224_C) + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; +#endif + } + + ctx->is224 = is224; + + return( 0 ); +} + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) +#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define R(t) \ + ( \ + local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ + S0(local.W[(t) - 15]) + local.W[(t) - 16] \ + ) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + } local; + + unsigned int i; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); + + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i ); + else + R( i ); + + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); + + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], R(i+0), K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], R(i+1), K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], R(i+2), K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], R(i+3), K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], R(i+4), K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], R(i+5), K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], R(i+6), K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_BE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[5], output, 20 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[6], output, 24 ); + +#if defined(MBEDTLS_SHA224_C) + if( ctx->is224 == 0 ) +#endif + MBEDTLS_PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha256_context ctx; + +#if defined(MBEDTLS_SHA224_C) + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); +#else + SHA256_VALIDATE_RET( is224 == 0 ); +#endif + + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha256_init( &ctx ); + + if( ( ret = mbedtls_sha256_starts( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha256_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = +{ + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha256_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); + + if( ( ret = mbedtls_sha256_starts( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + + } + else + { + ret = mbedtls_sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish( &ctx, sha256sum ) ) != 0 ) + goto fail; + + + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/sha512.c b/component/common/network/ssl/mbedtls-3.1.0/library/sha512.c new file mode 100644 index 00000000..2b4cc547 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/sha512.c @@ -0,0 +1,618 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA512_ALT) + +#if defined(MBEDTLS_SHA512_SMALLER) +static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i ) +{ + MBEDTLS_PUT_UINT64_BE(n, b, i); +} +#else +#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE +#endif /* MBEDTLS_SHA512_SMALLER */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + SHA512_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); + + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +{ + SHA512_VALIDATE_RET( ctx != NULL ); +#if defined(MBEDTLS_SHA384_C) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { +#if !defined(MBEDTLS_SHA384_C) + return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ); +#else + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); +#endif /* MBEDTLS_SHA384_C */ + } + +#if defined(MBEDTLS_SHA384_C) + ctx->is384 = is384; +#endif + + return( 0 ); +} + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + struct + { + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + } local; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); + +#define SHR(x,n) ((x) >> (n)) +#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA512_SMALLER) + for( i = 0; i < 80; i++ ) + { + if( i < 16 ) + { + local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 ); + } + else + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } + + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); + + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA512_SMALLER */ + for( i = 0; i < 16; i++ ) + { + local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } + + i = 0; + do + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++; + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++; + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++; + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++; + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++; + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++; + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++; + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++; + } + while( i < 80 ); +#endif /* MBEDTLS_SHA512_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + unsigned int left; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned used; + uint64_t high, low; + + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + sha512_put_uint64_be( high, ctx->buffer, 112 ); + sha512_put_uint64_be( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + sha512_put_uint64_be( ctx->state[0], output, 0 ); + sha512_put_uint64_be( ctx->state[1], output, 8 ); + sha512_put_uint64_be( ctx->state[2], output, 16 ); + sha512_put_uint64_be( ctx->state[3], output, 24 ); + sha512_put_uint64_be( ctx->state[4], output, 32 ); + sha512_put_uint64_be( ctx->state[5], output, 40 ); + +#if defined(MBEDTLS_SHA384_C) + if( ctx->is384 == 0 ) +#endif + { + sha512_put_uint64_be( ctx->state[6], output, 48 ); + sha512_put_uint64_be( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha512_context ctx; + +#if defined(MBEDTLS_SHA384_C) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[][64] = +{ +#if defined(MBEDTLS_SHA384_C) + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, +#endif /* MBEDTLS_SHA384_C */ + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) ) + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ ) + { + j = i % 3; +#if defined(MBEDTLS_SHA384_C) + k = i < 3; +#else + k = 0; +#endif + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#undef ARRAY_LENGTH + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cache.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cache.c new file mode 100644 index 00000000..fe4f30cf --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cache.c @@ -0,0 +1,357 @@ +/* + * SSL session cache implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cache.h" +#include "ssl_misc.h" + +#include + +void mbedtls_ssl_cache_init( mbedtls_ssl_cache_context *cache ) +{ + memset( cache, 0, sizeof( mbedtls_ssl_cache_context ) ); + + cache->timeout = MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT; + cache->max_entries = MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &cache->mutex ); +#endif +} + +static int ssl_cache_find_entry( mbedtls_ssl_cache_context *cache, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_cache_entry **dst ) +{ + int ret = 1; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ); +#endif + mbedtls_ssl_cache_entry *cur; + + for( cur = cache->chain; cur != NULL; cur = cur->next ) + { +#if defined(MBEDTLS_HAVE_TIME) + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + continue; +#endif + + if( session_id_len != cur->session_id_len || + memcmp( session_id, cur->session_id, + cur->session_id_len ) != 0 ) + { + continue; + } + + break; + } + + if( cur != NULL ) + { + *dst = cur; + ret = 0; + } + + return( ret ); +} + + +int mbedtls_ssl_cache_get( void *data, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_session *session ) +{ + int ret = 1; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *entry; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &cache->mutex ) != 0 ) + return( 1 ); +#endif + + ret = ssl_cache_find_entry( cache, session_id, session_id_len, &entry ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_ssl_session_load( session, + entry->session, + entry->session_len ); + if( ret != 0 ) + goto exit; + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + return( ret ); +} + +static int ssl_cache_pick_writing_slot( mbedtls_ssl_cache_context *cache, + unsigned char const *session_id, + size_t session_id_len, + mbedtls_ssl_cache_entry **dst ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t = mbedtls_time( NULL ), oldest = 0; +#endif /* MBEDTLS_HAVE_TIME */ + + mbedtls_ssl_cache_entry *old = NULL; + int count = 0; + mbedtls_ssl_cache_entry *cur, *last; + + /* Check 1: Is there already an entry with the given session ID? + * + * If yes, overwrite it. + * + * If not, `count` will hold the size of the session cache + * at the end of this loop, and `last` will point to the last + * entry, both of which will be used later. */ + + last = NULL; + for( cur = cache->chain; cur != NULL; cur = cur->next ) + { + count++; + if( session_id_len == cur->session_id_len && + memcmp( session_id, cur->session_id, cur->session_id_len ) == 0 ) + { + goto found; + } + last = cur; + } + + /* Check 2: Is there an outdated entry in the cache? + * + * If so, overwrite it. + * + * If not, remember the oldest entry in `old` for later. + */ + +#if defined(MBEDTLS_HAVE_TIME) + for( cur = cache->chain; cur != NULL; cur = cur->next ) + { + if( cache->timeout != 0 && + (int) ( t - cur->timestamp ) > cache->timeout ) + { + goto found; + } + + if( oldest == 0 || cur->timestamp < oldest ) + { + oldest = cur->timestamp; + old = cur; + } + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* Check 3: Is there free space in the cache? */ + + if( count < cache->max_entries ) + { + /* Create new entry */ + cur = mbedtls_calloc( 1, sizeof(mbedtls_ssl_cache_entry) ); + if( cur == NULL ) + return( 1 ); + + /* Append to the end of the linked list. */ + if( last == NULL ) + cache->chain = cur; + else + last->next = cur; + + goto found; + } + + /* Last resort: The cache is full and doesn't contain any outdated + * elements. In this case, we evict the oldest one, judged by timestamp + * (if present) or cache-order. */ + +#if defined(MBEDTLS_HAVE_TIME) + if( old == NULL ) + { + /* This should only happen on an ill-configured cache + * with max_entries == 0. */ + return( 1 ); + } +#else /* MBEDTLS_HAVE_TIME */ + /* Reuse first entry in chain, but move to last place. */ + if( cache->chain == NULL ) + return( 1 ); + + old = cache->chain; + cache->chain = old->next; + old->next = NULL; + last->next = old; +#endif /* MBEDTLS_HAVE_TIME */ + + /* Now `old` points to the oldest entry to be overwritten. */ + cur = old; + +found: + +#if defined(MBEDTLS_HAVE_TIME) + cur->timestamp = t; +#endif + + /* If we're reusing an entry, free it first. */ + if( cur->session != NULL ) + { + mbedtls_free( cur->session ); + cur->session = NULL; + cur->session_len = 0; + memset( cur->session_id, 0, sizeof( cur->session_id ) ); + cur->session_id_len = 0; + } + + *dst = cur; + return( 0 ); +} + +int mbedtls_ssl_cache_set( void *data, + unsigned char const *session_id, + size_t session_id_len, + const mbedtls_ssl_session *session ) +{ + int ret = 1; + mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data; + mbedtls_ssl_cache_entry *cur; + + size_t session_serialized_len; + unsigned char *session_serialized = NULL; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &cache->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = ssl_cache_pick_writing_slot( cache, + session_id, session_id_len, + &cur ); + if( ret != 0 ) + goto exit; + + /* Check how much space we need to serialize the session + * and allocate a sufficiently large buffer. */ + ret = mbedtls_ssl_session_save( session, NULL, 0, &session_serialized_len ); + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + { + ret = 1; + goto exit; + } + + session_serialized = mbedtls_calloc( 1, session_serialized_len ); + if( session_serialized == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + /* Now serialize the session into the allocated buffer. */ + ret = mbedtls_ssl_session_save( session, + session_serialized, + session_serialized_len, + &session_serialized_len ); + if( ret != 0 ) + goto exit; + + if( session_id_len > sizeof( cur->session_id ) ) + { + ret = 1; + goto exit; + } + cur->session_id_len = session_id_len; + memcpy( cur->session_id, session_id, session_id_len ); + + cur->session = session_serialized; + cur->session_len = session_serialized_len; + session_serialized = NULL; + + ret = 0; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &cache->mutex ) != 0 ) + ret = 1; +#endif + + if( session_serialized != NULL ) + mbedtls_platform_zeroize( session_serialized, session_serialized_len ); + + return( ret ); +} + +#if defined(MBEDTLS_HAVE_TIME) +void mbedtls_ssl_cache_set_timeout( mbedtls_ssl_cache_context *cache, int timeout ) +{ + if( timeout < 0 ) timeout = 0; + + cache->timeout = timeout; +} +#endif /* MBEDTLS_HAVE_TIME */ + +void mbedtls_ssl_cache_set_max_entries( mbedtls_ssl_cache_context *cache, int max ) +{ + if( max < 0 ) max = 0; + + cache->max_entries = max; +} + +void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache ) +{ + mbedtls_ssl_cache_entry *cur, *prv; + + cur = cache->chain; + + while( cur != NULL ) + { + prv = cur; + cur = cur->next; + + mbedtls_free( prv->session ); + mbedtls_free( prv ); + } + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &cache->mutex ); +#endif + cache->chain = NULL; +} + +#endif /* MBEDTLS_SSL_CACHE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_ciphersuites.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_ciphersuites.c new file mode 100644 index 00000000..62588dc2 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_ciphersuites.c @@ -0,0 +1,2146 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" +#include "ssl_misc.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except weak and null which come last): + * 1. By key exchange: + * Forward-secure non-PSK > forward-secure PSK > ECJPAKE > other non-PSK > other PSK + * 2. By key length and cipher: + * ChaCha > AES-256 > Camellia-256 > ARIA-256 > AES-128 > Camellia-128 > ARIA-128 + * 3. By cipher mode when relevant GCM > CCM > CBC > CCM_8 + * 4. By hash function used when relevant + * 5. By key exchange/auth again: EC > non-EC + */ +static const int ciphersuite_preference[] = +{ +#if defined(MBEDTLS_SSL_CIPHERSUITES) + MBEDTLS_SSL_CIPHERSUITES, +#else +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* TLS 1.3 ciphersuites */ + MBEDTLS_TLS1_3_AES_128_GCM_SHA256, + MBEDTLS_TLS1_3_AES_256_GCM_SHA384, + MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS1_3_AES_128_CCM_SHA256, + MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* Chacha-Poly ephemeral suites */ + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + + /* All AES-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, + + /* All ARIA-256 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, + + /* All ARIA-128 ephemeral suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The PSK ephemeral suites */ + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The ECJPAKE suite */ + MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, + + /* All AES-256 suites */ + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, + + /* All CAMELLIA-256 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, + + /* All ARIA-256 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + + /* All AES-128 suites */ + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, + + /* All CAMELLIA-128 suites */ + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, + + /* All ARIA-128 suites */ + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + + /* The RSA PSK suites */ + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + + /* The PSK suites */ + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + + /* NULL suites */ + MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, + + MBEDTLS_TLS_RSA_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_WITH_NULL_MD5, + MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, + MBEDTLS_TLS_PSK_WITH_NULL_SHA384, + MBEDTLS_TLS_PSK_WITH_NULL_SHA256, + MBEDTLS_TLS_PSK_WITH_NULL_SHA, + +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + 0 +}; + +static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] = +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + 0 }, + { MBEDTLS_TLS1_3_AES_128_CCM_8_SHA256, "TLS1-3-AES-128-CCM-8-SHA256", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_SHA256_C && MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) && defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256, + "TLS1-3-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */ + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_4, + 0 }, +#endif /* MBEDTLS_CHACHAPOLY_C && MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_CHACHAPOLY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-ECDSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + { MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-RSA-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + { MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-ECDHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + { MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-DHE-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + { MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, + "TLS-RSA-PSK-WITH-CHACHA20-POLY1305-SHA256", + MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256, + MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#endif /* MBEDTLS_CHACHAPOLY_C && + MBEDTLS_SHA256_C && + MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, "TLS-ECDHE-ECDSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA384_C) && \ + defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS-DHE-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, "TLS-DHE-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, "TLS-DHE-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, "TLS-DHE-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA384_C) && \ + defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C && MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS-RSA-WITH-AES-256-CBC-SHA256", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, "TLS-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, "TLS-RSA-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM, "TLS-RSA-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, "TLS-RSA-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-256-CBC-SHA", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_SHA1_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, "TLS-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, "TLS-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM, "TLS-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, "TLS-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, "TLS-DHE-PSK-WITH-AES-256-CCM-8", + MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, "TLS-DHE-PSK-WITH-AES-128-CCM", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, "TLS-DHE-PSK-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256", + MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384", + MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA", + MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, + + { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA", + MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256", + MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384", + MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_GCM_C */ +#endif /* MBEDTLS_CAMELLIA_C */ + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8", + MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_SHORT_TAG }, +#endif /* MBEDTLS_CCM_C */ +#endif /* MBEDTLS_AES_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) +#if defined(MBEDTLS_MD5_C) + { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +#if defined(MBEDTLS_SHA1_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif + +#if defined(MBEDTLS_SHA384_C) + { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384", + MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_CIPHERSUITE_WEAK }, +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + +#if defined(MBEDTLS_ARIA_C) + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384,MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384, + "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256, + "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384", + MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA384_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384, + "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384", + MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256", + MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif +#if (defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_SHA256_C)) + { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256, + "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256", + MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3, + 0 }, +#endif + +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#endif /* MBEDTLS_ARIA_C */ + + + { 0, "", + MBEDTLS_CIPHER_NONE, MBEDTLS_MD_NONE, MBEDTLS_KEY_EXCHANGE_NONE, + 0, 0, 0, 0, 0 } +}; + +#if defined(MBEDTLS_SSL_CIPHERSUITES) +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + return( ciphersuite_preference ); +} +#else +#define MAX_CIPHERSUITES sizeof( ciphersuite_definitions ) / \ + sizeof( ciphersuite_definitions[0] ) +static int supported_ciphersuites[MAX_CIPHERSUITES]; +static int supported_init = 0; + +static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) +{ + (void)cs_info; + + return( 0 ); +} + +const int *mbedtls_ssl_list_ciphersuites( void ) +{ + /* + * On initial call filter out all ciphersuites not supported by current + * build based on presence in the ciphersuite_definitions. + */ + if( supported_init == 0 ) + { + const int *p; + int *q; + + for( p = ciphersuite_preference, q = supported_ciphersuites; + *p != 0 && q < supported_ciphersuites + MAX_CIPHERSUITES - 1; + p++ ) + { + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + !ciphersuite_is_removed( cs_info ) ) + { + *(q++) = *p; + } + } + *q = 0; + + supported_init = 1; + } + + return( supported_ciphersuites ); +} +#endif /* MBEDTLS_SSL_CIPHERSUITES */ + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string( + const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + if( NULL == ciphersuite_name ) + return( NULL ); + + while( cur->id != 0 ) + { + if( 0 == strcmp( cur->name, ciphersuite_name ) ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id( int ciphersuite ) +{ + const mbedtls_ssl_ciphersuite_t *cur = ciphersuite_definitions; + + while( cur->id != 0 ) + { + if( cur->id == ciphersuite ) + return( cur ); + + cur++; + } + + return( NULL ); +} + +const char *mbedtls_ssl_get_ciphersuite_name( const int ciphersuite_id ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( cur == NULL ) + return( "unknown" ); + + return( cur->name ); +} + +int mbedtls_ssl_get_ciphersuite_id( const char *ciphersuite_name ) +{ + const mbedtls_ssl_ciphersuite_t *cur; + + cur = mbedtls_ssl_ciphersuite_from_string( ciphersuite_name ); + + if( cur == NULL ) + return( 0 ); + + return( cur->id ); +} + +#if defined(MBEDTLS_PK_C) +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + return( MBEDTLS_PK_ECKEY ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + return( MBEDTLS_PK_RSA ); + + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + return( MBEDTLS_PK_ECDSA ); + + default: + return( MBEDTLS_PK_NONE ); + } +} + +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +int mbedtls_ssl_ciphersuite_uses_ec( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_ciphersuite_uses_psk( const mbedtls_ssl_ciphersuite_t *info ) +{ + switch( info->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cli.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cli.c new file mode 100644 index 00000000..32d49691 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cli.c @@ -0,0 +1,4306 @@ +/* + * TLS client-side functions + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "ssl_misc.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/constant_time.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 ); + + /* + * Sect. 3, RFC 6066 (TLS Extensions Definitions) + * + * In order to provide any of the server names, clients MAY include an + * extension of type "server_name" in the (extended) client hello. The + * "extension_data" field of this extension SHALL contain + * "ServerNameList" where: + * + * struct { + * NameType name_type; + * select (name_type) { + * case host_name: HostName; + * } name; + * } ServerName; + * + * enum { + * host_name(0), (255) + * } NameType; + * + * opaque HostName<1..2^16-1>; + * + * struct { + * ServerName server_name_list<1..2^16-1> + * } ServerNameList; + * + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SERVERNAME, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( hostname_len + 5, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( hostname_len + 3, p, 0 ); + p += 2; + + *p++ = MBEDTLS_BYTE_0( MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ); + + MBEDTLS_PUT_UINT16_BE( hostname_len, p, 0 ); + p += 2; + + memcpy( p, ssl->hostname, hostname_len ); + + *olen = hostname_len + 9; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + /* We're always including an TLS_EMPTY_RENEGOTIATION_INFO_SCSV in the + * initial ClientHello, in which case also adding the renegotiation + * info extension is NOT RECOMMENDED as per RFC 5746 Section 3.4. */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding renegotiation extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len ); + + /* + * Secure renegotiation + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len + 1 ); + *p++ = MBEDTLS_BYTE_0( ssl->verify_data_len ); + + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + + *olen = 5 + ssl->verify_data_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* + * Only if we handle at least one key exchange that needs signatures. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t sig_alg_len = 0; + const int *md; + +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) + unsigned char *sig_alg_list = buf + 6; +#endif + + *olen = 0; + + if( ssl->conf->max_minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding signature_algorithms extension" ) ); + + if( ssl->conf->sig_hashes == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_len += 2; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_len += 2; +#endif + if( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "length in bytes of sig-hash-alg extension too big" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty signature algorithms list, this is a configuration error. */ + if( sig_alg_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 ); + + /* + * Prepare signature_algorithms extension (TLS 1.2) + */ + sig_alg_len = 0; + + for( md = ssl->conf->sig_hashes; *md != MBEDTLS_MD_NONE; md++ ) + { +#if defined(MBEDTLS_ECDSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif +#if defined(MBEDTLS_RSA_C) + sig_alg_list[sig_alg_len++] = mbedtls_ssl_hash_from_md_alg( *md ); + sig_alg_list[sig_alg_len++] = MBEDTLS_SSL_SIG_RSA; +#endif + } + + /* + * enum { + * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5), + * sha512(6), (255) + * } HashAlgorithm; + * + * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) } + * SignatureAlgorithm; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2..2^16-2>; + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( sig_alg_len + 2, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( sig_alg_len, p, 0 ); + p += 2; + + *olen = 6 + sig_alg_len; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; + const uint16_t *group_list = mbedtls_ssl_get_groups( ssl ); + *olen = 0; + + /* Check there is room for header */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_elliptic_curves extension" ) ); + + if( group_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( ; *group_list != 0; group_list++ ) + { + info = mbedtls_ecp_curve_info_from_tls_id( *group_list ); + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "invalid curve in ssl configuration" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + + /* Check there is room for another curve */ + MBEDTLS_SSL_CHK_BUF_PTR( elliptic_curve_list, end, elliptic_curve_len + 2 ); + + MBEDTLS_PUT_UINT16_BE( *group_list, elliptic_curve_list, elliptic_curve_len ); + elliptic_curve_len += 2; + + if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "malformed supported_elliptic_curves extension in config" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty elliptic curve list, this is a configuration error. */ + if( elliptic_curve_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( elliptic_curve_len + 2, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( elliptic_curve_len, p, 0 ); + p += 2; + + *olen = 6 + elliptic_curve_len; + + return( 0 ); +} + +static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + (void) ssl; /* ssl used for debugging only */ + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_point_formats extension" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly extension if we can't use EC J-PAKE anyway */ + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding ecjpake_kkpp extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 ); + p += 2; + + /* + * We may need to send ClientHello multiple times for Hello verification. + * We don't want to compute fresh values every time (both for performance + * and consistency reasons), so cache the extension content. + */ + if( ssl->handshake->ecjpake_cache == NULL || + ssl->handshake->ecjpake_cache_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "generating new ecjpake parameters" ) ); + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , + "mbedtls_ecjpake_write_round_one", ret ); + return( ret ); + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->ecjpake_cache, p + 2, kkpp_len ); + ssl->handshake->ecjpake_cache_len = kkpp_len; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "re-using cached ecjpake parameters" ) ); + + kkpp_len = ssl->handshake->ecjpake_cache_len; + MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len ); + + memcpy( p + 2, ssl->handshake->ecjpake_cache, kkpp_len ); + } + + MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 ); + p += 2; + + *olen = kkpp_len + 4; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static int ssl_write_cid_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t ext_len; + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + *olen = 0; + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + return( 0 ); + } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding CID extension" ) ); + + /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX + * which is at most 255, so the increment cannot overflow. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, (unsigned)( ssl->own_cid_len + 5 ) ); + + /* Add extension ID + size */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 ); + p += 2; + ext_len = (size_t) ssl->own_cid_len + 1; + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2; + + *p++ = (uint8_t) ssl->own_cid_len; + memcpy( p, ssl->own_cid, ssl->own_cid_len ); + + *olen = ssl->own_cid_len + 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding max_fragment_length extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->conf->mfl_code; + + *olen = 5; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding encrypt_then_mac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding extended_master_secret extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding session ticket extension" ) ); + + /* The addition is safe here since the ticket length is 16 bit. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( tlen, p, 0 ); + p += 2; + + *olen = 4; + + if( ssl->session_negotiate->ticket == NULL || tlen == 0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "sending session ticket of length %" MBEDTLS_PRINTF_SIZET, tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += strlen( *cur ) + 1; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, p, 0 ); + p += 2; + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Skip writing extension and list length for now */ + p += 4; + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + *p = (unsigned char)strlen( *cur ); + memcpy( p + 1, *cur, *p ); + p += 1 + *p; + } + + *olen = p - buf; + + /* List length = olen - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */ + MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 ); + + /* Extension length = olen - 2 (ext_type) - 2 (ext_len) */ + MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static int ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t protection_profiles_index = 0, ext_len = 0; + uint16_t mki_len = 0, profile_value = 0; + + *olen = 0; + + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + { + return( 0 ); + } + + /* RFC 5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + /* Extension length = 2 bytes for profiles length, + * ssl->conf->dtls_srtp_profile_list_len * 2 (each profile is 2 bytes length ), + * 1 byte for srtp_mki vector length and the mki_len value + */ + ext_len = 2 + 2 * ( ssl->conf->dtls_srtp_profile_list_len ) + 1 + mki_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding use_srtp extension" ) ); + + /* Check there is room in the buffer for the extension + 4 bytes + * - the extension tag (2 bytes) + * - the extension length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, ext_len + 4 ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_USE_SRTP, p, 0 ); + p += 2; + + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2; + + /* protection profile length: 2*(ssl->conf->dtls_srtp_profile_list_len) */ + /* micro-optimization: + * the list size is limited to MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + * which is lower than 127, so the upper byte of the length is always 0 + * For the documentation, the more generic code is left in comments + * *p++ = (unsigned char)( ( ( 2 * ssl->conf->dtls_srtp_profile_list_len ) + * >> 8 ) & 0xFF ); + */ + *p++ = 0; + *p++ = MBEDTLS_BYTE_0( 2 * ssl->conf->dtls_srtp_profile_list_len ); + + for( protection_profiles_index=0; + protection_profiles_index < ssl->conf->dtls_srtp_profile_list_len; + protection_profiles_index++ ) + { + profile_value = mbedtls_ssl_check_srtp_profile_value + ( ssl->conf->dtls_srtp_profile_list[protection_profiles_index] ); + if( profile_value != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_write_use_srtp_ext, add profile: %04x", + profile_value ) ); + MBEDTLS_PUT_UINT16_BE( profile_value, p, 0 ); + p += 2; + } + else + { + /* + * Note: we shall never arrive here as protection profiles + * is checked by mbedtls_ssl_conf_dtls_srtp_protection_profiles function + */ + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, " + "illegal DTLS-SRTP protection profile %d", + ssl->conf->dtls_srtp_profile_list[protection_profiles_index] + ) ); + return( MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ); + } + } + + *p++ = mki_len & 0xFF; + + if( mki_len != 0 ) + { + memcpy( p, ssl->dtls_srtp_info.mki_value, mki_len ); + /* + * Increment p to point to the current position. + */ + p += mki_len; + MBEDTLS_SSL_DEBUG_BUF( 3, "sending mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } + + /* + * total extension length: extension type (2 bytes) + * + extension length (2 bytes) + * + protection profile length (2 bytes) + * + 2 * number of protection profiles + * + srtp_mki vector length(1 byte) + * + mki value + */ + *olen = p - buf; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Generate random bytes for ClientHello + */ +static int ssl_generate_random( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = ssl->handshake->randbytes; +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + + /* + * When responding to a verify request, MUST reuse random (RFC 6347 4.2.1) + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie != NULL ) + { + return( 0 ); + } +#endif + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + MBEDTLS_PUT_UINT32_BE( t, p, 0 ); + p += 4; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, current time: %" MBEDTLS_PRINTF_LONGLONG, + (long long) t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( + const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + /* Don't suggest PSK-based ciphersuite if no PSK is available. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_static_psk( ssl->conf ) == 0 ) + { + return( 1 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + + return( 0 ); +} + +static int ssl_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, olen, ext_len = 0; + + unsigned char *buf; + unsigned char *p, *q; + const unsigned char *end; + + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + } + + if( ssl->conf->max_major_ver == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "configured max major version is invalid, consider using mbedtls_ssl_config_defaults()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + buf = ssl->out_msg; + end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN; + + /* + * Check if there's enough space for the first part of the ClientHello + * consisting of the 38 bytes described below, the session identifier (at + * most 32 bytes) and its length (1 byte). + * + * Use static upper bounds instead of the actual values + * to allow the compiler to optimize this away. + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 ); + + /* + * The 38 first bytes of the ClientHello: + * 0 . 0 handshake type (written later) + * 1 . 3 handshake length (written later) + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + * + * The current UNIX time (4 bytes) and following 28 random bytes are written + * by ssl_generate_random() into ssl->handshake->randbytes buffer and then + * copied from there into the output buffer. + */ + + p = buf + 4; + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, max version: [%d:%d]", + buf[4], buf[5] ) ); + + if( ( ret = ssl_generate_random( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_generate_random", ret ); + return( ret ); + } + + memcpy( p, ssl->handshake->randbytes, 32 ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", p, 32 ); + p += 32; + + /* + * 38 . 38 session id length + * 39 . 39+n session id + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + n = ssl->session_negotiate->id_len; + + if( n < 16 || n > 32 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->handshake->resume == 0 ) + { + n = 0; + } + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + /* + * RFC 5077 section 3.4: "When presenting a ticket, the client MAY + * generate and include a Session ID in the TLS ClientHello." + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ssl->session_negotiate->ticket != NULL && + ssl->session_negotiate->ticket_len != 0 ) + { + ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ); + + if( ret != 0 ) + return( ret ); + + ssl->session_negotiate->id_len = n = 32; + } + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + + /* + * The first check of the output buffer size above ( + * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) + * has checked that there is enough space in the output buffer for the + * session identifier length byte and the session identifier (n <= 32). + */ + *p++ = (unsigned char) n; + + for( i = 0; i < n; i++ ) + *p++ = ssl->session_negotiate->id[i]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 39, n ); + + /* + * With 'n' being the length of the session identifier + * + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no verify cookie to send" ) ); + *p++ = 0; + } + else + { + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + + *p++ = ssl->handshake->verify_cookie_len; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, + ssl->handshake->verify_cookie_len ); + memcpy( p, ssl->handshake->verify_cookie, + ssl->handshake->verify_cookie_len ); + p += ssl->handshake->verify_cookie_len; + } + } +#endif + + /* + * Ciphersuite list + */ + ciphersuites = ssl->conf->ciphersuite_list; + + /* Skip writing ciphersuite length for now */ + n = 0; + q = p; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %#04x (%s)", + (unsigned int)ciphersuites[i], ciphersuite_info->name ) ); + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + + n++; + MBEDTLS_PUT_UINT16_BE( ciphersuites[i], p, 0 ); + p += 2; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %" MBEDTLS_PRINTF_SIZET " ciphersuites (excluding SCSVs)", n ) ); + + /* + * Add TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding EMPTY_RENEGOTIATION_INFO_SCSV" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO, p, 0 ); + p += 2; + n++; + } + + *q++ = (unsigned char)( n >> 7 ); + *q++ = (unsigned char)( n << 1 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress len.: %d", 1 ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, compress alg.: %d", + MBEDTLS_SSL_COMPRESS_NULL ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* First write extensions, then the total length */ + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ( ret = mbedtls_ssl_write_hostname_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_hostname_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* Note that TLS_EMPTY_RENEGOTIATION_INFO_SCSV is always added + * even if MBEDTLS_SSL_RENEGOTIATION is not defined. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( uses_ec ) + { + if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret ); + return( ret ); + } + ext_len += olen; + + if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret ); + return( ret ); + } + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ( ret = ssl_write_cid_ext( ssl, p + 2 + ext_len, end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_cid_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + if( ( ret = ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_use_srtp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + + /* olen unused if all extensions are disabled */ + ((void) olen); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET, + ext_len ) ); + + if( ext_len > 0 ) + { + /* No need to check for space here, because the extension + * writing functions already took care of that. */ + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2 + ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_HELLO; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + + return( 0 ); +} + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len * 2 || + buf[0] != ssl->verify_data_len * 2 || + mbedtls_ct_memcmp( buf + 1, + ssl->own_verify_data, ssl->verify_data_len ) != 0 || + mbedtls_ct_memcmp( buf + 1 + ssl->verify_data_len, + ssl->peer_verify_data, ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x00 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + /* + * server should use the extension only if we did, + * and if so the server's value should match ours (and len is always 1) + */ + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE || + len != 1 || + buf[0] != ssl->conf->mfl_code ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching max fragment length extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t peer_cid_len; + + if( /* CID extension only makes sense in DTLS */ + ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + /* The server must only send the CID extension if we have offered it. */ + ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension unexpected" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + if( len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + peer_cid_len = *buf++; + len--; + + if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + if( len != peer_cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CID extension invalid" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; + ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; + memcpy( ssl->handshake->peer_cid, buf, peer_cid_len ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Server CID", buf, peer_cid_len ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching encrypt-then-MAC extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + ((void) buf); + + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching extended master secret extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + ((void) buf); + + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED || + len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-matching session ticket extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + ((void) buf); + + ssl->handshake->new_session_ticket = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_point_formats_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_set_point_format( &ssl->handshake->ecjpake_ctx, + p[0] ); +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no point format in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl->handshake->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + /* If we got here, we no longer need our cached extension */ + mbedtls_free( ssl->handshake->ecjpake_cache ); + ssl->handshake->ecjpake_cache = NULL; + ssl->handshake->ecjpake_cache_len = 0; + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, name_len; + const char **p; + + /* If we didn't send it, the server shouldn't send it */ + if( ssl->conf->alpn_list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching ALPN extension" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + * + * the "ProtocolNameList" MUST contain exactly one "ProtocolName" + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + name_len = buf[2]; + if( name_len != list_len - 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Check that the server chosen protocol was in our list and save it */ + for( p = ssl->conf->alpn_list; *p != NULL; p++ ) + { + if( name_len == strlen( *p ) && + memcmp( buf + 3, *p, name_len ) == 0 ) + { + ssl->alpn_chosen = *p; + return( 0 ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ALPN extension: no matching protocol" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + mbedtls_ssl_srtp_profile server_protection = MBEDTLS_TLS_SRTP_UNSET; + size_t i, mki_len = 0; + uint16_t server_protection_profile_value = 0; + + /* If use_srtp is not configured, just ignore the extension */ + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + return( 0 ); + + /* RFC 5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + * + */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + + /* + * Length is 5 + optional mki_value : one protection profile length (2 bytes) + * + protection profile (2 bytes) + * + mki_len(1 byte) + * and optional srtp_mki + */ + if( ( len < 5 ) || ( len != ( buf[4] + 5u ) ) ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + /* + * get the server protection profile + */ + + /* + * protection profile length must be 0x0002 as we must have only + * one protection profile in server Hello + */ + if( ( buf[0] != 0 ) || ( buf[1] != 2 ) ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + server_protection_profile_value = ( buf[2] << 8 ) | buf[3]; + server_protection = mbedtls_ssl_check_srtp_profile_value( + server_protection_profile_value ); + if( server_protection != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + server_protection ) ) ); + } + + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; + + /* + * Check we have the server profile in our list + */ + for( i=0; i < ssl->conf->dtls_srtp_profile_list_len; i++) + { + if( server_protection == ssl->conf->dtls_srtp_profile_list[i] ) + { + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + server_protection ) ) ); + break; + } + } + + /* If no match was found : server problem, it shall never answer with incompatible profile */ + if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + /* If server does not use mki in its reply, make sure the client won't keep + * one as negotiated */ + if( len == 5 ) + { + ssl->dtls_srtp_info.mki_len = 0; + } + + /* + * RFC5764: + * If the client detects a nonzero-length MKI in the server's response + * that is different than the one the client offered, then the client + * MUST abort the handshake and SHOULD send an invalid_parameter alert. + */ + if( len > 5 && ( buf[4] != mki_len || + ( memcmp( ssl->dtls_srtp_info.mki_value, &buf[5], mki_len ) ) ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } +#if defined (MBEDTLS_DEBUG_C) + if( len > 5 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "received mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } +#endif + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Parse HelloVerifyRequest. Only called after verifying the HS type. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_parse_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + const unsigned char *p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + int major_ver, minor_ver; + unsigned char cookie_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse hello verify request" ) ); + + /* Check that there is enough room for: + * - 2 bytes of version + * - 1 byte of cookie_len + */ + if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "incoming HelloVerifyRequest message is too short" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, p ); + p += 2; + + /* + * Since the RFC is not clear on this point, accept DTLS 1.0 (TLS 1.1) + * even is lower than our min version. + */ + if( major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + minor_ver < MBEDTLS_SSL_MINOR_VERSION_2 || + major_ver > ssl->conf->max_major_ver || + minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server version" ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + } + + cookie_len = *p++; + if( ( ssl->in_msg + ssl->in_msglen ) - p < cookie_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "cookie length does not match incoming message size" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + mbedtls_free( ssl->handshake->verify_cookie ); + + ssl->handshake->verify_cookie = mbedtls_calloc( 1, cookie_len ); + if( ssl->handshake->verify_cookie == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc failed (%d bytes)", cookie_len ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ssl->handshake->verify_cookie, p, cookie_len ); + ssl->handshake->verify_cookie_len = cookie_len; + + /* Start over at ClientHello */ + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + mbedtls_ssl_reset_checksum( ssl ); + + mbedtls_ssl_recv_flight_completed( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret, i; + size_t n; + size_t ext_len; + unsigned char *buf, *ext; + unsigned char comp; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const mbedtls_ssl_ciphersuite_t *suite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + buf = ssl->in_msg; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_records_seen++; + + if( ssl->conf->renego_max_records >= 0 && + ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation requested, but not honored by server" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "non-handshake message during renegotiation" ) ); + + ssl->keep_current_message = 1; + return( MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( buf[0] == MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received hello verify request" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + return( ssl_parse_hello_verify_request( ssl ) ); + } + else + { + /* We made it through the verification process */ + mbedtls_free( ssl->handshake->verify_cookie ); + ssl->handshake->verify_cookie = NULL; + ssl->handshake->verify_cookie_len = 0; + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ssl->in_hslen < 38 + mbedtls_ssl_hs_hdr_len( ssl ) || + buf[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * 0 . 1 server_version + * 2 . 33 random (maybe including 4 bytes of Unix time) + * 34 . 34 session_id length = n + * 35 . 34+n session_id + * 35+n . 36+n cipher_suite + * 37+n . 37+n compression_method + * + * 38+n . 39+n extensions length (optional) + * 40+n . .. extensions + */ + buf += mbedtls_ssl_hs_hdr_len( ssl ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", buf + 0, 2 ); + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf + 0 ); + ssl->session_negotiate->minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver || + ssl->major_ver > ssl->conf->max_major_ver || + ssl->minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server version out of bounds - min: [%d:%d], server: [%d:%d], max: [%d:%d]", + ssl->conf->min_major_ver, + ssl->conf->min_minor_ver, + ssl->major_ver, ssl->minor_ver, + ssl->conf->max_major_ver, + ssl->conf->max_minor_ver ) ); + + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + + return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %lu", + ( (unsigned long) buf[2] << 24 ) | + ( (unsigned long) buf[3] << 16 ) | + ( (unsigned long) buf[4] << 8 ) | + ( (unsigned long) buf[5] ) ) ); + + memcpy( ssl->handshake->randbytes + 32, buf + 2, 32 ); + + n = buf[34]; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 2, 32 ); + + if( n > 32 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + if( ssl->in_hslen > mbedtls_ssl_hs_hdr_len( ssl ) + 39 + n ) + { + ext_len = ( ( buf[38 + n] << 8 ) + | ( buf[39 + n] ) ); + + if( ( ext_len > 0 && ext_len < 4 ) || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 40 + n + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + } + else if( ssl->in_hslen == mbedtls_ssl_hs_hdr_len( ssl ) + 38 + n ) + { + ext_len = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* ciphersuite (used later) */ + i = ( buf[35 + n] << 8 ) | buf[36 + n]; + + /* + * Read and check compression + */ + comp = buf[37 + n]; + + if( comp != MBEDTLS_SSL_COMPRESS_NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server hello, bad compression: %d", comp ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + /* + * Initialize update checksum functions + */ + ssl->handshake->ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( i ); + if( ssl->handshake->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "ciphersuite info for %04x not found", (unsigned int)i ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + mbedtls_ssl_optimize_checksum( ssl, ssl->handshake->ciphersuite_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 35, n ); + + /* + * Check if the session can be resumed + */ + if( ssl->handshake->resume == 0 || n == 0 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE || +#endif + ssl->session_negotiate->ciphersuite != i || + ssl->session_negotiate->compression != comp || + ssl->session_negotiate->id_len != n || + memcmp( ssl->session_negotiate->id, buf + 35, n ) != 0 ) + { + ssl->state++; + ssl->handshake->resume = 0; +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + ssl->session_negotiate->ciphersuite = i; + ssl->session_negotiate->compression = comp; + ssl->session_negotiate->id_len = n; + memcpy( ssl->session_negotiate->id, buf + 35, n ); + } + else + { + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %04x", (unsigned) i ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: %d", + buf[37 + n] ) ); + + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ + i = 0; + while( 1 ) + { + if( ssl->conf->ciphersuite_list[i] == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + if( ssl->conf->ciphersuite_list[i++] == + ssl->session_negotiate->ciphersuite ) + { + break; + } + } + + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, + ssl->minor_ver ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ecrs_enabled = 1; + } +#endif + + if( comp != MBEDTLS_SSL_COMPRESS_NULL + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + ssl->session_negotiate->compression = comp; + + ext = buf + 40 + n; + + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, ext_len ) ); + + while( ext_len ) + { + unsigned int ext_id = ( ( ext[0] << 8 ) + | ( ext[1] ) ); + unsigned int ext_size = ( ( ext[2] << 8 ) + | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + mbedtls_ssl_send_alert_message( + ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + switch( ext_id ) + { + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + if( ( ret = ssl_parse_renegotiation_info( ssl, ext + 4, + ext_size ) ) != 0 ) + return( ret ); + + break; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found max_fragment_length extension" ) ); + + if( ( ret = ssl_parse_max_fragment_length_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + case MBEDTLS_TLS_EXT_CID: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) ); + + if( ( ret = ssl_parse_cid_ext( ssl, + ext + 4, + ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt_then_mac extension" ) ); + + if( ( ret = ssl_parse_encrypt_then_mac_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found extended_master_secret extension" ) ); + + if( ( ret = ssl_parse_extended_ms_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session_ticket extension" ) ); + + if( ( ret = ssl_parse_session_ticket_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_point_formats extension" ) ); + + if( ( ret = ssl_parse_supported_point_formats_ext( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake_kkpp extension" ) ); + + if( ( ret = ssl_parse_ecjpake_kkpp( ssl, + ext + 4, ext_size ) ) != 0 ) + { + return( ret ); + } + + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + if( ( ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + case MBEDTLS_TLS_EXT_USE_SRTP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) ); + + if( ( ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ) ) != 0 ) + return( ret ); + + break; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "unknown extension found: %u (ignoring)", ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + + if( ext_len > 0 && ext_len < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_server_dh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t dhm_actual_bitlen; + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_read_params( &ssl->handshake->dhm_ctx, + p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 2, ( "mbedtls_dhm_read_params" ), ret ); + return( ret ); + } + + dhm_actual_bitlen = mbedtls_dhm_get_bitlen( &ssl->handshake->dhm_ctx ); + if( dhm_actual_bitlen < ssl->conf->dhm_min_bitlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHM prime too short: %" MBEDTLS_PRINTF_SIZET " < %u", + dhm_actual_bitlen, + ssl->conf->dhm_min_bitlen ) ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_check_server_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif + + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) +#else + if( ssl->handshake->ecdh_ctx.grp.nbits < 163 || + ssl->handshake->ecdh_ctx.grp.nbits > 521 ) +#endif + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) +static int ssl_parse_server_ecdh_params_psa( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + uint16_t tls_id; + size_t ecdh_bits = 0; + uint8_t ecpoint_len; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* + * Parse ECC group + */ + + if( end - *p < 4 ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + /* First byte is curve_type; only named_curve is handled */ + if( *(*p)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + + /* Next two bytes are the namedcurve value */ + tls_id = *(*p)++; + tls_id <<= 8; + tls_id |= *(*p)++; + + /* Convert EC group to PSA key type. */ + if( ( handshake->ecdh_psa_type = + mbedtls_psa_parse_tls_ecc_group( tls_id, &ecdh_bits ) ) == 0 ) + { + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + if( ecdh_bits > 0xffff ) + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + handshake->ecdh_bits = (uint16_t) ecdh_bits; + + /* + * Put peer's ECDH public key in the format understood by PSA. + */ + + ecpoint_len = *(*p)++; + if( (size_t)( end - *p ) < ecpoint_len ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + if( mbedtls_psa_tls_ecpoint_to_psa_ec( + *p, ecpoint_len, + handshake->ecdh_psa_peerkey, + sizeof( handshake->ecdh_psa_peerkey ), + &handshake->ecdh_psa_peerkey_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + *p += ecpoint_len; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) +static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + if( ( ret = mbedtls_ecdh_read_params( &ssl->handshake->ecdh_ctx, + (const unsigned char **) p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (ECDHE curve)" ) ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + uint16_t len; + ((void) ssl); + + /* + * PSK parameters: + * + * opaque psk_identity_hint<0..2^16-1>; + */ + if( end - (*p) < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + len = (*p)[0] << 8 | (*p)[1]; + *p += 2; + + if( end - (*p) < len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message (psk_identity_hint length)" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * Note: we currently ignore the PKS identity hint, as we only allow one + * PSK to be provisionned on the client. This could be changed later if + * someone needs that feature. + */ + *p += len; + ret = 0; + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) +/* + * Generate a pre-master secret and encrypt it with the server's RSA key + */ +static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl, + size_t offset, size_t *olen, + size_t pms_offset ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len_bytes = 2; + unsigned char *p = ssl->handshake->premaster + pms_offset; + mbedtls_pk_context * peer_pk; + + if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate (part of) the pre-master as + * struct { + * ProtocolVersion client_version; + * opaque random[46]; + * } PreMasterSecret; + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p + 2, 46 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + + ssl->handshake->pmslen = 48; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * Now write it out, encrypted + */ + if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_pk_encrypt( peer_pk, + p, ssl->handshake->pmslen, + ssl->out_msg + offset + len_bytes, olen, + MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_rsa_pkcs1_encrypt", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( len_bytes == 2 ) + { + MBEDTLS_PUT_UINT16_BE( *olen, ssl->out_msg, offset ); + *olen += 2; + } +#endif + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +static int ssl_parse_signature_algorithm( mbedtls_ssl_context *ssl, + unsigned char **p, + unsigned char *end, + mbedtls_md_type_t *md_alg, + mbedtls_pk_type_t *pk_alg ) +{ + ((void) ssl); + *md_alg = MBEDTLS_MD_NONE; + *pk_alg = MBEDTLS_PK_NONE; + + /* Only in TLS 1.2 */ + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 0 ); + } + + if( (*p) + 2 > end ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + /* + * Get hash algorithm + */ + if( ( *md_alg = mbedtls_ssl_md_alg_from_hash( (*p)[0] ) ) + == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Server used unsupported HashAlgorithm %d", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + /* + * Get signature algorithm + */ + if( ( *pk_alg = mbedtls_ssl_pk_alg_from_sig( (*p)[1] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used unsupported SignatureAlgorithm %d", (*p)[1] ) ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + /* + * Check if the hash is acceptable + */ + if( mbedtls_ssl_check_sig_hash( ssl, *md_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server used HashAlgorithm %d that was not offered", *(p)[0] ) ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used SignatureAlgorithm %d", + (*p)[1] ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Server used HashAlgorithm %d", + (*p)[0] ) ); + *p += 2; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ecp_keypair *peer_key; + mbedtls_pk_context * peer_pk; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + peer_key = mbedtls_pk_ec( *peer_pk ); + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key, + MBEDTLS_ECDH_THEIRS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + if( ssl_check_server_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server certificate (ECDH curve)" ) ); + return( MBEDTLS_ERR_SSL_BAD_CERTIFICATE ); + } + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it, + * so that more RAM is available for upcoming expensive + * operations like ECDHE. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + unsigned char *p = NULL, *end = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_ecdh_params_from_cert", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) ); + ssl->state++; + return( 0 ); + } + ((void) p); + ((void) end); +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) + { + goto start_processing; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * ServerKeyExchange may be skipped with PSK and RSA-PSK when the server + * doesn't use a psk_identity_hint + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* Current message is probably either + * CertificateRequest or ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "server key exchange message must not be skipped" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ssl_parse_server_psk_hint( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + } /* FALLTROUGH */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + ; /* nothing more to do */ + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ssl_parse_server_dh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params_psa( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + if( ssl_parse_server_ecdh_params( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t sig_len, hashlen; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char hash[PSA_HASH_MAX_SIZE]; +#else + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#endif + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + size_t params_len = p - params; + void *rs_ctx = NULL; + + mbedtls_pk_context * peer_pk; + + /* + * Handle the digitally-signed structure + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( ssl_parse_signature_algorithm( ssl, &p, end, + &md_alg, &pk_alg ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + if( pk_alg != + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Read signature + */ + + if( p > end - 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + sig_len = ( p[0] << 8 ) | p[1]; + p += 2; + + if( p != end - sig_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "signature", p, sig_len ); + + /* + * Compute the hash that has been signed + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + params, params_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * Verify signature + */ + if( !mbedtls_pk_can_do( peer_pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( peer_pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* We don't need the peer's public key anymore. Free it, + * so that more RAM is available for upcoming expensive + * operations like ECDHE. */ + mbedtls_pk_free( peer_pk ); +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +exit: + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server key exchange" ) ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_parse_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t n = 0; + size_t cert_type_len = 0, dn_len = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate request" ) ); + + if( ! mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate request" ) ); + ssl->state++; + return( 0 ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->state++; + ssl->client_auth = ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "got %s certificate request", + ssl->client_auth ? "a" : "no" ) ); + + if( ssl->client_auth == 0 ) + { + /* Current message is probably the ServerHelloDone */ + ssl->keep_current_message = 1; + goto exit; + } + + /* + * struct { + * ClientCertificateType certificate_types<1..2^8-1>; + * SignatureAndHashAlgorithm + * supported_signature_algorithms<2^16-1>; -- TLS 1.2 only + * DistinguishedName certificate_authorities<0..2^16-1>; + * } CertificateRequest; + * + * Since we only support a single certificate on clients, let's just + * ignore all the information that's supposed to help us pick a + * certificate. + * + * We could check that our certificate matches the request, and bail out + * if it doesn't, but it's simpler to just send the certificate anyway, + * and give the server the opportunity to decide if it should terminate + * the connection when it doesn't like our certificate. + * + * Same goes for the hash in TLS 1.2's signature_algorithms: at this + * point we only have one hash available (see comments in + * write_certificate_verify), so let's just use what we have. + * + * However, we still minimally parse the message to check it is at least + * superficially sane. + */ + buf = ssl->in_msg; + + /* certificate_types */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* supported_signature_algorithms */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + size_t sig_alg_len = + ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); +#if defined(MBEDTLS_DEBUG_C) + unsigned char* sig_alg; + size_t i; +#endif + + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + + 3 + n + sig_alg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + for( i = 0; i < sig_alg_len; i += 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "Supported Signature Algorithm found: %d,%d", + sig_alg[i], sig_alg[i + 1] ) ); + } +#endif + + n += 2 + sig_alg_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* certificate_authorities */ + dn_len = ( ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 1 + n] << 8 ) + | ( buf[mbedtls_ssl_hs_hdr_len( ssl ) + 2 + n] ) ); + + n += dn_len; + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate request message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +static int ssl_parse_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse server hello done" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) || + ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO_DONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server hello done message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse server hello done" ) ); + + return( 0 ); +} + +static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + size_t header_len; + size_t content_len; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + /* + * DHM key exchange -- send G^X mod P + */ + content_len = mbedtls_dhm_get_len( &ssl->handshake->dhm_ctx ); + + MBEDTLS_PUT_UINT16_BE( content_len, ssl->out_msg, 4 ); + header_len = 6; + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_dhm_get_len( &ssl->handshake->dhm_ctx ), + &ssl->out_msg[header_len], content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) ) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA ) + { + psa_status_t status; + psa_key_attributes_t key_attributes; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + unsigned char own_pubkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t own_pubkey_len; + unsigned char *own_pubkey_ecpoint; + size_t own_pubkey_ecpoint_len; + + header_len = 4; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based ECDH computation." ) ); + + /* + * Generate EC private key for ECDHE exchange. + */ + + /* The master secret is obtained from the shared ECDH secret by + * applying the TLS 1.2 PRF with a specific salt and label. While + * the PSA Crypto API encourages combining key agreement schemes + * such as ECDH with fixed KDFs such as TLS 1.2 PRF, it does not + * yet support the provisioning of salt + label to the KDF. + * For the time being, we therefore need to split the computation + * of the ECDH secret and the application of the TLS 1.2 PRF. */ + key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &key_attributes, PSA_ALG_ECDH ); + psa_set_key_type( &key_attributes, handshake->ecdh_psa_type ); + psa_set_key_bits( &key_attributes, handshake->ecdh_bits ); + + /* Generate ECDH private key. */ + status = psa_generate_key( &key_attributes, + &handshake->ecdh_psa_privkey ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + /* Export the public part of the ECDH private key from PSA + * and convert it to ECPoint format used in ClientKeyExchange. */ + status = psa_export_public_key( handshake->ecdh_psa_privkey, + own_pubkey, sizeof( own_pubkey ), + &own_pubkey_len ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + if( mbedtls_psa_tls_psa_ec_to_ecpoint( own_pubkey, + own_pubkey_len, + &own_pubkey_ecpoint, + &own_pubkey_ecpoint_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + /* Copy ECPoint structure to outgoing message buffer. */ + ssl->out_msg[header_len] = (unsigned char) own_pubkey_ecpoint_len; + memcpy( ssl->out_msg + header_len + 1, + own_pubkey_ecpoint, own_pubkey_ecpoint_len ); + content_len = own_pubkey_ecpoint_len + 1; + + /* The ECDH secret is the premaster secret used for key derivation. */ + + /* Compute ECDH shared secret. */ + status = psa_raw_key_agreement( PSA_ALG_ECDH, + handshake->ecdh_psa_privkey, + handshake->ecdh_psa_peerkey, + handshake->ecdh_psa_peerkey_len, + ssl->handshake->premaster, + sizeof( ssl->handshake->premaster ), + &ssl->handshake->pmslen ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + status = psa_destroy_key( handshake->ecdh_psa_privkey ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + ( MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED ) */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + /* + * ECDH key exchange -- send client public value + */ + header_len = 4; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) + goto ecdh_calc_secret; + + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } +#endif + + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &content_len, + &ssl->out_msg[header_len], 1000, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = content_len; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; + } + +ecdh_calc_secret: + if( ssl->handshake->ecrs_enabled ) + content_len = ssl->handshake->ecrs_n; +#endif + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( ciphersuite_info ) ) + { + /* + * opaque psk_identity<0..2^16-1>; + */ + if( ssl_conf_has_static_psk( ssl->conf ) == 0 ) + { + /* We don't offer PSK suites if we don't have a PSK, + * and we check that the server's choice is among the + * ciphersuites we offered, so this should never happen. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + header_len = 4; + content_len = ssl->conf->psk_identity_len; + + if( header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len ); + ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len ); + + memcpy( ssl->out_msg + header_len, + ssl->conf->psk_identity, + ssl->conf->psk_identity_len ); + header_len += ssl->conf->psk_identity_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + content_len = 0; + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( ( ret = ssl_write_encrypted_pms( ssl, header_len, + &content_len, 2 ) ) != 0 ) + return( ret ); + } + else +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * ClientDiffieHellmanPublic public (DHM send G^X mod P) + */ + content_len = mbedtls_dhm_get_len( &ssl->handshake->dhm_ctx ); + + if( header_len + 2 + content_len > + MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "psk identity or DHM size too long or SSL buffer too short" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[header_len++] = MBEDTLS_BYTE_1( content_len ); + ssl->out_msg[header_len++] = MBEDTLS_BYTE_0( content_len ); + + ret = mbedtls_dhm_make_public( &ssl->handshake->dhm_ctx, + (int) mbedtls_dhm_get_len( &ssl->handshake->dhm_ctx ), + &ssl->out_msg[header_len], content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_public", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* + * ClientECDiffieHellmanPublic public; + */ + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, + &content_len, + &ssl->out_msg[header_len], + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "skip PMS generation for opaque PSK" ) ); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + header_len = 4; + if( ( ret = ssl_write_encrypted_pms( ssl, header_len, + &content_len, 0 ) ) != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + header_len = 4; + + ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx, + ssl->out_msg + header_len, + MBEDTLS_SSL_OUT_CONTENT_LEN - header_len, + &content_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ + { + ((void) ciphersuite_info); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_msglen = header_len + content_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + size_t n = 0, offset = 0; + unsigned char hash[48]; + unsigned char *hash_start = hash; + mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; + size_t hashlen; + void *rs_ctx = NULL; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len - ( ssl->out_msg - ssl->out_buf ); +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - ( ssl->out_msg - ssl->out_buf ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) + { + goto sign; + } +#endif + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->client_auth == 0 || mbedtls_ssl_own_cert( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for certificate" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Make a signature of the handshake digests + */ +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + + ssl->handshake->calc_verify( ssl, hash, &hashlen ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * digitally-signed struct { + * opaque handshake_messages[handshake_messages_length]; + * }; + * + * Taking shortcut here. We assume that the server always allows the + * PRF Hash function and has sent it in the allowed signature + * algorithms list received in the Certificate Request message. + * + * Until we encounter a server that does not, we will take this + * shortcut. + * + * Reason: Otherwise we should have running hashes for SHA512 and + * SHA224 in order to satisfy 'weird' needs from the server + * side. + */ + if( ssl->handshake->ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + { + md_alg = MBEDTLS_MD_SHA384; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA384; + } + else + { + md_alg = MBEDTLS_MD_SHA256; + ssl->out_msg[4] = MBEDTLS_SSL_HASH_SHA256; + } + ssl->out_msg[5] = mbedtls_ssl_sig_from_pk( mbedtls_ssl_own_key( ssl ) ); + + /* Info from md_alg will be used instead */ + hashlen = 0; + offset = 2; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx.pk; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, + ssl->out_msg + 6 + offset, + out_buf_len - 6 - offset, + &n, + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif + return( ret ); + } + + MBEDTLS_PUT_UINT16_BE( n, ssl->out_msg, offset + 4 ); + + ssl->out_msglen = 6 + n + offset; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate verify" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t lifetime; + size_t ticket_len; + unsigned char *ticket; + const unsigned char *msg; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse new session ticket" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( + ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 0 . 3 ticket_lifetime_hint + * 4 . 5 ticket_len (n) + * 6 . 5+n ticket content + */ + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_NEW_SESSION_TICKET || + ssl->in_hslen < 6 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + + lifetime = ( ((uint32_t) msg[0]) << 24 ) | ( msg[1] << 16 ) | + ( msg[2] << 8 ) | ( msg[3] ); + + ticket_len = ( msg[4] << 8 ) | ( msg[5] ); + + if( ticket_len + 6 + mbedtls_ssl_hs_hdr_len( ssl ) != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad new session ticket message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, ticket_len ) ); + + /* We're not waiting for a NewSessionTicket message any more */ + ssl->handshake->new_session_ticket = 0; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + /* + * Zero-length ticket means the server changed his mind and doesn't want + * to send a ticket after all, so just forget it + */ + if( ticket_len == 0 ) + return( 0 ); + + if( ssl->session != NULL && ssl->session->ticket != NULL ) + { + mbedtls_platform_zeroize( ssl->session->ticket, + ssl->session->ticket_len ); + mbedtls_free( ssl->session->ticket ); + ssl->session->ticket = NULL; + ssl->session->ticket_len = 0; + } + + mbedtls_platform_zeroize( ssl->session_negotiate->ticket, + ssl->session_negotiate->ticket_len ); + mbedtls_free( ssl->session_negotiate->ticket ); + ssl->session_negotiate->ticket = NULL; + ssl->session_negotiate->ticket_len = 0; + + if( ( ticket = mbedtls_calloc( 1, ticket_len ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ticket alloc failed" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + memcpy( ticket, msg + 6, ticket_len ); + + ssl->session_negotiate->ticket = ticket; + ssl->session_negotiate->ticket_len = ticket_len; + ssl->session_negotiate->ticket_lifetime = lifetime; + + /* + * RFC 5077 section 3.4: + * "If the client receives a session ticket from the server, then it + * discards any Session ID that was sent in the ServerHello." + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket in use, discarding session id" ) ); + ssl->session_negotiate->id_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- client side -- single step + */ +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client state: %d", ssl->state ) ); + + /* Change state now, so that it is right in mbedtls_ssl_read_record(), used + * by DTLS for dropping out-of-sequence ChangeCipherSpec records */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC && + ssl->handshake->new_session_ticket != 0 ) + { + ssl->state = MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET; + } +#endif + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * ==> ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_write_client_hello( ssl ); + break; + + /* + * <== ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_parse_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_parse_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_parse_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_parse_server_hello_done( ssl ); + break; + + /* + * ==> ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_write_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_write_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + /* + * <== ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET: + ret = ssl_parse_new_session_ticket( ssl ); + break; +#endif + + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cookie.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cookie.c new file mode 100644 index 00000000..358169e8 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_cookie.c @@ -0,0 +1,256 @@ +/* + * DTLS cookie callbacks implementation + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "ssl_misc.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/constant_time.h" + +#include + +/* + * If DTLS is in use, then at least one of SHA-1, SHA-256, SHA-512 is + * available. Try SHA-256 first, 512 wastes resources + */ +#if defined(MBEDTLS_SHA224_C) +#define COOKIE_MD MBEDTLS_MD_SHA224 +#define COOKIE_MD_OUTLEN 32 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA384_C) +#define COOKIE_MD MBEDTLS_MD_SHA384 +#define COOKIE_MD_OUTLEN 48 +#define COOKIE_HMAC_LEN 28 +#elif defined(MBEDTLS_SHA1_C) +#define COOKIE_MD MBEDTLS_MD_SHA1 +#define COOKIE_MD_OUTLEN 20 +#define COOKIE_HMAC_LEN 20 +#else +#error "DTLS hello verify needs SHA-1 or SHA-2" +#endif + +/* + * Cookies are formed of a 4-bytes timestamp (or serial number) and + * an HMAC of timestemp and client ID. + */ +#define COOKIE_LEN ( 4 + COOKIE_HMAC_LEN ) + +void mbedtls_ssl_cookie_init( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_init( &ctx->hmac_ctx ); +#if !defined(MBEDTLS_HAVE_TIME) + ctx->serial = 0; +#endif + ctx->timeout = MBEDTLS_SSL_COOKIE_TIMEOUT; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +void mbedtls_ssl_cookie_set_timeout( mbedtls_ssl_cookie_ctx *ctx, unsigned long delay ) +{ + ctx->timeout = delay; +} + +void mbedtls_ssl_cookie_free( mbedtls_ssl_cookie_ctx *ctx ) +{ + mbedtls_md_free( &ctx->hmac_ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_cookie_ctx ) ); +} + +int mbedtls_ssl_cookie_setup( mbedtls_ssl_cookie_ctx *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char key[COOKIE_MD_OUTLEN]; + + if( ( ret = f_rng( p_rng, key, sizeof( key ) ) ) != 0 ) + return( ret ); + + ret = mbedtls_md_setup( &ctx->hmac_ctx, mbedtls_md_info_from_type( COOKIE_MD ), 1 ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_md_hmac_starts( &ctx->hmac_ctx, key, sizeof( key ) ); + if( ret != 0 ) + return( ret ); + + mbedtls_platform_zeroize( key, sizeof( key ) ); + + return( 0 ); +} + +/* + * Generate the HMAC part of a cookie + */ +static int ssl_cookie_hmac( mbedtls_md_context_t *hmac_ctx, + const unsigned char time[4], + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char hmac_out[COOKIE_MD_OUTLEN]; + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); + + if( mbedtls_md_hmac_reset( hmac_ctx ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, time, 4 ) != 0 || + mbedtls_md_hmac_update( hmac_ctx, cli_id, cli_id_len ) != 0 || + mbedtls_md_hmac_finish( hmac_ctx, hmac_out ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( *p, hmac_out, COOKIE_HMAC_LEN ); + *p += COOKIE_HMAC_LEN; + + return( 0 ); +} + +/* + * Generate cookie for DTLS ClientHello verification + */ +int mbedtls_ssl_cookie_write( void *p_ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long t; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); + +#if defined(MBEDTLS_HAVE_TIME) + t = (unsigned long) mbedtls_time( NULL ); +#else + t = ctx->serial++; +#endif + + MBEDTLS_PUT_UINT32_BE(t, *p, 0); + *p += 4; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) ); +#endif + + ret = ssl_cookie_hmac( &ctx->hmac_ctx, *p - 4, + p, end, cli_id, cli_id_len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, + MBEDTLS_ERR_THREADING_MUTEX_ERROR ) ); +#endif + + return( ret ); +} + +/* + * Check a cookie + */ +int mbedtls_ssl_cookie_check( void *p_ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + unsigned char ref_hmac[COOKIE_HMAC_LEN]; + int ret = 0; + unsigned char *p = ref_hmac; + mbedtls_ssl_cookie_ctx *ctx = (mbedtls_ssl_cookie_ctx *) p_ctx; + unsigned long cur_time, cookie_time; + + if( ctx == NULL || cli_id == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( cookie_len != COOKIE_LEN ) + return( -1 ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, ret ) ); +#endif + + if( ssl_cookie_hmac( &ctx->hmac_ctx, cookie, + &p, p + sizeof( ref_hmac ), + cli_id, cli_id_len ) != 0 ) + ret = -1; + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_SSL_INTERNAL_ERROR, + MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + } +#endif + + if( ret != 0 ) + goto exit; + + if( mbedtls_ct_memcmp( cookie + 4, ref_hmac, sizeof( ref_hmac ) ) != 0 ) + { + ret = -1; + goto exit; + } + +#if defined(MBEDTLS_HAVE_TIME) + cur_time = (unsigned long) mbedtls_time( NULL ); +#else + cur_time = ctx->serial; +#endif + + cookie_time = ( (unsigned long) cookie[0] << 24 ) | + ( (unsigned long) cookie[1] << 16 ) | + ( (unsigned long) cookie[2] << 8 ) | + ( (unsigned long) cookie[3] ); + + if( ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout ) + { + ret = -1; + goto exit; + } + +exit: + mbedtls_platform_zeroize( ref_hmac, sizeof( ref_hmac ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_COOKIE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_misc.h b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_misc.h new file mode 100644 index 00000000..d54e336f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_misc.h @@ -0,0 +1,1751 @@ +/** + * \file ssl_misc.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright The Mbed TLS Contributors + * 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. + */ +#ifndef MBEDTLS_SSL_MISC_H +#define MBEDTLS_SSL_MISC_H + +#include "mbedtls/build_info.h" + +#include "mbedtls/ssl.h" +#include "mbedtls/cipher.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#include "mbedtls/ecjpake.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* Legacy minor version numbers as defined by: + * - RFC 2246: ProtocolVersion version = { 3, 1 }; // TLS v1.0 + * - RFC 4346: ProtocolVersion version = { 3, 2 }; // TLS v1.1 + * + * We no longer support these versions, but some code still references those + * constants as part of negotiating with the peer, so keep them available + * internally. + */ +#define MBEDTLS_SSL_MINOR_VERSION_1 1 +#define MBEDTLS_SSL_MINOR_VERSION_2 2 + +//not support TLS record-level compression +#define MBEDTLS_SSL_COMPRESSION_ADD 0 + +/* Determine minimum supported version */ +#define MBEDTLS_SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#define MBEDTLS_SSL_MIN_VALID_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#define MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +/* Determine maximum supported version */ +#define MBEDTLS_SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAJOR_VERSION_3 + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MINOR_VERSION_3 +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +/* Shorthand for restartable ECC */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED +#endif + +#define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 +#define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ +#define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ +#define MBEDTLS_SSL_RENEGOTIATION_PENDING 3 /* Requested (server only) */ + +/* + * Mask of TLS 1.3 handshake extensions used in extensions_present + * of mbedtls_ssl_handshake_params. + */ +#define MBEDTLS_SSL_EXT_NONE 0 + +#define MBEDTLS_SSL_EXT_SERVERNAME ( 1 << 0 ) +#define MBEDTLS_SSL_EXT_MAX_FRAGMENT_LENGTH ( 1 << 1 ) +#define MBEDTLS_SSL_EXT_STATUS_REQUEST ( 1 << 2 ) +#define MBEDTLS_SSL_EXT_SUPPORTED_GROUPS ( 1 << 3 ) +#define MBEDTLS_SSL_EXT_SIG_ALG ( 1 << 4 ) +#define MBEDTLS_SSL_EXT_USE_SRTP ( 1 << 5 ) +#define MBEDTLS_SSL_EXT_HEARTBEAT ( 1 << 6 ) +#define MBEDTLS_SSL_EXT_ALPN ( 1 << 7 ) +#define MBEDTLS_SSL_EXT_SCT ( 1 << 8 ) +#define MBEDTLS_SSL_EXT_CLI_CERT_TYPE ( 1 << 9 ) +#define MBEDTLS_SSL_EXT_SERV_CERT_TYPE ( 1 << 10 ) +#define MBEDTLS_SSL_EXT_PADDING ( 1 << 11 ) +#define MBEDTLS_SSL_EXT_PRE_SHARED_KEY ( 1 << 12 ) +#define MBEDTLS_SSL_EXT_EARLY_DATA ( 1 << 13 ) +#define MBEDTLS_SSL_EXT_SUPPORTED_VERSIONS ( 1 << 14 ) +#define MBEDTLS_SSL_EXT_COOKIE ( 1 << 15 ) +#define MBEDTLS_SSL_EXT_PSK_KEY_EXCHANGE_MODES ( 1 << 16 ) +#define MBEDTLS_SSL_EXT_CERT_AUTH ( 1 << 17 ) +#define MBEDTLS_SSL_EXT_OID_FILTERS ( 1 << 18 ) +#define MBEDTLS_SSL_EXT_POST_HANDSHAKE_AUTH ( 1 << 19 ) +#define MBEDTLS_SSL_EXT_SIG_ALG_CERT ( 1 << 20 ) +#define MBEDTLS_SSL_EXT_KEY_SHARE ( 1 << 21 ) + +/* + * Helper macros for function call with return check. + */ +/* + * Exit when return non-zero value + */ +#define MBEDTLS_SSL_PROC_CHK( f ) \ + do { \ + ret = ( f ); \ + if( ret != 0 ) \ + { \ + goto cleanup; \ + } \ + } while( 0 ) +/* + * Exit when return negative value + */ +#define MBEDTLS_SSL_PROC_CHK_NEG( f ) \ + do { \ + ret = ( f ); \ + if( ret < 0 ) \ + { \ + goto cleanup; \ + } \ + } while( 0 ) + +/* + * DTLS retransmission states, see RFC 6347 4.2.4 + * + * The SENDING state is merged in PREPARING for initial sends, + * but is distinct for resends. + * + * Note: initial state is wrong for server, but is not used anyway. + */ +#define MBEDTLS_SSL_RETRANS_PREPARING 0 +#define MBEDTLS_SSL_RETRANS_SENDING 1 +#define MBEDTLS_SSL_RETRANS_WAITING 2 +#define MBEDTLS_SSL_RETRANS_FINISHED 3 + +/* + * Allow extra bytes for record, authentication and encryption overhead: + * counter (8) + header (5) + IV(16) + MAC (16-48) + padding (0-256). + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_CAMELLIA_C) || \ + defined(MBEDTLS_ARIA_C) || \ + defined(MBEDTLS_DES_C) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether a ciphersuite using a + * stream cipher can be used. */ +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#define MBEDTLS_SSL_SOME_SUITES_USE_STREAM +#endif + +/* This macro determines whether the CBC construct used in TLS 1.2 is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) || \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) +#define MBEDTLS_SSL_SOME_SUITES_USE_MAC +#endif + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +/* Ciphersuites using HMAC */ +#if defined(MBEDTLS_SHA384_C) +#define MBEDTLS_SSL_MAC_ADD 48 /* SHA-384 used for HMAC */ +#elif defined(MBEDTLS_SHA256_C) +#define MBEDTLS_SSL_MAC_ADD 32 /* SHA-256 used for HMAC */ +#else +#define MBEDTLS_SSL_MAC_ADD 20 /* SHA-1 used for HMAC */ +#endif +#else /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ +/* AEAD ciphersuites: GCM and CCM use a 128 bits tag */ +#define MBEDTLS_SSL_MAC_ADD 16 +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_SSL_PADDING_ADD 256 +#else +#define MBEDTLS_SSL_PADDING_ADD 0 +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_MAX_CID_EXPANSION MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY +#else +#define MBEDTLS_SSL_MAX_CID_EXPANSION 0 +#endif + +#define MBEDTLS_SSL_PAYLOAD_OVERHEAD ( MBEDTLS_MAX_IV_LENGTH + \ + MBEDTLS_SSL_MAC_ADD + \ + MBEDTLS_SSL_PADDING_ADD + \ + MBEDTLS_SSL_MAX_CID_EXPANSION \ + ) + +#define MBEDTLS_SSL_IN_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_IN_CONTENT_LEN ) ) + +#define MBEDTLS_SSL_OUT_PAYLOAD_LEN ( MBEDTLS_SSL_PAYLOAD_OVERHEAD + \ + ( MBEDTLS_SSL_OUT_CONTENT_LEN ) ) + +/* The maximum number of buffered handshake messages. */ +#define MBEDTLS_SSL_MAX_BUFFERED_HS 4 + +/* Maximum length we can advertise as our max content length for + RFC 6066 max_fragment_length extension negotiation purposes + (the lesser of both sizes, if they are unequal.) + */ +#define MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ( \ + (MBEDTLS_SSL_IN_CONTENT_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN) \ + ? ( MBEDTLS_SSL_OUT_CONTENT_LEN ) \ + : ( MBEDTLS_SSL_IN_CONTENT_LEN ) \ + ) + +/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ +#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +/* + * Check that we obey the standard's message size bounds + */ + +#if MBEDTLS_SSL_IN_CONTENT_LEN > 16384 +#error "Bad configuration - incoming record content too large." +#endif + +#if MBEDTLS_SSL_OUT_CONTENT_LEN > 16384 +#error "Bad configuration - outgoing record content too large." +#endif + +#if MBEDTLS_SSL_IN_PAYLOAD_LEN > MBEDTLS_SSL_IN_CONTENT_LEN + 2048 +#error "Bad configuration - incoming protected record payload too large." +#endif + +#if MBEDTLS_SSL_OUT_PAYLOAD_LEN > MBEDTLS_SSL_OUT_CONTENT_LEN + 2048 +#error "Bad configuration - outgoing protected record payload too large." +#endif + +/* Calculate buffer sizes */ + +/* Note: Even though the TLS record header is only 5 bytes + long, we're internally using 8 bytes to store the + implicit sequence number. */ +#define MBEDTLS_SSL_HEADER_LEN 13 + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) ) +#else +#define MBEDTLS_SSL_IN_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_IN_PAYLOAD_LEN ) \ + + ( MBEDTLS_SSL_CID_IN_LEN_MAX ) ) +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) ) +#else +#define MBEDTLS_SSL_OUT_BUFFER_LEN \ + ( ( MBEDTLS_SSL_HEADER_LEN ) + ( MBEDTLS_SSL_OUT_PAYLOAD_LEN ) \ + + ( MBEDTLS_SSL_CID_OUT_LEN_MAX ) ) +#endif + +#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32 +#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32 + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the output buffer. For the client, this is the configured + * value. For the server, it is the minimum of two - the + * configured value and the negotiated one. + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_out_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ); + +/** + * \brief Return the maximum fragment length (payload, in bytes) for + * the input buffer. This is the negotiated maximum fragment + * length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN. + * If it is not defined either, the value is 2^14. This function + * works as its predecessor, \c mbedtls_ssl_get_max_frag_len(). + * + * \sa mbedtls_ssl_conf_max_frag_len() + * \sa mbedtls_ssl_get_max_in_record_payload() + * + * \param ssl SSL context + * + * \return Current maximum fragment length for the output buffer. + */ +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static inline size_t mbedtls_ssl_get_output_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_OUT_LEN_MAX; +#else + return mbedtls_ssl_get_output_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} + +static inline size_t mbedtls_ssl_get_input_buflen( const mbedtls_ssl_context *ctx ) +{ +#if defined (MBEDTLS_SSL_DTLS_CONNECTION_ID) + return mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD + + MBEDTLS_SSL_CID_IN_LEN_MAX; +#else + return mbedtls_ssl_get_input_max_frag_len( ctx ) + + MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD; +#endif +} +#endif + +/* + * TLS extension flags (for extensions with outgoing ServerHello content + * that need it (e.g. for RENEGOTIATION_INFO the server already knows because + * of state of the renegotiation flag, so no indicator is required) + */ +#define MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT (1 << 0) +#define MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK (1 << 1) + +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur, + const uint8_t *end, size_t need ) +{ + return( ( cur > end ) || ( need > (size_t)( end - cur ) ) ); +} + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); \ + } \ + } while( 0 ) + +/** + * \brief This macro checks if the remaining length in an input buffer is + * greater or equal than a needed length. If it is not the case, it + * returns #MBEDTLS_ERR_SSL_DECODE_ERROR error and pends a + * #MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR alert message. + * + * This is a function-like macro. It is guaranteed to evaluate each + * argument exactly once. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed length in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_READ_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + MBEDTLS_SSL_DEBUG_MSG( 1, \ + ( "missing input data in %s", __func__ ) ); \ + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \ + MBEDTLS_ERR_SSL_DECODE_ERROR ); \ + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); \ + } \ + } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Abstraction for a grid of allowed signature-hash-algorithm pairs. + */ +struct mbedtls_ssl_sig_hash_set_t +{ + /* At the moment, we only need to remember a single suitable + * hash algorithm per signature algorithm. As long as that's + * the case - and we don't need a general lookup function - + * we can implement the sig-hash-set as a map from signatures + * to hash algorithms. */ + mbedtls_md_type_t rsa; + mbedtls_md_type_t ecdsa; +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +typedef int mbedtls_ssl_tls_prf_cb( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); + +/* cipher.h exports the maximum IV, key and block length from + * all ciphers enabled in the config, regardless of whether those + * ciphers are actually usable in SSL/TLS. Notably, XTS is enabled + * in the default configuration and uses 64 Byte keys, but it is + * not used for record protection in SSL/TLS. + * + * In order to prevent unnecessary inflation of key structures, + * we introduce SSL-specific variants of the max-{key,block,IV} + * macros here which are meant to only take those ciphers into + * account which can be negotiated in SSL/TLS. + * + * Since the current definitions of MBEDTLS_MAX_{KEY|BLOCK|IV}_LENGTH + * in cipher.h are rough overapproximations of the real maxima, here + * we content ourselves with replicating those overapproximations + * for the maximum block and IV length, and excluding XTS from the + * computation of the maximum key length. */ +#define MBEDTLS_SSL_MAX_BLOCK_LENGTH 16 +#define MBEDTLS_SSL_MAX_IV_LENGTH 16 +#define MBEDTLS_SSL_MAX_KEY_LENGTH 32 + +/** + * \brief The data structure holding the cryptographic material (key and IV) + * used for record protection in TLS 1.3. + */ +struct mbedtls_ssl_key_set +{ + /*! The key for client->server records. */ + unsigned char client_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The key for server->client records. */ + unsigned char server_write_key[ MBEDTLS_SSL_MAX_KEY_LENGTH ]; + /*! The IV for client->server records. */ + unsigned char client_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + /*! The IV for server->client records. */ + unsigned char server_write_iv[ MBEDTLS_SSL_MAX_IV_LENGTH ]; + + size_t key_len; /*!< The length of client_write_key and + * server_write_key, in Bytes. */ + size_t iv_len; /*!< The length of client_write_iv and + * server_write_iv, in Bytes. */ +}; +typedef struct mbedtls_ssl_key_set mbedtls_ssl_key_set; + +typedef struct +{ + unsigned char binder_key [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char client_early_traffic_secret [ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char early_exporter_master_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; +} mbedtls_ssl_tls13_early_secrets; + +typedef struct +{ + unsigned char client_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; + unsigned char server_handshake_traffic_secret[ MBEDTLS_TLS1_3_MD_MAX_SIZE ]; +} mbedtls_ssl_tls13_handshake_secrets; + +/* + * This structure contains the parameters only needed during handshake. + */ +struct mbedtls_ssl_handshake_params +{ + /* Frequently-used boolean or byte fields (placed early to take + * advantage of smaller code size for indirect access on Arm Thumb) */ + uint8_t max_major_ver; /*!< max. major version client*/ + uint8_t max_minor_ver; /*!< max. minor version client*/ + uint8_t resume; /*!< session resume indicator*/ + uint8_t cli_exts; /*!< client extension presence*/ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + uint8_t sni_authmode; /*!< authmode from SNI callback */ +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + uint8_t new_session_ticket; /*!< use NewSessionTicket? */ +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + uint8_t extended_ms; /*!< use Extended Master Secret? */ +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + uint8_t async_in_progress; /*!< an asynchronous operation is in progress */ +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned char retransmit_state; /*!< Retransmission state */ +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + unsigned char group_list_heap_allocated; +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + uint8_t ecrs_enabled; /*!< Handshake supports EC restart? */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */ + size_t ecrs_n; /*!< place for saving a length */ +#endif + + size_t pmslen; /*!< premaster length */ + + mbedtls_ssl_ciphersuite_t const *ciphersuite_info; + + void (*update_checksum)(mbedtls_ssl_context *, const unsigned char *, size_t); + void (*calc_verify)(const mbedtls_ssl_context *, unsigned char *, size_t *); + void (*calc_finished)(mbedtls_ssl_context *, unsigned char *, int); + mbedtls_ssl_tls_prf_cb *tls_prf; + + /* + * Handshake specific crypto variables + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + int tls13_kex_modes; /*!< key exchange modes for TLS 1.3 */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_ssl_sig_hash_set_t hash_algs; /*!< Set of suitable sig-hash pairs */ +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + const uint16_t *group_list; +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_context dhm_ctx; /*!< DHM key exchange */ +#endif + +/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due + * to guards also being in ssl_srv.c and ssl_cli.c. There is a gap + * in functionality that access to ecdh_ctx structure is needed for + * MBEDTLS_ECDSA_C which does not seem correct. + */ +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + mbedtls_ecdh_context ecdh_ctx; /*!< ECDH key exchange */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_type_t ecdh_psa_type; + uint16_t ecdh_bits; + psa_key_id_t ecdh_psa_privkey; + unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH]; + size_t ecdh_psa_peerkey_len; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_context ecjpake_ctx; /*!< EC J-PAKE key exchange */ +#if defined(MBEDTLS_SSL_CLI_C) + unsigned char *ecjpake_cache; /*!< Cache for ClientHello ext */ + size_t ecjpake_cache_len; /*!< Length of cached data */ +#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_id_t psk_opaque; /*!< Opaque PSK from the callback */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char *psk; /*!< PSK from the callback */ + size_t psk_len; /*!< Length of PSK from callback */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + mbedtls_ssl_key_cert *sni_key_cert; /*!< key/cert list from SNI */ + mbedtls_x509_crt *sni_ca_chain; /*!< trusted CAs from SNI callback */ + mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */ +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + struct + { + size_t total_bytes_buffered; /*!< Cumulative size of heap allocated + * buffers used for message buffering. */ + + uint8_t seen_ccs; /*!< Indicates if a CCS message has + * been seen in the current flight. */ + + struct mbedtls_ssl_hs_buffer + { + unsigned is_valid : 1; + unsigned is_fragmented : 1; + unsigned is_complete : 1; + unsigned char *data; + size_t data_len; + } hs[MBEDTLS_SSL_MAX_BUFFERED_HS]; + + struct + { + unsigned char *data; + size_t len; + unsigned epoch; + } future_record; + + } buffering; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ + unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ + + unsigned char *verify_cookie; /*!< Cli: HelloVerifyRequest cookie + Srv: unused */ + unsigned char verify_cookie_len; /*!< Cli: cookie length + Srv: flag for sending a cookie */ + + uint32_t retransmit_timeout; /*!< Current value of timeout */ + mbedtls_ssl_flight_item *flight; /*!< Current outgoing flight */ + mbedtls_ssl_flight_item *cur_msg; /*!< Current message in flight */ + unsigned char *cur_msg_p; /*!< Position in current message */ + unsigned int in_flight_start_seq; /*!< Minimum message sequence in the + flight being received */ + mbedtls_ssl_transform *alt_transform_out; /*!< Alternative transform for + resending messages */ + unsigned char alt_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Alternative record epoch/counter + for resending messages */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The state of CID configuration in this handshake. */ + + uint8_t cid_in_use; /*!< This indicates whether the use of the CID extension + * has been negotiated. Possible values are + * #MBEDTLS_SSL_CID_ENABLED and + * #MBEDTLS_SSL_CID_DISABLED. */ + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; /*! The peer's CID */ + uint8_t peer_cid_len; /*!< The length of + * \c peer_cid. */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + uint16_t mtu; /*!< Handshake mtu, used to fragment outgoing messages */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /*! TLS 1.3 transforms for 0-RTT and encrypted handshake messages. + * Those pointers own the transforms they reference. */ + mbedtls_ssl_transform *transform_handshake; + mbedtls_ssl_transform *transform_earlydata; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * Checksum contexts + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha256_psa; +#else + mbedtls_sha256_context fin_sha256; +#endif +#endif +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t fin_sha384_psa; +#else + mbedtls_sha512_context fin_sha512; +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + uint16_t offered_group_id; /* The NamedGroup value for the group + * that is being used for ephemeral + * key exchange. + * + * On the client: Defaults to the first + * entry in the client's group list, + * but can be overwritten by the HRR. */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * State-local variables used during the processing + * of a specific handshake state. + */ + union + { + /* Outgoing Finished message */ + struct + { + uint8_t preparation_done; + + /* Buffer holding digest of the handshake up to + * but excluding the outgoing finished message. */ + unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t digest_len; + } finished_out; + + /* Incoming Finished message */ + struct + { + uint8_t preparation_done; + + /* Buffer holding digest of the handshake up to but + * excluding the peer's incoming finished message. */ + unsigned char digest[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t digest_len; + } finished_in; + + } state_local; + + /* End of state-local variables. */ + + unsigned char randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN + + MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + /*!< random bytes */ + unsigned char premaster[MBEDTLS_PREMASTER_SIZE]; + /*!< premaster secret */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + int extensions_present; /*!< extension presence; Each bitfield + represents an extension and defined + as \c MBEDTLS_SSL_EXT_XXX */ + + union + { + unsigned char early [MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char handshake[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + unsigned char app [MBEDTLS_TLS1_3_MD_MAX_SIZE]; + } tls13_master_secrets; + + mbedtls_ssl_tls13_handshake_secrets tls13_hs_secrets; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /** Asynchronous operation context. This field is meant for use by the + * asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start, + * mbedtls_ssl_config::f_async_decrypt_start, + * mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel). + * The library does not use it internally. */ + void *user_async_ctx; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +}; + +typedef struct mbedtls_ssl_hs_buffer mbedtls_ssl_hs_buffer; + +/* + * Representation of decryption/encryption transformations on records + * + * There are the following general types of record transformations: + * - Stream transformations (TLS versions == 1.2 only) + * Transformation adding a MAC and applying a stream-cipher + * to the authenticated message. + * - CBC block cipher transformations ([D]TLS versions == 1.2 only) + * For TLS 1.2, no IV is generated at key extraction time, but every + * encrypted record is explicitly prefixed by the IV with which it was + * encrypted. + * - AEAD transformations ([D]TLS versions == 1.2 only) + * These come in two fundamentally different versions, the first one + * used in TLS 1.2, excluding ChaChaPoly ciphersuites, and the second + * one used for ChaChaPoly ciphersuites in TLS 1.2 as well as for TLS 1.3. + * In the first transformation, the IV to be used for a record is obtained + * as the concatenation of an explicit, static 4-byte IV and the 8-byte + * record sequence number, and explicitly prepending this sequence number + * to the encrypted record. In contrast, in the second transformation + * the IV is obtained by XOR'ing a static IV obtained at key extraction + * time with the 8-byte record sequence number, without prepending the + * latter to the encrypted record. + * + * Additionally, DTLS 1.2 + CID as well as TLS 1.3 use an inner plaintext + * which allows to add flexible length padding and to hide a record's true + * content type. + * + * In addition to type and version, the following parameters are relevant: + * - The symmetric cipher algorithm to be used. + * - The (static) encryption/decryption keys for the cipher. + * - For stream/CBC, the type of message digest to be used. + * - For stream/CBC, (static) encryption/decryption keys for the digest. + * - For AEAD transformations, the size (potentially 0) of an explicit, + * random initialization vector placed in encrypted records. + * - For some transformations (currently AEAD) an implicit IV. It is static + * and (if present) is combined with the explicit IV in a transformation- + * -dependent way (e.g. appending in TLS 1.2 and XOR'ing in TLS 1.3). + * - For stream/CBC, a flag determining the order of encryption and MAC. + * - The details of the transformation depend on the SSL/TLS version. + * - The length of the authentication tag. + * + * The struct below refines this abstract view as follows: + * - The cipher underlying the transformation is managed in + * cipher contexts cipher_ctx_{enc/dec}, which must have the + * same cipher type. The mode of these cipher contexts determines + * the type of the transformation in the sense above: e.g., if + * the type is MBEDTLS_CIPHER_AES_256_CBC resp. MBEDTLS_CIPHER_AES_192_GCM + * then the transformation has type CBC resp. AEAD. + * - The cipher keys are never stored explicitly but + * are maintained within cipher_ctx_{enc/dec}. + * - For stream/CBC transformations, the message digest contexts + * used for the MAC's are stored in md_ctx_{enc/dec}. These contexts + * are unused for AEAD transformations. + * - For stream/CBC transformations, the MAC keys are not stored explicitly + * but maintained within md_ctx_{enc/dec}. + * - The mac_enc and mac_dec fields are unused for EAD transformations. + * - For transformations using an implicit IV maintained within + * the transformation context, its contents are stored within + * iv_{enc/dec}. + * - The value of ivlen indicates the length of the IV. + * This is redundant in case of stream/CBC transformations + * which always use 0 resp. the cipher's block length as the + * IV length, but is needed for AEAD ciphers and may be + * different from the underlying cipher's block length + * in this case. + * - The field fixed_ivlen is nonzero for AEAD transformations only + * and indicates the length of the static part of the IV which is + * constant throughout the communication, and which is stored in + * the first fixed_ivlen bytes of the iv_{enc/dec} arrays. + * - minor_ver denotes the SSL/TLS version + * - For stream/CBC transformations, maclen denotes the length of the + * authentication tag, while taglen is unused and 0. + * - For AEAD transformations, taglen denotes the length of the + * authentication tag, while maclen is unused and 0. + * - For CBC transformations, encrypt_then_mac determines the + * order of encryption and authentication. This field is unused + * in other transformations. + * + */ +struct mbedtls_ssl_transform +{ + /* + * Session specific crypto layer + */ + size_t minlen; /*!< min. ciphertext length */ + size_t ivlen; /*!< IV length */ + size_t fixed_ivlen; /*!< Fixed part of IV (AEAD) */ + size_t maclen; /*!< MAC(CBC) len */ + size_t taglen; /*!< TAG(AEAD) len */ + + unsigned char iv_enc[16]; /*!< IV (encryption) */ + unsigned char iv_dec[16]; /*!< IV (decryption) */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + + mbedtls_md_context_t md_ctx_enc; /*!< MAC (encryption) */ + mbedtls_md_context_t md_ctx_dec; /*!< MAC (decryption) */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac; /*!< flag for EtM activation */ +#endif + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + mbedtls_cipher_context_t cipher_ctx_enc; /*!< encryption context */ + mbedtls_cipher_context_t cipher_ctx_dec; /*!< decryption context */ + int minor_ver; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t in_cid_len; + uint8_t out_cid_len; + unsigned char in_cid [ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + unsigned char out_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ]; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + /* We need the Hello random bytes in order to re-derive keys from the + * Master Secret and other session info, + * see ssl_tls12_populate_transform() */ + unsigned char randbytes[MBEDTLS_SERVER_HELLO_RANDOM_LEN + + MBEDTLS_CLIENT_HELLO_RANDOM_LEN]; + /*!< ServerHello.random+ClientHello.random */ +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ +}; + +/* + * Return 1 if the transform uses an AEAD cipher, 0 otherwise. + * Equivalently, return 0 if a separate MAC is used, 1 otherwise. + */ +static inline int mbedtls_ssl_transform_uses_aead( + const mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + return( transform->maclen == 0 && transform->taglen != 0 ); +#else + (void) transform; + return( 1 ); +#endif +} + +/* + * Internal representation of record frames + * + * Instances come in two flavors: + * (1) Encrypted + * These always have data_offset = 0 + * (2) Unencrypted + * These have data_offset set to the amount of + * pre-expansion during record protection. Concretely, + * this is the length of the fixed part of the explicit IV + * used for encryption, or 0 if no explicit IV is used + * (e.g. for stream ciphers). + * + * The reason for the data_offset in the unencrypted case + * is to allow for in-place conversion of an unencrypted to + * an encrypted record. If the offset wasn't included, the + * encrypted content would need to be shifted afterwards to + * make space for the fixed IV. + * + */ +#if MBEDTLS_SSL_CID_OUT_LEN_MAX > MBEDTLS_SSL_CID_IN_LEN_MAX +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_OUT_LEN_MAX +#else +#define MBEDTLS_SSL_CID_LEN_MAX MBEDTLS_SSL_CID_IN_LEN_MAX +#endif + +typedef struct +{ + uint8_t ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /* In TLS: The implicit record sequence number. + * In DTLS: The 2-byte epoch followed by + * the 6-byte sequence number. + * This is stored as a raw big endian byte array + * as opposed to a uint64_t because we rarely + * need to perform arithmetic on this, but do + * need it as a Byte array for the purpose of + * MAC computations. */ + uint8_t type; /* The record content type. */ + uint8_t ver[2]; /* SSL/TLS version as present on the wire. + * Convert to internal presentation of versions + * using mbedtls_ssl_read_version() and + * mbedtls_ssl_write_version(). + * Keep wire-format for MAC computations. */ + + unsigned char *buf; /* Memory buffer enclosing the record content */ + size_t buf_len; /* Buffer length */ + size_t data_offset; /* Offset of record content */ + size_t data_len; /* Length of record content */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + uint8_t cid_len; /* Length of the CID (0 if not present) */ + unsigned char cid[ MBEDTLS_SSL_CID_LEN_MAX ]; /* The CID */ +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +} mbedtls_record; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * List of certificate + private key pairs + */ +struct mbedtls_ssl_key_cert +{ + mbedtls_x509_crt *cert; /*!< cert */ + mbedtls_pk_context *key; /*!< private key */ + mbedtls_ssl_key_cert *next; /*!< next key/cert pair */ +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * List of handshake messages kept around for resending + */ +struct mbedtls_ssl_flight_item +{ + unsigned char *p; /*!< message, including handshake headers */ + size_t len; /*!< length of p */ + unsigned char type; /*!< type of the message: handshake or CCS */ + mbedtls_ssl_flight_item *next; /*!< next handshake message(s) */ +}; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ); +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ); +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ); + +/* Setup an empty signature-hash set */ +static inline void mbedtls_ssl_sig_hash_set_init( mbedtls_ssl_sig_hash_set_t *set ) +{ + mbedtls_ssl_sig_hash_set_const_hash( set, MBEDTLS_MD_NONE ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/** + * \brief Free referenced items in an SSL transform context and clear + * memory + * + * \param transform SSL transform context + */ +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ); + +/** + * \brief Free referenced items in an SSL handshake context and clear + * memory + * + * \param ssl SSL context + */ +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ); + +/* set inbound transform of ssl context */ +void mbedtls_ssl_set_inbound_transform( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); + +/* set outbound transform of ssl context */ +void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ); +#endif + +int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ); + +/** + * \brief Update record layer + * + * This function roughly separates the implementation + * of the logic of (D)TLS from the implementation + * of the secure transport. + * + * \param ssl The SSL context to use. + * \param update_hs_digest This indicates if the handshake digest + * should be automatically updated in case + * a handshake message is found. + * + * \return 0 or non-zero error code. + * + * \note A clarification on what is called 'record layer' here + * is in order, as many sensible definitions are possible: + * + * The record layer takes as input an untrusted underlying + * transport (stream or datagram) and transforms it into + * a serially multiplexed, secure transport, which + * conceptually provides the following: + * + * (1) Three datagram based, content-agnostic transports + * for handshake, alert and CCS messages. + * (2) One stream- or datagram-based transport + * for application data. + * (3) Functionality for changing the underlying transform + * securing the contents. + * + * The interface to this functionality is given as follows: + * + * a Updating + * [Currently implemented by mbedtls_ssl_read_record] + * + * Check if and on which of the four 'ports' data is pending: + * Nothing, a controlling datagram of type (1), or application + * data (2). In any case data is present, internal buffers + * provide access to the data for the user to process it. + * Consumption of type (1) datagrams is done automatically + * on the next update, invalidating that the internal buffers + * for previous datagrams, while consumption of application + * data (2) is user-controlled. + * + * b Reading of application data + * [Currently manual adaption of ssl->in_offt pointer] + * + * As mentioned in the last paragraph, consumption of data + * is different from the automatic consumption of control + * datagrams (1) because application data is treated as a stream. + * + * c Tracking availability of application data + * [Currently manually through decreasing ssl->in_msglen] + * + * For efficiency and to retain datagram semantics for + * application data in case of DTLS, the record layer + * provides functionality for checking how much application + * data is still available in the internal buffer. + * + * d Changing the transformation securing the communication. + * + * Given an opaque implementation of the record layer in the + * above sense, it should be possible to implement the logic + * of (D)TLS on top of it without the need to know anything + * about the record layer's internals. This is done e.g. + * in all the handshake handling functions, and in the + * application data reading function mbedtls_ssl_read. + * + * \note The above tries to give a conceptual picture of the + * record layer, but the current implementation deviates + * from it in some places. For example, our implementation of + * the update functionality through mbedtls_ssl_read_record + * discards datagrams depending on the current state, which + * wouldn't fall under the record layer's responsibility + * following the above definition. + * + */ +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ); +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ); + +int mbedtls_ssl_write_handshake_msg_ext( mbedtls_ssl_context *ssl, + int update_checksum ); +static inline int mbedtls_ssl_write_handshake_msg( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_write_handshake_msg_ext( ssl, 1 /* update checksum */ ) ); +} + +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ); +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ); + +/** + * Get the first defined PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk() in the PSK callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk() + * Return a code and update the pair (PSK, PSK length) passed to this function + */ +static inline int mbedtls_ssl_get_psk( const mbedtls_ssl_context *ssl, + const unsigned char **psk, size_t *psk_len ) +{ + if( ssl->handshake->psk != NULL && ssl->handshake->psk_len > 0 ) + { + *psk = ssl->handshake->psk; + *psk_len = ssl->handshake->psk_len; + } + + else if( ssl->conf->psk != NULL && ssl->conf->psk_len > 0 ) + { + *psk = ssl->conf->psk; + *psk_len = ssl->conf->psk_len; + } + + else + { + *psk = NULL; + *psk_len = 0; + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * Get the first defined opaque PSK by order of precedence: + * 1. handshake PSK set by \c mbedtls_ssl_set_hs_psk_opaque() in the PSK + * callback + * 2. static PSK configured by \c mbedtls_ssl_conf_psk_opaque() + * Return an opaque PSK + */ +static inline psa_key_id_t mbedtls_ssl_get_opaque_psk( + const mbedtls_ssl_context *ssl ) +{ + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + return( ssl->handshake->psk_opaque ); + + if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) ) + return( ssl->conf->psk_opaque ); + + return( MBEDTLS_SVC_KEY_ID_INIT ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_PK_C) +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ); +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ); +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ); +#endif + +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ); +unsigned char mbedtls_ssl_hash_from_md_alg( int md ); +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ); + +#if defined(MBEDTLS_ECP_C) +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ); +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static inline mbedtls_ssl_srtp_profile mbedtls_ssl_check_srtp_profile_value + ( const uint16_t srtp_profile_value ) +{ + switch( srtp_profile_value ) + { + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_AES128_CM_HMAC_SHA1_32: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_80: + case MBEDTLS_TLS_SRTP_NULL_HMAC_SHA1_32: + return srtp_profile_value; + default: break; + } + return( MBEDTLS_TLS_SRTP_UNSET ); +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static inline mbedtls_pk_context *mbedtls_ssl_own_key( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->key ); +} + +static inline mbedtls_x509_crt *mbedtls_ssl_own_cert( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_key_cert *key_cert; + + if( ssl->handshake != NULL && ssl->handshake->key_cert != NULL ) + key_cert = ssl->handshake->key_cert; + else + key_cert = ssl->conf->key_cert; + + return( key_cert == NULL ? NULL : key_cert->cert ); +} + +/* + * Check usage of a certificate wrt extensions: + * keyUsage, extendedKeyUsage (later), and nSCertType (later). + * + * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we + * check a cert we received from them)! + * + * Return 0 if everything is OK, -1 if not. + */ +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ); +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ); + +static inline size_t mbedtls_ssl_in_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + return( 13 ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + return( 5 ); + } +} + +static inline size_t mbedtls_ssl_out_hdr_len( const mbedtls_ssl_context *ssl ) +{ + return( (size_t) ( ssl->out_iv - ssl->out_hdr ) ); +} + +static inline size_t mbedtls_ssl_hs_hdr_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 12 ); +#else + ((void) ssl); +#endif + return( 4 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ); +#endif + +/* Visible for testing purposes only */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ); +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ); +#endif + +int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* The hash buffer must have at least MBEDTLS_MD_MAX_SIZE bytes of length. */ +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#ifdef __cplusplus +} +#endif + +void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ); +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ); + +/* Length of the "epoch" field in the record header */ +static inline size_t mbedtls_ssl_ep_len( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 2 ); +#else + ((void) ssl); +#endif + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ); +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ); + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ); +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ); + +/* + * Send pending alert + */ +int mbedtls_ssl_handle_pending_alert( mbedtls_ssl_context *ssl ); + +/* + * Set pending fatal alert flag. + */ +void mbedtls_ssl_pend_fatal_alert( mbedtls_ssl_context *ssl, + unsigned char alert_type, + int alert_reason ); + +/* Alias of mbedtls_ssl_pend_fatal_alert */ +#define MBEDTLS_SSL_PEND_FATAL_ALERT( type, user_return_value ) \ + mbedtls_ssl_pend_fatal_alert( ssl, type, user_return_value ) + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ); +#endif + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ); +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ); +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/** + * ssl utils functions for checking configuration. + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +static inline int mbedtls_ssl_conf_is_tls13_only( const mbedtls_ssl_config *conf ) +{ + if( conf->min_major_ver == MBEDTLS_SSL_MAJOR_VERSION_3 && + conf->max_major_ver == MBEDTLS_SSL_MAJOR_VERSION_3 && + conf->min_minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 && + conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + return( 1 ); + } + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +static inline int mbedtls_ssl_conf_is_tls12_only( const mbedtls_ssl_config *conf ) +{ + if( conf->min_major_ver == MBEDTLS_SSL_MAJOR_VERSION_3 && + conf->max_major_ver == MBEDTLS_SSL_MAJOR_VERSION_3 && + conf->min_minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + return( 1 ); + } + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) +static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13( const mbedtls_ssl_config *conf ) +{ + if( conf->min_major_ver == MBEDTLS_SSL_MAJOR_VERSION_3 && + conf->max_major_ver == MBEDTLS_SSL_MAJOR_VERSION_3 && + conf->min_minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + return( 1 ); + } + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +int mbedtls_ssl_tls13_process_finished_message( mbedtls_ssl_context *ssl ); +int mbedtls_ssl_tls13_write_finished_message( mbedtls_ssl_context *ssl ); +void mbedtls_ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ); + +/** + * \brief TLS 1.3 client side state machine entry + * + * \param ssl SSL context + */ +int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl ); + +/** + * \brief TLS 1.3 server side state machine entry + * + * \param ssl SSL context + */ +int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl ); + + +/* + * Helper functions around key exchange modes. + */ +static inline unsigned mbedtls_ssl_conf_tls13_check_kex_modes( mbedtls_ssl_context *ssl, + int kex_mode_mask ) +{ + return( ( ssl->conf->tls13_kex_modes & kex_mode_mask ) != 0 ); +} + +static inline int mbedtls_ssl_conf_tls13_psk_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK ) ); +} + +static inline int mbedtls_ssl_conf_tls13_psk_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) ); +} + +static inline int mbedtls_ssl_conf_tls13_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL ) ); +} + +static inline int mbedtls_ssl_conf_tls13_some_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL ) ); +} + +static inline int mbedtls_ssl_conf_tls13_some_psk_enabled( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_conf_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL ) ); +} + +/** + * Given a list of key exchange modes, check if at least one of them is + * supported. + * + * \param[in] ssl SSL context + * \param kex_modes_mask Mask of the key exchange modes to check + * + * \return 0 if at least one of the key exchange modes is supported, + * !=0 otherwise. + */ +static inline unsigned mbedtls_ssl_tls13_check_kex_modes( mbedtls_ssl_context *ssl, + int kex_modes_mask ) +{ + return( ( ssl->handshake->tls13_kex_modes & kex_modes_mask ) == 0 ); +} + +static inline int mbedtls_ssl_tls13_psk_enabled( mbedtls_ssl_context *ssl ) +{ + return( ! mbedtls_ssl_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK ) ); +} + +static inline int mbedtls_ssl_tls13_psk_ephemeral_enabled( + mbedtls_ssl_context *ssl ) +{ + return( ! mbedtls_ssl_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL ) ); +} + +static inline int mbedtls_ssl_tls13_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( ! mbedtls_ssl_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL ) ); +} + +static inline int mbedtls_ssl_tls13_some_ephemeral_enabled( mbedtls_ssl_context *ssl ) +{ + return( ! mbedtls_ssl_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL ) ); +} + +static inline int mbedtls_ssl_tls13_some_psk_enabled( mbedtls_ssl_context *ssl ) +{ + return( ! mbedtls_ssl_tls13_check_kex_modes( ssl, + MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL ) ); +} + +/* + * Helper functions for NamedGroup. + */ +static inline int mbedtls_ssl_tls13_named_group_is_ecdhe( uint16_t named_group ) +{ + return( named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X25519 || + named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448 ); +} + +static inline int mbedtls_ssl_tls13_named_group_is_dhe( uint16_t named_group ) +{ + return( named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 && + named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192 ); +} + +static inline void mbedtls_ssl_handshake_set_state( mbedtls_ssl_context *ssl, + mbedtls_ssl_states state ) +{ + ssl->state = ( int ) state; +} + +/* + * Fetch TLS 1.3 handshake message header + */ +int mbedtls_ssl_tls13_fetch_handshake_msg( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len ); + +/* + * Write TLS 1.3 handshake message header + */ +int mbedtls_ssl_tls13_start_handshake_msg( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len ); + +/* + * Handler of TLS 1.3 server certificate message + */ +int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl ); + +/* + * Generic handler of Certificate Verify + */ +int mbedtls_ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl ); + +/* + * Write of dummy-CCS's for middlebox compatibility + */ +int mbedtls_ssl_tls13_write_change_cipher_spec( mbedtls_ssl_context *ssl ); + +/* + * Write TLS 1.3 handshake message tail + */ +int mbedtls_ssl_tls13_finish_handshake_msg( mbedtls_ssl_context *ssl, + size_t buf_len, + size_t msg_len ); + +void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl, + unsigned hs_type, + size_t total_hs_len ); + +/* + * Update checksum of handshake messages. + */ +void mbedtls_ssl_tls13_add_hs_msg_to_checksum( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char const *msg, + size_t msg_len ); + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Write TLS 1.3 Signature Algorithm extension + */ +int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len); + +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +/* Get handshake transcript */ +int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen ); + +/* + * Return supported groups. + * + * In future, invocations can be changed to ssl->conf->group_list + * when mbedtls_ssl_conf_curves() is deleted. + * + * ssl->handshake->group_list is either a translation of curve_list to IANA TLS group + * identifiers when mbedtls_ssl_conf_curves() has been used, or a pointer to + * ssl->conf->group_list when mbedtls_ssl_conf_groups() has been more recently invoked. + * + */ +static inline const void *mbedtls_ssl_get_groups( const mbedtls_ssl_context *ssl ) +{ + #if defined(MBEDTLS_DEPRECATED_REMOVED) || !defined(MBEDTLS_ECP_C) + return( ssl->conf->group_list ); + #else + if( ( ssl->handshake != NULL ) && ( ssl->handshake->group_list != NULL ) ) + return( ssl->handshake->group_list ); + else + return( ssl->conf->group_list ); + #endif +} + +#endif /* ssl_misc.h */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_msg.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_msg.c new file mode 100644 index 00000000..51eb4619 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_msg.c @@ -0,0 +1,5561 @@ +/* + * Generic SSL/TLS messaging layer functions + * (record layer + retransmission state machine) + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "ssl_misc.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ); + +/* + * Start a timer. + * Passing millisecs = 0 cancels a running timer. + */ +void mbedtls_ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs ) +{ + if( ssl->f_set_timer == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) ); + ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs ); +} + +/* + * Return -1 is timer is expired, 0 if it isn't. + */ +int mbedtls_ssl_check_timer( mbedtls_ssl_context *ssl ) +{ + if( ssl->f_get_timer == NULL ) + return( 0 ); + + if( ssl->f_get_timer( ssl->p_timer ) == 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) ); + return( -1 ); + } + + return( 0 ); +} + +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ); + +int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t buflen ) +{ + int ret = 0; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen ); + + /* We don't support record checking in TLS because + * there doesn't seem to be a usecase for it. + */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + goto exit; + } +#if defined(MBEDTLS_SSL_PROTO_DTLS) + else + { + mbedtls_record rec; + + ret = ssl_parse_record_header( ssl, buf, buflen, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret ); + goto exit; + } + + if( ssl->transform_in != NULL ) + { + ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret ); + goto exit; + } + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +exit: + /* On success, we have decrypted the buffer in-place, so make + * sure we don't leak any plaintext data. */ + mbedtls_platform_zeroize( buf, buflen ); + + /* For the purpose of this API, treat messages with unexpected CID + * as well as such from future epochs as unexpected. */ + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID || + ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) ); + return( ret ); +} + +#define SSL_DONT_FORCE_FLUSH 0 +#define SSL_FORCE_FLUSH 1 + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +/* Forward declarations for functions related to message buffering. */ +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ); +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ); +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ); +static int ssl_buffer_message( mbedtls_ssl_context *ssl ); +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ); +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ); + +static size_t ssl_get_maximum_datagram_size( mbedtls_ssl_context const *ssl ) +{ + size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + if( mtu != 0 && mtu < out_buf_len ) + return( mtu ); + + return( out_buf_len ); +} + +static int ssl_get_remaining_space_in_datagram( mbedtls_ssl_context const *ssl ) +{ + size_t const bytes_written = ssl->out_left; + size_t const mtu = ssl_get_maximum_datagram_size( ssl ); + + /* Double-check that the write-index hasn't gone + * past what we can transmit in a single datagram. */ + if( bytes_written > mtu ) + { + /* Should never happen... */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( (int) ( mtu - bytes_written ) ); +} + +static int ssl_get_remaining_payload_in_datagram( mbedtls_ssl_context const *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t remaining, expansion; + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; + + /* By the standard (RFC 6066 Sect. 4), the MFL extension + * only limits the maximum record payload size, so in theory + * we would be allowed to pack multiple records of payload size + * MFL into a single datagram. However, this would mean that there's + * no way to explicitly communicate MTU restrictions to the peer. + * + * The following reduction of max_len makes sure that we never + * write datagrams larger than MFL + Record Expansion Overhead. + */ + if( max_len <= ssl->out_left ) + return( 0 ); + + max_len -= ssl->out_left; +#endif + + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + remaining = (size_t) ret; + + ret = mbedtls_ssl_get_record_expansion( ssl ); + if( ret < 0 ) + return( ret ); + expansion = (size_t) ret; + + if( remaining <= expansion ) + return( 0 ); + + remaining -= expansion; + if( remaining >= max_len ) + remaining = max_len; + + return( (int) remaining ); +} + +/* + * Double the retransmit timeout value, within the allowed range, + * returning -1 if the maximum value has already been reached. + */ +static int ssl_double_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + uint32_t new_timeout; + + if( ssl->handshake->retransmit_timeout >= ssl->conf->hs_timeout_max ) + return( -1 ); + + /* Implement the final paragraph of RFC 6347 section 4.1.1.1 + * in the following way: after the initial transmission and a first + * retransmission, back off to a temporary estimated MTU of 508 bytes. + * This value is guaranteed to be deliverable (if not guaranteed to be + * delivered) of any compliant IPv4 (and IPv6) network, and should work + * on most non-IP stacks too. */ + if( ssl->handshake->retransmit_timeout != ssl->conf->hs_timeout_min ) + { + ssl->handshake->mtu = 508; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "mtu autoreduction to %d bytes", ssl->handshake->mtu ) ); + } + + new_timeout = 2 * ssl->handshake->retransmit_timeout; + + /* Avoid arithmetic overflow and range overflow */ + if( new_timeout < ssl->handshake->retransmit_timeout || + new_timeout > ssl->conf->hs_timeout_max ) + { + new_timeout = ssl->conf->hs_timeout_max; + } + + ssl->handshake->retransmit_timeout = new_timeout; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs", + (unsigned long) ssl->handshake->retransmit_timeout ) ); + + return( 0 ); +} + +static void ssl_reset_retransmit_timeout( mbedtls_ssl_context *ssl ) +{ + ssl->handshake->retransmit_timeout = ssl->conf->hs_timeout_min; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "update timeout value to %lu millisecs", + (unsigned long) ssl->handshake->retransmit_timeout ) ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Encryption/decryption functions + */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) || defined(MBEDTLS_SSL_PROTO_TLS1_3) + +static size_t ssl_compute_padding_length( size_t len, + size_t granularity ) +{ + return( ( granularity - ( len + 1 ) % granularity ) % granularity ); +} + +/* This functions transforms a (D)TLS plaintext fragment and a record content + * type into an instance of the (D)TLSInnerPlaintext structure. This is used + * in DTLS 1.2 + CID and within TLS 1.3 to allow flexible padding and to protect + * a record's content type. + * + * struct { + * opaque content[DTLSPlaintext.length]; + * ContentType real_type; + * uint8 zeros[length_of_padding]; + * } (D)TLSInnerPlaintext; + * + * Input: + * - `content`: The beginning of the buffer holding the + * plaintext to be wrapped. + * - `*content_size`: The length of the plaintext in Bytes. + * - `max_len`: The number of Bytes available starting from + * `content`. This must be `>= *content_size`. + * - `rec_type`: The desired record content type. + * + * Output: + * - `content`: The beginning of the resulting (D)TLSInnerPlaintext structure. + * - `*content_size`: The length of the resulting (D)TLSInnerPlaintext structure. + * + * Returns: + * - `0` on success. + * - A negative error code if `max_len` didn't offer enough space + * for the expansion. + */ +static int ssl_build_inner_plaintext( unsigned char *content, + size_t *content_size, + size_t remaining, + uint8_t rec_type, + size_t pad ) +{ + size_t len = *content_size; + + /* Write real content type */ + if( remaining == 0 ) + return( -1 ); + content[ len ] = rec_type; + len++; + remaining--; + + if( remaining < pad ) + return( -1 ); + memset( content + len, 0, pad ); + len += pad; + remaining -= pad; + + *content_size = len; + return( 0 ); +} + +/* This function parses a (D)TLSInnerPlaintext structure. + * See ssl_build_inner_plaintext() for details. */ +static int ssl_parse_inner_plaintext( unsigned char const *content, + size_t *content_size, + uint8_t *rec_type ) +{ + size_t remaining = *content_size; + + /* Determine length of padding by skipping zeroes from the back. */ + do + { + if( remaining == 0 ) + return( -1 ); + remaining--; + } while( content[ remaining ] == 0 ); + + *content_size = remaining; + *rec_type = content[ remaining ]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID || MBEDTLS_SSL_PROTO_TLS1_3 */ + +/* `add_data` must have size 13 Bytes if the CID extension is disabled, + * and 13 + 1 + CID-length Bytes if the CID extension is enabled. */ +static void ssl_extract_add_data_from_record( unsigned char* add_data, + size_t *add_data_len, + mbedtls_record *rec, + unsigned minor_ver, + size_t taglen ) +{ + /* Quoting RFC 5246 (TLS 1.2): + * + * additional_data = seq_num + TLSCompressed.type + + * TLSCompressed.version + TLSCompressed.length; + * + * For the CID extension, this is extended as follows + * (quoting draft-ietf-tls-dtls-connection-id-05, + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05): + * + * additional_data = seq_num + DTLSPlaintext.type + + * DTLSPlaintext.version + + * cid + + * cid_length + + * length_of_DTLSInnerPlaintext; + * + * For TLS 1.3, the record sequence number is dropped from the AAD + * and encoded within the nonce of the AEAD operation instead. + * Moreover, the additional data involves the length of the TLS + * ciphertext, not the TLS plaintext as in earlier versions. + * Quoting RFC 8446 (TLS 1.3): + * + * additional_data = TLSCiphertext.opaque_type || + * TLSCiphertext.legacy_record_version || + * TLSCiphertext.length + * + * We pass the tag length to this function in order to compute the + * ciphertext length from the inner plaintext length rec->data_len via + * + * TLSCiphertext.length = TLSInnerPlaintext.length + taglen. + * + */ + + unsigned char *cur = add_data; + size_t ad_len_field = rec->data_len; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + /* In TLS 1.3, the AAD contains the length of the TLSCiphertext, + * which differs from the length of the TLSInnerPlaintext + * by the length of the authentication tag. */ + ad_len_field += taglen; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + { + ((void) minor_ver); + ((void) taglen); + memcpy( cur, rec->ctr, sizeof( rec->ctr ) ); + cur += sizeof( rec->ctr ); + } + + *cur = rec->type; + cur++; + + memcpy( cur, rec->ver, sizeof( rec->ver ) ); + cur += sizeof( rec->ver ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + memcpy( cur, rec->cid, rec->cid_len ); + cur += rec->cid_len; + + *cur = rec->cid_len; + cur++; + + MBEDTLS_PUT_UINT16_BE( ad_len_field, cur, 0 ); + cur += 2; + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + MBEDTLS_PUT_UINT16_BE( ad_len_field, cur, 0 ); + cur += 2; + } + + *add_data_len = cur - add_data; +} + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) +static int ssl_transform_aead_dynamic_iv_is_explicit( + mbedtls_ssl_transform const *transform ) +{ + return( transform->ivlen != transform->fixed_ivlen ); +} + +/* Compute IV := ( fixed_iv || 0 ) XOR ( 0 || dynamic_IV ) + * + * Concretely, this occurs in two variants: + * + * a) Fixed and dynamic IV lengths add up to total IV length, giving + * IV = fixed_iv || dynamic_iv + * + * This variant is used in TLS 1.2 when used with GCM or CCM. + * + * b) Fixed IV lengths matches total IV length, giving + * IV = fixed_iv XOR ( 0 || dynamic_iv ) + * + * This variant occurs in TLS 1.3 and for TLS 1.2 when using ChaChaPoly. + * + * See also the documentation of mbedtls_ssl_transform. + * + * This function has the precondition that + * + * dst_iv_len >= max( fixed_iv_len, dynamic_iv_len ) + * + * which has to be ensured by the caller. If this precondition + * violated, the behavior of this function is undefined. + */ +static void ssl_build_record_nonce( unsigned char *dst_iv, + size_t dst_iv_len, + unsigned char const *fixed_iv, + size_t fixed_iv_len, + unsigned char const *dynamic_iv, + size_t dynamic_iv_len ) +{ + size_t i; + + /* Start with Fixed IV || 0 */ + memset( dst_iv, 0, dst_iv_len ); + memcpy( dst_iv, fixed_iv, fixed_iv_len ); + + dst_iv += dst_iv_len - dynamic_iv_len; + for( i = 0; i < dynamic_iv_len; i++ ) + dst_iv[i] ^= dynamic_iv[i]; +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_ssl_encrypt_buf( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + mbedtls_cipher_mode_t mode; + int auth_done = 0; + unsigned char * data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_OUT_LEN_MAX ]; + size_t add_data_len; + size_t post_avail; + + /* The SSL context is only used for debugging purposes! */ +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* The PRNG is used for dynamic IV generation that's used + * for CBC transformations in TLS 1.2. */ +#if !( defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) + ((void) f_rng); + ((void) p_rng); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> encrypt buf" ) ); + + if( transform == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + if( rec == NULL + || rec->buf == NULL + || rec->buf_len < rec->data_offset + || rec->buf_len - rec->data_offset < rec->data_len +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + || rec->cid_len != 0 +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to encrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + MBEDTLS_SSL_DEBUG_BUF( 4, "before encrypt: output payload", + data, rec->data_len ); + + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ); + + if( rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record content %" MBEDTLS_PRINTF_SIZET + " too large, maximum %" MBEDTLS_PRINTF_SIZET, + rec->data_len, + (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* The following two code paths implement the (D)TLSInnerPlaintext + * structure present in TLS 1.3 and DTLS 1.2 + CID. + * + * See ssl_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + * + * Note also that the two code paths cannot occur simultaneously + * since they apply to different versions of the protocol. There + * is hence no risk of double-addition of the inner plaintext. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + size_t padding = + ssl_compute_padding_length( rec->data_len, + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY ); + if( ssl_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type, + padding ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_APPLICATION_DATA; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Add CID information + */ + rec->cid_len = transform->out_cid_len; + memcpy( rec->cid, transform->out_cid, transform->out_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "CID", rec->cid, rec->cid_len ); + + if( rec->cid_len != 0 ) + { + size_t padding = + ssl_compute_padding_length( rec->data_len, + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY ); + /* + * Wrap plaintext into DTLSInnerPlaintext structure. + * See ssl_build_inner_plaintext() for more information. + * + * Note that this changes `rec->data_len`, and hence + * `post_avail` needs to be recalculated afterwards. + */ + if( ssl_build_inner_plaintext( data, + &rec->data_len, + post_avail, + rec->type, + padding ) != 0 ) + { + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + rec->type = MBEDTLS_SSL_MSG_CID; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + post_avail = rec->buf_len - ( rec->data_len + rec->data_offset ); + + /* + * Add MAC before if needed + */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if( mode == MBEDTLS_MODE_STREAM || + ( mode == MBEDTLS_MODE_CBC +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + && transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED +#endif + ) ) + { + if( post_avail < transform->maclen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver, + transform->taglen ); + + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, data, rec->data_len ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + if( ret != 0 ) + goto hmac_failed_etm_disabled; + + memcpy( data + rec->data_len, mac, transform->maclen ); +#endif + + MBEDTLS_SSL_DEBUG_BUF( 4, "computed mac", data + rec->data_len, + transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + + hmac_failed_etm_disabled: + mbedtls_platform_zeroize( mac, transform->maclen ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_hmac_xxx", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + /* + * Encrypt + */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) + if( mode == MBEDTLS_MODE_STREAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including %d bytes of padding", + rec->data_len, 0 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; + int dynamic_iv_is_explicit = + ssl_transform_aead_dynamic_iv_is_explicit( transform ); + + /* Check that there's space for the authentication tag. */ + if( post_avail < transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Build nonce for AEAD encryption. + * + * Note: In the case of CCM and GCM in TLS 1.2, the dynamic + * part of the IV is prepended to the ciphertext and + * can be chosen freely - in particular, it need not + * agree with the record sequence number. + * However, since ChaChaPoly as well as all AEAD modes + * in TLS 1.3 use the record sequence number as the + * dynamic part of the nonce, we uniformly use the + * record sequence number here in all cases. + */ + dynamic_iv = rec->ctr; + dynamic_iv_len = sizeof( rec->ctr ); + + ssl_build_record_nonce( iv, sizeof( iv ), + transform->iv_enc, + transform->fixed_ivlen, + dynamic_iv, + dynamic_iv_len ); + + /* + * Build additional data for AEAD encryption. + * This depends on the TLS version. + */ + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver, + transform->taglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (internal)", + iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used (transmitted)", + dynamic_iv, + dynamic_iv_is_explicit ? dynamic_iv_len : 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including 0 bytes of padding", + rec->data_len ) ); + + /* + * Encrypt and authenticate + */ + + if( ( ret = mbedtls_cipher_auth_encrypt_ext( &transform->cipher_ctx_enc, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len, /* src */ + data, rec->buf_len - (data - rec->buf), /* dst */ + &rec->data_len, + transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_encrypt_ext", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_BUF( 4, "after encrypt: tag", + data + rec->data_len - transform->taglen, + transform->taglen ); + /* Account for authentication tag. */ + post_avail -= transform->taglen; + + /* + * Prefix record content with dynamic IV in case it is explicit. + */ + if( dynamic_iv_is_explicit != 0 ) + { + if( rec->data_offset < dynamic_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + memcpy( data - dynamic_iv_len, dynamic_iv, dynamic_iv_len ); + rec->data_offset -= dynamic_iv_len; + rec->data_len += dynamic_iv_len; + } + + auth_done++; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t padlen, i; + size_t olen; + + /* Currently we're always using minimal padding + * (up to 255 bytes would be allowed). */ + padlen = transform->ivlen - ( rec->data_len + 1 ) % transform->ivlen; + if( padlen == transform->ivlen ) + padlen = 0; + + /* Check there's enough space in the buffer for the padding. */ + if( post_avail < padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + for( i = 0; i <= padlen; i++ ) + data[rec->data_len + i] = (unsigned char) padlen; + + rec->data_len += padlen + 1; + post_avail -= padlen + 1; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Prepend per-record IV for block cipher in TLS v1.2 as per + * Method 1 (6.2.3.2. in RFC4346 and RFC5246) + */ + if( f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No PRNG provided to encrypt_record routine" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( rec->data_offset < transform->ivlen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + /* + * Generate IV + */ + ret = f_rng( p_rng, transform->iv_enc, transform->ivlen ); + if( ret != 0 ) + return( ret ); + + memcpy( data - transform->ivlen, transform->iv_enc, transform->ivlen ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %" MBEDTLS_PRINTF_SIZET ", " + "including %" MBEDTLS_PRINTF_SIZET + " bytes of IV and %" MBEDTLS_PRINTF_SIZET " bytes of padding", + rec->data_len, transform->ivlen, + padlen + 1 ) ); + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_enc, + transform->iv_enc, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data -= transform->ivlen; + rec->data_offset -= transform->ivlen; + rec->data_len += transform->ivlen; + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( auth_done == 0 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + /* + * MAC(MAC_write_key, seq_num + + * TLSCipherText.type + + * TLSCipherText.version + + * length_of( (IV +) ENC(...) ) + + * IV + + * ENC(content + padding + padding_length)); + */ + + if( post_avail < transform->maclen) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Buffer provided for encrypted record not large enough" ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl_extract_add_data_from_record( add_data, &add_data_len, + rec, transform->minor_ver, + transform->taglen ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, add_data, + add_data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_update( &transform->md_ctx_enc, + data, rec->data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_finish( &transform->md_ctx_enc, mac ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_reset( &transform->md_ctx_enc ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + + memcpy( data + rec->data_len, mac, transform->maclen ); + + rec->data_len += transform->maclen; + post_avail -= transform->maclen; + auth_done++; + + hmac_failed_etm_enabled: + mbedtls_platform_zeroize( mac, transform->maclen ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "HMAC calculation failed", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= encrypt buf" ) ); + + return( 0 ); +} + +int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl, + mbedtls_ssl_transform *transform, + mbedtls_record *rec ) +{ + size_t olen; + mbedtls_cipher_mode_t mode; + int ret, auth_done = 0; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + size_t padlen = 0, correct = 1; +#endif + unsigned char* data; + unsigned char add_data[13 + 1 + MBEDTLS_SSL_CID_IN_LEN_MAX ]; + size_t add_data_len; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) ); + if( rec == NULL || + rec->buf == NULL || + rec->buf_len < rec->data_offset || + rec->buf_len - rec->data_offset < rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad record structure provided to decrypt_buf" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + data = rec->buf + rec->data_offset; + mode = mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* + * Match record's CID with incoming CID. + */ + if( rec->cid_len != transform->in_cid_len || + memcmp( rec->cid, transform->in_cid, rec->cid_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_UNEXPECTED_CID ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM) + if( mode == MBEDTLS_MODE_STREAM ) + { + padlen = 0; + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, + transform->ivlen, + data, rec->data_len, + data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */ +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mode == MBEDTLS_MODE_GCM || + mode == MBEDTLS_MODE_CCM || + mode == MBEDTLS_MODE_CHACHAPOLY ) + { + unsigned char iv[12]; + unsigned char *dynamic_iv; + size_t dynamic_iv_len; + + /* + * Extract dynamic part of nonce for AEAD decryption. + * + * Note: In the case of CCM and GCM in TLS 1.2, the dynamic + * part of the IV is prepended to the ciphertext and + * can be chosen freely - in particular, it need not + * agree with the record sequence number. + */ + dynamic_iv_len = sizeof( rec->ctr ); + if( ssl_transform_aead_dynamic_iv_is_explicit( transform ) == 1 ) + { + if( rec->data_len < dynamic_iv_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + " ) < explicit_iv_len (%" MBEDTLS_PRINTF_SIZET ") ", + rec->data_len, + dynamic_iv_len ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + dynamic_iv = data; + + data += dynamic_iv_len; + rec->data_offset += dynamic_iv_len; + rec->data_len -= dynamic_iv_len; + } + else + { + dynamic_iv = rec->ctr; + } + + /* Check that there's space for the authentication tag. */ + if( rec->data_len < transform->taglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") < taglen (%" MBEDTLS_PRINTF_SIZET ") ", + rec->data_len, + transform->taglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + rec->data_len -= transform->taglen; + + /* + * Prepare nonce from dynamic and static parts. + */ + ssl_build_record_nonce( iv, sizeof( iv ), + transform->iv_dec, + transform->fixed_ivlen, + dynamic_iv, + dynamic_iv_len ); + + /* + * Build additional data for AEAD encryption. + * This depends on the TLS version. + */ + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver, + transform->taglen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD", + add_data, add_data_len ); + + /* Because of the check above, we know that there are + * explicit_iv_len Bytes preceeding data, and taglen + * bytes following data + data_len. This justifies + * the debug message and the invocation of + * mbedtls_cipher_auth_decrypt_ext() below. */ + + MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len, + transform->taglen ); + + /* + * Decrypt and authenticate + */ + if( ( ret = mbedtls_cipher_auth_decrypt_ext( &transform->cipher_ctx_dec, + iv, transform->ivlen, + add_data, add_data_len, + data, rec->data_len + transform->taglen, /* src */ + data, rec->buf_len - (data - rec->buf), &olen, /* dst */ + transform->taglen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_auth_decrypt_ext", ret ); + + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + + return( ret ); + } + auth_done++; + + /* Double-check that AEAD decryption doesn't change content length. */ + if( olen != rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) + if( mode == MBEDTLS_MODE_CBC ) + { + size_t minlen = 0; + + /* + * Check immediate ciphertext sanity + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* The ciphertext is prefixed with the CBC IV. */ + minlen += transform->ivlen; +#endif + + /* Size considerations: + * + * - The CBC cipher text must not be empty and hence + * at least of size transform->ivlen. + * + * Together with the potential IV-prefix, this explains + * the first of the two checks below. + * + * - The record must contain a MAC, either in plain or + * encrypted, depending on whether Encrypt-then-MAC + * is used or not. + * - If it is, the message contains the IV-prefix, + * the CBC ciphertext, and the MAC. + * - If it is not, the padded plaintext, and hence + * the CBC ciphertext, has at least length maclen + 1 + * because there is at least the padding length byte. + * + * As the CBC ciphertext is not empty, both cases give the + * lower bound minlen + maclen + 1 on the record size, which + * we test for in the second check below. + */ + if( rec->data_len < minlen + transform->ivlen || + rec->data_len < minlen + transform->maclen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") < max( ivlen(%" MBEDTLS_PRINTF_SIZET + "), maclen (%" MBEDTLS_PRINTF_SIZET ") " + "+ 1 ) ( + expl IV )", rec->data_len, + transform->ivlen, + transform->maclen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + /* + * Authenticate before decrypt if enabled + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( transform->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) ); + + /* Update data_len in tandem with add_data. + * + * The subtraction is safe because of the previous check + * data_len >= minlen + maclen + 1. + * + * Afterwards, we know that data + data_len is followed by at + * least maclen Bytes, which justifies the call to + * mbedtls_ct_memcmp() below. + * + * Further, we still know that data_len > minlen */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver, + transform->taglen ); + + /* Calculate expected MAC. */ + MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data, + add_data_len ); + ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data, + add_data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_update( &transform->md_ctx_dec, + data, rec->data_len ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_finish( &transform->md_ctx_dec, mac_expect ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + ret = mbedtls_md_hmac_reset( &transform->md_ctx_dec ); + if( ret != 0 ) + goto hmac_failed_etm_enabled; + + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", data + rec->data_len, + transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, + transform->maclen ); + + /* Compare expected MAC with MAC at the end of the record. */ + if( mbedtls_ct_memcmp( data + rec->data_len, mac_expect, + transform->maclen ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + goto hmac_failed_etm_enabled; + } + auth_done++; + + hmac_failed_etm_enabled: + mbedtls_platform_zeroize( mac_expect, transform->maclen ); + if( ret != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_hmac_xxx", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + + /* + * Check length sanity + */ + + /* We know from above that data_len > minlen >= 0, + * so the following check in particular implies that + * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */ + if( rec->data_len % transform->ivlen != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") %% ivlen (%" MBEDTLS_PRINTF_SIZET ") != 0", + rec->data_len, transform->ivlen ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Initialize for prepended IV for block cipher in TLS v1.2 + */ + /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */ + memcpy( transform->iv_dec, data, transform->ivlen ); + + data += transform->ivlen; + rec->data_offset += transform->ivlen; + rec->data_len -= transform->ivlen; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */ + + if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec, + transform->iv_dec, transform->ivlen, + data, rec->data_len, data, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_crypt", ret ); + return( ret ); + } + + /* Double-check that length hasn't changed during decryption. */ + if( rec->data_len != olen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Safe since data_len >= minlen + maclen + 1, so after having + * subtracted at most minlen and maclen up to this point, + * data_len > 0 (because of data_len % ivlen == 0, it's actually + * >= ivlen ). */ + padlen = data[rec->data_len - 1]; + + if( auth_done == 1 ) + { + const size_t mask = mbedtls_ct_size_mask_ge( + rec->data_len, + padlen + 1 ); + correct &= mask; + padlen &= mask; + } + else + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( rec->data_len < transform->maclen + padlen + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%" MBEDTLS_PRINTF_SIZET + ") < maclen (%" MBEDTLS_PRINTF_SIZET + ") + padlen (%" MBEDTLS_PRINTF_SIZET ")", + rec->data_len, + transform->maclen, + padlen + 1 ) ); + } +#endif + + const size_t mask = mbedtls_ct_size_mask_ge( + rec->data_len, + transform->maclen + padlen + 1 ); + correct &= mask; + padlen &= mask; + } + + padlen++; + + /* Regardless of the validity of the padding, + * we have data_len >= padlen here. */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* The padding check involves a series of up to 256 + * consecutive memory reads at the end of the record + * plaintext buffer. In order to hide the length and + * validity of the padding, always perform exactly + * `min(256,plaintext_len)` reads (but take into account + * only the last `padlen` bytes for the padding check). */ + size_t pad_count = 0; + volatile unsigned char* const check = data; + + /* Index of first padding byte; it has been ensured above + * that the subtraction is safe. */ + size_t const padding_idx = rec->data_len - padlen; + size_t const num_checks = rec->data_len <= 256 ? rec->data_len : 256; + size_t const start_idx = rec->data_len - num_checks; + size_t idx; + + for( idx = start_idx; idx < rec->data_len; idx++ ) + { + /* pad_count += (idx >= padding_idx) && + * (check[idx] == padlen - 1); + */ + const size_t mask = mbedtls_ct_size_mask_ge( idx, padding_idx ); + const size_t equal = mbedtls_ct_size_bool_eq( check[idx], + padlen - 1 ); + pad_count += mask & equal; + } + correct &= mbedtls_ct_size_bool_eq( pad_count, padlen ); + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( padlen > 0 && correct == 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad padding byte detected" ) ); +#endif + padlen &= mbedtls_ct_size_mask( correct ); + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* If the padding was found to be invalid, padlen == 0 + * and the subtraction is safe. If the padding was found valid, + * padlen hasn't been changed and the previous assertion + * data_len >= padlen still holds. */ + rec->data_len -= padlen; + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + data, rec->data_len ); +#endif + + /* + * Authenticate if not done yet. + * Compute the MAC regardless of the padding result (RFC4346, CBCTIME). + */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if( auth_done == 0 ) + { + unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD]; + unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD]; + + /* If the initial value of padlen was such that + * data_len < maclen + padlen + 1, then padlen + * got reset to 1, and the initial check + * data_len >= minlen + maclen + 1 + * guarantees that at this point we still + * have at least data_len >= maclen. + * + * If the initial value of padlen was such that + * data_len >= maclen + padlen + 1, then we have + * subtracted either padlen + 1 (if the padding was correct) + * or 0 (if the padding was incorrect) since then, + * hence data_len >= maclen in any case. + */ + rec->data_len -= transform->maclen; + ssl_extract_add_data_from_record( add_data, &add_data_len, rec, + transform->minor_ver, + transform->taglen ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * The next two sizes are the minimum and maximum values of + * data_len over all padlen values. + * + * They're independent of padlen, since we previously did + * data_len -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = rec->data_len + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + ret = mbedtls_ct_hmac( &transform->md_ctx_dec, + add_data, add_data_len, + data, rec->data_len, min_len, max_len, + mac_expect ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ct_hmac", ret ); + goto hmac_failed_etm_disabled; + } + + mbedtls_ct_memcpy_offset( mac_peer, data, + rec->data_len, + min_len, max_len, + transform->maclen ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, transform->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", mac_peer, transform->maclen ); +#endif + + if( mbedtls_ct_memcmp( mac_peer, mac_expect, + transform->maclen ) != 0 ) + { +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "message mac does not match" ) ); +#endif + correct = 0; + } + auth_done++; + + hmac_failed_etm_disabled: + mbedtls_platform_zeroize( mac_peer, transform->maclen ); + mbedtls_platform_zeroize( mac_expect, transform->maclen ); + if( ret != 0 ) + return( ret ); + } + + /* + * Finally check the correct flag + */ + if( correct == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_MAC ); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + /* Make extra sure authentication was performed, exactly once */ + if( auth_done != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( transform->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + /* Remove inner padding and infer true content type. */ + ret = ssl_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( rec->cid_len != 0 ) + { + ret = ssl_parse_inner_plaintext( data, &rec->data_len, + &rec->type ); + if( ret != 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= decrypt buf" ) ); + + return( 0 ); +} + +#undef MAC_NONE +#undef MAC_PLAINTEXT +#undef MAC_CIPHERTEXT + +/* + * Fill the input message buffer by appending data to it. + * The amount of data already fetched is in ssl->in_left. + * + * If we return 0, is it guaranteed that (at least) nb_want bytes are + * available (from this read and/or a previous one). Otherwise, an error code + * is returned (possibly EOF or WANT_READ). + * + * With stream transport (TLS) on success ssl->in_left == nb_want, but + * with datagram transport (DTLS) on success ssl->in_left >= nb_want, + * since we always read a whole datagram at once. + * + * For DTLS, it is up to the caller to set ssl->next_record_offset when + * they're done reading a record. + */ +int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> fetch input" ) ); + + if( ssl->f_recv == NULL && ssl->f_recv_timeout == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( nb_want > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "requesting more data than fits" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + uint32_t timeout; + + /* + * The point is, we need to always read a full datagram at once, so we + * sometimes read more then requested, and handle the additional data. + * It could be the rest of the current record (while fetching the + * header) and/or some other records in the same datagram. + */ + + /* + * Move to the next record in the already read datagram if applicable + */ + if( ssl->next_record_offset != 0 ) + { + if( ssl->in_left < ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left -= ssl->next_record_offset; + + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "next record in same datagram, offset: %" + MBEDTLS_PRINTF_SIZET, + ssl->next_record_offset ) ); + memmove( ssl->in_hdr, + ssl->in_hdr + ssl->next_record_offset, + ssl->in_left ); + } + + ssl->next_record_offset = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET + ", nb_want: %" MBEDTLS_PRINTF_SIZET, + ssl->in_left, nb_want ) ); + + /* + * Done if we already have enough data. + */ + if( nb_want <= ssl->in_left) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + return( 0 ); + } + + /* + * A record can't be split across datagrams. If we need to read but + * are not at the beginning of a new record, the caller did something + * wrong. + */ + if( ssl->in_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Don't even try to read if time's out already. + * This avoids by-passing the timer when repeatedly receiving messages + * that will end up being dropped. + */ + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) ); + ret = MBEDTLS_ERR_SSL_TIMEOUT; + } + else + { + len = in_buf_len - ( ssl->in_hdr - ssl->in_buf ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + timeout = ssl->handshake->retransmit_timeout; + else + timeout = ssl->conf->read_timeout; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "f_recv_timeout: %lu ms", (unsigned long) timeout ) ); + + if( ssl->f_recv_timeout != NULL ) + ret = ssl->f_recv_timeout( ssl->p_bio, ssl->in_hdr, len, + timeout ); + else + ret = ssl->f_recv( ssl->p_bio, ssl->in_hdr, len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + } + + if( ret == MBEDTLS_ERR_SSL_TIMEOUT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "timeout" ) ); + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ssl_double_retransmit_timeout( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake timeout" ) ); + return( MBEDTLS_ERR_SSL_TIMEOUT ); + } + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_WANT_READ ); + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + } + + if( ret < 0 ) + return( ret ); + + ssl->in_left = ret; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET + ", nb_want: %" MBEDTLS_PRINTF_SIZET, + ssl->in_left, nb_want ) ); + + while( ssl->in_left < nb_want ) + { + len = nb_want - ssl->in_left; + + if( mbedtls_ssl_check_timer( ssl ) != 0 ) + ret = MBEDTLS_ERR_SSL_TIMEOUT; + else + { + if( ssl->f_recv_timeout != NULL ) + { + ret = ssl->f_recv_timeout( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len, + ssl->conf->read_timeout ); + } + else + { + ret = ssl->f_recv( ssl->p_bio, + ssl->in_hdr + ssl->in_left, len ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "in_left: %" MBEDTLS_PRINTF_SIZET + ", nb_want: %" MBEDTLS_PRINTF_SIZET, + ssl->in_left, nb_want ) ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_recv(_timeout)", ret ); + + if( ret == 0 ) + return( MBEDTLS_ERR_SSL_CONN_EOF ); + + if( ret < 0 ) + return( ret ); + + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " were requested", + ret, len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->in_left += ret; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= fetch input" ) ); + + return( 0 ); +} + +/* + * Flush any data not yet written + */ +int mbedtls_ssl_flush_output( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> flush output" ) ); + + if( ssl->f_send == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Bad usage of mbedtls_ssl_set_bio() " + "or mbedtls_ssl_set_bio()" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Avoid incrementing counter if data is flushed */ + if( ssl->out_left == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + return( 0 ); + } + + while( ssl->out_left > 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message length: %" MBEDTLS_PRINTF_SIZET + ", out_left: %" MBEDTLS_PRINTF_SIZET, + mbedtls_ssl_out_hdr_len( ssl ) + ssl->out_msglen, ssl->out_left ) ); + + buf = ssl->out_hdr - ssl->out_left; + ret = ssl->f_send( ssl->p_bio, buf, ssl->out_left ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", ret ); + + if( ret <= 0 ) + return( ret ); + + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %" MBEDTLS_PRINTF_SIZET " bytes were sent", + ret, ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ssl->out_left -= ret; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + } + else +#endif + { + ssl->out_hdr = ssl->out_buf + 8; + } + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= flush output" ) ); + + return( 0 ); +} + +/* + * Functions to handle the DTLS retransmission state machine + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) +/* + * Append current handshake message to current outgoing flight + */ +static int ssl_flight_append( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_flight_item *msg; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_flight_append" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message appended to flight", + ssl->out_msg, ssl->out_msglen ); + + /* Allocate space for current message */ + if( ( msg = mbedtls_calloc( 1, sizeof( mbedtls_ssl_flight_item ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", + sizeof( mbedtls_ssl_flight_item ) ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + if( ( msg->p = mbedtls_calloc( 1, ssl->out_msglen ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc %" MBEDTLS_PRINTF_SIZET " bytes failed", + ssl->out_msglen ) ); + mbedtls_free( msg ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Copy current handshake message with headers */ + memcpy( msg->p, ssl->out_msg, ssl->out_msglen ); + msg->len = ssl->out_msglen; + msg->type = ssl->out_msgtype; + msg->next = NULL; + + /* Append to the current flight */ + if( ssl->handshake->flight == NULL ) + ssl->handshake->flight = msg; + else + { + mbedtls_ssl_flight_item *cur = ssl->handshake->flight; + while( cur->next != NULL ) + cur = cur->next; + cur->next = msg; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_flight_append" ) ); + return( 0 ); +} + +/* + * Free the current flight of handshake messages + */ +void mbedtls_ssl_flight_free( mbedtls_ssl_flight_item *flight ) +{ + mbedtls_ssl_flight_item *cur = flight; + mbedtls_ssl_flight_item *next; + + while( cur != NULL ) + { + next = cur->next; + + mbedtls_free( cur->p ); + mbedtls_free( cur ); + + cur = next; + } +} + +/* + * Swap transform_out and out_ctr with the alternative ones + */ +static int ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "swap epochs" ) ); + + /* Swap transforms */ + tmp_transform = ssl->transform_out; + ssl->transform_out = ssl->handshake->alt_transform_out; + ssl->handshake->alt_transform_out = tmp_transform; + + /* Swap epoch + sequence_number */ + memcpy( tmp_out_ctr, ssl->cur_out_ctr, sizeof( tmp_out_ctr ) ); + memcpy( ssl->cur_out_ctr, ssl->handshake->alt_out_ctr, + sizeof( ssl->cur_out_ctr ) ); + memcpy( ssl->handshake->alt_out_ctr, tmp_out_ctr, + sizeof( ssl->handshake->alt_out_ctr ) ); + + /* Adjust to the newly activated transform */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + return( 0 ); +} + +/* + * Retransmit the current flight of messages. + */ +int mbedtls_ssl_resend( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_resend" ) ); + + ret = mbedtls_ssl_flight_transmit( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_resend" ) ); + + return( ret ); +} + +/* + * Transmit or retransmit the current flight of messages. + * + * Need to remember the current message in case flush_output returns + * WANT_WRITE, causing us to exit this function and come back later. + * This function must be called until state is no longer SENDING. + */ +int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_flight_transmit" ) ); + + if( ssl->handshake->retransmit_state != MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialise flight transmission" ) ); + + ssl->handshake->cur_msg = ssl->handshake->flight; + ssl->handshake->cur_msg_p = ssl->handshake->flight->p + 12; + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + size_t max_frag_len; + const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + + int const is_finished = + ( cur->type == MBEDTLS_SSL_MSG_HANDSHAKE && + cur->p[0] == MBEDTLS_SSL_HS_FINISHED ); + + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + + /* Swap epochs before sending Finished: we can't do it after + * sending ChangeCipherSpec, in case write returns WANT_READ. + * Must be done before copying, may change out_msg pointer */ + if( is_finished && ssl->handshake->cur_msg_p == ( cur->p + 12 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "swap epochs to send finished message" ) ); + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + max_frag_len = (size_t) ret; + + /* CCS is copied as is, while HS messages may need fragmentation */ + if( cur->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( max_frag_len == 0 ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + + memcpy( ssl->out_msg, cur->p, cur->len ); + ssl->out_msglen = cur->len; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur->len; + } + else + { + const unsigned char * const p = ssl->handshake->cur_msg_p; + const size_t hs_len = cur->len - 12; + const size_t frag_off = p - ( cur->p + 12 ); + const size_t rem_len = hs_len - frag_off; + size_t cur_hs_frag_len, max_hs_frag_len; + + if( ( max_frag_len < 12 ) || ( max_frag_len == 12 && hs_len != 0 ) ) + { + if( is_finished ) + { + ret = ssl_swap_epochs( ssl ); + if( ret != 0 ) + return( ret ); + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + continue; + } + max_hs_frag_len = max_frag_len - 12; + + cur_hs_frag_len = rem_len > max_hs_frag_len ? + max_hs_frag_len : rem_len; + + if( frag_off == 0 && cur_hs_frag_len != hs_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "fragmenting handshake message (%u > %u)", + (unsigned) cur_hs_frag_len, + (unsigned) max_hs_frag_len ) ); + } + + /* Messages are stored with handshake headers as if not fragmented, + * copy beginning of headers then fill fragmentation fields. + * Handshake headers: type(1) len(3) seq(2) f_off(3) f_len(3) */ + memcpy( ssl->out_msg, cur->p, 6 ); + + ssl->out_msg[6] = MBEDTLS_BYTE_2( frag_off ); + ssl->out_msg[7] = MBEDTLS_BYTE_1( frag_off ); + ssl->out_msg[8] = MBEDTLS_BYTE_0( frag_off ); + + ssl->out_msg[ 9] = MBEDTLS_BYTE_2( cur_hs_frag_len ); + ssl->out_msg[10] = MBEDTLS_BYTE_1( cur_hs_frag_len ); + ssl->out_msg[11] = MBEDTLS_BYTE_0( cur_hs_frag_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake header", ssl->out_msg, 12 ); + + /* Copy the handshake message content and set records fields */ + memcpy( ssl->out_msg + 12, p, cur_hs_frag_len ); + ssl->out_msglen = cur_hs_frag_len + 12; + ssl->out_msgtype = cur->type; + + /* Update position inside current message */ + ssl->handshake->cur_msg_p += cur_hs_frag_len; + } + + /* If done with the current message move to the next one if any */ + if( ssl->handshake->cur_msg_p >= cur->p + cur->len ) + { + if( cur->next != NULL ) + { + ssl->handshake->cur_msg = cur->next; + ssl->handshake->cur_msg_p = cur->next->p + 12; + } + else + { + ssl->handshake->cur_msg = NULL; + ssl->handshake->cur_msg_p = NULL; + } + } + + /* Actually send the message out */ + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + /* Update state and set timer */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + else + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_flight_transmit" ) ); + + return( 0 ); +} + +/* + * To be called when the last message of an incoming flight is received. + */ +void mbedtls_ssl_recv_flight_completed( mbedtls_ssl_context *ssl ) +{ + /* We won't need to resend that one any more */ + mbedtls_ssl_flight_free( ssl->handshake->flight ); + ssl->handshake->flight = NULL; + ssl->handshake->cur_msg = NULL; + + /* The next incoming flight will start with this msg_seq */ + ssl->handshake->in_flight_start_seq = ssl->handshake->in_msg_seq; + + /* We don't want to remember CCS's across flight boundaries. */ + ssl->handshake->buffering.seen_ccs = 0; + + /* Clear future message buffering structure. */ + mbedtls_ssl_buffering_free( ssl ); + + /* Cancel timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; +} + +/* + * To be called when the last message of an outgoing flight is send. + */ +void mbedtls_ssl_send_flight_completed( mbedtls_ssl_context *ssl ) +{ + ssl_reset_retransmit_timeout( ssl ); + mbedtls_ssl_set_timer( ssl, ssl->handshake->retransmit_timeout ); + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED ) + { + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_FINISHED; + } + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Handshake layer functions + */ + +/* + * Write (DTLS: or queue) current handshake (including CCS) message. + * + * - fill in handshake headers + * - update handshake checksum + * - DTLS: save message for resending + * - then pass to the record layer + * + * DTLS: except for HelloRequest, messages are only queued, and will only be + * actually sent when calling flight_transmit() or resend(). + * + * Inputs: + * - ssl->out_msglen: 4 + actual handshake message len + * (4 is the size of handshake headers for TLS) + * - ssl->out_msg[0]: the handshake type (ClientHello, ServerHello, etc) + * - ssl->out_msg + 4: the handshake message body + * + * Outputs, ie state before passing to flight_append() or write_record(): + * - ssl->out_msglen: the length of the record contents + * (including handshake headers but excluding record headers) + * - ssl->out_msg: the record contents (handshake headers + content) + */ +int mbedtls_ssl_write_handshake_msg_ext( mbedtls_ssl_context *ssl, + int update_checksum ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t hs_len = ssl->out_msglen - 4; + const unsigned char hs_type = ssl->out_msg[0]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write handshake message" ) ); + + /* + * Sanity checks + */ + if( ssl->out_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->out_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Whenever we send anything different from a + * HelloRequest we should be in a handshake - double check. */ + if( ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) && + ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif + + /* Double-check that we did not exceed the bounds + * of the outgoing record buffer. + * This should never fail as the various message + * writing functions must obey the bounds of the + * outgoing record buffer, but better be safe. + * + * Note: We deliberately do not check for the MTU or MFL here. + */ + if( ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Record too large: " + "size %" MBEDTLS_PRINTF_SIZET + ", maximum %" MBEDTLS_PRINTF_SIZET, + ssl->out_msglen, + (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Fill handshake headers + */ + if( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ssl->out_msg[1] = MBEDTLS_BYTE_2( hs_len ); + ssl->out_msg[2] = MBEDTLS_BYTE_1( hs_len ); + ssl->out_msg[3] = MBEDTLS_BYTE_0( hs_len ); + + /* + * DTLS has additional fields in the Handshake layer, + * between the length field and the actual payload: + * uint16 message_seq; + * uint24 fragment_offset; + * uint24 fragment_length; + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Make room for the additional DTLS fields */ + if( MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS handshake message too large: " + "size %" MBEDTLS_PRINTF_SIZET ", maximum %" MBEDTLS_PRINTF_SIZET, + hs_len, + (size_t) ( MBEDTLS_SSL_OUT_CONTENT_LEN - 12 ) ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memmove( ssl->out_msg + 12, ssl->out_msg + 4, hs_len ); + ssl->out_msglen += 8; + + /* Write message_seq and update it, except for HelloRequest */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST ) + { + MBEDTLS_PUT_UINT16_BE( ssl->handshake->out_msg_seq, ssl->out_msg, 4 ); + ++( ssl->handshake->out_msg_seq ); + } + else + { + ssl->out_msg[4] = 0; + ssl->out_msg[5] = 0; + } + + /* Handshake hashes are computed without fragmentation, + * so set frag_offset = 0 and frag_len = hs_len for now */ + memset( ssl->out_msg + 6, 0x00, 3 ); + memcpy( ssl->out_msg + 9, ssl->out_msg + 1, 3 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Update running hashes of handshake messages seen */ + if( hs_type != MBEDTLS_SSL_HS_HELLO_REQUEST && update_checksum != 0 ) + ssl->handshake->update_checksum( ssl, ssl->out_msg, ssl->out_msglen ); + } + + /* Either send now, or just save to be sent (and resent) later */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ! ( ssl->out_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + hs_type == MBEDTLS_SSL_HS_HELLO_REQUEST ) ) + { + if( ( ret = ssl_flight_append( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_flight_append", ret ); + return( ret ); + } + } + else +#endif + { + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_record", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write handshake message" ) ); + + return( 0 ); +} + +/* + * Record layer functions + */ + +/* + * Write current record. + * + * Uses: + * - ssl->out_msgtype: type of the message (AppData, Handshake, Alert, CCS) + * - ssl->out_msglen: length of the record content (excl headers) + * - ssl->out_msg: record content + */ +int mbedtls_ssl_write_record( mbedtls_ssl_context *ssl, uint8_t force_flush ) +{ + int ret, done = 0; + size_t len = ssl->out_msglen; + uint8_t flush = force_flush; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write record" ) ); + + if( !done ) + { + unsigned i; + size_t protected_record_size; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + /* Skip writing the record content type to after the encryption, + * as it may change when using the CID extension. */ + int minor_ver = ssl->minor_ver; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* TLS 1.3 still uses the TLS 1.2 version identifier + * for backwards compatibility. */ + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + mbedtls_ssl_write_version( ssl->major_ver, minor_ver, + ssl->conf->transport, ssl->out_hdr + 1 ); + + memcpy( ssl->out_ctr, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ); + MBEDTLS_PUT_UINT16_BE( len, ssl->out_len, 0); + + if( ssl->transform_out != NULL ) + { + mbedtls_record rec; + + rec.buf = ssl->out_iv; + rec.buf_len = out_buf_len - ( ssl->out_iv - ssl->out_buf ); + rec.data_len = ssl->out_msglen; + rec.data_offset = ssl->out_msg - rec.buf; + + memcpy( &rec.ctr[0], ssl->out_ctr, sizeof( rec.ctr ) ); + mbedtls_ssl_write_version( ssl->major_ver, minor_ver, + ssl->conf->transport, rec.ver ); + rec.type = ssl->out_msgtype; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* The CID is set by mbedtls_ssl_encrypt_buf(). */ + rec.cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( ( ret = mbedtls_ssl_encrypt_buf( ssl, ssl->transform_out, &rec, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_encrypt_buf", ret ); + return( ret ); + } + + if( rec.data_offset != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Update the record content type and CID. */ + ssl->out_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID ) + memcpy( ssl->out_cid, rec.cid, rec.cid_len ); +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_msglen = len = rec.data_len; + MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->out_len, 0 ); + } + + protected_record_size = len + mbedtls_ssl_out_hdr_len( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* In case of DTLS, double-check that we don't exceed + * the remaining space in the datagram. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ret = ssl_get_remaining_space_in_datagram( ssl ); + if( ret < 0 ) + return( ret ); + + if( protected_record_size > (size_t) ret ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Now write the potentially updated record content type. */ + ssl->out_hdr[0] = (unsigned char) ssl->out_msgtype; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "output record: msgtype = %u, " + "version = [%u:%u], msglen = %" MBEDTLS_PRINTF_SIZET, + ssl->out_hdr[0], ssl->out_hdr[1], + ssl->out_hdr[2], len ) ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_hdr, protected_record_size ); + + ssl->out_left += protected_record_size; + ssl->out_hdr += protected_record_size; + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_out ); + + for( i = 8; i > mbedtls_ssl_ep_len( ssl ); i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "outgoing message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + flush == SSL_DONT_FORCE_FLUSH ) + { + size_t remaining; + ret = ssl_get_remaining_payload_in_datagram( ssl ); + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_get_remaining_payload_in_datagram", + ret ); + return( ret ); + } + + remaining = (size_t) ret; + if( remaining == 0 ) + { + flush = SSL_FORCE_FLUSH; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Still %u bytes available in current datagram", (unsigned) remaining ) ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( ( flush == SSL_FORCE_FLUSH ) && + ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static int ssl_hs_is_proper_fragment( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < ssl->in_hslen || + memcmp( ssl->in_msg + 6, "\0\0\0", 3 ) != 0 || + memcmp( ssl->in_msg + 9, ssl->in_msg + 1, 3 ) != 0 ) + { + return( 1 ); + } + return( 0 ); +} + +static uint32_t ssl_get_hs_frag_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[9] << 16 ) | + ( ssl->in_msg[10] << 8 ) | + ssl->in_msg[11] ); +} + +static uint32_t ssl_get_hs_frag_off( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[6] << 16 ) | + ( ssl->in_msg[7] << 8 ) | + ssl->in_msg[8] ); +} + +static int ssl_check_hs_header( mbedtls_ssl_context const *ssl ) +{ + uint32_t msg_len, frag_off, frag_len; + + msg_len = ssl_get_hs_total_len( ssl ); + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + if( frag_off > msg_len ) + return( -1 ); + + if( frag_len > msg_len - frag_off ) + return( -1 ); + + if( frag_len + 12 > ssl->in_msglen ) + return( -1 ); + + return( 0 ); +} + +/* + * Mark bits in bitmask (used for DTLS HS reassembly) + */ +static void ssl_bitmask_set( unsigned char *mask, size_t offset, size_t len ) +{ + unsigned int start_bits, end_bits; + + start_bits = 8 - ( offset % 8 ); + if( start_bits != 8 ) + { + size_t first_byte_idx = offset / 8; + + /* Special case */ + if( len <= start_bits ) + { + for( ; len != 0; len-- ) + mask[first_byte_idx] |= 1 << ( start_bits - len ); + + /* Avoid potential issues with offset or len becoming invalid */ + return; + } + + offset += start_bits; /* Now offset % 8 == 0 */ + len -= start_bits; + + for( ; start_bits != 0; start_bits-- ) + mask[first_byte_idx] |= 1 << ( start_bits - 1 ); + } + + end_bits = len % 8; + if( end_bits != 0 ) + { + size_t last_byte_idx = ( offset + len ) / 8; + + len -= end_bits; /* Now len % 8 == 0 */ + + for( ; end_bits != 0; end_bits-- ) + mask[last_byte_idx] |= 1 << ( 8 - end_bits ); + } + + memset( mask + offset / 8, 0xFF, len / 8 ); +} + +/* + * Check that bitmask is full + */ +static int ssl_bitmask_check( unsigned char *mask, size_t len ) +{ + size_t i; + + for( i = 0; i < len / 8; i++ ) + if( mask[i] != 0xFF ) + return( -1 ); + + for( i = 0; i < len % 8; i++ ) + if( ( mask[len / 8] & ( 1 << ( 7 - i ) ) ) == 0 ) + return( -1 ); + + return( 0 ); +} + +/* msg_len does not include the handshake header */ +static size_t ssl_get_reassembly_buffer_size( size_t msg_len, + unsigned add_bitmap ) +{ + size_t alloc_len; + + alloc_len = 12; /* Handshake header */ + alloc_len += msg_len; /* Content buffer */ + + if( add_bitmap ) + alloc_len += msg_len / 8 + ( msg_len % 8 != 0 ); /* Bitmap */ + + return( alloc_len ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static uint32_t ssl_get_hs_total_len( mbedtls_ssl_context const *ssl ) +{ + return( ( ssl->in_msg[1] << 16 ) | + ( ssl->in_msg[2] << 8 ) | + ssl->in_msg[3] ); +} + +int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake message too short: %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + ssl->in_hslen = mbedtls_ssl_hs_hdr_len( ssl ) + ssl_get_hs_total_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "handshake message: msglen =" + " %" MBEDTLS_PRINTF_SIZET ", type = %u, hslen = %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen, ssl->in_msg[0], ssl->in_hslen ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + + if( ssl_check_hs_header( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid handshake header" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->handshake != NULL && + ( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && + recv_msg_seq != ssl->handshake->in_msg_seq ) || + ( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) ) + { + if( recv_msg_seq > ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received future handshake message of sequence number %u (next %u)", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + /* Retransmit only on last message from previous flight, to avoid + * too many retransmissions. + * Besides, No sane server ever retransmits HelloVerifyRequest */ + if( recv_msg_seq == ssl->handshake->in_flight_start_seq - 1 && + ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received message from last flight, " + "message_seq = %u, start_of_flight = %u", + recv_msg_seq, + ssl->handshake->in_flight_start_seq ) ); + + if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret ); + return( ret ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "dropping out-of-sequence message: " + "message_seq = %u, expected = %u", + recv_msg_seq, + ssl->handshake->in_msg_seq ) ); + } + + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + /* Wait until message completion to increment in_msg_seq */ + + /* Message reassembly is handled alongside buffering of future + * messages; the commonality is that both handshake fragments and + * future messages cannot be forwarded immediately to the + * handshake logic layer. */ + if( ssl_hs_is_proper_fragment( ssl ) == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "found fragmented DTLS handshake message" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* With TLS we don't handle fragmentation (for now) */ + if( ssl->in_msglen < ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLS handshake fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} + +void mbedtls_ssl_update_handshake_status( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER && hs != NULL ) + { + ssl->handshake->update_checksum( ssl, ssl->in_msg, ssl->in_hslen ); + } + + /* Handshake message is complete, increment counter */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake != NULL ) + { + unsigned offset; + mbedtls_ssl_hs_buffer *hs_buf; + + /* Increment handshake sequence number */ + hs->in_msg_seq++; + + /* + * Clear up handshake buffering and reassembly structure. + */ + + /* Free first entry */ + ssl_buffering_free_slot( ssl, 0 ); + + /* Shift all other entries */ + for( offset = 0, hs_buf = &hs->buffering.hs[0]; + offset + 1 < MBEDTLS_SSL_MAX_BUFFERED_HS; + offset++, hs_buf++ ) + { + *hs_buf = *(hs_buf + 1); + } + + /* Create a fresh last entry */ + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +#endif +} + +/* + * DTLS anti-replay: RFC 6347 4.1.2.6 + * + * in_window is a field of bits numbered from 0 (lsb) to 63 (msb). + * Bit n is set iff record number in_window_top - n has been seen. + * + * Usually, in_window_top is the last record number seen and the lsb of + * in_window is set. The only exception is the initial state (record number 0 + * not seen yet). + */ +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_dtls_replay_reset( mbedtls_ssl_context *ssl ) +{ + ssl->in_window_top = 0; + ssl->in_window = 0; +} + +static inline uint64_t ssl_load_six_bytes( unsigned char *buf ) +{ + return( ( (uint64_t) buf[0] << 40 ) | + ( (uint64_t) buf[1] << 32 ) | + ( (uint64_t) buf[2] << 24 ) | + ( (uint64_t) buf[3] << 16 ) | + ( (uint64_t) buf[4] << 8 ) | + ( (uint64_t) buf[5] ) ); +} + +static int mbedtls_ssl_dtls_record_replay_check( mbedtls_ssl_context *ssl, uint8_t *record_in_ctr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *original_in_ctr; + + // save original in_ctr + original_in_ctr = ssl->in_ctr; + + // use counter from record + ssl->in_ctr = record_in_ctr; + + ret = mbedtls_ssl_dtls_replay_check( (mbedtls_ssl_context const *) ssl ); + + // restore the counter + ssl->in_ctr = original_in_ctr; + + return ret; +} + +/* + * Return 0 if sequence number is acceptable, -1 otherwise + */ +int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + uint64_t bit; + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return( 0 ); + + if( rec_seqnum > ssl->in_window_top ) + return( 0 ); + + bit = ssl->in_window_top - rec_seqnum; + + if( bit >= 64 ) + return( -1 ); + + if( ( ssl->in_window & ( (uint64_t) 1 << bit ) ) != 0 ) + return( -1 ); + + return( 0 ); +} + +/* + * Update replay window on new validated record + */ +void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl ) +{ + uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 ); + + if( ssl->conf->anti_replay == MBEDTLS_SSL_ANTI_REPLAY_DISABLED ) + return; + + if( rec_seqnum > ssl->in_window_top ) + { + /* Update window_top and the contents of the window */ + uint64_t shift = rec_seqnum - ssl->in_window_top; + + if( shift >= 64 ) + ssl->in_window = 1; + else + { + ssl->in_window <<= shift; + ssl->in_window |= 1; + } + + ssl->in_window_top = rec_seqnum; + } + else + { + /* Mark that number as seen in the current window */ + uint64_t bit = ssl->in_window_top - rec_seqnum; + + if( bit < 64 ) /* Always true, but be extra sure */ + ssl->in_window |= (uint64_t) 1 << bit; + } +} +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +/* + * Without any SSL context, check if a datagram looks like a ClientHello with + * a valid cookie, and if it doesn't, generate a HelloVerifyRequest message. + * Both input and output include full DTLS headers. + * + * - if cookie is valid, return 0 + * - if ClientHello looks superficially valid but cookie is not, + * fill obuf and set olen, then + * return MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED + * - otherwise return a specific error code + */ +static int ssl_check_dtls_clihlo_cookie( + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie, + const unsigned char *cli_id, size_t cli_id_len, + const unsigned char *in, size_t in_len, + unsigned char *obuf, size_t buf_len, size_t *olen ) +{ + size_t sid_len, cookie_len; + unsigned char *p; + + /* + * Structure of ClientHello with record and handshake headers, + * and expected values. We don't need to check a lot, more checks will be + * done when actually parsing the ClientHello - skipping those checks + * avoids code duplication and does not make cookie forging any easier. + * + * 0-0 ContentType type; copied, must be handshake + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied, must be 0 + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; (ignored) + * + * 13-13 HandshakeType msg_type; (ignored) + * 14-16 uint24 length; (ignored) + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied, must be 0 + * 22-24 uint24 fragment_length; (ignored) + * + * 25-26 ProtocolVersion client_version; (ignored) + * 27-58 Random random; (ignored) + * 59-xx SessionID session_id; 1 byte len + sid_len content + * 60+ opaque cookie<0..2^8-1>; 1 byte len + content + * ... + * + * Minimum length is 61 bytes. + */ + if( in_len < 61 || + in[0] != MBEDTLS_SSL_MSG_HANDSHAKE || + in[3] != 0 || in[4] != 0 || + in[19] != 0 || in[20] != 0 || in[21] != 0 ) + { + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + sid_len = in[59]; + if( sid_len > in_len - 61 ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + cookie_len = in[60 + sid_len]; + if( cookie_len > in_len - 60 ) + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + + if( f_cookie_check( p_cookie, in + sid_len + 61, cookie_len, + cli_id, cli_id_len ) == 0 ) + { + /* Valid cookie */ + return( 0 ); + } + + /* + * If we get here, we've got an invalid cookie, let's prepare HVR. + * + * 0-0 ContentType type; copied + * 1-2 ProtocolVersion version; copied + * 3-4 uint16 epoch; copied + * 5-10 uint48 sequence_number; copied + * 11-12 uint16 length; olen - 13 + * + * 13-13 HandshakeType msg_type; hello_verify_request + * 14-16 uint24 length; olen - 25 + * 17-18 uint16 message_seq; copied + * 19-21 uint24 fragment_offset; copied + * 22-24 uint24 fragment_length; olen - 25 + * + * 25-26 ProtocolVersion server_version; 0xfe 0xff + * 27-27 opaque cookie<0..2^8-1>; cookie_len = olen - 27, cookie + * + * Minimum length is 28. + */ + if( buf_len < 28 ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + /* Copy most fields and adapt others */ + memcpy( obuf, in, 25 ); + obuf[13] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + obuf[25] = 0xfe; + obuf[26] = 0xff; + + /* Generate and write actual cookie */ + p = obuf + 28; + if( f_cookie_write( p_cookie, + &p, obuf + buf_len, cli_id, cli_id_len ) != 0 ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + *olen = p - obuf; + + /* Go back and fill length fields */ + obuf[27] = (unsigned char)( *olen - 28 ); + + obuf[14] = obuf[22] = MBEDTLS_BYTE_2( *olen - 25 ); + obuf[15] = obuf[23] = MBEDTLS_BYTE_1( *olen - 25 ); + obuf[16] = obuf[24] = MBEDTLS_BYTE_0( *olen - 25 ); + + MBEDTLS_PUT_UINT16_BE( *olen - 13, obuf, 11 ); + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +} + +/* + * Handle possible client reconnect with the same UDP quadruplet + * (RFC 6347 Section 4.2.8). + * + * Called by ssl_parse_record_header() in case we receive an epoch 0 record + * that looks like a ClientHello. + * + * - if the input looks like a ClientHello without cookies, + * send back HelloVerifyRequest, then return 0 + * - if the input looks like a ClientHello with a valid cookie, + * reset the session of the current context, and + * return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * - if anything goes wrong, return a specific error code + * + * This function is called (through ssl_check_client_reconnect()) when an + * unexpected record is found in ssl_get_next_record(), which will discard the + * record if we return 0, and bubble up the return value otherwise (this + * includes the case of MBEDTLS_ERR_SSL_CLIENT_RECONNECT and of unexpected + * errors, and is the right thing to do in both cases). + */ +static int ssl_handle_possible_reconnect( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ssl->conf->f_cookie_write == NULL || + ssl->conf->f_cookie_check == NULL ) + { + /* If we can't use cookies to verify reachability of the peer, + * drop the record. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no cookie callbacks, " + "can't check reconnect validity" ) ); + return( 0 ); + } + + ret = ssl_check_dtls_clihlo_cookie( + ssl->conf->f_cookie_write, + ssl->conf->f_cookie_check, + ssl->conf->p_cookie, + ssl->cli_id, ssl->cli_id_len, + ssl->in_buf, ssl->in_left, + ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len ); + + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_dtls_clihlo_cookie", ret ); + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + int send_ret; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_buf, len ); + /* Don't check write errors as we can't do anything here. + * If the error is permanent we'll catch it later, + * if it's not, then hopefully it'll work next time. */ + send_ret = ssl->f_send( ssl->p_bio, ssl->out_buf, len ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); + (void) send_ret; + + return( 0 ); + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting context" ) ); + if( ( ret = mbedtls_ssl_session_reset_int( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "reset", ret ); + return( ret ); + } + + return( MBEDTLS_ERR_SSL_CLIENT_RECONNECT ); + } + + return( ret ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +static int ssl_check_record_type( uint8_t record_type ) +{ + if( record_type != MBEDTLS_SSL_MSG_HANDSHAKE && + record_type != MBEDTLS_SSL_MSG_ALERT && + record_type != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC && + record_type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * ContentType type; + * ProtocolVersion version; + * uint16 epoch; // DTLS only + * uint48 sequence_number; // DTLS only + * uint16 length; + * + * Return 0 if header looks sane (and, for DTLS, the record is expected) + * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad, + * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected. + * + * With DTLS, mbedtls_ssl_read_record() will: + * 1. proceed with the record if this function returns 0 + * 2. drop only the current record if this function returns UNEXPECTED_RECORD + * 3. return CLIENT_RECONNECT if this function return that value + * 4. drop the whole datagram if this function returns anything else. + * Point 2 is needed when the peer is resending, and we have already received + * the first record from a datagram but are still waiting for the others. + */ +static int ssl_parse_record_header( mbedtls_ssl_context const *ssl, + unsigned char *buf, + size_t len, + mbedtls_record *rec ) +{ + int major_ver, minor_ver; + + size_t const rec_hdr_type_offset = 0; + size_t const rec_hdr_type_len = 1; + + size_t const rec_hdr_version_offset = rec_hdr_type_offset + + rec_hdr_type_len; + size_t const rec_hdr_version_len = 2; + + size_t const rec_hdr_ctr_len = 8; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint32_t rec_epoch; + size_t const rec_hdr_ctr_offset = rec_hdr_version_offset + + rec_hdr_version_len; + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset + + rec_hdr_ctr_len; + size_t rec_hdr_cid_len = 0; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + size_t rec_hdr_len_offset; /* To be determined */ + size_t const rec_hdr_len_len = 2; + + /* + * Check minimum lengths for record header. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len; + } + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse and validate record content type + */ + + rec->type = buf[ rec_hdr_type_offset ]; + + /* Check record content type */ +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + rec->cid_len = 0; + + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->cid_len != 0 && + rec->type == MBEDTLS_SSL_MSG_CID ) + { + /* Shift pointers to account for record header including CID + * struct { + * ContentType special_type = tls12_cid; + * ProtocolVersion version; + * uint16 epoch; + * uint48 sequence_number; + * opaque cid[cid_length]; // Additional field compared to + * // default DTLS record format + * uint16 length; + * opaque enc_content[DTLSCiphertext.length]; + * } DTLSCiphertext; + */ + + /* So far, we only support static CID lengths + * fixed in the configuration. */ + rec_hdr_cid_len = ssl->conf->cid_len; + rec_hdr_len_offset += rec_hdr_cid_len; + + if( len < rec_hdr_len_offset + rec_hdr_len_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u", + (unsigned) len, + (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* configured CID len is guaranteed at most 255, see + * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */ + rec->cid_len = (uint8_t) rec_hdr_cid_len; + memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len ); + } + else +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + { + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u", + (unsigned) rec->type ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + } + + /* + * Parse and validate record version + */ + + rec->ver[0] = buf[ rec_hdr_version_offset + 0 ]; + rec->ver[1] = buf[ rec_hdr_version_offset + 1 ]; + mbedtls_ssl_read_version( &major_ver, &minor_ver, + ssl->conf->transport, + &rec->ver[0] ); + + if( major_ver != ssl->major_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( minor_ver > ssl->conf->max_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* + * Parse/Copy record sequence number. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Copy explicit record sequence number from input buffer. */ + memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset, + rec_hdr_ctr_len ); + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + /* Copy implicit record sequence number from SSL context structure. */ + memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len ); + } + + /* + * Parse record length. + */ + + rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len; + rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) | + ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %u, " + "version = [%d:%d], msglen = %" MBEDTLS_PRINTF_SIZET, + rec->type, + major_ver, minor_ver, rec->data_len ) ); + + rec->buf = buf; + rec->buf_len = rec->data_offset + rec->data_len; + + if( rec->data_len == 0 ) + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + + /* + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1]; + + /* Check that the datagram is large enough to contain a record + * of the advertised length. */ + if( len < rec->data_offset + rec->data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.", + (unsigned) len, + (unsigned)( rec->data_offset + rec->data_len ) ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + /* Records from other, non-matching epochs are silently discarded. + * (The case of same-port Client reconnects must be considered in + * the caller). */ + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: " + "expected %u, received %lu", + ssl->in_epoch, (unsigned long) rec_epoch ) ); + + /* Records from the next epoch are considered for buffering + * (concretely: early Finished messages). */ + if( rec_epoch == (unsigned) ssl->in_epoch + 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } + + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + /* For records from the correct epoch, check whether their + * sequence number has been seen before. */ + else if( mbedtls_ssl_dtls_record_replay_check( (mbedtls_ssl_context *) ssl, + &rec->ctr[0] ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) +static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl ) +{ + unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1]; + + /* + * Check for an epoch 0 ClientHello. We can't use in_msg here to + * access the first byte of record content (handshake type), as we + * have an active transform (possibly iv_len != 0), so use the + * fact that the record header len is 13 instead. + */ + if( rec_epoch == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_left > 13 && + ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect " + "from the same port" ) ); + return( ssl_handle_possible_reconnect( ssl ) ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */ + +/* + * If applicable, decrypt record content + */ +static int ssl_prepare_record_content( mbedtls_ssl_context *ssl, + mbedtls_record *rec ) +{ + int ret, done = 0; + + MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network", + rec->buf, rec->buf_len ); + + /* + * In TLS 1.3, always treat ChangeCipherSpec records + * as unencrypted. The only thing we do with them is + * check the length and content and ignore them. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( ssl->transform_in != NULL && + ssl->transform_in->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + if( rec->type == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + done = 1; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + if( !done && ssl->transform_in != NULL ) + { + unsigned char const old_msg_type = rec->type; + + if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, + rec ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID && + ssl->conf->ignore_unexpected_cid + == MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ignoring unexpected CID" ) ); + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( ret ); + } + + if( old_msg_type != rec->type ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d", + old_msg_type, rec->type ) ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt", + rec->buf + rec->data_offset, rec->data_len ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* We have already checked the record content type + * in ssl_parse_record_header(), failing or silently + * dropping the record in the case of an unknown type. + * + * Since with the use of CIDs, the record content type + * might change during decryption, re-check the record + * content type, but treat a failure as fatal this time. */ + if( ssl_check_record_type( rec->type ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + if( rec->data_len == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + ssl->nb_zero++; + + /* + * Three or more empty messages may be a DoS attack + * (excessive CPU consumption). + */ + if( ssl->nb_zero > 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received four consecutive empty " + "messages, possible DoS attack" ) ); + /* Treat the records as if they were not properly authenticated, + * thereby failing the connection if we see more than allowed + * by the configured bad MAC threshold. */ + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + } + else + ssl->nb_zero = 0; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ; /* in_ctr read from peer, not maintained internally */ + } + else +#endif + { + unsigned i; + for( i = MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + i > mbedtls_ssl_ep_len( ssl ); i-- ) + { + if( ++ssl->in_ctr[i - 1] != 0 ) + break; + } + + /* The loop goes to its end iff the counter is wrapping */ + if( i == mbedtls_ssl_ep_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "incoming message counter would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + mbedtls_ssl_dtls_replay_update( ssl ); + } +#endif + + /* Check actual (decrypted) record content length against + * configured maximum. */ + if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + return( 0 ); +} + +/* + * Read a record. + * + * Silently ignore non-fatal alert (and for DTLS, invalid records as well, + * RFC 6347 4.1.2.7) and continue reading until a valid record is found. + * + */ + +/* Helper functions for mbedtls_ssl_read_record(). */ +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ); +static int ssl_get_next_record( mbedtls_ssl_context *ssl ); +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ); + +int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl, + unsigned update_hs_digest ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read record" ) ); + + if( ssl->keep_current_message == 0 ) + { + do { + + ret = ssl_consume_current_message( ssl ); + if( ret != 0 ) + return( ret ); + + if( ssl_record_is_in_progress( ssl ) == 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + int have_buffered = 0; + + /* We only check for buffered messages if the + * current datagram is fully consumed. */ + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl_next_record_is_in_datagram( ssl ) == 0 ) + { + if( ssl_load_buffered_message( ssl ) == 0 ) + have_buffered = 1; + } + + if( have_buffered == 0 ) +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ret = ssl_get_next_record( ssl ); + if( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ) + continue; + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_get_next_record" ), ret ); + return( ret ); + } + } + } + + ret = mbedtls_ssl_handle_message_type( ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + /* Buffer future message */ + ret = ssl_buffer_message( ssl ); + if( ret != 0 ) + return( ret ); + + ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + } while( MBEDTLS_ERR_SSL_NON_FATAL == ret || + MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret ); + + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret ); + return( ret ); + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + update_hs_digest == 1 ) + { + mbedtls_ssl_update_handshake_status( ssl ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "reuse previously read message" ) ); + ssl->keep_current_message = 0; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read record" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_left > ssl->next_record_offset ) + return( 1 ); + + return( 0 ); +} + +static int ssl_load_buffered_message( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * hs_buf; + int ret = 0; + + if( hs == NULL ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_messsage" ) ); + + if( ssl->state == MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC || + ssl->state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + /* Check if we have seen a ChangeCipherSpec before. + * If yes, synthesize a CCS record. */ + if( !hs->buffering.seen_ccs ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "CCS not seen in the current flight" ) ); + ret = -1; + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Injecting buffered CCS message" ) ); + ssl->in_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->in_msglen = 1; + ssl->in_msg[0] = 1; + + /* As long as they are equal, the exact value doesn't matter. */ + ssl->in_left = 0; + ssl->next_record_offset = 0; + + hs->buffering.seen_ccs = 0; + goto exit; + } + +#if defined(MBEDTLS_DEBUG_C) + /* Debug only */ + { + unsigned offset; + for( offset = 1; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + { + hs_buf = &hs->buffering.hs[offset]; + if( hs_buf->is_valid == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Future message with sequence number %u %s buffered.", + hs->in_msg_seq + offset, + hs_buf->is_complete ? "fully" : "partially" ) ); + } + } + } +#endif /* MBEDTLS_DEBUG_C */ + + /* Check if we have buffered and/or fully reassembled the + * next handshake message. */ + hs_buf = &hs->buffering.hs[0]; + if( ( hs_buf->is_valid == 1 ) && ( hs_buf->is_complete == 1 ) ) + { + /* Synthesize a record containing the buffered HS message. */ + size_t msg_len = ( hs_buf->data[1] << 16 ) | + ( hs_buf->data[2] << 8 ) | + hs_buf->data[3]; + + /* Double-check that we haven't accidentally buffered + * a message that doesn't fit into the input buffer. */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message has been buffered - load" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered handshake message (incl. header)", + hs_buf->data, msg_len + 12 ); + + ssl->in_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->in_hslen = msg_len + 12; + ssl->in_msglen = msg_len + 12; + memcpy( ssl->in_msg, hs_buf->data, ssl->in_hslen ); + + ret = 0; + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Next handshake message %u not or only partially bufffered", + hs->in_msg_seq ) ); + } + + ret = -1; + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_message" ) ); + return( ret ); +} + +static int ssl_buffer_make_space( mbedtls_ssl_context *ssl, + size_t desired ) +{ + int offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Attempt to free buffered messages to have %u bytes available", + (unsigned) desired ) ); + + /* Get rid of future records epoch first, if such exist. */ + ssl_free_buffered_record( ssl ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing future epoch record" ) ); + return( 0 ); + } + + /* We don't have enough space to buffer the next expected handshake + * message. Remove buffers used for future messages to gain space, + * starting with the most distant one. */ + for( offset = MBEDTLS_SSL_MAX_BUFFERED_HS - 1; + offset >= 0; offset-- ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Free buffering slot %d to make space for reassembly of next handshake message", + offset ) ); + + ssl_buffering_free_slot( ssl, (uint8_t) offset ); + + /* Check if we have enough space available now. */ + if( desired <= ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Enough space available after freeing buffered HS messages" ) ); + return( 0 ); + } + } + + return( -1 ); +} + +static int ssl_buffer_message( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_buffer_message" ) ); + + switch( ssl->in_msgtype ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Remember CCS message" ) ); + + hs->buffering.seen_ccs = 1; + break; + + case MBEDTLS_SSL_MSG_HANDSHAKE: + { + unsigned recv_msg_seq_offset; + unsigned recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5]; + mbedtls_ssl_hs_buffer *hs_buf; + size_t msg_len = ssl->in_hslen - 12; + + /* We should never receive an old handshake + * message - double-check nonetheless. */ + if( recv_msg_seq < ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + recv_msg_seq_offset = recv_msg_seq - ssl->handshake->in_msg_seq; + if( recv_msg_seq_offset >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + { + /* Silently ignore -- message too far in the future */ + MBEDTLS_SSL_DEBUG_MSG( 2, + ( "Ignore future HS message with sequence number %u, " + "buffering window %u - %u", + recv_msg_seq, ssl->handshake->in_msg_seq, + ssl->handshake->in_msg_seq + MBEDTLS_SSL_MAX_BUFFERED_HS - 1 ) ); + + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering HS message with sequence number %u, offset %u ", + recv_msg_seq, recv_msg_seq_offset ) ); + + hs_buf = &hs->buffering.hs[ recv_msg_seq_offset ]; + + /* Check if the buffering for this seq nr has already commenced. */ + if( !hs_buf->is_valid ) + { + size_t reassembly_buf_sz; + + hs_buf->is_fragmented = + ( ssl_hs_is_proper_fragment( ssl ) == 1 ); + + /* We copy the message back into the input buffer + * after reassembly, so check that it's not too large. + * This is an implementation-specific limitation + * and not one from the standard, hence it is not + * checked in ssl_check_hs_header(). */ + if( msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + /* Ignore message */ + goto exit; + } + + /* Check if we have enough space to buffer the message. */ + if( hs->buffering.total_bytes_buffered > + MBEDTLS_SSL_DTLS_MAX_BUFFERING ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + reassembly_buf_sz = ssl_get_reassembly_buffer_size( msg_len, + hs_buf->is_fragmented ); + + if( reassembly_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + if( recv_msg_seq_offset > 0 ) + { + /* If we can't buffer a future message because + * of space limitations -- ignore. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET + " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- ignore\n", + msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + goto exit; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future message of size %" MBEDTLS_PRINTF_SIZET + " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- attempt to make space by freeing buffered future messages\n", + msg_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + } + + if( ssl_buffer_make_space( ssl, reassembly_buf_sz ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reassembly of next message of size %" MBEDTLS_PRINTF_SIZET + " (%" MBEDTLS_PRINTF_SIZET " with bitmap) would exceed" + " the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- fail\n", + msg_len, + reassembly_buf_sz, + (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "initialize reassembly, total length = %" MBEDTLS_PRINTF_SIZET, + msg_len ) ); + + hs_buf->data = mbedtls_calloc( 1, reassembly_buf_sz ); + if( hs_buf->data == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + hs_buf->data_len = reassembly_buf_sz; + + /* Prepare final header: copy msg_type, length and message_seq, + * then add standardised fragment_offset and fragment_length */ + memcpy( hs_buf->data, ssl->in_msg, 6 ); + memset( hs_buf->data + 6, 0, 3 ); + memcpy( hs_buf->data + 9, hs_buf->data + 1, 3 ); + + hs_buf->is_valid = 1; + + hs->buffering.total_bytes_buffered += reassembly_buf_sz; + } + else + { + /* Make sure msg_type and length are consistent */ + if( memcmp( hs_buf->data, ssl->in_msg, 4 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Fragment header mismatch - ignore" ) ); + /* Ignore */ + goto exit; + } + } + + if( !hs_buf->is_complete ) + { + size_t frag_len, frag_off; + unsigned char * const msg = hs_buf->data + 12; + + /* + * Check and copy current fragment + */ + + /* Validation of header fields already done in + * mbedtls_ssl_prepare_handshake_record(). */ + frag_off = ssl_get_hs_frag_off( ssl ); + frag_len = ssl_get_hs_frag_len( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "adding fragment, offset = %" MBEDTLS_PRINTF_SIZET + ", length = %" MBEDTLS_PRINTF_SIZET, + frag_off, frag_len ) ); + memcpy( msg + frag_off, ssl->in_msg + 12, frag_len ); + + if( hs_buf->is_fragmented ) + { + unsigned char * const bitmask = msg + msg_len; + ssl_bitmask_set( bitmask, frag_off, frag_len ); + hs_buf->is_complete = ( ssl_bitmask_check( bitmask, + msg_len ) == 0 ); + } + else + { + hs_buf->is_complete = 1; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "message %scomplete", + hs_buf->is_complete ? "" : "not yet " ) ); + } + + break; + } + + default: + /* We don't buffer other types of messages. */ + break; + } + +exit: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_buffer_message" ) ); + return( ret ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_consume_current_message( mbedtls_ssl_context *ssl ) +{ + /* + * Consume last content-layer message and potentially + * update in_msglen which keeps track of the contents' + * consumption state. + * + * (1) Handshake messages: + * Remove last handshake message, move content + * and adapt in_msglen. + * + * (2) Alert messages: + * Consume whole record content, in_msglen = 0. + * + * (3) Change cipher spec: + * Consume whole record content, in_msglen = 0. + * + * (4) Application data: + * Don't do anything - the record layer provides + * the application data as a stream transport + * and consumes through mbedtls_ssl_read only. + * + */ + + /* Case (1): Handshake messages */ + if( ssl->in_hslen != 0 ) + { + /* Hard assertion to be sure that no application data + * is in flight, as corrupting ssl->in_msglen during + * ssl->in_offt != NULL is fatal. */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * Get next Handshake message in the current record + */ + + /* Notes: + * (1) in_hslen is not necessarily the size of the + * current handshake content: If DTLS handshake + * fragmentation is used, that's the fragment + * size instead. Using the total handshake message + * size here is faulty and should be changed at + * some point. + * (2) While it doesn't seem to cause problems, one + * has to be very careful not to assume that in_hslen + * is always <= in_msglen in a sensible communication. + * Again, it's wrong for DTLS handshake fragmentation. + * The following check is therefore mandatory, and + * should not be treated as a silently corrected assertion. + * Additionally, ssl->in_hslen might be arbitrarily out of + * bounds after handling a DTLS message with an unexpected + * sequence number, see mbedtls_ssl_prepare_handshake_record. + */ + if( ssl->in_hslen < ssl->in_msglen ) + { + ssl->in_msglen -= ssl->in_hslen; + memmove( ssl->in_msg, ssl->in_msg + ssl->in_hslen, + ssl->in_msglen ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "remaining content in record", + ssl->in_msg, ssl->in_msglen ); + } + else + { + ssl->in_msglen = 0; + } + + ssl->in_hslen = 0; + } + /* Case (4): Application data */ + else if( ssl->in_offt != NULL ) + { + return( 0 ); + } + /* Everything else (CCS & Alerts) */ + else + { + ssl->in_msglen = 0; + } + + return( 0 ); +} + +static int ssl_record_is_in_progress( mbedtls_ssl_context *ssl ) +{ + if( ssl->in_msglen > 0 ) + return( 1 ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +static void ssl_free_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + if( hs == NULL ) + return; + + if( hs->buffering.future_record.data != NULL ) + { + hs->buffering.total_bytes_buffered -= + hs->buffering.future_record.len; + + mbedtls_free( hs->buffering.future_record.data ); + hs->buffering.future_record.data = NULL; + } +} + +static int ssl_load_buffered_record( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + unsigned char * rec; + size_t rec_len; + unsigned rec_epoch; +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( 0 ); + + if( hs == NULL ) + return( 0 ); + + rec = hs->buffering.future_record.data; + rec_len = hs->buffering.future_record.len; + rec_epoch = hs->buffering.future_record.epoch; + + if( rec == NULL ) + return( 0 ); + + /* Only consider loading future records if the + * input buffer is empty. */ + if( ssl_next_record_is_in_datagram( ssl ) == 1 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> ssl_load_buffered_record" ) ); + + if( rec_epoch != ssl->in_epoch ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffered record not from current epoch." ) ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Found buffered record from current epoch - load" ) ); + + /* Double-check that the record is not too large */ + if( rec_len > in_buf_len - (size_t)( ssl->in_hdr - ssl->in_buf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( ssl->in_hdr, rec, rec_len ); + ssl->in_left = rec_len; + ssl->next_record_offset = 0; + + ssl_free_buffered_record( ssl ); + +exit: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= ssl_load_buffered_record" ) ); + return( 0 ); +} + +static int ssl_buffer_future_record( mbedtls_ssl_context *ssl, + mbedtls_record const *rec ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + /* Don't buffer future records outside handshakes. */ + if( hs == NULL ) + return( 0 ); + + /* Only buffer handshake records (we are only interested + * in Finished messages). */ + if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE ) + return( 0 ); + + /* Don't buffer more than one future epoch record. */ + if( hs->buffering.future_record.data != NULL ) + return( 0 ); + + /* Don't buffer record if there's not enough buffering space remaining. */ + if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING - + hs->buffering.total_bytes_buffered ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %" MBEDTLS_PRINTF_SIZET + " would exceed the compile-time limit %" MBEDTLS_PRINTF_SIZET + " (already %" MBEDTLS_PRINTF_SIZET + " bytes buffered) -- ignore\n", + rec->buf_len, (size_t) MBEDTLS_SSL_DTLS_MAX_BUFFERING, + hs->buffering.total_bytes_buffered ) ); + return( 0 ); + } + + /* Buffer record */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u", + ssl->in_epoch + 1U ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len ); + + /* ssl_parse_record_header() only considers records + * of the next epoch as candidates for buffering. */ + hs->buffering.future_record.epoch = ssl->in_epoch + 1; + hs->buffering.future_record.len = rec->buf_len; + + hs->buffering.future_record.data = + mbedtls_calloc( 1, hs->buffering.future_record.len ); + if( hs->buffering.future_record.data == NULL ) + { + /* If we run out of RAM trying to buffer a + * record from the next epoch, just ignore. */ + return( 0 ); + } + + memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len ); + + hs->buffering.total_bytes_buffered += rec->buf_len; + return( 0 ); +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +static int ssl_get_next_record( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_record rec; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* We might have buffered a future record; if so, + * and if the epoch matches now, load it. + * On success, this call will set ssl->in_left to + * the length of the buffered record, so that + * the calls to ssl_fetch_input() below will + * essentially be no-ops. */ + ret = ssl_load_buffered_record( ssl ); + if( ret != 0 ) + return( ret ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* Ensure that we have enough space available for the default form + * of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS, + * with no space for CIDs counted in). */ + ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec ); + if( ret != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE ) + { + ret = ssl_buffer_future_record( ssl, &rec ); + if( ret != 0 ) + return( ret ); + + /* Fall through to handling of unexpected records */ + ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD; + } + + if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ) + { +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C) + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); + + /* Setup internal message pointers from record structure. */ + ssl->in_msgtype = rec.type; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_msg = ssl->in_len + 2; + ssl->in_msglen = rec.data_len; + + ret = ssl_check_client_reconnect( ssl ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_check_client_reconnect", ret ); + if( ret != 0 ) + return( ret ); +#endif + + /* Skip unexpected record (but not whole datagram) */ + ssl->next_record_offset = rec.buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record " + "(header)" ) ); + } + else + { + /* Skip invalid record and the rest of the datagram */ + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record " + "(header)" ) ); + } + + /* Get next record */ + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + else +#endif + { + return( ret ); + } + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Remember offset of next record within datagram. */ + ssl->next_record_offset = rec.buf_len; + if( ssl->next_record_offset < ssl->in_left ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) ); + } + } + else +#endif + { + /* + * Fetch record contents from underlying transport. + */ + ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + ssl->in_left = 0; + } + + /* + * Decrypt record contents. + */ + + if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Silently discard invalid records */ + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + /* Except when waiting for Finished as a bad mac here + * probably means something went wrong in the handshake + * (eg wrong psk used, mitm downgrade attempt, etc.) */ + if( ssl->state == MBEDTLS_SSL_CLIENT_FINISHED || + ssl->state == MBEDTLS_SSL_SERVER_FINISHED ) + { +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + + if( ssl->conf->badmac_limit != 0 && + ++ssl->badmac_seen >= ssl->conf->badmac_limit ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "too many records with bad MAC" ) ); + return( MBEDTLS_ERR_SSL_INVALID_MAC ); + } + + /* As above, invalid records cause + * dismissal of the whole datagram. */ + + ssl->next_record_offset = 0; + ssl->in_left = 0; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); + } + + return( ret ); + } + else +#endif + { + /* Error out (and send alert) on invalid records */ +#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES) + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + { + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC ); + } +#endif + return( ret ); + } + } + + + /* Reset in pointers to default state for TLS/DTLS records, + * assuming no CID and no offset between record content and + * record plaintext. */ + mbedtls_ssl_update_in_pointers( ssl ); +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_len = ssl->in_cid + rec.cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + + /* The record content type may change during decryption, + * so re-read it. */ + ssl->in_msgtype = rec.type; + /* Also update the input buffer, because unfortunately + * the server-side ssl_parse_client_hello() reparses the + * record header when receiving a ClientHello initiating + * a renegotiation. */ + ssl->in_hdr[0] = rec.type; + ssl->in_msg = rec.buf + rec.data_offset; + ssl->in_msglen = rec.data_len; + MBEDTLS_PUT_UINT16_BE( rec.data_len, ssl->in_len, 0 ); + + return( 0 ); +} + +int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Handle particular types of records + */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + if( ( ret = mbedtls_ssl_prepare_handshake_record( ssl ) ) != 0 ) + { + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + if( ssl->in_msglen != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, len: %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + if( ssl->in_msg[0] != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid CCS message, content: %02x", + ssl->in_msg[0] ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC && + ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ) + { + if( ssl->handshake == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping ChangeCipherSpec outside handshake" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received out-of-order ChangeCipherSpec - remember" ) ); + return( MBEDTLS_ERR_SSL_EARLY_MESSAGE ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Ignore ChangeCipherSpec in TLS 1.3 compatibility mode" ) ); + return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING ); +#else + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "ChangeCipherSpec invalid in TLS 1.3 without compatibility mode" ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %" MBEDTLS_PRINTF_SIZET, + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "got an alert message, type: [%u:%u]", + ssl->in_msg[0], ssl->in_msg[1] ) ); + + /* + * Ignore non-fatal alerts, except close_notify and no_renegotiation + */ + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_FATAL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "is a fatal alert message (msg %d)", + ssl->in_msg[1] ) ); + return( MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE ); + } + + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a close notify message" ) ); + return( MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ); + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION_ENABLED) + if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING && + ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a no renegotiation alert" ) ); + /* Will be handled when trying to parse ServerHello */ + return( 0 ); + } +#endif + /* Silently ignore: fetch new message */ + return MBEDTLS_ERR_SSL_NON_FATAL; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* Drop unexpected ApplicationData records, + * except at the beginning of renegotiations */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA && + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) +#endif + ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) ); + return( MBEDTLS_ERR_SSL_NON_FATAL ); + } + + if( ssl->handshake != NULL && + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( 0 ); +} + +int mbedtls_ssl_send_fatal_handshake_failure( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ) ); +} + +int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl, + unsigned char level, + unsigned char message ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> send alert message" ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "send alert level=%u message=%u", level, message )); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_ALERT; + ssl->out_msglen = 2; + ssl->out_msg[0] = level; + ssl->out_msg[1] = message; + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= send alert message" ) ); + + return( 0 ); +} + +int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + ssl->out_msglen = 1; + ssl->out_msg[0] = 1; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + + return( 0 ); +} + +int mbedtls_ssl_parse_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse change cipher spec" ) ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad change cipher spec message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + /* CCS records are only accepted if they have length 1 and content '1', + * so we don't need to check this here. */ + + /* + * Switch to our negotiated transform and session parameters for inbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for inbound data" ) ); + ssl->transform_in = ssl->transform_negotiate; + ssl->session_in = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + /* Increment epoch */ + if( ++ssl->in_epoch == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + /* This is highly unlikely to happen for legitimate reasons, so + treat it as an attack and don't send an alert. */ + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ); + + mbedtls_ssl_update_in_pointers( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse change cipher spec" ) ); + + return( 0 ); +} + +/* Once ssl->out_hdr as the address of the beginning of the + * next outgoing record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->out_hdr, + * and the caller has to make sure there's space for this. + */ + +static size_t ssl_transform_get_explicit_iv_len( + mbedtls_ssl_transform const *transform ) +{ + if( transform->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 ) + return( 0 ); + + return( transform->ivlen - transform->fixed_ivlen ); +} + +void mbedtls_ssl_update_out_pointers( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_ctr = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + ssl->out_len = ssl->out_cid; + if( transform != NULL ) + ssl->out_len += transform->out_cid_len; +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_len = ssl->out_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->out_iv = ssl->out_len + 2; + } + else +#endif + { + ssl->out_len = ssl->out_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->out_cid = ssl->out_len; +#endif + ssl->out_iv = ssl->out_hdr + 5; + } + + ssl->out_msg = ssl->out_iv; + /* Adjust out_msg to make space for explicit IV, if used. */ + if( transform != NULL ) + ssl->out_msg += ssl_transform_get_explicit_iv_len( transform ); +} + +/* Once ssl->in_hdr as the address of the beginning of the + * next incoming record is set, deduce the other pointers. + * + * Note: For TLS, we save the implicit record sequence number + * (entering MAC computation) in the 8 bytes before ssl->in_hdr, + * and the caller has to make sure there's space for this. + */ + +void mbedtls_ssl_update_in_pointers( mbedtls_ssl_context *ssl ) +{ + /* This function sets the pointers to match the case + * of unprotected TLS/DTLS records, with both ssl->in_iv + * and ssl->in_msg pointing to the beginning of the record + * content. + * + * When decrypting a protected record, ssl->in_msg + * will be shifted to point to the beginning of the + * record plaintext. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* This sets the header pointers to match records + * without CID. When we receive a record containing + * a CID, the fields are shifted accordingly in + * ssl_parse_record_header(). */ + ssl->in_ctr = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + ssl->in_len = ssl->in_cid; /* Default: no CID */ +#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_len = ssl->in_ctr + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + ssl->in_iv = ssl->in_len + 2; + } + else +#endif + { + ssl->in_ctr = ssl->in_hdr - MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + ssl->in_len = ssl->in_hdr + 3; +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl->in_cid = ssl->in_len; +#endif + ssl->in_iv = ssl->in_hdr + 5; + } + + /* This will be adjusted at record decryption time. */ + ssl->in_msg = ssl->in_iv; +} + +/* + * Setup an SSL context + */ + +void mbedtls_ssl_reset_in_out_pointers( mbedtls_ssl_context *ssl ) +{ + /* Set the incoming and outgoing record pointers. */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->out_hdr = ssl->out_buf; + ssl->in_hdr = ssl->in_buf; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + { + ssl->out_ctr = ssl->out_buf; + ssl->out_hdr = ssl->out_buf + 8; + ssl->in_hdr = ssl->in_buf + 8; + } + + /* Derive other internal pointers. */ + mbedtls_ssl_update_out_pointers( ssl, NULL /* no transform enabled */ ); + mbedtls_ssl_update_in_pointers ( ssl ); +} + +/* + * SSL get accessors + */ +size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl ) +{ + return( ssl->in_offt == NULL ? 0 : ssl->in_msglen ); +} + +int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl ) +{ + /* + * Case A: We're currently holding back + * a message for further processing. + */ + + if( ssl->keep_current_message == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) ); + return( 1 ); + } + + /* + * Case B: Further records are pending in the current datagram. + */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->in_left > ssl->next_record_offset ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) ); + return( 1 ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + /* + * Case C: A handshake message is being processed. + */ + + if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) ); + return( 1 ); + } + + /* + * Case D: An application data message is being processed + */ + if( ssl->in_offt != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) ); + return( 1 ); + } + + /* + * In all other cases, the rest of the message can be dropped. + * As in ssl_get_next_record, this needs to be adapted if + * we implement support for multiple alerts in single records. + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) ); + return( 0 ); +} + + +int mbedtls_ssl_get_record_expansion( const mbedtls_ssl_context *ssl ) +{ + size_t transform_expansion = 0; + const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + size_t out_hdr_len = mbedtls_ssl_out_hdr_len( ssl ); + + if( transform == NULL ) + return( (int) out_hdr_len ); + + switch( mbedtls_cipher_get_cipher_mode( &transform->cipher_ctx_enc ) ) + { + case MBEDTLS_MODE_GCM: + case MBEDTLS_MODE_CCM: + case MBEDTLS_MODE_CHACHAPOLY: + case MBEDTLS_MODE_STREAM: + transform_expansion = transform->minlen; + break; + + case MBEDTLS_MODE_CBC: + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.2 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( transform->out_cid_len != 0 ) + transform_expansion += MBEDTLS_SSL_MAX_CID_EXPANSION; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + return( (int)( out_hdr_len + transform_expansion ) ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +/* + * Check record counters and renegotiate if they're above the limit. + */ +static int ssl_check_ctr_renegotiate( mbedtls_ssl_context *ssl ) +{ + size_t ep_len = mbedtls_ssl_ep_len( ssl ); + int in_ctr_cmp; + int out_ctr_cmp; + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER || + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING || + ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + return( 0 ); + } + + in_ctr_cmp = memcmp( ssl->in_ctr + ep_len, + &ssl->conf->renego_period[ep_len], + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN - ep_len ); + out_ctr_cmp = memcmp( &ssl->cur_out_ctr[ep_len], + &ssl->conf->renego_period[ep_len], + sizeof( ssl->cur_out_ctr ) - ep_len ); + + if( in_ctr_cmp <= 0 && out_ctr_cmp <= 0 ) + { + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "record counter limit reached: renegotiate" ) ); + return( mbedtls_ssl_renegotiate( ssl ) ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +/* This function is called from mbedtls_ssl_read() when a handshake message is + * received after the initial handshake. In this context, handshake messages + * may only be sent for the purpose of initiating renegotiations. + * + * This function is introduced as a separate helper since the handling + * of post-handshake handshake messages changes significantly in TLS 1.3, + * and having a helper function allows to distinguish between TLS <= 1.2 and + * TLS 1.3 in the future without bloating the logic of mbedtls_ssl_read(). + */ +static int ssl_handle_hs_message_post_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * - For client-side, expect SERVER_HELLO_REQUEST. + * - For server-side, expect CLIENT_HELLO. + * - Fail (TLS) or silently drop record (DTLS) in other cases. + */ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_HELLO_REQUEST || + ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not HelloRequest)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + return( 0 ); + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "handshake received (not ClientHello)" ) ); + + /* With DTLS, drop the packet (probably from last handshake) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + return( 0 ); + } +#endif + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + /* Determine whether renegotiation attempt should be accepted */ + if( ! ( ssl->conf->disable_renegotiation == MBEDTLS_SSL_RENEGOTIATION_DISABLED || + ( ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == + MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) ) ) + { + /* + * Accept renegotiation request + */ + + /* DTLS clients need to know renego is server-initiated */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + } +#endif + ret = mbedtls_ssl_start_renegotiation( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", + ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + /* + * Refuse renegotiation + */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "refusing renegotiation, sending alert" ) ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + } + + return( 0 ); +} + +/* + * Receive application data decrypted from the SSL layer + */ +int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> read" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + + if( ssl->handshake != NULL && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } + } +#endif + + /* + * Check if renegotiation is necessary and/or handshake is + * in process. If yes, perform/continue, and fall through + * if an unexpected packet is received while the client + * is waiting for the ServerHello. + * + * (There is no equivalent to the last condition on + * the server-side as it is not treated as within + * a handshake while waiting for the ClientHello + * after a renegotiation request.) + */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ret = ssl_check_ctr_renegotiate( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake( ssl ); + if( ret != MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO && + ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + /* Loop as long as no application data record is available */ + while( ssl->in_offt == NULL ) + { + /* Start timer if not already running */ + if( ssl->f_get_timer != NULL && + ssl->f_get_timer( ssl->p_timer ) == -1 ) + { + mbedtls_ssl_set_timer( ssl, ssl->conf->read_timeout ); + } + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ssl->in_msglen == 0 && + ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* + * OpenSSL sends empty messages to randomize the IV + */ + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_SSL_CONN_EOF ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + } + + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) + { + ret = ssl_handle_hs_message_post_handshake( ssl ); + if( ret != 0) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_handle_hs_message_post_handshake", + ret ); + return( ret ); + } + + /* At this point, we don't know whether the renegotiation triggered + * by the post-handshake message has been completed or not. The cases + * to consider are the following: + * 1) The renegotiation is complete. In this case, no new record + * has been read yet. + * 2) The renegotiation is incomplete because the client received + * an application data record while awaiting the ServerHello. + * 3) The renegotiation is incomplete because the client received + * a non-handshake, non-application data message while awaiting + * the ServerHello. + * + * In each of these cases, looping will be the proper action: + * - For 1), the next iteration will read a new record and check + * if it's application data. + * - For 2), the loop condition isn't satisfied as application data + * is present, hence continue is the same as break + * - For 3), the loop condition is satisfied and read_record + * will re-deliver the message that was held back by the client + * when expecting the ServerHello. + */ + + continue; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->renego_max_records >= 0 ) + { + if( ++ssl->renego_records_seen > ssl->conf->renego_max_records ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation requested, " + "but not honored by client" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + } + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* Fatal and closure alerts handled by mbedtls_ssl_read_record() */ + if( ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ignoring non-fatal non-closure alert" ) ); + return( MBEDTLS_ERR_SSL_WANT_READ ); + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad application data message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + ssl->in_offt = ssl->in_msg; + + /* We're going to return something now, cancel timer, + * except if handshake (renegotiation) is in progress */ + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + mbedtls_ssl_set_timer( ssl, 0 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + /* If we requested renego but received AppData, resend HelloRequest. + * Do it now, after setting in_offt, to avoid taking this branch + * again if ssl_write_hello_request() returns WANT_WRITE */ +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ( ret = mbedtls_ssl_resend_hello_request( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend_hello_request", + ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + } + + n = ( len < ssl->in_msglen ) + ? len : ssl->in_msglen; + + memcpy( buf, ssl->in_offt, n ); + ssl->in_msglen -= n; + + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_platform_zeroize( ssl->in_offt, n ); + + if( ssl->in_msglen == 0 ) + { + /* all bytes consumed */ + ssl->in_offt = NULL; + ssl->keep_current_message = 0; + } + else + { + /* more data available */ + ssl->in_offt += n; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= read" ) ); + + return( (int) n ); +} + +/* + * Send application data to be encrypted by the SSL layer, taking care of max + * fragment length and buffer size. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. + */ +static int ssl_write_real( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + int ret = mbedtls_ssl_get_max_out_record_payload( ssl ); + const size_t max_len = (size_t) ret; + + if( ret < 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_max_out_record_payload", ret ); + return( ret ); + } + + if( len > max_len ) + { +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "fragment larger than the (negotiated) " + "maximum fragment length: %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + len, max_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + else +#endif + len = max_len; + } + + if( ssl->out_left != 0 ) + { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ + ssl->out_msglen = len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_APPLICATION_DATA; + memcpy( ssl->out_msg, buf, len ); + + if( ( ret = mbedtls_ssl_write_record( ssl, SSL_FORCE_FLUSH ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); + return( ret ); + } + } + + return( (int) len ); +} + +/* + * Write application data (public-facing wrapper) + */ +int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write" ) ); + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ( ret = ssl_check_ctr_renegotiate( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_check_ctr_renegotiate", ret ); + return( ret ); + } +#endif + + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } + + ret = ssl_write_real( ssl, buf, len ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write" ) ); + + return( ret ); +} + +/* + * Notify the peer that the connection is being closed + */ +int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write close notify" ) ); + + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + if( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + if( ( ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_WARNING, + MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_send_alert_message", ret ); + return( ret ); + } + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write close notify" ) ); + + return( 0 ); +} + +void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform ) +{ + if( transform == NULL ) + return; + + mbedtls_cipher_free( &transform->cipher_ctx_enc ); + mbedtls_cipher_free( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + mbedtls_md_free( &transform->md_ctx_enc ); + mbedtls_md_free( &transform->md_ctx_dec ); +#endif + + mbedtls_platform_zeroize( transform, sizeof( mbedtls_ssl_transform ) ); +} + +void mbedtls_ssl_set_inbound_transform( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ + ssl->transform_in = transform; + memset( ssl->in_ctr, 0, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ); +} + +void mbedtls_ssl_set_outbound_transform( mbedtls_ssl_context *ssl, + mbedtls_ssl_transform *transform ) +{ + ssl->transform_out = transform; + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_buffering_free( mbedtls_ssl_context *ssl ) +{ + unsigned offset; + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + + if( hs == NULL ) + return; + + ssl_free_buffered_record( ssl ); + + for( offset = 0; offset < MBEDTLS_SSL_MAX_BUFFERED_HS; offset++ ) + ssl_buffering_free_slot( ssl, offset ); +} + +static void ssl_buffering_free_slot( mbedtls_ssl_context *ssl, + uint8_t slot ) +{ + mbedtls_ssl_handshake_params * const hs = ssl->handshake; + mbedtls_ssl_hs_buffer * const hs_buf = &hs->buffering.hs[slot]; + + if( slot >= MBEDTLS_SSL_MAX_BUFFERED_HS ) + return; + + if( hs_buf->is_valid == 1 ) + { + hs->buffering.total_bytes_buffered -= hs_buf->data_len; + mbedtls_platform_zeroize( hs_buf->data, hs_buf->data_len ); + mbedtls_free( hs_buf->data ); + memset( hs_buf, 0, sizeof( mbedtls_ssl_hs_buffer ) ); + } +} + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +/* + * Convert version numbers to/from wire format + * and, for DTLS, to/from TLS equivalent. + * + * For TLS this is the identity. + * For DTLS, use 1's complement (v -> 255 - v, and then map as follows: + * 1.x <-> 3.x+1 for x != 0 (DTLS 1.2 based on TLS 1.2) + */ +void mbedtls_ssl_write_version( int major, int minor, int transport, + unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( minor == MBEDTLS_SSL_MINOR_VERSION_2 ) + --minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + + ver[0] = (unsigned char)( 255 - ( major - 2 ) ); + ver[1] = (unsigned char)( 255 - ( minor - 1 ) ); + } + else +#else + ((void) transport); +#endif + { + ver[0] = (unsigned char) major; + ver[1] = (unsigned char) minor; + } +} + +void mbedtls_ssl_read_version( int *major, int *minor, int transport, + const unsigned char ver[2] ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + *major = 255 - ver[0] + 2; + *minor = 255 - ver[1] + 1; + + if( *minor == MBEDTLS_SSL_MINOR_VERSION_1 ) + ++*minor; /* DTLS 1.0 stored as TLS 1.1 internally */ + } + else +#else + ((void) transport); +#endif + { + *major = ver[0]; + *minor = ver[1]; + } +} + +/* + * Send pending fatal alert. + * 0, No alert message. + * !0, if mbedtls_ssl_send_alert_message() returned in error, the error code it + * returned, ssl->alert_reason otherwise. + */ +int mbedtls_ssl_handle_pending_alert( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* No pending alert, return success*/ + if( ssl->send_alert == 0 ) + return( 0 ); + + ret = mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + ssl->alert_type ); + + /* If mbedtls_ssl_send_alert_message() returned with MBEDTLS_ERR_SSL_WANT_WRITE, + * do not clear the alert to be able to send it later. + */ + if( ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + ssl->send_alert = 0; + } + + if( ret != 0 ) + return( ret ); + + return( ssl->alert_reason ); +} + +/* + * Set pending fatal alert flag. + */ +void mbedtls_ssl_pend_fatal_alert( mbedtls_ssl_context *ssl, + unsigned char alert_type, + int alert_reason ) +{ + ssl->send_alert = 1; + ssl->alert_type = alert_type; + ssl->alert_reason = alert_reason; +} + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_srv.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_srv.c new file mode 100644 index 00000000..f34f2de3 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_srv.c @@ -0,0 +1,4355 @@ +/* + * TLS server-side functions + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "ssl_misc.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "constant_time_internal.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +int mbedtls_ssl_set_client_transport_id( mbedtls_ssl_context *ssl, + const unsigned char *info, + size_t ilen ) +{ + if( ssl->conf->endpoint != MBEDTLS_SSL_IS_SERVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_free( ssl->cli_id ); + + if( ( ssl->cli_id = mbedtls_calloc( 1, ilen ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->cli_id, info, ilen ); + ssl->cli_id_len = ilen; + + return( 0 ); +} + +void mbedtls_ssl_conf_dtls_cookies( mbedtls_ssl_config *conf, + mbedtls_ssl_cookie_write_t *f_cookie_write, + mbedtls_ssl_cookie_check_t *f_cookie_check, + void *p_cookie ) +{ + conf->f_cookie_write = f_cookie_write; + conf->f_cookie_check = f_cookie_check; + conf->p_cookie = p_cookie; +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t servername_list_size, hostname_len; + const unsigned char *p; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) ); + + if( len < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( servername_list_size + 2 != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + p = buf + 2; + while( servername_list_size > 2 ) + { + hostname_len = ( ( p[1] << 8 ) | p[2] ); + if( hostname_len + 3 > servername_list_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + if( p[0] == MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME ) + { + ret = ssl->conf->f_sni( ssl->conf->p_sni, + ssl, p + 3, hostname_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME ); + return( MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME ); + } + return( 0 ); + } + + servername_list_size -= hostname_len + 3; + p += hostname_len + 3; + } + + if( servername_list_size != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf ) +{ + if( conf->f_psk != NULL ) + return( 1 ); + + if( conf->psk_identity_len == 0 || conf->psk_identity == NULL ) + return( 0 ); + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + return( 1 ); + + return( 0 ); + } + + if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Check verify-data in constant-time. The length OTOH is no secret */ + if( len != 1 + ssl->verify_data_len || + buf[0] != ssl->verify_data_len || + mbedtls_ct_memcmp( buf + 1, ssl->peer_verify_data, + ssl->verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-matching renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + if( len != 1 || buf[0] != 0x0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "non-zero length renegotiation info" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* + * Status of the implementation of signature-algorithms extension: + * + * Currently, we are only considering the signature-algorithm extension + * to pick a ciphersuite which allows us to send the ServerKeyExchange + * message with a signature-hash combination that the user allows. + * + * We do *not* check whether all certificates in our certificate + * chain are signed with an allowed signature-hash pair. + * This needs to be done at a later stage. + * + */ +static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t sig_alg_list_size; + + const unsigned char *p; + const unsigned char *end = buf + len; + + mbedtls_md_type_t md_cur; + mbedtls_pk_type_t sig_cur; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( sig_alg_list_size + 2 != len || + sig_alg_list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Currently we only guarantee signing the ServerKeyExchange message according + * to the constraints specified in this extension (see above), so it suffices + * to remember only one suitable hash for each possible signature algorithm. + * + * This will change when we also consider certificate signatures, + * in which case we will need to remember the whole signature-hash + * pair list from the extension. + */ + + for( p = buf + 2; p < end; p += 2 ) + { + /* Silently ignore unknown signature or hash algorithms. */ + + if( ( sig_cur = mbedtls_ssl_pk_alg_from_sig( p[1] ) ) == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext" + " unknown sig alg encoding %d", p[1] ) ); + continue; + } + + /* Check if we support the hash the user proposes */ + md_cur = mbedtls_ssl_md_alg_from_hash( p[0] ); + if( md_cur == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " unknown hash alg encoding %d", p[0] ) ); + continue; + } + + if( mbedtls_ssl_check_sig_hash( ssl, md_cur ) == 0 ) + { + mbedtls_ssl_sig_hash_set_add( &ssl->handshake->hash_algs, sig_cur, md_cur ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext:" + " match sig %u and hash %u", + (unsigned) sig_cur, (unsigned) md_cur ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: " + "hash alg %u not supported", (unsigned) md_cur ) ); + } + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size, our_size; + const unsigned char *p; + const mbedtls_ecp_curve_info *curve_info, **curves; + + if ( len < 2 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + list_size = ( ( buf[0] << 8 ) | ( buf[1] ) ); + if( list_size + 2 != len || + list_size % 2 != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Should never happen unless client duplicates the extension */ + if( ssl->handshake->curves != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + /* Don't allow our peer to make us allocate too much memory, + * and leave room for a final 0 */ + our_size = list_size / 2 + 1; + if( our_size > MBEDTLS_ECP_DP_MAX ) + our_size = MBEDTLS_ECP_DP_MAX; + + if( ( curves = mbedtls_calloc( our_size, sizeof( *curves ) ) ) == NULL ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ssl->handshake->curves = curves; + + p = buf + 2; + while( list_size > 0 && our_size > 1 ) + { + curve_info = mbedtls_ecp_curve_info_from_tls_id( ( p[0] << 8 ) | p[1] ); + + if( curve_info != NULL ) + { + *curves++ = curve_info; + our_size--; + } + + list_size -= 2; + p += 2; + } + + return( 0 ); +} + +static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t list_size; + const unsigned char *p; + + if( len == 0 || (size_t)( buf[0] + 1 ) != len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + list_size = buf[0]; + + p = buf + 1; + while( list_size > 0 ) + { + if( p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED || + p[0] == MBEDTLS_ECP_PF_COMPRESSED ) + { +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + ssl->handshake->ecdh_ctx.point_format = p[0]; +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_set_point_format( &ssl->handshake->ecjpake_ctx, + p[0] ); +#endif + MBEDTLS_SSL_DEBUG_MSG( 4, ( "point format selected: %d", p[0] ) ); + return( 0 ); + } + + list_size--; + p++; + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_parse_ecjpake_kkpp( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip ecjpake kkpp extension" ) ); + return( 0 ); + } + + if( ( ret = mbedtls_ecjpake_read_round_one( &ssl->handshake->ecjpake_ctx, + buf, len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_one", ret ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( ret ); + } + + /* Only mark the extension as OK when we're sure it is */ + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_parse_max_fragment_length_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 1 || buf[0] >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + ssl->session_negotiate->mfl_code = buf[0]; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static int ssl_parse_cid_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + size_t peer_cid_len; + + /* CID extension only makes sense in DTLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + + if( len < 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + peer_cid_len = *buf++; + len--; + + if( len != peer_cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Ignore CID if the user has disabled its use. */ + if( ssl->negotiate_cid == MBEDTLS_SSL_CID_DISABLED ) + { + /* Leave ssl->handshake->cid_in_use in its default + * value of MBEDTLS_SSL_CID_DISABLED. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Client sent CID extension, but CID disabled" ) ); + return( 0 ); + } + + if( peer_cid_len > MBEDTLS_SSL_CID_OUT_LEN_MAX ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + ssl->handshake->cid_in_use = MBEDTLS_SSL_CID_ENABLED; + ssl->handshake->peer_cid_len = (uint8_t) peer_cid_len; + memcpy( ssl->handshake->peer_cid, buf, peer_cid_len ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use of CID extension negotiated" ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Client CID", buf, peer_cid_len ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_parse_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ((void) buf); + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + ssl->session_negotiate->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_parse_extended_ms_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + if( len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ((void) buf); + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + ssl->handshake->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_parse_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_session session; + + mbedtls_ssl_session_init( &session ); + + if( ssl->conf->f_ticket_parse == NULL || + ssl->conf->f_ticket_write == NULL ) + { + return( 0 ); + } + + /* Remember the client asked us to send a new ticket */ + ssl->handshake->new_session_ticket = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket length: %" MBEDTLS_PRINTF_SIZET, len ) ); + + if( len == 0 ) + return( 0 ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket rejected: renegotiating" ) ); + return( 0 ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * Failures are ok: just ignore the ticket and proceed. + */ + if( ( ret = ssl->conf->f_ticket_parse( ssl->conf->p_ticket, &session, + buf, len ) ) != 0 ) + { + mbedtls_ssl_session_free( &session ); + + if( ret == MBEDTLS_ERR_SSL_INVALID_MAC ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is not authentic" ) ); + else if( ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED ) + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ticket is expired" ) ); + else + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_parse", ret ); + + return( 0 ); + } + + /* + * Keep the session ID sent by the client, since we MUST send it back to + * inform them we're accepting the ticket (RFC 5077 section 3.4) + */ + session.id_len = ssl->session_negotiate->id_len; + memcpy( &session.id, ssl->session_negotiate->id, session.id_len ); + + mbedtls_ssl_session_free( ssl->session_negotiate ); + memcpy( ssl->session_negotiate, &session, sizeof( mbedtls_ssl_session ) ); + + /* Zeroize instead of free as we copied the content */ + mbedtls_platform_zeroize( &session, sizeof( mbedtls_ssl_session ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from ticket" ) ); + + ssl->handshake->resume = 1; + + /* Don't send a new ticket after all, this one is OK */ + ssl->handshake->new_session_ticket = 0; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_parse_alpn_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ + size_t list_len, cur_len, ours_len; + const unsigned char *theirs, *start, *end; + const char **ours; + + /* If ALPN not configured, just ignore the extension */ + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + /* + * opaque ProtocolName<1..2^8-1>; + * + * struct { + * ProtocolName protocol_name_list<2..2^16-1> + * } ProtocolNameList; + */ + + /* Min length is 2 (list_len) + 1 (name_len) + 1 (name) */ + if( len < 4 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + list_len = ( buf[0] << 8 ) | buf[1]; + if( list_len != len - 2 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * Validate peer's list (lengths) + */ + start = buf + 2; + end = buf + len; + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + /* Current identifier must fit in list */ + if( cur_len > (size_t)( end - theirs ) ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Empty strings MUST NOT be included */ + if( cur_len == 0 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + } + + /* + * Use our order of preference + */ + for( ours = ssl->conf->alpn_list; *ours != NULL; ours++ ) + { + ours_len = strlen( *ours ); + for( theirs = start; theirs != end; theirs += cur_len ) + { + cur_len = *theirs++; + + if( cur_len == ours_len && + memcmp( theirs, *ours, cur_len ) == 0 ) + { + ssl->alpn_chosen = *ours; + return( 0 ); + } + } + } + + /* If we get there, no match was found */ + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL ); + return( MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +static int ssl_parse_use_srtp_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + mbedtls_ssl_srtp_profile client_protection = MBEDTLS_TLS_SRTP_UNSET; + size_t i,j; + size_t profile_length; + uint16_t mki_length; + /*! 2 bytes for profile length and 1 byte for mki len */ + const size_t size_of_lengths = 3; + + /* If use_srtp is not configured, just ignore the extension */ + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->conf->dtls_srtp_profile_list == NULL ) || + ( ssl->conf->dtls_srtp_profile_list_len == 0 ) ) + { + return( 0 ); + } + + /* RFC5764 section 4.1.1 + * uint8 SRTPProtectionProfile[2]; + * + * struct { + * SRTPProtectionProfiles SRTPProtectionProfiles; + * opaque srtp_mki<0..255>; + * } UseSRTPData; + + * SRTPProtectionProfile SRTPProtectionProfiles<2..2^16-1>; + */ + + /* + * Min length is 5: at least one protection profile(2 bytes) + * and length(2 bytes) + srtp_mki length(1 byte) + * Check here that we have at least 2 bytes of protection profiles length + * and one of srtp_mki length + */ + if( len < size_of_lengths ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = MBEDTLS_TLS_SRTP_UNSET; + + /* first 2 bytes are protection profile length(in bytes) */ + profile_length = ( buf[0] << 8 ) | buf[1]; + buf += 2; + + /* The profile length cannot be bigger than input buffer size - lengths fields */ + if( profile_length > len - size_of_lengths || + profile_length % 2 != 0 ) /* profiles are 2 bytes long, so the length must be even */ + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + /* + * parse the extension list values are defined in + * http://www.iana.org/assignments/srtp-protection/srtp-protection.xhtml + */ + for( j = 0; j < profile_length; j += 2 ) + { + uint16_t protection_profile_value = buf[j] << 8 | buf[j + 1]; + client_protection = mbedtls_ssl_check_srtp_profile_value( protection_profile_value ); + + if( client_protection != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + client_protection ) ) ); + } + else + { + continue; + } + /* check if suggested profile is in our list */ + for( i = 0; i < ssl->conf->dtls_srtp_profile_list_len; i++) + { + if( client_protection == ssl->conf->dtls_srtp_profile_list[i] ) + { + ssl->dtls_srtp_info.chosen_dtls_srtp_profile = ssl->conf->dtls_srtp_profile_list[i]; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "selected srtp profile: %s", + mbedtls_ssl_get_srtp_profile_as_string( + client_protection ) ) ); + break; + } + } + if( ssl->dtls_srtp_info.chosen_dtls_srtp_profile != MBEDTLS_TLS_SRTP_UNSET ) + break; + } + buf += profile_length; /* buf points to the mki length */ + mki_length = *buf; + buf++; + + if( mki_length > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH || + mki_length + profile_length + size_of_lengths != len ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Parse the mki only if present and mki is supported locally */ + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED && + mki_length > 0 ) + { + ssl->dtls_srtp_info.mki_len = mki_length; + + memcpy( ssl->dtls_srtp_info.mki_value, buf, mki_length ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "using mki", ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +/* + * Auxiliary functions for ServerHello parsing and related actions + */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/* + * Return 0 if the given key uses one of the acceptable curves, -1 otherwise + */ +#if defined(MBEDTLS_ECDSA_C) +static int ssl_check_key_curve( mbedtls_pk_context *pk, + const mbedtls_ecp_curve_info **curves ) +{ + const mbedtls_ecp_curve_info **crv = curves; + mbedtls_ecp_group_id grp_id = mbedtls_pk_ec( *pk )->grp.id; + + while( *crv != NULL ) + { + if( (*crv)->grp_id == grp_id ) + return( 0 ); + crv++; + } + + return( -1 ); +} +#endif /* MBEDTLS_ECDSA_C */ + +/* + * Try picking a certificate for this ciphersuite, + * return 0 on success and -1 on failure. + */ +static int ssl_pick_cert( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t * ciphersuite_info ) +{ + mbedtls_ssl_key_cert *cur, *list, *fallback = NULL; + mbedtls_pk_type_t pk_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + uint32_t flags; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_key_cert != NULL ) + list = ssl->handshake->sni_key_cert; + else +#endif + list = ssl->conf->key_cert; + + if( pk_alg == MBEDTLS_PK_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite requires certificate" ) ); + + if( list == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server has no certificate" ) ); + return( -1 ); + } + + for( cur = list; cur != NULL; cur = cur->next ) + { + flags = 0; + MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate", + cur->cert ); + + if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) ); + continue; + } + + /* + * This avoids sending the client a cert it'll reject based on + * keyUsage or other extensions. + * + * It also allows the user to provision different certificates for + * different uses based on keyUsage, eg if they want to avoid signing + * and decrypting with the same RSA key. + */ + if( mbedtls_ssl_check_cert_usage( cur->cert, ciphersuite_info, + MBEDTLS_SSL_IS_SERVER, &flags ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: " + "(extended) key usage extension" ) ); + continue; + } + +#if defined(MBEDTLS_ECDSA_C) + if( pk_alg == MBEDTLS_PK_ECDSA && + ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) ); + continue; + } +#endif + + /* + * Try to select a SHA-1 certificate for pre-1.2 clients, but still + * present them a SHA-higher cert rather than failing if it's the only + * one we got that satisfies the other conditions. + */ + if( ssl->minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 && + cur->cert->sig_md != MBEDTLS_MD_SHA1 ) + { + if( fallback == NULL ) + fallback = cur; + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate not preferred: " + "sha-2 with pre-TLS 1.2 client" ) ); + continue; + } + } + + /* If we get there, we got a winner */ + break; + } + + if( cur == NULL ) + cur = fallback; + + /* Do not update ssl->handshake->key_cert unless there is a match */ + if( cur != NULL ) + { + ssl->handshake->key_cert = cur; + MBEDTLS_SSL_DEBUG_CRT( 3, "selected certificate chain, certificate", + ssl->handshake->key_cert->cert ); + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Check if a given ciphersuite is suitable for use with our config/keys/etc + * Sets ciphersuite_info only if the suite matches. + */ +static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, + const mbedtls_ssl_ciphersuite_t **ciphersuite_info ) +{ + const mbedtls_ssl_ciphersuite_t *suite_info; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_pk_type_t sig_type; +#endif + + suite_info = mbedtls_ssl_ciphersuite_from_id( suite_id ); + if( suite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "trying ciphersuite: %#04x (%s)", + (unsigned int) suite_id, suite_info->name ) ); + + if( suite_info->min_minor_ver > ssl->minor_ver || + suite_info->max_minor_ver < ssl->minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: version" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 0 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + ( ssl->handshake->cli_exts & MBEDTLS_TLS_EXT_ECJPAKE_KKPP_OK ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: ecjpake " + "not configured or ext missing" ) ); + return( 0 ); + } +#endif + + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) + if( mbedtls_ssl_ciphersuite_uses_ec( suite_info ) && + ( ssl->handshake->curves == NULL || + ssl->handshake->curves[0] == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no common elliptic curve" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + /* If the ciphersuite requires a pre-shared key and we don't + * have one, skip it now rather than failing later */ + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* If the ciphersuite requires signing, check whether + * a suitable hash algorithm is present. */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + sig_type = mbedtls_ssl_get_ciphersuite_sig_alg( suite_info ); + if( sig_type != MBEDTLS_PK_NONE && + mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, sig_type ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no suitable hash algorithm " + "for signature algorithm %u", (unsigned) sig_type ) ); + return( 0 ); + } + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * Final check: if ciphersuite requires us to have a + * certificate/key of a particular type: + * - select the appropriate certificate if we have one, or + * - try the next ciphersuite if we don't + * This must be done last since we modify the key_cert list. + */ + if( ssl_pick_cert( ssl, suite_info ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: " + "no suitable certificate" ) ); + return( 0 ); + } +#endif + + *ciphersuite_info = suite_info; + return( 0 ); +} + +/* This function doesn't alert on errors that happen early during + ClientHello parsing because they might indicate that the client is + not talking SSL/TLS at all and would not understand our alert. */ +static int ssl_parse_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret, got_common_suite; + size_t i, j; + size_t ciph_offset, comp_offset, ext_offset; + size_t msg_len, ciph_len, sess_len, comp_len, ext_len; +#if defined(MBEDTLS_SSL_PROTO_DTLS) + size_t cookie_offset, cookie_len; +#endif + unsigned char *buf, *p, *ext; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + int renegotiation_info_seen = 0; +#endif + int handshake_failure = 0; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + int major, minor; + + /* If there is no signature-algorithm extension present, + * we need to fall back to the default values for allowed + * signature-hash pairs. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + int sig_hash_alg_ext_present = 0; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +read_record_header: +#endif + /* + * If renegotiating, then the input was read with mbedtls_ssl_read_record(), + * otherwise read it ourselves manually in order to support SSLv2 + * ClientHello, which doesn't use the same record layer format. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE ) +#endif + { + if( ( ret = mbedtls_ssl_fetch_input( ssl, 5 ) ) != 0 ) + { + /* No alert on a read error. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + } + + buf = ssl->in_hdr; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record header", buf, mbedtls_ssl_in_hdr_len( ssl ) ); + + /* + * TLS Client Hello + * + * Record layer: + * 0 . 0 message type + * 1 . 2 protocol version + * 3 . 11 DTLS: epoch + record sequence number + * 3 . 4 message length + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, message type: %d", + buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, message len.: %d", + ( ssl->in_len[0] << 8 ) | ssl->in_len[1] ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, protocol version: [%d:%d]", + buf[1], buf[2] ) ); + + mbedtls_ssl_read_version( &major, &minor, ssl->conf->transport, buf + 1 ); + + /* According to RFC 5246 Appendix E.1, the version here is typically + * "{03,00}, the lowest version number supported by the client, [or] the + * value of ClientHello.client_version", so the only meaningful check here + * is the major version shouldn't be less than 3 */ + if( major < MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + } + + /* For DTLS if this is the initial handshake, remember the client sequence + * number to use it in our next message (RFC 6347 4.2.1) */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + /* Epoch should be 0 for initial handshakes */ + if( ssl->in_ctr[0] != 0 || ssl->in_ctr[1] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + memcpy( &ssl->cur_out_ctr[2], ssl->in_ctr + 2, + sizeof( ssl->cur_out_ctr ) - 2 ); + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record, discarding" ) ); + ssl->next_record_offset = 0; + ssl->in_left = 0; + goto read_record_header; + } + + /* No MAC to check yet, so we can update right now */ + mbedtls_ssl_dtls_replay_update( ssl ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + msg_len = ( ssl->in_len[0] << 8 ) | ssl->in_len[1]; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + /* Set by mbedtls_ssl_read_record() */ + msg_len = ssl->in_hslen; + } + else +#endif + { + if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + if( ( ret = mbedtls_ssl_fetch_input( ssl, + mbedtls_ssl_in_hdr_len( ssl ) + msg_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret ); + return( ret ); + } + + /* Done reading this record, get ready for the next one */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len( ssl ); + else +#endif + ssl->in_left = 0; + } + + buf = ssl->in_msg; + + MBEDTLS_SSL_DEBUG_BUF( 4, "record contents", buf, msg_len ); + + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + /* + * Handshake layer: + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 DTLS only: message seqence number + * 6 . 8 DTLS only: fragment offset + * 9 . 11 DTLS only: fragment length + */ + if( msg_len < mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake type: %d", buf[0] ) ); + + if( buf[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, handshake len.: %d", + ( buf[1] << 16 ) | ( buf[2] << 8 ) | buf[3] ) ); + + /* We don't support fragmentation of ClientHello (yet?) */ + if( buf[1] != 0 || + msg_len != mbedtls_ssl_hs_hdr_len( ssl ) + ( ( buf[2] << 8 ) | buf[3] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + /* + * Copy the client's handshake message_seq on initial handshakes, + * check sequence number on renego. + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* This couldn't be done in ssl_prepare_handshake_record() */ + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + + if( cli_msg_seq != ssl->handshake->in_msg_seq ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message_seq: " + "%u (expected %u)", cli_msg_seq, + ssl->handshake->in_msg_seq ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ssl->handshake->in_msg_seq++; + } + else +#endif + { + unsigned int cli_msg_seq = ( ssl->in_msg[4] << 8 ) | + ssl->in_msg[5]; + ssl->handshake->out_msg_seq = cli_msg_seq; + ssl->handshake->in_msg_seq = cli_msg_seq + 1; + } + + /* + * For now we don't support fragmentation, so make sure + * fragment_offset == 0 and fragment_length == length + */ + if( ssl->in_msg[6] != 0 || ssl->in_msg[7] != 0 || ssl->in_msg[8] != 0 || + memcmp( ssl->in_msg + 1, ssl->in_msg + 9, 3 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ClientHello fragmentation not supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + buf += mbedtls_ssl_hs_hdr_len( ssl ); + msg_len -= mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * ClientHello layer: + * 0 . 1 protocol version + * 2 . 33 random bytes (starting with 4 bytes of Unix time) + * 34 . 35 session id length (1 byte) + * 35 . 34+x session id + * 35+x . 35+x DTLS only: cookie length (1 byte) + * 36+x . .. DTLS only: cookie + * .. . .. ciphersuite list length (2 bytes) + * .. . .. ciphersuite list + * .. . .. compression alg. list length (1 byte) + * .. . .. compression alg. list + * .. . .. extensions length (2 bytes, optional) + * .. . .. extensions (optional) + */ + + /* + * Minimal length (with everything empty and extensions omitted) is + * 2 + 32 + 1 + 2 + 1 = 38 bytes. Check that first, so that we can + * read at least up to session id length without worrying. + */ + if( msg_len < 38 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * Check and save the protocol version + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, version", buf, 2 ); + + mbedtls_ssl_read_version( &ssl->major_ver, &ssl->minor_ver, + ssl->conf->transport, buf ); + ssl->session_negotiate->minor_ver = ssl->minor_ver; + + ssl->handshake->max_major_ver = ssl->major_ver; + ssl->handshake->max_minor_ver = ssl->minor_ver; + + if( ssl->major_ver < ssl->conf->min_major_ver || + ssl->minor_ver < ssl->conf->min_minor_ver ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "client only supports ssl smaller than minimum" + " [%d:%d] < [%d:%d]", + ssl->major_ver, ssl->minor_ver, + ssl->conf->min_major_ver, ssl->conf->min_minor_ver ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + } + + if( ssl->major_ver > ssl->conf->max_major_ver ) + { + ssl->major_ver = ssl->conf->max_major_ver; + ssl->minor_ver = ssl->conf->max_minor_ver; + } + else if( ssl->minor_ver > ssl->conf->max_minor_ver ) + ssl->minor_ver = ssl->conf->max_minor_ver; + + /* + * Save client random (inc. Unix time) + */ + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", buf + 2, 32 ); + + memcpy( ssl->handshake->randbytes, buf + 2, 32 ); + + /* + * Check the session ID length and save session ID + */ + sess_len = buf[34]; + + if( sess_len > sizeof( ssl->session_negotiate->id ) || + sess_len + 34 + 2 > msg_len ) /* 2 for cipherlist length field */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, session id", buf + 35, sess_len ); + + ssl->session_negotiate->id_len = sess_len; + memset( ssl->session_negotiate->id, 0, + sizeof( ssl->session_negotiate->id ) ); + memcpy( ssl->session_negotiate->id, buf + 35, + ssl->session_negotiate->id_len ); + + /* + * Check the cookie length and content + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + cookie_offset = 35 + sess_len; + cookie_len = buf[cookie_offset]; + + if( cookie_offset + 1 + cookie_len + 2 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, cookie", + buf + cookie_offset + 1, cookie_len ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->f_cookie_check != NULL +#if defined(MBEDTLS_SSL_RENEGOTIATION) + && ssl->renego_status == MBEDTLS_SSL_INITIAL_HANDSHAKE +#endif + ) + { + if( ssl->conf->f_cookie_check( ssl->conf->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + /* This may be an attacker's probe, so don't send an alert */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } + + /* + * Check the ciphersuitelist length (will be parsed later) + */ + ciph_offset = cookie_offset + 1 + cookie_len; + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + ciph_offset = 35 + sess_len; + + ciph_len = ( buf[ciph_offset + 0] << 8 ) + | ( buf[ciph_offset + 1] ); + + if( ciph_len < 2 || + ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */ + ( ciph_len % 2 ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, ciphersuitelist", + buf + ciph_offset + 2, ciph_len ); + + /* + * Check the compression algorithms length and pick one + */ + comp_offset = ciph_offset + 2 + ciph_len; + + comp_len = buf[comp_offset]; + + if( comp_len < 1 || + comp_len > 16 || + comp_len + comp_offset + 1 > msg_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, compression", + buf + comp_offset + 1, comp_len ); + + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; + /* See comments in ssl_write_client_hello() */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + ssl->session_negotiate->compression = MBEDTLS_SSL_COMPRESS_NULL; +#endif + /* + * Check the extension length + */ + ext_offset = comp_offset + 1 + comp_len; + if( msg_len > ext_offset ) + { + if( msg_len < ext_offset + 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + ext_len = ( buf[ext_offset + 0] << 8 ) + | ( buf[ext_offset + 1] ); + + if( msg_len != ext_offset + 2 + ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + } + else + ext_len = 0; + + ext = buf + ext_offset + 2; + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", ext, ext_len ); + + while( ext_len != 0 ) + { + unsigned int ext_id; + unsigned int ext_size; + if ( ext_len < 4 ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) ); + + if( ext_size + 4 > ext_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + switch( ext_id ) + { +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + case MBEDTLS_TLS_EXT_SERVERNAME: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ServerName extension" ) ); + if( ssl->conf->f_sni == NULL ) + break; + + ret = ssl_parse_servername_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + case MBEDTLS_TLS_EXT_RENEGOTIATION_INFO: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found renegotiation extension" ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + renegotiation_info_seen = 1; +#endif + + ret = ssl_parse_renegotiation_info( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_TLS_EXT_SIG_ALG: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found signature_algorithms extension" ) ); + + ret = ssl_parse_signature_algorithms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + + sig_hash_alg_ext_present = 1; + break; +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported elliptic curves extension" ) ); + + ret = ssl_parse_supported_elliptic_curves( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found supported point formats extension" ) ); + ssl->handshake->cli_exts |= MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT; + + ret = ssl_parse_supported_point_formats( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + case MBEDTLS_TLS_EXT_ECJPAKE_KKPP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found ecjpake kkpp extension" ) ); + + ret = ssl_parse_ecjpake_kkpp( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + case MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found max fragment length extension" ) ); + + ret = ssl_parse_max_fragment_length_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + case MBEDTLS_TLS_EXT_CID: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found CID extension" ) ); + + ret = ssl_parse_cid_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + case MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found encrypt then mac extension" ) ); + + ret = ssl_parse_encrypt_then_mac_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + case MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extended master secret extension" ) ); + + ret = ssl_parse_extended_ms_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + case MBEDTLS_TLS_EXT_SESSION_TICKET: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found session ticket extension" ) ); + + ret = ssl_parse_session_ticket_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) + case MBEDTLS_TLS_EXT_ALPN: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found alpn extension" ) ); + + ret = ssl_parse_alpn_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + case MBEDTLS_TLS_EXT_USE_SRTP: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found use_srtp extension" ) ); + + ret = ssl_parse_use_srtp_ext( ssl, ext + 4, ext_size ); + if( ret != 0 ) + return( ret ); + break; +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "unknown extension found: %u (ignoring)", + ext_id ) ); + } + + ext_len -= 4 + ext_size; + ext += 4 + ext_size; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + + /* + * Try to fall back to default hash SHA1 if the client + * hasn't provided any preferred signature-hash combinations. + */ + if( sig_hash_alg_ext_present == 0 ) + { + mbedtls_md_type_t md_default = MBEDTLS_MD_SHA1; + + if( mbedtls_ssl_check_sig_hash( ssl, md_default ) != 0 ) + md_default = MBEDTLS_MD_NONE; + + mbedtls_ssl_sig_hash_set_const_hash( &ssl->handshake->hash_algs, md_default ); + } + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + /* + * Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV + */ + for( i = 0, p = buf + ciph_offset + 2; i < ciph_len; i += 2, p += 2 ) + { + if( p[0] == 0 && p[1] == MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "received TLS_EMPTY_RENEGOTIATION_INFO " ) ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "received RENEGOTIATION SCSV " + "during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION; + break; + } + } + + /* + * Renegotiation security checks + */ + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation, breaking off handshake" ) ); + handshake_failure = 1; + } +#if defined(MBEDTLS_SSL_RENEGOTIATION) + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_SECURE_RENEGOTIATION && + renegotiation_info_seen == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension missing (secure)" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + ssl->conf->allow_legacy_renegotiation == MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "legacy renegotiation not allowed" ) ); + handshake_failure = 1; + } + else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS && + ssl->secure_renegotiation == MBEDTLS_SSL_LEGACY_RENEGOTIATION && + renegotiation_info_seen == 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "renegotiation_info extension present (legacy)" ) ); + handshake_failure = 1; + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + if( handshake_failure == 1 ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + /* + * Search for a matching ciphersuite + * (At the end because we need information from the EC-based extensions + * and certificate from the SNI callback triggered by the SNI extension.) + */ + got_common_suite = 0; + ciphersuites = ssl->conf->ciphersuite_list; + ciphersuite_info = NULL; + + if (ssl->conf->respect_cli_pref == MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_CLIENT) + { + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + for( i = 0; ciphersuites[i] != 0; i++ ) + { + if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + } else { + for( i = 0; ciphersuites[i] != 0; i++ ) + for( j = 0, p = buf + ciph_offset + 2; j < ciph_len; j += 2, p += 2 ) + { + if( MBEDTLS_GET_UINT16_BE(p, 0) != ciphersuites[i] ) + continue; + + got_common_suite = 1; + + if( ( ret = ssl_ciphersuite_match( ssl, ciphersuites[i], + &ciphersuite_info ) ) != 0 ) + return( ret ); + + if( ciphersuite_info != NULL ) + goto have_ciphersuite; + } + } + + if( got_common_suite ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got ciphersuites in common, " + "but none of them usable" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no ciphersuites in common" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + +have_ciphersuite: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "selected ciphersuite: %s", ciphersuite_info->name ) ); + + ssl->session_negotiate->ciphersuite = ciphersuites[i]; + ssl->handshake->ciphersuite_info = ciphersuite_info; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + /* Debugging-only output for testsuite */ +#if defined(MBEDTLS_DEBUG_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_pk_type_t sig_alg = mbedtls_ssl_get_ciphersuite_sig_alg( ciphersuite_info ); + if( sig_alg != MBEDTLS_PK_NONE ) + { + mbedtls_md_type_t md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello v3, signature_algorithm ext: %d", + mbedtls_ssl_hash_from_md_alg( md_alg ) ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no hash algorithm for signature algorithm " + "%u - should not happen", (unsigned) sig_alg ) ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client hello" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +static void ssl_write_cid_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + size_t ext_len; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + + *olen = 0; + + /* Skip writing the extension if we don't want to use it or if + * the client hasn't offered it. */ + if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_DISABLED ) + return; + + /* ssl->own_cid_len is at most MBEDTLS_SSL_CID_IN_LEN_MAX + * which is at most 255, so the increment cannot overflow. */ + if( end < p || (size_t)( end - p ) < (unsigned)( ssl->own_cid_len + 5 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding CID extension" ) ); + + /* + * Quoting draft-ietf-tls-dtls-connection-id-05 + * https://tools.ietf.org/html/draft-ietf-tls-dtls-connection-id-05 + * + * struct { + * opaque cid<0..2^8-1>; + * } ConnectionId; + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_CID, p, 0 ); + p += 2; + ext_len = (size_t) ssl->own_cid_len + 1; + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2; + + *p++ = (uint8_t) ssl->own_cid_len; + memcpy( p, ssl->own_cid, ssl->own_cid_len ); + + *olen = ssl->own_cid_len + 5; +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static void ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + const mbedtls_ssl_ciphersuite_t *suite = NULL; + const mbedtls_cipher_info_t *cipher = NULL; + + if( ssl->session_negotiate->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED ) + { + *olen = 0; + return; + } + + /* + * RFC 7366: "If a server receives an encrypt-then-MAC request extension + * from a client and then selects a stream or Authenticated Encryption + * with Associated Data (AEAD) ciphersuite, it MUST NOT send an + * encrypt-then-MAC response extension back to the client." + */ + if( ( suite = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ) ) == NULL || + ( cipher = mbedtls_cipher_info_from_type( suite->cipher ) ) == NULL || + cipher->mode != MBEDTLS_MODE_CBC ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding encrypt then mac extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static void ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding extended master secret " + "extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static void ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->handshake->new_session_ticket == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding session ticket extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SESSION_TICKET, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 0x00; + + *olen = 4; +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +static void ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->secure_renegotiation != MBEDTLS_SSL_SECURE_RENEGOTIATION ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, secure renegotiation extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_RENEGOTIATION_INFO, p, 0 ); + p += 2; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + { + *p++ = 0x00; + *p++ = ( ssl->verify_data_len * 2 + 1 ) & 0xFF; + *p++ = ssl->verify_data_len * 2 & 0xFF; + + memcpy( p, ssl->peer_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + memcpy( p, ssl->own_verify_data, ssl->verify_data_len ); + p += ssl->verify_data_len; + } + else +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + { + *p++ = 0x00; + *p++ = 0x01; + *p++ = 0x00; + } + + *olen = p - buf; +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static void ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + + if( ssl->session_negotiate->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, max_fragment_length extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 1; + + *p++ = ssl->session_negotiate->mfl_code; + + *olen = 5; +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + unsigned char *p = buf; + ((void) ssl); + + if( ( ssl->handshake->cli_exts & + MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT ) == 0 ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, supported_point_formats extension" ) ); + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS, p, 0 ); + p += 2; + + *p++ = 0x00; + *p++ = 2; + + *p++ = 1; + *p++ = MBEDTLS_ECP_PF_UNCOMPRESSED; + + *olen = 6; +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = buf; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + size_t kkpp_len; + + *olen = 0; + + /* Skip costly computation if not needed */ + if( ssl->handshake->ciphersuite_info->key_exchange != + MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, ecjpake kkpp extension" ) ); + + if( end - p < 4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ECJPAKE_KKPP, p, 0 ); + p += 2; + + ret = mbedtls_ecjpake_write_round_one( &ssl->handshake->ecjpake_ctx, + p + 2, end - p - 2, &kkpp_len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1 , "mbedtls_ecjpake_write_round_one", ret ); + return; + } + + MBEDTLS_PUT_UINT16_BE( kkpp_len, p, 0 ); + p += 2; + + *olen = kkpp_len + 4; +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_ALPN ) +static void ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, size_t *olen ) +{ + if( ssl->alpn_chosen == NULL ) + { + *olen = 0; + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding alpn extension" ) ); + + /* + * 0 . 1 ext identifier + * 2 . 3 ext length + * 4 . 5 protocol list length + * 6 . 6 protocol name length + * 7 . 7+n protocol name + */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_ALPN, buf, 0); + + *olen = 7 + strlen( ssl->alpn_chosen ); + + MBEDTLS_PUT_UINT16_BE( *olen - 4, buf, 2 ); + + MBEDTLS_PUT_UINT16_BE( *olen - 6, buf, 4 ); + + buf[6] = MBEDTLS_BYTE_0( *olen - 7 ); + + memcpy( buf + 7, ssl->alpn_chosen, *olen - 7 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP ) && defined(MBEDTLS_SSL_PROTO_DTLS) +static void ssl_write_use_srtp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t *olen ) +{ + size_t mki_len = 0, ext_len = 0; + uint16_t profile_value = 0; + const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + + *olen = 0; + + if( ( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) || + ( ssl->dtls_srtp_info.chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) ) + { + return; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, adding use_srtp extension" ) ); + + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_SUPPORTED ) + { + mki_len = ssl->dtls_srtp_info.mki_len; + } + + /* The extension total size is 9 bytes : + * - 2 bytes for the extension tag + * - 2 bytes for the total size + * - 2 bytes for the protection profile length + * - 2 bytes for the protection profile + * - 1 byte for the mki length + * + the actual mki length + * Check we have enough room in the output buffer */ + if( (size_t)( end - buf ) < mki_len + 9 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small" ) ); + return; + } + + /* extension */ + MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_USE_SRTP, buf, 0 ); + /* + * total length 5 and mki value: only one profile(2 bytes) + * and length(2 bytes) and srtp_mki ) + */ + ext_len = 5 + mki_len; + MBEDTLS_PUT_UINT16_BE( ext_len, buf, 2 ); + + /* protection profile length: 2 */ + buf[4] = 0x00; + buf[5] = 0x02; + profile_value = mbedtls_ssl_check_srtp_profile_value( + ssl->dtls_srtp_info.chosen_dtls_srtp_profile ); + if( profile_value != MBEDTLS_TLS_SRTP_UNSET ) + { + MBEDTLS_PUT_UINT16_BE( profile_value, buf, 6 ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "use_srtp extension invalid profile" ) ); + return; + } + + buf[8] = mki_len & 0xFF; + memcpy( &buf[9], ssl->dtls_srtp_info.mki_value, mki_len ); + + *olen = 9 + mki_len; +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = ssl->out_msg + 4; + unsigned char *cookie_len_byte; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello verify request" ) ); + + /* + * struct { + * ProtocolVersion server_version; + * opaque cookie<0..2^8-1>; + * } HelloVerifyRequest; + */ + + /* The RFC is not clear on this point, but sending the actual negotiated + * version looks like the most interoperable thing to do. */ + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server version", p, 2 ); + p += 2; + + /* If we get here, f_cookie_check is not null */ + if( ssl->conf->f_cookie_write == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Skip length byte until we know the length */ + cookie_len_byte = p++; + + if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie, + &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN, + ssl->cli_id, ssl->cli_id_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret ); + return( ret ); + } + + *cookie_len_byte = (unsigned char)( p - ( cookie_len_byte + 1 ) ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte ); + + ssl->out_msglen = p - ssl->out_msg; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST; + + ssl->state = MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello verify request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +static void ssl_handle_id_based_session_resumption( mbedtls_ssl_context *ssl ) +{ + int ret; + mbedtls_ssl_session session_tmp; + mbedtls_ssl_session * const session = ssl->session_negotiate; + + /* Resume is 0 by default, see ssl_handshake_init(). + * It may be already set to 1 by ssl_parse_session_ticket_ext(). */ + if( ssl->handshake->resume == 1 ) + return; + if( session->id_len == 0 ) + return; + if( ssl->conf->f_get_cache == NULL ) + return; +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE ) + return; +#endif + + mbedtls_ssl_session_init( &session_tmp ); + + ret = ssl->conf->f_get_cache( ssl->conf->p_cache, + session->id, + session->id_len, + &session_tmp ); + if( ret != 0 ) + goto exit; + + if( session->ciphersuite != session_tmp.ciphersuite || + session->compression != session_tmp.compression ) + { + /* Mismatch between cached and negotiated session */ + goto exit; + } + + /* Move semantics */ + mbedtls_ssl_session_free( session ); + *session = session_tmp; + memset( &session_tmp, 0, sizeof( session_tmp ) ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) ); + ssl->handshake->resume = 1; + +exit: + + mbedtls_ssl_session_free( &session_tmp ); +} + +static int ssl_write_server_hello( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_HAVE_TIME) + mbedtls_time_t t; +#endif + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen, ext_len = 0, n; + unsigned char *buf, *p; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello" ) ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->verify_cookie_len != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "client hello was not authenticated" ) ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ssl_write_hello_verify_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided") ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 5 protocol version + * 6 . 9 UNIX time() + * 10 . 37 random bytes + */ + buf = ssl->out_msg; + p = buf + 4; + + mbedtls_ssl_write_version( ssl->major_ver, ssl->minor_ver, + ssl->conf->transport, p ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen version: [%d:%d]", + buf[4], buf[5] ) ); + +#if defined(MBEDTLS_HAVE_TIME) + t = mbedtls_time( NULL ); + MBEDTLS_PUT_UINT32_BE( t, p, 0 ); + p += 4; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, current time: %" MBEDTLS_PRINTF_LONGLONG, + (long long) t ) ); +#else + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 4 ) ) != 0 ) + return( ret ); + + p += 4; +#endif /* MBEDTLS_HAVE_TIME */ + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, p, 28 ) ) != 0 ) + return( ret ); + + p += 28; + + memcpy( ssl->handshake->randbytes + 32, buf + 6, 32 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", buf + 6, 32 ); + + ssl_handle_id_based_session_resumption( ssl ); + + if( ssl->handshake->resume == 0 ) + { + /* + * New session, create a new session id, + * unless we're about to issue a session ticket + */ + ssl->state++; + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = mbedtls_time( NULL ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + { + ssl->session_negotiate->id_len = n = 0; + memset( ssl->session_negotiate->id, 0, 32 ); + } + else +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + { + ssl->session_negotiate->id_len = n = 32; + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, ssl->session_negotiate->id, + n ) ) != 0 ) + return( ret ); + } + } + else + { + /* + * Resuming a session + */ + n = ssl->session_negotiate->id_len; + ssl->state = MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC; + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + } + + /* + * 38 . 38 session id length + * 39 . 38+n session id + * 39+n . 40+n chosen ciphersuite + * 41+n . 41+n chosen compression alg. + * 42+n . 43+n extensions length + * 44+n . 43+n+m extensions + */ + *p++ = (unsigned char) ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, session id len.: %" MBEDTLS_PRINTF_SIZET, n ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, session id", buf + 39, n ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "%s session has been resumed", + ssl->handshake->resume ? "a" : "no" ) ); + + MBEDTLS_PUT_UINT16_BE( ssl->session_negotiate->ciphersuite, p, 0 ); + p += 2; + *p++ = MBEDTLS_BYTE_0( ssl->session_negotiate->compression ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", + mbedtls_ssl_get_ciphersuite_name( ssl->session_negotiate->ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, compress alg.: 0x%02X", + (unsigned int) ssl->session_negotiate->compression ) ); + + /* + * First write extensions, then the total length + */ + ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + ssl_write_cid_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + ssl_write_alpn_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + ssl_write_use_srtp_ext( ssl, p + 2 + ext_len, &olen ); + ext_len += olen; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, total extension length: %" MBEDTLS_PRINTF_SIZET, + ext_len ) ); + + if( ext_len > 0 ) + { + MBEDTLS_PUT_UINT16_BE( ext_len, p, 0 ); + p += 2 + ext_len; + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO; + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello" ) ); + + return( ret ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + uint16_t dn_size, total_dn_size; /* excluding length bytes */ + size_t ct_len, sa_len; /* including length bytes */ + unsigned char *buf, *p; + const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN; + const mbedtls_x509_crt *crt; + int authmode; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) ); + + ssl->state++; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) + authmode = ssl->handshake->sni_authmode; + else +#endif + authmode = ssl->conf->authmode; + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) || + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) ); + return( 0 ); + } + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 4 cert type count + * 5 .. m-1 cert types + * m .. m+1 sig alg length (TLS 1.2 only) + * m+1 .. n-1 SignatureAndHashAlgorithms (TLS 1.2 only) + * n .. n+1 length of all DNs + * n+2 .. n+3 length of DN 1 + * n+4 .. ... Distinguished Name #1 + * ... .. ... length of DN 2, etc. + */ + buf = ssl->out_msg; + p = buf + 4; + + /* + * Supported certificate types + * + * ClientCertificateType certificate_types<1..2^8-1>; + * enum { (255) } ClientCertificateType; + */ + ct_len = 0; + +#if defined(MBEDTLS_RSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN; +#endif + + p[0] = (unsigned char) ct_len++; + p += ct_len; + + sa_len = 0; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* + * Add signature_algorithms for verify (TLS 1.2) + * + * SignatureAndHashAlgorithm supported_signature_algorithms<2..2^16-2>; + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * enum { (255) } HashAlgorithm; + * enum { (255) } SignatureAlgorithm; + */ + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + const int *cur; + + /* + * Supported signature algorithms + */ + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + { + unsigned char hash = mbedtls_ssl_hash_from_md_alg( *cur ); + + if( MBEDTLS_SSL_HASH_NONE == hash || mbedtls_ssl_set_calc_verify_md( ssl, hash ) ) + continue; + +#if defined(MBEDTLS_RSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_RSA; +#endif +#if defined(MBEDTLS_ECDSA_C) + p[2 + sa_len++] = hash; + p[2 + sa_len++] = MBEDTLS_SSL_SIG_ECDSA; +#endif + } + + MBEDTLS_PUT_UINT16_BE( sa_len, p, 0 ); + sa_len += 2; + p += sa_len; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + /* + * DistinguishedName certificate_authorities<0..2^16-1>; + * opaque DistinguishedName<1..2^16-1>; + */ + p += 2; + + total_dn_size = 0; + + if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) + { + /* NOTE: If trusted certificates are provisioned + * via a CA callback (configured through + * `mbedtls_ssl_conf_ca_cb()`, then the + * CertificateRequest is currently left empty. */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + crt = ssl->handshake->sni_ca_chain; + else +#endif + crt = ssl->conf->ca_chain; + + while( crt != NULL && crt->version != 0 ) + { + /* It follows from RFC 5280 A.1 that this length + * can be represented in at most 11 bits. */ + dn_size = (uint16_t) crt->subject_raw.len; + + if( end < p || (size_t)( end - p ) < 2 + (size_t) dn_size ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skipping CAs: buffer too short" ) ); + break; + } + + MBEDTLS_PUT_UINT16_BE( dn_size, p, 0 ); + p += 2; + memcpy( p, crt->subject_raw.p, dn_size ); + p += dn_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "requested DN", p - dn_size, dn_size ); + + total_dn_size += 2 + dn_size; + crt = crt->next; + } + } + + ssl->out_msglen = p - buf; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST; + MBEDTLS_PUT_UINT16_BE( total_dn_size, ssl->out_msg, 4 + ct_len + sa_len ); + + ret = mbedtls_ssl_write_handshake_msg( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate request" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) +static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_ECKEY ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) ); + return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); + } + + if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, + mbedtls_pk_ec( *mbedtls_ssl_own_key( ssl ) ), + MBEDTLS_ECDH_OURS ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_get_params" ), ret ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2; + size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN + - sig_start ); + int ret = ssl->conf->f_async_resume( ssl, + sig_start, signature_len, sig_max_len ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret ); + return( ret ); +} +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + +/* Prepare the ServerKeyExchange message, up to and including + * calculating the signature if any, but excluding formatting the + * signature and sending the message. */ +static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl, + size_t *signature_len ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED) +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + unsigned char *dig_signed = NULL; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */ + + (void) ciphersuite_info; /* unused in some configurations */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + (void) signature_len; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len - ( ssl->out_msg - ssl->out_buf ); +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - ( ssl->out_msg - ssl->out_buf ); +#endif +#endif + + ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */ + + /* + * + * Part 1: Provide key exchange parameters for chosen ciphersuite. + * + */ + + /* + * - ECJPAKE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + ret = mbedtls_ecjpake_write_round_two( + &ssl->handshake->ecjpake_ctx, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret ); + return( ret ); + } + + ssl->out_msglen += len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + + /* + * For (EC)DHE key exchanges with PSK, parameters are prefixed by support + * identity hint (RFC 4279, Sec. 3). Until someone needs this feature, + * we use empty support identity hints here. + **/ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + ssl->out_msg[ssl->out_msglen++] = 0x00; + ssl->out_msg[ssl->out_msglen++] = 0x00; + } +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + + /* + * - DHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Ephemeral DH parameters: + * + * struct { + * opaque dh_p<1..2^16-1>; + * opaque dh_g<1..2^16-1>; + * opaque dh_Ys<1..2^16-1>; + * } ServerDHParams; + */ + if( ( ret = mbedtls_dhm_set_group( &ssl->handshake->dhm_ctx, + &ssl->conf->dhm_P, + &ssl->conf->dhm_G ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_set_group", ret ); + return( ret ); + } + + if( ( ret = mbedtls_dhm_make_params( + &ssl->handshake->dhm_ctx, + (int) mbedtls_dhm_get_len( &ssl->handshake->dhm_ctx ), + ssl->out_msg + ssl->out_msglen, &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: G ", &ssl->handshake->dhm_ctx.G ); + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GX", &ssl->handshake->dhm_ctx.GX ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED */ + + /* + * - ECDHE key exchanges + */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdhe( ciphersuite_info ) ) + { + /* + * Ephemeral ECDH parameters: + * + * struct { + * ECParameters curve_params; + * ECPoint public; + * } ServerECDHParams; + */ + const mbedtls_ecp_curve_info **curve = NULL; + const uint16_t *group_list = mbedtls_ssl_get_groups( ssl ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* Match our preference list against the offered curves */ + if( group_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + for( ; *group_list != 0; group_list++ ) + for( curve = ssl->handshake->curves; *curve != NULL; curve++ ) + if( (*curve)->tls_id == *group_list ) + goto curve_matching_done; + +curve_matching_done: + if( curve == NULL || *curve == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no matching curve for ECDHE" ) ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDHE curve: %s", (*curve)->name ) ); + + if( ( ret = mbedtls_ecdh_setup( &ssl->handshake->ecdh_ctx, + (*curve)->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecp_group_load", ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_make_params( + &ssl->handshake->ecdh_ctx, &len, + ssl->out_msg + ssl->out_msglen, + MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret ); + return( ret ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + dig_signed = ssl->out_msg + ssl->out_msglen; +#endif + + ssl->out_msglen += len; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + + /* + * + * Part 2: For key exchanges involving the server signing the + * exchange parameters, compute and add the signature here. + * + */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) ) + { + size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed; + size_t hashlen = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + unsigned char hash[PSA_HASH_MAX_SIZE]; +#else + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; +#endif + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * 2.1: Choose hash algorithm: + * For TLS 1.2, obey signature-hash-algorithm extension + * to choose appropriate hash. + */ + + mbedtls_md_type_t md_alg; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t sig_alg = + mbedtls_ssl_get_ciphersuite_sig_pk_alg( ciphersuite_info ); + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* For TLS 1.2, obey signature-hash-algorithm extension + * (RFC 5246, Sec. 7.4.1.4.1). */ + if( sig_alg == MBEDTLS_PK_NONE || + ( md_alg = mbedtls_ssl_sig_hash_set_find( &ssl->handshake->hash_algs, + sig_alg ) ) == MBEDTLS_MD_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + /* (... because we choose a cipher suite + * only if there is a matching hash.) */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %u for signing", (unsigned) md_alg ) ); + + /* + * 2.2: Compute the hash to be signed + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( md_alg != MBEDTLS_MD_NONE ) + { + ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen, + dig_signed, + dig_signed_len, + md_alg ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen ); + + /* + * 2.3: Compute and add the signature + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + /* + * For TLS 1.2, we need to specify signature and hash algorithm + * explicitly through a prefix to the signature. + * + * struct { + * HashAlgorithm hash; + * SignatureAlgorithm signature; + * } SignatureAndHashAlgorithm; + * + * struct { + * SignatureAndHashAlgorithm algorithm; + * opaque signature<0..2^16-1>; + * } DigitallySigned; + * + */ + + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_hash_from_md_alg( md_alg ); + ssl->out_msg[ssl->out_msglen++] = + mbedtls_ssl_sig_from_pk_alg( sig_alg ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_sign_start != NULL ) + { + ret = ssl->conf->f_async_sign_start( ssl, + mbedtls_ssl_own_cert( ssl ), + md_alg, hash, hashlen ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_sign was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_server_key_exchange( ssl, signature_len ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( mbedtls_ssl_own_key( ssl ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* Append the signature to ssl->out_msg, leaving 2 bytes for the + * signature length which will be added in ssl_write_server_key_exchange + * after the call to ssl_prepare_server_key_exchange. + * ssl_write_server_key_exchange also takes care of incrementing + * ssl->out_msglen. */ + if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), + md_alg, hash, hashlen, + ssl->out_msg + ssl->out_msglen + 2, + out_buf_len - ssl->out_msglen - 2, + signature_len, + ssl->conf->f_rng, + ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + return( 0 ); +} + +/* Prepare the ServerKeyExchange message and send it. For ciphersuites + * that do not include a ServerKeyExchange message, do nothing. Either + * way, if successful, move on to the next step in the SSL state + * machine. */ +static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t signature_len = 0; +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED) + /* Extract static ECDH parameters and abort if ServerKeyExchange + * is not needed. */ + if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) ) + { + /* For suites involving ECDH, extract DH parameters + * from certificate at this point. */ +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) ) + { + ssl_get_ecdh_params_from_cert( ssl ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */ + + /* Key exchanges not involving ephemeral keys don't use + * ServerKeyExchange, so end here. */ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) ); + ssl->state++; + return( 0 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && \ + defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already prepared the message and there is an ongoing + * signature operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) ); + ret = ssl_resume_server_key_exchange( ssl, &signature_len ); + } + else +#endif /* defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) && + defined(MBEDTLS_SSL_ASYNC_PRIVATE) */ + { + /* ServerKeyExchange is needed. Prepare the message. */ + ret = ssl_prepare_server_key_exchange( ssl, &signature_len ); + } + + if( ret != 0 ) + { + /* If we're starting to write a new message, set ssl->out_msglen + * to 0. But if we're resuming after an asynchronous message, + * out_msglen is the amount of data written so far and mst be + * preserved. */ + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) ); + else + ssl->out_msglen = 0; + return( ret ); + } + + /* If there is a signature, write its length. + * ssl_prepare_server_key_exchange already wrote the signature + * itself at its proper place in the output buffer. */ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED) + if( signature_len != 0 ) + { + ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_1( signature_len ); + ssl->out_msg[ssl->out_msglen++] = MBEDTLS_BYTE_0( signature_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", + ssl->out_msg + ssl->out_msglen, + signature_len ); + + /* Skip over the already-written signature */ + ssl->out_msglen += signature_len; + } +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */ + + /* Add header and send. */ + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) ); + return( 0 ); +} + +static int ssl_write_server_hello_done( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server hello done" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_HELLO_DONE; + + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server hello done" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) +static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t n; + + /* + * Receive G^Y mod P, premaster = (G^Y)^X mod P + */ + if( *p + 2 > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( *p + n > end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + if( ( ret = mbedtls_dhm_read_public( &ssl->handshake->dhm_ctx, *p, n ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_read_public", ret ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + *p += n; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: GY", &ssl->handshake->dhm_ctx.GY ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = ssl->conf->f_async_resume( ssl, + peer_pms, peer_pmslen, peer_pmssize ); + if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + { + ssl->handshake->async_in_progress = 0; + mbedtls_ssl_set_async_operation_data( ssl, NULL ); + } + MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret ); + return( ret ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + unsigned char *peer_pms, + size_t *peer_pmslen, + size_t peer_pmssize ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl ); + mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk; + size_t len = mbedtls_pk_get_len( public_key ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + /* If we have already started decoding the message and there is an ongoing + * decryption operation, resume signing. */ + if( ssl->handshake->async_in_progress != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) ); + return( ssl_resume_decrypt_pms( ssl, + peer_pms, peer_pmslen, peer_pmssize ) ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + /* + * Prepare to decrypt the premaster using own private RSA key + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if ( p + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + if( *p++ != MBEDTLS_BYTE_1( len ) || + *p++ != MBEDTLS_BYTE_0( len ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } +#endif + + if( p + len != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * Decrypt the premaster secret + */ +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_decrypt_start != NULL ) + { + ret = ssl->conf->f_async_decrypt_start( ssl, + mbedtls_ssl_own_cert( ssl ), + p, len ); + switch( ret ) + { + case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: + /* act as if f_async_decrypt_start was null */ + break; + case 0: + ssl->handshake->async_in_progress = 1; + return( ssl_resume_decrypt_pms( ssl, + peer_pms, + peer_pmslen, + peer_pmssize ) ); + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: + ssl->handshake->async_in_progress = 1; + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + default: + MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + ret = mbedtls_pk_decrypt( private_key, p, len, + peer_pms, peer_pmslen, peer_pmssize, + ssl->conf->f_rng, ssl->conf->p_rng ); + return( ret ); +} + +static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, + const unsigned char *p, + const unsigned char *end, + size_t pms_offset ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *pms = ssl->handshake->premaster + pms_offset; + unsigned char ver[2]; + unsigned char fake_pms[48], peer_pms[48]; + unsigned char mask; + size_t i, peer_pmslen; + unsigned int diff; + + /* In case of a failure in decryption, the decryption may write less than + * 2 bytes of output, but we always read the first two bytes. It doesn't + * matter in the end because diff will be nonzero in that case due to + * ret being nonzero, and we only care whether diff is 0. + * But do initialize peer_pms and peer_pmslen for robustness anyway. This + * also makes memory analyzers happy (don't access uninitialized memory, + * even if it's an unsigned char). */ + peer_pms[0] = peer_pms[1] = ~0; + peer_pmslen = 0; + + ret = ssl_decrypt_encrypted_pms( ssl, p, end, + peer_pms, + &peer_pmslen, + sizeof( peer_pms ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ) + return( ret ); +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + mbedtls_ssl_write_version( ssl->handshake->max_major_ver, + ssl->handshake->max_minor_ver, + ssl->conf->transport, ver ); + + /* Avoid data-dependent branches while checking for invalid + * padding, to protect against timing-based Bleichenbacher-type + * attacks. */ + diff = (unsigned int) ret; + diff |= peer_pmslen ^ 48; + diff |= peer_pms[0] ^ ver[0]; + diff |= peer_pms[1] ^ ver[1]; + + /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */ + mask = mbedtls_ct_uint_mask( diff ); + + /* + * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding + * must not cause the connection to end immediately; instead, send a + * bad_record_mac later in the handshake. + * To protect against timing-based variants of the attack, we must + * not have any branch that depends on whether the decryption was + * successful. In particular, always generate the fake premaster secret, + * regardless of whether it will ultimately influence the output or not. + */ + ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) ); + if( ret != 0 ) + { + /* It's ok to abort on an RNG failure, since this does not reveal + * anything about the RSA decryption. */ + return( ret ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + if( diff != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); +#endif + + if( sizeof( ssl->handshake->premaster ) < pms_offset || + sizeof( ssl->handshake->premaster ) - pms_offset < 48 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + ssl->handshake->pmslen = 48; + + /* Set pms to either the true or the fake PMS, without + * data-dependent branches. */ + for( i = 0; i < ssl->handshake->pmslen; i++ ) + pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] ); + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned char **p, + const unsigned char *end ) +{ + int ret = 0; + uint16_t n; + + if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); + return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + } + + /* + * Receive client pre-shared key identity name + */ + if( end - *p < 2 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + n = ( (*p)[0] << 8 ) | (*p)[1]; + *p += 2; + + if( n == 0 || n > end - *p ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + if( ssl->conf->f_psk != NULL ) + { + if( ssl->conf->f_psk( ssl->conf->p_psk, ssl, *p, n ) != 0 ) + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + else + { + /* Identity is not a big secret since clients send it in the clear, + * but treat it carefully anyway, just in case */ + if( n != ssl->conf->psk_identity_len || + mbedtls_ct_memcmp( ssl->conf->psk_identity, *p, n ) != 0 ) + { + ret = MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY; + } + } + + if( ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Unknown PSK identity", *p, n ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY ); + return( MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY ); + } + + *p += n; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char *p, *end; + + ciphersuite_info = ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) ); + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) + if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) && + ( ssl->handshake->async_in_progress != 0 ) ) + { + /* We've already read a record and there is an asynchronous + * operation in progress to decrypt it. So skip reading the + * record. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) ); + } + else +#endif + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); + end = ssl->in_msg + ssl->in_hslen; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_RSA ) + { + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + ssl->handshake->premaster, + MBEDTLS_PREMASTER_SIZE, + &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_RSA || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA ) + { + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, + &ssl->handshake->pmslen, + ssl->handshake->premaster, + MBEDTLS_MPI_MAX_SIZE, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || + MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically + * and skip the intermediate PMS. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if ( ssl->handshake->async_in_progress != 0 ) + { + /* There is an asynchronous operation in progress to + * decrypt the encrypted premaster secret, so skip + * directly to resuming this operation. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) ); + /* Update p to skip the PSK identity. ssl_parse_encrypted_pms + * won't actually use it, but maintain p anyway for robustness. */ + p += ssl->conf->psk_identity_len + 2; + } + else +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + if( ( ret = ssl_parse_client_dh_public( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_dh_public" ), ret ); + return( ret ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret ); + return( ret ); + } + + if( ( ret = mbedtls_ecdh_read_public( &ssl->handshake->ecdh_ctx, + p, end - p ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_read_public", ret ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, + ciphersuite_info->key_exchange ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_psk_derive_premaster", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) + { + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_parse_encrypted_pms_secret" ), ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + ret = mbedtls_ecjpake_read_round_two( &ssl->handshake->ecjpake_ctx, + p, end - p ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_read_round_two", ret ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + ret = mbedtls_ecjpake_derive_secret( &ssl->handshake->ecjpake_ctx, + ssl->handshake->premaster, 32, &ssl->handshake->pmslen, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_derive_secret", ret ); + return( ret ); + } + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); + return( ret ); + } + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse client key exchange" ) ); + + return( 0 ); +} + +#if !defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#else /* !MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, sig_len; + unsigned char hash[48]; + unsigned char *hash_start = hash; + size_t hashlen; +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + mbedtls_pk_type_t pk_alg; +#endif + mbedtls_md_type_t md_alg; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + mbedtls_pk_context * peer_pk; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( ssl->session_negotiate->peer_cert == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert_digest == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) ); + ssl->state++; + return( 0 ); + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* Read the message without adding it to the checksum */ + ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ ); + if( 0 != ret ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record" ), ret ); + return( ret ); + } + + ssl->state++; + + /* Process the message contents */ + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE_VERIFY ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + peer_pk = &ssl->handshake->peer_pubkey; +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( ssl->session_negotiate->peer_cert == NULL ) + { + /* Should never happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + peer_pk = &ssl->session_negotiate->peer_cert->pk; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + /* + * struct { + * SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only + * opaque signature<0..2^16-1>; + * } DigitallySigned; + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* + * Hash + */ + md_alg = mbedtls_ssl_md_alg_from_hash( ssl->in_msg[i] ); + + if( md_alg == MBEDTLS_MD_NONE || mbedtls_ssl_set_calc_verify_md( ssl, ssl->in_msg[i] ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + +#if !defined(MBEDTLS_MD_SHA1) + if( MBEDTLS_MD_SHA1 == md_alg ) + hash_start += 16; +#endif + + /* Info from md_alg will be used instead */ + hashlen = 0; + + i++; + + /* + * Signature + */ + if( ( pk_alg = mbedtls_ssl_pk_alg_from_sig( ssl->in_msg[i] ) ) + == MBEDTLS_PK_NONE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "peer not adhering to requested sig_alg" + " for verify message" ) ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + /* + * Check the certificate's key type matches the signature alg + */ + if( !mbedtls_pk_can_do( peer_pk, pk_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + i++; + } + else +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( i + 2 > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + sig_len = ( ssl->in_msg[i] << 8 ) | ssl->in_msg[i+1]; + i += 2; + + if( i + sig_len != ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate verify message" ) ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Calculate hash and verify signature */ + { + size_t dummy_hlen; + ssl->handshake->calc_verify( ssl, hash, &dummy_hlen ); + } + + if( ( ret = mbedtls_pk_verify( peer_pk, + md_alg, hash_start, hashlen, + ssl->in_msg + i, sig_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); + return( ret ); + } + + mbedtls_ssl_update_handshake_status( ssl ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tlen; + uint32_t lifetime; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write new session ticket" ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_NEW_SESSION_TICKET; + + /* + * struct { + * uint32 ticket_lifetime_hint; + * opaque ticket<0..2^16-1>; + * } NewSessionTicket; + * + * 4 . 7 ticket_lifetime_hint (0 = unspecified) + * 8 . 9 ticket_len (n) + * 10 . 9+n ticket content + */ + + if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket, + ssl->session_negotiate, + ssl->out_msg + 10, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &tlen, &lifetime ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret ); + tlen = 0; + } + + MBEDTLS_PUT_UINT32_BE( lifetime, ssl->out_msg, 4 ); + MBEDTLS_PUT_UINT16_BE( tlen, ssl->out_msg, 8 ); + ssl->out_msglen = 10 + tlen; + + /* + * Morally equivalent to updating ssl->state, but NewSessionTicket and + * ChangeCipherSpec share the same state. + */ + ssl->handshake->new_session_ticket = 0; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +/* + * SSL handshake -- server side -- single step + */ +int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "server state: %d", ssl->state ) ); + + switch( ssl->state ) + { + case MBEDTLS_SSL_HELLO_REQUEST: + ssl->state = MBEDTLS_SSL_CLIENT_HELLO; + break; + + /* + * <== ClientHello + */ + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_parse_client_hello( ssl ); + break; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT: + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); +#endif + + /* + * ==> ServerHello + * Certificate + * ( ServerKeyExchange ) + * ( CertificateRequest ) + * ServerHelloDone + */ + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_write_server_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = mbedtls_ssl_write_certificate( ssl ); + break; + + case MBEDTLS_SSL_SERVER_KEY_EXCHANGE: + ret = ssl_write_server_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_write_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO_DONE: + ret = ssl_write_server_hello_done( ssl ); + break; + + /* + * <== ( Certificate/Alert ) + * ClientKeyExchange + * ( CertificateVerify ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_CLIENT_CERTIFICATE: + ret = mbedtls_ssl_parse_certificate( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE: + ret = ssl_parse_client_key_exchange( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_parse_certificate_verify( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC: + ret = mbedtls_ssl_parse_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = mbedtls_ssl_parse_finished( ssl ); + break; + + /* + * ==> ( NewSessionTicket ) + * ChangeCipherSpec + * Finished + */ + case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC: +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ssl->handshake->new_session_ticket != 0 ) + ret = ssl_write_new_session_ticket( ssl ); + else +#endif + ret = mbedtls_ssl_write_change_cipher_spec( ssl ); + break; + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = mbedtls_ssl_write_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + mbedtls_ssl_handshake_wrapup( ssl ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} + +void mbedtls_ssl_conf_preference_order( mbedtls_ssl_config *conf, int order ) +{ + conf->respect_cli_pref = order; +} + +#endif /* MBEDTLS_SSL_SRV_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_ticket.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_ticket.c new file mode 100644 index 00000000..e998111d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_ticket.c @@ -0,0 +1,402 @@ +/* + * TLS server tickets callbacks implementation + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "ssl_misc.h" +#include "mbedtls/ssl_ticket.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" + +#include + +/* + * Initialze context + */ +void mbedtls_ssl_ticket_init( mbedtls_ssl_ticket_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ssl_ticket_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +#define MAX_KEY_BYTES 32 /* 256 bits */ + +#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_IV_BYTES 12 +#define TICKET_CRYPT_LEN_BYTES 2 +#define TICKET_AUTH_TAG_BYTES 16 + +#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES + \ + TICKET_AUTH_TAG_BYTES ) +#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES ) + +/* + * Generate/update a key + */ +static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, + unsigned char index ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MAX_KEY_BYTES]; + mbedtls_ssl_ticket_key *key = ctx->keys + index; + +#if defined(MBEDTLS_HAVE_TIME) + key->generation_time = (uint32_t) mbedtls_time( NULL ); +#endif + + if( ( ret = ctx->f_rng( ctx->p_rng, key->name, sizeof( key->name ) ) ) != 0 ) + return( ret ); + + if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) + return( ret ); + + /* With GCM and CCM, same context can encrypt & decrypt */ + ret = mbedtls_cipher_setkey( &key->ctx, buf, + mbedtls_cipher_get_key_bitlen( &key->ctx ), + MBEDTLS_ENCRYPT ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Rotate/generate keys if necessary + */ +static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) +{ +#if !defined(MBEDTLS_HAVE_TIME) + ((void) ctx); +#else + if( ctx->ticket_lifetime != 0 ) + { + uint32_t current_time = (uint32_t) mbedtls_time( NULL ); + uint32_t key_time = ctx->keys[ctx->active].generation_time; + + if( current_time >= key_time && + current_time - key_time < ctx->ticket_lifetime ) + { + return( 0 ); + } + + ctx->active = 1 - ctx->active; + + return( ssl_ticket_gen_key( ctx, ctx->active ) ); + } + else +#endif /* MBEDTLS_HAVE_TIME */ + return( 0 ); +} + +/* + * Setup context for actual use + */ +int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_cipher_type_t cipher, + uint32_t lifetime ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_cipher_info_t *cipher_info; + + ctx->f_rng = f_rng; + ctx->p_rng = p_rng; + + ctx->ticket_lifetime = lifetime; + + cipher_info = mbedtls_cipher_info_from_type( cipher); + + if( mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_GCM && + mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CCM ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( mbedtls_cipher_info_get_key_bitlen( cipher_info ) > 8 * MAX_KEY_BYTES ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx, + cipher_info, TICKET_AUTH_TAG_BYTES ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + return( ret ); + /* We don't yet expect to support all ciphers through PSA, + * so allow fallback to ordinary mbedtls_cipher_setup(). */ + if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx, + cipher_info, TICKET_AUTH_TAG_BYTES ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + return( ret ); + if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) + return( ret ); + + if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || + ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Create session ticket, with the following structure: + * + * struct { + * opaque key_name[4]; + * opaque iv[12]; + * opaque encrypted_state<0..2^16-1>; + * opaque tag[16]; + * } ticket; + * + * The key_name, iv, and length of encrypted_state are the additional + * authenticated data. + */ + +int mbedtls_ssl_ticket_write( void *p_ticket, + const mbedtls_ssl_session *session, + unsigned char *start, + const unsigned char *end, + size_t *tlen, + uint32_t *ticket_lifetime ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = start; + unsigned char *iv = start + TICKET_KEY_NAME_BYTES; + unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; + unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; + size_t clear_len, ciph_len; + + *tlen = 0; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* We need at least 4 bytes for key_name, 12 for IV, 2 for len 16 for tag, + * in addition to session itself, that will be checked when writing it. */ + MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + key = &ctx->keys[ctx->active]; + + *ticket_lifetime = ctx->ticket_lifetime; + + memcpy( key_name, key->name, TICKET_KEY_NAME_BYTES ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 0 ) + goto cleanup; + + /* Dump session state */ + if( ( ret = mbedtls_ssl_session_save( session, + state, end - state, + &clear_len ) ) != 0 || + (unsigned long) clear_len > 65535 ) + { + goto cleanup; + } + MBEDTLS_PUT_UINT16_BE( clear_len, state_len_bytes, 0 ); + + /* Encrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, + state, end - state, &ciph_len, + TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len + TICKET_AUTH_TAG_BYTES ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = TICKET_MIN_LEN + ciph_len - TICKET_AUTH_TAG_BYTES; + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Select key based on name + */ +static mbedtls_ssl_ticket_key *ssl_ticket_select_key( + mbedtls_ssl_ticket_context *ctx, + const unsigned char name[4] ) +{ + unsigned char i; + + for( i = 0; i < sizeof( ctx->keys ) / sizeof( *ctx->keys ); i++ ) + if( memcmp( name, ctx->keys[i].name, 4 ) == 0 ) + return( &ctx->keys[i] ); + + return( NULL ); +} + +/* + * Load session ticket (see mbedtls_ssl_ticket_write for structure) + */ +int mbedtls_ssl_ticket_parse( void *p_ticket, + mbedtls_ssl_session *session, + unsigned char *buf, + size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_ticket_context *ctx = p_ticket; + mbedtls_ssl_ticket_key *key; + unsigned char *key_name = buf; + unsigned char *iv = buf + TICKET_KEY_NAME_BYTES; + unsigned char *enc_len_p = iv + TICKET_IV_BYTES; + unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( len < TICKET_MIN_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + if( ( ret = ssl_ticket_update_keys( ctx ) ) != 0 ) + goto cleanup; + + enc_len = ( enc_len_p[0] << 8 ) | enc_len_p[1]; + + if( len != TICKET_MIN_LEN + enc_len ) + { + ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; + goto cleanup; + } + + /* Select key */ + if( ( key = ssl_ticket_select_key( ctx, key_name ) ) == NULL ) + { + /* We can't know for sure but this is a likely option unless we're + * under attack - this is only informative anyway */ + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + + /* Decrypt and authenticate */ + if( ( ret = mbedtls_cipher_auth_decrypt_ext( &key->ctx, + iv, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len + TICKET_AUTH_TAG_BYTES, + ticket, enc_len, &clear_len, + TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED ) + ret = MBEDTLS_ERR_SSL_INVALID_MAC; + + goto cleanup; + } + if( clear_len != enc_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + /* Actually load session */ + if( ( ret = mbedtls_ssl_session_load( session, ticket, clear_len ) ) != 0 ) + goto cleanup; + +#if defined(MBEDTLS_HAVE_TIME) + { + /* Check for expiration */ + mbedtls_time_t current_time = mbedtls_time( NULL ); + + if( current_time < session->start || + (uint32_t)( current_time - session->start ) > ctx->ticket_lifetime ) + { + ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED; + goto cleanup; + } + } +#endif + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Free context + */ +void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) +{ + mbedtls_cipher_free( &ctx->keys[0].ctx ); + mbedtls_cipher_free( &ctx->keys[1].ctx ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ssl_ticket_context ) ); +} + +#endif /* MBEDTLS_SSL_TICKET_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls.c new file mode 100644 index 00000000..d868e496 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls.c @@ -0,0 +1,7192 @@ +/* + * TLS shared functions + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * http://www.ietf.org/rfc/rfc2246.txt + * http://www.ietf.org/rfc/rfc4346.txt + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl.h" +#include "ssl_misc.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/version.h" +#include "mbedtls/constant_time.h" + +#include + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "mbedtls/psa_util.h" +#include "psa/crypto.h" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +/* Top-level Connection ID API */ + +int mbedtls_ssl_conf_cid( mbedtls_ssl_config *conf, + size_t len, + int ignore_other_cid ) +{ + if( len > MBEDTLS_SSL_CID_IN_LEN_MAX ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_FAIL && + ignore_other_cid != MBEDTLS_SSL_UNEXPECTED_CID_IGNORE ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->ignore_unexpected_cid = ignore_other_cid; + conf->cid_len = len; + return( 0 ); +} + +int mbedtls_ssl_set_cid( mbedtls_ssl_context *ssl, + int enable, + unsigned char const *own_cid, + size_t own_cid_len ) +{ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->negotiate_cid = enable; + if( enable == MBEDTLS_SSL_CID_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Disable use of CID extension." ) ); + return( 0 ); + } + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Enable use of CID extension." ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Own CID", own_cid, own_cid_len ); + + if( own_cid_len != ssl->conf->cid_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "CID length %u does not match CID length %u in config", + (unsigned) own_cid_len, + (unsigned) ssl->conf->cid_len ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + memcpy( ssl->own_cid, own_cid, own_cid_len ); + /* Truncation is not an issue here because + * MBEDTLS_SSL_CID_IN_LEN_MAX at most 255. */ + ssl->own_cid_len = (uint8_t) own_cid_len; + + return( 0 ); +} + +int mbedtls_ssl_get_peer_cid( mbedtls_ssl_context *ssl, + int *enabled, + unsigned char peer_cid[ MBEDTLS_SSL_CID_OUT_LEN_MAX ], + size_t *peer_cid_len ) +{ + *enabled = MBEDTLS_SSL_CID_DISABLED; + + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* We report MBEDTLS_SSL_CID_DISABLED in case the CID extensions + * were used, but client and server requested the empty CID. + * This is indistinguishable from not using the CID extension + * in the first place. */ + if( ssl->transform_in->in_cid_len == 0 && + ssl->transform_in->out_cid_len == 0 ) + { + return( 0 ); + } + + if( peer_cid_len != NULL ) + { + *peer_cid_len = ssl->transform_in->out_cid_len; + if( peer_cid != NULL ) + { + memcpy( peer_cid, ssl->transform_in->out_cid, + ssl->transform_in->out_cid_len ); + } + } + + *enabled = MBEDTLS_SSL_CID_ENABLED; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +/* + * Convert max_fragment_length codes to length. + * RFC 6066 says: + * enum{ + * 2^9(1), 2^10(2), 2^11(3), 2^12(4), (255) + * } MaxFragmentLength; + * and we add 0 -> extension unused + */ +static unsigned int ssl_mfl_code_to_length( int mfl ) +{ + switch( mfl ) + { + case MBEDTLS_SSL_MAX_FRAG_LEN_NONE: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + case MBEDTLS_SSL_MAX_FRAG_LEN_512: + return 512; + case MBEDTLS_SSL_MAX_FRAG_LEN_1024: + return 1024; + case MBEDTLS_SSL_MAX_FRAG_LEN_2048: + return 2048; + case MBEDTLS_SSL_MAX_FRAG_LEN_4096: + return 4096; + default: + return ( MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ); + } +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst, + const mbedtls_ssl_session *src ) +{ + mbedtls_ssl_session_free( dst ); + memcpy( dst, src, sizeof( mbedtls_ssl_session ) ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + dst->ticket = NULL; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( src->peer_cert != NULL ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + dst->peer_cert = mbedtls_calloc( 1, sizeof(mbedtls_x509_crt) ); + if( dst->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( dst->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( dst->peer_cert, src->peer_cert->raw.p, + src->peer_cert->raw.len ) ) != 0 ) + { + mbedtls_free( dst->peer_cert ); + dst->peer_cert = NULL; + return( ret ); + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( src->peer_cert_digest != NULL ) + { + dst->peer_cert_digest = + mbedtls_calloc( 1, src->peer_cert_digest_len ); + if( dst->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->peer_cert_digest, src->peer_cert_digest, + src->peer_cert_digest_len ); + dst->peer_cert_digest_type = src->peer_cert_digest_type; + dst->peer_cert_digest_len = src->peer_cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( src->ticket != NULL ) + { + dst->ticket = mbedtls_calloc( 1, src->ticket_len ); + if( dst->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( dst->ticket, src->ticket, src->ticket_len ); + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) +static int resize_buffer( unsigned char **buffer, size_t len_new, size_t *len_old ) +{ + unsigned char* resized_buffer = mbedtls_calloc( 1, len_new ); + if( resized_buffer == NULL ) + return -1; + + /* We want to copy len_new bytes when downsizing the buffer, and + * len_old bytes when upsizing, so we choose the smaller of two sizes, + * to fit one buffer into another. Size checks, ensuring that no data is + * lost, are done outside of this function. */ + memcpy( resized_buffer, *buffer, + ( len_new < *len_old ) ? len_new : *len_old ); + mbedtls_platform_zeroize( *buffer, *len_old ); + mbedtls_free( *buffer ); + + *buffer = resized_buffer; + *len_old = len_new; + + return 0; +} + +static void handle_buffer_resizing( mbedtls_ssl_context *ssl, int downsizing, + size_t in_buf_new_len, + size_t out_buf_new_len ) +{ + int modified = 0; + size_t written_in = 0, iv_offset_in = 0, len_offset_in = 0; + size_t written_out = 0, iv_offset_out = 0, len_offset_out = 0; + if( ssl->in_buf != NULL ) + { + written_in = ssl->in_msg - ssl->in_buf; + iv_offset_in = ssl->in_iv - ssl->in_buf; + len_offset_in = ssl->in_len - ssl->in_buf; + if( downsizing ? + ssl->in_buf_len > in_buf_new_len && ssl->in_left < in_buf_new_len : + ssl->in_buf_len < in_buf_new_len ) + { + if( resize_buffer( &ssl->in_buf, in_buf_new_len, &ssl->in_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "input buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating in_buf to %" MBEDTLS_PRINTF_SIZET, + in_buf_new_len ) ); + modified = 1; + } + } + } + + if( ssl->out_buf != NULL ) + { + written_out = ssl->out_msg - ssl->out_buf; + iv_offset_out = ssl->out_iv - ssl->out_buf; + len_offset_out = ssl->out_len - ssl->out_buf; + if( downsizing ? + ssl->out_buf_len > out_buf_new_len && ssl->out_left < out_buf_new_len : + ssl->out_buf_len < out_buf_new_len ) + { + if( resize_buffer( &ssl->out_buf, out_buf_new_len, &ssl->out_buf_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "output buffer resizing failed - out of memory" ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "Reallocating out_buf to %" MBEDTLS_PRINTF_SIZET, + out_buf_new_len ) ); + modified = 1; + } + } + } + if( modified ) + { + /* Update pointers here to avoid doing it twice. */ + mbedtls_ssl_reset_in_out_pointers( ssl ); + /* Fields below might not be properly updated with record + * splitting or with CID, so they are manually updated here. */ + ssl->out_msg = ssl->out_buf + written_out; + ssl->out_len = ssl->out_buf + len_offset_out; + ssl->out_iv = ssl->out_buf + iv_offset_out; + + ssl->in_msg = ssl->in_buf + written_in; + ssl->in_len = ssl->in_buf + len_offset_in; + ssl->in_iv = ssl->in_buf + iv_offset_in; + } +} +#endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static psa_status_t setup_psa_key_derivation( psa_key_derivation_operation_t* derivation, + psa_key_id_t key, + psa_algorithm_t alg, + const unsigned char* seed, size_t seed_length, + const unsigned char* label, size_t label_length, + size_t capacity ) +{ + psa_status_t status; + + status = psa_key_derivation_setup( derivation, alg ); + if( status != PSA_SUCCESS ) + return( status ); + + if( PSA_ALG_IS_TLS12_PRF( alg ) || PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) ) + { + status = psa_key_derivation_input_bytes( derivation, + PSA_KEY_DERIVATION_INPUT_SEED, + seed, seed_length ); + if( status != PSA_SUCCESS ) + return( status ); + + if( mbedtls_svc_key_id_is_null( key ) ) + { + status = psa_key_derivation_input_bytes( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, + NULL, 0 ); + } + else + { + status = psa_key_derivation_input_key( + derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key ); + } + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_key_derivation_input_bytes( derivation, + PSA_KEY_DERIVATION_INPUT_LABEL, + label, label_length ); + if( status != PSA_SUCCESS ) + return( status ); + } + else + { + return( PSA_ERROR_NOT_SUPPORTED ); + } + + status = psa_key_derivation_set_capacity( derivation, capacity ); + if( status != PSA_SUCCESS ) + return( status ); + + return( PSA_SUCCESS ); +} + +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + psa_status_t status; + psa_algorithm_t alg; + psa_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + + if( md_type == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256); + + /* Normally a "secret" should be long enough to be impossible to + * find by brute force, and in particular should not be empty. But + * this PRF is also used to derive an IV, in particular in EAP-TLS, + * and for this use case it makes sense to have a 0-length "secret". + * Since the key API doesn't allow importing a key of length 0, + * keep master_key=0, which setup_psa_key_derivation() understands + * to mean a 0-length "secret" input. */ + if( slen != 0 ) + { + psa_key_attributes_t key_attributes = psa_key_attributes_init(); + psa_set_key_usage_flags( &key_attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &key_attributes, alg ); + psa_set_key_type( &key_attributes, PSA_KEY_TYPE_DERIVE ); + + status = psa_import_key( &key_attributes, secret, slen, &master_key ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = setup_psa_key_derivation( &derivation, + master_key, alg, + random, rlen, + (unsigned char const *) label, + (size_t) strlen( label ), + dlen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + psa_destroy_key( master_key ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, dstbuf, dlen ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + psa_destroy_key( master_key ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + { + psa_destroy_key( master_key ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + if( ! mbedtls_svc_key_id_is_null( master_key ) ) + status = psa_destroy_key( master_key ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + return( 0 ); +} + +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +static int tls_prf_generic( mbedtls_md_type_t md_type, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + size_t nb; + size_t i, j, k, md_len; + unsigned char *tmp; + size_t tmp_len = 0; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &md_ctx ); + + if( ( md_info = mbedtls_md_info_from_type( md_type ) ) == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + md_len = mbedtls_md_get_size( md_info ); + + tmp_len = md_len + strlen( label ) + rlen; + tmp = mbedtls_calloc( 1, tmp_len ); + if( tmp == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + + nb = strlen( label ); + memcpy( tmp + md_len, label, nb ); + memcpy( tmp + md_len + nb, random, rlen ); + nb += rlen; + + /* + * Compute P_(secret, label + random)[0..dlen] + */ + if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + ret = mbedtls_md_hmac_starts( &md_ctx, secret, slen ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, tmp ); + if( ret != 0 ) + goto exit; + + for( i = 0; i < dlen; i += md_len ) + { + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, h_i ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_md_hmac_reset ( &md_ctx ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len ); + if( ret != 0 ) + goto exit; + ret = mbedtls_md_hmac_finish( &md_ctx, tmp ); + if( ret != 0 ) + goto exit; + + k = ( i + md_len > dlen ) ? dlen % md_len : md_len; + + for( j = 0; j < k; j++ ) + dstbuf[i + j] = h_i[j]; + } + +exit: + mbedtls_md_free( &md_ctx ); + + mbedtls_platform_zeroize( tmp, tmp_len ); + mbedtls_platform_zeroize( h_i, sizeof( h_i ) ); + + mbedtls_free( tmp ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_SHA256_C) +static int tls_prf_sha256( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA256, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) +static int tls_prf_sha384( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + return( tls_prf_generic( MBEDTLS_MD_SHA384, secret, slen, + label, random, rlen, dstbuf, dlen ) ); +} +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static void ssl_update_checksum_start( mbedtls_ssl_context *, const unsigned char *, size_t ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *,unsigned char*, size_t * ); +static void ssl_calc_finished_tls_sha256( mbedtls_ssl_context *,unsigned char *, int ); +#endif + +#if defined(MBEDTLS_SHA384_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *, const unsigned char *, size_t ); +static void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *, unsigned char*, size_t * ); +static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char *, int ); +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + return( 1 ); + + return( 0 ); + } + + if( ! mbedtls_svc_key_id_is_null( ssl->conf->psk_opaque ) ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ + +static mbedtls_tls_prf_types tls_prf_get_type( mbedtls_ssl_tls_prf_cb *tls_prf ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA384_C) + if( tls_prf == tls_prf_sha384 ) + { + return( MBEDTLS_SSL_TLS_PRF_SHA384 ); + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( tls_prf == tls_prf_sha256 ) + { + return( MBEDTLS_SSL_TLS_PRF_SHA256 ); + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + return( MBEDTLS_SSL_TLS_PRF_NONE ); +} + +int mbedtls_ssl_tls_prf( const mbedtls_tls_prf_types prf, + const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ) +{ + mbedtls_ssl_tls_prf_cb *tls_prf = NULL; + + switch( prf ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_SSL_TLS_PRF_SHA384: + tls_prf = tls_prf_sha384; + break; +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_TLS_PRF_SHA256: + tls_prf = tls_prf_sha256; + break; +#endif /* MBEDTLS_SHA256_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + default: + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + return( tls_prf( secret, slen, label, random, rlen, dstbuf, dlen ) ); +} + +/* Type for the TLS PRF */ +typedef int ssl_tls_prf_t(const unsigned char *, size_t, const char *, + const unsigned char *, size_t, + unsigned char *, size_t); + +/* + * Populate a transform structure with session keys and all the other + * necessary information. + * + * Parameters: + * - [in/out]: transform: structure to populate + * [in] must be just initialised with mbedtls_ssl_transform_init() + * [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf() + * - [in] ciphersuite + * - [in] master + * - [in] encrypt_then_mac + * - [in] compression + * - [in] tls_prf: pointer to PRF to use for key derivation + * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random + * - [in] minor_ver: SSL/TLS minor version + * - [in] endpoint: client or server + * - [in] ssl: used for: + * - ssl->conf->{f,p}_export_keys + * [in] optionally used for: + * - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg + */ +static int ssl_tls12_populate_transform( mbedtls_ssl_transform *transform, + int ciphersuite, + const unsigned char master[48], +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) && \ + defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + int encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC && + MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + ssl_tls_prf_t tls_prf, + const unsigned char randbytes[64], + int minor_ver, + unsigned endpoint, + const mbedtls_ssl_context *ssl ) +{ + int ret = 0; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psa_fallthrough; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char keyblk[256]; + unsigned char *key1; + unsigned char *key2; + unsigned char *mac_enc; + unsigned char *mac_dec; + size_t mac_key_len = 0; + size_t iv_copy_len; + size_t keylen; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + const mbedtls_cipher_info_t *cipher_info; + const mbedtls_md_info_t *md_info; + +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + if( ssl->f_export_keys == NULL ) + { + ssl = NULL; /* make sure we don't use it except for these cases */ + (void) ssl; + } +#endif + + /* + * Some data just needs copying into the structure + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + transform->encrypt_then_mac = encrypt_then_mac; +#endif + transform->minor_ver = minor_ver; + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + memcpy( transform->randbytes, randbytes, sizeof( transform->randbytes ) ); +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_4 ) + { + /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform + * generation separate. This should never happen. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * Get various info structures + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite ); + if( ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found", + ciphersuite ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found", + ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( ciphersuite_info->mac ); + if( md_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "mbedtls_md info for %u not found", + (unsigned) ciphersuite_info->mac ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Copy own and peer's CID if the use of the CID + * extension has been negotiated. */ + if( ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Copy CIDs into SSL transform" ) ); + + transform->in_cid_len = ssl->own_cid_len; + memcpy( transform->in_cid, ssl->own_cid, ssl->own_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Incoming CID", transform->in_cid, + transform->in_cid_len ); + + transform->out_cid_len = ssl->handshake->peer_cid_len; + memcpy( transform->out_cid, ssl->handshake->peer_cid, + ssl->handshake->peer_cid_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Outgoing CID", transform->out_cid, + transform->out_cid_len ); + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Compute key block using the PRF + */ + ret = tls_prf( master, 48, "key expansion", randbytes, 64, keyblk, 256 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite = %s", + mbedtls_ssl_get_ciphersuite_name( ciphersuite ) ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "master secret", master, 48 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "random bytes", randbytes, 64 ); + MBEDTLS_SSL_DEBUG_BUF( 4, "key block", keyblk, 256 ); + + /* + * Determine the appropriate key, IV and MAC length. + */ + + keylen = mbedtls_cipher_info_get_key_bitlen( cipher_info ) / 8; + +#if defined(MBEDTLS_GCM_C) || \ + defined(MBEDTLS_CCM_C) || \ + defined(MBEDTLS_CHACHAPOLY_C) + if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_GCM || + mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CCM || + mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CHACHAPOLY ) + { + size_t explicit_ivlen; + + transform->maclen = 0; + mac_key_len = 0; + transform->taglen = + ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16; + + /* All modes haves 96-bit IVs, but the length of the static parts vary + * with mode and version: + * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes + * (to be concatenated with a dynamically chosen IV of 8 Bytes) + * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's + * a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record + * sequence number). + */ + transform->ivlen = 12; + if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CHACHAPOLY ) + transform->fixed_ivlen = 12; + else + transform->fixed_ivlen = 4; + + /* Minimum length of encrypted record */ + explicit_ivlen = transform->ivlen - transform->fixed_ivlen; + transform->minlen = explicit_ivlen + transform->taglen; + } + else +#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_STREAM || + mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CBC ) + { + /* Initialize HMAC contexts */ + if( ( ret = mbedtls_md_setup( &transform->md_ctx_enc, md_info, 1 ) ) != 0 || + ( ret = mbedtls_md_setup( &transform->md_ctx_dec, md_info, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto end; + } + + /* Get MAC length */ + mac_key_len = mbedtls_md_get_size( md_info ); + transform->maclen = mac_key_len; + + /* IV length */ + transform->ivlen = cipher_info->iv_size; + + /* Minimum length */ + if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_STREAM ) + transform->minlen = transform->maclen; + else + { + /* + * GenericBlockCipher: + * 1. if EtM is in use: one block plus MAC + * otherwise: * first multiple of blocklen greater than maclen + * 2. IV + */ +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( encrypt_then_mac == MBEDTLS_SSL_ETM_ENABLED ) + { + transform->minlen = transform->maclen + + cipher_info->block_size; + } + else +#endif + { + transform->minlen = transform->maclen + + cipher_info->block_size + - transform->maclen % cipher_info->block_size; + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + transform->minlen += transform->ivlen; + } + else +#endif + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + } + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "keylen: %u, minlen: %u, ivlen: %u, maclen: %u", + (unsigned) keylen, + (unsigned) transform->minlen, + (unsigned) transform->ivlen, + (unsigned) transform->maclen ) ); + + /* + * Finally setup the cipher contexts, IVs and MAC secrets. + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key1 = keyblk + mac_key_len * 2; + key2 = keyblk + mac_key_len * 2 + keylen; + + mac_enc = keyblk; + mac_dec = keyblk + mac_key_len; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_enc, key2 + keylen, iv_copy_len ); + memcpy( transform->iv_dec, key2 + keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key1 = keyblk + mac_key_len * 2 + keylen; + key2 = keyblk + mac_key_len * 2; + + mac_enc = keyblk + mac_key_len; + mac_dec = keyblk; + + /* + * This is not used in TLS v1.1. + */ + iv_copy_len = ( transform->fixed_ivlen ) ? + transform->fixed_ivlen : transform->ivlen; + memcpy( transform->iv_dec, key1 + keylen, iv_copy_len ); + memcpy( transform->iv_enc, key1 + keylen + iv_copy_len, + iv_copy_len ); + } + else +#endif /* MBEDTLS_SSL_SRV_C */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto end; + } + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + ret = mbedtls_md_hmac_starts( &transform->md_ctx_enc, mac_enc, mac_key_len ); + if( ret != 0 ) + goto end; + ret = mbedtls_md_hmac_starts( &transform->md_ctx_dec, mac_dec, mac_key_len ); + if( ret != 0 ) + goto end; + } +#endif +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + + ((void) mac_dec); + ((void) mac_enc); + + if( ssl != NULL && ssl->f_export_keys != NULL ) + { + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET, + master, 48, + randbytes + 32, + randbytes, + tls_prf_get_type( tls_prf ) ); + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_enc, + cipher_info, transform->taglen ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret ); + goto end; + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) ); + psa_fallthrough = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record encryption - fall through to default setup." ) ); + psa_fallthrough = 1; + } + + if( psa_fallthrough == 1 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + goto end; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + ret = mbedtls_cipher_setup_psa( &transform->cipher_ctx_dec, + cipher_info, transform->taglen ); + if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup_psa", ret ); + goto end; + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) ); + psa_fallthrough = 0; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Failed to setup PSA-based cipher context for record decryption - fall through to default setup." ) ); + psa_fallthrough = 1; + } + + if( psa_fallthrough == 1 ) +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, key1, + (int) mbedtls_cipher_info_get_key_bitlen( cipher_info ), + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, key2, + (int) mbedtls_cipher_info_get_key_bitlen( cipher_info ), + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + goto end; + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( mbedtls_cipher_info_get_mode( cipher_info ) == MBEDTLS_MODE_CBC ) + { + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_enc, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + goto end; + } + + if( ( ret = mbedtls_cipher_set_padding_mode( &transform->cipher_ctx_dec, + MBEDTLS_PADDING_NONE ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_set_padding_mode", ret ); + goto end; + } + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + +end: + mbedtls_platform_zeroize( keyblk, sizeof( keyblk ) ); + return( ret ); +} + +/* + * Set appropriate PRF function and other SSL / TLS1.2 functions + * + * Inputs: + * - SSL/TLS minor version + * - hash associated with the ciphersuite (only used by TLS 1.2) + * + * Outputs: + * - the tls_prf, calc_verify and calc_finished members of handshake structure + */ +static int ssl_set_handshake_prfs( mbedtls_ssl_handshake_params *handshake, + int minor_ver, + mbedtls_md_type_t hash ) +{ +#if !defined(MBEDTLS_SSL_PROTO_TLS1_2) || !defined(MBEDTLS_SHA384_C) + (void) hash; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA384_C) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + hash == MBEDTLS_MD_SHA384 ) + { + handshake->tls_prf = tls_prf_sha384; + handshake->calc_verify = ssl_calc_verify_tls_sha384; + handshake->calc_finished = ssl_calc_finished_tls_sha384; + } + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + handshake->tls_prf = tls_prf_sha256; + handshake->calc_verify = ssl_calc_verify_tls_sha256; + handshake->calc_finished = ssl_calc_finished_tls_sha256; + } + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} + +/* + * Compute master secret if needed + * + * Parameters: + * [in/out] handshake + * [in] resume, premaster, extended_ms, calc_verify, tls_prf + * (PSA-PSK) ciphersuite_info, psk_opaque + * [out] premaster (cleared) + * [out] master + * [in] ssl: optionally used for debugging, EMS and PSA-PSK + * debug: conf->f_dbg, conf->p_dbg + * EMS: passed to calc_verify (debug + session_negotiate) + * PSA-PSA: minor_ver, conf + */ +static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, + unsigned char *master, + const mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* cf. RFC 5246, Section 8.1: + * "The master secret is always exactly 48 bytes in length." */ + size_t const master_secret_len = 48; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned char session_hash[48]; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The salt for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *salt = handshake->randbytes; + size_t salt_len = 64; + +#if !defined(MBEDTLS_DEBUG_C) && \ + !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !(defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + if( handshake->resume != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + return( 0 ); + } + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) + { + lbl = "extended master secret"; + salt = session_hash; + handshake->calc_verify( ssl, session_hash, &salt_len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash for extended master secret", + session_hash, salt_len ); + } +#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_use_opaque_psk( ssl ) == 1 ) + { + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + psa_key_id_t psk; + psa_key_derivation_operation_t derivation = + PSA_KEY_DERIVATION_OPERATION_INIT; + mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); + + psk = mbedtls_ssl_get_opaque_psk( ssl ); + + if( hash_alg == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + + status = setup_psa_key_derivation( &derivation, psk, alg, + salt, salt_len, + (unsigned char const *) lbl, + (size_t) strlen( lbl ), + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_output_bytes( &derivation, + master, + master_secret_len ); + if( status != PSA_SUCCESS ) + { + psa_key_derivation_abort( &derivation ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_key_derivation_abort( &derivation ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + else +#endif + { + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + lbl, salt, salt_len, + master, + master_secret_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); + + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); + } + + return( 0 ); +} + +int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive keys" ) ); + + /* Set PRF, calc_verify and calc_finished function pointers */ + ret = ssl_set_handshake_prfs( ssl->handshake, + ssl->minor_ver, + ciphersuite_info->mac ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_set_handshake_prfs", ret ); + return( ret ); + } + + /* Compute master secret if needed */ + ret = ssl_compute_master( ssl->handshake, + ssl->session_negotiate->master, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_compute_master", ret ); + return( ret ); + } + + /* Swap the client and server random values: + * - MS derivation wanted client+server (RFC 5246 8.1) + * - key derivation wants server+client (RFC 5246 6.3) */ + { + unsigned char tmp[64]; + memcpy( tmp, ssl->handshake->randbytes, 64 ); + memcpy( ssl->handshake->randbytes, tmp + 32, 32 ); + memcpy( ssl->handshake->randbytes + 32, tmp, 32 ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + } + + /* Populate transform structure */ + ret = ssl_tls12_populate_transform( ssl->transform_negotiate, + ssl->session_negotiate->ciphersuite, + ssl->session_negotiate->master, +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) && \ + defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session_negotiate->encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC && + MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + ssl->handshake->tls_prf, + ssl->handshake->randbytes, + ssl->minor_ver, + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls12_populate_transform", ret ); + return( ret ); + } + + /* We no longer need Server/ClientHello.random values */ + mbedtls_platform_zeroize( ssl->handshake->randbytes, + sizeof( ssl->handshake->randbytes ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive keys" ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +void ssl_calc_verify_tls_sha256( const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_status_t status; + psa_hash_operation_t sha256_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha256" ) ); + status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha256_psa, hash, 32, &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + + *hlen = 32; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); +#else + mbedtls_sha256_context sha256; + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + mbedtls_sha256_finish( &sha256, hash ); + + *hlen = 32; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha256_free( &sha256 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return; +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) +void ssl_calc_verify_tls_sha384( const mbedtls_ssl_context *ssl, + unsigned char *hash, + size_t *hlen ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_status_t status; + psa_hash_operation_t sha384_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> PSA calc verify sha384" ) ); + status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha384_psa, hash, 48, &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + + *hlen = 48; + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= PSA calc verify" ) ); +#else + mbedtls_sha512_context sha512; + + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc verify sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + mbedtls_sha512_finish( &sha512, hash ); + + *hlen = 48; + + MBEDTLS_SSL_DEBUG_BUF( 3, "calculated verify result", hash, *hlen ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc verify" ) ); + + mbedtls_sha512_free( &sha512 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return; +} +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) +int mbedtls_ssl_psk_derive_premaster( mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex ) +{ + unsigned char *p = ssl->handshake->premaster; + unsigned char *end = p + sizeof( ssl->handshake->premaster ); + const unsigned char *psk = NULL; + size_t psk_len = 0; + + if( mbedtls_ssl_get_psk( ssl, &psk, &psk_len ) + == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ) + { + /* + * This should never happen because the existence of a PSK is always + * checked before calling this function + */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* + * PMS = struct { + * opaque other_secret<0..2^16-1>; + * opaque psk<0..2^16-1>; + * }; + * with "other_secret" depending on the particular key exchange + */ +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_PSK ) + { + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_PUT_UINT16_BE( psk_len, p, 0 ); + p += 2; + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memset( p, 0, psk_len ); + p += psk_len; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + /* + * other_secret already set by the ClientKeyExchange message, + * and is 48 bytes long + */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *p++ = 0; + *p++ = 48; + p += 48; + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Write length only when we know the actual value */ + if( ( ret = mbedtls_dhm_calc_secret( &ssl->handshake->dhm_ctx, + p + 2, end - ( p + 2 ), &len, + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_calc_secret", ret ); + return( ret ); + } + MBEDTLS_PUT_UINT16_BE( len, p, 0 ); + p += 2 + len; + + MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: K ", &ssl->handshake->dhm_ctx.K ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) + if( key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t zlen; + + if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &zlen, + p + 2, end - ( p + 2 ), + ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } + + MBEDTLS_PUT_UINT16_BE( zlen, p, 0 ); + p += 2 + zlen; + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Z ); + } + else +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* opaque psk<0..2^16-1>; */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + MBEDTLS_PUT_UINT16_BE( psk_len, p, 0 ); + p += 2; + + if( end < p || (size_t)( end - p ) < psk_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( p, psk, psk_len ); + p += psk_len; + + ssl->handshake->pmslen = p - ssl->handshake->premaster; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +int mbedtls_ssl_resend_hello_request( mbedtls_ssl_context *ssl ) +{ + /* If renegotiation is not enforced, retransmit until we would reach max + * timeout if we were using the usual handshake doubling scheme */ + if( ssl->conf->renego_max_records < 0 ) + { + uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1; + unsigned char doublings = 1; + + while( ratio != 0 ) + { + ++doublings; + ratio >>= 1; + } + + if( ++ssl->renego_records_seen > doublings ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "no longer retransmitting hello request" ) ); + return( 0 ); + } + } + + return( ssl_write_hello_request( ssl ) ); +} +#endif +#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_clear_peer_cert( mbedtls_ssl_session *session ) +{ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert != NULL ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + /* Zeroization is not necessary. */ + mbedtls_free( session->peer_cert_digest ); + session->peer_cert_digest = NULL; + session->peer_cert_digest_type = MBEDTLS_MD_NONE; + session->peer_cert_digest_len = 0; + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Handshake functions + */ +#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* No certificate support -> dummy functions */ +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +/* Some certificate support -> implement write and parse */ + +int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + size_t i, n; + const mbedtls_x509_crt *crt; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) ); + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + if( ssl->client_auth == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) ); + ssl->state++; + return( 0 ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( mbedtls_ssl_own_cert( ssl ) == NULL ) + { + /* Should never happen because we shouldn't have picked the + * ciphersuite if we don't have a certificate. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + } +#endif + + MBEDTLS_SSL_DEBUG_CRT( 3, "own certificate", mbedtls_ssl_own_cert( ssl ) ); + + /* + * 0 . 0 handshake type + * 1 . 3 handshake length + * 4 . 6 length of all certs + * 7 . 9 length of cert. 1 + * 10 . n-1 peer certificate + * n . n+2 length of cert. 2 + * n+3 . ... upper level cert, etc. + */ + i = 7; + crt = mbedtls_ssl_own_cert( ssl ); + + while( crt != NULL ) + { + n = crt->raw.len; + if( n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate too large, %" MBEDTLS_PRINTF_SIZET + " > %" MBEDTLS_PRINTF_SIZET, + i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN ) ); + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + } + + ssl->out_msg[i ] = MBEDTLS_BYTE_2( n ); + ssl->out_msg[i + 1] = MBEDTLS_BYTE_1( n ); + ssl->out_msg[i + 2] = MBEDTLS_BYTE_0( n ); + + i += 3; memcpy( ssl->out_msg + i, crt->raw.p, n ); + i += n; crt = crt->next; + } + + ssl->out_msg[4] = MBEDTLS_BYTE_2( i - 7 ); + ssl->out_msg[5] = MBEDTLS_BYTE_1( i - 7 ); + ssl->out_msg[6] = MBEDTLS_BYTE_0( i - 7 ); + + ssl->out_msglen = i; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE; + + ssl->state++; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write certificate" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert; + + if( peer_crt == NULL ) + return( -1 ); + + if( peer_crt->raw.len != crt_buf_len ) + return( -1 ); + + return( memcmp( peer_crt->raw.p, crt_buf, peer_crt->raw.len ) ); +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl, + unsigned char *crt_buf, + size_t crt_buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char const * const peer_cert_digest = + ssl->session->peer_cert_digest; + mbedtls_md_type_t const peer_cert_digest_type = + ssl->session->peer_cert_digest_type; + mbedtls_md_info_t const * const digest_info = + mbedtls_md_info_from_type( peer_cert_digest_type ); + unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN]; + size_t digest_len; + + if( peer_cert_digest == NULL || digest_info == NULL ) + return( -1 ); + + digest_len = mbedtls_md_get_size( digest_info ); + if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN ) + return( -1 ); + + ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest ); + if( ret != 0 ) + return( -1 ); + + return( memcmp( tmp_digest, peer_cert_digest, digest_len ) ); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *chain ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + int crt_cnt=0; +#endif + size_t i, n; + uint8_t alert; + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + if( ssl->in_hslen < mbedtls_ssl_hs_hdr_len( ssl ) + 3 + 3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + i = mbedtls_ssl_hs_hdr_len( ssl ); + + /* + * Same message structure as in mbedtls_ssl_write_certificate() + */ + n = ( ssl->in_msg[i+1] << 8 ) | ssl->in_msg[i+2]; + + if( ssl->in_msg[i] != 0 || + ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len( ssl ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */ + i += 3; + + /* Iterate through and parse the CRTs in the provided chain. */ + while( i < ssl->in_hslen ) + { + /* Check that there's room for the next CRT's length fields. */ + if ( i + 3 > ssl->in_hslen ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + /* In theory, the CRT can be up to 2**24 Bytes, but we don't support + * anything beyond 2**16 ~ 64K. */ + if( ssl->in_msg[i] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT ); + return( MBEDTLS_ERR_SSL_BAD_CERTIFICATE ); + } + + /* Read length of the next CRT in the chain. */ + n = ( (unsigned int) ssl->in_msg[i + 1] << 8 ) + | (unsigned int) ssl->in_msg[i + 2]; + i += 3; + + if( n < 128 || i + n > ssl->in_hslen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* Check if we're handling the first CRT in the chain. */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C) + if( crt_cnt++ == 0 && + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + /* During client-side renegotiation, check that the server's + * end-CRTs hasn't changed compared to the initial handshake, + * mitigating the triple handshake attack. On success, reuse + * the original end-CRT instead of parsing it again. */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) ); + if( ssl_check_peer_crt_unchanged( ssl, + &ssl->in_msg[i], + n ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "new server cert during renegotiation" ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED ); + return( MBEDTLS_ERR_SSL_BAD_CERTIFICATE ); + } + + /* Now we can safely free the original chain. */ + ssl_clear_peer_cert( ssl->session ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + + /* Parse the next certificate in the chain. */ +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n ); +#else + /* If we don't need to store the CRT chain permanently, parse + * it in-place from the input buffer instead of making a copy. */ + ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + switch( ret ) + { + case 0: /*ok*/ + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR; + goto crt_parse_der_failed; + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + goto crt_parse_der_failed; + + default: + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + crt_parse_der_failed: + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + i += n; + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain ); + return( 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl ) +{ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + return( -1 ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) && + ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE && + ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE && + memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) ); + return( 0 ); + } + + return( -1 ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* Check if a certificate message is expected. + * Return either + * - SSL_CERTIFICATE_EXPECTED, or + * - SSL_CERTIFICATE_SKIP + * indicating whether a Certificate message is expected or not. + */ +#define SSL_CERTIFICATE_EXPECTED 0 +#define SSL_CERTIFICATE_SKIP 1 +static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl, + int authmode ) +{ + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + + if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) ) + return( SSL_CERTIFICATE_SKIP ); + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + return( SSL_CERTIFICATE_SKIP ); + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = + MBEDTLS_X509_BADCERT_SKIP_VERIFY; + return( SSL_CERTIFICATE_SKIP ); + } + } +#else + ((void) authmode); +#endif /* MBEDTLS_SSL_SRV_C */ + + return( SSL_CERTIFICATE_EXPECTED ); +} + +static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, + int authmode, + mbedtls_x509_crt *chain, + void *rs_ctx ) +{ + int ret = 0; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->handshake->ciphersuite_info; + int have_ca_chain = 0; + + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *); + void *p_vrfy; + + if( authmode == MBEDTLS_SSL_VERIFY_NONE ) + return( 0 ); + + if( ssl->f_vrfy != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) ); + f_vrfy = ssl->f_vrfy; + p_vrfy = ssl->p_vrfy; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) ); + f_vrfy = ssl->conf->f_vrfy; + p_vrfy = ssl->conf->p_vrfy; + } + + /* + * Main check: verify certificate + */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( ssl->conf->f_ca_cb != NULL ) + { + ((void) rs_ctx); + have_ca_chain = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) ); + ret = mbedtls_x509_crt_verify_with_ca_cb( + chain, + ssl->conf->f_ca_cb, + ssl->conf->p_ca_cb, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy ); + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + if( ca_chain != NULL ) + have_ca_chain = 1; + + ret = mbedtls_x509_crt_verify_restartable( + chain, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + f_vrfy, p_vrfy, rs_ctx ); + } + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); +#endif + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &chain->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (EC key curve)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( chain, + ciphersuite_info, + ! ssl->conf->endpoint, + &ssl->session_negotiate->verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate (usage extensions)" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + + /* mbedtls_x509_crt_verify_with_profile is supposed to report a + * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED, + * with details encoded in the verification flags. All other kinds + * of error codes, including those from the user provided f_vrfy + * functions, are treated as fatal and lead to a failure of + * ssl_parse_certificate even if verification was optional. */ + if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && + ( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || + ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE ) ) + { + ret = 0; + } + + if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + uint8_t alert; + + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER ) + alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY ) + alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED; + else if( ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA; + else + alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN; + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + alert ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( ssl->session_negotiate->verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x", + (unsigned int) ssl->session_negotiate->verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + + return( ret ); +} + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl, + unsigned char *start, size_t len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* Remember digest of the peer's end-CRT. */ + ssl->session_negotiate->peer_cert_digest = + mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ); + if( ssl->session_negotiate->peer_cert_digest == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed", + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + ret = mbedtls_md( mbedtls_md_info_from_type( + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ), + start, len, + ssl->session_negotiate->peer_cert_digest ); + + ssl->session_negotiate->peer_cert_digest_type = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE; + ssl->session_negotiate->peer_cert_digest_len = + MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN; + + return( ret ); +} + +static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl, + unsigned char *start, size_t len ) +{ + unsigned char *end = start + len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Make a copy of the peer's raw public key. */ + mbedtls_pk_init( &ssl->handshake->peer_pubkey ); + ret = mbedtls_pk_parse_subpubkey( &start, end, + &ssl->handshake->peer_pubkey ); + if( ret != 0 ) + { + /* We should have parsed the public key before. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + return( 0 ); +} +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + int crt_expected; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + void *rs_ctx = NULL; + mbedtls_x509_crt *chain = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + crt_expected = ssl_parse_certificate_coordinate( ssl, authmode ); + if( crt_expected == SSL_CERTIFICATE_SKIP ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + goto exit; + } + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) + { + chain = ssl->handshake->ecrs_peer_cert; + ssl->handshake->ecrs_peer_cert = NULL; + goto crt_verify; + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto exit; + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; + + if( authmode != MBEDTLS_SSL_VERIFY_OPTIONAL ) + ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE; + + goto exit; + } +#endif /* MBEDTLS_SSL_SRV_C */ + + /* Clear existing peer CRT structure in case we tried to + * reuse a session but it failed, and allocate a new one. */ + ssl_clear_peer_cert( ssl->session_negotiate ); + + chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + if( chain == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", + sizeof( mbedtls_x509_crt ) ) ); + mbedtls_ssl_send_alert_message( ssl, + MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto exit; + } + mbedtls_x509_crt_init( chain ); + + ret = ssl_parse_certificate_chain( ssl, chain ); + if( ret != 0 ) + goto exit; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; + +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif + + ret = ssl_parse_certificate_verify( ssl, authmode, + chain, rs_ctx ); + if( ret != 0 ) + goto exit; + +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + { + unsigned char *crt_start, *pk_start; + size_t crt_len, pk_len; + + /* We parse the CRT chain without copying, so + * these pointers point into the input buffer, + * and are hence still valid after freeing the + * CRT chain. */ + + crt_start = chain->raw.p; + crt_len = chain->raw.len; + + pk_start = chain->pk_raw.p; + pk_len = chain->pk_raw.len; + + /* Free the CRT structures before computing + * digest and copying the peer's public key. */ + mbedtls_x509_crt_free( chain ); + mbedtls_free( chain ); + chain = NULL; + + ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len ); + if( ret != 0 ) + goto exit; + + ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len ); + if( ret != 0 ) + goto exit; + } +#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Pass ownership to session structure. */ + ssl->session_negotiate->peer_cert = chain; + chain = NULL; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); + +exit: + + if( ret == 0 ) + ssl->state++; + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + ssl->handshake->ecrs_peer_cert = chain; + chain = NULL; + } +#endif + + if( chain != NULL ) + { + mbedtls_x509_crt_free( chain ); + mbedtls_free( chain ); + } + + return( ret ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +void mbedtls_ssl_optimize_checksum( mbedtls_ssl_context *ssl, + const mbedtls_ssl_ciphersuite_t *ciphersuite_info ) +{ + ((void) ciphersuite_info); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA384_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha384; + else +#endif +#if defined(MBEDTLS_SHA256_C) + if( ciphersuite_info->mac != MBEDTLS_MD_SHA384 ) + ssl->handshake->update_checksum = ssl_update_checksum_sha256; + else +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return; + } +} + +void mbedtls_ssl_reset_checksum( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &ssl->handshake->fin_sha256_psa ); + psa_hash_setup( &ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256 ); +#else + mbedtls_sha256_starts( &ssl->handshake->fin_sha256, 0 ); +#endif +#endif +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &ssl->handshake->fin_sha384_psa ); + psa_hash_setup( &ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384 ); +#else + mbedtls_sha512_starts( &ssl->handshake->fin_sha512, 1 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +static void ssl_update_checksum_start( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len ); +#else + mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); +#endif +#endif +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len ); +#else + mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_update_checksum_sha256( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha256_psa, buf, len ); +#else + mbedtls_sha256_update( &ssl->handshake->fin_sha256, buf, len ); +#endif +} +#endif + +#if defined(MBEDTLS_SHA384_C) +static void ssl_update_checksum_sha384( mbedtls_ssl_context *ssl, + const unsigned char *buf, size_t len ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_update( &ssl->handshake->fin_sha384_psa, buf, len ); +#else + mbedtls_sha512_update( &ssl->handshake->fin_sha512, buf, len ); +#endif +} +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +static void ssl_calc_finished_tls_sha256( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + unsigned char padbuf[32]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT; + psa_status_t status; +#else + mbedtls_sha256_context sha256; +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + sha256_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha256" ) ); + + status = psa_hash_clone( &ssl->handshake->fin_sha256_psa, &sha256_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha256_psa, padbuf, sizeof( padbuf ), &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 32 ); +#else + + mbedtls_sha256_init( &sha256 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha256" ) ); + + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA256_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha2 state", (unsigned char *) + sha256.state, sizeof( sha256.state ) ); +#endif + + mbedtls_sha256_finish( &sha256, padbuf ); + mbedtls_sha256_free( &sha256 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 32, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + +static void ssl_calc_finished_tls_sha384( + mbedtls_ssl_context *ssl, unsigned char *buf, int from ) +{ + int len = 12; + const char *sender; + unsigned char padbuf[48]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + size_t hash_size; + psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT; + psa_status_t status; +#else + mbedtls_sha512_context sha512; +#endif + + mbedtls_ssl_session *session = ssl->session_negotiate; + if( !session ) + session = ssl->session; + + sender = ( from == MBEDTLS_SSL_IS_CLIENT ) + ? "client finished" + : "server finished"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + sha384_psa = psa_hash_operation_init(); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc PSA finished tls sha384" ) ); + + status = psa_hash_clone( &ssl->handshake->fin_sha384_psa, &sha384_psa ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash clone failed" ) ); + return; + } + + status = psa_hash_finish( &sha384_psa, padbuf, sizeof( padbuf ), &hash_size ); + if( status != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "PSA hash finish failed" ) ); + return; + } + MBEDTLS_SSL_DEBUG_BUF( 3, "PSA calculated padbuf", padbuf, 48 ); +#else + mbedtls_sha512_init( &sha512 ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> calc finished tls sha384" ) ); + + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + /* + * TLSv1.2: + * hash = PRF( master, finished_label, + * Hash( handshake ) )[0.11] + */ + +#if !defined(MBEDTLS_SHA512_ALT) + MBEDTLS_SSL_DEBUG_BUF( 4, "finished sha512 state", (unsigned char *) + sha512.state, sizeof( sha512.state ) ); +#endif + mbedtls_sha512_finish( &sha512, padbuf ); + + mbedtls_sha512_free( &sha512 ); +#endif + + ssl->handshake->tls_prf( session->master, 48, sender, + padbuf, 48, buf, len ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "calc finished result", buf, len ); + + mbedtls_platform_zeroize( padbuf, sizeof( padbuf ) ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= calc finished" ) ); +} +#endif /* MBEDTLS_SHA384_C */ +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +void mbedtls_ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup: final free" ) ); + + /* + * Free our handshake params + */ + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + + /* + * Free the previous transform and swith in the current one + */ + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + ssl->transform = ssl->transform_negotiate; + ssl->transform_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup: final free" ) ); +} + +void mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + int resume = ssl->handshake->resume; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_DONE; + ssl->renego_records_seen = 0; + } +#endif + + /* + * Free the previous session and switch in the current one + */ + if( ssl->session ) + { +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + /* RFC 7366 3.1: keep the EtM state */ + ssl->session_negotiate->encrypt_then_mac = + ssl->session->encrypt_then_mac; +#endif + + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + /* + * Add cache entry + */ + if( ssl->conf->f_set_cache != NULL && + ssl->session->id_len != 0 && + resume == 0 ) + { + if( ssl->conf->f_set_cache( ssl->conf->p_cache, + ssl->session->id, + ssl->session->id_len, + ssl->session ) != 0 ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cache did not store session" ) ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->flight != NULL ) + { + /* Cancel handshake timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + /* Keep last flight around in case we need to resend it: + * we need the handshake and transform structures for that */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip freeing handshake and transform" ) ); + } + else +#endif + mbedtls_ssl_handshake_wrapup_free_hs_transform( ssl ); + + ssl->state++; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +int mbedtls_ssl_write_finished( mbedtls_ssl_context *ssl ) +{ + int ret, hash_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished" ) ); + + mbedtls_ssl_update_out_pointers( ssl, ssl->transform_negotiate ); + + ssl->handshake->calc_finished( ssl, ssl->out_msg + 4, ssl->conf->endpoint ); + + /* + * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites + * may define some other value. Currently (early 2016), no defined + * ciphersuite does this (and this is unlikely to change as activity has + * moved to TLS 1.3 now) so we can keep the hardcoded 12 here. + */ + hash_len = 12; + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->own_verify_data, ssl->out_msg + 4, hash_len ); +#endif + + ssl->out_msglen = 4 + hash_len; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_FINISHED; + + /* + * In case of session resuming, invert the client and server + * ChangeCipherSpec messages order. + */ + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif + } + else + ssl->state++; + + /* + * Switch to our negotiated transform and session parameters for outbound + * data. + */ + MBEDTLS_SSL_DEBUG_MSG( 3, ( "switching to new transform spec for outbound data" ) ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + unsigned char i; + + /* Remember current epoch settings for resending */ + ssl->handshake->alt_transform_out = ssl->transform_out; + memcpy( ssl->handshake->alt_out_ctr, ssl->cur_out_ctr, + sizeof( ssl->handshake->alt_out_ctr ) ); + + /* Set sequence_number to zero */ + memset( &ssl->cur_out_ctr[2], 0, sizeof( ssl->cur_out_ctr ) - 2 ); + + + /* Increment epoch */ + for( i = 2; i > 0; i-- ) + if( ++ssl->cur_out_ctr[i - 1] != 0 ) + break; + + /* The loop goes to its end iff the counter is wrapping */ + if( i == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS epoch would wrap" ) ); + return( MBEDTLS_ERR_SSL_COUNTER_WRAPPING ); + } + } + else +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + + ssl->transform_out = ssl->transform_negotiate; + ssl->session_out = ssl->session_negotiate; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_send_flight_completed( ssl ); +#endif + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flight_transmit", ret ); + return( ret ); + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished" ) ); + + return( 0 ); +} + +#define SSL_MAX_HASH_LEN 12 + +int mbedtls_ssl_parse_finished( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned int hash_len = 12; + unsigned char buf[SSL_MAX_HASH_LEN]; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished" ) ); + + ssl->handshake->calc_finished( ssl, buf, ssl->conf->endpoint ^ 1 ); + + if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto exit; + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto exit; + } + + if( ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE ); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto exit; + } + + if( ssl->in_hslen != mbedtls_ssl_hs_hdr_len( ssl ) + hash_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR ); + ret = MBEDTLS_ERR_SSL_DECODE_ERROR; + goto exit; + } + + if( mbedtls_ct_memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), + buf, hash_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + goto exit; + } + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->verify_data_len = hash_len; + memcpy( ssl->peer_verify_data, buf, hash_len ); +#endif + + if( ssl->handshake->resume != 0 ) + { +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC; +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP; +#endif + } + else + ssl->state++; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + mbedtls_ssl_recv_flight_completed( ssl ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished" ) ); + +exit: + mbedtls_platform_zeroize( buf, hash_len ); + return( ret ); +} + +static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) +{ + memset( handshake, 0, sizeof( mbedtls_ssl_handshake_params ) ); + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha256_psa = psa_hash_operation_init(); + psa_hash_setup( &handshake->fin_sha256_psa, PSA_ALG_SHA_256 ); +#else + mbedtls_sha256_init( &handshake->fin_sha256 ); + mbedtls_sha256_starts( &handshake->fin_sha256, 0 ); +#endif +#endif +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + handshake->fin_sha384_psa = psa_hash_operation_init(); + psa_hash_setup( &handshake->fin_sha384_psa, PSA_ALG_SHA_384 ); +#else + mbedtls_sha512_init( &handshake->fin_sha512 ); + mbedtls_sha512_starts( &handshake->fin_sha512, 1 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + handshake->update_checksum = ssl_update_checksum_start; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + mbedtls_ssl_sig_hash_set_init( &handshake->hash_algs ); +#endif + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_init( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_init( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_init( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_init( &handshake->peer_pubkey ); +#endif +} + +void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform ) +{ + memset( transform, 0, sizeof(mbedtls_ssl_transform) ); + + mbedtls_cipher_init( &transform->cipher_ctx_enc ); + mbedtls_cipher_init( &transform->cipher_ctx_dec ); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) + mbedtls_md_init( &transform->md_ctx_enc ); + mbedtls_md_init( &transform->md_ctx_dec ); +#endif +} + +void mbedtls_ssl_session_init( mbedtls_ssl_session *session ) +{ + memset( session, 0, sizeof(mbedtls_ssl_session) ); +} + +static int ssl_handshake_init( mbedtls_ssl_context *ssl ) +{ + /* Clear old handshake information if present */ + if( ssl->transform_negotiate ) + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + if( ssl->session_negotiate ) + mbedtls_ssl_session_free( ssl->session_negotiate ); + if( ssl->handshake ) + mbedtls_ssl_handshake_free( ssl ); + + /* + * Either the pointers are now NULL or cleared properly and can be freed. + * Now allocate missing structures. + */ + if( ssl->transform_negotiate == NULL ) + { + ssl->transform_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_transform) ); + } + + if( ssl->session_negotiate == NULL ) + { + ssl->session_negotiate = mbedtls_calloc( 1, sizeof(mbedtls_ssl_session) ); + } + + if( ssl->handshake == NULL ) + { + ssl->handshake = mbedtls_calloc( 1, sizeof(mbedtls_ssl_handshake_params) ); + } +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too small - reallocate */ + + handle_buffer_resizing( ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN, + MBEDTLS_SSL_OUT_BUFFER_LEN ); +#endif + + /* All pointers should exist and can be directly freed without issue */ + if( ssl->handshake == NULL || + ssl->transform_negotiate == NULL || + ssl->session_negotiate == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc() of ssl sub-contexts failed" ) ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + + ssl->handshake = NULL; + ssl->transform_negotiate = NULL; + ssl->session_negotiate = NULL; + + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + /* Initialize structures */ + mbedtls_ssl_session_init( ssl->session_negotiate ); + mbedtls_ssl_transform_init( ssl->transform_negotiate ); + ssl_handshake_params_init( ssl->handshake ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + ssl->handshake->alt_transform_out = ssl->transform_out; + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_PREPARING; + else + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_WAITING; + + mbedtls_ssl_set_timer( ssl, 0 ); + } +#endif + +/* + * curve_list is translated to IANA TLS group identifiers here because + * mbedtls_ssl_conf_curves returns void and so can't return + * any error codes. + */ +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + /* Heap allocate and translate curve_list from internal to IANA group ids */ + if ( ssl->conf->curve_list != NULL ) + { + size_t length; + const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list; + + for( length = 0; ( curve_list[length] != MBEDTLS_ECP_DP_NONE ) && + ( length < MBEDTLS_ECP_DP_MAX ); length++ ) {} + + /* Leave room for zero termination */ + uint16_t *group_list = mbedtls_calloc( length + 1, sizeof(uint16_t) ); + if ( group_list == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + for( size_t i = 0; i < length; i++ ) + { + const mbedtls_ecp_curve_info *info = + mbedtls_ecp_curve_info_from_grp_id( curve_list[i] ); + if ( info == NULL ) + { + mbedtls_free( group_list ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + group_list[i] = info->tls_id; + } + + group_list[length] = 0; + + ssl->handshake->group_list = group_list; + ssl->handshake->group_list_heap_allocated = 1; + } + else + { + ssl->handshake->group_list = ssl->conf->group_list; + ssl->handshake->group_list_heap_allocated = 0; + } +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + + return( 0 ); +} + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY && MBEDTLS_SSL_SRV_C */ + +/* + * Initialize an SSL context + */ +void mbedtls_ssl_init( mbedtls_ssl_context *ssl ) +{ + memset( ssl, 0, sizeof( mbedtls_ssl_context ) ); +} + +static int ssl_conf_version_check( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( mbedtls_ssl_conf_is_tls13_only( ssl->conf ) ) + { + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DTLS 1.3 is not yet supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + MBEDTLS_SSL_DEBUG_MSG( 4, ( "The SSL configuration is tls13 only." ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( mbedtls_ssl_conf_is_tls12_only( ssl->conf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 4, ( "The SSL configuration is tls12 only." ) ); + return( 0 ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( mbedtls_ssl_conf_is_hybrid_tls12_tls13( ssl->conf ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Hybrid TLS 1.2 + TLS 1.3 configurations are not yet supported" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } +#endif + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "The SSL configuration is invalid." ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); +} + +static int ssl_conf_check(const mbedtls_ssl_context *ssl) +{ + int ret; + ret = ssl_conf_version_check( ssl ); + if( ret != 0 ) + return( ret ); + + /* Space for further checks */ + + return( 0 ); +} + +/* + * Setup an SSL context + */ + +int mbedtls_ssl_setup( mbedtls_ssl_context *ssl, + const mbedtls_ssl_config *conf ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; + + ssl->conf = conf; + + if( ( ret = ssl_conf_check( ssl ) ) != 0 ) + return( ret ); + + /* + * Prepare base structures + */ + + /* Set to NULL in case of an error condition */ + ssl->out_buf = NULL; + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = in_buf_len; +#endif + ssl->in_buf = mbedtls_calloc( 1, in_buf_len ); + if( ssl->in_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", in_buf_len ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->out_buf_len = out_buf_len; +#endif + ssl->out_buf = mbedtls_calloc( 1, out_buf_len ); + if( ssl->out_buf == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed", out_buf_len ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + + mbedtls_ssl_reset_in_out_pointers( ssl ); + +#if defined(MBEDTLS_SSL_DTLS_SRTP) + memset( &ssl->dtls_srtp_info, 0, sizeof(ssl->dtls_srtp_info) ); +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + goto error; + + return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + ssl->in_buf_len = 0; + ssl->out_buf_len = 0; +#endif + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + * + * If partial is non-zero, keep data in the input buffer and client ID. + * (Use when a DTLS client reconnects from the same port.) + */ +static void ssl_session_reset_msg_layer( mbedtls_ssl_context *ssl, + int partial ) +{ +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; + size_t out_buf_len = ssl->out_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + +#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C) + partial = 0; +#endif + + /* Cancel any possibly running timer */ + mbedtls_ssl_set_timer( ssl, 0 ); + + mbedtls_ssl_reset_in_out_pointers( ssl ); + + /* Reset incoming message parsing */ + ssl->in_offt = NULL; + ssl->nb_zero = 0; + ssl->in_msgtype = 0; + ssl->in_msglen = 0; + ssl->in_hslen = 0; + ssl->keep_current_message = 0; + ssl->transform_in = NULL; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->next_record_offset = 0; + ssl->in_epoch = 0; +#endif + + /* Keep current datagram if partial == 1 */ + if( partial == 0 ) + { + ssl->in_left = 0; + memset( ssl->in_buf, 0, in_buf_len ); + } + + /* Reset outgoing message writing */ + ssl->out_msgtype = 0; + ssl->out_msglen = 0; + ssl->out_left = 0; + memset( ssl->out_buf, 0, out_buf_len ); + memset( ssl->cur_out_ctr, 0, sizeof( ssl->cur_out_ctr ) ); + ssl->transform_out = NULL; + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + mbedtls_ssl_dtls_replay_reset( ssl ); +#endif + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + ssl->transform = NULL; + } +} + +int mbedtls_ssl_session_reset_int( mbedtls_ssl_context *ssl, int partial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + + ssl_session_reset_msg_layer( ssl, partial ); + + /* Reset renegotiation state */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->renego_status = MBEDTLS_SSL_INITIAL_HANDSHAKE; + ssl->renego_records_seen = 0; + + ssl->verify_data_len = 0; + memset( ssl->own_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); + memset( ssl->peer_verify_data, 0, MBEDTLS_SSL_VERIFY_DATA_MAX_LEN ); +#endif + ssl->secure_renegotiation = MBEDTLS_SSL_LEGACY_RENEGOTIATION; + + ssl->session_in = NULL; + ssl->session_out = NULL; + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + ssl->session = NULL; + } + +#if defined(MBEDTLS_SSL_ALPN) + ssl->alpn_chosen = NULL; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) + if( partial == 0 ) +#endif + { + mbedtls_free( ssl->cli_id ); + ssl->cli_id = NULL; + ssl->cli_id_len = 0; + } +#endif + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Reset an initialized and used SSL context for re-use while retaining + * all application-set variables, function pointers and data. + */ +int mbedtls_ssl_session_reset( mbedtls_ssl_context *ssl ) +{ + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * SSL set accessors + */ +void mbedtls_ssl_conf_endpoint( mbedtls_ssl_config *conf, int endpoint ) +{ + conf->endpoint = endpoint; +} + +void mbedtls_ssl_conf_transport( mbedtls_ssl_config *conf, int transport ) +{ + conf->transport = transport; +} + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +void mbedtls_ssl_conf_dtls_anti_replay( mbedtls_ssl_config *conf, char mode ) +{ + conf->anti_replay = mode; +} +#endif + +void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limit ) +{ + conf->badmac_limit = limit; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + +void mbedtls_ssl_set_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) +{ + conf->hs_timeout_min = min; + conf->hs_timeout_max = max; +} +#endif + +void mbedtls_ssl_conf_authmode( mbedtls_ssl_config *conf, int authmode ) +{ + conf->authmode = authmode; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + conf->f_vrfy = f_vrfy; + conf->p_vrfy = p_vrfy; +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_conf_rng( mbedtls_ssl_config *conf, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + conf->f_rng = f_rng; + conf->p_rng = p_rng; +} + +void mbedtls_ssl_conf_dbg( mbedtls_ssl_config *conf, + void (*f_dbg)(void *, int, const char *, int, const char *), + void *p_dbg ) +{ + conf->f_dbg = f_dbg; + conf->p_dbg = p_dbg; +} + +void mbedtls_ssl_set_bio( mbedtls_ssl_context *ssl, + void *p_bio, + mbedtls_ssl_send_t *f_send, + mbedtls_ssl_recv_t *f_recv, + mbedtls_ssl_recv_timeout_t *f_recv_timeout ) +{ + ssl->p_bio = p_bio; + ssl->f_send = f_send; + ssl->f_recv = f_recv; + ssl->f_recv_timeout = f_recv_timeout; +} + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu ) +{ + ssl->mtu = mtu; +} +#endif + +void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout ) +{ + conf->read_timeout = timeout; +} + +void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl, + void *p_timer, + mbedtls_ssl_set_timer_t *f_set_timer, + mbedtls_ssl_get_timer_t *f_get_timer ) +{ + ssl->p_timer = p_timer; + ssl->f_set_timer = f_set_timer; + ssl->f_get_timer = f_get_timer; + + /* Make sure we start with no timer running */ + mbedtls_ssl_set_timer( ssl, 0 ); +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf, + void *p_cache, + mbedtls_ssl_cache_get_t *f_get_cache, + mbedtls_ssl_cache_set_t *f_set_cache ) +{ + conf->p_cache = p_cache; + conf->f_get_cache = f_get_cache; + conf->f_set_cache = f_set_cache; +} +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session *session ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || + session == NULL || + ssl->session_negotiate == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ssl->handshake->resume == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate, + session ) ) != 0 ) + return( ret ); + + ssl->handshake->resume = 1; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +void mbedtls_ssl_conf_ciphersuites( mbedtls_ssl_config *conf, + const int *ciphersuites ) +{ + conf->ciphersuite_list = ciphersuites; +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +void mbedtls_ssl_conf_tls13_key_exchange_modes( mbedtls_ssl_config *conf, + const int kex_modes ) +{ + conf->tls13_kex_modes = kex_modes & MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_conf_cert_profile( mbedtls_ssl_config *conf, + const mbedtls_x509_crt_profile *profile ) +{ + conf->cert_profile = profile; +} + +/* Append a new keycert entry to a (possibly empty) list */ +static int ssl_append_key_cert( mbedtls_ssl_key_cert **head, + mbedtls_x509_crt *cert, + mbedtls_pk_context *key ) +{ + mbedtls_ssl_key_cert *new_cert; + + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new_cert; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new_cert; + } + + return( 0 ); +} + +int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &conf->key_cert, own_cert, pk_key ) ); +} + +void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + conf->ca_chain = ca_chain; + conf->ca_crl = ca_crl; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->f_ca_cb = NULL; + conf->p_ca_cb = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ) +{ + conf->f_ca_cb = f_ca_cb; + conf->p_ca_cb = p_ca_cb; + + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->ca_chain = NULL; + conf->ca_crl = NULL; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +int mbedtls_ssl_set_hs_own_cert( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *own_cert, + mbedtls_pk_context *pk_key ) +{ + return( ssl_append_key_cert( &ssl->handshake->sni_key_cert, + own_cert, pk_key ) ); +} + +void mbedtls_ssl_set_hs_ca_chain( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *ca_chain, + mbedtls_x509_crl *ca_crl ) +{ + ssl->handshake->sni_ca_chain = ca_chain; + ssl->handshake->sni_ca_crl = ca_crl; +} + +void mbedtls_ssl_set_hs_authmode( mbedtls_ssl_context *ssl, + int authmode ) +{ + ssl->handshake->sni_authmode = authmode; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + ssl->f_vrfy = f_vrfy; + ssl->p_vrfy = p_vrfy; +} +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +/* + * Set EC J-PAKE password for current handshake + */ +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + mbedtls_ecjpake_role role; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + role = MBEDTLS_ECJPAKE_SERVER; + else + role = MBEDTLS_ECJPAKE_CLIENT; + + return( mbedtls_ecjpake_setup( &ssl->handshake->ecjpake_ctx, + role, + MBEDTLS_MD_SHA256, + MBEDTLS_ECP_DP_SECP256R1, + pw, pw_len ) ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + +static int ssl_conf_psk_is_configured( mbedtls_ssl_config const *conf ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( !mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( conf->psk != NULL ) + return( 1 ); + + return( 0 ); +} + +static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) +{ + /* Remove reference to existing PSK, if any. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( conf->psk_opaque ) ) + { + /* The maintenance of the PSK key slot is the + * user's responsibility. */ + conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } + /* This and the following branch should never + * be taken simultaenously as we maintain the + * invariant that raw and opaque PSKs are never + * configured simultaneously. As a safeguard, + * though, `else` is omitted here. */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + /* Remove reference to PSK identity, if any. */ + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +} + +/* This function assumes that PSK identity in the SSL config is unset. + * It checks that the provided identity is well-formed and attempts + * to make a copy of it in the SSL config. + * On failure, the PSK identity in the config remains unset. */ +static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf, + unsigned char const *psk_identity, + size_t psk_identity_len ) +{ + /* Identity len will be encoded on two bytes */ + if( psk_identity == NULL || + ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ); + if( conf->psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + conf->psk_identity_len = psk_identity_len; + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + return( 0 ); +} + +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* We currently only support one PSK, raw or opaque. */ + if( ssl_conf_psk_is_configured( conf ) ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + + /* Check and set raw PSK */ + if( psk == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( psk_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + conf->psk_len = psk_len; + memcpy( conf->psk, psk, conf->psk_len ); + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + +static void ssl_remove_psk( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ! mbedtls_svc_key_id_is_null( ssl->handshake->psk_opaque ) ) + { + ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ssl->handshake->psk != NULL ) + { + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } +} + +int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, + const unsigned char *psk, size_t psk_len ) +{ + if( psk == NULL || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + + if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + ssl->handshake->psk_len = psk_len; + memcpy( ssl->handshake->psk, psk, ssl->handshake->psk_len ); + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_id_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* We currently only support one PSK, raw or opaque. */ + if( ssl_conf_psk_is_configured( conf ) ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + + /* Check and set opaque PSK */ + if( mbedtls_svc_key_id_is_null( psk ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + conf->psk_opaque = psk; + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, + psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_id_t psk ) +{ + if( ( mbedtls_svc_key_id_is_null( psk ) ) || + ( ssl->handshake == NULL ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + ssl->handshake->psk_opaque = psk; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, + int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, + size_t), + void *p_psk ) +{ + conf->f_psk = f_psk; + conf->p_psk = p_psk; +} +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) +int mbedtls_ssl_conf_dh_param_bin( mbedtls_ssl_config *conf, + const unsigned char *dhm_P, size_t P_len, + const unsigned char *dhm_G, size_t G_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_read_binary( &conf->dhm_P, dhm_P, P_len ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &conf->dhm_G, dhm_G, G_len ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} + +int mbedtls_ssl_conf_dh_param_ctx( mbedtls_ssl_config *conf, mbedtls_dhm_context *dhm_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_dhm_get_value( dhm_ctx, MBEDTLS_DHM_PARAM_P, + &conf->dhm_P ) ) != 0 || + ( ret = mbedtls_dhm_get_value( dhm_ctx, MBEDTLS_DHM_PARAM_G, + &conf->dhm_G ) ) != 0 ) + { + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) +/* + * Set the minimum length for Diffie-Hellman parameters + */ +void mbedtls_ssl_conf_dhm_min_bitlen( mbedtls_ssl_config *conf, + unsigned int bitlen ) +{ + conf->dhm_min_bitlen = bitlen; +} +#endif /* MBEDTLS_DHM_C && MBEDTLS_SSL_CLI_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Set allowed/preferred hashes for handshake signatures + */ +void mbedtls_ssl_conf_sig_hashes( mbedtls_ssl_config *conf, + const int *hashes ) +{ + conf->sig_hashes = hashes; +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +/* Configure allowed signature algorithms for use in TLS 1.3 */ +void mbedtls_ssl_conf_sig_algs( mbedtls_ssl_config *conf, + const uint16_t* sig_algs ) +{ + conf->tls13_sig_algs = sig_algs; +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +/* + * Set the allowed elliptic curves + * + * mbedtls_ssl_setup() takes the provided list + * and translates it to a list of IANA TLS group identifiers, + * stored in ssl->handshake->group_list. + * + */ +void mbedtls_ssl_conf_curves( mbedtls_ssl_config *conf, + const mbedtls_ecp_group_id *curve_list ) +{ + conf->curve_list = curve_list; + conf->group_list = NULL; +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +/* + * Set the allowed groups + */ +void mbedtls_ssl_conf_groups( mbedtls_ssl_config *conf, + const uint16_t *group_list ) +{ +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = group_list; +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_set_hostname( mbedtls_ssl_context *ssl, const char *hostname ) +{ + /* Initialize to suppress unnecessary compiler warning */ + size_t hostname_len = 0; + + /* Check if new hostname is valid before + * making any change to current one */ + if( hostname != NULL ) + { + hostname_len = strlen( hostname ); + + if( hostname_len > MBEDTLS_SSL_MAX_HOST_NAME_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Now it's clear that we will overwrite the old hostname, + * so we can free it safely */ + + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } + + /* Passing NULL as hostname shall clear the old one */ + + if( hostname == NULL ) + { + ssl->hostname = NULL; + } + else + { + ssl->hostname = mbedtls_calloc( 1, hostname_len + 1 ); + if( ssl->hostname == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( ssl->hostname, hostname, hostname_len ); + + ssl->hostname[hostname_len] = '\0'; + } + + return( 0 ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, + int (*f_sni)(void *, mbedtls_ssl_context *, + const unsigned char *, size_t), + void *p_sni ) +{ + conf->f_sni = f_sni; + conf->p_sni = p_sni; +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ALPN) +int mbedtls_ssl_conf_alpn_protocols( mbedtls_ssl_config *conf, const char **protos ) +{ + size_t cur_len, tot_len; + const char **p; + + /* + * RFC 7301 3.1: "Empty strings MUST NOT be included and byte strings + * MUST NOT be truncated." + * We check lengths now rather than later. + */ + tot_len = 0; + for( p = protos; *p != NULL; p++ ) + { + cur_len = strlen( *p ); + tot_len += cur_len; + + if( ( cur_len == 0 ) || + ( cur_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) || + ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->alpn_list = protos; + + return( 0 ); +} + +const char *mbedtls_ssl_get_alpn_protocol( const mbedtls_ssl_context *ssl ) +{ + return( ssl->alpn_chosen ); +} +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) +void mbedtls_ssl_conf_srtp_mki_value_supported( mbedtls_ssl_config *conf, + int support_mki_value ) +{ + conf->dtls_srtp_mki_support = support_mki_value; +} + +int mbedtls_ssl_dtls_srtp_set_mki_value( mbedtls_ssl_context *ssl, + unsigned char *mki_value, + uint16_t mki_len ) +{ + if( mki_len > MBEDTLS_TLS_SRTP_MAX_MKI_LENGTH ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + if( ssl->conf->dtls_srtp_mki_support == MBEDTLS_SSL_DTLS_SRTP_MKI_UNSUPPORTED ) + { + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + memcpy( ssl->dtls_srtp_info.mki_value, mki_value, mki_len ); + ssl->dtls_srtp_info.mki_len = mki_len; + return( 0 ); +} + +int mbedtls_ssl_conf_dtls_srtp_protection_profiles( mbedtls_ssl_config *conf, + const mbedtls_ssl_srtp_profile *profiles ) +{ + const mbedtls_ssl_srtp_profile *p; + size_t list_size = 0; + + /* check the profiles list: all entry must be valid, + * its size cannot be more than the total number of supported profiles, currently 4 */ + for( p = profiles; *p != MBEDTLS_TLS_SRTP_UNSET && + list_size <= MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH; + p++ ) + { + if( mbedtls_ssl_check_srtp_profile_value( *p ) != MBEDTLS_TLS_SRTP_UNSET ) + { + list_size++; + } + else + { + /* unsupported value, stop parsing and set the size to an error value */ + list_size = MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH + 1; + } + } + + if( list_size > MBEDTLS_TLS_SRTP_MAX_PROFILE_LIST_LENGTH ) + { + conf->dtls_srtp_profile_list = NULL; + conf->dtls_srtp_profile_list_len = 0; + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->dtls_srtp_profile_list = profiles; + conf->dtls_srtp_profile_list_len = list_size; + + return( 0 ); +} + +void mbedtls_ssl_get_dtls_srtp_negotiation_result( const mbedtls_ssl_context *ssl, + mbedtls_dtls_srtp_info *dtls_srtp_info ) +{ + dtls_srtp_info->chosen_dtls_srtp_profile = ssl->dtls_srtp_info.chosen_dtls_srtp_profile; + /* do not copy the mki value if there is no chosen profile */ + if( dtls_srtp_info->chosen_dtls_srtp_profile == MBEDTLS_TLS_SRTP_UNSET ) + { + dtls_srtp_info->mki_len = 0; + } + else + { + dtls_srtp_info->mki_len = ssl->dtls_srtp_info.mki_len; + memcpy( dtls_srtp_info->mki_value, ssl->dtls_srtp_info.mki_value, + ssl->dtls_srtp_info.mki_len ); + } +} +#endif /* MBEDTLS_SSL_DTLS_SRTP */ + +void mbedtls_ssl_conf_max_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->max_major_ver = major; + conf->max_minor_ver = minor; +} + +void mbedtls_ssl_conf_min_version( mbedtls_ssl_config *conf, int major, int minor ) +{ + conf->min_major_ver = major; + conf->min_minor_ver = minor; +} + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_cert_req_ca_list( mbedtls_ssl_config *conf, + char cert_req_ca_list ) +{ + conf->cert_req_ca_list = cert_req_ca_list; +} +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +void mbedtls_ssl_conf_encrypt_then_mac( mbedtls_ssl_config *conf, char etm ) +{ + conf->encrypt_then_mac = etm; +} +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +void mbedtls_ssl_conf_extended_master_secret( mbedtls_ssl_config *conf, char ems ) +{ + conf->extended_ms = ems; +} +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +int mbedtls_ssl_conf_max_frag_len( mbedtls_ssl_config *conf, unsigned char mfl_code ) +{ + if( mfl_code >= MBEDTLS_SSL_MAX_FRAG_LEN_INVALID || + ssl_mfl_code_to_length( mfl_code ) > MBEDTLS_TLS_EXT_ADV_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + conf->mfl_code = mfl_code; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +void mbedtls_ssl_conf_legacy_renegotiation( mbedtls_ssl_config *conf, int allow_legacy ) +{ + conf->allow_legacy_renegotiation = allow_legacy; +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +void mbedtls_ssl_conf_renegotiation( mbedtls_ssl_config *conf, int renegotiation ) +{ + conf->disable_renegotiation = renegotiation; +} + +void mbedtls_ssl_conf_renegotiation_enforced( mbedtls_ssl_config *conf, int max_records ) +{ + conf->renego_max_records = max_records; +} + +void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf, + const unsigned char period[8] ) +{ + memcpy( conf->renego_period, period, 8 ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#if defined(MBEDTLS_SSL_CLI_C) +void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets ) +{ + conf->session_tickets = use_tickets; +} +#endif + +#if defined(MBEDTLS_SSL_SRV_C) +void mbedtls_ssl_conf_session_tickets_cb( mbedtls_ssl_config *conf, + mbedtls_ssl_ticket_write_t *f_ticket_write, + mbedtls_ssl_ticket_parse_t *f_ticket_parse, + void *p_ticket ) +{ + conf->f_ticket_write = f_ticket_write; + conf->f_ticket_parse = f_ticket_parse; + conf->p_ticket = p_ticket; +} +#endif +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +void mbedtls_ssl_set_export_keys_cb( mbedtls_ssl_context *ssl, + mbedtls_ssl_export_keys_t *f_export_keys, + void *p_export_keys ) +{ + ssl->f_export_keys = f_export_keys; + ssl->p_export_keys = p_export_keys; +} + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +void mbedtls_ssl_conf_async_private_cb( + mbedtls_ssl_config *conf, + mbedtls_ssl_async_sign_t *f_async_sign, + mbedtls_ssl_async_decrypt_t *f_async_decrypt, + mbedtls_ssl_async_resume_t *f_async_resume, + mbedtls_ssl_async_cancel_t *f_async_cancel, + void *async_config_data ) +{ + conf->f_async_sign_start = f_async_sign; + conf->f_async_decrypt_start = f_async_decrypt; + conf->f_async_resume = f_async_resume; + conf->f_async_cancel = f_async_cancel; + conf->p_async_config_data = async_config_data; +} + +void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf ) +{ + return( conf->p_async_config_data ); +} + +void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl ) +{ + if( ssl->handshake == NULL ) + return( NULL ); + else + return( ssl->handshake->user_async_ctx ); +} + +void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl, + void *ctx ) +{ + if( ssl->handshake != NULL ) + ssl->handshake->user_async_ctx = ctx; +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * SSL get accessors + */ +uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl ) +{ + if( ssl->session != NULL ) + return( ssl->session->verify_result ); + + if( ssl->session_negotiate != NULL ) + return( ssl->session_negotiate->verify_result ); + + return( 0xFFFFFFFF ); +} + +const char *mbedtls_ssl_get_ciphersuite( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + + return mbedtls_ssl_get_ciphersuite_name( ssl->session->ciphersuite ); +} + +const char *mbedtls_ssl_get_version( const mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "DTLSv1.2" ); + + default: + return( "unknown (DTLS)" ); + } + } +#endif + + switch( ssl->minor_ver ) + { + case MBEDTLS_SSL_MINOR_VERSION_3: + return( "TLSv1.2" ); + + default: + return( "unknown" ); + } +} + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +size_t mbedtls_ssl_get_input_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; + size_t read_mfl; + + /* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE ) + { + return ssl_mfl_code_to_length( ssl->conf->mfl_code ); + } + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + // During a handshake, use the value being negotiated + if( ssl->session_negotiate != NULL ) + { + read_mfl = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + if( read_mfl < max_len ) + { + max_len = read_mfl; + } + } + + return( max_len ); +} + +size_t mbedtls_ssl_get_output_max_frag_len( const mbedtls_ssl_context *ssl ) +{ + size_t max_len; + + /* + * Assume mfl_code is correct since it was checked when set + */ + max_len = ssl_mfl_code_to_length( ssl->conf->mfl_code ); + + /* Check if a smaller max length was negotiated */ + if( ssl->session_out != NULL && + ssl_mfl_code_to_length( ssl->session_out->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_out->mfl_code ); + } + + /* During a handshake, use the value being negotiated */ + if( ssl->session_negotiate != NULL && + ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ) < max_len ) + { + max_len = ssl_mfl_code_to_length( ssl->session_negotiate->mfl_code ); + } + + return( max_len ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +size_t mbedtls_ssl_get_current_mtu( const mbedtls_ssl_context *ssl ) +{ + /* Return unlimited mtu for client hello messages to avoid fragmentation. */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + ( ssl->state == MBEDTLS_SSL_CLIENT_HELLO || + ssl->state == MBEDTLS_SSL_SERVER_HELLO ) ) + return ( 0 ); + + if( ssl->handshake == NULL || ssl->handshake->mtu == 0 ) + return( ssl->mtu ); + + if( ssl->mtu == 0 ) + return( ssl->handshake->mtu ); + + return( ssl->mtu < ssl->handshake->mtu ? + ssl->mtu : ssl->handshake->mtu ); +} +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_output_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( mbedtls_ssl_get_current_mtu( ssl ) != 0 ) + { + const size_t mtu = mbedtls_ssl_get_current_mtu( ssl ); + const int ret = mbedtls_ssl_get_record_expansion( ssl ); + const size_t overhead = (size_t) ret; + + if( ret < 0 ) + return( ret ); + + if( mtu <= overhead ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "MTU too low for record expansion" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + if( max_len > mtu - overhead ) + max_len = mtu - overhead; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \ + !defined(MBEDTLS_SSL_PROTO_DTLS) + ((void) ssl); +#endif + + return( (int) max_len ); +} + +int mbedtls_ssl_get_max_in_record_payload( const mbedtls_ssl_context *ssl ) +{ + size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN; + +#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + (void) ssl; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + const size_t mfl = mbedtls_ssl_get_input_max_frag_len( ssl ); + + if( max_len > mfl ) + max_len = mfl; +#endif + + return( (int) max_len ); +} + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL || ssl->session == NULL ) + return( NULL ); + +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + return( ssl->session->peer_cert ); +#else + return( NULL ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) +int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, + mbedtls_ssl_session *dst ) +{ + int ret; + + if( ssl == NULL || + dst == NULL || + ssl->session == NULL || + ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* Since Mbed TLS 3.0, mbedtls_ssl_get_session() is no longer + * idempotent: Each session can only be exported once. + * + * (This is in preparation for TLS 1.3 support where we will + * need the ability to export multiple sessions (aka tickets), + * which will be achieved by calling mbedtls_ssl_get_session() + * multiple times until it fails.) + * + * Check whether we have already exported the current session, + * and fail if so. + */ + if( ssl->session->exported == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + + ret = mbedtls_ssl_session_copy( dst, ssl->session ); + if( ret != 0 ) + return( ret ); + + /* Remember that we've exported the session. */ + ssl->session->exported = 1; + return( 0 ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +/* + * Define ticket header determining Mbed TLS version + * and structure of the ticket. + */ + +/* + * Define bitflag determining compile-time settings influencing + * structure of serialized SSL sessions. + */ + +#if defined(MBEDTLS_HAVE_TIME) +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0 +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0 +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0 +#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0 +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0 +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1 +#else +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0 +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0 +#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1 +#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2 +#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3 +#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 4 +#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 5 + +#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \ + ( (uint16_t) ( \ + ( SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \ + ( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) ) ) + +static unsigned char ssl_serialized_session_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), + MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), +}; + +/* + * Serialize a session in the following format: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * struct { + * + * opaque mbedtls_version[3]; // library version: major, minor, patch + * opaque session_format[2]; // library-version specific 16-bit field + * // determining the format of the remaining + * // serialized data. + * + * Note: When updating the format, remember to keep + * these version+format bytes. + * + * // In this version, `session_format` determines + * // the setting of those compile-time + * // configuration options which influence + * // the structure of mbedtls_ssl_session. + * + * uint8_t minor_ver; // Protocol-version. Possible values: + * // - TLS 1.2 (MBEDTLS_SSL_MINOR_VERSION_3) + * + * select (serialized_session.minor_ver) { + * + * case MBEDTLS_SSL_MINOR_VERSION_3: // TLS 1.2 + * serialized_session_tls12 data; + * + * }; + * + * } serialized_session; + * + */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +/* Serialization of TLS 1.2 sessions: + * + * struct { + * uint64 start_time; + * uint8 ciphersuite[2]; // defined by the standard + * uint8 compression; // 0 or 1 + * uint8 session_id_len; // at most 32 + * opaque session_id[32]; + * opaque master[48]; // fixed length in the standard + * uint32 verify_result; + * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert + * opaque ticket<0..2^24-1>; // length 0 means no ticket + * uint32 ticket_lifetime; + * uint8 mfl_code; // up to 255 according to standard + * uint8 encrypt_then_mac; // 0 or 1 + * } serialized_session_tls12; + * + */ +static size_t ssl_session_save_tls12( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len ) +{ + unsigned char *p = buf; + size_t used = 0; + +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + used += 8; + + if( used <= buf_len ) + { + start = (uint64_t) session->start; + + MBEDTLS_PUT_UINT64_BE( start, p, 0 ); + p += 8; + } +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + used += 2 /* ciphersuite */ + + 1 /* compression */ + + 1 /* id_len */ + + sizeof( session->id ) + + sizeof( session->master ) + + 4; /* verify_result */ + + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT16_BE( session->ciphersuite, p, 0 ); + p += 2; + + *p++ = MBEDTLS_BYTE_0( session->compression ); + + *p++ = MBEDTLS_BYTE_0( session->id_len ); + memcpy( p, session->id, 32 ); + p += 32; + + memcpy( p, session->master, 48 ); + p += 48; + + MBEDTLS_PUT_UINT32_BE( session->verify_result, p, 0 ); + p += 4; + } + + /* + * Peer's end-entity certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + if( session->peer_cert == NULL ) + cert_len = 0; + else + cert_len = session->peer_cert->raw.len; + + used += 3 + cert_len; + + if( used <= buf_len ) + { + *p++ = MBEDTLS_BYTE_2( cert_len ); + *p++ = MBEDTLS_BYTE_1( cert_len ); + *p++ = MBEDTLS_BYTE_0( cert_len ); + + if( session->peer_cert != NULL ) + { + memcpy( p, session->peer_cert->raw.p, cert_len ); + p += cert_len; + } + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + if( session->peer_cert_digest != NULL ) + { + used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len; + if( used <= buf_len ) + { + *p++ = (unsigned char) session->peer_cert_digest_type; + *p++ = (unsigned char) session->peer_cert_digest_len; + memcpy( p, session->peer_cert_digest, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } + } + else + { + used += 2; + if( used <= buf_len ) + { + *p++ = (unsigned char) MBEDTLS_MD_NONE; + *p++ = 0; + } + } +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Session ticket if any, plus associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */ + + if( used <= buf_len ) + { + *p++ = MBEDTLS_BYTE_2( session->ticket_len ); + *p++ = MBEDTLS_BYTE_1( session->ticket_len ); + *p++ = MBEDTLS_BYTE_0( session->ticket_len ); + + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } + + MBEDTLS_PUT_UINT32_BE( session->ticket_lifetime, p, 0 ); + p += 4; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + used += 1; + + if( used <= buf_len ) + *p++ = session->mfl_code; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + used += 1; + + if( used <= buf_len ) + *p++ = MBEDTLS_BYTE_0( session->encrypt_then_mac ); +#endif + + return( used ); +} +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +static int ssl_session_save( const mbedtls_ssl_session *session, + unsigned char omit_header, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t used = 0; + + if( !omit_header ) + { + /* + * Add Mbed TLS version identifier + */ + + used += sizeof( ssl_serialized_session_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ); + p += sizeof( ssl_serialized_session_header ); + } + } + + /* + * TLS version identifier + */ + used += 1; + if( used <= buf_len ) + { + *p++ = session->minor_ver; + } + + /* Forward to version-specific serialization routine. */ + switch( session->minor_ver ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + case MBEDTLS_SSL_MINOR_VERSION_3: + { + size_t remaining_len = used <= buf_len ? buf_len - used : 0; + used += ssl_session_save_tls12( session, p, remaining_len ); + break; + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + default: + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); + } + + *olen = used; + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + return( 0 ); +} + +/* + * Public wrapper for ssl_session_save() + */ +int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + return( ssl_session_save( session, 0, buf, buf_len, olen ) ); +} + +/* + * Deserialize session, see mbedtls_ssl_session_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error, and has an extra option omit_header. + */ +static int ssl_session_load_tls12( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ +#if defined(MBEDTLS_HAVE_TIME) + uint64_t start; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + size_t cert_len; +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + + /* + * Time + */ +#if defined(MBEDTLS_HAVE_TIME) + if( 8 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + start = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + session->start = (time_t) start; +#endif /* MBEDTLS_HAVE_TIME */ + + /* + * Basic mandatory fields + */ + if( 2 + 1 + 1 + 32 + 48 + 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ciphersuite = ( p[0] << 8 ) | p[1]; + p += 2; + + session->compression = *p++; + + session->id_len = *p++; + memcpy( session->id, p, 32 ); + p += 32; + + memcpy( session->master, p, 48 ); + p += 48; + + session->verify_result = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; + + /* Immediately clear invalid pointer values that have been read, in case + * we exit early before we replaced them with valid ones. */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + session->peer_cert = NULL; +#else + session->peer_cert_digest = NULL; +#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + session->ticket = NULL; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Peer certificate + */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + /* Deserialize CRT from the end of the ticket. */ + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( cert_len != 0 ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( cert_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( session->peer_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + mbedtls_x509_crt_init( session->peer_cert ); + + if( ( ret = mbedtls_x509_crt_parse_der( session->peer_cert, + p, cert_len ) ) != 0 ) + { + mbedtls_x509_crt_free( session->peer_cert ); + mbedtls_free( session->peer_cert ); + session->peer_cert = NULL; + return( ret ); + } + + p += cert_len; + } +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + /* Deserialize CRT digest from the end of the ticket. */ + if( 2 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest_type = (mbedtls_md_type_t) *p++; + session->peer_cert_digest_len = (size_t) *p++; + + if( session->peer_cert_digest_len != 0 ) + { + const mbedtls_md_info_t *md_info = + mbedtls_md_info_from_type( session->peer_cert_digest_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( session->peer_cert_digest_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->peer_cert_digest = + mbedtls_calloc( 1, session->peer_cert_digest_len ); + if( session->peer_cert_digest == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->peer_cert_digest, p, + session->peer_cert_digest_len ); + p += session->peer_cert_digest_len; + } +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * Session ticket and associated data + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( session->ticket_len != 0 ) + { + if( session->ticket_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket = mbedtls_calloc( 1, session->ticket_len ); + if( session->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->ticket, p, session->ticket_len ); + p += session->ticket_len; + } + + if( 4 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_lifetime = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* + * Misc extension-related info + */ +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->mfl_code = *p++; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->encrypt_then_mac = *p++; +#endif + + /* Done, should have consumed entire buffer */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int ssl_session_load( mbedtls_ssl_session *session, + unsigned char omit_header, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + + if( !omit_header ) + { + /* + * Check Mbed TLS version identifier + */ + + if( (size_t)( end - p ) < sizeof( ssl_serialized_session_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_session_header, + sizeof( ssl_serialized_session_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_session_header ); + } + + /* + * TLS version identifier + */ + if( 1 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + session->minor_ver = *p++; + + /* Dispatch according to TLS version. */ + switch( session->minor_ver ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + case MBEDTLS_SSL_MINOR_VERSION_3: /* TLS 1.2 */ + { + size_t remaining_len = ( end - p ); + return( ssl_session_load_tls12( session, p, remaining_len ) ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + default: + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +} + +/* + * Deserialize session: public wrapper for error cleaning + */ +int mbedtls_ssl_session_load( mbedtls_ssl_session *session, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_session_load( session, 0, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_session_free( session ); + + return( ret ); +} + +/* + * Perform a single step of the SSL handshake + */ +static int ssl_prepare_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING ) + { + if( ( ret = mbedtls_ssl_flight_transmit( ssl ) ) != 0 ) + return( ret ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + return( ret ); +} + +int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ssl == NULL || + ssl->conf == NULL || + ssl->handshake == NULL || + ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + ret = ssl_prepare_handshake_step( ssl ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_handle_pending_alert( ssl ); + if( ret != 0 ) + goto cleanup; + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( mbedtls_ssl_conf_is_tls13_only( ssl->conf ) ) + ret = mbedtls_ssl_tls13_handshake_client_step( ssl ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( mbedtls_ssl_conf_is_tls12_only( ssl->conf ) ) + ret = mbedtls_ssl_handshake_client_step( ssl ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + } +#endif +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + if( mbedtls_ssl_conf_is_tls13_only( ssl->conf ) ) + ret = mbedtls_ssl_tls13_handshake_server_step( ssl ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( mbedtls_ssl_conf_is_tls12_only( ssl->conf ) ) + ret = mbedtls_ssl_handshake_server_step( ssl ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + } +#endif + + if( ret != 0 ) + { + /* handshake_step return error. And it is same + * with alert_reason. + */ + if( ssl->send_alert ) + { + ret = mbedtls_ssl_handle_pending_alert( ssl ); + goto cleanup; + } + } + +cleanup: + return( ret ); +} + +/* + * Perform the SSL handshake + */ +int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + /* Sanity checks */ + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use " + "mbedtls_ssl_set_timer_cb() for DTLS" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> handshake" ) ); + + /* Main handshake loop */ + while( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + ret = mbedtls_ssl_handshake_step( ssl ); + + if( ret != 0 ) + break; + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= handshake" ) ); + + return( ret ); +} + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#if defined(MBEDTLS_SSL_SRV_C) +/* + * Write HelloRequest to request renegotiation on server + */ +static int ssl_write_hello_request( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write hello request" ) ); + + ssl->out_msglen = 4; + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = MBEDTLS_SSL_HS_HELLO_REQUEST; + + if( ( ret = mbedtls_ssl_write_handshake_msg( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_handshake_msg", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write hello request" ) ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SRV_C */ + +/* + * Actually renegotiate current connection, triggered by either: + * - any side: calling mbedtls_ssl_renegotiate(), + * - client: receiving a HelloRequest during mbedtls_ssl_read(), + * - server: receiving any handshake message on server during mbedtls_ssl_read() after + * the initial handshake is completed. + * If the handshake doesn't complete due to waiting for I/O, it will continue + * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively. + */ +int mbedtls_ssl_start_renegotiation( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> renegotiate" ) ); + + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) + return( ret ); + + /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and + * the ServerHello will have message_seq = 1" */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING ) + { + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + ssl->handshake->out_msg_seq = 1; + else + ssl->handshake->in_msg_seq = 1; + } +#endif + + ssl->state = MBEDTLS_SSL_HELLO_REQUEST; + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS; + + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= renegotiate" ) ); + + return( 0 ); +} + +/* + * Renegotiate current connection on client, + * or request renegotiation on server + */ +int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + if( ssl == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_SSL_SRV_C) + /* On server, just send the request */ + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING; + + /* Did we already try/start sending HelloRequest? */ + if( ssl->out_left != 0 ) + return( mbedtls_ssl_flush_output( ssl ) ); + + return( ssl_write_hello_request( ssl ) ); + } +#endif /* MBEDTLS_SSL_SRV_C */ + +#if defined(MBEDTLS_SSL_CLI_C) + /* + * On client, either start the renegotiation process or, + * if already in progress, continue the handshake + */ + if( ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS ) + { + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ssl_start_renegotiation( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_start_renegotiation", ret ); + return( ret ); + } + } + else + { + if( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_handshake", ret ); + return( ret ); + } + } +#endif /* MBEDTLS_SSL_CLI_C */ + + return( ret ); +} +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert ) +{ + mbedtls_ssl_key_cert *cur = key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if( handshake == NULL ) + return; + +#if defined(MBEDTLS_ECP_C) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + if ( ssl->handshake->group_list_heap_allocated ) + mbedtls_free( (void*) handshake->group_list ); + handshake->group_list = NULL; +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 ) + { + ssl->conf->f_async_cancel( ssl ); + handshake->async_in_progress = 0; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) +#if defined(MBEDTLS_SHA256_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &handshake->fin_sha256_psa ); +#else + mbedtls_sha256_free( &handshake->fin_sha256 ); +#endif +#endif +#if defined(MBEDTLS_SHA384_C) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_abort( &handshake->fin_sha384_psa ); +#else + mbedtls_sha512_free( &handshake->fin_sha512 ); +#endif +#endif +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_DHM_C) + mbedtls_dhm_free( &handshake->dhm_ctx ); +#endif +#if defined(MBEDTLS_ECDH_C) + mbedtls_ecdh_free( &handshake->ecdh_ctx ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); +#if defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( handshake->ecjpake_cache ); + handshake->ecjpake_cache = NULL; + handshake->ecjpake_cache_len = 0; +#endif +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + /* explicit void pointer cast for buggy MS compiler */ + mbedtls_free( (void *) handshake->curves ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( handshake->psk != NULL ) + { + mbedtls_platform_zeroize( handshake->psk, handshake->psk_len ); + mbedtls_free( handshake->psk ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* + * Free only the linked list wrapper, not the keys themselves + * since the belong to the SNI callback + */ + if( handshake->sni_key_cert != NULL ) + { + mbedtls_ssl_key_cert *cur = handshake->sni_key_cert, *next; + + while( cur != NULL ) + { + next = cur->next; + mbedtls_free( cur ); + cur = next; + } + } +#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED) + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); + if( handshake->ecrs_peer_cert != NULL ) + { + mbedtls_x509_crt_free( handshake->ecrs_peer_cert ); + mbedtls_free( handshake->ecrs_peer_cert ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_pk_free( &handshake->peer_pubkey ); +#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + mbedtls_free( handshake->verify_cookie ); + mbedtls_ssl_flight_free( handshake->flight ); + mbedtls_ssl_buffering_free( ssl ); +#endif + +#if defined(MBEDTLS_ECDH_C) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key( handshake->ecdh_psa_privkey ); +#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free( handshake->transform_handshake ); + mbedtls_ssl_transform_free( handshake->transform_earlydata ); + mbedtls_free( handshake->transform_earlydata ); + mbedtls_free( handshake->transform_handshake ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + /* If the buffers are too big - reallocate. Because of the way Mbed TLS + * processes datagrams and the fact that a datagram is allowed to have + * several records in it, it is possible that the I/O buffers are not + * empty at this stage */ + handle_buffer_resizing( ssl, 1, mbedtls_ssl_get_input_buflen( ssl ), + mbedtls_ssl_get_output_buflen( ssl ) ); +#endif + + /* mbedtls_platform_zeroize MUST be last one in this function */ + mbedtls_platform_zeroize( handshake, + sizeof( mbedtls_ssl_handshake_params ) ); +} + +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ) +{ + if( session == NULL ) + return; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_clear_peer_cert( session ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + mbedtls_free( session->ticket ); +#endif + + mbedtls_platform_zeroize( session, sizeof( mbedtls_ssl_session ) ); +} + +#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_ALPN) +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u +#else +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u +#endif /* MBEDTLS_SSL_ALPN */ + +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT 0 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT 1 +#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT 2 +#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT 3 + +#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG \ + ( (uint32_t) ( \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT ) | \ + ( SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT ) | \ + 0u ) ) + +static unsigned char ssl_serialized_context_header[] = { + MBEDTLS_VERSION_MAJOR, + MBEDTLS_VERSION_MINOR, + MBEDTLS_VERSION_PATCH, + MBEDTLS_BYTE_1( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), + MBEDTLS_BYTE_0( SSL_SERIALIZED_SESSION_CONFIG_BITFLAG ), + MBEDTLS_BYTE_2( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ), + MBEDTLS_BYTE_1( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ), + MBEDTLS_BYTE_0( SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG ), +}; + +/* + * Serialize a full SSL context + * + * The format of the serialized data is: + * (in the presentation language of TLS, RFC 8446 section 3) + * + * // header + * opaque mbedtls_version[3]; // major, minor, patch + * opaque context_format[5]; // version-specific field determining + * // the format of the remaining + * // serialized data. + * Note: When updating the format, remember to keep these + * version+format bytes. (We may make their size part of the API.) + * + * // session sub-structure + * opaque session<1..2^32-1>; // see mbedtls_ssl_session_save() + * // transform sub-structure + * uint8 random[64]; // ServerHello.random+ClientHello.random + * uint8 in_cid<0..2^8-1> // Connection ID: expected incoming value + * uint8 out_cid<0..2^8-1> // Connection ID: outgoing value to use + * // fields from ssl_context + * uint32 badmac_seen; // DTLS: number of records with failing MAC + * uint64 in_window_top; // DTLS: last validated record seq_num + * uint64 in_window; // DTLS: bitmask for replay protection + * uint8 disable_datagram_packing; // DTLS: only one record per datagram + * uint64 cur_out_ctr; // Record layer: outgoing sequence number + * uint16 mtu; // DTLS: path mtu (max outgoing fragment size) + * uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol + * + * Note that many fields of the ssl_context or sub-structures are not + * serialized, as they fall in one of the following categories: + * + * 1. forced value (eg in_left must be 0) + * 2. pointer to dynamically-allocated memory (eg session, transform) + * 3. value can be re-derived from other data (eg session keys from MS) + * 4. value was temporary (eg content of input buffer) + * 5. value will be provided by the user again (eg I/O callbacks and context) + */ +int mbedtls_ssl_context_save( mbedtls_ssl_context *ssl, + unsigned char *buf, + size_t buf_len, + size_t *olen ) +{ + unsigned char *p = buf; + size_t used = 0; + size_t session_len; + int ret = 0; + + /* + * Enforce usage restrictions, see "return BAD_INPUT_DATA" in + * this function's documentation. + * + * These are due to assumptions/limitations in the implementation. Some of + * them are likely to stay (no handshake in progress) some might go away + * (only DTLS) but are currently used to simplify the implementation. + */ + /* The initial handshake must be over */ + if( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Initial handshake isn't over" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->handshake != NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Handshake isn't completed" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Double-check that sub-structures are indeed ready */ + if( ssl->transform == NULL || ssl->session == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Serialised structures aren't ready" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* There must be no pending incoming or outgoing data */ + if( mbedtls_ssl_check_pending( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending incoming data" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->out_left != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "There is pending outgoing data" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Protocol must be DLTS, not TLS */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only DTLS is supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Version must be 1.2 */ + if( ssl->major_ver != MBEDTLS_SSL_MAJOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only version 1.2 supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* We must be using an AEAD ciphersuite */ + if( mbedtls_ssl_transform_uses_aead( ssl->transform ) != 1 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Only AEAD ciphersuites supported" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + /* Renegotiation must not be enabled */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Renegotiation must not be enabled" ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } +#endif + + /* + * Version and format identifier + */ + used += sizeof( ssl_serialized_context_header ); + + if( used <= buf_len ) + { + memcpy( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ); + p += sizeof( ssl_serialized_context_header ); + } + + /* + * Session (length + data) + */ + ret = ssl_session_save( ssl->session, 1, NULL, 0, &session_len ); + if( ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ) + return( ret ); + + used += 4 + session_len; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT32_BE( session_len, p, 0 ); + p += 4; + + ret = ssl_session_save( ssl->session, 1, + p, session_len, &session_len ); + if( ret != 0 ) + return( ret ); + + p += session_len; + } + + /* + * Transform + */ + used += sizeof( ssl->transform->randbytes ); + if( used <= buf_len ) + { + memcpy( p, ssl->transform->randbytes, + sizeof( ssl->transform->randbytes ) ); + p += sizeof( ssl->transform->randbytes ); + } + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len; + if( used <= buf_len ) + { + *p++ = ssl->transform->in_cid_len; + memcpy( p, ssl->transform->in_cid, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + *p++ = ssl->transform->out_cid_len; + memcpy( p, ssl->transform->out_cid, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; + } +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Saved fields from top-level ssl_context structure + */ + used += 4; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT32_BE( ssl->badmac_seen, p, 0 ); + p += 4; + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + used += 16; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT64_BE( ssl->in_window_top, p, 0 ); + p += 8; + + MBEDTLS_PUT_UINT64_BE( ssl->in_window, p, 0 ); + p += 8; + } +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 1; + if( used <= buf_len ) + { + *p++ = ssl->disable_datagram_packing; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + if( used <= buf_len ) + { + memcpy( p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN ); + p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN; + } + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + used += 2; + if( used <= buf_len ) + { + MBEDTLS_PUT_UINT16_BE( ssl->mtu, p, 0 ); + p += 2; + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + const uint8_t alpn_len = ssl->alpn_chosen + ? (uint8_t) strlen( ssl->alpn_chosen ) + : 0; + + used += 1 + alpn_len; + if( used <= buf_len ) + { + *p++ = alpn_len; + + if( ssl->alpn_chosen != NULL ) + { + memcpy( p, ssl->alpn_chosen, alpn_len ); + p += alpn_len; + } + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Done + */ + *olen = used; + + if( used > buf_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "saved context", buf, used ); + + return( mbedtls_ssl_session_reset_int( ssl, 0 ) ); +} + +/* + * Helper to get TLS 1.2 PRF from ciphersuite + * (Duplicates bits of logic from ssl_set_handshake_prfs().) + */ +typedef int (*tls_prf_fn)( const unsigned char *secret, size_t slen, + const char *label, + const unsigned char *random, size_t rlen, + unsigned char *dstbuf, size_t dlen ); +static tls_prf_fn ssl_tls12prf_from_cs( int ciphersuite_id ) +{ +#if defined(MBEDTLS_SHA384_C) + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( ciphersuite_id ); + + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + return( tls_prf_sha384 ); +#else + (void) ciphersuite_id; +#endif + return( tls_prf_sha256 ); +} + +/* + * Deserialize context, see mbedtls_ssl_context_save() for format. + * + * This internal version is wrapped by a public function that cleans up in + * case of error. + */ +static int ssl_context_load( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t len ) +{ + const unsigned char *p = buf; + const unsigned char * const end = buf + len; + size_t session_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * The context should have been freshly setup or reset. + * Give the user an error in case of obvious misuse. + * (Checking session is useful because it won't be NULL if we're + * renegotiating, or if the user mistakenly loaded a session first.) + */ + if( ssl->state != MBEDTLS_SSL_HELLO_REQUEST || + ssl->session != NULL ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * We can't check that the config matches the initial one, but we can at + * least check it matches the requirements for serializing. + */ + if( ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM || + ssl->conf->max_major_ver < MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->min_major_ver > MBEDTLS_SSL_MAJOR_VERSION_3 || + ssl->conf->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3 || + ssl->conf->min_minor_ver > MBEDTLS_SSL_MINOR_VERSION_3 || +#if defined(MBEDTLS_SSL_RENEGOTIATION) + ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED || +#endif + 0 ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "context to load", buf, len ); + + /* + * Check version identifier + */ + if( (size_t)( end - p ) < sizeof( ssl_serialized_context_header ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( memcmp( p, ssl_serialized_context_header, + sizeof( ssl_serialized_context_header ) ) != 0 ) + { + return( MBEDTLS_ERR_SSL_VERSION_MISMATCH ); + } + p += sizeof( ssl_serialized_context_header ); + + /* + * Session + */ + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session_len = ( (size_t) p[0] << 24 ) | + ( (size_t) p[1] << 16 ) | + ( (size_t) p[2] << 8 ) | + ( (size_t) p[3] ); + p += 4; + + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->session = ssl->session_negotiate; + ssl->session_in = ssl->session; + ssl->session_out = ssl->session; + ssl->session_negotiate = NULL; + + if( (size_t)( end - p ) < session_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_session_load( ssl->session, 1, p, session_len ); + if( ret != 0 ) + { + mbedtls_ssl_session_free( ssl->session ); + return( ret ); + } + + p += session_len; + + /* + * Transform + */ + + /* This has been allocated by ssl_handshake_init(), called by + * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */ + ssl->transform = ssl->transform_negotiate; + ssl->transform_in = ssl->transform; + ssl->transform_out = ssl->transform; + ssl->transform_negotiate = NULL; + + /* Read random bytes and populate structure */ + if( (size_t)( end - p ) < sizeof( ssl->transform->randbytes ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ret = ssl_tls12_populate_transform( ssl->transform, + ssl->session->ciphersuite, + ssl->session->master, +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) && \ + defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + ssl->session->encrypt_then_mac, +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC && + MBEDTLS_SSL_SOME_SUITES_USE_MAC */ + ssl_tls12prf_from_cs( ssl->session->ciphersuite ), + p, /* currently pointing to randbytes */ + MBEDTLS_SSL_MINOR_VERSION_3, /* (D)TLS 1.2 is forced */ + ssl->conf->endpoint, + ssl ); + if( ret != 0 ) + return( ret ); + + p += sizeof( ssl->transform->randbytes ); + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) + /* Read connection IDs and store them */ + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->transform->in_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->in_cid_len + 1u ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->in_cid, p, ssl->transform->in_cid_len ); + p += ssl->transform->in_cid_len; + + ssl->transform->out_cid_len = *p++; + + if( (size_t)( end - p ) < ssl->transform->out_cid_len ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + memcpy( ssl->transform->out_cid, p, ssl->transform->out_cid_len ); + p += ssl->transform->out_cid_len; +#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */ + + /* + * Saved fields from top-level ssl_context structure + */ + if( (size_t)( end - p ) < 4 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->badmac_seen = ( (uint32_t) p[0] << 24 ) | + ( (uint32_t) p[1] << 16 ) | + ( (uint32_t) p[2] << 8 ) | + ( (uint32_t) p[3] ); + p += 4; + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( (size_t)( end - p ) < 16 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->in_window_top = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; + + ssl->in_window = ( (uint64_t) p[0] << 56 ) | + ( (uint64_t) p[1] << 48 ) | + ( (uint64_t) p[2] << 40 ) | + ( (uint64_t) p[3] << 32 ) | + ( (uint64_t) p[4] << 24 ) | + ( (uint64_t) p[5] << 16 ) | + ( (uint64_t) p[6] << 8 ) | + ( (uint64_t) p[7] ); + p += 8; +#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */ + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->disable_datagram_packing = *p++; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( (size_t)( end - p ) < sizeof( ssl->cur_out_ctr ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + memcpy( ssl->cur_out_ctr, p, sizeof( ssl->cur_out_ctr ) ); + p += sizeof( ssl->cur_out_ctr ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( (size_t)( end - p ) < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl->mtu = ( p[0] << 8 ) | p[1]; + p += 2; +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_ALPN) + { + uint8_t alpn_len; + const char **cur; + + if( (size_t)( end - p ) < 1 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + alpn_len = *p++; + + if( alpn_len != 0 && ssl->conf->alpn_list != NULL ) + { + /* alpn_chosen should point to an item in the configured list */ + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + { + if( strlen( *cur ) == alpn_len && + memcmp( p, cur, alpn_len ) == 0 ) + { + ssl->alpn_chosen = *cur; + break; + } + } + } + + /* can only happen on conf mismatch */ + if( alpn_len != 0 && ssl->alpn_chosen == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + p += alpn_len; + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * Forced fields from top-level ssl_context structure + * + * Most of them already set to the correct value by mbedtls_ssl_init() and + * mbedtls_ssl_reset(), so we only need to set the remaining ones. + */ + ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER; + + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; + + /* Adjust pointers for header fields of outgoing records to + * the given transform, accounting for explicit IV and CID. */ + mbedtls_ssl_update_out_pointers( ssl, ssl->transform ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + ssl->in_epoch = 1; +#endif + + /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated, + * which we don't want - otherwise we'd end up freeing the wrong transform + * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform() + * inappropriately. */ + if( ssl->handshake != NULL ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_free( ssl->handshake ); + ssl->handshake = NULL; + } + + /* + * Done - should have consumed entire buffer + */ + if( p != end ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + return( 0 ); +} + +/* + * Deserialize context: public wrapper for error cleaning + */ +int mbedtls_ssl_context_load( mbedtls_ssl_context *context, + const unsigned char *buf, + size_t len ) +{ + int ret = ssl_context_load( context, buf, len ); + + if( ret != 0 ) + mbedtls_ssl_free( context ); + + return( ret ); +} +#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */ + +/* + * Free an SSL context + */ +void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) +{ + if( ssl == NULL ) + return; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> free" ) ); + + if( ssl->out_buf != NULL ) + { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t out_buf_len = ssl->out_buf_len; +#else + size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN; +#endif + + mbedtls_platform_zeroize( ssl->out_buf, out_buf_len ); + mbedtls_free( ssl->out_buf ); + ssl->out_buf = NULL; + } + + if( ssl->in_buf != NULL ) + { +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) + size_t in_buf_len = ssl->in_buf_len; +#else + size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN; +#endif + + mbedtls_platform_zeroize( ssl->in_buf, in_buf_len ); + mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; + } + + if( ssl->transform ) + { + mbedtls_ssl_transform_free( ssl->transform ); + mbedtls_free( ssl->transform ); + } + + if( ssl->handshake ) + { + mbedtls_ssl_handshake_free( ssl ); + mbedtls_ssl_transform_free( ssl->transform_negotiate ); + mbedtls_ssl_session_free( ssl->session_negotiate ); + + mbedtls_free( ssl->handshake ); + mbedtls_free( ssl->transform_negotiate ); + mbedtls_free( ssl->session_negotiate ); + } + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + mbedtls_ssl_transform_free( ssl->transform_application ); + mbedtls_free( ssl->transform_application ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ssl->hostname != NULL ) + { + mbedtls_platform_zeroize( ssl->hostname, strlen( ssl->hostname ) ); + mbedtls_free( ssl->hostname ); + } +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + mbedtls_free( ssl->cli_id ); +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= free" ) ); + + /* Actually clear after last debug message */ + mbedtls_platform_zeroize( ssl, sizeof( mbedtls_ssl_context ) ); +} + +/* + * Initialze mbedtls_ssl_config + */ +void mbedtls_ssl_config_init( mbedtls_ssl_config *conf ) +{ + memset( conf, 0, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* The selection should be the same as mbedtls_x509_crt_profile_default in + * x509_crt.c. Here, the order matters. Currently we favor stronger hashes, + * for no fundamental reason. + * See the documentation of mbedtls_ssl_conf_curves() for what we promise + * about this list. */ +static int ssl_preset_default_hashes[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#endif +#if defined(MBEDTLS_SHA384_C) + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, +#endif + MBEDTLS_MD_NONE +}; +#endif + +/* The selection should be the same as mbedtls_x509_crt_profile_default in + * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters: + * curves with a lower resource usage come first. + * See the documentation of mbedtls_ssl_conf_curves() for what we promise + * about this list. + */ +static uint16_t ssl_preset_default_groups[] = { +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_X25519, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_X448, +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, +#endif + MBEDTLS_SSL_IANA_TLS_GROUP_NONE +}; + +static int ssl_preset_suiteb_ciphersuites[] = { + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + 0 +}; + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +static int ssl_preset_suiteb_hashes[] = { + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA384, + MBEDTLS_MD_NONE +}; + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) +static uint16_t ssl_preset_default_sig_algs[] = { + /* ECDSA algorithms */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, +#endif /* MBEDTLS_SHA256_C && MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, +#endif /* MBEDTLS_SHA384_C && MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512, +#endif /* MBEDTLS_SHA512_C && MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#endif /* MBEDTLS_ECDSA_C */ + + /* RSA algorithms */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, + + MBEDTLS_TLS1_3_SIG_NONE +}; + +static uint16_t ssl_preset_suiteb_sig_algs[] = { + /* ECDSA algorithms */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, +#endif /* MBEDTLS_SHA256_C && MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_SHA384_C) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384, +#endif /* MBEDTLS_SHA384_C && MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#endif /* MBEDTLS_ECDSA_C */ + + /* RSA algorithms */ +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256, +#endif + MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256, + + MBEDTLS_TLS1_3_SIG_NONE +}; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif + +static uint16_t ssl_preset_suiteb_groups[] = { +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, +#endif + MBEDTLS_SSL_IANA_TLS_GROUP_NONE +}; + +/* + * Load default in mbedtls_ssl_config + */ +int mbedtls_ssl_config_defaults( mbedtls_ssl_config *conf, + int endpoint, int transport, int preset ) +{ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; +#endif + + /* Use the functions here so that they are covered in tests, + * but otherwise access member directly for efficiency */ + mbedtls_ssl_conf_endpoint( conf, endpoint ); + mbedtls_ssl_conf_transport( conf, transport ); + + /* + * Things that are common to all presets + */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED; +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED; +#endif + } +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C) + conf->f_cookie_write = ssl_cookie_write_dummy; + conf->f_cookie_check = ssl_cookie_check_dummy; +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED; +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED; + conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER; +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN; + conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX; +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT; + memset( conf->renego_period, 0x00, 2 ); + memset( conf->renego_period + 2, 0xFF, 6 ); +#endif + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + const unsigned char dhm_p[] = + MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN; + const unsigned char dhm_g[] = + MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN; + + if ( ( ret = mbedtls_ssl_conf_dh_param_bin( conf, + dhm_p, sizeof( dhm_p ), + dhm_g, sizeof( dhm_g ) ) ) != 0 ) + { + return( ret ); + } + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + /* + * Allow all TLS 1.3 key exchange modes by default. + */ + conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + + /* + * Preset-specific defaults + */ + switch( preset ) + { + /* + * NSA Suite B + */ + case MBEDTLS_SSL_PRESET_SUITEB: + conf->min_major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; /* TLS 1.2 */ + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + + conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_suiteb; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + conf->sig_hashes = ssl_preset_suiteb_hashes; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + conf->tls13_sig_algs = ssl_preset_suiteb_sig_algs; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif + +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = ssl_preset_suiteb_groups; + break; + + /* + * Default + */ + default: + conf->min_major_ver = ( MBEDTLS_SSL_MIN_MAJOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION ) ? + MBEDTLS_SSL_MIN_MAJOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MAJOR_VERSION; + conf->min_minor_ver = ( MBEDTLS_SSL_MIN_MINOR_VERSION > + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION ) ? + MBEDTLS_SSL_MIN_MINOR_VERSION : + MBEDTLS_SSL_MIN_VALID_MINOR_VERSION; + conf->max_major_ver = MBEDTLS_SSL_MAX_MAJOR_VERSION; + conf->max_minor_ver = MBEDTLS_SSL_MAX_MINOR_VERSION; + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + conf->min_minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; +#endif + conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites(); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + conf->cert_profile = &mbedtls_x509_crt_profile_default; +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + conf->sig_hashes = ssl_preset_default_hashes; +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + conf->tls13_sig_algs = ssl_preset_default_sig_algs; +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED) + conf->curve_list = NULL; +#endif + conf->group_list = ssl_preset_default_groups; + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C) + conf->dhm_min_bitlen = 1024; +#endif + } + + return( 0 ); +} + +/* + * Free mbedtls_ssl_config + */ +void mbedtls_ssl_config_free( mbedtls_ssl_config *conf ) +{ +#if defined(MBEDTLS_DHM_C) + mbedtls_mpi_free( &conf->dhm_P ); + mbedtls_mpi_free( &conf->dhm_G ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + if( conf->psk_identity != NULL ) + { + mbedtls_platform_zeroize( conf->psk_identity, conf->psk_identity_len ); + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + ssl_key_cert_free( conf->key_cert ); +#endif + + mbedtls_platform_zeroize( conf, sizeof( mbedtls_ssl_config ) ); +} + +#if defined(MBEDTLS_PK_C) && \ + ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECDSA_C) ) +/* + * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX + */ +unsigned char mbedtls_ssl_sig_from_pk( mbedtls_pk_context *pk ) +{ +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_RSA ) ) + return( MBEDTLS_SSL_SIG_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECDSA ) ) + return( MBEDTLS_SSL_SIG_ECDSA ); +#endif + return( MBEDTLS_SSL_SIG_ANON ); +} + +unsigned char mbedtls_ssl_sig_from_pk_alg( mbedtls_pk_type_t type ) +{ + switch( type ) { + case MBEDTLS_PK_RSA: + return( MBEDTLS_SSL_SIG_RSA ); + case MBEDTLS_PK_ECDSA: + case MBEDTLS_PK_ECKEY: + return( MBEDTLS_SSL_SIG_ECDSA ); + default: + return( MBEDTLS_SSL_SIG_ANON ); + } +} + +mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig( unsigned char sig ) +{ + switch( sig ) + { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_SSL_SIG_RSA: + return( MBEDTLS_PK_RSA ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_SSL_SIG_ECDSA: + return( MBEDTLS_PK_ECDSA ); +#endif + default: + return( MBEDTLS_PK_NONE ); + } +} +#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_ECDSA_C ) */ + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* Find an entry in a signature-hash set matching a given hash algorithm. */ +mbedtls_md_type_t mbedtls_ssl_sig_hash_set_find( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + return( set->rsa ); + case MBEDTLS_PK_ECDSA: + return( set->ecdsa ); + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* Add a signature-hash-pair to a signature-hash set */ +void mbedtls_ssl_sig_hash_set_add( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_pk_type_t sig_alg, + mbedtls_md_type_t md_alg ) +{ + switch( sig_alg ) + { + case MBEDTLS_PK_RSA: + if( set->rsa == MBEDTLS_MD_NONE ) + set->rsa = md_alg; + break; + + case MBEDTLS_PK_ECDSA: + if( set->ecdsa == MBEDTLS_MD_NONE ) + set->ecdsa = md_alg; + break; + + default: + break; + } +} + +/* Allow exactly one hash algorithm for each signature. */ +void mbedtls_ssl_sig_hash_set_const_hash( mbedtls_ssl_sig_hash_set_t *set, + mbedtls_md_type_t md_alg ) +{ + set->rsa = md_alg; + set->ecdsa = md_alg; +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2) && + MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/* + * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX + */ +mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash( unsigned char hash ) +{ + switch( hash ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_SSL_HASH_MD5: + return( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_SSL_HASH_SHA1: + return( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_SSL_HASH_SHA224: + return( MBEDTLS_MD_SHA224 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + return( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_SSL_HASH_SHA384: + return( MBEDTLS_MD_SHA384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_SSL_HASH_SHA512: + return( MBEDTLS_MD_SHA512 ); +#endif + default: + return( MBEDTLS_MD_NONE ); + } +} + +/* + * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX + */ +unsigned char mbedtls_ssl_hash_from_md_alg( int md ) +{ + switch( md ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( MBEDTLS_SSL_HASH_MD5 ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( MBEDTLS_SSL_HASH_SHA1 ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( MBEDTLS_SSL_HASH_SHA224 ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( MBEDTLS_SSL_HASH_SHA256 ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( MBEDTLS_SSL_HASH_SHA384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( MBEDTLS_SSL_HASH_SHA512 ); +#endif + default: + return( MBEDTLS_SSL_HASH_NONE ); + } +} + +#if defined(MBEDTLS_ECP_C) +/* + * Check if a curve proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_curve( const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id ) +{ + const uint16_t *group_list = mbedtls_ssl_get_groups( ssl ); + + if( group_list == NULL ) + return( -1 ); + uint16_t tls_id = mbedtls_ecp_curve_info_from_grp_id(grp_id)->tls_id; + + for( ; *group_list != 0; group_list++ ) + { + if( *group_list == tls_id ) + return( 0 ); + } + + return( -1 ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Check if a hash proposed by the peer is in our list. + * Return 0 if we're willing to use it, -1 otherwise. + */ +int mbedtls_ssl_check_sig_hash( const mbedtls_ssl_context *ssl, + mbedtls_md_type_t md ) +{ + const int *cur; + + if( ssl->conf->sig_hashes == NULL ) + return( -1 ); + + for( cur = ssl->conf->sig_hashes; *cur != MBEDTLS_MD_NONE; cur++ ) + if( *cur == (int) md ) + return( 0 ); + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +int mbedtls_ssl_check_cert_usage( const mbedtls_x509_crt *cert, + const mbedtls_ssl_ciphersuite_t *ciphersuite, + int cert_endpoint, + uint32_t *flags ) +{ + int ret = 0; + int usage = 0; + const char *ext_oid; + size_t ext_len; + + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + /* Server part of the key exchange */ + switch( ciphersuite->key_exchange ) + { + case MBEDTLS_KEY_EXCHANGE_RSA: + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + break; + + case MBEDTLS_KEY_EXCHANGE_DHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA: + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + break; + + case MBEDTLS_KEY_EXCHANGE_ECDH_RSA: + case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA: + usage = MBEDTLS_X509_KU_KEY_AGREEMENT; + break; + + /* Don't use default: we want warnings when adding new values */ + case MBEDTLS_KEY_EXCHANGE_NONE: + case MBEDTLS_KEY_EXCHANGE_PSK: + case MBEDTLS_KEY_EXCHANGE_DHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + usage = 0; + } + } + else + { + /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */ + usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + } + + if( mbedtls_x509_crt_check_key_usage( cert, usage ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE; + ret = -1; + } + + if( cert_endpoint == MBEDTLS_SSL_IS_SERVER ) + { + ext_oid = MBEDTLS_OID_SERVER_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_SERVER_AUTH ); + } + else + { + ext_oid = MBEDTLS_OID_CLIENT_AUTH; + ext_len = MBEDTLS_OID_SIZE( MBEDTLS_OID_CLIENT_AUTH ); + } + + if( mbedtls_x509_crt_check_extended_key_usage( cert, ext_oid, ext_len ) != 0 ) + { + *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE; + ret = -1; + } + + return( ret ); +} +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +int mbedtls_ssl_set_calc_verify_md( mbedtls_ssl_context *ssl, int md ) +{ +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_3 ) + return( -1 ); + + switch( md ) + { +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_SSL_HASH_SHA384: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384; + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_SSL_HASH_SHA256: + ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256; + break; +#endif + default: + return( -1 ); + } + + return 0; +#else /* !MBEDTLS_SSL_PROTO_TLS1_2 */ + (void) ssl; + (void) md; + + return( -1 ); +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +} + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + psa_status_t status; + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) ); + + if( ( status = psa_hash_setup( &hash_operation, + hash_alg ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_setup", status ); + goto exit; + } + + if( ( status = psa_hash_update( &hash_operation, ssl->handshake->randbytes, + 64 ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status ); + goto exit; + } + + if( ( status = psa_hash_update( &hash_operation, + data, data_len ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_update", status ); + goto exit; + } + + if( ( status = psa_hash_finish( &hash_operation, hash, PSA_HASH_MAX_SIZE, + hashlen ) ) != PSA_SUCCESS ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "psa_hash_finish", status ); + goto exit; + } + +exit: + if( status != PSA_SUCCESS ) + { + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + switch( status ) + { + case PSA_ERROR_NOT_SUPPORTED: + return( MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE ); + case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */ + case PSA_ERROR_BUFFER_TOO_SMALL: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + case PSA_ERROR_INSUFFICIENT_MEMORY: + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + default: + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + } + } + return( 0 ); +} + +#else + +int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl, + unsigned char *hash, size_t *hashlen, + unsigned char *data, size_t data_len, + mbedtls_md_type_t md_alg ) +{ + int ret = 0; + mbedtls_md_context_t ctx; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + *hashlen = mbedtls_md_get_size( md_info ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) ); + + mbedtls_md_init( &ctx ); + + /* + * digitally-signed struct { + * opaque client_random[32]; + * opaque server_random[32]; + * ServerDHParams params; + * }; + */ + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_setup", ret ); + goto exit; + } + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_starts", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, ssl->handshake->randbytes, 64 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_update( &ctx, data, data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret ); + goto exit; + } + if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret ); + goto exit; + } + +exit: + mbedtls_md_free( &ctx ); + + if( ret != 0 ) + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR ); + + return( ret ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen ) +{ + ((void) ssl); + ((void) md); + ((void) dst); + ((void) dst_len); + *olen = 0; + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE); +} +#else /* MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(MBEDTLS_SHA384_C) +static int ssl_get_handshake_transcript_sha384( mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *olen ) +{ + int ret; + mbedtls_sha512_context sha512; + + if( dst_len < 48 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + mbedtls_sha512_init( &sha512 ); + mbedtls_sha512_clone( &sha512, &ssl->handshake->fin_sha512 ); + + if( ( ret = mbedtls_sha512_finish( &sha512, dst ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha512_finish", ret ); + goto exit; + } + + *olen = 48; + +exit: + + mbedtls_sha512_free( &sha512 ); + return( ret ); +} +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA256_C) +static int ssl_get_handshake_transcript_sha256( mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *olen ) +{ + int ret; + mbedtls_sha256_context sha256; + + if( dst_len < 32 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + mbedtls_sha256_init( &sha256 ); + mbedtls_sha256_clone( &sha256, &ssl->handshake->fin_sha256 ); + + if( ( ret = mbedtls_sha256_finish( &sha256, dst ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_sha256_finish", ret ); + goto exit; + } + + *olen = 32; + +exit: + + mbedtls_sha256_free( &sha256 ); + return( ret ); +} +#endif /* MBEDTLS_SHA256_C */ + +int mbedtls_ssl_get_handshake_transcript( mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md, + unsigned char *dst, + size_t dst_len, + size_t *olen ) +{ + switch( md ) + { + +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( ssl_get_handshake_transcript_sha384( ssl, dst, dst_len, olen ) ); +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( ssl_get_handshake_transcript_sha256( ssl, dst, dst_len, olen ) ); +#endif /* MBEDTLS_SHA256_C */ + + default: + break; + } + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} +#endif /* !MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_client.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_client.c new file mode 100644 index 00000000..31d7dafd --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_client.c @@ -0,0 +1,1793 @@ +/* + * TLS 1.3 client-side functions + * + * Copyright The Mbed TLS Contributors + * 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. + * + * This file is part of mbed TLS ( https://tls.mbed.org ) + */ + +#include "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_CLI_C) + +#include + +#include "mbedtls/debug.h" +#include "mbedtls/error.h" +#include "mbedtls/platform.h" + +#include "ssl_misc.h" +#include "ecdh_misc.h" +#include "ssl_tls13_keys.h" +#include "ssl_debug_helpers_generated.h" + +/* Write extensions */ + +/* + * ssl_tls13_write_supported_versions_ext(): + * + * struct { + * ProtocolVersion versions<2..254>; + * } SupportedVersions; + */ +static int ssl_tls13_write_supported_versions_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + + *out_len = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported versions extension" ) ); + + /* Check if we have space to write the extension: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - versions_length (1 byte ) + * - versions (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 7 ); + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS, p, 0 ); + + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( 3, p, 2 ); + p += 4; + + /* Length of versions */ + *p++ = 0x2; + + /* Write values of supported versions. + * + * They are defined by the configuration. + * + * Currently, only one version is advertised. + */ + mbedtls_ssl_write_version( ssl->conf->max_major_ver, + ssl->conf->max_minor_ver, + ssl->conf->transport, p ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "supported version: [%d:%d]", + ssl->conf->max_major_ver, + ssl->conf->max_minor_ver ) ); + + *out_len = 7; + + return( 0 ); +} + +static int ssl_tls13_parse_supported_versions_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2); + if( buf[0] != MBEDTLS_SSL_MAJOR_VERSION_3 || + buf[1] != MBEDTLS_SSL_MINOR_VERSION_4 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected version" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* + * Functions for writing supported_groups extension. + * + * Stucture of supported_groups: + * enum { + * secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019), + * x25519(0x001D), x448(0x001E), + * ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102), + * ffdhe6144(0x0103), ffdhe8192(0x0104), + * ffdhe_private_use(0x01FC..0x01FF), + * ecdhe_private_use(0xFE00..0xFEFF), + * (0xFFFF) + * } NamedGroup; + * struct { + * NamedGroup named_group_list<2..2^16-1>; + * } NamedGroupList; + */ +#if defined(MBEDTLS_ECDH_C) +/* + * In versions of TLS prior to TLS 1.3, this extension was named + * 'elliptic_curves' and only contained elliptic curve groups. + */ +static int ssl_tls13_write_named_group_list_ecdhe( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + + *out_len = 0; + + const uint16_t *group_list = mbedtls_ssl_get_groups( ssl ); + + if( group_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for ( ; *group_list != 0; group_list++ ) + { + const mbedtls_ecp_curve_info *curve_info; + curve_info = mbedtls_ecp_curve_info_from_tls_id( *group_list ); + if( curve_info == NULL ) + continue; + + if( !mbedtls_ssl_tls13_named_group_is_ecdhe( *group_list ) ) + continue; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2); + MBEDTLS_PUT_UINT16_BE( *group_list, p, 0 ); + p += 2; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "NamedGroup: %s ( %x )", + curve_info->name, *group_list ) ); + } + + *out_len = p - buf; + + return( 0 ); +} +#else +static int ssl_tls13_write_named_group_list_ecdhe( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + ((void) ssl); + ((void) buf); + ((void) end); + *out_len = 0; + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_ECDH_C */ + +static int ssl_tls13_write_named_group_list_dhe( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + ((void) ssl); + ((void) buf); + ((void) end); + *out_len = 0; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "write_named_group_dhe is not implemented" ) ); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_tls13_write_supported_groups_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf ; + unsigned char *named_group_list; /* Start of named_group_list */ + size_t named_group_list_len; /* Length of named_group_list */ + size_t output_len = 0; + int ret_ecdhe, ret_dhe; + + *out_len = 0; + + if( !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding supported_groups extension" ) ); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - named_group_list_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + p += 6; + + named_group_list = p; + ret_ecdhe = ssl_tls13_write_named_group_list_ecdhe( ssl, p, end, &output_len ); + if( ret_ecdhe != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_named_group_list_ecdhe", ret_ecdhe ); + } + p += output_len; + + ret_dhe = ssl_tls13_write_named_group_list_dhe( ssl, p, end, &output_len ); + if( ret_dhe != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_tls13_write_named_group_list_dhe", ret_dhe ); + } + p += output_len; + + /* Both ECDHE and DHE failed. */ + if( ret_ecdhe != 0 && ret_dhe != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Both ECDHE and DHE groups are fail. " ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Length of named_group_list*/ + named_group_list_len = p - named_group_list; + if( named_group_list_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No group available." ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SUPPORTED_GROUPS, buf, 0 ); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( named_group_list_len + 2, buf, 2 ); + /* Write length of named_group_list */ + MBEDTLS_PUT_UINT16_BE( named_group_list_len, buf, 4 ); + + MBEDTLS_SSL_DEBUG_BUF( 3, "Supported groups extension", buf + 4, named_group_list_len + 2 ); + + *out_len = p - buf; + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SUPPORTED_GROUPS; + + return( 0 ); +} + +/* + * Functions for writing key_share extension. + */ +#if defined(MBEDTLS_ECDH_C) +static int ssl_tls13_generate_and_write_ecdh_key_exchange( + mbedtls_ssl_context *ssl, + uint16_t named_group, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_ecp_curve_info *curve_info = + mbedtls_ecp_curve_info_from_tls_id( named_group ); + + if( curve_info == NULL ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "offer curve %s", curve_info->name ) ); + + if( ( ret = mbedtls_ecdh_setup_no_everest( &ssl->handshake->ecdh_ctx, + curve_info->grp_id ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_setup_no_everest", ret ); + return( ret ); + } + + ret = mbedtls_ecdh_tls13_make_params( &ssl->handshake->ecdh_ctx, out_len, + buf, end - buf, + ssl->conf->f_rng, ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_tls13_make_params", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_Q ); + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C */ + +static int ssl_tls13_get_default_group_id( mbedtls_ssl_context *ssl, + uint16_t *group_id ) +{ + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + +#if defined(MBEDTLS_ECDH_C) + const uint16_t *group_list = mbedtls_ssl_get_groups( ssl ); + /* Pick first available ECDHE group compatible with TLS 1.3 */ + if( group_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for ( ; *group_list != 0; group_list++ ) + { + const mbedtls_ecp_curve_info *curve_info; + curve_info = mbedtls_ecp_curve_info_from_tls_id( *group_list ); + if( curve_info != NULL && + mbedtls_ssl_tls13_named_group_is_ecdhe( *group_list ) ) + { + *group_id = *group_list; + return( 0 ); + } + } +#else + ((void) ssl); + ((void) group_id); +#endif /* MBEDTLS_ECDH_C */ + + /* + * Add DHE named groups here. + * Pick first available DHE group compatible with TLS 1.3 + */ + + return( ret ); +} + +/* + * ssl_tls13_write_key_share_ext + * + * Structure of key_share extension in ClientHello: + * + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + * struct { + * KeyShareEntry client_shares<0..2^16-1>; + * } KeyShareClientHello; + */ +static int ssl_tls13_write_key_share_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + unsigned char *client_shares; /* Start of client_shares */ + size_t client_shares_len; /* Length of client_shares */ + uint16_t group_id; + int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + + *out_len = 0; + + if( !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + return( 0 ); + + /* Check if we have space for header and length fields: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - client_shares_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + p += 6; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello: adding key share extension" ) ); + + /* HRR could already have requested something else. */ + group_id = ssl->handshake->offered_group_id; + if( !mbedtls_ssl_tls13_named_group_is_ecdhe( group_id ) && + !mbedtls_ssl_tls13_named_group_is_dhe( group_id ) ) + { + MBEDTLS_SSL_PROC_CHK( ssl_tls13_get_default_group_id( ssl, + &group_id ) ); + } + + /* + * Dispatch to type-specific key generation function. + * + * So far, we're only supporting ECDHE. With the introduction + * of PQC KEMs, we'll want to have multiple branches, one per + * type of KEM, and dispatch to the corresponding crypto. And + * only one key share entry is allowed. + */ + client_shares = p; +#if defined(MBEDTLS_ECDH_C) + if( mbedtls_ssl_tls13_named_group_is_ecdhe( group_id ) ) + { + /* Pointer to group */ + unsigned char *group = p; + /* Length of key_exchange */ + size_t key_exchange_len; + + /* Check there is space for header of KeyShareEntry + * - group (2 bytes) + * - key_exchange_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + p += 4; + ret = ssl_tls13_generate_and_write_ecdh_key_exchange( ssl, group_id, + p, end, + &key_exchange_len ); + p += key_exchange_len; + if( ret != 0 ) + return( ret ); + + /* Write group */ + MBEDTLS_PUT_UINT16_BE( group_id, group, 0 ); + /* Write key_exchange_length */ + MBEDTLS_PUT_UINT16_BE( key_exchange_len, group, 2 ); + } + else +#endif /* MBEDTLS_ECDH_C */ + if( 0 /* other KEMs? */ ) + { + /* Do something */ + } + else + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* Length of client_shares */ + client_shares_len = p - client_shares; + if( client_shares_len == 0) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No key share defined." ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_KEY_SHARE, buf, 0 ); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( client_shares_len + 2, buf, 2 ); + /* Write client_shares_length */ + MBEDTLS_PUT_UINT16_BE( client_shares_len, buf, 4 ); + + /* Update offered_group_id field */ + ssl->handshake->offered_group_id = group_id; + + /* Output the total length of key_share extension. */ + *out_len = p - buf; + + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, key_share extension", buf, *out_len ); + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECDH_C) + +static int ssl_tls13_check_ecdh_params( const mbedtls_ssl_context *ssl ) +{ + const mbedtls_ecp_curve_info *curve_info; + mbedtls_ecp_group_id grp_id; +#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) + grp_id = ssl->handshake->ecdh_ctx.grp.id; +#else + grp_id = ssl->handshake->ecdh_ctx.grp_id; +#endif + + curve_info = mbedtls_ecp_curve_info_from_grp_id( grp_id ); + if( curve_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "ECDH curve: %s", curve_info->name ) ); + + if( mbedtls_ssl_check_curve( ssl, grp_id ) != 0 ) + return( -1 ); + + MBEDTLS_SSL_DEBUG_ECDH( 3, &ssl->handshake->ecdh_ctx, + MBEDTLS_DEBUG_ECDH_QP ); + + return( 0 ); +} + +static int ssl_tls13_read_public_ecdhe_share( mbedtls_ssl_context *ssl, + const unsigned char *buf, + size_t buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_ecdh_tls13_read_public( &ssl->handshake->ecdh_ctx, + buf, buf_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_tls13_read_public" ), ret ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + if( ssl_tls13_check_ecdh_params( ssl ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ssl_tls13_check_ecdh_params() failed!" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C */ + +/* + * ssl_tls13_parse_key_share_ext() + * Parse key_share extension in Server Hello + * + * struct { + * KeyShareEntry server_share; + * } KeyShareServerHello; + * struct { + * NamedGroup group; + * opaque key_exchange<1..2^16-1>; + * } KeyShareEntry; + */ +static int ssl_tls13_parse_key_share_ext( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t group, offered_group; + + /* ... + * NamedGroup group; (2 bytes) + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + group = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + /* Check that the chosen group matches the one we offered. */ + offered_group = ssl->handshake->offered_group_id; + if( offered_group != group ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "Invalid server key share, our group %u, their group %u", + (unsigned) offered_group, (unsigned) group ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + +#if defined(MBEDTLS_ECDH_C) + if( mbedtls_ssl_tls13_named_group_is_ecdhe( group ) ) + { + /* Complete ECDHE key agreement */ + ret = ssl_tls13_read_public_ecdhe_share( ssl, p, end - p ); + if( ret != 0 ) + return( ret ); + } + else +#endif /* MBEDTLS_ECDH_C */ + if( 0 /* other KEMs? */ ) + { + /* Do something */ + } + else + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_KEY_SHARE; + return( ret ); +} + +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/* Write cipher_suites + * CipherSuite cipher_suites<2..2^16-2>; + */ +static int ssl_tls13_write_client_hello_cipher_suites( + mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + const int *ciphersuite_list; + unsigned char *cipher_suites; /* Start of the cipher_suites list */ + size_t cipher_suites_len; + + *out_len = 0 ; + + /* + * Ciphersuite list + * + * This is a list of the symmetric cipher options supported by + * the client, specifically the record protection algorithm + * ( including secret key length ) and a hash to be used with + * HKDF, in descending order of client preference. + */ + ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check there is space for the cipher suite list length (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + /* Write cipher_suites */ + cipher_suites = p; + for ( size_t i = 0; ciphersuite_list[i] != 0; i++ ) + { + int cipher_suite = ciphersuite_list[i]; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite ); + if( ciphersuite_info == NULL ) + continue; + if( !( MBEDTLS_SSL_MINOR_VERSION_4 >= ciphersuite_info->min_minor_ver && + MBEDTLS_SSL_MINOR_VERSION_4 <= ciphersuite_info->max_minor_ver ) ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x, %s", + (unsigned int) cipher_suite, + ciphersuite_info->name ) ); + + /* Check there is space for the cipher suite identifier (2 bytes). */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( cipher_suite, p, 0 ); + p += 2; + } + + /* Write the cipher_suites length in number of bytes */ + cipher_suites_len = p - cipher_suites; + MBEDTLS_PUT_UINT16_BE( cipher_suites_len, buf, 0 ); + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites", + cipher_suites_len/2 ) ); + + /* Output the total length of cipher_suites field. */ + *out_len = p - buf; + + return( 0 ); +} + +/* + * Structure of ClientHello message: + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * Random random; + * opaque legacy_session_id<0..32>; + * CipherSuite cipher_suites<2..2^16-2>; + * opaque legacy_compression_methods<1..2^8-1>; + * Extension extensions<8..2^16-1>; + * } ClientHello; + */ +static int ssl_tls13_write_client_hello_body( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + + int ret; + unsigned char *p_extensions_len; /* Pointer to extensions length */ + size_t output_len; /* Length of buffer used by function */ + size_t extensions_len; /* Length of the list of extensions*/ + + /* Buffer management */ + unsigned char *p = buf; + + *out_len = 0; + + /* No validation needed here. It has been done by ssl_conf_check() */ + ssl->major_ver = ssl->conf->min_major_ver; + ssl->minor_ver = ssl->conf->min_minor_ver; + + /* + * Write legacy_version + * ProtocolVersion legacy_version = 0x0303; // TLS v1.2 + * + * For TLS 1.3 we use the legacy version number {0x03, 0x03} + * instead of the true version number. + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( 0x0303, p, 0 ); + p += 2; + + /* Write the random bytes ( random ).*/ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); + memcpy( p, ssl->handshake->randbytes, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello, random bytes", + p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN ); + p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN; + + /* + * Write legacy_session_id + * + * Versions of TLS before TLS 1.3 supported a "session resumption" feature + * which has been merged with pre-shared keys in this version. A client + * which has a cached session ID set by a pre-TLS 1.3 server SHOULD set + * this field to that value. In compatibility mode, this field MUST be + * non-empty, so a client not offering a pre-TLS 1.3 session MUST generate + * a new 32-byte value. This value need not be random but SHOULD be + * unpredictable to avoid implementations fixating on a specific value + * ( also known as ossification ). Otherwise, it MUST be set as a zero-length + * vector ( i.e., a zero-valued single byte length field ). + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + MBEDTLS_SSL_CHK_BUF_PTR( p, end, ssl->session_negotiate->id_len + 1 ); + *p++ = (unsigned char)ssl->session_negotiate->id_len; + memcpy( p, ssl->session_negotiate->id, ssl->session_negotiate->id_len ); + p += ssl->session_negotiate->id_len; + + MBEDTLS_SSL_DEBUG_BUF( 3, "session id", ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); +#else + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + *p++ = 0; /* session id length set to zero */ +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + /* Write cipher_suites */ + ret = ssl_tls13_write_client_hello_cipher_suites( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + + /* Write legacy_compression_methods + * + * For every TLS 1.3 ClientHello, this vector MUST contain exactly + * one byte set to zero, which corresponds to the 'null' compression + * method in prior versions of TLS. + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + + /* Write extensions */ + + /* Keeping track of the included extensions */ + ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE; + + /* First write extensions, then the total length */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p_extensions_len = p; + p += 2; + + /* Write supported_versions extension + * + * Supported Versions Extension is mandatory with TLS 1.3. + */ + ret = ssl_tls13_write_supported_versions_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + /* Write supported_groups extension + * + * It is REQUIRED for ECDHE cipher_suites. + */ + ret = ssl_tls13_write_supported_groups_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + + /* Write key_share extension + * + * We need to send the key shares under three conditions: + * 1) A certificate-based ciphersuite is being offered. In this case + * supported_groups and supported_signature extensions have been + * successfully added. + * 2) A PSK-based ciphersuite with ECDHE is offered. In this case the + * psk_key_exchange_modes has been added as the last extension. + * 3) Or, in case all ciphers are supported ( which includes #1 and #2 + * from above ) + */ + ret = ssl_tls13_write_key_share_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + + /* Write signature_algorithms extension + * + * It is REQUIRED for certificate authenticated cipher_suites. + */ + ret = mbedtls_ssl_tls13_write_sig_alg_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; + +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + /* Write server name extension */ + ret = mbedtls_ssl_write_hostname_ext( ssl, p, end, &output_len ); + if( ret != 0 ) + return( ret ); + p += output_len; +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + + /* Add more extensions here */ + + /* Write the length of the list of extensions. */ + extensions_len = p - p_extensions_len - 2; + MBEDTLS_PUT_UINT16_BE( extensions_len, p_extensions_len, 0 ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, total extension length: %" MBEDTLS_PRINTF_SIZET , + extensions_len ) ); + MBEDTLS_SSL_DEBUG_BUF( 3, "client hello extensions", p_extensions_len, extensions_len ); + + *out_len = p - buf; + return( 0 ); +} + +static int ssl_tls13_finalize_client_hello( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_HELLO ); + return( 0 ); +} + +static int ssl_tls13_prepare_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret; + + if( ssl->conf->f_rng == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "no RNG provided" ) ); + return( MBEDTLS_ERR_SSL_NO_RNG ); + } + + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->handshake->randbytes, + MBEDTLS_CLIENT_HELLO_RANDOM_LEN ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + /* + * Create a session identifier for the purpose of middlebox compatibility + * only if one has not been created already. + */ + if( ssl->session_negotiate->id_len == 0 ) + { + /* Creating a session id with 32 byte length */ + if( ( ret = ssl->conf->f_rng( ssl->conf->p_rng, + ssl->session_negotiate->id, 32 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "creating session id failed", ret ); + return( ret ); + } + ssl->session_negotiate->id_len = 32; + } +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + return( 0 ); +} + +/* + * Write ClientHello handshake message. + * Handler for MBEDTLS_SSL_CLIENT_HELLO + */ +static int ssl_tls13_write_client_hello( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write client hello" ) ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_prepare_client_hello( ssl ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_start_handshake_msg( + ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, + &buf, &buf_len ) ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_client_hello_body( ssl, buf, + buf + buf_len, + &msg_len ) ); + + mbedtls_ssl_tls13_add_hs_hdr_to_checksum( ssl, + MBEDTLS_SSL_HS_CLIENT_HELLO, + msg_len ); + ssl->handshake->update_checksum( ssl, buf, msg_len ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_client_hello( ssl ) ); + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_finish_handshake_msg( ssl, + buf_len, + msg_len ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write client hello" ) ); + return ret; +} + +/* + * Functions for parsing and processing Server Hello + */ +/* Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO_COORDINATE_HELLO or + * - SSL_SERVER_HELLO_COORDINATE_HRR + * to indicate which message is expected and to be parsed next. */ +#define SSL_SERVER_HELLO_COORDINATE_HELLO 0 +#define SSL_SERVER_HELLO_COORDINATE_HRR 1 +static int ssl_server_hello_is_hrr( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + static const unsigned char magic_hrr_string[MBEDTLS_SERVER_HELLO_RANDOM_LEN] = + { 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33 ,0x9C }; + + /* Check whether this message is a HelloRetryRequest ( HRR ) message. + * + * Server Hello and HRR are only distinguished by Random set to the + * special value of the SHA-256 of "HelloRetryRequest". + * + * struct { + * ProtocolVersion legacy_version = 0x0303; + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + * + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( buf, end, 2 + sizeof( magic_hrr_string ) ); + + if( memcmp( buf + 2, magic_hrr_string, sizeof( magic_hrr_string ) ) == 0 ) + { + return( SSL_SERVER_HELLO_COORDINATE_HRR ); + } + + return( SSL_SERVER_HELLO_COORDINATE_HELLO ); +} + +/* Fetch and preprocess + * Returns a negative value on failure, and otherwise + * - SSL_SERVER_HELLO_COORDINATE_HELLO or + * - SSL_SERVER_HELLO_COORDINATE_HRR + */ +static int ssl_tls13_server_hello_coordinate( mbedtls_ssl_context *ssl, + unsigned char **buf, + size_t *buf_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_read_record( ssl, 0 ) ); + + if( ( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) || + ( ssl->in_msg[0] != MBEDTLS_SSL_HS_SERVER_HELLO ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "unexpected message" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + } + + *buf = ssl->in_msg + 4; + *buf_len = ssl->in_hslen - 4; + + ret = ssl_server_hello_is_hrr( ssl, *buf, *buf + *buf_len ); + switch( ret ) + { + case SSL_SERVER_HELLO_COORDINATE_HELLO: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received ServerHello message" ) ); + break; + case SSL_SERVER_HELLO_COORDINATE_HRR: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "received HelloRetryRequest message" ) ); + break; + } + +cleanup: + + return( ret ); +} + +static int ssl_tls13_check_server_hello_session_id_echo( mbedtls_ssl_context *ssl, + const unsigned char **buf, + const unsigned char *end ) +{ + const unsigned char *p = *buf; + size_t legacy_session_id_echo_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 ); + legacy_session_id_echo_len = *p++ ; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, legacy_session_id_echo_len ); + + /* legacy_session_id_echo */ + if( ssl->session_negotiate->id_len != legacy_session_id_echo_len || + memcmp( ssl->session_negotiate->id, p , legacy_session_id_echo_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_BUF( 3, "Expected Session ID", + ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); + MBEDTLS_SSL_DEBUG_BUF( 3, "Received Session ID", p, + legacy_session_id_echo_len ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER); + + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + p += legacy_session_id_echo_len; + *buf = p; + + MBEDTLS_SSL_DEBUG_BUF( 3, "Session ID", ssl->session_negotiate->id, + ssl->session_negotiate->id_len ); + return( 0 ); +} + +static int ssl_tls13_cipher_suite_is_offered( mbedtls_ssl_context *ssl, + int cipher_suite ) +{ + const int *ciphersuite_list = ssl->conf->ciphersuite_list; + + /* Check whether we have offered this ciphersuite */ + for ( size_t i = 0; ciphersuite_list[i] != 0; i++ ) + { + if( ciphersuite_list[i] == cipher_suite ) + { + return( 1 ); + } + } + return( 0 ); +} + +/* Parse ServerHello message and configure context + * + * struct { + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * Random random; + * opaque legacy_session_id_echo<0..32>; + * CipherSuite cipher_suite; + * uint8 legacy_compression_method = 0; + * Extension extensions<6..2^16-1>; + * } ServerHello; + */ +static int ssl_tls13_parse_server_hello( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + size_t extensions_len; + const unsigned char *extensions_end; + uint16_t cipher_suite; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + + /* + * Check there is space for minimal fields + * + * - legacy_version ( 2 bytes) + * - random (MBEDTLS_SERVER_HELLO_RANDOM_LEN bytes) + * - legacy_session_id_echo ( 1 byte ), minimum size + * - cipher_suite ( 2 bytes) + * - legacy_compression_method ( 1 byte ) + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, MBEDTLS_SERVER_HELLO_RANDOM_LEN + 6 ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "server hello", p, end - p ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, version", p, 2 ); + + /* ... + * ProtocolVersion legacy_version = 0x0303; // TLS 1.2 + * ... + * with ProtocolVersion defined as: + * uint16 ProtocolVersion; + */ + if( !( p[0] == MBEDTLS_SSL_MAJOR_VERSION_3 && + p[1] == MBEDTLS_SSL_MINOR_VERSION_3 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unsupported version of TLS." ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION, + MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + return( MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION ); + } + p += 2; + + /* ... + * Random random; + * ... + * with Random defined as: + * opaque Random[MBEDTLS_SERVER_HELLO_RANDOM_LEN]; + */ + memcpy( &ssl->handshake->randbytes[MBEDTLS_CLIENT_HELLO_RANDOM_LEN], p, + MBEDTLS_SERVER_HELLO_RANDOM_LEN ); + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello, random bytes", + p, MBEDTLS_SERVER_HELLO_RANDOM_LEN ); + p += MBEDTLS_SERVER_HELLO_RANDOM_LEN; + + /* ... + * opaque legacy_session_id_echo<0..32>; + * ... + */ + if( ssl_tls13_check_server_hello_session_id_echo( ssl, &p, end ) != 0 ) + { + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + /* ... + * CipherSuite cipher_suite; + * ... + * with CipherSuite defined as: + * uint8 CipherSuite[2]; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + cipher_suite = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + + /* + * Check whether this ciphersuite is supported and offered. + * Via the force_ciphersuite version we may have instructed the client + * to use a different ciphersuite. + */ + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( cipher_suite ); + if( ciphersuite_info == NULL || + ssl_tls13_cipher_suite_is_offered( ssl, cipher_suite ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite(%04x) not found or not offered", + cipher_suite ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + + + /* Configure ciphersuites */ + mbedtls_ssl_optimize_checksum( ssl, ciphersuite_info ); + + ssl->handshake->ciphersuite_info = ciphersuite_info; + ssl->session_negotiate->ciphersuite = cipher_suite; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: ( %04x ) - %s", + cipher_suite, ciphersuite_info->name ) ); + +#if defined(MBEDTLS_HAVE_TIME) + ssl->session_negotiate->start = time( NULL ); +#endif /* MBEDTLS_HAVE_TIME */ + + /* ... + * uint8 legacy_compression_method = 0; + * ... + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 1 ); + if( p[0] != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad legacy compression method" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER, + MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + return( MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER ); + } + p++; + + /* ... + * Extension extensions<6..2^16-1>; + * ... + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + /* Check extensions do not go beyond the buffer of data. */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len ); + extensions_end = p + extensions_len; + + MBEDTLS_SSL_DEBUG_BUF( 3, "server hello extensions", p, extensions_len ); + + while( p < extensions_end ) + { + unsigned int extension_type; + size_t extension_data_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 ); + extension_type = MBEDTLS_GET_UINT16_BE( p, 0 ); + extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 ); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len ); + + switch( extension_type ) + { + case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS: + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "found supported_versions extension" ) ); + + ret = ssl_tls13_parse_supported_versions_ext( ssl, + p, + p + extension_data_len ); + if( ret != 0 ) + return( ret ); + break; + + case MBEDTLS_TLS_EXT_PRE_SHARED_KEY: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found pre_shared_key extension." ) ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "pre_shared_key:Not supported yet" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_TLS_EXT_KEY_SHARE: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found key_shares extension" ) ); + if( ( ret = ssl_tls13_parse_key_share_ext( ssl, + p, p + extension_data_len ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "ssl_tls13_parse_key_share_ext", + ret ); + return( ret ); + } + break; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + default: + MBEDTLS_SSL_DEBUG_MSG( + 3, + ( "unknown extension found: %u ( ignoring )", + extension_type ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + return( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + p += extension_data_len; + } + + return( 0 ); +} + +static int ssl_tls13_finalize_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_handshake = NULL; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Determine the key exchange mode: + * 1) If both the pre_shared_key and key_share extensions were received + * then the key exchange mode is PSK with EPHEMERAL. + * 2) If only the pre_shared_key extension was received then the key + * exchange mode is PSK-only. + * 3) If only the key_share extension was received then the key + * exchange mode is EPHEMERAL-only. + */ + switch( handshake->extensions_present & + ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ) ) + { + /* Only the pre_shared_key extension was received */ + case MBEDTLS_SSL_EXT_PRE_SHARED_KEY: + handshake->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK; + break; + + /* Only the key_share extension was received */ + case MBEDTLS_SSL_EXT_KEY_SHARE: + handshake->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL; + break; + + /* Both the pre_shared_key and key_share extensions were received */ + case ( MBEDTLS_SSL_EXT_PRE_SHARED_KEY | MBEDTLS_SSL_EXT_KEY_SHARE ): + handshake->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL; + break; + + /* Neither pre_shared_key nor key_share extension was received */ + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Unknown key exchange." ) ); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + goto cleanup; + } + + /* Start the TLS 1.3 key schedule: Set the PSK and derive early secret. + * + * TODO: We don't have to do this in case we offered 0-RTT and the + * server accepted it. In this case, we could skip generating + * the early secret. */ + ret = mbedtls_ssl_tls13_key_schedule_stage_early( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_key_schedule_stage_early_data", + ret ); + goto cleanup; + } + + /* Compute handshake secret */ + ret = mbedtls_ssl_tls13_key_schedule_stage_handshake( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_master_secret", ret ); + goto cleanup; + } + + /* Next evolution in key schedule: Establish handshake secret and + * key material. */ + ret = mbedtls_ssl_tls13_generate_handshake_keys( ssl, &traffic_keys ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_generate_handshake_keys", + ret ); + goto cleanup; + } + + transform_handshake = mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) ); + if( transform_handshake == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( transform_handshake, + ssl->conf->endpoint, + ssl->session_negotiate->ciphersuite, + &traffic_keys, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret ); + goto cleanup; + } + + handshake->transform_handshake = transform_handshake; + mbedtls_ssl_set_inbound_transform( ssl, transform_handshake ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to handshake keys for inbound traffic" ) ); + ssl->session_in = ssl->session_negotiate; + + /* + * State machine update + */ + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS ); + +cleanup: + + mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) ); + if( ret != 0 ) + { + mbedtls_free( transform_handshake ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + return( ret ); +} + +/* + * Wait and parse ServerHello handshake message. + * Handler for MBEDTLS_SSL_SERVER_HELLO + */ +static int ssl_tls13_process_server_hello( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> %s", __func__ ) ); + + /* Coordination step + * - Fetch record + * - Make sure it's either a ServerHello or a HRR. + * - Switch processing routine in case of HRR + */ + ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; + ssl->handshake->extensions_present = MBEDTLS_SSL_EXT_NONE; + + ret = ssl_tls13_server_hello_coordinate( ssl, &buf, &buf_len ); + /* Parsing step + * We know what message to expect by now and call + * the respective parsing function. + */ + if( ret == SSL_SERVER_HELLO_COORDINATE_HELLO ) + { + MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_server_hello( ssl, buf, + buf + buf_len ) ); + + mbedtls_ssl_tls13_add_hs_msg_to_checksum( ssl, + MBEDTLS_SSL_HS_SERVER_HELLO, + buf, buf_len ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_server_hello( ssl ) ); + } + else if( ret == SSL_SERVER_HELLO_COORDINATE_HRR ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "HRR not supported" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE , + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + } + +cleanup: + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= %s", __func__ ) ); + return( ret ); +} + +/* + * + * EncryptedExtensions message + * + * The EncryptedExtensions message contains any extensions which + * should be protected, i.e., any which are not needed to establish + * the cryptographic context. + */ + +/* + * Overview + */ + +/* Main entry point; orchestrates the other functions */ +static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl ); + +static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ); +static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl ); + +/* + * Handler for MBEDTLS_SSL_ENCRYPTED_EXTENSIONS + */ +static int ssl_tls13_process_encrypted_extensions( mbedtls_ssl_context *ssl ) +{ + int ret; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse encrypted extensions" ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl, + MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, + &buf, &buf_len ) ); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK( + ssl_tls13_parse_encrypted_extensions( ssl, buf, buf + buf_len ) ); + + mbedtls_ssl_tls13_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, buf_len ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_encrypted_extensions( ssl ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse encrypted extensions" ) ); + return( ret ); + +} + +/* Parse EncryptedExtensions message + * struct { + * Extension extensions<0..2^16-1>; + * } EncryptedExtensions; + */ +static int ssl_tls13_parse_encrypted_extensions( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + int ret = 0; + size_t extensions_len; + const unsigned char *p = buf; + const unsigned char *extensions_end; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + MBEDTLS_SSL_DEBUG_BUF( 3, "encrypted extensions", p, extensions_len ); + extensions_end = p + extensions_len; + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, extensions_len ); + + while( p < extensions_end ) + { + unsigned int extension_type; + size_t extension_data_len; + + /* + * struct { + * ExtensionType extension_type; (2 bytes) + * opaque extension_data<0..2^16-1>; + * } Extension; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, 4 ); + extension_type = MBEDTLS_GET_UINT16_BE( p, 0 ); + extension_data_len = MBEDTLS_GET_UINT16_BE( p, 2 ); + p += 4; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, extensions_end, extension_data_len ); + + /* The client MUST check EncryptedExtensions for the + * presence of any forbidden extensions and if any are found MUST abort + * the handshake with an "unsupported_extension" alert. + */ + switch( extension_type ) + { + + case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS: + MBEDTLS_SSL_DEBUG_MSG( 3, ( "found extensions supported groups" ) ); + break; + + default: + MBEDTLS_SSL_DEBUG_MSG( + 3, ( "unsupported extension found: %u ", extension_type) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT, + MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + return ( MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION ); + } + + p += extension_data_len; + } + + /* Check that we consumed all the message. */ + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "EncryptedExtension lengths misaligned" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + return( ret ); +} + +static int ssl_tls13_postprocess_encrypted_extensions( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + if( mbedtls_ssl_tls13_some_psk_enabled( ssl ) ) + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED ); + else + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_REQUEST ); +#else + ((void) ssl); + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED ); +#endif + return( 0 ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_REQUEST + */ +static int ssl_tls13_process_certificate_request( mbedtls_ssl_context *ssl ) +{ + int ret = mbedtls_ssl_read_record( ssl, 0 ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE ) && + ( ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE_REQUEST ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "CertificateRequest not supported" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + + ssl->keep_current_message = 1; + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_CERTIFICATE ); + + return( 0 ); +} + +/* + * Handler for MBEDTLS_SSL_SERVER_CERTIFICATE + */ +static int ssl_tls13_process_server_certificate( mbedtls_ssl_context *ssl ) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_certificate( ssl ); + if( ret != 0 ) + return( ret ); + + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CERTIFICATE_VERIFY ); + return( 0 ); +} + +/* + * Handler for MBEDTLS_SSL_CERTIFICATE_VERIFY + */ +static int ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl ) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_certificate_verify( ssl ); + if( ret != 0 ) + return( ret ); + + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_SERVER_FINISHED ); + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +/* + * Handler for MBEDTLS_SSL_SERVER_FINISHED + */ +static int ssl_tls13_process_server_finished( mbedtls_ssl_context *ssl ) +{ + int ret; + + ret = mbedtls_ssl_tls13_process_finished_message( ssl ); + if( ret != 0 ) + return( ret ); + +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + mbedtls_ssl_handshake_set_state( + ssl, + MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED ); +#else + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED ); +#endif + + return( 0 ); +} + +/* + * Handler for MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) +static int ssl_tls13_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret; + + ret = mbedtls_ssl_tls13_write_change_cipher_spec( ssl ); + if( ret != 0 ) + return( ret ); + + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_CLIENT_FINISHED ); + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +/* + * Handler for MBEDTLS_SSL_CLIENT_FINISHED + */ +static int ssl_tls13_write_client_finished( mbedtls_ssl_context *ssl ) +{ + int ret; + + mbedtls_ssl_set_outbound_transform( ssl, ssl->handshake->transform_handshake ); + + ret = mbedtls_ssl_tls13_write_finished_message( ssl ); + if( ret != 0 ) + return( ret ); + + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_FLUSH_BUFFERS ); + return( 0 ); +} + +/* + * Handler for MBEDTLS_SSL_FLUSH_BUFFERS + */ +static int ssl_tls13_flush_buffers( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake: done" ) ); + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP ); + return( 0 ); +} + +/* + * Handler for MBEDTLS_SSL_HANDSHAKE_WRAPUP + */ +static int ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to application keys for inbound traffic" ) ); + mbedtls_ssl_set_inbound_transform ( ssl, ssl->transform_application ); + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Switch to application keys for outbound traffic" ) ); + mbedtls_ssl_set_outbound_transform( ssl, ssl->transform_application ); + + mbedtls_ssl_tls13_handshake_wrapup( ssl ); + + mbedtls_ssl_handshake_set_state( ssl, MBEDTLS_SSL_HANDSHAKE_OVER ); + return( 0 ); +} + +int mbedtls_ssl_tls13_handshake_client_step( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "tls13 client state: %s(%d)", + mbedtls_ssl_states_str( ssl->state ), + ssl->state ) ); + + switch( ssl->state ) + { + /* + * ssl->state is initialized as HELLO_REQUEST. It is the same + * as CLIENT_HELLO state. + */ + case MBEDTLS_SSL_HELLO_REQUEST: + case MBEDTLS_SSL_CLIENT_HELLO: + ret = ssl_tls13_write_client_hello( ssl ); + break; + + case MBEDTLS_SSL_SERVER_HELLO: + ret = ssl_tls13_process_server_hello( ssl ); + break; + + case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS: + ret = ssl_tls13_process_encrypted_extensions( ssl ); + break; + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + case MBEDTLS_SSL_CERTIFICATE_REQUEST: + ret = ssl_tls13_process_certificate_request( ssl ); + break; + + case MBEDTLS_SSL_SERVER_CERTIFICATE: + ret = ssl_tls13_process_server_certificate( ssl ); + break; + + case MBEDTLS_SSL_CERTIFICATE_VERIFY: + ret = ssl_tls13_process_certificate_verify( ssl ); + break; +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + + case MBEDTLS_SSL_SERVER_FINISHED: + ret = ssl_tls13_process_server_finished( ssl ); + break; + + case MBEDTLS_SSL_CLIENT_FINISHED: + ret = ssl_tls13_write_client_finished( ssl ); + break; + + case MBEDTLS_SSL_FLUSH_BUFFERS: + ret = ssl_tls13_flush_buffers( ssl ); + break; + + case MBEDTLS_SSL_HANDSHAKE_WRAPUP: + ret = ssl_tls13_handshake_wrapup( ssl ); + break; + + /* + * Injection of dummy-CCS's for middlebox compatibility + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED: + ret = ssl_tls13_write_change_cipher_spec( ssl ); + break; +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid state %d", ssl->state ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + return( ret ); +} + +#endif /* MBEDTLS_SSL_CLI_C */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_generic.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_generic.c new file mode 100644 index 00000000..1260740e --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_generic.c @@ -0,0 +1,1201 @@ +/* + * TLS 1.3 functionality shared between client and server + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include + +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform.h" +#include "mbedtls/constant_time.h" +#include + +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" + +int mbedtls_ssl_tls13_fetch_handshake_msg( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len ) +{ + int ret; + + if( ( ret = mbedtls_ssl_read_record( ssl, 0 ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + goto cleanup; + } + + if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE || + ssl->in_msg[0] != hs_type ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Receive unexpected handshake message." ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE, + MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); + ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE; + goto cleanup; + } + + /* + * Jump handshake header (4 bytes, see Section 4 of RFC 8446). + * ... + * HandshakeType msg_type; + * uint24 length; + * ... + */ + *buf = ssl->in_msg + 4; + *buf_len = ssl->in_hslen - 4; + +cleanup: + + return( ret ); +} + +int mbedtls_ssl_tls13_start_handshake_msg( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char **buf, + size_t *buf_len ) +{ + /* + * Reserve 4 bytes for hanshake header. ( Section 4,RFC 8446 ) + * ... + * HandshakeType msg_type; + * uint24 length; + * ... + */ + *buf = ssl->out_msg + 4; + *buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4; + + ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE; + ssl->out_msg[0] = hs_type; + + return( 0 ); +} + +int mbedtls_ssl_tls13_finish_handshake_msg( mbedtls_ssl_context *ssl, + size_t buf_len, + size_t msg_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msg_with_header_len; + ((void) buf_len); + + /* Add reserved 4 bytes for handshake header */ + msg_with_header_len = msg_len + 4; + ssl->out_msglen = msg_with_header_len; + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_write_handshake_msg_ext( ssl, 0 ) ); + +cleanup: + return( ret ); +} + +void mbedtls_ssl_tls13_add_hs_msg_to_checksum( mbedtls_ssl_context *ssl, + unsigned hs_type, + unsigned char const *msg, + size_t msg_len ) +{ + mbedtls_ssl_tls13_add_hs_hdr_to_checksum( ssl, hs_type, msg_len ); + ssl->handshake->update_checksum( ssl, msg, msg_len ); +} + +void mbedtls_ssl_tls13_add_hs_hdr_to_checksum( mbedtls_ssl_context *ssl, + unsigned hs_type, + size_t total_hs_len ) +{ + unsigned char hs_hdr[4]; + + /* Build HS header for checksum update. */ + hs_hdr[0] = MBEDTLS_BYTE_0( hs_type ); + hs_hdr[1] = MBEDTLS_BYTE_2( total_hs_len ); + hs_hdr[2] = MBEDTLS_BYTE_1( total_hs_len ); + hs_hdr[3] = MBEDTLS_BYTE_0( total_hs_len ); + + ssl->handshake->update_checksum( ssl, hs_hdr, sizeof( hs_hdr ) ); +} + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + +/* + * mbedtls_ssl_tls13_write_sig_alg_ext( ) + * + * enum { + * .... + * ecdsa_secp256r1_sha256( 0x0403 ), + * ecdsa_secp384r1_sha384( 0x0503 ), + * ecdsa_secp521r1_sha512( 0x0603 ), + * .... + * } SignatureScheme; + * + * struct { + * SignatureScheme supported_signature_algorithms<2..2^16-2>; + * } SignatureSchemeList; + * + * Only if we handle at least one key exchange that needs signatures. + */ +int mbedtls_ssl_tls13_write_sig_alg_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + unsigned char *p = buf; + unsigned char *supported_sig_alg; /* Start of supported_signature_algorithms */ + size_t supported_sig_alg_len = 0; /* Length of supported_signature_algorithms */ + + *out_len = 0; + + /* Skip the extension on the client if all allowed key exchanges + * are PSK-based. */ +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT && + !mbedtls_ssl_conf_tls13_some_ephemeral_enabled( ssl ) ) + { + return( 0 ); + } +#endif /* MBEDTLS_SSL_CLI_C */ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "adding signature_algorithms extension" ) ); + + /* Check if we have space for header and length field: + * - extension_type (2 bytes) + * - extension_data_length (2 bytes) + * - supported_signature_algorithms_length (2 bytes) + */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + p += 6; + + /* + * Write supported_signature_algorithms + */ + supported_sig_alg = p; + for( const uint16_t *sig_alg = ssl->conf->tls13_sig_algs; + *sig_alg != MBEDTLS_TLS1_3_SIG_NONE; sig_alg++ ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + MBEDTLS_PUT_UINT16_BE( *sig_alg, p, 0 ); + p += 2; + MBEDTLS_SSL_DEBUG_MSG( 3, ( "signature scheme [%x]", *sig_alg ) ); + } + + /* Length of supported_signature_algorithms */ + supported_sig_alg_len = p - supported_sig_alg; + if( supported_sig_alg_len == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "No signature algorithms defined." ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + /* Write extension_type */ + MBEDTLS_PUT_UINT16_BE( MBEDTLS_TLS_EXT_SIG_ALG, buf, 0 ); + /* Write extension_data_length */ + MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len + 2, buf, 2 ); + /* Write length of supported_signature_algorithms */ + MBEDTLS_PUT_UINT16_BE( supported_sig_alg_len, buf, 4 ); + + /* Output the total length of signature algorithms extension. */ + *out_len = p - buf; + + ssl->handshake->extensions_present |= MBEDTLS_SSL_EXT_SIG_ALG; + return( 0 ); +} + +/* + * STATE HANDLING: Read CertificateVerify + */ +/* Macro to express the maximum length of the verify structure. + * + * The structure is computed per TLS 1.3 specification as: + * - 64 bytes of octet 32, + * - 33 bytes for the context string + * (which is either "TLS 1.3, client CertificateVerify" + * or "TLS 1.3, server CertificateVerify"), + * - 1 byte for the octet 0x0, which serves as a separator, + * - 32 or 48 bytes for the Transcript-Hash(Handshake Context, Certificate) + * (depending on the size of the transcript_hash) + * + * This results in a total size of + * - 130 bytes for a SHA256-based transcript hash, or + * (64 + 33 + 1 + 32 bytes) + * - 146 bytes for a SHA384-based transcript hash. + * (64 + 33 + 1 + 48 bytes) + * + */ +#define SSL_VERIFY_STRUCT_MAX_SIZE ( 64 + \ + 33 + \ + 1 + \ + MBEDTLS_TLS1_3_MD_MAX_SIZE \ + ) + +/* + * The ssl_tls13_create_verify_structure() creates the verify structure. + * As input, it requires the transcript hash. + * + * The caller has to ensure that the buffer has size at least + * SSL_VERIFY_STRUCT_MAX_SIZE bytes. + */ +static void ssl_tls13_create_verify_structure( const unsigned char *transcript_hash, + size_t transcript_hash_len, + unsigned char *verify_buffer, + size_t *verify_buffer_len, + int from ) +{ + size_t idx; + + /* RFC 8446, Section 4.4.3: + * + * The digital signature [in the CertificateVerify message] is then + * computed over the concatenation of: + * - A string that consists of octet 32 (0x20) repeated 64 times + * - The context string + * - A single 0 byte which serves as the separator + * - The content to be signed + */ + memset( verify_buffer, 0x20, 64 ); + idx = 64; + + if( from == MBEDTLS_SSL_IS_CLIENT ) + { + memcpy( verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( client_cv ) ); + idx += MBEDTLS_SSL_TLS1_3_LBL_LEN( client_cv ); + } + else + { /* from == MBEDTLS_SSL_IS_SERVER */ + memcpy( verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( server_cv ) ); + idx += MBEDTLS_SSL_TLS1_3_LBL_LEN( server_cv ); + } + + verify_buffer[idx++] = 0x0; + + memcpy( verify_buffer + idx, transcript_hash, transcript_hash_len ); + idx += transcript_hash_len; + + *verify_buffer_len = idx; +} + +static int ssl_tls13_sig_alg_is_offered( const mbedtls_ssl_context *ssl, + uint16_t sig_alg ) +{ + const uint16_t *tls13_sig_alg = ssl->conf->tls13_sig_algs; + + for( ; *tls13_sig_alg != MBEDTLS_TLS1_3_SIG_NONE ; tls13_sig_alg++ ) + { + if( *tls13_sig_alg == sig_alg ) + return( 1 ); + } + return( 0 ); +} + +static int ssl_tls13_parse_certificate_verify( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end, + const unsigned char *verify_buffer, + size_t verify_buffer_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned char *p = buf; + uint16_t algorithm; + size_t signature_len; + mbedtls_pk_type_t sig_alg; + mbedtls_md_type_t md_alg; + unsigned char verify_hash[MBEDTLS_MD_MAX_SIZE]; + size_t verify_hash_len; + + void const *options = NULL; +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_pk_rsassa_pss_options rsassa_pss_options; +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + /* + * struct { + * SignatureScheme algorithm; + * opaque signature<0..2^16-1>; + * } CertificateVerify; + */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + algorithm = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + + /* RFC 8446 section 4.4.3 + * + * If the CertificateVerify message is sent by a server, the signature algorithm + * MUST be one offered in the client's "signature_algorithms" extension unless + * no valid certificate chain can be produced without unsupported algorithms + * + * RFC 8446 section 4.4.2.2 + * + * If the client cannot construct an acceptable chain using the provided + * certificates and decides to abort the handshake, then it MUST abort the handshake + * with an appropriate certificate-related alert (by default, "unsupported_certificate"). + * + * Check if algorithm is an offered signature algorithm. + */ + if( ! ssl_tls13_sig_alg_is_offered( ssl, algorithm ) ) + { + /* algorithm not in offered signature algorithms list */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Received signature algorithm(%04x) is not " + "offered.", + ( unsigned int ) algorithm ) ); + goto error; + } + + /* We currently only support ECDSA-based signatures */ + switch( algorithm ) + { + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256: + md_alg = MBEDTLS_MD_SHA256; + sig_alg = MBEDTLS_PK_ECDSA; + break; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384: + md_alg = MBEDTLS_MD_SHA384; + sig_alg = MBEDTLS_PK_ECDSA; + break; + case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512: + md_alg = MBEDTLS_MD_SHA512; + sig_alg = MBEDTLS_PK_ECDSA; + break; +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256: + MBEDTLS_SSL_DEBUG_MSG( 4, ( "Certificate Verify: using RSA PSS" ) ); + md_alg = MBEDTLS_MD_SHA256; + sig_alg = MBEDTLS_PK_RSASSA_PSS; + break; +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + default: + MBEDTLS_SSL_DEBUG_MSG( 1, ( "Certificate Verify: Unknown signature algorithm." ) ); + goto error; + } + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate Verify: Signature algorithm ( %04x )", + ( unsigned int ) algorithm ) ); + + /* + * Check the certificate's key type matches the signature alg + */ + if( !mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, sig_alg ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "signature algorithm doesn't match cert key" ) ); + goto error; + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 2 ); + signature_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, signature_len ); + + /* Hash verify buffer with indicated hash function */ + switch( md_alg ) + { +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + verify_hash_len = 32; + ret = mbedtls_sha256( verify_buffer, verify_buffer_len, verify_hash, 0 ); + break; +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + verify_hash_len = 48; + ret = mbedtls_sha512( verify_buffer, verify_buffer_len, verify_hash, 1 ); + break; +#endif /* MBEDTLS_SHA384_C */ + +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + verify_hash_len = 64; + ret = mbedtls_sha512( verify_buffer, verify_buffer_len, verify_hash, 0 ); + break; +#endif /* MBEDTLS_SHA512_C */ + + default: + ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE; + break; + } + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "hash computation error", ret ); + goto error; + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "verify hash", verify_hash, verify_hash_len ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( sig_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_md_info_t* md_info; + rsassa_pss_options.mgf1_hash_id = md_alg; + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + { + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + rsassa_pss_options.expected_salt_len = mbedtls_md_get_size( md_info ); + options = (const void*) &rsassa_pss_options; + } +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + if( ( ret = mbedtls_pk_verify_ext( sig_alg, options, + &ssl->session_negotiate->peer_cert->pk, + md_alg, verify_hash, verify_hash_len, + p, signature_len ) ) == 0 ) + { + return( 0 ); + } + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify_ext", ret ); + +error: + /* RFC 8446 section 4.4.3 + * + * If the verification fails, the receiver MUST terminate the handshake + * with a "decrypt_error" alert. + */ + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + +} +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ + +int mbedtls_ssl_tls13_process_certificate_verify( mbedtls_ssl_context *ssl ) +{ + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char verify_buffer[SSL_VERIFY_STRUCT_MAX_SIZE]; + size_t verify_buffer_len; + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) ); + + MBEDTLS_SSL_PROC_CHK( + mbedtls_ssl_tls13_fetch_handshake_msg( ssl, + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len ) ); + + /* Need to calculate the hash of the transcript first + * before reading the message since otherwise it gets + * included in the transcript + */ + ret = mbedtls_ssl_get_handshake_transcript( ssl, + ssl->handshake->ciphersuite_info->mac, + transcript, sizeof( transcript ), + &transcript_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 3, "handshake hash", transcript, transcript_len ); + + /* Create verify structure */ + ssl_tls13_create_verify_structure( transcript, + transcript_len, + verify_buffer, + &verify_buffer_len, + ( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) ? + MBEDTLS_SSL_IS_SERVER : + MBEDTLS_SSL_IS_CLIENT ); + + /* Process the message contents */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_certificate_verify( ssl, buf, + buf + buf_len, verify_buffer, verify_buffer_len ) ); + + mbedtls_ssl_tls13_add_hs_msg_to_checksum( ssl, + MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf, buf_len ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate verify" ) ); + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_process_certificate_verify", ret ); + return( ret ); +#else + ((void) ssl); + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */ +} + +/* + * + * STATE HANDLING: Incoming Certificate, client-side only currently. + * + */ + +/* + * Implementation + */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +/* + * Structure of Certificate message: + * + * enum { + * X509(0), + * RawPublicKey(2), + * (255) + * } CertificateType; + * + * struct { + * select (certificate_type) { + * case RawPublicKey: + * * From RFC 7250 ASN.1_subjectPublicKeyInfo * + * opaque ASN1_subjectPublicKeyInfo<1..2^24-1>; + * case X509: + * opaque cert_data<1..2^24-1>; + * }; + * Extension extensions<0..2^16-1>; + * } CertificateEntry; + * + * struct { + * opaque certificate_request_context<0..2^8-1>; + * CertificateEntry certificate_list<0..2^24-1>; + * } Certificate; + * + */ + +/* Parse certificate chain send by the server. */ +static int ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t certificate_request_context_len = 0; + size_t certificate_list_len = 0; + const unsigned char *p = buf; + const unsigned char *certificate_list_end; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, end, 4 ); + certificate_request_context_len = p[0]; + certificate_list_len = MBEDTLS_GET_UINT24_BE( p, 1 ); + p += 4; + + /* In theory, the certificate list can be up to 2^24 Bytes, but we don't + * support anything beyond 2^16 = 64K. + */ + if( ( certificate_request_context_len != 0 ) || + ( certificate_list_len >= 0x10000 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + /* In case we tried to reuse a session but it failed */ + if( ssl->session_negotiate->peer_cert != NULL ) + { + mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert ); + mbedtls_free( ssl->session_negotiate->peer_cert ); + } + + if( ( ssl->session_negotiate->peer_cert = + mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc( %" MBEDTLS_PRINTF_SIZET " bytes ) failed", + sizeof( mbedtls_x509_crt ) ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_SSL_ALLOC_FAILED ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert ); + + certificate_list_end = p + certificate_list_len; + while( p < certificate_list_end ) + { + size_t cert_data_len, extensions_len; + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, 3 ); + cert_data_len = MBEDTLS_GET_UINT24_BE( p, 0 ); + p += 3; + + /* In theory, the CRT can be up to 2^24 Bytes, but we don't support + * anything beyond 2^16 = 64K. Otherwise as in the TLS 1.2 code, + * check that we have a minimum of 128 bytes of data, this is not + * clear why we need that though. + */ + if( ( cert_data_len < 128 ) || ( cert_data_len >= 0x10000 ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad Certificate message" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, cert_data_len ); + ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert, + p, cert_data_len ); + + switch( ret ) + { + case 0: /*ok*/ + break; + case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND: + /* Ignore certificate with an unknown algorithm: maybe a + prior certificate was already trusted. */ + break; + + case MBEDTLS_ERR_X509_ALLOC_FAILED: + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR, + MBEDTLS_ERR_X509_ALLOC_FAILED ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + + case MBEDTLS_ERR_X509_UNKNOWN_VERSION: + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, + MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + + default: + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_BAD_CERT, + ret ); + MBEDTLS_SSL_DEBUG_RET( 1, " mbedtls_x509_crt_parse_der", ret ); + return( ret ); + } + + p += cert_data_len; + + /* Certificate extensions length */ + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, 2 ); + extensions_len = MBEDTLS_GET_UINT16_BE( p, 0 ); + p += 2; + MBEDTLS_SSL_CHK_BUF_READ_PTR( p, certificate_list_end, extensions_len ); + p += extensions_len; + } + + /* Check that all the message is consumed. */ + if( p != end ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad Certificate message" ) ); + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, \ + MBEDTLS_ERR_SSL_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert ); + + return( ret ); +} +#else +static int ssl_tls13_parse_certificate( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + ((void) ssl); + ((void) buf); + ((void) end); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) +/* Validate certificate chain sent by the server. */ +static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = 0; + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + uint32_t verify_result = 0; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + /* + * Main check: verify certificate + */ + ret = mbedtls_x509_crt_verify_with_profile( + ssl->session_negotiate->peer_cert, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); + } + + /* + * Secondary checks: always done, but change 'ret' only if it was 0 + */ + +#if defined(MBEDTLS_ECP_C) + { + const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk; + + /* If certificate uses an EC key, make sure the curve is OK */ + if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) && + mbedtls_ssl_check_curve( ssl, mbedtls_pk_ec( *pk )->grp.id ) != 0 ) + { + verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY; + + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate ( EC key curve )" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + } +#endif /* MBEDTLS_ECP_C */ + + if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert, + ssl->handshake->ciphersuite_info, + !ssl->conf->endpoint, + &verify_result ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate ( usage extensions )" ) ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE; + } + + + if( ca_chain == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); + ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; + } + + if( ret != 0 ) + { + /* The certificate may have been rejected for several reasons. + Pick one and send the corresponding alert. Which alert to send + may be a subject of debate in some cases. */ + if( verify_result & MBEDTLS_X509_BADCERT_OTHER ) + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret ); + else if( verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH ) + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret ); + else if( verify_result & ( MBEDTLS_X509_BADCERT_KEY_USAGE | + MBEDTLS_X509_BADCERT_EXT_KEY_USAGE | + MBEDTLS_X509_BADCERT_NS_CERT_TYPE | + MBEDTLS_X509_BADCERT_BAD_PK | + MBEDTLS_X509_BADCERT_BAD_KEY ) ) + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret ); + else if( verify_result & MBEDTLS_X509_BADCERT_EXPIRED ) + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret ); + else if( verify_result & MBEDTLS_X509_BADCERT_REVOKED ) + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret ); + else if( verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED ) + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret ); + else + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret ); + } + +#if defined(MBEDTLS_DEBUG_C) + if( verify_result != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "! Certificate verification flags %08x", + (unsigned int) verify_result ) ); + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) ); + } +#endif /* MBEDTLS_DEBUG_C */ + + ssl->session_negotiate->verify_result = verify_result; + return( ret ); +} +#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +static int ssl_tls13_validate_certificate( mbedtls_ssl_context *ssl ) +{ + ((void) ssl); + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + +int mbedtls_ssl_tls13_process_certificate( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( + ssl, MBEDTLS_SSL_HS_CERTIFICATE, + &buf, &buf_len ) ); + + /* Parse the certificate chain sent by the peer. */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_certificate( ssl, buf, buf + buf_len ) ); + /* Validate the certificate chain and set the verification results. */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_validate_certificate( ssl ) ); + + mbedtls_ssl_tls13_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_CERTIFICATE, + buf, buf_len ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); +#else + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; +#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */ + return( ret ); +} + +/* + * + * STATE HANDLING: Incoming Finished message. + */ +/* + * Implementation + */ + +static int ssl_tls13_preprocess_finished_message( mbedtls_ssl_context *ssl ) +{ + int ret; + + ret = mbedtls_ssl_tls13_calculate_verify_data( ssl, + ssl->handshake->state_local.finished_in.digest, + sizeof( ssl->handshake->state_local.finished_in.digest ), + &ssl->handshake->state_local.finished_in.digest_len, + ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ? + MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_calculate_verify_data", ret ); + return( ret ); + } + + return( 0 ); +} + +static int ssl_tls13_parse_finished_message( mbedtls_ssl_context *ssl, + const unsigned char *buf, + const unsigned char *end ) +{ + /* + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + */ + const unsigned char *expected_verify_data = + ssl->handshake->state_local.finished_in.digest; + size_t expected_verify_data_len = + ssl->handshake->state_local.finished_in.digest_len; + /* Structural validation */ + if( (size_t)( end - buf ) != expected_verify_data_len ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR, + MBEDTLS_ERR_SSL_DECODE_ERROR ); + return( MBEDTLS_ERR_SSL_DECODE_ERROR ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "verify_data (self-computed):", + expected_verify_data, + expected_verify_data_len ); + MBEDTLS_SSL_DEBUG_BUF( 4, "verify_data (received message):", buf, + expected_verify_data_len ); + + /* Semantic validation */ + if( mbedtls_ct_memcmp( buf, + expected_verify_data, + expected_verify_data_len ) != 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad finished message" ) ); + + MBEDTLS_SSL_PEND_FATAL_ALERT( MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + return( MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + return( 0 ); +} + +#if defined(MBEDTLS_SSL_CLI_C) +static int ssl_tls13_postprocess_server_finished_message( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_key_set traffic_keys; + mbedtls_ssl_transform *transform_application = NULL; + + ret = mbedtls_ssl_tls13_key_schedule_stage_application( ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_tls13_key_schedule_stage_application", ret ); + goto cleanup; + } + + ret = mbedtls_ssl_tls13_generate_application_keys( ssl, &traffic_keys ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_tls13_generate_application_keys", ret ); + goto cleanup; + } + + transform_application = + mbedtls_calloc( 1, sizeof( mbedtls_ssl_transform ) ); + if( transform_application == NULL ) + { + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto cleanup; + } + + ret = mbedtls_ssl_tls13_populate_transform( + transform_application, + ssl->conf->endpoint, + ssl->session_negotiate->ciphersuite, + &traffic_keys, + ssl ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_populate_transform", ret ); + goto cleanup; + } + + ssl->transform_application = transform_application; + +cleanup: + + mbedtls_platform_zeroize( &traffic_keys, sizeof( traffic_keys ) ); + if( ret != 0 ) + { + mbedtls_free( transform_application ); + MBEDTLS_SSL_PEND_FATAL_ALERT( + MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE, + MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE ); + } + return( ret ); +} +#endif /* MBEDTLS_SSL_CLI_C */ + +static int ssl_tls13_postprocess_finished_message( mbedtls_ssl_context *ssl ) +{ + +#if defined(MBEDTLS_SSL_CLI_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + return( ssl_tls13_postprocess_server_finished_message( ssl ) ); + } +#else + ((void) ssl); +#endif /* MBEDTLS_SSL_CLI_C */ + + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); +} + +int mbedtls_ssl_tls13_process_finished_message( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse finished message" ) ); + + /* Preprocessing step: Compute handshake digest */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_preprocess_finished_message( ssl ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_fetch_handshake_msg( ssl, + MBEDTLS_SSL_HS_FINISHED, + &buf, &buf_len ) ); + MBEDTLS_SSL_PROC_CHK( ssl_tls13_parse_finished_message( ssl, buf, buf + buf_len ) ); + mbedtls_ssl_tls13_add_hs_msg_to_checksum( + ssl, MBEDTLS_SSL_HS_FINISHED, buf, buf_len ); + MBEDTLS_SSL_PROC_CHK( ssl_tls13_postprocess_finished_message( ssl ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse finished message" ) ); + return( ret ); +} + +/* + * + * STATE HANDLING: Write and send Finished message. + * + */ +/* + * Implement + */ + +static int ssl_tls13_prepare_finished_message( mbedtls_ssl_context *ssl ) +{ + int ret; + + /* Compute transcript of handshake up to now. */ + ret = mbedtls_ssl_tls13_calculate_verify_data( ssl, + ssl->handshake->state_local.finished_out.digest, + sizeof( ssl->handshake->state_local.finished_out.digest ), + &ssl->handshake->state_local.finished_out.digest_len, + ssl->conf->endpoint ); + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "calculate_verify_data failed", ret ); + return( ret ); + } + + return( 0 ); +} + +static int ssl_tls13_finalize_finished_message( mbedtls_ssl_context *ssl ) +{ + // TODO: Add back resumption keys calculation after MVP. + ((void) ssl); + + return( 0 ); +} + +static int ssl_tls13_write_finished_message_body( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *out_len ) +{ + size_t verify_data_len = ssl->handshake->state_local.finished_out.digest_len; + /* + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, verify_data_len ); + + memcpy( buf, ssl->handshake->state_local.finished_out.digest, + verify_data_len ); + + *out_len = verify_data_len; + return( 0 ); +} + +/* Main entry point: orchestrates the other functions */ +int mbedtls_ssl_tls13_write_finished_message( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *buf; + size_t buf_len, msg_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write finished message" ) ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_prepare_finished_message( ssl ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_start_handshake_msg( ssl, + MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len ) ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_finished_message_body( + ssl, buf, buf + buf_len, &msg_len ) ); + + mbedtls_ssl_tls13_add_hs_msg_to_checksum( ssl, MBEDTLS_SSL_HS_FINISHED, + buf, msg_len ); + + MBEDTLS_SSL_PROC_CHK( ssl_tls13_finalize_finished_message( ssl ) ); + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_tls13_finish_handshake_msg( ssl, + buf_len, msg_len ) ); + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_flush_output( ssl ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write finished message" ) ); + return( ret ); +} + +void mbedtls_ssl_tls13_handshake_wrapup( mbedtls_ssl_context *ssl ) +{ + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "=> handshake wrapup" ) ); + + /* + * Free the previous session and switch to the current one. + */ + if( ssl->session ) + { + mbedtls_ssl_session_free( ssl->session ); + mbedtls_free( ssl->session ); + } + ssl->session = ssl->session_negotiate; + ssl->session_negotiate = NULL; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "<= handshake wrapup" ) ); +} + +/* + * + * STATE HANDLING: Write ChangeCipherSpec + * + */ +#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE) + +static int ssl_tls13_write_change_cipher_spec_body( mbedtls_ssl_context *ssl, + unsigned char *buf, + unsigned char *end, + size_t *olen ) +{ + ((void) ssl); + + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 1 ); + buf[0] = 1; + *olen = 1; + + return( 0 ); +} + +int mbedtls_ssl_tls13_write_change_cipher_spec( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write change cipher spec" ) ); + + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_flush_output( ssl ) ); + + /* Write CCS message */ + MBEDTLS_SSL_PROC_CHK( ssl_tls13_write_change_cipher_spec_body( + ssl, ssl->out_msg, + ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN, + &ssl->out_msglen ) ); + + ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC; + + /* Dispatch message */ + MBEDTLS_SSL_PROC_CHK( mbedtls_ssl_write_record( ssl, 1 ) ); + +cleanup: + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write change cipher spec" ) ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ + +#endif /* MBEDTLS_SSL_TLS_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.c new file mode 100644 index 00000000..99eb8a4c --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.c @@ -0,0 +1,1251 @@ +/* + * TLS 1.3 key schedule + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#include +#include + +#include "mbedtls/hkdf.h" +#include "mbedtls/debug.h" +#include "mbedtls/error.h" + +#include "ssl_misc.h" +#include "ssl_tls13_keys.h" + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + .name = string, + +struct mbedtls_ssl_tls13_labels_struct const mbedtls_ssl_tls13_labels = +{ + /* This seems to work in C, despite the string literal being one + * character too long due to the 0-termination. */ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; + +#undef MBEDTLS_SSL_TLS1_3_LABEL + +/* + * This function creates a HkdfLabel structure used in the TLS 1.3 key schedule. + * + * The HkdfLabel is specified in RFC 8446 as follows: + * + * struct HkdfLabel { + * uint16 length; // Length of expanded key material + * opaque label<7..255>; // Always prefixed by "tls13 " + * opaque context<0..255>; // Usually a communication transcript hash + * }; + * + * Parameters: + * - desired_length: Length of expanded key material + * Even though the standard allows expansion to up to + * 2**16 Bytes, TLS 1.3 never uses expansion to more than + * 255 Bytes, so we require `desired_length` to be at most + * 255. This allows us to save a few Bytes of code by + * hardcoding the writing of the high bytes. + * - (label, label_len): label + label length, without "tls13 " prefix + * The label length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN + * It is the caller's responsibility to ensure this. + * All (label, label length) pairs used in TLS 1.3 + * can be obtained via MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(). + * - (ctx, ctx_len): context + context length + * The context length MUST be less than or equal to + * MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN + * It is the caller's responsibility to ensure this. + * - dst: Target buffer for HkdfLabel structure, + * This MUST be a writable buffer of size + * at least SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN Bytes. + * - dst_len: Pointer at which to store the actual length of + * the HkdfLabel structure on success. + */ + +static const char tls13_label_prefix[6] = "tls13 "; + +#define SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( label_len, context_len ) \ + ( 2 /* expansion length */ \ + + 1 /* label length */ \ + + label_len \ + + 1 /* context length */ \ + + context_len ) + +#define SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN \ + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( \ + sizeof(tls13_label_prefix) + \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN, \ + MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + +static void ssl_tls13_hkdf_encode_label( + size_t desired_length, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *dst, size_t *dst_len ) +{ + size_t total_label_len = + sizeof(tls13_label_prefix) + label_len; + size_t total_hkdf_lbl_len = + SSL_TLS1_3_KEY_SCHEDULE_HKDF_LABEL_LEN( total_label_len, ctx_len ); + + unsigned char *p = dst; + + /* Add the size of the expanded key material. + * We're hardcoding the high byte to 0 here assuming that we never use + * TLS 1.3 HKDF key expansion to more than 255 Bytes. */ +#if MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN > 255 +#error "The implementation of ssl_tls13_hkdf_encode_label() is not fit for the \ + value of MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN" +#endif + + *p++ = 0; + *p++ = MBEDTLS_BYTE_0( desired_length ); + + /* Add label incl. prefix */ + *p++ = MBEDTLS_BYTE_0( total_label_len ); + memcpy( p, tls13_label_prefix, sizeof(tls13_label_prefix) ); + p += sizeof(tls13_label_prefix); + memcpy( p, label, label_len ); + p += label_len; + + /* Add context value */ + *p++ = MBEDTLS_BYTE_0( ctx_len ); + if( ctx_len != 0 ) + memcpy( p, ctx, ctx_len ); + + /* Return total length to the caller. */ + *dst_len = total_hkdf_lbl_len; +} + +int mbedtls_ssl_tls13_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *buf, size_t buf_len ) +{ + const mbedtls_md_info_t *md_info; + unsigned char hkdf_label[ SSL_TLS1_3_KEY_SCHEDULE_MAX_HKDF_LABEL_LEN ]; + size_t hkdf_label_len; + + if( label_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN ) + { + /* Should never happen since this is an internal + * function, and we know statically which labels + * are allowed. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( ctx_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + if( buf_len > MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN ) + { + /* Should not happen, as above. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + md_info = mbedtls_md_info_from_type( hash_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_tls13_hkdf_encode_label( buf_len, + label, label_len, + ctx, ctx_len, + hkdf_label, + &hkdf_label_len ); + + return( mbedtls_hkdf_expand( md_info, + secret, secret_len, + hkdf_label, hkdf_label_len, + buf, buf_len ) ); +} + +/* + * The traffic keying material is generated from the following inputs: + * + * - One secret value per sender. + * - A purpose value indicating the specific value being generated + * - The desired lengths of key and IV. + * + * The expansion itself is based on HKDF: + * + * [sender]_write_key = HKDF-Expand-Label( Secret, "key", "", key_length ) + * [sender]_write_iv = HKDF-Expand-Label( Secret, "iv" , "", iv_length ) + * + * [sender] denotes the sending side and the Secret value is provided + * by the function caller. Note that we generate server and client side + * keys in a single function call. + */ +int mbedtls_ssl_tls13_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, size_t secret_len, + size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ) +{ + int ret = 0; + + ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, + client_secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->client_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, + server_secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( key ), + NULL, 0, + keys->server_write_key, key_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, + client_secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->client_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, + server_secret, secret_len, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( iv ), + NULL, 0, + keys->server_write_iv, iv_len ); + if( ret != 0 ) + return( ret ); + + keys->key_len = key_len; + keys->iv_len = iv_len; + + return( 0 ); +} + +int mbedtls_ssl_tls13_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + int ctx_hashed, + unsigned char *dstbuf, size_t dstbuf_len ) +{ + int ret; + unsigned char hashed_context[ MBEDTLS_MD_MAX_SIZE ]; + + const mbedtls_md_info_t *md_info; + md_info = mbedtls_md_info_from_type( hash_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( ctx_hashed == MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED ) + { + ret = mbedtls_md( md_info, ctx, ctx_len, hashed_context ); + if( ret != 0 ) + return( ret ); + ctx_len = mbedtls_md_get_size( md_info ); + } + else + { + if( ctx_len > sizeof(hashed_context) ) + { + /* This should never happen since this function is internal + * and the code sets `ctx_hashed` correctly. + * Let's double-check nonetheless to not run at the risk + * of getting a stack overflow. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( hashed_context, ctx, ctx_len ); + } + + return( mbedtls_ssl_tls13_hkdf_expand_label( hash_alg, + secret, secret_len, + label, label_len, + hashed_context, ctx_len, + dstbuf, dstbuf_len ) ); +} + +int mbedtls_ssl_tls13_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ) +{ + int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + size_t hlen, ilen; + unsigned char tmp_secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 }; + unsigned char tmp_input [ MBEDTLS_ECP_MAX_BYTES ] = { 0 }; + + const mbedtls_md_info_t *md_info; + md_info = mbedtls_md_info_from_type( hash_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + /* For non-initial runs, call Derive-Secret( ., "derived", "") + * on the old secret. */ + if( secret_old != NULL ) + { + ret = mbedtls_ssl_tls13_derive_secret( + hash_alg, + secret_old, hlen, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ), + NULL, 0, /* context */ + MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + tmp_secret, hlen ); + if( ret != 0 ) + goto cleanup; + } + + if( input != NULL ) + { + memcpy( tmp_input, input, input_len ); + ilen = input_len; + } + else + { + ilen = hlen; + } + + /* HKDF-Extract takes a salt and input key material. + * The salt is the old secret, and the input key material + * is the input secret (PSK / ECDHE). */ + ret = mbedtls_hkdf_extract( md_info, + tmp_secret, hlen, + tmp_input, ilen, + secret_new ); + if( ret != 0 ) + goto cleanup; + + ret = 0; + + cleanup: + + mbedtls_platform_zeroize( tmp_secret, sizeof(tmp_secret) ); + mbedtls_platform_zeroize( tmp_input, sizeof(tmp_input) ); + return( ret ); +} + +int mbedtls_ssl_tls13_derive_early_secrets( + mbedtls_md_type_t md_type, + unsigned char const *early_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_early_secrets *derived ) +{ + int ret; + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if( md_info == 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * +-----> Derive-Secret(., "c e traffic", ClientHello) + * | = client_early_traffic_secret + * | + * +-----> Derive-Secret(., "e exp master", ClientHello) + * | = early_exporter_master_secret + * v + */ + + /* Create client_early_traffic_secret */ + ret = mbedtls_ssl_tls13_derive_secret( md_type, + early_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( c_e_traffic ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_early_traffic_secret, + md_size ); + if( ret != 0 ) + return( ret ); + + /* Create early exporter */ + ret = mbedtls_ssl_tls13_derive_secret( md_type, + early_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( e_exp_master ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->early_exporter_master_secret, + md_size ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_ssl_tls13_derive_handshake_secrets( + mbedtls_md_type_t md_type, + unsigned char const *handshake_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_handshake_secrets *derived ) +{ + int ret; + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if( md_info == 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* + * + * Handshake Secret + * | + * +-----> Derive-Secret( ., "c hs traffic", + * | ClientHello...ServerHello ) + * | = client_handshake_traffic_secret + * | + * +-----> Derive-Secret( ., "s hs traffic", + * | ClientHello...ServerHello ) + * | = server_handshake_traffic_secret + * + */ + + /* + * Compute client_handshake_traffic_secret with + * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello ) + */ + + ret = mbedtls_ssl_tls13_derive_secret( md_type, + handshake_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( c_hs_traffic ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_handshake_traffic_secret, + md_size ); + if( ret != 0 ) + return( ret ); + + /* + * Compute server_handshake_traffic_secret with + * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello ) + */ + + ret = mbedtls_ssl_tls13_derive_secret( md_type, + handshake_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( s_hs_traffic ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->server_handshake_traffic_secret, + md_size ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_ssl_tls13_derive_application_secrets( + mbedtls_md_type_t md_type, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived ) +{ + int ret; + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if( md_info == 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* Generate {client,server}_application_traffic_secret_0 + * + * Master Secret + * | + * +-----> Derive-Secret( ., "c ap traffic", + * | ClientHello...server Finished ) + * | = client_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "s ap traffic", + * | ClientHello...Server Finished ) + * | = server_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "exp master", + * | ClientHello...server Finished) + * | = exporter_master_secret + * + */ + + ret = mbedtls_ssl_tls13_derive_secret( md_type, + application_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( c_ap_traffic ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->client_application_traffic_secret_N, + md_size ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls13_derive_secret( md_type, + application_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( s_ap_traffic ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->server_application_traffic_secret_N, + md_size ); + if( ret != 0 ) + return( ret ); + + ret = mbedtls_ssl_tls13_derive_secret( md_type, + application_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( exp_master ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->exporter_master_secret, + md_size ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +/* Generate resumption_master_secret for use with the ticket exchange. + * + * This is not integrated with mbedtls_ssl_tls13_derive_application_secrets() + * because it uses the transcript hash up to and including ClientFinished. */ +int mbedtls_ssl_tls13_derive_resumption_master_secret( + mbedtls_md_type_t md_type, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived ) +{ + int ret; + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if( md_info == 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + ret = mbedtls_ssl_tls13_derive_secret( md_type, + application_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( res_master ), + transcript, transcript_len, + MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED, + derived->resumption_master_secret, + md_size ); + + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_ssl_tls13_key_schedule_stage_application( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + mbedtls_md_type_t const md_type = handshake->ciphersuite_info->mac; +#if defined(MBEDTLS_DEBUG_C) + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); +#endif /* MBEDTLS_DEBUG_C */ + + /* + * Compute MasterSecret + */ + ret = mbedtls_ssl_tls13_evolve_secret( md_type, + handshake->tls13_master_secrets.handshake, + NULL, 0, + handshake->tls13_master_secrets.app ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_evolve_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "Master secret", + handshake->tls13_master_secrets.app, md_size ); + + return( 0 ); +} + +static int ssl_tls13_calc_finished_core( mbedtls_md_type_t md_type, + unsigned char const *base_key, + unsigned char const *transcript, + unsigned char *dst ) +{ + const mbedtls_md_info_t* const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + unsigned char finished_key[MBEDTLS_MD_MAX_SIZE]; + int ret; + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if( md_info == 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* TLS 1.3 Finished message + * + * struct { + * opaque verify_data[Hash.length]; + * } Finished; + * + * verify_data = + * HMAC( finished_key, + * Hash( Handshake Context + + * Certificate* + + * CertificateVerify* ) + * ) + * + * finished_key = + * HKDF-Expand-Label( BaseKey, "finished", "", Hash.length ) + */ + + ret = mbedtls_ssl_tls13_hkdf_expand_label( + md_type, base_key, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( finished ), + NULL, 0, + finished_key, md_size ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_md_hmac( md_info, finished_key, md_size, transcript, md_size, dst ); + if( ret != 0 ) + goto exit; + +exit: + + mbedtls_platform_zeroize( finished_key, sizeof( finished_key ) ); + return( ret ); +} + +int mbedtls_ssl_tls13_calculate_verify_data( mbedtls_ssl_context* ssl, + unsigned char* dst, + size_t dst_len, + size_t *actual_len, + int from ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + unsigned char *base_key = NULL; + size_t base_key_len = 0; + mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = + &ssl->handshake->tls13_hs_secrets; + + mbedtls_md_type_t const md_type = ssl->handshake->ciphersuite_info->mac; + const mbedtls_md_info_t* const md_info = + mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_tls13_calculate_verify_data" ) ); + + if( from == MBEDTLS_SSL_IS_CLIENT ) + { + base_key = tls13_hs_secrets->client_handshake_traffic_secret; + base_key_len = sizeof( tls13_hs_secrets->client_handshake_traffic_secret ); + } + else + { + base_key = tls13_hs_secrets->server_handshake_traffic_secret; + base_key_len = sizeof( tls13_hs_secrets->server_handshake_traffic_secret ); + } + + if( dst_len < md_size ) + { + ret = MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL; + goto exit; + } + + ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type, + transcript, sizeof( transcript ), + &transcript_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_get_handshake_transcript", ret ); + goto exit; + } + MBEDTLS_SSL_DEBUG_BUF( 4, "handshake hash", transcript, transcript_len ); + + ret = ssl_tls13_calc_finished_core( md_type, base_key, transcript, dst ); + if( ret != 0 ) + goto exit; + *actual_len = md_size; + + MBEDTLS_SSL_DEBUG_BUF( 3, "verify_data for finished message", dst, md_size ); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_tls13_calculate_verify_data" ) ); + +exit: + /* Erase handshake secrets */ + mbedtls_platform_zeroize( base_key, base_key_len ); + mbedtls_platform_zeroize( transcript, sizeof( transcript ) ); + return( ret ); +} + +int mbedtls_ssl_tls13_create_psk_binder( mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md_type, + unsigned char const *psk, size_t psk_len, + int psk_type, + unsigned char const *transcript, + unsigned char *result ) +{ + int ret = 0; + unsigned char binder_key[MBEDTLS_MD_MAX_SIZE]; + unsigned char early_secret[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_info_t const *md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for debug */ + ((void) ssl); +#endif + + /* We should never call this function with an unknown hash, + * but add an assertion anyway. */ + if( md_info == 0 ) + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + + /* + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * +-----> Derive-Secret(., "ext binder" | "res binder", "") + * | = binder_key + * v + */ + + ret = mbedtls_ssl_tls13_evolve_secret( md_type, + NULL, /* Old secret */ + psk, psk_len, /* Input */ + early_secret ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_evolve_secret", ret ); + goto exit; + } + + if( psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION ) + { + ret = mbedtls_ssl_tls13_derive_secret( md_type, + early_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( res_binder ), + NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + binder_key, md_size ); + MBEDTLS_SSL_DEBUG_MSG( 4, ( "Derive Early Secret with 'res binder'" ) ); + } + else + { + ret = mbedtls_ssl_tls13_derive_secret( md_type, + early_secret, md_size, + MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( ext_binder ), + NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED, + binder_key, md_size ); + MBEDTLS_SSL_DEBUG_MSG( 4, ( "Derive Early Secret with 'ext binder'" ) ); + } + + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_secret", ret ); + goto exit; + } + + /* + * The binding_value is computed in the same way as the Finished message + * but with the BaseKey being the binder_key. + */ + + ret = ssl_tls13_calc_finished_core( md_type, binder_key, transcript, result ); + if( ret != 0 ) + goto exit; + + MBEDTLS_SSL_DEBUG_BUF( 3, "psk binder", result, md_size ); + +exit: + + mbedtls_platform_zeroize( early_secret, sizeof( early_secret ) ); + mbedtls_platform_zeroize( binder_key, sizeof( binder_key ) ); + return( ret ); +} + +int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform, + int endpoint, + int ciphersuite, + mbedtls_ssl_key_set const *traffic_keys, + mbedtls_ssl_context *ssl /* DEBUG ONLY */ ) +{ + int ret; + mbedtls_cipher_info_t const *cipher_info; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + unsigned char const *key_enc; + unsigned char const *iv_enc; + unsigned char const *key_dec; + unsigned char const *iv_dec; + +#if !defined(MBEDTLS_DEBUG_C) + ssl = NULL; /* make sure we don't use it except for those cases */ + (void) ssl; +#endif + + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuite ); + if( ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "ciphersuite info for %d not found", + ciphersuite ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); + if( cipher_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher info for %u not found", + ciphersuite_info->cipher ) ); + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + /* + * Setup cipher contexts in target transform + */ + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_enc, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setup( &transform->cipher_ctx_dec, + cipher_info ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setup", ret ); + return( ret ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( endpoint == MBEDTLS_SSL_IS_SERVER ) + { + key_enc = traffic_keys->server_write_key; + key_dec = traffic_keys->client_write_key; + iv_enc = traffic_keys->server_write_iv; + iv_dec = traffic_keys->client_write_iv; + } + else +#endif /* MBEDTLS_SSL_SRV_C */ +#if defined(MBEDTLS_SSL_CLI_C) + if( endpoint == MBEDTLS_SSL_IS_CLIENT ) + { + key_enc = traffic_keys->client_write_key; + key_dec = traffic_keys->server_write_key; + iv_enc = traffic_keys->client_write_iv; + iv_dec = traffic_keys->server_write_iv; + } + else +#endif /* MBEDTLS_SSL_CLI_C */ + { + /* should not happen */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + memcpy( transform->iv_enc, iv_enc, traffic_keys->iv_len ); + memcpy( transform->iv_dec, iv_dec, traffic_keys->iv_len ); + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_enc, + key_enc, cipher_info->key_bitlen, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + + if( ( ret = mbedtls_cipher_setkey( &transform->cipher_ctx_dec, + key_dec, cipher_info->key_bitlen, + MBEDTLS_DECRYPT ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_cipher_setkey", ret ); + return( ret ); + } + + /* + * Setup other fields in SSL transform + */ + + if( ( ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ) != 0 ) + transform->taglen = 8; + else + transform->taglen = 16; + + transform->ivlen = traffic_keys->iv_len; + transform->maclen = 0; + transform->fixed_ivlen = transform->ivlen; + transform->minor_ver = MBEDTLS_SSL_MINOR_VERSION_4; + + /* We add the true record content type (1 Byte) to the plaintext and + * then pad to the configured granularity. The mimimum length of the + * type-extended and padded plaintext is therefore the padding + * granularity. */ + transform->minlen = + transform->taglen + MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY; + + return( 0 ); +} + +int mbedtls_ssl_tls13_key_schedule_stage_early( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_md_type_t md_type; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + if( handshake->ciphersuite_info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cipher suite info not found" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + md_type = handshake->ciphersuite_info->mac; + + ret = mbedtls_ssl_tls13_evolve_secret( md_type, NULL, NULL, 0, + handshake->tls13_master_secrets.early ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_evolve_secret", ret ); + return( ret ); + } + + return( 0 ); +} + +/* mbedtls_ssl_tls13_generate_handshake_keys() generates keys necessary for + * protecting the handshake messages, as described in Section 7 of TLS 1.3. */ +int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_type_t md_type; + mbedtls_md_info_t const *md_info; + size_t md_size; + + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + mbedtls_cipher_info_t const *cipher_info; + size_t key_len, iv_len; + + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info; + mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> mbedtls_ssl_tls13_generate_handshake_keys" ) ); + + cipher_info = mbedtls_cipher_info_from_type( ciphersuite_info->cipher ); + key_len = cipher_info->key_bitlen >> 3; + iv_len = cipher_info->iv_size; + + md_type = ciphersuite_info->mac; + md_info = mbedtls_md_info_from_type( md_type ); + md_size = mbedtls_md_get_size( md_info ); + + ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type, + transcript, + sizeof( transcript ), + &transcript_len ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_get_handshake_transcript", + ret ); + return( ret ); + } + + ret = mbedtls_ssl_tls13_derive_handshake_secrets( md_type, + handshake->tls13_master_secrets.handshake, + transcript, transcript_len, tls13_hs_secrets ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_derive_handshake_secrets", + ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "Client handshake traffic secret", + tls13_hs_secrets->client_handshake_traffic_secret, + md_size ); + MBEDTLS_SSL_DEBUG_BUF( 4, "Server handshake traffic secret", + tls13_hs_secrets->server_handshake_traffic_secret, + md_size ); + + /* + * Export client handshake traffic secret + */ + if( ssl->f_export_keys != NULL ) + { + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->client_handshake_traffic_secret, + md_size, + handshake->randbytes + 32, + handshake->randbytes, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ ); + + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET, + tls13_hs_secrets->server_handshake_traffic_secret, + md_size, + handshake->randbytes + 32, + handshake->randbytes, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */ ); + } + + ret = mbedtls_ssl_tls13_make_traffic_keys( md_type, + tls13_hs_secrets->client_handshake_traffic_secret, + tls13_hs_secrets->server_handshake_traffic_secret, + md_size, key_len, iv_len, traffic_keys ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_make_traffic_keys", ret ); + goto exit; + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_key", + traffic_keys->client_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_key", + traffic_keys->server_write_key, + traffic_keys->key_len); + + MBEDTLS_SSL_DEBUG_BUF( 4, "client_handshake write_iv", + traffic_keys->client_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_BUF( 4, "server_handshake write_iv", + traffic_keys->server_write_iv, + traffic_keys->iv_len); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= mbedtls_ssl_tls13_generate_handshake_keys" ) ); + +exit: + + return( ret ); +} + +int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + mbedtls_md_type_t const md_type = handshake->ciphersuite_info->mac; + size_t ephemeral_len = 0; + unsigned char ecdhe[MBEDTLS_ECP_MAX_BYTES]; +#if defined(MBEDTLS_DEBUG_C) + mbedtls_md_info_t const * const md_info = mbedtls_md_info_from_type( md_type ); + size_t const md_size = mbedtls_md_get_size( md_info ); +#endif /* MBEDTLS_DEBUG_C */ + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + /* + * Compute ECDHE secret used to compute the handshake secret from which + * client_handshake_traffic_secret and server_handshake_traffic_secret + * are derived in the handshake secret derivation stage. + */ + if( mbedtls_ssl_tls13_ephemeral_enabled( ssl ) ) + { + if( mbedtls_ssl_tls13_named_group_is_ecdhe( handshake->offered_group_id ) ) + { +#if defined(MBEDTLS_ECDH_C) + ret = mbedtls_ecdh_calc_secret( &handshake->ecdh_ctx, + &ephemeral_len, ecdhe, sizeof( ecdhe ), + ssl->conf->f_rng, + ssl->conf->p_rng ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); + return( ret ); + } +#endif /* MBEDTLS_ECDH_C */ + } + else if( mbedtls_ssl_tls13_named_group_is_dhe( handshake->offered_group_id ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "DHE not supported." ) ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } + } +#else + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + + /* + * Compute the Handshake Secret + */ + ret = mbedtls_ssl_tls13_evolve_secret( md_type, + handshake->tls13_master_secrets.early, + ecdhe, ephemeral_len, + handshake->tls13_master_secrets.handshake ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_evolve_secret", ret ); + return( ret ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "Handshake secret", + handshake->tls13_master_secrets.handshake, md_size ); + +#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) + mbedtls_platform_zeroize( ecdhe, sizeof( ecdhe ) ); +#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED */ + return( 0 ); +} + +/* Generate application traffic keys since any records following a 1-RTT Finished message + * MUST be encrypted under the application traffic key. + */ +int mbedtls_ssl_tls13_generate_application_keys( + mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ssl_handshake_params *handshake = ssl->handshake; + + /* Address at which to store the application secrets */ + mbedtls_ssl_tls13_application_secrets * const app_secrets = + &ssl->session_negotiate->app_secrets; + + /* Holding the transcript up to and including the ServerFinished */ + unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE]; + size_t transcript_len; + + /* Variables relating to the hash for the chosen ciphersuite. */ + mbedtls_md_type_t md_type; + mbedtls_md_info_t const *md_info; + size_t md_size; + + /* Variables relating to the cipher for the chosen ciphersuite. */ + mbedtls_cipher_info_t const *cipher_info; + size_t key_len, iv_len; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> derive application traffic keys" ) ); + + /* Extract basic information about hash and ciphersuite */ + + cipher_info = mbedtls_cipher_info_from_type( + handshake->ciphersuite_info->cipher ); + key_len = cipher_info->key_bitlen / 8; + iv_len = cipher_info->iv_size; + + md_type = handshake->ciphersuite_info->mac; + md_info = mbedtls_md_info_from_type( md_type ); + md_size = mbedtls_md_get_size( md_info ); + + /* Compute current handshake transcript. It's the caller's responsiblity + * to call this at the right time, that is, after the ServerFinished. */ + + ret = mbedtls_ssl_get_handshake_transcript( ssl, md_type, + transcript, sizeof( transcript ), + &transcript_len ); + if( ret != 0 ) + goto cleanup; + + /* Compute application secrets from master secret and transcript hash. */ + + ret = mbedtls_ssl_tls13_derive_application_secrets( md_type, + handshake->tls13_master_secrets.app, + transcript, transcript_len, + app_secrets ); + /* Erase master secrets */ + mbedtls_platform_zeroize( &ssl->handshake->tls13_master_secrets, + sizeof( ssl->handshake->tls13_master_secrets ) ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, + "mbedtls_ssl_tls13_derive_application_secrets", ret ); + goto cleanup; + } + + /* Derive first epoch of IV + Key for application traffic. */ + + ret = mbedtls_ssl_tls13_make_traffic_keys( md_type, + app_secrets->client_application_traffic_secret_N, + app_secrets->server_application_traffic_secret_N, + md_size, key_len, iv_len, traffic_keys ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls13_make_traffic_keys", ret ); + goto cleanup; + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "Client application traffic secret", + app_secrets->client_application_traffic_secret_N, + md_size ); + + MBEDTLS_SSL_DEBUG_BUF( 4, "Server application traffic secret", + app_secrets->server_application_traffic_secret_N, + md_size ); + + /* + * Export client/server application traffic secret 0 + */ + if( ssl->f_export_keys != NULL ) + { + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET, + app_secrets->client_application_traffic_secret_N, md_size, + handshake->randbytes + 32, + handshake->randbytes, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by + a new constant for TLS 1.3! */ ); + + ssl->f_export_keys( ssl->p_export_keys, + MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET, + app_secrets->server_application_traffic_secret_N, md_size, + handshake->randbytes + 32, + handshake->randbytes, + MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by + a new constant for TLS 1.3! */ ); + } + + MBEDTLS_SSL_DEBUG_BUF( 4, "client application_write_key:", + traffic_keys->client_write_key, key_len ); + MBEDTLS_SSL_DEBUG_BUF( 4, "server application write key", + traffic_keys->server_write_key, key_len ); + MBEDTLS_SSL_DEBUG_BUF( 4, "client application write IV", + traffic_keys->client_write_iv, iv_len ); + MBEDTLS_SSL_DEBUG_BUF( 4, "server application write IV", + traffic_keys->server_write_iv, iv_len ); + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= derive application traffic keys" ) ); + + cleanup: + /* randbytes is not used again */ + mbedtls_platform_zeroize( ssl->handshake->randbytes, + sizeof( ssl->handshake->randbytes ) ); + mbedtls_platform_zeroize( transcript, sizeof( transcript ) ); + return( ret ); +} + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.h b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.h new file mode 100644 index 00000000..da967c39 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_keys.h @@ -0,0 +1,640 @@ +/* + * TLS 1.3 key schedule + * + * Copyright The Mbed TLS Contributors + * 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. + */ +#if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H) +#define MBEDTLS_SSL_TLS1_3_KEYS_H + +/* This requires MBEDTLS_SSL_TLS1_3_LABEL( idx, name, string ) to be defined at + * the point of use. See e.g. the definition of mbedtls_ssl_tls13_labels_union + * below. */ +#define MBEDTLS_SSL_TLS1_3_LABEL_LIST \ + MBEDTLS_SSL_TLS1_3_LABEL( finished , "finished" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( resumption , "resumption" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( traffic_upd , "traffic upd" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exporter , "exporter" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( key , "key" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( iv , "iv" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_hs_traffic, "c hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_ap_traffic, "c ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( c_e_traffic , "c e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_hs_traffic, "s hs traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_ap_traffic, "s ap traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( s_e_traffic , "s e traffic" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( e_exp_master, "e exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_master , "res master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( exp_master , "exp master" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( ext_binder , "ext binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( res_binder , "res binder" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( derived , "derived" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( client_cv , "TLS 1.3, client CertificateVerify" ) \ + MBEDTLS_SSL_TLS1_3_LABEL( server_cv , "TLS 1.3, server CertificateVerify" ) + +#define MBEDTLS_SSL_TLS1_3_LABEL( name, string ) \ + const unsigned char name [ sizeof(string) - 1 ]; + +union mbedtls_ssl_tls13_labels_union +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +struct mbedtls_ssl_tls13_labels_struct +{ + MBEDTLS_SSL_TLS1_3_LABEL_LIST +}; +#undef MBEDTLS_SSL_TLS1_3_LABEL + +extern const struct mbedtls_ssl_tls13_labels_struct mbedtls_ssl_tls13_labels; + +#define MBEDTLS_SSL_TLS1_3_LBL_LEN( LABEL ) \ + sizeof(mbedtls_ssl_tls13_labels.LABEL) + +#define MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( LABEL ) \ + mbedtls_ssl_tls13_labels.LABEL, \ + MBEDTLS_SSL_TLS1_3_LBL_LEN( LABEL ) + +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_LABEL_LEN \ + sizeof( union mbedtls_ssl_tls13_labels_union ) + +/* The maximum length of HKDF contexts used in the TLS 1.3 standard. + * Since contexts are always hashes of message transcripts, this can + * be approximated from above by the maximum hash size. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_CONTEXT_LEN \ + MBEDTLS_MD_MAX_SIZE + +/* Maximum desired length for expanded key material generated + * by HKDF-Expand-Label. + * + * Warning: If this ever needs to be increased, the implementation + * ssl_tls13_hkdf_encode_label() in ssl_tls13_keys.c needs to be + * adjusted since it currently assumes that HKDF key expansion + * is never used with more than 255 Bytes of output. */ +#define MBEDTLS_SSL_TLS1_3_KEY_SCHEDULE_MAX_EXPANSION_LEN 255 + +/** + * \brief The \c HKDF-Expand-Label function from + * the TLS 1.3 standard RFC 8446. + * + * + * HKDF-Expand-Label( Secret, Label, Context, Length ) = + * HKDF-Expand( Secret, HkdfLabel, Length ) + * + * + * \param hash_alg The identifier for the hash algorithm to use. + * \param secret The \c Secret argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length + * \p secret_len Bytes. + * \param secret_len The length of \p secret in Bytes. + * \param label The \c Label argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length + * \p label_len Bytes. + * \param label_len The length of \p label in Bytes. + * \param ctx The \c Context argument to \c HKDF-Expand-Label. + * This must be a readable buffer of length \p ctx_len Bytes. + * \param ctx_len The length of \p context in Bytes. + * \param buf The destination buffer to hold the expanded secret. + * This must be a writable buffer of length \p buf_len Bytes. + * \param buf_len The desired size of the expanded secret in Bytes. + * + * \returns \c 0 on success. + * \return A negative error code on failure. + */ + +int mbedtls_ssl_tls13_hkdf_expand_label( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + unsigned char *buf, size_t buf_len ); + +/** + * \brief This function is part of the TLS 1.3 key schedule. + * It extracts key and IV for the actual client/server traffic + * from the client/server traffic secrets. + * + * From RFC 8446: + * + * + * [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length) + * [sender]_write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)* + * + * + * \param hash_alg The identifier for the hash algorithm to be used + * for the HKDF-based expansion of the secret. + * \param client_secret The client traffic secret. + * This must be a readable buffer of size + * \p secret_len Bytes + * \param server_secret The server traffic secret. + * This must be a readable buffer of size + * \p secret_len Bytes + * \param secret_len Length of the secrets \p client_secret and + * \p server_secret in Bytes. + * \param key_len The desired length of the key to be extracted in Bytes. + * \param iv_len The desired length of the IV to be extracted in Bytes. + * \param keys The address of the structure holding the generated + * keys and IVs. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls13_make_traffic_keys( + mbedtls_md_type_t hash_alg, + const unsigned char *client_secret, + const unsigned char *server_secret, size_t secret_len, + size_t key_len, size_t iv_len, + mbedtls_ssl_key_set *keys ); + + +#define MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED 0 +#define MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED 1 + +/** + * \brief The \c Derive-Secret function from the TLS 1.3 standard RFC 8446. + * + * + * Derive-Secret( Secret, Label, Messages ) = + * HKDF-Expand-Label( Secret, Label, + * Hash( Messages ), + * Hash.Length ) ) + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret The \c Secret argument to the \c Derive-Secret function. + * This must be a readable buffer of length + * \p secret_len Bytes. + * \param secret_len The length of \p secret in Bytes. + * \param label The \c Label argument to the \c Derive-Secret function. + * This must be a readable buffer of length + * \p label_len Bytes. + * \param label_len The length of \p label in Bytes. + * \param ctx The hash of the \c Messages argument to the + * \c Derive-Secret function, or the \c Messages argument + * itself, depending on \p ctx_hashed. + * \param ctx_len The length of \p ctx in Bytes. + * \param ctx_hashed This indicates whether the \p ctx contains the hash of + * the \c Messages argument in the application of the + * \c Derive-Secret function + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED), or whether + * it is the content of \c Messages itself, in which case + * the function takes care of the hashing + * (value MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED). + * \param dstbuf The target buffer to write the output of + * \c Derive-Secret to. This must be a writable buffer of + * size \p dtsbuf_len Bytes. + * \param dstbuf_len The length of \p dstbuf in Bytes. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_derive_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret, size_t secret_len, + const unsigned char *label, size_t label_len, + const unsigned char *ctx, size_t ctx_len, + int ctx_hashed, + unsigned char *dstbuf, size_t dstbuf_len ); + +/** + * \brief Derive TLS 1.3 early data key material from early secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels. + * + * + * Early Secret + * | + * +-----> Derive-Secret(., "c e traffic", ClientHello) + * | = client_early_traffic_secret + * | + * +-----> Derive-Secret(., "e exp master", ClientHello) + * . = early_exporter_master_secret + * . + * . + * + * + * \note To obtain the actual key and IV for the early data traffic, + * the client secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \note The binder key, which is also generated from the early secret, + * is omitted here. Its calculation is part of the separate routine + * mbedtls_ssl_tls13_create_psk_binder(). + * + * \param md_type The hash algorithm associated with the PSK for which + * early data key material is being derived. + * \param early_secret The early secret from which the early data key material + * should be derived. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p md_size. + * \param transcript The transcript of the handshake so far, calculated with + * respect to \p md_type. This must be a readable buffer + * whose length is the digest size of the hash algorithm + * represented by \p md_size. + * \param derived The address of the structure in which to store + * the early data key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_derive_early_secrets( + mbedtls_md_type_t md_type, + unsigned char const *early_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_early_secrets *derived ); + +/** + * \brief Derive TLS 1.3 handshake key material from the handshake secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * + * Handshake Secret + * | + * +-----> Derive-Secret( ., "c hs traffic", + * | ClientHello...ServerHello ) + * | = client_handshake_traffic_secret + * | + * +-----> Derive-Secret( ., "s hs traffic", + * . ClientHello...ServerHello ) + * . = server_handshake_traffic_secret + * . + * + * + * \note To obtain the actual key and IV for the encrypted handshake traffic, + * the client and server secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \param md_type The hash algorithm associated with the ciphersuite + * that's being used for the connection. + * \param handshake_secret The handshake secret from which the handshake key + * material should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake so far, calculated + * with respect to \p md_type. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param derived The address of the structure in which to + * store the handshake key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_derive_handshake_secrets( + mbedtls_md_type_t md_type, + unsigned char const *handshake_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_handshake_secrets *derived ); + +/** + * \brief Derive TLS 1.3 application key material from the master secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * + * Master Secret + * | + * +-----> Derive-Secret( ., "c ap traffic", + * | ClientHello...server Finished ) + * | = client_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "s ap traffic", + * | ClientHello...Server Finished ) + * | = server_application_traffic_secret_0 + * | + * +-----> Derive-Secret( ., "exp master", + * . ClientHello...server Finished) + * . = exporter_master_secret + * . + * + * + * \note To obtain the actual key and IV for the (0-th) application traffic, + * the client and server secret derived by this function need to be + * further processed by mbedtls_ssl_tls13_make_traffic_keys(). + * + * \param md_type The hash algorithm associated with the ciphersuite + * that's being used for the connection. + * \param master_secret The master secret from which the application key + * material should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake up to and including + * the ServerFinished message, calculated with respect + * to \p md_type. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p md_type. + * \param derived The address of the structure in which to + * store the application key material. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_derive_application_secrets( + mbedtls_md_type_t md_type, + unsigned char const *master_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived ); + +/** + * \brief Derive TLS 1.3 resumption master secret from the master secret. + * + * This is a small wrapper invoking mbedtls_ssl_tls13_derive_secret() + * with the appropriate labels from the standard. + * + * \param md_type The hash algorithm used in the application for which + * key material is being derived. + * \param application_secret The application secret from which the resumption master + * secret should be derived. This must be a readable + * buffer whose length is the digest size of the hash + * algorithm represented by \p md_size. + * \param transcript The transcript of the handshake up to and including + * the ClientFinished message, calculated with respect + * to \p md_type. This must be a readable buffer whose + * length is the digest size of the hash algorithm + * represented by \p md_type. + * \param transcript_len The length of \p transcript in Bytes. + * \param derived The address of the structure in which to + * store the resumption master secret. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_derive_resumption_master_secret( + mbedtls_md_type_t md_type, + unsigned char const *application_secret, + unsigned char const *transcript, size_t transcript_len, + mbedtls_ssl_tls13_application_secrets *derived ); + +/** + * \brief Compute the next secret in the TLS 1.3 key schedule + * + * The TLS 1.3 key schedule proceeds as follows to compute + * the three main secrets during the handshake: The early + * secret for early data, the handshake secret for all + * other encrypted handshake messages, and the master + * secret for all application traffic. + * + * + * 0 + * | + * v + * PSK -> HKDF-Extract = Early Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * (EC)DHE -> HKDF-Extract = Handshake Secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * 0 -> HKDF-Extract = Master Secret + * + * + * Each of the three secrets in turn is the basis for further + * key derivations, such as the derivation of traffic keys and IVs; + * see e.g. mbedtls_ssl_tls13_make_traffic_keys(). + * + * This function implements one step in this evolution of secrets: + * + * + * old_secret + * | + * v + * Derive-Secret( ., "derived", "" ) + * | + * v + * input -> HKDF-Extract = new_secret + * + * + * \param hash_alg The identifier for the hash function used for the + * applications of HKDF. + * \param secret_old The address of the buffer holding the old secret + * on function entry. If not \c NULL, this must be a + * readable buffer whose size matches the output size + * of the hash function represented by \p hash_alg. + * If \c NULL, an all \c 0 array will be used instead. + * \param input The address of the buffer holding the additional + * input for the key derivation (e.g., the PSK or the + * ephemeral (EC)DH secret). If not \c NULL, this must be + * a readable buffer whose size \p input_len Bytes. + * If \c NULL, an all \c 0 array will be used instead. + * \param input_len The length of \p input in Bytes. + * \param secret_new The address of the buffer holding the new secret + * on function exit. This must be a writable buffer + * whose size matches the output size of the hash + * function represented by \p hash_alg. + * This may be the same as \p secret_old. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ + +int mbedtls_ssl_tls13_evolve_secret( + mbedtls_md_type_t hash_alg, + const unsigned char *secret_old, + const unsigned char *input, size_t input_len, + unsigned char *secret_new ); + +#define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL 0 +#define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1 + +/** + * \brief Calculate a TLS 1.3 PSK binder. + * + * \param ssl The SSL context. This is used for debugging only and may + * be \c NULL if MBEDTLS_DEBUG_C is disabled. + * \param md_type The hash algorithm associated to the PSK \p psk. + * \param psk The buffer holding the PSK for which to create a binder. + * \param psk_len The size of \p psk in bytes. + * \param psk_type This indicates whether the PSK \p psk is externally + * provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a + * resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION). + * \param transcript The handshake transcript up to the point where the + * PSK binder calculation happens. This must be readable, + * and its size must be equal to the digest size of + * the hash algorithm represented by \p md_type. + * \param result The address at which to store the PSK binder on success. + * This must be writable, and its size must be equal to the + * digest size of the hash algorithm represented by + * \p md_type. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_create_psk_binder( mbedtls_ssl_context *ssl, + const mbedtls_md_type_t md_type, + unsigned char const *psk, size_t psk_len, + int psk_type, + unsigned char const *transcript, + unsigned char *result ); + +/** + * \bref Setup an SSL transform structure representing the + * record protection mechanism used by TLS 1.3 + * + * \param transform The SSL transform structure to be created. This must have + * been initialized through mbedtls_ssl_transform_init() and + * not used in any other way prior to calling this function. + * In particular, this function does not clean up the + * transform structure prior to installing the new keys. + * \param endpoint Indicates whether the transform is for the client + * (value #MBEDTLS_SSL_IS_CLIENT) or the server + * (value #MBEDTLS_SSL_IS_SERVER). + * \param ciphersuite The numerical identifier for the ciphersuite to use. + * This must be one of the identifiers listed in + * ssl_ciphersuites.h. + * \param traffic_keys The key material to use. No reference is stored in + * the SSL transform being generated, and the caller + * should destroy the key material afterwards. + * \param ssl (Debug-only) The SSL context to use for debug output + * in case of failure. This parameter is only needed if + * #MBEDTLS_DEBUG_C is set, and is ignored otherwise. + * + * \return \c 0 on success. In this case, \p transform is ready to + * be used with mbedtls_ssl_transform_decrypt() and + * mbedtls_ssl_transform_encrypt(). + * \return A negative error code on failure. + */ +int mbedtls_ssl_tls13_populate_transform( mbedtls_ssl_transform *transform, + int endpoint, + int ciphersuite, + mbedtls_ssl_key_set const *traffic_keys, + mbedtls_ssl_context *ssl ); + +/* + * TLS 1.3 key schedule evolutions + * + * Early -> Handshake -> Application + * + * Small wrappers around mbedtls_ssl_tls13_evolve_secret(). + */ + +/** + * \brief Begin TLS 1.3 key schedule by calculating early secret. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Initial -> Early transition. + * + * \param ssl The SSL context to operate on. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_key_schedule_stage_early( mbedtls_ssl_context *ssl ); + +/** + * \brief Transition into handshake stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Early -> Handshake transition. + * + * In the handshake stage, mbedtls_ssl_tls13_generate_handshake_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Early. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_key_schedule_stage_handshake( mbedtls_ssl_context *ssl ); + +/** + * \brief Compute TLS 1.3 handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * mbedtls_ssl_tls13_key_schedule_stage_handshake(). + * \param traffic_keys The address at which to store the handshake traffic key + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_generate_handshake_keys( mbedtls_ssl_context *ssl, + mbedtls_ssl_key_set *traffic_keys ); + +/** + * \brief Transition into application stage of TLS 1.3 key schedule. + * + * The TLS 1.3 key schedule can be viewed as a simple state machine + * with states Initial -> Early -> Handshake -> Application, and + * this function represents the Handshake -> Application transition. + * + * In the handshake stage, mbedtls_ssl_tls13_generate_application_keys() + * can be used to derive the handshake traffic keys. + * + * \param ssl The SSL context to operate on. This must be in key schedule + * stage \c Handshake. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_key_schedule_stage_application( mbedtls_ssl_context *ssl ); + +/** + * \brief Compute TLS 1.3 application traffic keys. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Application, see + * mbedtls_ssl_tls13_key_schedule_stage_application(). + * \param traffic_keys The address at which to store the application traffic key + * keys. This must be writable but may be uninitialized. + * + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_generate_application_keys( + mbedtls_ssl_context* ssl, mbedtls_ssl_key_set *traffic_keys ); + +/** + * \brief Calculate the verify_data value for the client or server TLS 1.3 + * Finished message. + * + * \param ssl The SSL context to operate on. This must be in + * key schedule stage \c Handshake, see + * mbedtls_ssl_tls13_key_schedule_stage_application(). + * \param dst The address at which to write the verify_data value. + * \param dst_len The size of \p dst in bytes. + * \param actual_len The address at which to store the amount of data + * actually written to \p dst upon success. + * \param which The message to calculate the `verify_data` for: + * - #MBEDTLS_SSL_IS_CLIENT for the Client's Finished message + * - #MBEDTLS_SSL_IS_SERVER for the Server's Finished message + * + * \note Both client and server call this function twice, once to + * generate their own Finished message, and once to verify the + * peer's Finished message. + + * \returns \c 0 on success. + * \returns A negative error code on failure. + */ +int mbedtls_ssl_tls13_calculate_verify_data( mbedtls_ssl_context *ssl, + unsigned char *dst, + size_t dst_len, + size_t *actual_len, + int which ); + +#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_server.c b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_server.c new file mode 100644 index 00000000..faace4a0 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/ssl_tls13_server.c @@ -0,0 +1,43 @@ +/* + * TLS 1.3 server-side functions + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) + +#if defined(MBEDTLS_SSL_SRV_C) + +#include "mbedtls/debug.h" + +#include "ssl_misc.h" +#include "ssl_debug_helpers_generated.h" + +int mbedtls_ssl_tls13_handshake_server_step( mbedtls_ssl_context *ssl ) +{ + ((void) ssl); + MBEDTLS_SSL_DEBUG_MSG( 2, ( "tls13 server state: %s(%d)", + mbedtls_ssl_states_str( ssl->state ), + ssl->state ) ); + + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +#endif /* MBEDTLS_SSL_SRV_C */ + +#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/threading.c b/component/common/network/ssl/mbedtls-3.1.0/library/threading.c new file mode 100644 index 00000000..bae6644f --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/threading.c @@ -0,0 +1,187 @@ +/* + * Threading abstraction layer + * + * Copyright The Mbed TLS Contributors + * 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. + */ + +/* + * Ensure gmtime_r is available even with -std=c99; must be defined before + * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms. + */ +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif + +#include "common.h" + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) + +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ + +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ + +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define THREADING_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ + +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ + +#endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + /* A nonzero value of is_valid indicates a successfully initialized + * mutex. This is a workaround for not being able to return an error + * code for this function. The lock/unlock functions return an error + * if is_valid is nonzero. The Mbed TLS unit test code uses this field + * to distinguish more states of the mutex; see + * tests/src/threading_helpers for details. */ + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(THREADING_USE_GMTIME) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +#if defined(MBEDTLS_FS_IO) +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif +#if defined(THREADING_USE_GMTIME) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif + +#endif /* MBEDTLS_THREADING_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/timing.c b/component/common/network/ssl/mbedtls-3.1.0/library/timing.c new file mode 100644 index 00000000..b3c6edfc --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/timing.c @@ -0,0 +1,162 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) +/* +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) && !defined(__midipix__) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in mbedtls_config.h" +#endif +*/ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/** + * \brief Return the elapsed time in milliseconds + * + * \warning May change without notice + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ +#endif /* MBEDTLS_TIMING_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/version.c b/component/common/network/ssl/mbedtls-3.1.0/library/version.c new file mode 100644 index 00000000..32a0d7d5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/version.c @@ -0,0 +1,44 @@ +/* + * Version information + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" +#include + +unsigned int mbedtls_version_get_number( void ) +{ + return( MBEDTLS_VERSION_NUMBER ); +} + +void mbedtls_version_get_string( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING, + sizeof( MBEDTLS_VERSION_STRING ) ); +} + +void mbedtls_version_get_string_full( char *string ) +{ + memcpy( string, MBEDTLS_VERSION_STRING_FULL, + sizeof( MBEDTLS_VERSION_STRING_FULL ) ); +} + +#endif /* MBEDTLS_VERSION_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509.c new file mode 100644 index 00000000..2e11c7fc --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509.c @@ -0,0 +1,1000 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include "mbedtls/platform_util.h" +#include +#endif + +#define CHECK(code) if( ( ret = ( code ) ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) \ + do \ + { \ + if( ( val ) < ( min ) || ( val ) > ( max ) ) \ + { \ + return( ret ); \ + } \ + } while( 0 ) + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SERIAL, ret ) ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) parameters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + p = alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, + MBEDTLS_ERR_OID_NOT_FOUND ) ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, ret ) ); + + if( p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_ALG, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + end = *p + len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + val->p = *p; + *p += val->len; + + if( *p != end ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_NAME, ret ) ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret ) ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret ) ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* Extension structure use EXPLICIT tagging. That is, the actual + * `Extensions` structure is wrapped by a tag-length pair using + * the respective context-specific tag. */ + ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( end != *p + len ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c >= 127 ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + (unsigned int) pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt, tm_buf; + mbedtls_time_t tt; + int ret = 0; + + tt = mbedtls_time( NULL ); + lt = mbedtls_platform_gmtime_r( &tt, &tm_buf ); + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + + return( ret ); +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ +#endif /* MBEDTLS_X509_USE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509_create.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509_create.c new file mode 100644 index 00000000..056bbaa7 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509_create.c @@ -0,0 +1,374 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright The Mbed TLS Contributors + * 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 "common.h" + +#if defined(MBEDTLS_X509_CREATE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" + +#include + +/* Structure linking OIDs for X.509 DN AttributeTypes to their + * string representations and default string encodings used by Mbed TLS. */ +typedef struct { + const char *name; /* String representation of AttributeType, e.g. + * "CN" or "emailAddress". */ + size_t name_len; /* Length of 'name', without trailing 0 byte. */ + const char *oid; /* String representation of OID of AttributeType, + * as per RFC 5280, Appendix A.1. */ + int default_tag; /* The default character encoding used for the + * given attribute type, e.g. + * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */ +} x509_attr_descriptor_t; + +#define ADD_STRLEN( s ) s, sizeof( s ) - 1 + +/* X.509 DN attributes from RFC 5280, Appendix A.1. */ +static const x509_attr_descriptor_t x509_attrs[] = +{ + { ADD_STRLEN( "CN" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "commonName" ), + MBEDTLS_OID_AT_CN, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "C" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "countryName" ), + MBEDTLS_OID_AT_COUNTRY, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "O" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationName" ), + MBEDTLS_OID_AT_ORGANIZATION, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "L" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "locality" ), + MBEDTLS_OID_AT_LOCALITY, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "R" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "OU" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "organizationalUnitName" ), + MBEDTLS_OID_AT_ORG_UNIT, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "ST" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "stateOrProvinceName" ), + MBEDTLS_OID_AT_STATE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "emailAddress" ), + MBEDTLS_OID_PKCS9_EMAIL, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "serialNumber" ), + MBEDTLS_OID_AT_SERIAL_NUMBER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalAddress" ), + MBEDTLS_OID_AT_POSTAL_ADDRESS, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "postalCode" ), + MBEDTLS_OID_AT_POSTAL_CODE, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "dnQualifier" ), + MBEDTLS_OID_AT_DN_QUALIFIER, MBEDTLS_ASN1_PRINTABLE_STRING }, + { ADD_STRLEN( "title" ), + MBEDTLS_OID_AT_TITLE, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "surName" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "SN" ), + MBEDTLS_OID_AT_SUR_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "givenName" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "GN" ), + MBEDTLS_OID_AT_GIVEN_NAME, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "initials" ), + MBEDTLS_OID_AT_INITIALS, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "pseudonym" ), + MBEDTLS_OID_AT_PSEUDONYM, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "generationQualifier" ), + MBEDTLS_OID_AT_GENERATION_QUALIFIER, MBEDTLS_ASN1_UTF8_STRING }, + { ADD_STRLEN( "domainComponent" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { ADD_STRLEN( "DC" ), + MBEDTLS_OID_DOMAIN_COMPONENT, MBEDTLS_ASN1_IA5_STRING }, + { NULL, 0, NULL, MBEDTLS_ASN1_NULL } +}; + +static const x509_attr_descriptor_t *x509_attr_descr_from_name( const char *name, size_t name_len ) +{ + const x509_attr_descriptor_t *cur; + + for( cur = x509_attrs; cur->name != NULL; cur++ ) + if( cur->name_len == name_len && + strncmp( cur->name, name, name_len ) == 0 ) + break; + + if ( cur->name == NULL ) + return( NULL ); + + return( cur ); +} + +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ) +{ + int ret = 0; + const char *s = name, *c = s; + const char *end = s + strlen( s ); + const char *oid = NULL; + const x509_attr_descriptor_t* attr_descr = NULL; + int in_tag = 1; + char data[MBEDTLS_X509_MAX_DN_NAME_SIZE]; + char *d = data; + + /* Clear existing chain if present */ + mbedtls_asn1_free_named_data_list( head ); + + while( c <= end ) + { + if( in_tag && *c == '=' ) + { + if( ( attr_descr = x509_attr_descr_from_name( s, c - s ) ) == NULL ) + { + ret = MBEDTLS_ERR_X509_UNKNOWN_OID; + goto exit; + } + + oid = attr_descr->oid; + s = c + 1; + in_tag = 0; + d = data; + } + + if( !in_tag && *c == '\\' && c != end ) + { + c++; + + /* Check for valid escaped characters */ + if( c == end || *c != ',' ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + else if( !in_tag && ( *c == ',' || c == end ) ) + { + mbedtls_asn1_named_data* cur = + mbedtls_asn1_store_named_data( head, oid, strlen( oid ), + (unsigned char *) data, + d - data ); + + if(cur == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + // set tagType + cur->val.tag = attr_descr->default_tag; + + while( c < end && *(c + 1) == ' ' ) + c++; + + s = c + 1; + in_tag = 1; + } + + if( !in_tag && s != c + 1 ) + { + *(d++) = *c; + + if( d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE ) + { + ret = MBEDTLS_ERR_X509_INVALID_NAME; + goto exit; + } + } + + c++; + } + +exit: + + return( ret ); +} + +/* The first byte of the value in the mbedtls_asn1_named_data structure is reserved + * to store the critical boolean for us + */ +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_store_named_data( head, oid, oid_len, + NULL, val_len + 1 ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + cur->val.p[0] = critical; + memcpy( cur->val.p + 1, val, val_len ); + + return( 0 ); +} + +/* + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_write_name( unsigned char **p, unsigned char *start, mbedtls_asn1_named_data* cur_name) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const char *oid = (const char*)cur_name->oid.p; + size_t oid_len = cur_name->oid.len; + const unsigned char *name = cur_name->val.p; + size_t name_len = cur_name->val.len; + + // Write correct string tag and value + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tagged_string( p, start, + cur_name->val.tag, + (const char *) name, + name_len ) ); + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, + oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SET ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur = first; + + while( cur != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_name( p, start, cur ) ); + cur = cur->next; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, sig, len ); + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + // Write OID + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( p, start, oid, + oid_len, 0 ) ); + + return( (int) len ); +} + +static int x509_write_extension( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->val.p + 1, + ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->val.len - 1 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + if( ext->val.p[0] != 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( p, start, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, ext->oid.p, + ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, ext->oid.len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +/* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING + * -- contains the DER encoding of an ASN.1 value + * -- corresponding to the extension type identified + * -- by extnID + * } + */ +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + mbedtls_asn1_named_data *cur_ext = first; + + while( cur_ext != NULL ) + { + MBEDTLS_ASN1_CHK_ADD( len, x509_write_extension( p, start, cur_ext ) ); + cur_ext = cur_ext->next; + } + + return( (int) len ); +} + +#endif /* MBEDTLS_X509_CREATE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509_crl.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509_crl.c new file mode 100644 index 00000000..e6efdca5 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509_crl.c @@ -0,0 +1,770 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *p == end ) + return( 0 ); + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + return( ret ); + + end = ext->p + ext->len; + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + } + *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + cur_entry->raw.tag = **p; + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p = NULL, *end = NULL; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) && + ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len = 0; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509_crt.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509_crt.c new file mode 100644 index 00000000..2e824a3d --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509_crt.c @@ -0,0 +1,3393 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#if defined(__MBED__) +#include +#else +//#include +#endif // __MBED__ +#endif //!_WIN32 || EFIX64 || EFI32 +#endif + + +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/* Default profile. Do not remove items unless there are serious security + * concerns. */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ + /* Hashes from SHA-256 and above. Note that this selection + * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level. Note that this selection + * should be aligned with ssl_preset_default_curves in ssl_tls.c. */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + 0, +#else + 0, +#endif + 2048, +}; + +/* Next-generation profile. Currently identical to the default, but may + * be tightened at any time. */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above. */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level. */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Empty / all-forbidden profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_none = +{ + 0, + 0, + 0, + (uint32_t) -1, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + const mbedtls_pk_context *pk ) +{ + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = (uint32_t) -1; + } + + ver_chain->len = 0; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + ver_chain->trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, ret ) ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_DATE, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if( *max_pathlen == INT_MAX ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( bs.len != 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( bs.len < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_INVALID_LENGTH ) ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we list all types, but only use dNSName and otherName + * of type HwModuleName, as defined in RFC 4108, at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + while( *p < end ) + { + mbedtls_x509_subject_alternative_name dummy_san_buf; + memset( &dummy_san_buf, 0, sizeof( dummy_san_buf ) ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + /* + * Check that the SAN is structured correctly. + */ + ret = mbedtls_x509_parse_subject_alt_name( &(cur->buf), &dummy_san_buf ); + /* + * In case the extension is malformed, return an error, + * and clear the allocated sequences. + */ + if( ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + { + mbedtls_x509_sequence *seq_cur = subject_alt_name->next; + mbedtls_x509_sequence *seq_prv; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + subject_alt_name->next = NULL; + return( ret ); + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_ALLOC_FAILED ) ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + * + * anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } + * + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + * + * PolicyQualifierInfo ::= SEQUENCE { + * policyQualifierId PolicyQualifierId, + * qualifier ANY DEFINED BY policyQualifierId } + * + * -- policyQualifierIds for Internet policy qualifiers + * + * id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + * id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + * id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + * + * PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + * + * Qualifier ::= CHOICE { + * cPSuri CPSuri, + * userNotice UserNotice } + * + * CPSuri ::= IA5String + * + * UserNotice ::= SEQUENCE { + * noticeRef NoticeReference OPTIONAL, + * explicitText DisplayText OPTIONAL } + * + * NoticeReference ::= SEQUENCE { + * organization DisplayText, + * noticeNumbers SEQUENCE OF INTEGER } + * + * DisplayText ::= CHOICE { + * ia5String IA5String (SIZE (1..200)), + * visibleString VisibleString (SIZE (1..200)), + * bmpString BMPString (SIZE (1..200)), + * utf8String UTF8String (SIZE (1..200)) } + * + * NOTE: we only parse and use anyPolicy without qualifiers at this point + * as defined in RFC 5280. + */ +static int x509_get_certificate_policies( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *certificate_policies ) +{ + int ret, parse_ret = 0; + size_t len; + mbedtls_asn1_buf *buf; + mbedtls_asn1_sequence *cur = certificate_policies; + + /* Get main sequence tag */ + ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Cannot be an empty sequence. + */ + if( len == 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + while( *p < end ) + { + mbedtls_x509_buf policy_oid; + const unsigned char *policy_end; + + /* + * Get the policy sequence + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + policy_end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + policy_oid.tag = MBEDTLS_ASN1_OID; + policy_oid.len = len; + policy_oid.p = *p; + + /* + * Only AnyPolicy is currently supported when enforcing policy. + */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_POLICY, &policy_oid ) != 0 ) + { + /* + * Set the parsing return code but continue parsing, in case this + * extension is critical. + */ + parse_ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_ALLOC_FAILED ) ); + + cur = cur->next; + } + + buf = &( cur->buf ); + buf->tag = policy_oid.tag; + buf->p = policy_oid.p; + buf->len = policy_oid.len; + + *p += len; + + /* + * If there is an optional qualifier, then *p < policy_end + * Check the Qualifier len to verify it doesn't exceed policy_end. + */ + if( *p < policy_end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, policy_end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + /* + * Skip the optional policy qualifiers. + */ + *p += len; + } + + if( *p != policy_end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( parse_ret ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *end_ext_data, *start_ext_octet, *end_ext_octet; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + return( ret ); + + end = crt->v3_ext.p + crt->v3_ext.len; + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + end_ext_data = *p + len; + + /* Get extension ID */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + start_ext_octet = *p; + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* Give the callback (if any) a chance to handle the extension */ + if( cb != NULL ) + { + ret = cb( p_ctx, crt, &extn_oid, is_critical, *p, end_ext_octet ); + if( ret != 0 && is_critical ) + return( ret ); + *p = end_ext_octet; + continue; + } + + /* No parser found, skip extension */ + *p = end_ext_octet; + + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES: + /* Parse certificate policies type */ + if( ( ret = x509_get_certificate_policies( p, end_ext_octet, + &crt->certificate_policies ) ) != 0 ) + { + /* Give the callback (if any) a chance to handle the extension + * if it contains unsupported policies */ + if( ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE && cb != NULL && + cb( p_ctx, crt, &extn_oid, is_critical, + start_ext_octet, end_ext_octet ) == 0 ) + break; + + if( is_critical ) + return( ret ); + else + /* + * If MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE is returned, then we + * cannot interpret or enforce the policy. However, it is up to + * the user to choose how to enforce the policies, + * unless the extension is critical. + */ + if( ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + return( ret ); + } + break; + + default: + /* + * If this is a non-critical extension, which the oid layer + * supports, but there isn't an x509 parser for it, + * skip the extension. + */ + if( is_critical ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + else + *p = end_ext_octet; + } + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* Use the original buffer until we figure out actual length. */ + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + end = crt_end = p + len; + crt->raw.len = crt_end - buf; + if( make_copy != 0 ) + { + /* Create and populate a new buffer for the raw field. */ + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( crt->raw.p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( crt->raw.p, buf, crt->raw.len ); + crt->own_buffer = 1; + + p += crt->raw.len - len; + end = crt_end = p + len; + } + else + { + crt->raw.p = (unsigned char*) buf; + crt->own_buffer = 0; + } + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + crt->pk_raw.p = p; + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + crt->pk_raw.len = p - crt->pk_raw.p; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 3 ) + { + ret = x509_get_crt_ext( &p, end, crt, cb, p_ctx ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.tag != sig_params2.tag || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + ret = x509_crt_parse_der_core( crt, buf, buflen, make_copy, cb, p_ctx ); + if( ret != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +int mbedtls_x509_crt_parse_der_nocopy( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 0, NULL, NULL ) ); +} + +int mbedtls_x509_crt_parse_der_with_ext_cb( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen, + int make_copy, + mbedtls_x509_crt_ext_cb_t cb, + void *p_ctx ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, make_copy, cb, p_ctx ) ); +} + +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ + return( mbedtls_x509_crt_parse_der_internal( chain, buf, buflen, 1, NULL, NULL ) ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, + const unsigned char *buf, + size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + memset( &sb, 0, sizeof( sb ) ); + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * HardwareModuleName ::= SEQUENCE { + * hwType OBJECT IDENTIFIER, + * hwSerialNum OCTET STRING } + * + * NOTE: we currently only parse and use otherName of type HwModuleName, + * as defined in RFC 4108. + */ +static int x509_get_other_name( const mbedtls_x509_buf *subject_alt_name, + mbedtls_x509_san_other_name *other_name ) +{ + int ret = 0; + size_t len; + unsigned char *p = subject_alt_name->p; + const unsigned char *end = p + subject_alt_name->len; + mbedtls_x509_buf cur_oid; + + if( ( subject_alt_name->tag & + ( MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK ) ) != + ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ) ) + { + /* + * The given subject alternative name is not of type "othername". + */ + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + cur_oid.tag = MBEDTLS_ASN1_OID; + cur_oid.p = p; + cur_oid.len = len; + + /* + * Only HwModuleName is currently supported. + */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid ) != 0 ) + { + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + + if( p + len >= end ) + { + mbedtls_platform_zeroize( other_name, sizeof( *other_name ) ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + p += len; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID; + other_name->value.hardware_module_name.oid.p = p; + other_name->value.hardware_module_name.oid.len = len; + + if( p + len >= end ) + { + mbedtls_platform_zeroize( other_name, sizeof( *other_name ) ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + p += len; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret ) ); + + other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING; + other_name->value.hardware_module_name.val.p = p; + other_name->value.hardware_module_name.val.len = len; + p += len; + if( p != end ) + { + mbedtls_platform_zeroize( other_name, + sizeof( *other_name ) ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_EXTENSIONS, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + return( 0 ); +} + +int mbedtls_x509_parse_subject_alt_name( const mbedtls_x509_buf *san_buf, + mbedtls_x509_subject_alternative_name *san ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + switch( san_buf->tag & + ( MBEDTLS_ASN1_TAG_CLASS_MASK | + MBEDTLS_ASN1_TAG_VALUE_MASK ) ) + { + /* + * otherName + */ + case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME ): + { + mbedtls_x509_san_other_name other_name; + + ret = x509_get_other_name( san_buf, &other_name ); + if( ret != 0 ) + return( ret ); + + memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) ); + san->type = MBEDTLS_X509_SAN_OTHER_NAME; + memcpy( &san->san.other_name, + &other_name, sizeof( other_name ) ); + + } + break; + + /* + * dNSName + */ + case( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME ): + { + memset( san, 0, sizeof( mbedtls_x509_subject_alternative_name ) ); + san->type = MBEDTLS_X509_SAN_DNS_NAME; + + memcpy( &san->san.unstructured_name, + san_buf, sizeof( *san_buf ) ); + + } + break; + + /* + * Type not supported + */ + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + return( 0 ); +} + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence + *subject_alt_name, + const char *prefix ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + mbedtls_x509_subject_alternative_name san; + int parse_ret; + + while( cur != NULL ) + { + memset( &san, 0, sizeof( san ) ); + parse_ret = mbedtls_x509_parse_subject_alt_name( &cur->buf, &san ); + if( parse_ret != 0 ) + { + if( parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ) + { + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + else + { + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + cur = cur->next; + continue; + } + + switch( san.type ) + { + /* + * otherName + */ + case MBEDTLS_X509_SAN_OTHER_NAME: + { + mbedtls_x509_san_other_name *other_name = &san.san.other_name; + + ret = mbedtls_snprintf( p, n, "\n%s otherName :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ON_HW_MODULE_NAME, + &other_name->value.hardware_module_name.oid ) != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%s hardware module name :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "\n%s hardware type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_oid_get_numeric_string( p, n, &other_name->value.hardware_module_name.oid ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%s hardware serial number : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( other_name->value.hardware_module_name.val.len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + memcpy( p, other_name->value.hardware_module_name.val.p, + other_name->value.hardware_module_name.val.len ); + p += other_name->value.hardware_module_name.val.len; + + n -= other_name->value.hardware_module_name.val.len; + + }/* MBEDTLS_OID_ON_HW_MODULE_NAME */ + } + break; + + /* + * dNSName + */ + case MBEDTLS_X509_SAN_DNS_NAME: + { + ret = mbedtls_snprintf( p, n, "\n%s dNSName : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + if( san.san.unstructured_name.len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + memcpy( p, san.san.unstructured_name.p, san.san.unstructured_name.len ); + p += san.san.unstructured_name.len; + n -= san.san.unstructured_name.len; + } + break; + + /* + * Type not supported, skip item. + */ + default: + ret = mbedtls_snprintf( p, n, "\n%s ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + break; + } + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & (type) ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & (code) ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_cert_policies( char **buf, size_t *size, + const mbedtls_x509_sequence *certificate_policies ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = certificate_policies; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_certificate_policies( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name :", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names, + prefix ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES ) + { + ret = mbedtls_snprintf( p, n, "\n%scertificate policies : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_policies( &p, &n, + &crt->certificate_policies ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +#define X509_CRT_ERROR_INFO( err, err_str, info ) { err, info }, +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + MBEDTLS_X509_CRT_ERROR_INFO_LIST + { 0, NULL } +}; +#undef X509_CRT_ERROR_INFO + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} + +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ + if( mbedtls_x509_crt_check_key_usage( ca, + MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + size_t hash_len; +#if !defined(MBEDTLS_USE_PSA_CRYPTO) + const mbedtls_md_info_t *md_info; + md_info = mbedtls_md_info_from_type( child->sig_md ); + hash_len = mbedtls_md_get_size( md_info ); + + /* Note: hash errors can happen only after an internal error */ + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + return( -1 ); +#else + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( child->sig_md ); + + if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) + return( -1 ); + + if( psa_hash_update( &hash_operation, child->tbs.p, child->tbs.len ) + != PSA_SUCCESS ) + { + return( -1 ); + } + + if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) + != PSA_SUCCESS ) + { + return( -1 ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) + return( -1 ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) + { + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len, &rs_ctx->pk ) ); + } +#else + (void) rs_ctx; +#endif + + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, hash_len, + child->sig.p, child->sig.len ) ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } + + return( 0 ); +} + +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [out] r_parent: parent found (or NULL) + * - [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good = 0, fallback_signature_is_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* did we have something in progress? */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) + { + /* restore saved state */ + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; + + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_signature_is_good = 0; + + /* resume where we left */ + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_signature_is_good = 0; + + for( parent = candidates; parent != NULL; parent = parent->next ) + { + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) + continue; + + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) + { + continue; + } + + /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; + + return( ret ); + } +#else + (void) ret; +#endif + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) + continue; + + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) + { + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_signature_is_good = signature_is_good; + } + + continue; + } + + *r_parent = parent; + *r_signature_is_good = signature_is_good; + + break; + } + + if( parent == NULL ) + { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_signature_is_good; + } + + return( 0 ); +} + +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: list of locally trusted certificates + * - [out] parent: parent found (or NULL) + * - [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * - [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * - [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * - [in] self_cnt: number of self-signed certs in the chain so far + * (will always be no greater than path_cnt) + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - 0 on success + * - MBEDTLS_ERR_ECP_IN_PROGRESS otherwise + */ +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + unsigned path_cnt, + unsigned self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_x509_crt *search_list; + + *parent_is_trusted = 1; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { + *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } +#endif + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; + return( ret ); + } +#else + (void) ret; +#endif + + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; + + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( *parent == NULL ) + { + *parent_is_trusted = 0; + *signature_is_good = 0; + } + + return( 0 ); +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) + { + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } + } + + /* too bad */ + return( -1 ); +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermediate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. + * - [in-out] rs_ctx: context for restarting operations + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + mbedtls_x509_crt_verify_chain *ver_chain, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + unsigned self_cnt; + mbedtls_x509_crt *cur_trust_ca = NULL; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) + { + /* restore saved state */ + *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + + /* restore derived state */ + cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; + + while( 1 ) { + /* Add certificate to the verification chain */ + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + cur->flags = 0; + ver_chain->len++; + flags = &cur->flags; + + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); + + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* Special case: EE certs that are locally trusted */ + if( ver_chain->len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif + + /* Obtain list of potential trusted signers from CA callback, + * or use statically provided list. */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( f_ca_cb != NULL ) + { + mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result ); + mbedtls_free( ver_chain->trust_ca_cb_result ); + ver_chain->trust_ca_cb_result = NULL; + + ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + cur_trust_ca = ver_chain->trust_ca_cb_result; + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + ((void) f_ca_cb); + ((void) p_ca_cb); + cur_trust_ca = trust_ca; + } + + /* Look for a parent in trusted CAs or up the chain */ + ret = x509_crt_find_parent( child, cur_trust_ca, &parent, + &parent_is_trusted, &signature_is_good, + ver_chain->len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->in_progress = x509_crt_rs_find_parent; + rs_ctx->self_cnt = self_cnt; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ + + return( ret ); + } +#else + (void) ret; +#endif + + /* No parent? We're done here */ + if( parent == NULL ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( ver_chain->len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* signature was checked while searching parent */ + if( ! signature_is_good ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + signature_is_good = 0; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + { + return( 0 ); + } + + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Check for SAN match, see RFC 5280 Section 4.2.1.6 + */ +static int x509_crt_check_san( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + const unsigned char san_type = (unsigned char) name->tag & + MBEDTLS_ASN1_TAG_VALUE_MASK; + + /* dNSName */ + if( san_type == MBEDTLS_X509_SAN_DNS_NAME ) + return( x509_crt_check_cn( name, cn, cn_len ) ); + + /* (We may handle other types here later.) */ + + /* Unrecognized type */ + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) + { + if( x509_crt_check_san( &cur->buf, cn, cn_len ) == 0 ) + break; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + const mbedtls_x509_crt_verify_chain *ver_chain, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned i; + uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; + + for( i = ver_chain->len; i != 0; --i ) + { + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); + + *flags |= cur_flags; + } + + return( 0 ); +} + +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + * + * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` + * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the + * verification routine to search for trusted signers, and CRLs will + * be disabled. Otherwise, `trust_ca` will be used as the static list + * of trusted signers, and `ca_crl` will be use as the static list + * of CRLs. + */ +static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_pk_type_t pk_type; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t ee_flags; + + *flags = 0; + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + /* check name if requested */ + if( cn != NULL ) + x509_crt_verify_name( crt, cn, &ee_flags ); + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, + f_ca_cb, p_ca_cb, profile, + &ver_chain, rs_ctx ); + + if( ret != 0 ) + goto exit; + + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); + +exit: + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result ); + mbedtls_free( ver_chain.trust_ca_cb_result ); + ver_chain.trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + + +/* + * Verify the certificate validity (default profile, not restartable) + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + &mbedtls_x509_crt_profile_default, + cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/* + * Verify the certificate validity (user-chosen profile, CA callback, + * not restartable). + */ +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL, + f_ca_cb, p_ca_cb, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, rs_ctx ) ); +} + + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->certificate_policies.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL && cert_cur->own_buffer ) + { + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_pk_restart_init( &ctx->pk ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_signature_is_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->in_progress = x509_crt_rs_none; + ctx->self_cnt = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_pk_restart_free( &ctx->pk ); + mbedtls_x509_crt_restart_init( ctx ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509_csr.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509_csr.c new file mode 100644 index 00000000..25069b2a --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509_csr.c @@ -0,0 +1,416 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0) } + */ +static int x509_csr_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_VERSION, ret ) ); + } + + return( 0 ); +} + +/* + * Parse a CSR in DER format + */ +int mbedtls_x509_csr_parse_der( mbedtls_x509_csr *csr, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + unsigned char *p, *end; + mbedtls_x509_buf sig_params; + + memset( &sig_params, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + mbedtls_x509_csr_init( csr ); + + /* + * first copy the raw DER data + */ + p = mbedtls_calloc( 1, len = buflen ); + + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + csr->raw.p = p; + csr->raw.len = len; + end = p + len; + + /* + * CertificationRequest ::= SEQUENCE { + * certificationRequestInfo CertificationRequestInfo, + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + /* + * CertificationRequestInfo ::= SEQUENCE { + */ + csr->cri.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + end = p + len; + csr->cri.len = end - csr->cri.p; + + /* + * Version ::= INTEGER { v1(0) } + */ + if( ( ret = x509_csr_get_version( &p, end, &csr->version ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( csr->version != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + csr->version++; + + /* + * subject Name + */ + csr->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &csr->subject ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + csr->subject_raw.len = p - csr->subject_raw.p; + + /* + * subjectPKInfo SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &csr->pk ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + /* + * attributes [0] Attributes + * + * The list of possible attributes is open-ended, though RFC 2985 + * (PKCS#9) defines a few in section 5.4. We currently don't support any, + * so we just ignore them. This is a safe thing to do as the worst thing + * that could happen is that we issue a certificate that does not match + * the requester's expectations - this cannot cause a violation of our + * signature policies. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, ret ) ); + } + + p += len; + + end = csr->raw.p + csr->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signature BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &csr->sig_oid, &sig_params ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_sig_alg( &csr->sig_oid, &sig_params, + &csr->sig_md, &csr->sig_pk, + &csr->sig_opts ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &csr->sig ) ) != 0 ) + { + mbedtls_x509_csr_free( csr ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_csr_free( csr ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_X509_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + } + + return( 0 ); +} + +/* + * Parse a CSR, allowing for PEM or raw DER encoding + */ +int mbedtls_x509_csr_parse( mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t use_len; + mbedtls_pem_context pem; +#endif + + /* + * Check for valid input + */ + if( csr == NULL || buf == NULL || buflen == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_PEM_PARSE_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN NEW CERTIFICATE REQUEST-----", + "-----END NEW CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + } + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); + } + + mbedtls_pem_free( &pem ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_csr_parse_der( csr, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load a CSR into the structure + */ +int mbedtls_x509_csr_parse_file( mbedtls_x509_csr *csr, const char *path ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_csr_parse( csr, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CSR. + */ +int mbedtls_x509_csr_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_csr *csr ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCSR version : %d", + prefix, csr->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &csr->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md, + csr->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &csr->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &csr->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ + +/* + * Initialize a CSR + */ +void mbedtls_x509_csr_init( mbedtls_x509_csr *csr ) +{ + memset( csr, 0, sizeof(mbedtls_x509_csr) ); +} + +/* + * Unallocate all CSR data + */ +void mbedtls_x509_csr_free( mbedtls_x509_csr *csr ) +{ + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + + if( csr == NULL ) + return; + + mbedtls_pk_free( &csr->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( csr->sig_opts ); +#endif + + name_cur = csr->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + if( csr->raw.p != NULL ) + { + mbedtls_platform_zeroize( csr->raw.p, csr->raw.len ); + mbedtls_free( csr->raw.p ); + } + + mbedtls_platform_zeroize( csr, sizeof( mbedtls_x509_csr ) ); +} + +#endif /* MBEDTLS_X509_CSR_PARSE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509write_crt.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509write_crt.c new file mode 100644 index 00000000..17b3e796 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509write_crt.c @@ -0,0 +1,543 @@ +/* + * X.509 certificate writing + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * References: + * - certificates: RFC 5280, updated by RFC 6818 + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_cert ) ); + + mbedtls_mpi_init( &ctx->serial ); + ctx->version = MBEDTLS_X509_CRT_VERSION_3; +} + +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ) +{ + mbedtls_mpi_free( &ctx->serial ); + + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->issuer ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_cert ) ); +} + +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, + int version ) +{ + ctx->version = version; +} + +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, + mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->subject_key = key; +} + +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, + mbedtls_pk_context *key ) +{ + ctx->issuer_key = key; +} + +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ) +{ + return mbedtls_x509_string_to_names( &ctx->issuer, issuer_name ); +} + +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, + const mbedtls_mpi *serial ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_mpi_copy( &ctx->serial, serial ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, + const char *not_before, + const char *not_after ) +{ + if( strlen( not_before ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 || + strlen( not_after ) != MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1 ) + { + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + } + strncpy( ctx->not_before, not_before, MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + strncpy( ctx->not_after , not_after , MBEDTLS_X509_RFC5280_UTC_TIME_LEN ); + ctx->not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + ctx->not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN - 1] = 'Z'; + + return( 0 ); +} + +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return( mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ) ); +} + +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[9]; + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + + if( is_ca && max_pathlen > 127 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( is_ca ) + { + if( max_pathlen >= 0 ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, + max_pathlen ) ); + } + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_bool( &c, buf, 1 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( + mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_BASIC_CONSTRAINTS, + MBEDTLS_OID_SIZE( MBEDTLS_OID_BASIC_CONSTRAINTS ), + is_ca, buf + sizeof(buf) - len, len ) ); +} + +#if defined(MBEDTLS_SHA1_C) +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof(buf); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->subject_key ) ); + + ret = mbedtls_sha1( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_OCTET_STRING ) ); + + return mbedtls_x509write_crt_set_extension( ctx, + MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), + 0, buf + sizeof(buf) - len, len ); +} + +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE * 2 + 20]; /* tag, length + 2xMPI */ + unsigned char *c = buf + sizeof( buf ); + size_t len = 0; + + memset( buf, 0, sizeof(buf) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_pk_write_pubkey( &c, buf, ctx->issuer_key ) ); + + ret = mbedtls_sha1( buf + sizeof( buf ) - len, len, + buf + sizeof( buf ) - 20 ); + if( ret != 0 ) + return( ret ); + c = buf + sizeof( buf ) - 20; + len = 20; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return mbedtls_x509write_crt_set_extension( + ctx, MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER, + MBEDTLS_OID_SIZE( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), + 0, buf + sizeof( buf ) - len, len ); +} +#endif /* MBEDTLS_SHA1_C */ + +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ) +{ + unsigned char buf[5] = {0}, ku[2] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | + MBEDTLS_X509_KU_NON_REPUDIATION | + MBEDTLS_X509_KU_KEY_ENCIPHERMENT | + MBEDTLS_X509_KU_DATA_ENCIPHERMENT | + MBEDTLS_X509_KU_KEY_AGREEMENT | + MBEDTLS_X509_KU_KEY_CERT_SIGN | + MBEDTLS_X509_KU_CRL_SIGN | + MBEDTLS_X509_KU_ENCIPHER_ONLY | + MBEDTLS_X509_KU_DECIPHER_ONLY; + + /* Check that nothing other than the allowed flags is set */ + if( ( key_usage & ~allowed_bits ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 5; + MBEDTLS_PUT_UINT16_LE( key_usage, ku, 0 ); + ret = mbedtls_asn1_write_named_bitstring( &c, buf, ku, 9 ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 5 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509_write_time( unsigned char **p, unsigned char *start, + const char *t, size_t size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + + /* + * write MBEDTLS_ASN1_UTC_TIME if year < 2050 (2 bytes shorter) + */ + if( t[0] == '2' && t[1] == '0' && t[2] < '5' ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t + 2, + size - 2 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_UTC_TIME ) ); + } + else + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) t, + size ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_GENERALIZED_TIME ) ); + } + + return( (int) len ); +} + +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE]; + size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; + + /* + * Prepare data to be signed at the end of the target buffer + */ + c = buf + size; + + /* Signature algorithm needed in TBS, and later for actual signature */ + + /* There's no direct way of extracting a signature algorithm + * (represented as an element of mbedtls_pk_type_t) from a PK instance. */ + if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->issuer_key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + + /* Only for v3 */ + if( ctx->version == MBEDTLS_X509_CRT_VERSION_3 ) + { + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_extensions( &c, + buf, ctx->extensions ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3 ) ); + } + + /* + * SubjectPublicKeyInfo + */ + MBEDTLS_ASN1_CHK_ADD( pub_len, + mbedtls_pk_write_pubkey_der( ctx->subject_key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ + sub_len = 0; + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_after, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + MBEDTLS_ASN1_CHK_ADD( sub_len, + x509_write_time( &c, buf, ctx->not_before, + MBEDTLS_X509_RFC5280_UTC_TIME_LEN ) ); + + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Issuer ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->issuer ) ); + + /* + * Signature ::= AlgorithmIdentifier + */ + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_algorithm_identifier( &c, buf, + sig_oid, strlen( sig_oid ), 0 ) ); + + /* + * Serial ::= INTEGER + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, + &ctx->serial ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + + /* Can be omitted for v1 */ + if( ctx->version != MBEDTLS_X509_CRT_VERSION_1 ) + { + sub_len = 0; + MBEDTLS_ASN1_CHK_ADD( sub_len, + mbedtls_asn1_write_int( &c, buf, ctx->version ) ); + len += sub_len; + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_len( &c, buf, sub_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Make signature + */ + + /* Compute hash of CRT. */ + if( ( ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, + len, hash ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pk_sign( ctx->issuer_key, ctx->md_alg, + hash, 0, sig, sizeof( sig ), &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + /* Move CRT to the front of the buffer to have space + * for the signature. */ + memmove( buf, c, len ); + c = buf + len; + + /* Add signature at the end of the buffer, + * making sure that it doesn't underflow + * into the CRT buffer. */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, c, + sig_oid, sig_oid_len, sig, sig_len ) ); + + /* + * Memory layout after this step: + * + * buf c=buf+len c2 buf+size + * [CRT0,...,CRTn, UNUSED, ..., UNUSED, SIG0, ..., SIGm] + */ + + /* Move raw CRT to just before the signature. */ + c = c2 - len; + memmove( c, buf, len ); + + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +#define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" +#define PEM_END_CRT "-----END CERTIFICATE-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *crt, + unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + + if( ( ret = mbedtls_x509write_crt_der( crt, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CRT, PEM_END_CRT, + buf + size - ret, ret, + buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CRT_WRITE_C */ diff --git a/component/common/network/ssl/mbedtls-3.1.0/library/x509write_csr.c b/component/common/network/ssl/mbedtls-3.1.0/library/x509write_csr.c new file mode 100644 index 00000000..555f2963 --- /dev/null +++ b/component/common/network/ssl/mbedtls-3.1.0/library/x509write_csr.c @@ -0,0 +1,345 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright The Mbed TLS Contributors + * 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. + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#include "common.h" + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx ) +{ + mbedtls_asn1_free_named_data_list( &ctx->subject ); + mbedtls_asn1_free_named_data_list( &ctx->extensions ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) ); +} + +void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg ) +{ + ctx->md_alg = md_alg; +} + +void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key ) +{ + ctx->key = key; +} + +int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx, + const char *subject_name ) +{ + return mbedtls_x509_string_to_names( &ctx->subject, subject_name ); +} + +int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ) +{ + return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len, + critical, val, val_len ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 0, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx, + unsigned char ns_cert_type ) +{ + unsigned char buf[4] = {0}; + unsigned char *c; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + c = buf + 4; + + ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); + if( ret != 0 ) + return( ret ); + + return( 0 ); +} + +static int x509write_csr_der_internal( mbedtls_x509write_csr *ctx, + unsigned char *buf, + size_t size, + unsigned char *sig, size_t sig_size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const char *sig_oid; + size_t sig_oid_len = 0; + unsigned char *c, *c2; + unsigned char hash[64]; + size_t pub_len = 0, sig_and_oid_len = 0, sig_len; + size_t len = 0; + mbedtls_pk_type_t pk_alg; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT; + size_t hash_len; + psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* Write the CSR backwards starting from the end of buf */ + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, buf, + ctx->extensions ) ); + + if( len ) + { + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ); + + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_oid( + &c, buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ, + MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key, + buf, c - buf ) ); + c -= pub_len; + len += pub_len; + + /* + * Subject ::= Name + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, buf, + ctx->subject ) ); + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* + * Sign the written CSR data into the sig buffer + * Note: hash errors can happen only after an internal error + */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len ) + != PSA_SUCCESS ) + { + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } +#else /* MBEDTLS_USE_PSA_CRYPTO */ + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); +#endif + if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, + sig, sig_size, &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } + + if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) ) + pk_alg = MBEDTLS_PK_RSA; + else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) ) + pk_alg = MBEDTLS_PK_ECDSA; + else + return( MBEDTLS_ERR_X509_INVALID_ALG ); + + if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, + &sig_oid, &sig_oid_len ) ) != 0 ) + { + return( ret ); + } + + /* + * Move the written CSR data to the start of buf to create space for + * writing the signature into buf. + */ + memmove( buf, c, len ); + + /* + * Write sig and its OID into buf backwards from the end of buf. + * Note: mbedtls_x509_write_sig will check for c2 - ( buf + len ) < sig_len + * and return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if needed. + */ + c2 = buf + size; + MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, + mbedtls_x509_write_sig( &c2, buf + len, sig_oid, sig_oid_len, + sig, sig_len ) ); + + /* + * Compact the space between the CSR data and signature by moving the + * CSR data to the start of the signature. + */ + c2 -= len; + memmove( c2, buf, len ); + + /* ASN encode the total size and tag the CSR data with it. */ + len += sig_and_oid_len; + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, + mbedtls_asn1_write_tag( + &c2, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + /* Zero the unused bytes at the start of buf */ + memset( buf, 0, c2 - buf); + + return( (int) len ); +} + +int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, + size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char *sig; + + if( ( sig = mbedtls_calloc( 1, MBEDTLS_PK_SIGNATURE_MAX_SIZE ) ) == NULL ) + { + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + ret = x509write_csr_der_internal( ctx, buf, size, + sig, MBEDTLS_PK_SIGNATURE_MAX_SIZE, + f_rng, p_rng ); + + mbedtls_free( sig ); + + return( ret ); +} + +#define PEM_BEGIN_CSR "-----BEGIN CERTIFICATE REQUEST-----\n" +#define PEM_END_CSR "-----END CERTIFICATE REQUEST-----\n" + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen = 0; + + if( ( ret = mbedtls_x509write_csr_der( ctx, buf, size, + f_rng, p_rng ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR, + buf + size - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_X509_CSR_WRITE_C */ diff --git a/component/common/network/ssl/ssl_func_stubs/rom/rom_ssl_func_stubs.h b/component/common/network/ssl/ssl_func_stubs/rom/rom_ssl_func_stubs.h index 2d7b5d13..a4565076 100644 --- a/component/common/network/ssl/ssl_func_stubs/rom/rom_ssl_func_stubs.h +++ b/component/common/network/ssl/ssl_func_stubs/rom/rom_ssl_func_stubs.h @@ -1,6 +1,6 @@ #ifndef ROM_SSL_FUNC_STUBS_H #define ROM_SSL_FUNC_STUBS_H - +#include "platform_opts.h" #include "mbedtls/bignum.h" #include "mbedtls/ecp.h" #include "mbedtls/sha1.h" @@ -16,11 +16,11 @@ #include "mbedtls/pem.h" #include "mbedtls/dhm.h" #include "mbedtls/ecjpake.h" -#include "mbedtls/arc4.h" #include "mbedtls/ecdh.h" #include "mbedtls/ecdsa.h" #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" +#include "mbedtls/arc4.h" #if defined(CONFIG_PLATFORM_8710C) && defined(CONFIG_BUILD_SECURE) && (CONFIG_BUILD_SECURE == 1) typedef struct ssl_func_stubs_s { diff --git a/component/common/network/websocket/wsclient_tls.c b/component/common/network/websocket/wsclient_tls.c index 4dde757a..af2e081e 100644 --- a/component/common/network/websocket/wsclient_tls.c +++ b/component/common/network/websocket/wsclient_tls.c @@ -130,10 +130,13 @@ void *wss_tls_connect(int *sock , char *host, int port){ mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(conf, ws_random, NULL); +#if (defined(MBEDTLS_SSL_IN_CONTENT_LEN) && (MBEDTLS_SSL_IN_CONTENT_LEN == 4096)) || \ + (defined(MBEDTLS_SSL_MAX_CONTENT_LEN) && (MBEDTLS_SSL_MAX_CONTENT_LEN == 4096)) if(ret = mbedtls_ssl_conf_max_frag_len(conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { printf("\n[WSCLIENT] ERROR: mbedtls_ssl_conf_max_frag_len %d\n", ret); goto exit; } +#endif if((ret = mbedtls_ssl_setup(ssl, conf)) != 0) { printf("\n[WSCLIENT] ERROR: ssl_setup %d\n", ret); diff --git a/component/common/network/websocket/wsserver_tls.c b/component/common/network/websocket/wsserver_tls.c index ea62d3ab..b7cc3e5d 100644 --- a/component/common/network/websocket/wsserver_tls.c +++ b/component/common/network/websocket/wsserver_tls.c @@ -149,7 +149,6 @@ int ws_server_tls_setup_init(const char *server_cert, const char *server_key, co ret = -1; goto exit; } - if((ret = mbedtls_pk_parse_key(&wss_key, (const unsigned char *) server_key, strlen(server_key) + 1, NULL, 0)) != 0) { printf("\n[WS_SERVER] ERROR: mbedtls_pk_parse_key %d\n", ret); ret = -1; diff --git a/component/common/utilities/ssl_client.c b/component/common/utilities/ssl_client.c index dd087424..72626240 100644 --- a/component/common/utilities/ssl_client.c +++ b/component/common/utilities/ssl_client.c @@ -1,8 +1,6 @@ -#include "FreeRTOS.h" -#include "task.h" +#include "osdep_service.h" #include #include - #include "platform_opts.h" #include "osdep_service.h" @@ -388,6 +386,13 @@ static void ssl_client(void *param) mbedtls_ssl_conf_rng(&conf, my_random, NULL); mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); +#if MBEDTLS_SSL_MAX_CONTENT_LEN == 4096 + if(ret = mbedtls_ssl_conf_max_frag_len(&conf, MBEDTLS_SSL_MAX_FRAG_LEN_4096) < 0) { + printf(" failed\n\r ! mbedtls_ssl_conf_max_frag_len %d\n", ret); + goto exit; + } +#endif + #ifdef SSL_CLIENT_EXT if((ret = ssl_client_ext_setup(&conf)) != 0) { printf(" failed\n\r ! ssl_client_ext_setup returned %d\n", ret); diff --git a/component/common/utilities/ssl_client_ext.c b/component/common/utilities/ssl_client_ext.c index 23ef33be..bfb59391 100644 --- a/component/common/utilities/ssl_client_ext.c +++ b/component/common/utilities/ssl_client_ext.c @@ -1,4 +1,4 @@ -#include "FreeRTOS.h" +#include "osdep_service.h" #include "platform_opts.h" #if CONFIG_USE_POLARSSL diff --git a/component/common/utilities/uart_ymodem.h b/component/common/utilities/uart_ymodem.h index b5cbb846..2445efba 100644 --- a/component/common/utilities/uart_ymodem.h +++ b/component/common/utilities/uart_ymodem.h @@ -8,6 +8,7 @@ #include "serial_api.h" #include "flash_api.h" #include "device_lock.h" +#include "platform_opts.h" /*********************************************************************** * Macros * ***********************************************************************/ @@ -15,6 +16,11 @@ // 8710B #define UART_TX PA_23 #define UART_RX PA_18 +#elif defined(CONFIG_PLATFORM_8710C) +//8710C +#define UART_TX PA_14 +#define UART_RX PA_13 +// 8711AM #else // 8711AM #define UART_TX PA_7 diff --git a/component/os/freertos/freertos_v10.2.0/Source/queue.c b/component/os/freertos/freertos_v10.2.0/Source/queue.c new file mode 100644 index 00000000..ba90656e --- /dev/null +++ b/component/os/freertos/freertos_v10.2.0/Source/queue.c @@ -0,0 +1,2947 @@ +/* + * FreeRTOS Kernel V10.2.0 + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +#if ( configUSE_CO_ROUTINES == 1 ) + #include "croutine.h" +#endif + +/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified +because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +for the header files above, but not in this file, in order to generate the +correct privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ + + +/* Constants used with the cRxLock and cTxLock structure members. */ +#define queueUNLOCKED ( ( int8_t ) -1 ) +#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) + +/* When the Queue_t structure is used to represent a base queue its pcHead and +pcTail members are used as pointers into the queue storage area. When the +Queue_t structure is used to represent a mutex pcHead and pcTail pointers are +not necessary, and the pcHead pointer is set to NULL to indicate that the +structure instead holds a pointer to the mutex holder (if any). Map alternative +names to the pcHead and structure member to ensure the readability of the code +is maintained. The QueuePointers_t and SemaphoreData_t types are used to form +a union as their usage is mutually exclusive dependent on what the queue is +being used for. */ +#define uxQueueType pcHead +#define queueQUEUE_IS_MUTEX NULL + +typedef struct QueuePointers +{ + int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ + int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ +} QueuePointers_t; + +typedef struct SemaphoreData +{ + TaskHandle_t xMutexHolder; /*< The handle of the task that holds the mutex. */ + UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ +} SemaphoreData_t; + +/* Semaphores do not actually store or copy data, so have an item size of +zero. */ +#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) +#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + +#if( configUSE_PREEMPTION == 0 ) + /* If the cooperative scheduler is being used then a yield should not be + performed just because a higher priority task has been woken. */ + #define queueYIELD_IF_USING_PREEMPTION() +#else + #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() +#endif + +/* + * Definition of the queue used by the scheduler. + * Items are queued by copy, not reference. See the following link for the + * rationale: https://www.freertos.org/Embedded-RTOS-Queues.html + */ +typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */ +{ + int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ + int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ + + union + { + QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */ + SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */ + } u; + + List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ + List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ + + volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ + UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ + UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ + + volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ + + #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ + #endif + + #if ( configUSE_QUEUE_SETS == 1 ) + struct QueueDefinition *pxQueueSetContainer; + #endif + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxQueueNumber; + uint8_t ucQueueType; + #endif + +} xQUEUE; + +/* The old xQUEUE name is maintained above then typedefed to the new Queue_t +name below to enable the use of older kernel aware debuggers. */ +typedef xQUEUE Queue_t; + +/*-----------------------------------------------------------*/ + +/* + * The queue registry is just a means for kernel aware debuggers to locate + * queue structures. It has no other purpose so is an optional component. + */ +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + /* The type stored within the queue registry array. This allows a name + to be assigned to each queue making kernel aware debugging a little + more user friendly. */ + typedef struct QUEUE_REGISTRY_ITEM + { + const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + QueueHandle_t xHandle; + } xQueueRegistryItem; + + /* The old xQueueRegistryItem name is maintained above then typedefed to the + new xQueueRegistryItem name below to enable the use of older kernel aware + debuggers. */ + typedef xQueueRegistryItem QueueRegistryItem_t; + + /* The queue registry is simply an array of QueueRegistryItem_t structures. + The pcQueueName member of a structure being NULL is indicative of the + array position being vacant. */ + PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; + +#endif /* configQUEUE_REGISTRY_SIZE */ + +/* + * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not + * prevent an ISR from adding or removing items to the queue, but does prevent + * an ISR from removing tasks from the queue event lists. If an ISR finds a + * queue is locked it will instead increment the appropriate queue lock count + * to indicate that a task may require unblocking. When the queue in unlocked + * these lock counts are inspected, and the appropriate action taken. + */ +static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any data in a queue. + * + * @return pdTRUE if the queue contains no items, otherwise pdFALSE. + */ +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Uses a critical section to determine if there is any space in a queue. + * + * @return pdTRUE if there is no space, otherwise pdFALSE; + */ +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; + +/* + * Copies an item into the queue, either at the front of the queue or the + * back of the queue. + */ +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; + +/* + * Copies an item out of a queue. + */ +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; + +#if ( configUSE_QUEUE_SETS == 1 ) + /* + * Checks to see if a queue is a member of a queue set, and if so, notifies + * the queue set that the queue contains data. + */ + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION; +#endif + +/* + * Called after a Queue_t structure has been allocated either statically or + * dynamically to fill in the structure's members. + */ +static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; + +/* + * Mutexes are a special type of queue. When a mutex is created, first the + * queue is created, then prvInitialiseMutex() is called to configure the queue + * as a mutex. + */ +#if( configUSE_MUTEXES == 1 ) + static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; +#endif + +#if( configUSE_MUTEXES == 1 ) + /* + * If a task waiting for a mutex causes the mutex holder to inherit a + * priority, but the waiting task times out, then the holder should + * disinherit the priority - but only down to the highest priority of any + * other tasks that are waiting for the same mutex. This function returns + * that priority. + */ + static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; +#endif +/*-----------------------------------------------------------*/ + +/* + * Macro to mark a queue as locked. Locking a queue prevents an ISR from + * accessing the queue event lists. + */ +#define prvLockQueue( pxQueue ) \ + taskENTER_CRITICAL(); \ + { \ + if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ + } \ + if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ + { \ + ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ + } \ + } \ + taskEXIT_CRITICAL() +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) +{ +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; + pxQueue->pcWriteTo = pxQueue->pcHead; + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + pxQueue->cRxLock = queueUNLOCKED; + pxQueue->cTxLock = queueUNLOCKED; + + if( xNewQueue == pdFALSE ) + { + /* If there are tasks blocked waiting to read from the queue, then + the tasks will remain blocked as after this function exits the queue + will still be empty. If there are tasks blocked waiting to write to + the queue, then one should be unblocked as after this function exits + it will be possible to write to it. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Ensure the event queues start in the correct state. */ + vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); + vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); + } + } + taskEXIT_CRITICAL(); + + /* A value is returned for calling semantic consistency with previous + versions. */ + return pdPASS; +} +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + + /* The StaticQueue_t structure and the queue storage area must be + supplied. */ + configASSERT( pxStaticQueue != NULL ); + + /* A queue storage area should be provided if the item size is not 0, and + should not be provided if the item size is 0. */ + configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); + configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); + + #if( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + variable of type StaticQueue_t or StaticSemaphore_t equals the size of + the real queue and semaphore structures. */ + volatile size_t xSize = sizeof( StaticQueue_t ); + configASSERT( xSize == sizeof( Queue_t ) ); + ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ + } + #endif /* configASSERT_DEFINED */ + + /* The address of a statically allocated queue was passed in, use it. + The address of a statically allocated storage area was also passed in + but is already set. */ + pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ + + if( pxNewQueue != NULL ) + { + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Queues can be allocated wither statically or dynamically, so + note this queue was allocated statically in case the queue is + later deleted. */ + pxNewQueue->ucStaticallyAllocated = pdTRUE; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ + + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + mtCOVERAGE_TEST_MARKER(); + } + + return pxNewQueue; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) + { + Queue_t *pxNewQueue; + size_t xQueueSizeInBytes; + uint8_t *pucQueueStorage; + + configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); + + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* There is not going to be a queue storage area. */ + xQueueSizeInBytes = ( size_t ) 0; + } + else + { + /* Allocate enough space to hold the maximum number of items that + can be in the queue at any time. */ + xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ + } + + /* Check for multiplication overflow. */ + configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) ); + + /* Check for addition overflow. */ + configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes ); + + /* Allocate the queue and storage area. Justification for MISRA + deviation as follows: pvPortMalloc() always ensures returned memory + blocks are aligned per the requirements of the MCU stack. In this case + pvPortMalloc() must return a pointer that is guaranteed to meet the + alignment requirements of the Queue_t structure - which in this case + is an int8_t *. Therefore, whenever the stack alignment requirements + are greater than or equal to the pointer to char requirements the cast + is safe. In other cases alignment requirements are not strict (one or + two bytes). */ + pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ + + if( pxNewQueue != NULL ) + { + /* Jump past the queue structure to find the location of the queue + storage area. */ + pucQueueStorage = ( uint8_t * ) pxNewQueue; + pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ + + #if( configSUPPORT_STATIC_ALLOCATION == 1 ) + { + /* Queues can be created either statically or dynamically, so + note this task was created dynamically in case it is later + deleted. */ + pxNewQueue->ucStaticallyAllocated = pdFALSE; + } + #endif /* configSUPPORT_STATIC_ALLOCATION */ + + prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); + } + else + { + traceQUEUE_CREATE_FAILED( ucQueueType ); + mtCOVERAGE_TEST_MARKER(); + } + + return pxNewQueue; + } + +#endif /* configSUPPORT_STATIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) +{ + /* Remove compiler warnings about unused parameters should + configUSE_TRACE_FACILITY not be set to 1. */ + ( void ) ucQueueType; + + if( uxItemSize == ( UBaseType_t ) 0 ) + { + /* No RAM was allocated for the queue storage area, but PC head cannot + be set to NULL because NULL is used as a key to say the queue is used as + a mutex. Therefore just set pcHead to point to the queue as a benign + value that is known to be within the memory map. */ + pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; + } + else + { + /* Set the head to the start of the queue storage area. */ + pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; + } + + /* Initialise the queue members as described where the queue type is + defined. */ + pxNewQueue->uxLength = uxQueueLength; + pxNewQueue->uxItemSize = uxItemSize; + ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); + + #if ( configUSE_TRACE_FACILITY == 1 ) + { + pxNewQueue->ucQueueType = ucQueueType; + } + #endif /* configUSE_TRACE_FACILITY */ + + #if( configUSE_QUEUE_SETS == 1 ) + { + pxNewQueue->pxQueueSetContainer = NULL; + } + #endif /* configUSE_QUEUE_SETS */ + + traceQUEUE_CREATE( pxNewQueue ); +} +/*-----------------------------------------------------------*/ + +#if( configUSE_MUTEXES == 1 ) + + static void prvInitialiseMutex( Queue_t *pxNewQueue ) + { + if( pxNewQueue != NULL ) + { + /* The queue create function will set all the queue structure members + correctly for a generic queue, but this function is creating a + mutex. Overwrite those members that need to be set differently - + in particular the information required for priority inheritance. */ + pxNewQueue->u.xSemaphore.xMutexHolder = NULL; + pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; + + /* In case this is a recursive mutex. */ + pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0; + + traceCREATE_MUTEX( pxNewQueue ); + + /* Start with the semaphore in the expected state. */ + ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); + } + else + { + traceCREATE_MUTEX_FAILED(); + } + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) + { + QueueHandle_t xNewQueue; + const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + + xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); + prvInitialiseMutex( ( Queue_t * ) xNewQueue ); + + return xNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) + { + QueueHandle_t xNewQueue; + const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; + + /* Prevent compiler warnings about unused parameters if + configUSE_TRACE_FACILITY does not equal 1. */ + ( void ) ucQueueType; + + xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); + prvInitialiseMutex( ( Queue_t * ) xNewQueue ); + + return xNewQueue; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + + TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) + { + TaskHandle_t pxReturn; + Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore; + + /* This function is called by xSemaphoreGetMutexHolder(), and should not + be called directly. Note: This is a good way of determining if the + calling task is the mutex holder, but not a good way of determining the + identity of the mutex holder, as the holder may change between the + following critical section exiting and the function returning. */ + taskENTER_CRITICAL(); + { + if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder; + } + else + { + pxReturn = NULL; + } + } + taskEXIT_CRITICAL(); + + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + +#endif +/*-----------------------------------------------------------*/ + +#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) + + TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) + { + TaskHandle_t pxReturn; + + configASSERT( xSemaphore ); + + /* Mutexes cannot be used in interrupt service routines, so the mutex + holder should not change in an ISR, and therefore a critical section is + not required here. */ + if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) + { + pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder; + } + else + { + pxReturn = NULL; + } + + return pxReturn; + } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ + +#endif +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* If this is the task that holds the mutex then xMutexHolder will not + change outside of this task. If this task does not hold the mutex then + pxMutexHolder can never coincidentally equal the tasks handle, and as + this is the only condition we are interested in it does not matter if + pxMutexHolder is accessed simultaneously by another task. Therefore no + mutual exclusion is required to test the pxMutexHolder variable. */ + if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) + { + traceGIVE_MUTEX_RECURSIVE( pxMutex ); + + /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to + the task handle, therefore no underflow check is required. Also, + uxRecursiveCallCount is only modified by the mutex holder, and as + there can only be one, no mutual exclusion is required to modify the + uxRecursiveCallCount member. */ + ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--; + + /* Has the recursive call count unwound to 0? */ + if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 ) + { + /* Return the mutex. This will automatically unblock any other + task that might be waiting to access the mutex. */ + ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + /* The mutex cannot be given because the calling task is not the + holder. */ + xReturn = pdFAIL; + + traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_RECURSIVE_MUTEXES == 1 ) + + BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxMutex = ( Queue_t * ) xMutex; + + configASSERT( pxMutex ); + + /* Comments regarding mutual exclusion as per those within + xQueueGiveMutexRecursive(). */ + + traceTAKE_MUTEX_RECURSIVE( pxMutex ); + + if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) + { + ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; + xReturn = pdPASS; + } + else + { + xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait ); + + /* pdPASS will only be returned if the mutex was successfully + obtained. The calling task may have entered the Blocked state + before reaching here. */ + if( xReturn != pdFAIL ) + { + ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; + } + else + { + traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); + } + } + + return xReturn; + } + +#endif /* configUSE_RECURSIVE_MUTEXES */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + return xHandle; + } + +#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) + { + QueueHandle_t xHandle; + + configASSERT( uxMaxCount != 0 ); + configASSERT( uxInitialCount <= uxMaxCount ); + + xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); + + if( xHandle != NULL ) + { + ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; + + traceCREATE_COUNTING_SEMAPHORE(); + } + else + { + traceCREATE_COUNTING_SEMAPHORE_FAILED(); + } + + return xHandle; + } + +#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) +{ +BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /*lint -save -e904 This function relaxes the coding standard somewhat to + allow return statements within the function itself. This is done in the + interest of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Is there room on the queue now? The running task must be the + highest priority task wanting to access the queue. If the head item + in the queue is to be overwritten then it does not matter if the + queue is full. */ + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + traceQUEUE_SEND( pxQueue ); + + #if ( configUSE_QUEUE_SETS == 1 ) + { + UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; + + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) + { + /* Do not notify the queue set as an existing item + was overwritten in the queue so the number of items + in the queue has not changed. */ + mtCOVERAGE_TEST_MARKER(); + } + else if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to + do this from within the critical section - the + kernel takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes + and the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* If there was a task waiting for data to arrive on the + queue then unblock it now. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The unblocked task has a priority higher than + our own so yield immediately. Yes it is ok to do + this from within the critical section - the kernel + takes care of that. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else if( xYieldRequired != pdFALSE ) + { + /* This path is a special case that will only get + executed if the task was holding multiple mutexes and + the mutexes were given back in an order that is + different to that in which they were taken. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was full and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + + /* Return to the original privilege level before exiting + the function. */ + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was full and a block time was specified so + configure the timeout structure. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_SEND( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); + + /* Unlocking the queue means queue events can effect the + event list. It is possible that interrupts occurring now + remove this task from the event list again - but as the + scheduler is suspended the task will go onto the pending + ready last instead of the actual ready list. */ + prvUnlockQueue( pxQueue ); + + /* Resuming the scheduler will move tasks from the pending + ready list into the ready list - so it is feasible that this + task is already in a ready list before it yields - in which + case the yield will not cause a context switch unless there + is also a higher priority task in the pending ready list. */ + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + } + else + { + /* Try again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + traceQUEUE_SEND_FAILED( pxQueue ); + return errQUEUE_FULL; + } + } /*lint -restore */ +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + /* Similar to xQueueGenericSend, except without blocking if there is no room + in the queue. Also don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) + { + const int8_t cTxLock = pxQueue->cTxLock; + + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a + semaphore or mutex. That means prvCopyDataToQueue() cannot result + in a task disinheriting a priority and prvCopyDataToQueue() can be + called here even though the disinherit function does not check if + the scheduler is suspended before accessing the ready lists. */ + ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, xCopyPosition ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting + to the queue set caused a higher priority task to + unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = xQueue; + + /* Similar to xQueueGenericSendFromISR() but used with semaphores where the + item size is 0. Don't directly wake a task that was blocked on a queue + read, instead return a flag to say whether a context switch is required or + not (i.e. has a task with a higher priority than us been woken by this + post). */ + + configASSERT( pxQueue ); + + /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() + if the item size is not 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); + + /* Normally a mutex would not be given from an interrupt, especially if + there is a mutex holder, as priority inheritance makes no sense for an + interrupts, only tasks. */ + configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* When the queue is used to implement a semaphore no data is ever + moved through the queue but it is still valid to see if the queue 'has + space'. */ + if( uxMessagesWaiting < pxQueue->uxLength ) + { + const int8_t cTxLock = pxQueue->cTxLock; + + traceQUEUE_SEND_FROM_ISR( pxQueue ); + + /* A task can only have an inherited priority if it is a mutex + holder - and if there is a mutex holder then the mutex cannot be + given from an ISR. As this is the ISR version of the function it + can be assumed there is no mutex holder and no need to determine if + priority disinheritance is needed. Simply increase the count of + messages (semaphores) available. */ + pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + + /* The event list is not altered if the queue is locked. This will + be done when the queue is unlocked later. */ + if( cTxLock == queueUNLOCKED ) + { + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) + { + /* The semaphore is a member of a queue set, and + posting to the queue set caused a higher priority + task to unblock. A context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so + record that a context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_QUEUE_SETS */ + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was posted while it was locked. */ + pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); + xReturn = errQUEUE_FULL; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) +{ +BaseType_t xEntryTimeSet = pdFALSE; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = xQueue; + + /* Check the pointer is not NULL. */ + configASSERT( ( pxQueue ) ); + + /* The buffer into which data is received can only be NULL if the data size + is zero (so no data is copied into the buffer. */ + configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* Cannot block if the scheduler is suspended. */ + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /*lint -save -e904 This function relaxes the coding standard somewhat to + allow return statements within the function itself. This is done in the + interest of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* Is there data in the queue now? To be running the calling task + must be the highest priority task wanting to access the queue. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data available, remove one item. */ + prvCopyDataFromQueue( pxQueue, pvBuffer ); + traceQUEUE_RECEIVE( pxQueue ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; + + /* There is now space in the queue, were any tasks waiting to + post to the queue? If so, unblock the highest priority waiting + task. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + /* The timeout has not expired. If the queue is still empty place + the task on the list of tasks waiting to receive from the queue. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* The queue contains data again. Loop back to try and read the + data. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* Timed out. If there is no data in the queue exit, otherwise loop + back and attempt to read the data. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } /*lint -restore */ +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) +{ +BaseType_t xEntryTimeSet = pdFALSE; +TimeOut_t xTimeOut; +Queue_t * const pxQueue = xQueue; + +#if( configUSE_MUTEXES == 1 ) + BaseType_t xInheritanceOccurred = pdFALSE; +#endif + + /* Check the queue pointer is not NULL. */ + configASSERT( ( pxQueue ) ); + + /* Check this really is a semaphore, in which case the item size will be + 0. */ + configASSERT( pxQueue->uxItemSize == 0 ); + + /* Cannot block if the scheduler is suspended. */ + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /*lint -save -e904 This function relaxes the coding standard somewhat to allow return + statements within the function itself. This is done in the interest + of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + /* Semaphores are queues with an item size of 0, and where the + number of messages in the queue is the semaphore's count value. */ + const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting; + + /* Is there data in the queue now? To be running the calling task + must be the highest priority task wanting to access the queue. */ + if( uxSemaphoreCount > ( UBaseType_t ) 0 ) + { + traceQUEUE_RECEIVE( pxQueue ); + + /* Semaphores are queues with a data size of zero and where the + messages waiting is the semaphore's count. Reduce the count. */ + pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1; + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* Record the information required to implement + priority inheritance should it become necessary. */ + pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + + /* Check to see if other tasks are blocked waiting to give the + semaphore, and if so, unblock the highest priority such task. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* For inheritance to have occurred there must have been an + initial timeout, and an adjusted timeout cannot become 0, as + if it were 0 the function would have exited. */ + #if( configUSE_MUTEXES == 1 ) + { + configASSERT( xInheritanceOccurred == pdFALSE ); + } + #endif /* configUSE_MUTEXES */ + + /* The semaphore count was 0 and no block time is specified + (or the block time has expired) so exit now. */ + taskEXIT_CRITICAL(); + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The semaphore count was 0 and a block time was specified + so configure the timeout structure ready to block. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can give to and take from the semaphore + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + /* A block time is specified and not expired. If the semaphore + count is 0 then enter the Blocked state to wait for a semaphore to + become available. As semaphores are implemented with queues the + queue being empty is equivalent to the semaphore count being 0. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); + + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + taskENTER_CRITICAL(); + { + xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); + } + taskEXIT_CRITICAL(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif + + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* There was no timeout and the semaphore count was not 0, so + attempt to take the semaphore again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* Timed out. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + /* If the semaphore count is 0 exit now as the timeout has + expired. Otherwise return to attempt to take the semaphore that is + known to be available. As semaphores are implemented by queues the + queue being empty is equivalent to the semaphore count being 0. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + #if ( configUSE_MUTEXES == 1 ) + { + /* xInheritanceOccurred could only have be set if + pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to + test the mutex type again to check it is actually a mutex. */ + if( xInheritanceOccurred != pdFALSE ) + { + taskENTER_CRITICAL(); + { + UBaseType_t uxHighestWaitingPriority; + + /* This task blocking on the mutex caused another + task to inherit this task's priority. Now this task + has timed out the priority should be disinherited + again, but only as low as the next highest priority + task that is waiting for the same mutex. */ + uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); + vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); + } + taskEXIT_CRITICAL(); + } + } + #endif /* configUSE_MUTEXES */ + + traceQUEUE_RECEIVE_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } /*lint -restore */ +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) +{ +BaseType_t xEntryTimeSet = pdFALSE; +TimeOut_t xTimeOut; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = xQueue; + + /* Check the pointer is not NULL. */ + configASSERT( ( pxQueue ) ); + + /* The buffer into which data is received can only be NULL if the data size + is zero (so no data is copied into the buffer. */ + configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* Cannot block if the scheduler is suspended. */ + #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) + { + configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); + } + #endif + + + /*lint -save -e904 This function relaxes the coding standard somewhat to + allow return statements within the function itself. This is done in the + interest of execution time efficiency. */ + for( ;; ) + { + taskENTER_CRITICAL(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* Is there data in the queue now? To be running the calling task + must be the highest priority task wanting to access the queue. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Remember the read position so it can be reset after the data + is read from the queue as this function is only peeking the + data, not removing it. */ + pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + traceQUEUE_PEEK( pxQueue ); + + /* The data is not being removed, so reset the read pointer. */ + pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; + + /* The data is being left in the queue, so see if there are + any other tasks waiting for the data. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than this task. */ + queueYIELD_IF_USING_PREEMPTION(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + taskEXIT_CRITICAL(); + return pdPASS; + } + else + { + if( xTicksToWait == ( TickType_t ) 0 ) + { + /* The queue was empty and no block time is specified (or + the block time has expired) so leave now. */ + taskEXIT_CRITICAL(); + traceQUEUE_PEEK_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else if( xEntryTimeSet == pdFALSE ) + { + /* The queue was empty and a block time was specified so + configure the timeout structure ready to enter the blocked + state. */ + vTaskInternalSetTimeOutState( &xTimeOut ); + xEntryTimeSet = pdTRUE; + } + else + { + /* Entry time was already set. */ + mtCOVERAGE_TEST_MARKER(); + } + } + } + taskEXIT_CRITICAL(); + + /* Interrupts and other tasks can send to and receive from the queue + now the critical section has been exited. */ + + vTaskSuspendAll(); + prvLockQueue( pxQueue ); + + /* Update the timeout state to see if it has expired yet. */ + if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) + { + /* Timeout has not expired yet, check to see if there is data in the + queue now, and if not enter the Blocked state to wait for data. */ + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); + vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); + prvUnlockQueue( pxQueue ); + if( xTaskResumeAll() == pdFALSE ) + { + portYIELD_WITHIN_API(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* There is data in the queue now, so don't enter the blocked + state, instead return to try and obtain the data. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + } + } + else + { + /* The timeout has expired. If there is still no data in the queue + exit, otherwise go back and try to read the data again. */ + prvUnlockQueue( pxQueue ); + ( void ) xTaskResumeAll(); + + if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) + { + traceQUEUE_PEEK_FAILED( pxQueue ); + return errQUEUE_EMPTY; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } /*lint -restore */ +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + /* Cannot block in an ISR, so check there is data available. */ + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + const int8_t cRxLock = pxQueue->cRxLock; + + traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); + + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; + + /* If the queue is locked the event list will not be modified. + Instead update the lock count so the task that unlocks the queue + will know that an ISR has removed data while the queue was + locked. */ + if( cRxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + /* The task waiting has a higher priority than us so + force a context switch. */ + if( pxHigherPriorityTaskWoken != NULL ) + { + *pxHigherPriorityTaskWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Increment the lock count so the task that unlocks the queue + knows that data was removed while it was locked. */ + pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) +{ +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; +int8_t *pcOriginalReadPosition; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); + configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ + + /* RTOS ports that support interrupt nesting have the concept of a maximum + system call (or maximum API call) interrupt priority. Interrupts that are + above the maximum system call priority are kept permanently enabled, even + when the RTOS kernel is in a critical section, but cannot make any calls to + FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h + then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + failure if a FreeRTOS API function is called from an interrupt that has been + assigned a priority above the configured maximum system call priority. + Only FreeRTOS functions that end in FromISR can be called from interrupts + that have been assigned a priority at or (logically) below the maximum + system call interrupt priority. FreeRTOS maintains a separate interrupt + safe API to ensure interrupt entry is as fast and as simple as possible. + More information (albeit Cortex-M specific) is provided on the following + link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); + + uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Cannot block in an ISR, so check there is data available. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + traceQUEUE_PEEK_FROM_ISR( pxQueue ); + + /* Remember the read position so it can be reset as nothing is + actually being removed from the queue. */ + pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; + prvCopyDataFromQueue( pxQueue, pvBuffer ); + pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; + + configASSERT( xQueue ); + + taskENTER_CRITICAL(); + { + uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + + taskENTER_CRITICAL(); + { + uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; + } + taskEXIT_CRITICAL(); + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) +{ +UBaseType_t uxReturn; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + uxReturn = pxQueue->uxMessagesWaiting; + + return uxReturn; +} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ +/*-----------------------------------------------------------*/ + +void vQueueDelete( QueueHandle_t xQueue ) +{ +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + traceQUEUE_DELETE( pxQueue ); + + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueUnregisterQueue( pxQueue ); + } + #endif + + #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) + { + /* The queue can only have been allocated dynamically - free it + again. */ + vPortFree( pxQueue ); + } + #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) + { + /* The queue could have been allocated statically or dynamically, so + check before attempting to free the memory. */ + if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) + { + vPortFree( pxQueue ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #else + { + /* The queue must have been statically allocated, so is not going to be + deleted. Avoid compiler warnings about the unused parameter. */ + ( void ) pxQueue; + } + #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ +} +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) + { + ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) + { + return ( ( Queue_t * ) xQueue )->ucQueueType; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if( configUSE_MUTEXES == 1 ) + + static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) + { + UBaseType_t uxHighestPriorityOfWaitingTasks; + + /* If a task waiting for a mutex causes the mutex holder to inherit a + priority, but the waiting task times out, then the holder should + disinherit the priority - but only down to the highest priority of any + other tasks that are waiting for the same mutex. For this purpose, + return the priority of the highest priority task that is waiting for the + mutex. */ + if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U ) + { + uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ); + } + else + { + uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY; + } + + return uxHighestPriorityOfWaitingTasks; + } + +#endif /* configUSE_MUTEXES */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) +{ +BaseType_t xReturn = pdFALSE; +UBaseType_t uxMessagesWaiting; + + /* This function is called from a critical section. */ + + uxMessagesWaiting = pxQueue->uxMessagesWaiting; + + if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) + { + #if ( configUSE_MUTEXES == 1 ) + { + if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) + { + /* The mutex is no longer being held. */ + xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder ); + pxQueue->u.xSemaphore.xMutexHolder = NULL; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* configUSE_MUTEXES */ + } + else if( xPosition == queueSEND_TO_BACK ) + { + ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ + pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ + if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->pcWriteTo = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e9087 !e418 MISRA exception as the casts are only redundant for some ports. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. Assert checks null pointer only used when length is 0. */ + pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize; + if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ + { + pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xPosition == queueOVERWRITE ) + { + if( uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* An item is not being added but overwritten, so subtract + one from the recorded number of items in the queue so when + one is added again below the number of recorded items remains + correct. */ + --uxMessagesWaiting; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) +{ + if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) + { + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ + { + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ + } +} +/*-----------------------------------------------------------*/ + +static void prvUnlockQueue( Queue_t * const pxQueue ) +{ + /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ + + /* The lock counts contains the number of extra data items placed or + removed from the queue while the queue was locked. When a queue is + locked items can be added or removed, but the event lists cannot be + updated. */ + taskENTER_CRITICAL(); + { + int8_t cTxLock = pxQueue->cTxLock; + + /* See if data was added to the queue while it was locked. */ + while( cTxLock > queueLOCKED_UNMODIFIED ) + { + /* Data was posted while the queue was locked. Are any tasks + blocked waiting for data to become available? */ + #if ( configUSE_QUEUE_SETS == 1 ) + { + if( pxQueue->pxQueueSetContainer != NULL ) + { + if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) != pdFALSE ) + { + /* The queue is a member of a queue set, and posting to + the queue set caused a higher priority task to unblock. + A context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* Tasks that are removed from the event list will get + added to the pending ready list as the scheduler is still + suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that a + context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + } + #else /* configUSE_QUEUE_SETS */ + { + /* Tasks that are removed from the event list will get added to + the pending ready list as the scheduler is still suspended. */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority so record that + a context switch is required. */ + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + break; + } + } + #endif /* configUSE_QUEUE_SETS */ + + --cTxLock; + } + + pxQueue->cTxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); + + /* Do the same for the Rx lock. */ + taskENTER_CRITICAL(); + { + int8_t cRxLock = pxQueue->cRxLock; + + while( cRxLock > queueLOCKED_UNMODIFIED ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + vTaskMissedYield(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + --cRxLock; + } + else + { + break; + } + } + + pxQueue->cRxLock = queueUNLOCKED; + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) +{ +BaseType_t xReturn; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) +{ +BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) +{ +BaseType_t xReturn; +Queue_t * const pxQueue = xQueue; + + configASSERT( pxQueue ); + if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; + + /* If the queue is already full we may have to block. A critical section + is required to prevent an interrupt removing something from the queue + between the check to see if the queue is full and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( prvIsQueueFull( pxQueue ) != pdFALSE ) + { + /* The queue is full - do we want to block or just leave without + posting? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is called from a coroutine we cannot block directly, but + return indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + /* There is room in the queue, copy the data into the queue. */ + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + xReturn = pdPASS; + + /* Were any co-routines waiting for data to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The co-routine waiting has a higher priority so record + that a yield might be appropriate. */ + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = errQUEUE_FULL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; + + /* If the queue is already empty we may have to block. A critical section + is required to prevent an interrupt adding something to the queue + between the check to see if the queue is empty and blocking on the queue. */ + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) + { + /* There are no messages in the queue, do we want to block or just + leave with nothing? */ + if( xTicksToWait > ( TickType_t ) 0 ) + { + /* As this is a co-routine we cannot block directly, but return + indicating that we need to block. */ + vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); + portENABLE_INTERRUPTS(); + return errQUEUE_BLOCKED; + } + else + { + portENABLE_INTERRUPTS(); + return errQUEUE_FULL; + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + portENABLE_INTERRUPTS(); + + portDISABLE_INTERRUPTS(); + { + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Data is available from the queue. */ + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) + { + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + xReturn = pdPASS; + + /* Were any co-routines waiting for space to become available? */ + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + /* In this instance the co-routine could be placed directly + into the ready list as we are within a critical section. + Instead the same pending ready list mechanism is used as if + the event were caused from within an interrupt. */ + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + xReturn = errQUEUE_YIELD; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xReturn = pdFAIL; + } + } + portENABLE_INTERRUPTS(); + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) + { + Queue_t * const pxQueue = xQueue; + + /* Cannot block within an ISR so if there is no space on the queue then + exit without doing anything. */ + if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) + { + prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); + + /* We only want to wake one co-routine per ISR, so check that a + co-routine has not already been woken. */ + if( xCoRoutinePreviouslyWoken == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) + { + return pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCoRoutinePreviouslyWoken; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_CO_ROUTINES == 1 ) + + BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) + { + BaseType_t xReturn; + Queue_t * const pxQueue = xQueue; + + /* We cannot block from an ISR, so check there is data available. If + not then just leave without doing anything. */ + if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) + { + /* Copy the data from the queue. */ + pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; + if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) + { + pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + --( pxQueue->uxMessagesWaiting ); + ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); + + if( ( *pxCoRoutineWoken ) == pdFALSE ) + { + if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) + { + if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) + { + *pxCoRoutineWoken = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = pdPASS; + } + else + { + xReturn = pdFAIL; + } + + return xReturn; + } + +#endif /* configUSE_CO_ROUTINES */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + + /* See if there is an empty space in the registry. A NULL name denotes + a free slot. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].pcQueueName == NULL ) + { + /* Store the information on this queue. */ + xQueueRegistry[ ux ].pcQueueName = pcQueueName; + xQueueRegistry[ ux ].xHandle = xQueue; + + traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + } + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + { + UBaseType_t ux; + const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + + /* Note there is nothing here to protect against another task adding or + removing entries from the registry while it is being searched. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + pcReturn = xQueueRegistry[ ux ].pcQueueName; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + return pcReturn; + } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */ + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configQUEUE_REGISTRY_SIZE > 0 ) + + void vQueueUnregisterQueue( QueueHandle_t xQueue ) + { + UBaseType_t ux; + + /* See if the handle of the queue being unregistered in actually in the + registry. */ + for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) + { + if( xQueueRegistry[ ux ].xHandle == xQueue ) + { + /* Set the name to NULL to show that this slot if free again. */ + xQueueRegistry[ ux ].pcQueueName = NULL; + + /* Set the handle to NULL to ensure the same queue handle cannot + appear in the registry twice if it is added, removed, then + added again. */ + xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0; + break; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + + } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ + +#endif /* configQUEUE_REGISTRY_SIZE */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TIMERS == 1 ) + + void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) + { + Queue_t * const pxQueue = xQueue; + + /* This function should not be called by application code hence the + 'Restricted' in its name. It is not part of the public API. It is + designed for use by kernel code, and has special calling requirements. + It can result in vListInsert() being called on a list that can only + possibly ever have one item in it, so the list will be fast, but even + so it should be called with the scheduler locked and not from a critical + section. */ + + /* Only do anything if there are no messages in the queue. This function + will not actually cause the task to block, just place it on a blocked + list. It will not block until the scheduler is unlocked - at which + time a yield will be performed. If an item is added to the queue while + the queue is locked, and the calling task blocks on the queue, then the + calling task will be immediately unblocked when the queue is unlocked. */ + prvLockQueue( pxQueue ); + if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) + { + /* There is nothing in the queue, block for the specified period. */ + vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + prvUnlockQueue( pxQueue ); + } + +#endif /* configUSE_TIMERS */ +/*-----------------------------------------------------------*/ + +#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + + QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) + { + QueueSetHandle_t pxQueue; + + pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); + + return pxQueue; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + + taskENTER_CRITICAL(); + { + if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) + { + /* Cannot add a queue/semaphore to more than one queue set. */ + xReturn = pdFAIL; + } + else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* Cannot add a queue/semaphore to a queue set if there are already + items in the queue/semaphore. */ + xReturn = pdFAIL; + } + else + { + ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; + xReturn = pdPASS; + } + } + taskEXIT_CRITICAL(); + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) + { + BaseType_t xReturn; + Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; + + if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) + { + /* The queue was not a member of the set. */ + xReturn = pdFAIL; + } + else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) + { + /* It is dangerous to remove a queue from a set when the queue is + not empty because the queue set will still hold pending events for + the queue. */ + xReturn = pdFAIL; + } + else + { + taskENTER_CRITICAL(); + { + /* The queue is no longer contained in the set. */ + pxQueueOrSemaphore->pxQueueSetContainer = NULL; + } + taskEXIT_CRITICAL(); + xReturn = pdPASS; + } + + return xReturn; + } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) + { + QueueSetMemberHandle_t xReturn = NULL; + + ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_QUEUE_SETS == 1 ) + + static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue, const BaseType_t xCopyPosition ) + { + Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; + BaseType_t xReturn = pdFALSE; + + /* This function must be called form a critical section. */ + + configASSERT( pxQueueSetContainer ); + configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); + + if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) + { + const int8_t cTxLock = pxQueueSetContainer->cTxLock; + + traceQUEUE_SEND( pxQueueSetContainer ); + + /* The data copied is the handle of the queue that contains data. */ + xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, xCopyPosition ); + + if( cTxLock == queueUNLOCKED ) + { + if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) + { + if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) + { + /* The task waiting has a higher priority. */ + xReturn = pdTRUE; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xReturn; + } + +#endif /* configUSE_QUEUE_SETS */ + + + + + + + + + + + + diff --git a/component/os/freertos/freertos_v10.2.0/Source/stream_buffer.c b/component/os/freertos/freertos_v10.2.0/Source/stream_buffer.c new file mode 100644 index 00000000..a1d6289d --- /dev/null +++ b/component/os/freertos/freertos_v10.2.0/Source/stream_buffer.c @@ -0,0 +1,1270 @@ +/* + * FreeRTOS Kernel V10.2.0 + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + +/* Standard includes. */ +#include +#include + +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining +all the API functions to use the MPU wrappers. That should only be done when +task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "stream_buffer.h" + +#if( configUSE_TASK_NOTIFICATIONS != 1 ) + #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c +#endif + +/* Lint e961, e9021 and e750 are suppressed as a MISRA exception justified +because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined +for the header files above, but not in this file, in order to generate the +correct privileged Vs unprivileged linkage and placement. */ +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ + +/* If the user has not provided application specific Rx notification macros, +or #defined the notification macros away, them provide default implementations +that uses task notifications. */ +/*lint -save -e9026 Function like macros allowed and needed here so they can be overidden. */ +#ifndef sbRECEIVE_COMPLETED + #define sbRECEIVE_COMPLETED( pxStreamBuffer ) \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); +#endif /* sbRECEIVE_COMPLETED */ + +#ifndef sbRECEIVE_COMPLETED_FROM_ISR + #define sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, \ + pxHigherPriorityTaskWoken ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + \ + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) \ + { \ + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, \ + ( uint32_t ) 0, \ + eNoAction, \ + pxHigherPriorityTaskWoken ); \ + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; \ + } \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } +#endif /* sbRECEIVE_COMPLETED_FROM_ISR */ + +/* If the user has not provided an application specific Tx notification macro, +or #defined the notification macro away, them provide a default implementation +that uses task notifications. */ +#ifndef sbSEND_COMPLETED + #define sbSEND_COMPLETED( pxStreamBuffer ) \ + vTaskSuspendAll(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ + { \ + ( void ) xTaskNotify( ( pxStreamBuffer )->xTaskWaitingToReceive, \ + ( uint32_t ) 0, \ + eNoAction ); \ + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ + } \ + } \ + ( void ) xTaskResumeAll(); +#endif /* sbSEND_COMPLETED */ + +#ifndef sbSEND_COMPLETE_FROM_ISR + #define sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ) \ + { \ + UBaseType_t uxSavedInterruptStatus; \ + \ + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); \ + { \ + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) \ + { \ + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, \ + ( uint32_t ) 0, \ + eNoAction, \ + pxHigherPriorityTaskWoken ); \ + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; \ + } \ + } \ + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); \ + } +#endif /* sbSEND_COMPLETE_FROM_ISR */ +/*lint -restore (9026) */ + +/* The number of bytes used to hold the length of a message in the buffer. */ +#define sbBYTES_TO_STORE_MESSAGE_LENGTH ( sizeof( configMESSAGE_BUFFER_LENGTH_TYPE ) ) + +/* Bits stored in the ucFlags field of the stream buffer. */ +#define sbFLAGS_IS_MESSAGE_BUFFER ( ( uint8_t ) 1 ) /* Set if the stream buffer was created as a message buffer, in which case it holds discrete messages rather than a stream. */ +#define sbFLAGS_IS_STATICALLY_ALLOCATED ( ( uint8_t ) 2 ) /* Set if the stream buffer was created using statically allocated memory. */ + +/*-----------------------------------------------------------*/ + +/* Structure that hold state information on the buffer. */ +typedef struct StreamBufferDef_t /*lint !e9058 Style convention uses tag. */ +{ + volatile size_t xTail; /* Index to the next item to read within the buffer. */ + volatile size_t xHead; /* Index to the next item to write within the buffer. */ + size_t xLength; /* The length of the buffer pointed to by pucBuffer. */ + size_t xTriggerLevelBytes; /* The number of bytes that must be in the stream buffer before a task that is waiting for data is unblocked. */ + volatile TaskHandle_t xTaskWaitingToReceive; /* Holds the handle of a task waiting for data, or NULL if no tasks are waiting. */ + volatile TaskHandle_t xTaskWaitingToSend; /* Holds the handle of a task waiting to send data to a message buffer that is full. */ + uint8_t *pucBuffer; /* Points to the buffer itself - that is - the RAM that stores the data passed through the buffer. */ + uint8_t ucFlags; + + #if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxStreamBufferNumber; /* Used for tracing purposes. */ + #endif +} StreamBuffer_t; + +/* + * The number of bytes available to be read from the buffer. + */ +static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) PRIVILEGED_FUNCTION; + +/* + * Add xCount bytes from pucData into the pxStreamBuffer message buffer. + * Returns the number of bytes written, which will either equal xCount in the + * success case, or 0 if there was not enough space in the buffer (in which case + * no data is written into the buffer). + */ +static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) PRIVILEGED_FUNCTION; + +/* + * If the stream buffer is being used as a message buffer, then reads an entire + * message out of the buffer. If the stream buffer is being used as a stream + * buffer then read as many bytes as possible from the buffer. + * prvReadBytesFromBuffer() is called to actually extract the bytes from the + * buffer's data storage area. + */ +static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, + void *pvRxData, + size_t xBufferLengthBytes, + size_t xBytesAvailable, + size_t xBytesToStoreMessageLength ) PRIVILEGED_FUNCTION; + +/* + * If the stream buffer is being used as a message buffer, then writes an entire + * message to the buffer. If the stream buffer is being used as a stream + * buffer then write as many bytes as possible to the buffer. + * prvWriteBytestoBuffer() is called to actually send the bytes to the buffer's + * data storage area. + */ +static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + size_t xSpace, + size_t xRequiredSpace ) PRIVILEGED_FUNCTION; + +/* + * Read xMaxCount bytes from the pxStreamBuffer message buffer and write them + * to pucData. + */ +static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, + uint8_t *pucData, + size_t xMaxCount, + size_t xBytesAvailable ) PRIVILEGED_FUNCTION; + +/* + * Called by both pxStreamBufferCreate() and pxStreamBufferCreateStatic() to + * initialise the members of the newly created stream buffer structure. + */ +static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, + uint8_t * const pucBuffer, + size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + uint8_t ucFlags ) PRIVILEGED_FUNCTION; + +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + + StreamBufferHandle_t xStreamBufferGenericCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes, BaseType_t xIsMessageBuffer ) + { + uint8_t *pucAllocatedMemory; + uint8_t ucFlags; + + /* In case the stream buffer is going to be used as a message buffer + (that is, it will hold discrete messages with a little meta data that + says how big the next message is) check the buffer will be large enough + to hold at least one message. */ + if( xIsMessageBuffer == pdTRUE ) + { + /* Is a message buffer but not statically allocated. */ + ucFlags = sbFLAGS_IS_MESSAGE_BUFFER; + configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); + } + else + { + /* Not a message buffer and not statically allocated. */ + ucFlags = 0; + configASSERT( xBufferSizeBytes > 0 ); + } + configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); + + /* A trigger level of 0 would cause a waiting task to unblock even when + the buffer was empty. */ + if( xTriggerLevelBytes == ( size_t ) 0 ) + { + xTriggerLevelBytes = ( size_t ) 1; + } + + /* A stream buffer requires a StreamBuffer_t structure and a buffer. + Both are allocated in a single call to pvPortMalloc(). The + StreamBuffer_t structure is placed at the start of the allocated memory + and the buffer follows immediately after. The requested size is + incremented so the free space is returned as the user would expect - + this is a quirk of the implementation that means otherwise the free + space would be reported as one byte smaller than would be logically + expected. */ + if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) + { + xBufferSizeBytes++; + pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + } + else + { + pucAllocatedMemory = NULL; + } + + if( pucAllocatedMemory != NULL ) + { + prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ + pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */ + xBufferSizeBytes, + xTriggerLevelBytes, + ucFlags ); + + traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer ); + } + else + { + traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ); + } + + return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */ + } + +#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ +/*-----------------------------------------------------------*/ + +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) + + StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + BaseType_t xIsMessageBuffer, + uint8_t * const pucStreamBufferStorageArea, + StaticStreamBuffer_t * const pxStaticStreamBuffer ) + { + StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) pxStaticStreamBuffer; /*lint !e740 !e9087 Safe cast as StaticStreamBuffer_t is opaque Streambuffer_t. */ + StreamBufferHandle_t xReturn; + uint8_t ucFlags; + + configASSERT( pucStreamBufferStorageArea ); + configASSERT( pxStaticStreamBuffer ); + configASSERT( xTriggerLevelBytes <= xBufferSizeBytes ); + + /* A trigger level of 0 would cause a waiting task to unblock even when + the buffer was empty. */ + if( xTriggerLevelBytes == ( size_t ) 0 ) + { + xTriggerLevelBytes = ( size_t ) 1; + } + + if( xIsMessageBuffer != pdFALSE ) + { + /* Statically allocated message buffer. */ + ucFlags = sbFLAGS_IS_MESSAGE_BUFFER | sbFLAGS_IS_STATICALLY_ALLOCATED; + } + else + { + /* Statically allocated stream buffer. */ + ucFlags = sbFLAGS_IS_STATICALLY_ALLOCATED; + } + + /* In case the stream buffer is going to be used as a message buffer + (that is, it will hold discrete messages with a little meta data that + says how big the next message is) check the buffer will be large enough + to hold at least one message. */ + configASSERT( xBufferSizeBytes > sbBYTES_TO_STORE_MESSAGE_LENGTH ); + + #if( configASSERT_DEFINED == 1 ) + { + /* Sanity check that the size of the structure used to declare a + variable of type StaticStreamBuffer_t equals the size of the real + message buffer structure. */ + volatile size_t xSize = sizeof( StaticStreamBuffer_t ); + configASSERT( xSize == sizeof( StreamBuffer_t ) ); + } /*lint !e529 xSize is referenced is configASSERT() is defined. */ + #endif /* configASSERT_DEFINED */ + + if( ( pucStreamBufferStorageArea != NULL ) && ( pxStaticStreamBuffer != NULL ) ) + { + prvInitialiseNewStreamBuffer( pxStreamBuffer, + pucStreamBufferStorageArea, + xBufferSizeBytes, + xTriggerLevelBytes, + ucFlags ); + + /* Remember this was statically allocated in case it is ever deleted + again. */ + pxStreamBuffer->ucFlags |= sbFLAGS_IS_STATICALLY_ALLOCATED; + + traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ); + + xReturn = ( StreamBufferHandle_t ) pxStaticStreamBuffer; /*lint !e9087 Data hiding requires cast to opaque type. */ + } + else + { + xReturn = NULL; + traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ); + } + + return xReturn; + } + +#endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ +/*-----------------------------------------------------------*/ + +void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ) +{ +StreamBuffer_t * pxStreamBuffer = xStreamBuffer; + + configASSERT( pxStreamBuffer ); + + traceSTREAM_BUFFER_DELETE( xStreamBuffer ); + + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_STATICALLY_ALLOCATED ) == ( uint8_t ) pdFALSE ) + { + #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) + { + /* Both the structure and the buffer were allocated using a single call + to pvPortMalloc(), hence only one call to vPortFree() is required. */ + vPortFree( ( void * ) pxStreamBuffer ); /*lint !e9087 Standard free() semantics require void *, plus pxStreamBuffer was allocated by pvPortMalloc(). */ + } + #else + { + /* Should not be possible to get here, ucFlags must be corrupt. + Force an assert. */ + configASSERT( xStreamBuffer == ( StreamBufferHandle_t ) ~0 ); + } + #endif + } + else + { + /* The structure and buffer were not allocated dynamically and cannot be + freed - just scrub the structure so future use will assert. */ + ( void ) memset( pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); + } +} +/*-----------------------------------------------------------*/ + +BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +BaseType_t xReturn = pdFAIL; + +#if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxStreamBufferNumber; +#endif + + configASSERT( pxStreamBuffer ); + + #if( configUSE_TRACE_FACILITY == 1 ) + { + /* Store the stream buffer number so it can be restored after the + reset. */ + uxStreamBufferNumber = pxStreamBuffer->uxStreamBufferNumber; + } + #endif + + /* Can only reset a message buffer if there are no tasks blocked on it. */ + taskENTER_CRITICAL(); + { + if( pxStreamBuffer->xTaskWaitingToReceive == NULL ) + { + if( pxStreamBuffer->xTaskWaitingToSend == NULL ) + { + prvInitialiseNewStreamBuffer( pxStreamBuffer, + pxStreamBuffer->pucBuffer, + pxStreamBuffer->xLength, + pxStreamBuffer->xTriggerLevelBytes, + pxStreamBuffer->ucFlags ); + xReturn = pdPASS; + + #if( configUSE_TRACE_FACILITY == 1 ) + { + pxStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; + } + #endif + + traceSTREAM_BUFFER_RESET( xStreamBuffer ); + } + } + } + taskEXIT_CRITICAL(); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +BaseType_t xReturn; + + configASSERT( pxStreamBuffer ); + + /* It is not valid for the trigger level to be 0. */ + if( xTriggerLevel == ( size_t ) 0 ) + { + xTriggerLevel = ( size_t ) 1; + } + + /* The trigger level is the number of bytes that must be in the stream + buffer before a task that is waiting for data is unblocked. */ + if( xTriggerLevel <= pxStreamBuffer->xLength ) + { + pxStreamBuffer->xTriggerLevelBytes = xTriggerLevel; + xReturn = pdPASS; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer ) +{ +const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xSpace; + + configASSERT( pxStreamBuffer ); + + xSpace = pxStreamBuffer->xLength + pxStreamBuffer->xTail; + xSpace -= pxStreamBuffer->xHead; + xSpace -= ( size_t ) 1; + + if( xSpace >= pxStreamBuffer->xLength ) + { + xSpace -= pxStreamBuffer->xLength; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xSpace; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer ) +{ +const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xReturn; + + configASSERT( pxStreamBuffer ); + + xReturn = prvBytesInBuffer( pxStreamBuffer ); + return xReturn; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, + const void *pvTxData, + size_t xDataLengthBytes, + TickType_t xTicksToWait ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xReturn, xSpace = 0; +size_t xRequiredSpace = xDataLengthBytes; +TimeOut_t xTimeOut; + + configASSERT( pvTxData ); + configASSERT( pxStreamBuffer ); + + /* This send function is used to write to both message buffers and stream + buffers. If this is a message buffer then the space needed must be + increased by the amount of bytes needed to store the length of the + message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; + + /* Overflow? */ + configASSERT( xRequiredSpace > xDataLengthBytes ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xTicksToWait != ( TickType_t ) 0 ) + { + vTaskSetTimeOutState( &xTimeOut ); + + do + { + /* Wait until the required number of bytes are free in the message + buffer. */ + taskENTER_CRITICAL(); + { + xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); + + if( xSpace < xRequiredSpace ) + { + /* Clear notification state as going to wait for space. */ + ( void ) xTaskNotifyStateClear( NULL ); + + /* Should only be one writer. */ + configASSERT( pxStreamBuffer->xTaskWaitingToSend == NULL ); + pxStreamBuffer->xTaskWaitingToSend = xTaskGetCurrentTaskHandle(); + } + else + { + taskEXIT_CRITICAL(); + break; + } + } + taskEXIT_CRITICAL(); + + traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ); + ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); + pxStreamBuffer->xTaskWaitingToSend = NULL; + + } while( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + if( xSpace == ( size_t ) 0 ) + { + xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace ); + + if( xReturn > ( size_t ) 0 ) + { + traceSTREAM_BUFFER_SEND( xStreamBuffer, xReturn ); + + /* Was a task waiting for the data? */ + if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) + { + sbSEND_COMPLETED( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ); + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, + const void *pvTxData, + size_t xDataLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xReturn, xSpace; +size_t xRequiredSpace = xDataLengthBytes; + + configASSERT( pvTxData ); + configASSERT( pxStreamBuffer ); + + /* This send function is used to write to both message buffers and stream + buffers. If this is a message buffer then the space needed must be + increased by the amount of bytes needed to store the length of the + message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xRequiredSpace += sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xSpace = xStreamBufferSpacesAvailable( pxStreamBuffer ); + xReturn = prvWriteMessageToBuffer( pxStreamBuffer, pvTxData, xDataLengthBytes, xSpace, xRequiredSpace ); + + if( xReturn > ( size_t ) 0 ) + { + /* Was a task waiting for the data? */ + if( prvBytesInBuffer( pxStreamBuffer ) >= pxStreamBuffer->xTriggerLevelBytes ) + { + sbSEND_COMPLETE_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xReturn ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static size_t prvWriteMessageToBuffer( StreamBuffer_t * const pxStreamBuffer, + const void * pvTxData, + size_t xDataLengthBytes, + size_t xSpace, + size_t xRequiredSpace ) +{ + BaseType_t xShouldWrite; + size_t xReturn; + + if( xSpace == ( size_t ) 0 ) + { + /* Doesn't matter if this is a stream buffer or a message buffer, there + is no space to write. */ + xShouldWrite = pdFALSE; + } + else if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) == ( uint8_t ) 0 ) + { + /* This is a stream buffer, as opposed to a message buffer, so writing a + stream of bytes rather than discrete messages. Write as many bytes as + possible. */ + xShouldWrite = pdTRUE; + xDataLengthBytes = configMIN( xDataLengthBytes, xSpace ); + } + else if( xSpace >= xRequiredSpace ) + { + /* This is a message buffer, as opposed to a stream buffer, and there + is enough space to write both the message length and the message itself + into the buffer. Start by writing the length of the data, the data + itself will be written later in this function. */ + xShouldWrite = pdTRUE; + ( void ) prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) &( xDataLengthBytes ), sbBYTES_TO_STORE_MESSAGE_LENGTH ); + } + else + { + /* There is space available, but not enough space. */ + xShouldWrite = pdFALSE; + } + + if( xShouldWrite != pdFALSE ) + { + /* Writes the data itself. */ + xReturn = prvWriteBytesToBuffer( pxStreamBuffer, ( const uint8_t * ) pvTxData, xDataLengthBytes ); /*lint !e9079 Storage buffer is implemented as uint8_t for ease of sizing, alighment and access. */ + } + else + { + xReturn = 0; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, + void *pvRxData, + size_t xBufferLengthBytes, + TickType_t xTicksToWait ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; + + configASSERT( pvRxData ); + configASSERT( pxStreamBuffer ); + + /* This receive function is used by both message buffers, which store + discrete messages, and stream buffers, which store a continuous stream of + bytes. Discrete messages include an additional + sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the + message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + xBytesToStoreMessageLength = 0; + } + + if( xTicksToWait != ( TickType_t ) 0 ) + { + /* Checking if there is data and clearing the notification state must be + performed atomically. */ + taskENTER_CRITICAL(); + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + + /* If this function was invoked by a message buffer read then + xBytesToStoreMessageLength holds the number of bytes used to hold + the length of the next discrete message. If this function was + invoked by a stream buffer read then xBytesToStoreMessageLength will + be 0. */ + if( xBytesAvailable <= xBytesToStoreMessageLength ) + { + /* Clear notification state as going to wait for data. */ + ( void ) xTaskNotifyStateClear( NULL ); + + /* Should only be one reader. */ + configASSERT( pxStreamBuffer->xTaskWaitingToReceive == NULL ); + pxStreamBuffer->xTaskWaitingToReceive = xTaskGetCurrentTaskHandle(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + taskEXIT_CRITICAL(); + + if( xBytesAvailable <= xBytesToStoreMessageLength ) + { + /* Wait for data to be available. */ + traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ); + ( void ) xTaskNotifyWait( ( uint32_t ) 0, ( uint32_t ) 0, NULL, xTicksToWait ); + pxStreamBuffer->xTaskWaitingToReceive = NULL; + + /* Recheck the data available after blocking. */ + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + } + + /* Whether receiving a discrete message (where xBytesToStoreMessageLength + holds the number of bytes used to store the message length) or a stream of + bytes (where xBytesToStoreMessageLength is zero), the number of bytes + available must be greater than xBytesToStoreMessageLength to be able to + read bytes from the buffer. */ + if( xBytesAvailable > xBytesToStoreMessageLength ) + { + xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); + + /* Was a task waiting for space in the buffer? */ + if( xReceivedLength != ( size_t ) 0 ) + { + traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ); + sbRECEIVE_COMPLETED( pxStreamBuffer ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ); + mtCOVERAGE_TEST_MARKER(); + } + + return xReceivedLength; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xReturn, xBytesAvailable, xOriginalTail; +configMESSAGE_BUFFER_LENGTH_TYPE xTempReturn; + + configASSERT( pxStreamBuffer ); + + /* Ensure the stream buffer is being used as a message buffer. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH ) + { + /* The number of bytes available is greater than the number of bytes + required to hold the length of the next message, so another message + is available. Return its length without removing the length bytes + from the buffer. A copy of the tail is stored so the buffer can be + returned to its prior state as the message is not actually being + removed from the buffer. */ + xOriginalTail = pxStreamBuffer->xTail; + ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable ); + xReturn = ( size_t ) xTempReturn; + pxStreamBuffer->xTail = xOriginalTail; + } + else + { + /* The minimum amount of bytes in a message buffer is + ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is + less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid + value is 0. */ + configASSERT( xBytesAvailable == 0 ); + xReturn = 0; + } + } + else + { + xReturn = 0; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, + void *pvRxData, + size_t xBufferLengthBytes, + BaseType_t * const pxHigherPriorityTaskWoken ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; + + configASSERT( pvRxData ); + configASSERT( pxStreamBuffer ); + + /* This receive function is used by both message buffers, which store + discrete messages, and stream buffers, which store a continuous stream of + bytes. Discrete messages include an additional + sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the + message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + xBytesToStoreMessageLength = 0; + } + + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + + /* Whether receiving a discrete message (where xBytesToStoreMessageLength + holds the number of bytes used to store the message length) or a stream of + bytes (where xBytesToStoreMessageLength is zero), the number of bytes + available must be greater than xBytesToStoreMessageLength to be able to + read bytes from the buffer. */ + if( xBytesAvailable > xBytesToStoreMessageLength ) + { + xReceivedLength = prvReadMessageFromBuffer( pxStreamBuffer, pvRxData, xBufferLengthBytes, xBytesAvailable, xBytesToStoreMessageLength ); + + /* Was a task waiting for space in the buffer? */ + if( xReceivedLength != ( size_t ) 0 ) + { + sbRECEIVE_COMPLETED_FROM_ISR( pxStreamBuffer, pxHigherPriorityTaskWoken ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ); + + return xReceivedLength; +} +/*-----------------------------------------------------------*/ + +static size_t prvReadMessageFromBuffer( StreamBuffer_t *pxStreamBuffer, + void *pvRxData, + size_t xBufferLengthBytes, + size_t xBytesAvailable, + size_t xBytesToStoreMessageLength ) +{ +size_t xOriginalTail, xReceivedLength, xNextMessageLength; +configMESSAGE_BUFFER_LENGTH_TYPE xTempNextMessageLength; + + if( xBytesToStoreMessageLength != ( size_t ) 0 ) + { + /* A discrete message is being received. First receive the length + of the message. A copy of the tail is stored so the buffer can be + returned to its prior state if the length of the message is too + large for the provided buffer. */ + xOriginalTail = pxStreamBuffer->xTail; + ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xTempNextMessageLength, xBytesToStoreMessageLength, xBytesAvailable ); + xNextMessageLength = ( size_t ) xTempNextMessageLength; + + /* Reduce the number of bytes available by the number of bytes just + read out. */ + xBytesAvailable -= xBytesToStoreMessageLength; + + /* Check there is enough space in the buffer provided by the + user. */ + if( xNextMessageLength > xBufferLengthBytes ) + { + /* The user has provided insufficient space to read the message + so return the buffer to its previous state (so the length of + the message is in the buffer again). */ + pxStreamBuffer->xTail = xOriginalTail; + xNextMessageLength = 0; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + else + { + /* A stream of bytes is being received (as opposed to a discrete + message), so read as many bytes as possible. */ + xNextMessageLength = xBufferLengthBytes; + } + + /* Read the actual data. */ + xReceivedLength = prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) pvRxData, xNextMessageLength, xBytesAvailable ); /*lint !e9079 Data storage area is implemented as uint8_t array for ease of sizing, indexing and alignment. */ + + return xReceivedLength; +} +/*-----------------------------------------------------------*/ + +BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer ) +{ +const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +BaseType_t xReturn; +size_t xTail; + + configASSERT( pxStreamBuffer ); + + /* True if no bytes are available. */ + xTail = pxStreamBuffer->xTail; + if( pxStreamBuffer->xHead == xTail ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ) +{ +BaseType_t xReturn; +size_t xBytesToStoreMessageLength; +const StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; + + configASSERT( pxStreamBuffer ); + + /* This generic version of the receive function is used by both message + buffers, which store discrete messages, and stream buffers, which store a + continuous stream of bytes. Discrete messages include an additional + sbBYTES_TO_STORE_MESSAGE_LENGTH bytes that hold the length of the message. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesToStoreMessageLength = sbBYTES_TO_STORE_MESSAGE_LENGTH; + } + else + { + xBytesToStoreMessageLength = 0; + } + + /* True if the available space equals zero. */ + if( xStreamBufferSpacesAvailable( xStreamBuffer ) <= xBytesToStoreMessageLength ) + { + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xStreamBufferSendCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; + + configASSERT( pxStreamBuffer ); + + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxStreamBuffer )->xTaskWaitingToReceive != NULL ) + { + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToReceive, + ( uint32_t ) 0, + eNoAction, + pxHigherPriorityTaskWoken ); + ( pxStreamBuffer )->xTaskWaitingToReceive = NULL; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +BaseType_t xStreamBufferReceiveCompletedFromISR( StreamBufferHandle_t xStreamBuffer, BaseType_t *pxHigherPriorityTaskWoken ) +{ +StreamBuffer_t * const pxStreamBuffer = xStreamBuffer; +BaseType_t xReturn; +UBaseType_t uxSavedInterruptStatus; + + configASSERT( pxStreamBuffer ); + + uxSavedInterruptStatus = ( UBaseType_t ) portSET_INTERRUPT_MASK_FROM_ISR(); + { + if( ( pxStreamBuffer )->xTaskWaitingToSend != NULL ) + { + ( void ) xTaskNotifyFromISR( ( pxStreamBuffer )->xTaskWaitingToSend, + ( uint32_t ) 0, + eNoAction, + pxHigherPriorityTaskWoken ); + ( pxStreamBuffer )->xTaskWaitingToSend = NULL; + xReturn = pdTRUE; + } + else + { + xReturn = pdFALSE; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + +static size_t prvWriteBytesToBuffer( StreamBuffer_t * const pxStreamBuffer, const uint8_t *pucData, size_t xCount ) +{ +size_t xNextHead, xFirstLength; + + configASSERT( xCount > ( size_t ) 0 ); + + xNextHead = pxStreamBuffer->xHead; + + /* Calculate the number of bytes that can be added in the first write - + which may be less than the total number of bytes that need to be added if + the buffer will wrap back to the beginning. */ + xFirstLength = configMIN( pxStreamBuffer->xLength - xNextHead, xCount ); + + /* Write as many bytes as can be written in the first write. */ + configASSERT( ( xNextHead + xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void* ) ( &( pxStreamBuffer->pucBuffer[ xNextHead ] ) ), ( const void * ) pucData, xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + + /* If the number of bytes written was less than the number that could be + written in the first write... */ + if( xCount > xFirstLength ) + { + /* ...then write the remaining bytes to the start of the buffer. */ + configASSERT( ( xCount - xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) pxStreamBuffer->pucBuffer, ( const void * ) &( pucData[ xFirstLength ] ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + xNextHead += xCount; + if( xNextHead >= pxStreamBuffer->xLength ) + { + xNextHead -= pxStreamBuffer->xLength; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + pxStreamBuffer->xHead = xNextHead; + + return xCount; +} +/*-----------------------------------------------------------*/ + +static size_t prvReadBytesFromBuffer( StreamBuffer_t *pxStreamBuffer, uint8_t *pucData, size_t xMaxCount, size_t xBytesAvailable ) +{ +size_t xCount, xFirstLength, xNextTail; + + /* Use the minimum of the wanted bytes and the available bytes. */ + xCount = configMIN( xBytesAvailable, xMaxCount ); + + if( xCount > ( size_t ) 0 ) + { + xNextTail = pxStreamBuffer->xTail; + + /* Calculate the number of bytes that can be read - which may be + less than the number wanted if the data wraps around to the start of + the buffer. */ + xFirstLength = configMIN( pxStreamBuffer->xLength - xNextTail, xCount ); + + /* Obtain the number of bytes it is possible to obtain in the first + read. Asserts check bounds of read and write. */ + configASSERT( xFirstLength <= xMaxCount ); + configASSERT( ( xNextTail + xFirstLength ) <= pxStreamBuffer->xLength ); + ( void ) memcpy( ( void * ) pucData, ( const void * ) &( pxStreamBuffer->pucBuffer[ xNextTail ] ), xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + + /* If the total number of wanted bytes is greater than the number + that could be read in the first read... */ + if( xCount > xFirstLength ) + { + /*...then read the remaining bytes from the start of the buffer. */ + configASSERT( xCount <= xMaxCount ); + ( void ) memcpy( ( void * ) &( pucData[ xFirstLength ] ), ( void * ) ( pxStreamBuffer->pucBuffer ), xCount - xFirstLength ); /*lint !e9087 memcpy() requires void *. */ + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + /* Move the tail pointer to effectively remove the data read from + the buffer. */ + xNextTail += xCount; + + if( xNextTail >= pxStreamBuffer->xLength ) + { + xNextTail -= pxStreamBuffer->xLength; + } + + pxStreamBuffer->xTail = xNextTail; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCount; +} +/*-----------------------------------------------------------*/ + +static size_t prvBytesInBuffer( const StreamBuffer_t * const pxStreamBuffer ) +{ +/* Returns the distance between xTail and xHead. */ +size_t xCount; + + xCount = pxStreamBuffer->xLength + pxStreamBuffer->xHead; + xCount -= pxStreamBuffer->xTail; + if ( xCount >= pxStreamBuffer->xLength ) + { + xCount -= pxStreamBuffer->xLength; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + + return xCount; +} +/*-----------------------------------------------------------*/ + +static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, + uint8_t * const pucBuffer, + size_t xBufferSizeBytes, + size_t xTriggerLevelBytes, + uint8_t ucFlags ) +{ + /* Assert here is deliberately writing to the entire buffer to ensure it can + be written to without generating exceptions, and is setting the buffer to a + known value to assist in development/debugging. */ + #if( configASSERT_DEFINED == 1 ) + { + /* The value written just has to be identifiable when looking at the + memory. Don't use 0xA5 as that is the stack fill value and could + result in confusion as to what is actually being observed. */ + const BaseType_t xWriteValue = 0x55; + configASSERT( memset( pucBuffer, ( int ) xWriteValue, xBufferSizeBytes ) == pucBuffer ); + } /*lint !e529 !e438 xWriteValue is only used if configASSERT() is defined. */ + #endif + + ( void ) memset( ( void * ) pxStreamBuffer, 0x00, sizeof( StreamBuffer_t ) ); /*lint !e9087 memset() requires void *. */ + pxStreamBuffer->pucBuffer = pucBuffer; + pxStreamBuffer->xLength = xBufferSizeBytes; + pxStreamBuffer->xTriggerLevelBytes = xTriggerLevelBytes; + pxStreamBuffer->ucFlags = ucFlags; +} + +#if ( configUSE_TRACE_FACILITY == 1 ) + + UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) + { + return xStreamBuffer->uxStreamBufferNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) + { + xStreamBuffer->uxStreamBufferNumber = uxStreamBufferNumber; + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ + +#if ( configUSE_TRACE_FACILITY == 1 ) + + uint8_t ucStreamBufferGetStreamBufferType( StreamBufferHandle_t xStreamBuffer ) + { + return ( xStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ); + } + +#endif /* configUSE_TRACE_FACILITY */ +/*-----------------------------------------------------------*/ diff --git a/component/os/os_dep/include/osdep_service.h b/component/os/os_dep/include/osdep_service.h index 26eadb9d..6b9d91ba 100644 --- a/component/os/os_dep/include/osdep_service.h +++ b/component/os/os_dep/include/osdep_service.h @@ -952,6 +952,8 @@ u64 rtw_modular64(u64 x, u64 y); */ int rtw_get_random_bytes(void* dst, u32 size); +int rtw_get_random_bytes_f_rng( void *p_rng, unsigned char *output, size_t output_size ); + /** * @brief This function gets the available heap size. * @return The value of the available heap size. diff --git a/component/os/os_dep/osdep_service.c b/component/os/os_dep/osdep_service.c index bb56607e..7f21468f 100644 --- a/component/os/os_dep/osdep_service.c +++ b/component/os/os_dep/osdep_service.c @@ -1052,6 +1052,12 @@ int rtw_get_random_bytes(void* dst, u32 size) return 0; } +int rtw_get_random_bytes_f_rng( void *p_rng, unsigned char *output, size_t output_size ) +{ + (void*)p_rng; + return rtw_get_random_bytes(output, output_size); +} + u32 rtw_getFreeHeapSize(void) { if(osdep_service.rtw_getFreeHeapSize) diff --git a/component/soc/realtek/8710c/misc/bsp/image/bootloader.axf b/component/soc/realtek/8710c/misc/bsp/image/bootloader.axf index 77b1b404..8378bec8 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/image/bootloader.axf and b/component/soc/realtek/8710c/misc/bsp/image/bootloader.axf differ diff --git a/component/soc/realtek/8710c/misc/bsp/image/bootloader.out b/component/soc/realtek/8710c/misc/bsp/image/bootloader.out index 83b5b0a0..9b3b975f 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/image/bootloader.out and b/component/soc/realtek/8710c/misc/bsp/image/bootloader.out differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_boot.a b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_boot.a index 3d5d7fef..c273ca0b 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_boot.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_boot.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan.a b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan.a index ca63a3a6..13250a04 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp.a b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp.a index d4a3f4cb..96fd996b 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp_ns.a b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp_ns.a index 3a1389e2..a8a8e843 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp_ns.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_mp_ns.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_ns.a b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_ns.a index a5449ab2..9e500931 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_ns.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_wlan_ns.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_boot.a b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_boot.a index 118eba45..772d65fd 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_boot.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_boot.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan.a b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan.a index 5f4679cd..bdf59db4 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp.a b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp.a index 6475b82d..bb941678 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp_ns.a b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp_ns.a index 4f0be1e9..019fcc0a 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp_ns.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_mp_ns.a differ diff --git a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_ns.a b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_ns.a index ed78c198..974272ed 100644 Binary files a/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_ns.a and b/component/soc/realtek/8710c/misc/bsp/lib/common/IAR/lib_wlan_ns.a differ diff --git a/component/soc/realtek/8710c/misc/gcc_utility/LZMA_GenCompressedFW_linux b/component/soc/realtek/8710c/misc/gcc_utility/LZMA_GenCompressedFW_linux new file mode 100644 index 00000000..bfeb0d5f Binary files /dev/null and b/component/soc/realtek/8710c/misc/gcc_utility/LZMA_GenCompressedFW_linux differ diff --git a/component/soc/realtek/8710c/misc/gcc_utility/elf2bin.linux b/component/soc/realtek/8710c/misc/gcc_utility/elf2bin.linux index c6343f6e..5372be3b 100644 Binary files a/component/soc/realtek/8710c/misc/gcc_utility/elf2bin.linux and b/component/soc/realtek/8710c/misc/gcc_utility/elf2bin.linux differ diff --git a/component/soc/realtek/8710c/misc/gcc_utility/lzma_linux b/component/soc/realtek/8710c/misc/gcc_utility/lzma_linux new file mode 100644 index 00000000..5eac95d8 Binary files /dev/null and b/component/soc/realtek/8710c/misc/gcc_utility/lzma_linux differ diff --git a/component/soc/realtek/8710c/misc/gcc_utility/openocd/target/swj-dp.tcl b/component/soc/realtek/8710c/misc/gcc_utility/openocd/target/swj-dp.tcl new file mode 100644 index 00000000..1d274cb1 --- /dev/null +++ b/component/soc/realtek/8710c/misc/gcc_utility/openocd/target/swj-dp.tcl @@ -0,0 +1,34 @@ +# ARM Debug Interface V5 (ADI_V5) utility +# ... Mostly for SWJ-DP (not SW-DP or JTAG-DP, since +# SW-DP and JTAG-DP targets don't need to switch based +# on which transport is active. +# +# declare a JTAG or SWD Debug Access Point (DAP) +# based on the transport in use with this session. +# You can't access JTAG ops when SWD is active, etc. + +# params are currently what "jtag newtap" uses +# because OpenOCD internals are still strongly biased +# to JTAG .... but for SWD, "irlen" etc are ignored, +# and the internals work differently + +# for now, ignore non-JTAG and non-SWD transports +# (e.g. initial flash programming via SPI or UART) + +# split out "chip" and "tag" so we can someday handle +# them more uniformly irlen too...) + +if [catch {transport select}] { + echo "Error: unable to select a session transport. Can't continue." + shutdown +} + +proc swj_newdap {chip tag args} { + if [using_hla] { + eval hla newtap $chip $tag $args + } elseif [using_jtag] { + eval jtag newtap $chip $tag $args + } elseif [using_swd] { + eval swd newdap $chip $tag $args + } +} diff --git a/component/soc/realtek/8710c/misc/iar_utility/LZMA_GenCompressedFW.exe b/component/soc/realtek/8710c/misc/iar_utility/LZMA_GenCompressedFW.exe new file mode 100644 index 00000000..8a3450c3 Binary files /dev/null and b/component/soc/realtek/8710c/misc/iar_utility/LZMA_GenCompressedFW.exe differ diff --git a/component/soc/realtek/8710c/misc/iar_utility/elf2bin.exe b/component/soc/realtek/8710c/misc/iar_utility/elf2bin.exe index 62f6096b..3d3515a9 100644 Binary files a/component/soc/realtek/8710c/misc/iar_utility/elf2bin.exe and b/component/soc/realtek/8710c/misc/iar_utility/elf2bin.exe differ diff --git a/component/soc/realtek/8710c/misc/iar_utility/lzma.exe b/component/soc/realtek/8710c/misc/iar_utility/lzma.exe new file mode 100644 index 00000000..099d13ec Binary files /dev/null and b/component/soc/realtek/8710c/misc/iar_utility/lzma.exe differ diff --git a/component/soc/realtek/8710c/misc/iar_utility/postbuild_is.bat b/component/soc/realtek/8710c/misc/iar_utility/postbuild_is.bat index ea8389ae..369f870b 100644 --- a/component/soc/realtek/8710c/misc/iar_utility/postbuild_is.bat +++ b/component/soc/realtek/8710c/misc/iar_utility/postbuild_is.bat @@ -93,8 +93,22 @@ if not exist Debug\Exe\firmware_is.bin ( goto error_exit ) +:: delete currently existing compressed LZMA bin file +::if exist %cfgdir%\Exe\firmware_is_lzma.bin ( +:: DEL /F %cfgdir%\Exe\firmware_is_lzma.bin +::) + +:: generate compressed LZMA bin file +%tooldir%\LZMA_GenCompressedFW.exe %cfgdir%\Exe\firmware_is.bin +::if not exist Debug\Exe\firmware_is_lzma.bin ( +:: echo LZMA compressed FW not generated +:: echo firmware_is_lzma.bin isn't generated > postbuild_is_error.txt +:: goto error_exit +::) + :: generate firmware ota image %tooldir%\checksum.exe Debug\Exe\firmware_is.bin +::%tooldir%\checksum.exe Debug\Exe\firmware_is_lzma.bin ::generate flash image, including partition + bootloader + firmware if exist %cfgdir%\Exe\flash_is.bin ( diff --git a/doc/AN0004 Realtek low power wi-fi mp user guide.pdf b/doc/AN0004 Realtek low power wi-fi mp user guide.pdf new file mode 100644 index 00000000..60f8ae23 Binary files /dev/null and b/doc/AN0004 Realtek low power wi-fi mp user guide.pdf differ diff --git a/doc/AN0011 Realtek wlan simple configuration.pdf b/doc/AN0011 Realtek wlan simple configuration.pdf new file mode 100644 index 00000000..876c8afc Binary files /dev/null and b/doc/AN0011 Realtek wlan simple configuration.pdf differ diff --git a/doc/AN0012 Realtek secure socket layer(ssl).pdf b/doc/AN0012 Realtek secure socket layer(ssl).pdf new file mode 100644 index 00000000..1a52144b Binary files /dev/null and b/doc/AN0012 Realtek secure socket layer(ssl).pdf differ diff --git a/doc/AN0025 Realtek at command.pdf b/doc/AN0025 Realtek at command.pdf new file mode 100644 index 00000000..0b40d74c Binary files /dev/null and b/doc/AN0025 Realtek at command.pdf differ diff --git a/doc/AN0075 Realtek Ameba-all at command v2.0.pdf b/doc/AN0075 Realtek Ameba-all at command v2.0.pdf new file mode 100644 index 00000000..221f5228 Binary files /dev/null and b/doc/AN0075 Realtek Ameba-all at command v2.0.pdf differ diff --git a/doc/UM0005 Realtek wlan init and configuration.pdf b/doc/UM0005 Realtek wlan init and configuration.pdf new file mode 100644 index 00000000..fd1d22c4 Binary files /dev/null and b/doc/UM0005 Realtek wlan init and configuration.pdf differ diff --git a/doc/UM0006 Realtek wificonf application programming interface.pdf b/doc/UM0006 Realtek wificonf application programming interface.pdf new file mode 100644 index 00000000..53ac8b49 Binary files /dev/null and b/doc/UM0006 Realtek wificonf application programming interface.pdf differ diff --git a/doc/UM0013 Realtek Wi-Fi Feature List.pdf b/doc/UM0013 Realtek Wi-Fi Feature List.pdf new file mode 100644 index 00000000..cf059030 Binary files /dev/null and b/doc/UM0013 Realtek Wi-Fi Feature List.pdf differ diff --git a/doc/UM0203 Realtek Ameba Common BT Mesh User Manual EN.pdf b/doc/UM0203 Realtek Ameba Common BT Mesh User Manual EN.pdf new file mode 100644 index 00000000..f46d8bc3 Binary files /dev/null and b/doc/UM0203 Realtek Ameba Common BT Mesh User Manual EN.pdf differ diff --git a/doc/UM0501 Realtek AmebaZ2 BLE Stack User Manual CN.pdf b/doc/UM0501 Realtek AmebaZ2 BLE Stack User Manual CN.pdf new file mode 100644 index 00000000..d3cf33b9 Binary files /dev/null and b/doc/UM0501 Realtek AmebaZ2 BLE Stack User Manual CN.pdf differ diff --git a/doc/UM0501 Realtek AmebaZ2 BLE Stack User Manual EN.pdf b/doc/UM0501 Realtek AmebaZ2 BLE Stack User Manual EN.pdf new file mode 100644 index 00000000..7b40ca84 Binary files /dev/null and b/doc/UM0501 Realtek AmebaZ2 BLE Stack User Manual EN.pdf differ diff --git a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_is.ewp b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_is.ewp index a3d25e5a..12c59913 100644 --- a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_is.ewp +++ b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_is.ewp @@ -3009,6 +3009,9 @@ $PROJ_DIR$\..\..\..\component\common\utilities\http_client.c + + $PROJ_DIR$\..\..\..\component\common\utilities\uart_ymodem.c + $PROJ_DIR$\..\..\..\component\common\utilities\xml.c diff --git a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_ns.ewp b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_ns.ewp new file mode 100644 index 00000000..64cf7c57 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/application_ns.ewp @@ -0,0 +1,5921 @@ + + + 3 + + Debug + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\prebuild.vbs" "$PROJ_DIR$" "$PROJ_FNAME$" + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\postbuild_tz.vbs" "$TARGET_DIR$" "$PROJ_DIR$" "$CONFIG_NAME$" "$TOOLKIT_DIR$" + + + + ILINK + 0 + + 21 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + amazon_freertos + + ARM + + 1 + + General + 3 + + 31 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 10 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + 0 + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\prebuild.vbs" "$PROJ_DIR$" + CSCRIPT "$PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\iar_utility\postbuild_tz.vbs" "$TARGET_DIR$" "$PROJ_DIR$" "Debug" "$TOOLKIT_DIR$" + + + + ILINK + 0 + + 21 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + Coder + 0 + + + + + @ERAM + + Debug + + ICCARM + + 34 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + amazon_freertos + + ICCARM + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @SRAM + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\flash_api.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\flash_api_ext.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\flash_fatfs.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_flash.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_spic.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\power_mode_api.c + + + Debug + + ICCARM + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + amazon_freertos + + ICCARM + + 34 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + amazon + + Debug + + + demos + + common + + demo_runner + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\demo_runner\aws_demo_runner.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\mqtt\aws_subscribe_publish_loop.c + + + + devmode_key_provisioning + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\devmode_key_provisioning\aws_dev_mode_key_provisioning.c + + + + greengrass_connectivity + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\greengrass_connectivity\aws_greengrass_discovery_demo.c + + + + logging + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\logging\aws_logging_task_dynamic_buffers.c + + + + mqtt + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\mqtt\aws_hello_world.c + + + + ota + + Debug + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\ota\aws_ota_update_demo.c + + + + shadow + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\shadow\aws_shadow_lightbulb_on_off.c + + + + tcp + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\tcp\aws_simple_tcp_echo_server.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\tcp\aws_tcp_echo_client_separate_tasks.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\common\tcp\aws_tcp_echo_client_single_task.c + + + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\demos\realtek\ameba\common\application_code\aws_main.c + + + + lib + + bufferpool + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\bufferpool\aws_bufferpool_static_thread_safe.c + + + + crypto + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\crypto\aws_crypto.c + + + + greengrass + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\greengrass\aws_greengrass_discovery.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\greengrass\aws_helper_secure_connect.c + + + + mqtt + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\mqtt\aws_mqtt_agent.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\mqtt\aws_mqtt_lib.c + + + + ota + + Debug + amazon_freertos + + + portable + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\ota\portable\realtek\ameba\aws_ota_pal.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\ota\portable\realtek\ameba\aws_ota_rtl8710b.c + + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\ota\aws_ota_agent.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\ota\aws_ota_cbor.c + + + + pkcs11 + + mbedtls + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\pkcs11\mbedtls\aws_pkcs11_mbedtls.c + + + + portable + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\pkcs11\portable\realtek\ameba\aws_pkcs11_pal.c + + + + + secure_sockets + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\secure_sockets\portable\realtek\ameba\aws_secure_sockets.c + + + + shadow + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\shadow\aws_shadow.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\shadow\aws_shadow_json.c + + + + third_party + + jsmn + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\jsmn\jsmn.c + + + + mbedtls + + Debug + amazon_freertos + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\aes.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\aesni.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\arc4.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\asn1parse.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\asn1write.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\base64.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\bignum.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\blowfish.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\camellia.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ccm.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\certs.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\cipher.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\cipher_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\cmac.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ctr_drbg.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\debug.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\des.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\dhm.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ecdh.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ecdsa.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ecjpake.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ecp.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ecp_curves.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\entropy.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\entropy_poll.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\error.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\gcm.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\havege.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\hmac_drbg.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\md.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\md2.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\md4.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\md5.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\md_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\memory_buffer_alloc.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\net_sockets.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\oid.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\padlock.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pem.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pk.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pk_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pkcs12.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pkcs5.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pkparse.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\pkwrite.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\platform.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\platform_util.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ripemd160.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\rsa.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\rsa_internal.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\sha1.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\sha256.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\sha512.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_cache.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_ciphersuites.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_cli.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_cookie.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_srv.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_ticket.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\ssl_tls.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\threading.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\timing.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\version.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\version_features.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509_create.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509_crl.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509_crt.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509_csr.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509write_crt.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\x509write_csr.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\mbedtls\library\xtea.c + + + + tinycbor + + Debug + amazon_freertos + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\tinycbor\cborencoder.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\tinycbor\cborencoder_close_container_checked.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\tinycbor\cborerrorstrings.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\tinycbor\cborparser.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\tinycbor\cborparser_dup_string.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\tinycbor\cborpretty.c + + + + unity + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\unity\src\unity.c + + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\third_party\unity\extras\fixture\src\unity_fixture.c + + + + + tls + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\tls\aws_tls.c + + + + utils + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\utils\aws_system_init.c + + + + wifi + + $PROJ_DIR$\..\..\..\component\common\application\amazon\amazon-freertos-1.4.7\lib\wifi\portable\realtek\ameba\aws_wifi.c + + + + + + bluetooth + + board + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\bt_fwconfig.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\bt_mp_patch.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\bt_normal_patch.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\cycle_queue.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\data_uart\data_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\hci_board.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\hci\hci_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\os\freertos\osif_freertos.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\platform_utils.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\rtk_coex.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\trace_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\src\vendor_cmd\vendor_cmd.c + + + + common + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\ancs_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\bas.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\bas_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\bt_uart_bridge.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\dfu_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\dis.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\ftl\ftl.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\ftl\ftl_crypto_plugin_iar.o + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\gaps_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\hci_adapter.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\hci_process.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids_kb.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hids_rmc.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\ota_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\simple_ble_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\simple_ble_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\common\src\trace_task.c + + + + example + + ble_central + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_central\ble_central_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_central\ble_central_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_central\ble_central_at_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_central\ble_central_client_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_central\ble_central_link_mgr.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\client\gcs_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_central\user_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\mcu\module\data_uart_cmd\user_cmd_parse.c + + + + ble_peripheral + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\ble_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\ble_peripheral_at_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_peripheral\peripheral_app.c + + + + ble_scatternet + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_scatternet\ble_scatternet_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_scatternet\ble_scatternet_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_scatternet\ble_scatternet_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_scatternet\ble_scatternet_link_mgr.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\ble_scatternet\ble_scatternet_user_cmd.c + + + + bt_airsync_config + + $PROJ_DIR$\..\..\..\component\common\application\airsync\1.0.4\airsync_ble_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_airsync_config\bt_airsync_config_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_airsync_config\bt_airsync_config_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_airsync_config\bt_airsync_config_peripheral_app.c + + + $PROJ_DIR$\..\..\..\component\common\application\airsync\1.0.4\check_endian.c + + + $PROJ_DIR$\..\..\..\component\common\application\airsync\1.0.4\epb.c + + + $PROJ_DIR$\..\..\..\component\common\application\airsync\1.0.4\epb_MmBp.c + + + $PROJ_DIR$\..\..\..\component\common\application\airsync\1.0.4\epb_WristBand.c + + + $PROJ_DIR$\..\..\..\component\common\application\airsync\1.0.4\wechat_airsync_protocol.c + + + + bt_ancs + + Debug + amazon_freertos + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ancs\bt_ancs.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ancs\bt_ancs_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ancs\bt_ancs_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ancs\bt_ancs_main.c + + + + bt_beacon + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_beacon\bt_beacon_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_beacon\bt_beacon_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_beacon\bt_beacon_app_task.c + + + + bt_config + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_peripheral_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_config\bt_config_wifi.c + + + + bt_datatrans + + Debug + amazon_freertos + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_app_queue.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_at_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_at_hci_cmd_process.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_central_application.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_module_param_config.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_multilink_manager.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_peripheral_application.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_profile.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_datatrans\bt_datatrans_uart.c + + + + bt_fuzz_test + + Debug + amazon_freertos + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_at_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_link_mgr.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_simple_ble_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_fuzz_test\bt_fuzz_test_user_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\gls.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\hrs.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\src\ble\profile\server\ias.c + + + + bt_mesh + + Debug + amazon_freertos + + + mesh_common + + cmd + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\cmd\mesh_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\cmd\mesh_data_uart.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\cmd\mesh_user_cmd_parse.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\cmd\test_cmd.c + + + + common + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\api\bt_mesh_user_api.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\customer_dfu_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\datatrans_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\delay_msg_rsp.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\dfudep_service.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\ping_app.c + + + + model + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\realtek\datatrans_model.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\realtek\ping_control.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\realtek\tp_control.c + + + + profile + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\profile\datatrans_service.c + + + + test + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_app_user_cmd_parse.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_datatrans_write_api.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_device_test.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_malloc_free.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_receive_response.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_test_result.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_test\bt_mesh_timer_handler.c + + + + + mesh_device + + Debug + amazon_freertos + + + bt_mesh_device_rtk_demo + + Debug + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_device_rtk_demo\example_bt_mesh_device_rtk_demo.c + + + + common + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\api\device\device_idle_check.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\dfu_updater_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\light_server_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\scene_server_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\scheduler_server_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\time_server_app.c + + + + device + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\device\bt_mesh_device_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\device\bt_mesh_device_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\device\device_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\device\device_cmd.c + + + + device_multiple_profile + + Debug + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\device_multiple_profile\bt_mesh_device_multiple_profile_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\device_multiple_profile\bt_mesh_device_multiple_profile_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\device_multiple_profile\device_multiple_profile_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\device_multiple_profile\device_multiple_profile_cmd.c + + + + lib + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\lib\amebaz2\btmesh_dev.a + + + + model + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\delay_execution.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_on_off_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_transition_time.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\health_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_ctl_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_ctl_setup_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_ctl_temperature_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_hsl_hue_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_hsl_saturation_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_hsl_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_hsl_setup_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_lightness_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_lightness_setup_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_xyl_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_xyl_setup_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\scene_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\scene_setup_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\scheduler_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\scheduler_setup_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\time_server.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\time_setup_server.c + + + + profile + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\profile\datatrans_server.c + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\api\device\bt_mesh_device_api.c + + + + mesh_provisioner + + Debug + amazon_freertos + + + bt_mesh_provisioner_rtk_demo + + Debug + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_provisioner_rtk_demo\src\bt_mesh_app_http_intf.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_provisioner_rtk_demo\src\bt_mesh_app_lib_intf.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_provisioner_rtk_demo\src\bt_mesh_app_list_intf.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_provisioner_rtk_demo\src\bt_mesh_broadcast_demo.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_provisioner_rtk_demo\example_bt_mesh_provisioner_rtk_demo.c + + + + cmd + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\cmd\client_cmd.c + + + + common + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\dfu_distributor_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\generic_client_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\light_client_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\common\rmt_prov_client_app.c + + + + lib + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\lib\amebaz2\btmesh_prov.a + + + + model + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\blob_transfer_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\configuration_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\firmware_distribution_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\firmware_update_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_battery_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_default_transition_time_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_level_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_location_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_on_off_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_power_level_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_power_on_off_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\generic_property_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\health_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_ctl_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\realtek\light_cwrgb_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_hsl_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_lc_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_lightness_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\light_xyl_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\private_beacon_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\scene_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\scheduler_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\sensor_client.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\lib\model\time_client.c + + + + provisioner + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\provisioner\bt_mesh_provisioner_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\provisioner\bt_mesh_provisioner_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\provisioner\provisioner_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\provisioner\provisioner_cmd.c + + + + provisioner_multiple_profile + + Debug + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\provisioner_multiple_profile\bt_mesh_provisioner_multiple_profile_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\provisioner_multiple_profile\bt_mesh_provisioner_multiple_profile_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\provisioner_multiple_profile\provisioner_multiple_profile_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh_multiple_profile\provisioner_multiple_profile\provisioner_multiple_profile_cmd.c + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_mesh\api\provisioner\bt_mesh_provisioner_api.c + + + + + bt_ota_central_client + + Debug + amazon_freertos + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\bt_ota_central_client_app.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\bt_ota_central_client_app_main.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\bt_ota_central_client_app_task.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\bt_ota_central_client_at_cmd.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\bt_ota_central_client_link_mgr.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\bt_ota_central_client_test_image.c + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\example\bt_ota_central_client\insert_write.c + + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\bt_example_entry.c + + + + + cmsis + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram_ns\app_start.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\utilities\source\ram\libc_wrap.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram\mpu_config.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram\sys_irq.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\cmsis\rtl8710c\source\ram_ns\system_rtl8710c_ns.c + + + + console + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_bt.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_isp.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_lwip.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_media.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_mp.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_mp_ext2.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_sys.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\atcmd_wifi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\app\shell\cmd_shell.c + + + $PROJ_DIR$\..\..\..\component\common\api\at_cmd\log_service.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\low_level_io.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\driver\rtl_console.c + + + + lib + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\application_s_import_lib.o + + + $PROJ_DIR$\..\..\..\component\common\bluetooth\realtek\sdk\board\amebaz2\lib\btgap.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\lib\lib\hal_pmc.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_dct_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_eap_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_googlenest_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_http_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_p2p_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_soc_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_websocket_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_wlan_ns.a + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\bsp\lib\common\IAR\lib_wps_ns.a + + + + network + + api + + wifi + + rtw_wpa_supplicant + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\src\crypto\tls_polarssl.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_eap_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_p2p_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\rtw_wpa_supplicant\wpa_supplicant\wifi_wps_config.c + + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_conf.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_ind.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_promisc.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_simple_config.c + + + $PROJ_DIR$\..\..\..\component\common\api\wifi\wifi_util.c + + + + $PROJ_DIR$\..\..\..\component\common\api\lwip_netconf.c + + + + app + + mqtt + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTClient\MQTTClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTConnectClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTConnectServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTDeserializePublish.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTFormat.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTClient\MQTTFreertos.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTPacket.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSerializePublish.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSubscribeClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTSubscribeServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTUnsubscribeClient.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\MQTTUnsubscribeServer.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\V5\MQTTProperties.c + + + $PROJ_DIR$\..\..\..\component\common\application\mqtt\MQTTPacket\V5\MQTTV5Packet.c + + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\misc\platform\ota_8710c.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\ping_test.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client_ext.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client_ext_ns.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\utilities\ssl_client_ns.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\utilities\tcptest.c + + + $PROJ_DIR$\..\..\..\component\common\api\network\src\wlan_network.c + + + + coap + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_ameba_port.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_builder.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_header_check.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_parser.c + + + $PROJ_DIR$\..\..\..\component\common\network\coap\sn_coap_protocol.c + + + + googlenest + + $PROJ_DIR$\..\..\..\component\common\application\google\google_tls.c + + + + http + + $PROJ_DIR$\..\..\..\component\common\network\httpc\httpc_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\httpd\httpd_tls.c + + + + lwip + + api + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\api_lib.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\api_msg.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\err.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netdb.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\netifapi.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\api\tcpip.c + + + + core + + ipv4 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\autoip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\dhcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\etharp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\icmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\igmp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv4\ip4_frag.c + + + + ipv6 + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\dhcp6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ethip6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\icmp6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\inet6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ip6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ip6_addr.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\ip6_frag.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\mld6.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ipv6\nd6.c + + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\def.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\dns.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\inet_chksum.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\init.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\ip.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\mem.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\memp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\netif.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\pbuf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\raw.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\stats.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\sys.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp_in.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\tcp_out.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\timeouts.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\core\udp.c + + + + netif + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\src\netif\ethernet.c + + + + port + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\port\realtek\freertos\ethernetif.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\osdep\lwip_intf.c + + + $PROJ_DIR$\..\..\..\component\common\network\lwip\lwip_v2.0.2\port\realtek\freertos\sys_arch.c + + + + $PROJ_DIR$\..\..\..\component\common\network\dhcp\dhcps.c + + + $PROJ_DIR$\..\..\..\component\common\network\sntp\sntp.c + + + + mdns + + $PROJ_DIR$\..\..\..\component\common\network\mDNS\mDNSPlatform.c + + + + ssl + + mbedtls + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\aesni.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\blowfish.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\camellia.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ccm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\certs.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cipher.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cipher_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\cmac.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\debug.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\entropy.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\entropy_poll.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\error.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\gcm.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\havege.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md2.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md4.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\md_wrap.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\memory_buffer_alloc.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\net_sockets.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\padlock.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs11.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs12.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkcs5.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\pkparse.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\platform.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ripemd160.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\sha256.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cache.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_ciphersuites.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cli.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_cookie.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_srv.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_ticket.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\ssl_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\threading.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\timing.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\version.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\version_features.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_create.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_crl.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509write_crt.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\x509write_csr.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\mbedtls-2.4.0\library\xtea.c + + + + ssl_ram_map + + $PROJ_DIR$\..\..\..\component\common\network\ssl\ssl_ram_map\rom\rom_ssl_ram_map.c + + + $PROJ_DIR$\..\..\..\component\common\network\ssl\ssl_func_stubs\ssl_func_stubs.c + + + + + websocket + + $PROJ_DIR$\..\..\..\component\common\network\websocket\wsclient_tls.c + + + $PROJ_DIR$\..\..\..\component\common\network\websocket\wsserver_tls.c + + + + + os + + freertos + + portable + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\portable\IAR\RTL8710C\non_secure\port.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\portable\IAR\RTL8710C\non_secure\portasm.s + + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\croutine.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\event_groups.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\list.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\queue.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\stream_buffer.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\tasks.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_v10.2.0\Source\timers.c + + + + $PROJ_DIR$\..\..\..\component\os\freertos\cmsis_os.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\device_lock.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_cb.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_heap5_config.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_heap_rtk.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_pmu.c + + + $PROJ_DIR$\..\..\..\component\os\freertos\freertos_service.c + + + $PROJ_DIR$\..\..\..\component\os\os_dep\osdep_service.c + + + + peripheral + + api + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\crypto_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\dma_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\efuse_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\gpio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\gpio_irq_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\i2c_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pinmap.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pinmap_common.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\port_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\pwmout_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\reset_reason_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\rtc_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\serial_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\spdio_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\spi_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\sys_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\timer_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\us_ticker.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\us_ticker_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\wait_api.c + + + $PROJ_DIR$\..\..\..\component\common\mbed\targets\hal\rtl8710c\wdt_api.c + + + + hal + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_gdma.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_gpio.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_i2c.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_misc.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_pwm.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_sdio_dev.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram_ns\hal_ssi.c + + + $PROJ_DIR$\..\..\..\component\soc\realtek\8710c\fwlib\source\ram\hal_uart.c + + + + wlan + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\core\option\rtw_opt_rf_para_rtl8710c.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\drivers\wlan\realtek\src\core\option\rtw_opt_skbuf.c + + Debug + amazon_freertos + + + + + + user + + $PROJ_DIR$\..\src\main.c + + + + utilities + + example + + $PROJ_DIR$\..\..\..\component\common\example\amazon_awsiot\example_amazon_awsiot.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\example\amazon_freertos\example_amazon_freertos.c + + Debug + + + + $PROJ_DIR$\..\..\..\component\common\example\bcast\example_bcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\cJSON\example_cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\example\coap\example_coap.c + + + $PROJ_DIR$\..\..\..\component\common\example\coap_client\example_coap_client.c + + + $PROJ_DIR$\..\..\..\component\common\example\coap_server\example_coap_server.c + + + $PROJ_DIR$\..\..\..\component\common\example\dct\example_dct.c + + + $PROJ_DIR$\..\..\..\component\common\example\eap\example_eap.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\example\example_entry.c + + + $PROJ_DIR$\..\..\..\component\common\example\fatfs\example_fatfs.c + + + $PROJ_DIR$\..\..\..\component\common\example\get_beacon_frame\example_get_beacon_frame.c + + + $PROJ_DIR$\..\..\..\component\common\example\googlenest\example_google.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\example\high_load_memory_use\example_high_load_memory_use.c + + + $PROJ_DIR$\..\..\..\component\common\example\http_client\example_http_client.c + + + $PROJ_DIR$\..\..\..\component\common\example\http_download\example_http_download.c + + + $PROJ_DIR$\..\..\..\component\common\example\httpc\example_httpc.c + + + $PROJ_DIR$\..\..\..\component\common\example\httpd\example_httpd.c + + + $PROJ_DIR$\..\..\..\component\common\example\mbedtls_ecdhe\example_mbedtls_ecdhe.c + + + $PROJ_DIR$\..\..\..\component\common\example\mcast\example_mcast.c + + + $PROJ_DIR$\..\..\..\component\common\example\mqtt\example_mqtt.c + + + $PROJ_DIR$\..\..\..\component\common\example\nonblock_connect\example_nonblock_connect.c + + + $PROJ_DIR$\..\..\..\component\common\example\ota_http\example_ota_http.c + + + $PROJ_DIR$\..\..\..\component\common\example\rarp\example_rarp.c + + + $PROJ_DIR$\..\..\..\component\common\example\secure_boot\example_secure_boot.c + + + $PROJ_DIR$\..\..\..\component\common\example\secure_storage\example_secure_storage_ns.c + + + $PROJ_DIR$\..\..\..\component\common\example\sntp_showtime\example_sntp_showtime.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_select\example_socket_select.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_tcp_trx\example_socket_tcp_trx_1.c + + + $PROJ_DIR$\..\..\..\component\common\example\socket_tcp_trx\example_socket_tcp_trx_2.c + + + $PROJ_DIR$\..\..\..\component\common\example\ssl_download\example_ssl_download.c + + + $PROJ_DIR$\..\..\..\component\common\example\ssl_server\example_ssl_server.c + + + $PROJ_DIR$\..\..\..\component\common\example\tcp_keepalive\example_tcp_keepalive.c + + + $PROJ_DIR$\..\..\..\component\common\example\tickless_wifi_roaming\example_tickless_wifi_roaming.c + + + $PROJ_DIR$\..\..\..\component\common\example\trust_zone\example_trust_zone.c + + + $PROJ_DIR$\..\..\..\component\common\example\uart_atcmd\example_uart_atcmd.c + + + $PROJ_DIR$\..\..\..\component\common\example\wifi_mac_monitor\example_wifi_mac_monitor.c + + + $PROJ_DIR$\..\..\..\component\common\example\wifi_roaming\example_wifi_roaming.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_fast_connect\example_wlan_fast_connect.c + + + $PROJ_DIR$\..\..\..\component\common\example\wlan_scenario\example_wlan_scenario.c + + + $PROJ_DIR$\..\..\..\component\common\example\websocket_client\example_wsclient.c + + + $PROJ_DIR$\..\..\..\component\common\example\xml\example_xml.c + + + + FatFs + + disk_if + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\sdcard.c + + + $PROJ_DIR$\..\..\..\component\common\drivers\sdio\realtek\sdio_host\src\sdio_combine.c + + Debug + amazon_freertos + + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\disk_if\src\usbdisk.c + + + + fatfs_ext + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\fatfs_ext\src\ff_driver.c + + + + r0.10c + + option + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\option\ccsbcs.c + + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\diskio.c + + + $PROJ_DIR$\..\..\..\component\common\file_system\fatfs\r0.10c\src\ff.c + + + + + $PROJ_DIR$\..\..\..\component\common\utilities\cJSON.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\gb2unicode.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\http_client.c + + + $PROJ_DIR$\..\..\..\component\common\utilities\xml.c + + + diff --git a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/bootloader_lzma.icf b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/bootloader_lzma.icf new file mode 100644 index 00000000..b5d73c24 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/bootloader_lzma.icf @@ -0,0 +1,176 @@ +/*###ICF### Section handled by ICF editor, don't touch! ****/ +/*-Editor annotation file-*/ +/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ +/*-Specials-*/ +//define symbol __ICFEDIT_intvec_start__ = 0x00000000; + +/*-Memory Regions-*/ +define symbol __ICFEDIT_region_RAM_start__ = 0x10020000; +define symbol __ICFEDIT_region_RAM_end__ = 0x10037FFF; + +define symbol __ICFEDIT_region_VECTORS_start__ = 0x10038000; +define symbol __ICFEDIT_region_VECTORS_end__ = 0x100380FF; + +define symbol __ICFEDIT_region_FUNTAB_start__ = 0x10038100; +define symbol __ICFEDIT_region_FUNTAB_end__ = 0x1003817F; + +define symbol __ICFEDIT_region_RAM_RO_start__ = 0x10038180; +define symbol __ICFEDIT_region_RAM_RO_end__ = 0x1003E9FF; + +define symbol __ICFEDIT_region_PSRAM_RAM_start__ = 0x60000000; +define symbol __ICFEDIT_region_PSRAM_RAM_end__ = 0x603F0000; // 4MB + +/*-Sizes-*/ +/*define symbol __ICFEDIT_size_cstack__ = 0x400;*/ +/*define symbol __ICFEDIT_size_heap__ = 0x800;*/ +/**** End of ICF editor section. ###ICF###*/ + +define memory mem with size = 4G; + +define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; +define region RAM_RO_region = mem:[from __ICFEDIT_region_RAM_RO_start__ to __ICFEDIT_region_RAM_RO_end__]; + +define region FUNTAB_region = mem:[from __ICFEDIT_region_FUNTAB_start__ to __ICFEDIT_region_FUNTAB_end__]; +define region VECTORS_region = mem:[from __ICFEDIT_region_VECTORS_start__ to __ICFEDIT_region_VECTORS_end__]; + +define region ERAM_region = mem:[from __ICFEDIT_region_PSRAM_RAM_start__ to __ICFEDIT_region_PSRAM_RAM_end__]; +define exported symbol EramStart = start(ERAM_region); +define exported symbol EramEnd = end(ERAM_region); + +/*define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };*/ +/*define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };*/ + +//initialize by copy { readwrite }; +//initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application + +//do not initialize { section * }; +do not initialize { readwrite }; + +/**************************************** + * BD RAM Section config * + ****************************************/ + +keep { section .rom_temp.bss }; +keep { section .sboot.bss}; +define block ROM_TEMP_BSS +{ + section .rom_temp.bss +}; +define block SBOOT_BSS +{ + section .sboot.bss +}; +define block BOOT_TMP_BSS with fixed order +{ + block ROM_TEMP_BSS, + block SBOOT_BSS +}; + +//place at start of RAM_region +//{ +// block BOOT_TMP_BSS +//}; + +keep { section .ram_vector_table }; +define block RAM_VECTOR with alignment = 256, fixed order +{ + section .ram_vector_table +}; +place at start of VECTORS_region +{ + block RAM_VECTOR +}; + +keep { section .start.ram.data* }; +define block RAM_FUNTAB with alignment = 32, fixed order +{ + section .start.ram.data* +}; +place at start of FUNTAB_region +{ + block RAM_FUNTAB +}; + +define block RAM_BSS with fixed order +{ + section .bss*, + section COMMON, + zeroinit +}; + +define block SHT$$PREINIT_ARRAY { preinit_array }; +define block SHT$$INIT_ARRAY { init_array }; +define block CPP_INIT with alignment = 8, fixed order +{ + block SHT$$PREINIT_ARRAY, + block SHT$$INIT_ARRAY +}; + +define block RAM_DATA with fixed order +{ + section vtable, + section .data*, + block CPP_INIT +}; + +keep { section .start.ram.sign* }; +define block RAM_TEXT with alignment = 32, fixed order +{ + section .start.ram.sign*, + section .text* +}; + +define block RAM_RODATA with fixed order +{ + section .rodata*, + section .rodata.str1* +}; + +define block RAM_NOINIT with alignment = 32, fixed order +{ + section .sys_restore.bss*, + section .ram.bss.noinit*, + section .noinit +}; + +place at start of RAM_RO_region +{ + block RAM_DATA, + readwrite +}; + +place in RAM_RO_region +{ + block RAM_TEXT, + readonly, + block RAM_RODATA +}; + +place in RAM_RO_region +{ + block RAM_NOINIT +}; + +define block RAM_HEAP with fixed order +{ + section .heap* +}; + +place at start of RAM_region +{ + block BOOT_TMP_BSS, + block RAM_BSS, + block RAM_HEAP +}; + +define block RAM_STACK with fixed order +{ + section .stack* +}; +place at end of RAM_region +{ + block RAM_STACK +}; + +include "..\..\..\component\soc\realtek\8710c\misc\bsp\ROM\romsym_iar_is.so"; +define exported symbol Reset_Handler = 0x1001; diff --git a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/key.json b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/key.json new file mode 100644 index 00000000..5dcc4b09 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/key.json @@ -0,0 +1,15 @@ +{ + "__comment_EFUSE":"should keep these two key in safe place, or secure firmware protection is useless", + "EFUSE":{ + "__comment_privkey_enc":"this key in EFUSE SUPER SECURE ZONE", + "privkey_enc":"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E5F", + "__comment_privkey_hash":"this key in EFUSE SECURE ZONE, encrypted by upper key", + "privkey_hash":"64A7433FCF027D19DDA4D446EEF8E78A22A8C33CB2C337C07366C040612EE0F2" + }, + "TOOL":{ + "__comment_pubkey_enc":"public key for encryption", + "pubkey_enc":"8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F", + "__comment_pubkey_hash":"public key for hash, only for partition table and bootloader", + "pubkey_hash":"8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F" + } +} diff --git a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/partition.json b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/partition.json index bc4e2c36..d17a47a9 100644 --- a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/partition.json +++ b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/partition.json @@ -16,6 +16,7 @@ }, "key_exp_op": 2, "user_len": 256, + "user_ext": "FFFFFFFFFFFFFFFFFFFFFFFF", "user_bin":"user.bin", "items":["boot","fw1","fw2"] }, diff --git a/project/realtek_amebaz2_v0_example/EWARM-RELEASE/postbuild_is_log.txt b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/postbuild_is_log.txt new file mode 100644 index 00000000..5f540ea3 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/EWARM-RELEASE/postbuild_is_log.txt @@ -0,0 +1,352 @@ +key pair 1: + private key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e5f +public key: 8f40c5adb68f25624ae5b214ea767a6ec94d829d3d7b5e1ad1ba6f3e2138285f +key pair 1: + private key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e5f +public key: 8f40c5adb68f25624ae5b214ea767a6ec94d829d3d7b5e1ad1ba6f3e2138285f +key pair 1: + private key: 64a7433fcf027d19dda4d446eef8e78a22a8c33cb2c337c07366c040612ee0f2 +public key: 8f40c5adb68f25624ae5b214ea767a6ec94d829d3d7b5e1ad1ba6f3e2138285f +key pair 1: + private key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e5f +public key: 8f40c5adb68f25624ae5b214ea767a6ec94d829d3d7b5e1ad1ba6f3e2138285f +Load ENC Key 8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F + and HASH Key 8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F +secure_bit ==> 0 +MSG LEVEL: 3 + [INFO]checksum 0 +[INFO]signature 0 +[INFO]pattern 0 +[INFO]hash 1 +[INFO]filename Debug/Exe/bootloader.bin +[INFO]privkey enc A0D6DAE7E062CA94CBB294BF896B9F68CF8438774256AC7403CA4FD9A1C9564F +[INFO]privkey hash 882AA16C8C44A7760AA8C9AB22E3568C6FA16C2AFA4F0CEA29A10ABCDF60E44F +[INFO]pubkey enc efuse (null) +[INFO]pubkey hash efuse (null) +[INFO]hash key (null) +[INFO]--flash offset 0 +[INFO]--source file Debug/Exe/bootloader.out +[INFO]---header-next (null) + [INFO]---header-type BOOT + [INFO]---header-encrypt 0 + [INFO]---header-serial 0 + [INFO]---header-user_key1 AA0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F + [INFO]---header-user_key2 (null) + [INFO]----shdr type SRAM +[INFO]----shdr enc 0 +[INFO]----option (null) +[INFO]----ram addr 0 +[INFO]----start RAM_FUNTAB$$Base +[INFO]----end RAM_RODATA$$Limit +[INFO]----entrytab gRamStartFun +[INFO]----file (null) +[INFO]-- +[INFO] +[INFO]checksum 0 +[INFO]signature 0 +[INFO]pubkey efuse (null) +[INFO]efuse enc pubkey: 8f 40 c5 ad b6 8f 25 62 4a e5 b2 14 ea 76 7a 6e c9 4d 82 9d 3d 7b 5e 1a d1 ba 6f 3e 21 38 28 5f +[INFO]efuse hash pubkey: 8f 40 c5 ad b6 8f 25 62 4a e5 b2 14 ea 76 7a 6e c9 4d 82 9d 3d 7b 5e 1a d1 ba 6f 3e 21 38 28 5f +[INFO]efuse enc privkey: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 5f +[INFO]Source name Debug/Exe/bootloader.out +[INFO]--flash offset 0 +[INFO]enc privkey: a0 d6 da e7 e0 62 ca 94 cb b2 94 bf 89 6b 9f 68 cf 84 38 77 42 56 ac 74 03 ca 4f d9 a1 c9 56 4f +[INFO]enc pubkey: 68 51 3e f8 3e 39 6b 12 ba 05 9a 90 0f 36 b6 d3 1d 11 fe 1c 5d 25 eb 8a a7 c5 50 30 7f 9c 24 05 +[INFO]hash privkey: 88 2a a1 6c 8c 44 a7 76 0a a8 c9 ab 22 e3 56 8c 6f a1 6c 2a fa 4f 0c ea 29 a1 0a bc df 60 e4 4f +[INFO]hash pubkey: 48 ad 23 dd bd ac 9e 65 71 9d b7 d3 94 d4 4d 62 82 0d 19 e5 0d 68 37 67 74 23 7e 98 d2 30 5e 6a +[INFO]AES key: 51 80 a8 8b ac 99 b5 f3 70 c0 c4 80 0e 71 9e 76 d2 9a 20 4a f8 5d 45 6c db a6 39 78 09 6c 7e 3c +[INFO]Use Default Hash key: 47 e5 66 13 35 a4 c5 e0 a9 4d 69 f3 c7 37 d5 4f 23 83 79 13 32 93 97 53 ef 24 27 96 08 f6 d7 2b +[INFO]filename Debug/Exe/bootloader.bin +[INFO]----ram addr 0 +[INFO]----start symbol RAM_FUNTAB$$Base, addr 10038100 + [INFO]----end symbol RAM_RODATA$$Limit, addr 1003e250 + [INFO] NO SECTION !!!!! +[INFO]----offset addr 0 + [INFO]----file (null) +[INFO]c04dd0 42a0e0 10038100 + [INFO]----phdr c03b04 seg len 6160 offset in file 34 +[INFO]-------- acquire by range +[INFO]---- base 10038100 length 6160 +[INFO]-------- found section A1 +[INFO]-------- found section A2 +[INFO]-------- found section P1-P2 +[INFO]-------- +[INFO]-- +[INFO]HASH start 0, end 6220 +[INFO]Hash key: 47 e5 66 13 35 a4 c5 e0 a9 4d 69 f3 c7 37 d5 4f 23 83 79 13 32 93 97 53 ef 24 27 96 08 f6 d7 2b +[INFO]SHA256HMAC: 16ca2aae40ed8cb580e49a5ed6da0649bb7983304469c5e19ddb82dec47094b3 +[INFO] +Load ENC Key 8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F + and HASH Key 8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F +secure_bit ==> 0 +MSG LEVEL: 3 + [INFO]checksum 0 +[INFO]signature 0 +[INFO]pattern 1 +[INFO]hash 1 +[INFO]filename Debug/Exe/partition.bin +[INFO]privkey enc A0D6DAE7E062CA94CBB294BF896B9F68CF8438774256AC7403CA4FD9A1C9564F +[INFO]privkey hash 882AA16C8C44A7760AA8C9AB22E3568C6FA16C2AFA4F0CEA29A10ABCDF60E44F +[INFO]pubkey enc efuse (null) +[INFO]pubkey hash efuse (null) +[INFO]hash key (null) +[INFO]--flash offset 20 +[INFO]--source file (null) +[INFO]---header-next (null) + [INFO]---header-type PARTAB + [INFO]---header-encrypt 0 + [INFO]---header-serial 0 + [INFO]---header-user_key1 (null) + [INFO]---header-user_key2 (null) + [INFO]--Partition Table +[INFO]----num 2 +[INFO]----fw1_idx 1 +[INFO]----fw2_idx 2 +[INFO]----user_len 256 +[INFO]----user_bin user.bin +[INFO]----ota_trap 0 +[INFO]----mp_trap 0 +[INFO]------start 4000 +[INFO]------length 8000 +[INFO]------type BOOT +[INFO]------dbg skip 0 +[INFO]------hash key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +[INFO]------start c000 +[INFO]------length f8000 +[INFO]------type FW1 +[INFO]------dbg skip 0 +[INFO]------hash key 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E5F +[INFO]------start 104000 +[INFO]------length f8000 +[INFO]------type FW2 +[INFO]------dbg skip 0 +[INFO]------hash key 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E5F +[INFO]-- +[INFO] +[INFO]checksum 0 +[INFO]signature 0 +[INFO]pubkey efuse (null) +[INFO]efuse enc pubkey: 8f 40 c5 ad b6 8f 25 62 4a e5 b2 14 ea 76 7a 6e c9 4d 82 9d 3d 7b 5e 1a d1 ba 6f 3e 21 38 28 5f +[INFO]efuse hash pubkey: 8f 40 c5 ad b6 8f 25 62 4a e5 b2 14 ea 76 7a 6e c9 4d 82 9d 3d 7b 5e 1a d1 ba 6f 3e 21 38 28 5f +[INFO]efuse enc privkey: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 5f +[INFO]Source name (null) +[INFO]--flash offset 20 +padding 0xff size 16 +[INFO]enc privkey: a0 d6 da e7 e0 62 ca 94 cb b2 94 bf 89 6b 9f 68 cf 84 38 77 42 56 ac 74 03 ca 4f d9 a1 c9 56 4f +[INFO]enc pubkey: 68 51 3e f8 3e 39 6b 12 ba 05 9a 90 0f 36 b6 d3 1d 11 fe 1c 5d 25 eb 8a a7 c5 50 30 7f 9c 24 05 +[INFO]hash privkey: 88 2a a1 6c 8c 44 a7 76 0a a8 c9 ab 22 e3 56 8c 6f a1 6c 2a fa 4f 0c ea 29 a1 0a bc df 60 e4 4f +[INFO]hash pubkey: 48 ad 23 dd bd ac 9e 65 71 9d b7 d3 94 d4 4d 62 82 0d 19 e5 0d 68 37 67 74 23 7e 98 d2 30 5e 6a +[INFO]AES key: 51 80 a8 8b ac 99 b5 f3 70 c0 c4 80 0e 71 9e 76 d2 9a 20 4a f8 5d 45 6c db a6 39 78 09 6c 7e 3c +[INFO]Use Default Hash key: 47 e5 66 13 35 a4 c5 e0 a9 4d 69 f3 c7 37 d5 4f 23 83 79 13 32 93 97 53 ef 24 27 96 08 f6 d7 2b +[INFO]filename Debug/Exe/partition.bin +[ERR]user binary user.bin not exist + [INFO]-- +[INFO]HASH start 20, end 2a0 +[INFO]Hash key: 47 e5 66 13 35 a4 c5 e0 a9 4d 69 f3 c7 37 d5 4f 23 83 79 13 32 93 97 53 ef 24 27 96 08 f6 d7 2b +[INFO]SHA256HMAC: 52ed5551ad40981d2a45b595a4086ec4678cbfda9af76274a0d98ee9b4fac2b6 +[INFO] +Load ENC Key 8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F + and HASH Key 8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F +secure_bit ==> 0 +MSG LEVEL: 3 + [INFO]checksum 0 +[INFO]signature 0 +[INFO]pattern 0 +[INFO]hash 0 +[INFO]filename Debug/Exe/firmware_is.bin +[INFO]privkey enc A0D6DAE7E062CA94CBB294BF896B9F68CF8438774256AC7403CA4FD9A1C9564F +[INFO]privkey hash (null) +[INFO]pubkey enc efuse (null) +[INFO]pubkey hash efuse (null) +[INFO]hash key (null) +[INFO]--flash offset 0 +[INFO]--source file Debug/Exe/application_is.out +[INFO]---header-next (null) + [INFO]---header-type FWHS_S + [INFO]---header-encrypt 0 + [INFO]---header-serial 100 + [INFO]---header-user_key1 (null) + [INFO]---header-user_key2 BB0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F + [INFO]---fst-enc algo 1 + [INFO]---fst-hash algo 1 + [INFO]---fst-part size 0 + [INFO]---fst-cipher key (null) + [INFO]---fst-cipher iv (null) + [INFO]---fst-validpat 0001020304050607 + [INFO]---fst-hash en 1 + [INFO]---fst-enc en 0 + [INFO]----shdr type SRAM +[INFO]----shdr enc 0 +[INFO]----option (null) +[INFO]----ram addr 0 +[INFO]----start (null) +[INFO]----end (null) +[INFO]----entrytab gRamStartFun +[INFO]----file (null) +[INFO]------ FIRMWARE_FUNTAB* +[INFO]------ FIRMWARE_SIGN* +[INFO]------ FIRMWARE_SRAM_RO* +[INFO]------ FIRMWARE_SRAM_RW* +[INFO]----shdr type PSRAM +[INFO]----shdr enc 0 +[INFO]----option (null) +[INFO]----ram addr 0 +[INFO]----start (null) +[INFO]----end (null) +[INFO]----entrytab (null) +[INFO]----file (null) +[INFO]------ FIRMWARE_ERAM_RO* +[INFO]------ FIRMWARE_ERAM_RW* +[INFO]-- +[INFO]--flash offset 0 +[INFO]--source file Debug/Exe/application_is.out +[INFO]---header-next (null) + [INFO]---header-type XIP + [INFO]---header-encrypt 0 + [INFO]---header-serial 0 + [INFO]---header-user_key1 (null) + [INFO]---header-user_key2 (null) + [INFO]---fst-enc algo 1 + [INFO]---fst-hash algo 1 + [INFO]---fst-part size 0 + [INFO]---fst-cipher key (null) + [INFO]---fst-cipher iv (null) + [INFO]---fst-validpat 0001020304050607 + [INFO]---fst-hash en 1 + [INFO]---fst-enc en 0 + [INFO]----shdr type XIP +[INFO]----shdr enc 0 +[INFO]----option (null) +[INFO]----ram addr 0 +[INFO]----start (null) +[INFO]----end (null) +[INFO]----entrytab (null) +[INFO]----file (null) +[INFO]------ FIRMWARE_XIP_C* +[INFO]-- +[INFO]--flash offset 0 +[INFO]--source file Debug/Exe/application_is.out +[INFO]---header-next (null) + [INFO]---header-type XIP + [INFO]---header-encrypt 0 + [INFO]---header-serial 0 + [INFO]---header-user_key1 (null) + [INFO]---header-user_key2 (null) + [INFO]---fst-enc algo 1 + [INFO]---fst-hash algo 1 + [INFO]---fst-part size 0 + [INFO]---fst-cipher key (null) + [INFO]---fst-cipher iv (null) + [INFO]---fst-validpat 0001020304050607 + [INFO]---fst-hash en 1 + [INFO]---fst-enc en 0 + [INFO]----shdr type XIP +[INFO]----shdr enc 0 +[INFO]----option (null) +[INFO]----ram addr 0 +[INFO]----start (null) +[INFO]----end (null) +[INFO]----entrytab (null) +[INFO]----file (null) +[INFO]------ FIRMWARE_XIP_P* +[INFO]-- +[INFO] +[INFO]efuse enc pubkey: 8f 40 c5 ad b6 8f 25 62 4a e5 b2 14 ea 76 7a 6e c9 4d 82 9d 3d 7b 5e 1a d1 ba 6f 3e 21 38 28 5f +[INFO]efuse enc privkey: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 5f +[INFO]Hash key from Partition table +[INFO]hash key: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 5f +[INFO]enc privkey: a0 d6 da e7 e0 62 ca 94 cb b2 94 bf 89 6b 9f 68 cf 84 38 77 42 56 ac 74 03 ca 4f d9 a1 c9 56 4f +[INFO]enc pubkey: 68 51 3e f8 3e 39 6b 12 ba 05 9a 90 0f 36 b6 d3 1d 11 fe 1c 5d 25 eb 8a a7 c5 50 30 7f 9c 24 05 +[INFO]AES key: 51 80 a8 8b ac 99 b5 f3 70 c0 c4 80 0e 71 9e 76 d2 9a 20 4a f8 5d 45 6c db a6 39 78 09 6c 7e 3c +[INFO]Source name Debug/Exe/application_is.out +[INFO]Current pos 1a0 Prev SHDR pos 0 +[INFO]-------- +[INFO]---- FIRMWARE_FUNTAB* +[INFO]---- 10000480 +[INFO]---- a27c +[INFO]---- 70 +[INFO]-------- +[INFO]-------- +[INFO]---- FIRMWARE_SIGN* +[INFO]---- 100004f0 +[INFO]---- a2ec +[INFO]---- c +[INFO]-------- +[INFO]-------- +[INFO]---- FIRMWARE_SRAM_RO* +[INFO]---- 10000e00 +[INFO]---- abf0 +[INFO]---- 24f8 +[INFO]-------- +[INFO]-------- +[INFO]---- FIRMWARE_SRAM_RW* +[INFO]---- 10000500 +[INFO]---- a2f8 +[INFO]---- 8f8 +[INFO]-------- +[INFO]-------- acquire by sections +[INFO]---- base 10000480 length 2e80 +[INFO]-------- +[INFO]---- target offset 0 elf offset a27c size 70 +[INFO]---- target offset 70 elf offset a2ec size c +[INFO]---- target offset 980 elf offset abf0 size 24f8 +[INFO]---- target offset 80 elf offset a2f8 size 8f8 +[INFO] SECTION SET !!!!! +[INFO]0 42a0e0 10000480 + [INFO]Current pos 30a0 Prev SHDR pos 1a0 +[INFO]-------- +[INFO]---- FIRMWARE_ERAM_RO* +[INFO]---- 60000000 +[INFO]---- d0e8 +[INFO]---- 0 +[INFO]-------- +[INFO]-------- +[INFO]---- FIRMWARE_ERAM_RW* +[INFO]---- 0 +[INFO]---- 0 +[INFO]---- 0 +[INFO]-------- +[INFO]-------- acquire by sections +[INFO]---- base 60000000 length 0 +[INFO]-------- +[INFO]NEXT align to 16K +[INFO]HASH: signature +[INFO]Hash result: d7 d7 ec d7 83 14 fb f0 60 f8 e7 6f 7e 0b df fc f0 27 47 12 17 7b 0e 79 4a 01 89 d1 a7 1b c3 c2 +[INFO]PADDING to 16K + [INFO]Source name Debug/Exe/application_is.out +[INFO]Current pos c0 Prev SHDR pos 0 +[INFO]-------- +[INFO]---- FIRMWARE_XIP_C* +[INFO]---- 9b000140 +[INFO]---- d0e8 +[INFO]---- 4da08 +[INFO]-------- +[INFO]-------- acquire by sections +[INFO]---- base 9b000140 length 4da20 +[INFO]-------- +[INFO]---- target offset 0 elf offset d0e8 size 4da08 +[INFO] SECTION SET !!!!! +[INFO]d0c478 42a0e0 ffffffff + [INFO]NEXT align to 16K +[INFO]Hash result: a5 37 b3 4c 45 ce 4f 80 95 8c c1 15 5f fe 70 3a 0a 15 c6 ba 83 69 9d a3 de c8 b6 5d 49 a5 6b 65 +[INFO]PADDING to 16K + [INFO]Source name Debug/Exe/application_is.out +[INFO]Current pos c0 Prev SHDR pos 0 +[INFO]-------- +[INFO]---- FIRMWARE_XIP_P* +[INFO]---- 9b800140 +[INFO]---- 5aaf0 +[INFO]---- 1ec96 +[INFO]-------- +[INFO]-------- acquire by sections +[INFO]---- base 9b800140 length 1eca0 +[INFO]-------- +[INFO]---- target offset 0 elf offset 5aaf0 size 1ec96 +[INFO] SECTION SET !!!!! +[INFO]d11488 42a0e0 ffffffff + [INFO]Hash result: 80 7b da 0f af 66 0f 8d 3b 30 22 13 f1 2e 5f 08 1a 23 36 45 dd 8b 16 f7 13 3a 03 95 1d 0c 30 c6 +[INFO]PADDING to 64B + [INFO] +PTAB ==> Debug\Exe\partition.bin +BOOT ==> Debug\Exe\bootloader.bin +FW1 ==> Debug\Exe\firmware_is.bin diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.is.mk b/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.is.mk index 1335f0b7..d42618b9 100644 --- a/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.is.mk +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.is.mk @@ -661,7 +661,13 @@ endif $(ELF2BIN) convert amebaz2_bootloader.json BOOTLOADER secure_bit=0 $(ELF2BIN) convert amebaz2_bootloader.json PARTITIONTABLE secure_bit=0 $(ELF2BIN) convert amebaz2_firmware_is.json FIRMWARE secure_bit=0 +#ifeq ($(findstring Linux, $(OS)), Linux) +# chmod 777 $(AMEBAZ2_GCCTOOLDIR)/LZMA_GenCompressedFW_linux +#endif +# $(LZMA_PY) $(BIN_DIR)/firmware_is.bin + $(CHKSUM) $(BIN_DIR)/firmware_is.bin +# $(CHKSUM) $(BIN_DIR)/firmware_is_lzma.bin $(ELF2BIN) combine $(BIN_DIR)/flash_is.bin PTAB=partition.bin,BOOT=$(BOOT_BIN_DIR)/bootloader.bin,FW1=$(BIN_DIR)/firmware_is.bin # Generate build info diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.ns.mk b/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.ns.mk new file mode 100644 index 00000000..0a25c5d1 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.ns.mk @@ -0,0 +1,1084 @@ + +# Initialize tool chain +# ------------------------------------------------------------------- + +AMEBAZ2_TOOLDIR = ../../../component/soc/realtek/8710c/misc/iar_utility +AMEBAZ2_GCCTOOLDIR = ../../../component/soc/realtek/8710c/misc/gcc_utility +AMEBAZ2_BSPDIR = ../../../component/soc/realtek/8710c/misc/bsp +AMEBAZ2_BOOTLOADERDIR = $(AMEBAZ2_BSPDIR)/image +AMEBAZ2_ROMSYMDIR = $(AMEBAZ2_BSPDIR)/ROM + +OS := $(shell uname) + +CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi- + +# Compilation tools +AR = $(CROSS_COMPILE)ar +CC = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)as +NM = $(CROSS_COMPILE)nm +LD = $(CROSS_COMPILE)gcc +GDB = $(CROSS_COMPILE)gdb +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +OS := $(shell uname) + +LDSCRIPT := ./rtl8710c_ram_ns.ld + +# Initialize target name and target object files +# ------------------------------------------------------------------- + +all: build_info application_ns manipulate_images + +mp: build_info application_ns manipulate_images + +TARGET=application_ns + +OBJ_DIR=$(TARGET)/Debug/obj +BIN_DIR=$(TARGET)/Debug/bin +INFO_DIR=$(TARGET)/Debug/info + + +ROMIMG = + +# Decide if 64 bit time wrapper is to be included +# ------------------------------------------------------------------- +#SYSTEM_TIME64_MAKE_OPTION = 1 + +# Include folder list +# ------------------------------------------------------------------- + +INCLUDES = +INCLUDES += -I../inc + +INCLUDES += -I../../../component/common/api +INCLUDES += -I../../../component/common/api/at_cmd +INCLUDES += -I../../../component/common/api/platform +INCLUDES += -I../../../component/common/api/wifi +INCLUDES += -I../../../component/common/api/wifi/rtw_wpa_supplicant/src +INCLUDES += -I../../../component/common/api/network/include +INCLUDES += -I../../../component/common/application +INCLUDES += -I../../../component/common/application/mqtt/MQTTClient +INCLUDES += -I../../../component/common/application/mqtt/MQTTPacket/V5 +INCLUDES += -I../../../component/common/application/mqtt/MQTTPacket +INCLUDES += -I../../../component/common/example +INCLUDES += -I../../../component/common/file_system +INCLUDES += -I../../../component/common/file_system/dct +INCLUDES += -I../../../component/common/file_system/fatfs +INCLUDES += -I../../../component/common/file_system/fatfs/r0.10c/include +INCLUDES += -I../../../component/common/file_system/ftl +INCLUDES += -I../../../component/common/utilities +INCLUDES += -I../../../component/common/mbed/hal +INCLUDES += -I../../../component/common/mbed/hal_ext +INCLUDES += -I../../../component/common/mbed/targets/hal/rtl8710c +INCLUDES += -I../../../component/common/network +INCLUDES += -I../../../component/common/network/coap/include +INCLUDES += -I../../../component/common/network/libcoap/include +INCLUDES += -I../../../component/common/network/http2/nghttp2-1.31.0/includes +INCLUDES += -I../../../component/common/network/lwip/lwip_v2.0.2/src/include +INCLUDES += -I../../../component/common/network/lwip/lwip_v2.0.2/src/include/lwip +INCLUDES += -I../../../component/common/network/lwip/lwip_v2.0.2/port/realtek +INCLUDES += -I../../../component/common/network/lwip/lwip_v2.0.2/port/realtek/freertos +INCLUDES += -I../../../component/common/network/ssl/mbedtls-2.4.0/include +INCLUDES += -I../../../component/common/network/ssl/ssl_ram_map/rom +INCLUDES += -I../../../component/common/drivers/wlan/realtek/include +INCLUDES += -I../../../component/common/drivers/wlan/realtek/src/osdep +INCLUDES += -I../../../component/common/test +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/app +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/bluetooth/gap +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/bluetooth/profile +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/client +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/bluetooth/profile/server +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/os +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/platform +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/inc/stack +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/amebaz2/lib +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/data_uart +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/hci +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/os +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/vendor_cmd +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_config +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/ble_central +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/ble_peripheral +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/ble_scatternet +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_ancs +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/gap +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/inc/amebaz2 +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/platform +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/utility +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/device +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/common +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/inc +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/src/mcu/module/data_uart_cmd +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/board/common/inc +INCLUDES += -I../../../component/common/bluetooth/realtek/sdk/example/bt_airsync_config +INCLUDES += -I../../../component/common/media/rtp_codec +INCLUDES += -I../../../component/common/media/mmfv2 +INCLUDES += -I../../../component/common/application/airsync/1.0.4 + +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/rtl8710c/include +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/rtl8710c/lib/include +INCLUDES += -I../../../component/soc/realtek/8710c/fwlib/include +INCLUDES += -I../../../component/soc/realtek/8710c/fwlib/lib/include +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/cmsis-core/include +INCLUDES += -I../../../component/soc/realtek/8710c/app/rtl_printf/include +INCLUDES += -I../../../component/soc/realtek/8710c/app/shell +INCLUDES += -I../../../component/soc/realtek/8710c/app/stdio_port +INCLUDES += -I../../../component/soc/realtek/8710c/misc/utilities/include +INCLUDES += -I../../../component/soc/realtek/8710c/mbed-drivers/include +INCLUDES += -I../../../component/soc/realtek/8710c/misc/platform +INCLUDES += -I../../../component/soc/realtek/8710c/misc/driver +INCLUDES += -I../../../component/soc/realtek/8710c/misc/os + +INCLUDES += -I../../../component/os/freertos +INCLUDES += -I../../../component/os/freertos/freertos_v10.2.0/Source/include +INCLUDES += -I../../../component/os/freertos/freertos_v10.2.0/Source/portable/GCC/RTL8710C/secure +INCLUDES += -I../../../component/os/freertos/freertos_v10.2.0/Source/portable/GCC/RTL8710C/non_secure +INCLUDES += -I../../../component/os/os_dep/include + +# Source file list +# ------------------------------------------------------------------- + +SRC_C = +SRAM_C = +ERAM_C = + +#bluetooth - board +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/hci/bt_fwconfig.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/hci/bt_mp_patch.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/hci/bt_normal_patch.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/common/src/cycle_queue.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/data_uart/data_uart.c +SRC_C += ../../../component/common/file_system/ftl/ftl.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/hci/hci_board.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/hci/hci_uart.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/common/os/freertos/osif_freertos.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/platform_utils.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/rtk_coex.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/trace_uart.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/src/vendor_cmd/vendor_cmd.c + +#bluetooth - common +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/ancs_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/bas.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/bas_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/common/src/bt_uart_bridge.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/dis.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/gaps_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/common/src/hci_adapter.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/common/src/hci_process.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/hids.c +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/hids_kb.c +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/hids_rmc.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/simple_ble_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/simple_ble_service.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/ota_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/dfu_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/board/common/src/trace_task.c + +#bluetooth - example - ble_central +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_app_main.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_app_task.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_at_cmd.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_client_app.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_central/ble_central_link_mgr.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_central/user_cmd.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/client/gcs_client.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/src/mcu/module/data_uart_cmd/user_cmd_parse.c + +#bluetooth - example - ble_peripheral +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_peripheral/app_task.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_peripheral/ble_app_main.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_peripheral/ble_peripheral_at_cmd.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_peripheral/peripheral_app.c + +#bluetooth - example - ble_scatternet +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_scatternet/ble_scatternet_app.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_scatternet/ble_scatternet_app_main.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_scatternet/ble_scatternet_app_task.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_scatternet/ble_scatternet_link_mgr.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/ble_scatternet/ble_scatternet_user_cmd.c + +#bluetooth - example - bt_fuzz_test +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_at_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_link_mgr.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_simple_ble_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_fuzz_test/bt_fuzz_test_user_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/gls.c \ + ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/hrs.c \ + ../../../component/common/bluetooth/realtek/sdk/src/ble/profile/server/ias.c +#bluetooth - example - bt_beacon +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_main.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_beacon/bt_beacon_app_task.c + +#bluetooth - example - bt_config +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_config/bt_config_app_main.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_config/bt_config_app_task.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_config/bt_config_peripheral_app.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_config/bt_config_service.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_config/bt_config_wifi.c + +#bluetooth - example - bt_airsync_config +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_main.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_app_task.c +SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_airsync_config/bt_airsync_config_peripheral_app.c +SRC_C += ../../../component/common/application/airsync/1.0.4/airsync_ble_service.c +SRC_C += ../../../component/common/application/airsync/1.0.4/check_endian.c +SRC_C += ../../../component/common/application/airsync/1.0.4/epb.c +SRC_C += ../../../component/common/application/airsync/1.0.4/epb_MmBp.c +SRC_C += ../../../component/common/application/airsync/1.0.4/epb_WristBand.c +SRC_C += ../../../component/common/application/airsync/1.0.4/wechat_airsync_protocol.c + +#bluetooth - example - bt_ota_central_client +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_link_mgr.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_test_image.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/bt_ota_central_client_at_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ota_central_client/insert_write.c + +#bluetooth - example - bt_datatrans +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_queue.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_at_hci_cmd_process.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_central_application.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_module_param_config.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_multilink_manager.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_peripheral_application.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_profile.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_datatrans/bt_datatrans_uart.c + +#bluetooth - example - bt_ancs +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_ancs/bt_ancs_main.c + +#bluetooth - example - bt_mesh_provisioner +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/provisioner_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/provisioner/bt_mesh_provisioner_app_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c + +#bluetooth - example - bt_mesh_device +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_temperature_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_hue_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_saturation_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/device/device_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/device/bt_mesh_device_app_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c + +#bluetooth - example - bt_mesh_provisioner_rtk_demo +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/example_bt_mesh_provisioner_rtk_demo.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_http_intf.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_lib_intf.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_app_list_intf.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_provisioner_rtk_demo/src/bt_mesh_broadcast_demo.c + +#bluetooth - example - provisioner_multiple_profile +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/configuration_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/blob_transfer_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_distribution_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/firmware_update_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/private_beacon_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/light_cwrgb_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_default_transition_time_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_level_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_location_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_on_off_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_property_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_power_level_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_battery_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lc_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/sensor_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_client.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_distributor_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/generic_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/rmt_prov_client_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/client_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/provisioner/bt_mesh_provisioner_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/bt_mesh_provisioner_multiple_profile_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/provisioner_multiple_profile/provisioner_multiple_profile_cmd.c + +#bluetooth - example - device_multiple_profile +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_data_uart.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_user_cmd_parse.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/profile/datatrans_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_ctl_temperature_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_hue_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_saturation_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_hsl_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_lightness_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/light_xyl_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/time_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_on_off_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_execution.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/generic_transition_time.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/ping_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/datatrans_model.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/realtek/tp_control.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/health_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scene_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/scheduler_setup_server.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/model/delay_msg_rsp.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/datatrans_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/customer_dfu_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfudep_service.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/dfu_updater_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/ping_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/light_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/time_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scene_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/common/scheduler_server_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/mesh_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/cmd/test_cmd.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/bt_mesh_device_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/device/device_idle_check.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/api/bt_mesh_user_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_main.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/bt_mesh_device_multiple_profile_app_task.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_app.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_multiple_profile/device_multiple_profile/device_multiple_profile_cmd.c + +#bluetooth - example - bt_mesh_device_rtk_demo +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_device_rtk_demo/example_bt_mesh_device_rtk_demo.c + +#bluetooth - example - bt_mesh_test +#SRC_C += ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_app_user_cmd_parse.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_datatrans_write_api.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_device_test.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_malloc_free.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_receive_response.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_test_result.c \ + ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh_test/bt_mesh_timer_handler.c + +#bluetooth - example +SRC_C += ../../../component/common/bluetooth/realtek/sdk/bt_example_entry.c + +#cmsis +SRC_C += ../../../component/soc/realtek/8710c/cmsis/rtl8710c/source/ram_ns/app_start.c +SRC_C += ../../../component/soc/realtek/8710c/cmsis/rtl8710c/source/ram/sys_irq.c +SRC_C += ../../../component/soc/realtek/8710c/cmsis/rtl8710c/source/ram/mpu_config.c +SRC_C += ../../../component/soc/realtek/8710c/cmsis/rtl8710c/source/ram_ns/system_rtl8710c_ns.c + +#libc api wrapper +SRC_C += ../../../component/soc/realtek/8710c/misc/utilities/source/ram/libc_wrap.c + +#console +SRC_C += ../../../component/common/api/at_cmd/atcmd_bt.c +SRC_C += ../../../component/common/api/at_cmd/atcmd_lwip.c +SRC_C += ../../../component/common/api/at_cmd/atcmd_mp.c +SRC_C += ../../../component/common/api/at_cmd/atcmd_mp_ext2.c +SRC_C += ../../../component/common/api/at_cmd/atcmd_sys.c +SRC_C += ../../../component/common/api/at_cmd/atcmd_wifi.c +SRC_C += ../../../component/soc/realtek/8710c/app/shell/cmd_shell.c +SRC_C += ../../../component/common/api/at_cmd/log_service.c +SRC_C += ../../../component/soc/realtek/8710c/misc/driver/rtl_console.c + +# network - api +SRC_C += ../../../component/common/api/lwip_netconf.c + +#network - api - wifi +SRC_C += ../../../component/common/api/wifi/wifi_conf.c +SRC_C += ../../../component/common/api/wifi/wifi_ind.c +SRC_C += ../../../component/common/api/wifi/wifi_promisc.c +SRC_C += ../../../component/common/api/wifi/wifi_simple_config.c +SRC_C += ../../../component/common/api/wifi/wifi_util.c + +#network - api - wifi - rtw_wpa_supplicant +SRC_C += ../../../component/common/api/wifi/rtw_wpa_supplicant/src/crypto/tls_polarssl.c +SRC_C += ../../../component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_eap_config.c +SRC_C += ../../../component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_p2p_config.c +SRC_C += ../../../component/common/api/wifi/rtw_wpa_supplicant/wpa_supplicant/wifi_wps_config.c + +#network - app +SRC_C += ../../../component/soc/realtek/8710c/misc/platform/ota_8710c.c +SRC_C += ../../../component/common/api/network/src/ping_test.c +SRC_C += ../../../component/common/utilities/ssl_client.c +SRC_C += ../../../component/common/utilities/ssl_client_ext.c +# SRC_C += ../../../component/common/utilities/ssl_client_ns.c +# SRC_C += ../../../component/common/utilities/ssl_client_ext_ns.c +SRC_C += ../../../component/common/utilities/tcptest.c +SRC_C += ../../../component/common/api/network/src/wlan_network.c + +#utilities +SRC_C += ../../../component/common/utilities/cJSON.c +SRC_C += ../../../component/common/utilities/http_client.c +SRC_C += ../../../component/common/utilities/xml.c +SRC_C += ../../../component/common/utilities/gb2unicode.c + +#network - app - mqtt +SRC_C += ../../../component/common/application/mqtt/MQTTClient/MQTTClient.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTConnectClient.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTConnectServer.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTDeserializePublish.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTFormat.c +SRC_C += ../../../component/common/application/mqtt/MQTTClient/MQTTFreertos.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTPacket.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTSerializePublish.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTSubscribeClient.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTSubscribeServer.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTUnsubscribeClient.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/MQTTUnsubscribeServer.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/V5/MQTTProperties.c +SRC_C += ../../../component/common/application/mqtt/MQTTPacket/V5/MQTTV5Packet.c + +#network - coap +SRC_C += ../../../component/common/network/coap/sn_coap_ameba_port.c +SRC_C += ../../../component/common/network/coap/sn_coap_builder.c +SRC_C += ../../../component/common/network/coap/sn_coap_header_check.c +SRC_C += ../../../component/common/network/coap/sn_coap_parser.c +SRC_C += ../../../component/common/network/coap/sn_coap_protocol.c + +#network - http +SRC_C += ../../../component/common/network/httpc/httpc_tls.c +SRC_C += ../../../component/common/network/httpd/httpd_tls.c + +#network +SRC_C += ../../../component/common/network/dhcp/dhcps.c +SRC_C += ../../../component/common/network/sntp/sntp.c + +#network - lwip +#network - lwip - api +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/api_lib.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/api_msg.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/err.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/netbuf.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/netdb.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/netifapi.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/sockets.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/api/tcpip.c + +#network - lwip - core +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/def.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/dns.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/inet_chksum.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/init.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ip.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/mem.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/memp.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/netif.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/pbuf.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/raw.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/stats.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/sys.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/tcp.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/tcp_in.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/tcp_out.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/timeouts.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/udp.c + +#network - lwip - core - ipv4 +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/autoip.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/dhcp.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/etharp.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/icmp.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/igmp.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/ip4.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/ip4_addr.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv4/ip4_frag.c + +#network - lwip - core - ipv6 +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/dhcp6.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/ethip6.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/icmp6.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/inet6.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/ip6.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/ip6_addr.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/ip6_frag.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/mld6.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/core/ipv6/nd6.c + +#network - lwip - netif +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/src/netif/ethernet.c + +#network - lwip - port +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/port/realtek/freertos/ethernetif.c +SRC_C += ../../../component/common/drivers/wlan/realtek/src/osdep/lwip_intf.c +SRC_C += ../../../component/common/network/lwip/lwip_v2.0.2/port/realtek/freertos/sys_arch.c + +#network - mdns +SRC_C += ../../../component/common/network/mDNS/mDNSPlatform.c + +#network - ssl - mbedtls +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/aesni.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/blowfish.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/camellia.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ccm.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/certs.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/cipher.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/cipher_wrap.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/cmac.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/debug.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/entropy.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/error.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/gcm.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/havege.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md2.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md4.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/md_wrap.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/memory_buffer_alloc.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/net_sockets.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/padlock.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkcs11.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkcs12.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkcs5.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/pkparse.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/platform.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ripemd160.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/sha256.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_cache.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_ciphersuites.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_cli.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_cookie.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_srv.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_ticket.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/ssl_tls.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/threading.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/timing.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/version.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/version_features.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_create.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_crl.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_crt.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509_csr.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509write_crt.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/x509write_csr.c +SRC_C += ../../../component/common/network/ssl/mbedtls-2.4.0/library/xtea.c + +#network - ssl - ssl_ram_map +SRC_C += ../../../component/common/network/ssl/ssl_ram_map/rom/rom_ssl_ram_map.c +SRC_C += ../../../component/common/network/ssl/ssl_func_stubs/ssl_func_stubs.c + +#network - websocket +SRC_C += ../../../component/common/network/websocket/wsclient_tls.c +SRC_C += ../../../component/common/network/websocket/wsserver_tls.c + +#os +SRC_C += ../../../component/os/freertos/cmsis_os.c +SRC_C += ../../../component/os/os_dep/device_lock.c +SRC_C += ../../../component/os/freertos/freertos_cb.c +SRC_C += ../../../component/os/freertos/freertos_service.c +SRC_C += ../../../component/os/freertos/freertos_heap5_config.c +SRC_C += ../../../component/os/freertos/freertos_heap_rtk.c +SRC_C += ../../../component/os/os_dep/osdep_service.c +SRC_C += ../../../component/os/freertos/freertos_pmu.c + +#os - freertos +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/croutine.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/event_groups.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/list.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/queue.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/stream_buffer.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/tasks.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/timers.c + +#os - freertos - portable +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/portable/GCC/RTL8710C/non_secure/port.c +SRC_C += ../../../component/os/freertos/freertos_v10.2.0/Source/portable/GCC/RTL8710C/non_secure/portasm.c + +#peripheral-api +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/crypto_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/dma_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/efuse_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/gpio_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/gpio_irq_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/i2c_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/pinmap.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/pinmap_common.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/port_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/pwmout_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/rtc_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/serial_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/spdio_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/spi_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/sys_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/timer_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/us_ticker.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/us_ticker_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/wait_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/wdt_api.c +SRC_C += ../../../component/common/mbed/targets/hal/rtl8710c/reset_reason_api.c + +#peripheral - hal +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_gdma.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_gpio.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_i2c.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_misc.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_pwm.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_sdio_dev.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_ssi.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_uart.c + +#peripheral - wlan +#SRC_C += ../../../component/common/drivers/wlan/realtek/src/core/option/rtw_opt_rf_para_rtl8710c.c + +#file_system - fatfs +SRC_C += ../../../component/common/file_system/fatfs/fatfs_ext/src/ff_driver.c +SRC_C += ../../../component/common/file_system/fatfs/r0.10c/src/diskio.c +SRC_C += ../../../component/common/file_system/fatfs/r0.10c/src/ff.c +SRC_C += ../../../component/common/file_system/fatfs/r0.10c/src/option/ccsbcs.c +SRC_C += ../../../component/common/file_system/fatfs/disk_if/src/flash_fatfs.c + +#utilities - example +#SRC_C += ../../../component/common/example/amazon_awsiot/example_amazon_awsiot.c +SRC_C += ../../../component/common/example/bcast/example_bcast.c +SRC_C += ../../../component/common/example/cJSON/example_cJSON.c +SRC_C += ../../../component/common/example/coap/example_coap.c +SRC_C += ../../../component/common/example/coap_client/example_coap_client.c +SRC_C += ../../../component/common/example/coap_server/example_coap_server.c +SRC_C += ../../../component/common/example/dct/example_dct.c +#SRC_C += ../../../component/common/example/eap/example_eap.c +SRC_C += ../../../component/common/example/example_entry.c +SRC_C += ../../../component/common/example/get_beacon_frame/example_get_beacon_frame.c +#SRC_C += ../../../component/common/example/googlenest/example_google.c +SRC_C += ../../../component/common/example/high_load_memory_use/example_high_load_memory_use.c +SRC_C += ../../../component/common/example/http_client/example_http_client.c +SRC_C += ../../../component/common/example/http_download/example_http_download.c +SRC_C += ../../../component/common/example/httpc/example_httpc.c +SRC_C += ../../../component/common/example/httpd/example_httpd.c +SRC_C += ../../../component/common/example/mbedtls_ecdhe/example_mbedtls_ecdhe.c +SRC_C += ../../../component/common/example/mcast/example_mcast.c +SRC_C += ../../../component/common/example/mqtt/example_mqtt.c +SRC_C += ../../../component/common/example/nonblock_connect/example_nonblock_connect.c +SRC_C += ../../../component/common/example/ota_http/example_ota_http.c +SRC_C += ../../../component/common/example/rarp/example_rarp.c +SRC_C += ../../../component/common/example/secure_boot/example_secure_boot.c +SRC_C += ../../../component/common/example/secure_storage/example_secure_storage_ns.c +SRC_C += ../../../component/common/example/sntp_showtime/example_sntp_showtime.c +SRC_C += ../../../component/common/example/socket_select/example_socket_select.c +SRC_C += ../../../component/common/example/socket_tcp_trx/example_socket_tcp_trx_1.c +SRC_C += ../../../component/common/example/socket_tcp_trx/example_socket_tcp_trx_2.c +SRC_C += ../../../component/common/example/ssl_download/example_ssl_download.c +SRC_C += ../../../component/common/example/ssl_server/example_ssl_server.c +SRC_C += ../../../component/common/example/tcp_keepalive/example_tcp_keepalive.c +SRC_C += ../../../component/common/example/tickless_wifi_roaming/example_tickless_wifi_roaming.c +SRC_C += ../../../component/common/example/trust_zone/example_trust_zone.c +SRC_C += ../../../component/common/example/uart_atcmd/example_uart_atcmd.c +SRC_C += ../../../component/common/example/wifi_mac_monitor/example_wifi_mac_monitor.c +SRC_C += ../../../component/common/example/wifi_roaming/example_wifi_roaming.c +SRC_C += ../../../component/common/example/wlan_fast_connect/example_wlan_fast_connect.c +SRC_C += ../../../component/common/example/wlan_scenario/example_wlan_scenario.c +SRC_C += ../../../component/common/example/websocket_client/example_wsclient.c +SRC_C += ../../../component/common/example/xml/example_xml.c +SRC_C += ../../../component/common/example/fatfs/example_fatfs.c + +#user +SRC_C += ../src/main.c +#SRC_CPP += ../src/main_ns.cpp + +#SRAM +# ------------------------------------------------------------------- +#@SRAM +SRAM_C += ../../../component/common/mbed/targets/hal/rtl8710c/flash_api.c +SRAM_C += ../../../component/soc/realtek/8710c/misc/driver/flash_api_ext.c +SRAM_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_flash.c +SRAM_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_spic.c +SRAM_C += ../../../component/common/mbed/targets/hal/rtl8710c/power_mode_api.c + +# Generate obj list +# ------------------------------------------------------------------- + +SRC_O = $(patsubst %.c,%_$(TARGET).o,$(SRC_C)) +SRAM_O = $(patsubst %.c,%_$(TARGET).o,$(SRAM_C)) +ERAM_O = $(patsubst %.c,%_$(TARGET).o,$(ERAM_C)) + +SRC_C_LIST = $(notdir $(SRC_C)) $(notdir $(SRAM_C)) $(notdir $(ERAM_C)) +OBJ_LIST = $(addprefix $(OBJ_DIR)/,$(patsubst %.c,%_$(TARGET).o,$(SRC_C_LIST))) +DEPENDENCY_LIST = $(addprefix $(OBJ_DIR)/,$(patsubst %.c,%_$(TARGET).d,$(SRC_C_LIST))) + +SRC_OO += $(patsubst %.cpp,%_$(TARGET).oo,$(SRC_CPP)) + +SRC_CPP_LIST = $(notdir $(SRC_CPP)) +OBJ_CPP_LIST = $(addprefix $(OBJ_DIR)/,$(patsubst %.cpp,%_$(TARGET).oo,$(SRC_CPP_LIST))) +DEPENDENCY_LIST += $(addprefix $(OBJ_DIR)/,$(patsubst %.cpp,%_$(TARGET).d,$(SRC_CPP_LIST))) +# Compile options +# ------------------------------------------------------------------- + +CFLAGS = +CFLAGS += -march=armv8-m.main+dsp -mthumb -mcmse -mfloat-abi=soft -D__thumb2__ -g -gdwarf-3 -Os +CFLAGS += -D__ARM_ARCH_8M_MAIN__=1 -gdwarf-3 -fstack-usage -fdata-sections -ffunction-sections +CFLAGS += -fdiagnostics-color=always -Wall -Wpointer-arith -Wundef -Wno-write-strings +CFLAGS += -Wno-maybe-uninitialized --save-temps -c -MMD -fsigned-char +CFLAGS += -DCONFIG_PLATFORM_8710C -DCONFIG_BUILD_RAM=1 +CFLAGS += -DV8M_STKOVF +CFLAGS += -DV8M_SECURE +CFLAGS += -DCONFIG_BUILD_NONSECURE=1 +CFLAGS += -DENABLE_SECCALL_PATCH + +CPPFLAGS := $(CFLAGS) + +#for time64 +ifdef SYSTEM_TIME64_MAKE_OPTION +CFLAGS += -DCONFIG_SYSTEM_TIME64=1 +CFLAGS += -include time64.h +else +CFLAGS += -DCONFIG_SYSTEM_TIME64=0 +endif + +CFLAGS += -Wstrict-prototypes +CPPFLAGS += -std=c++11 -fno-use-cxa-atexit + +LFLAGS = +LFLAGS += -Os -march=armv8-m.main+dsp -mthumb -mcmse -mfloat-abi=soft -nostartfiles -nodefaultlibs -nostdlib -specs=nosys.specs +LFLAGS += -Wl,--gc-sections -Wl,--warn-section-align -Wl,--cref -Wl,--build-id=none -Wl,--use-blx +LFLAGS += -Wl,-Map=$(BIN_DIR)/$(TARGET).map +# libc api wrapper +LFLAGS += -Wl,-wrap,strcat -Wl,-wrap,strchr -Wl,-wrap,strcmp +LFLAGS += -Wl,-wrap,strncmp -Wl,-wrap,strnicmp -Wl,-wrap,strcpy +LFLAGS += -Wl,-wrap,strncpy -Wl,-wrap,strlcpy -Wl,-wrap,strlen +LFLAGS += -Wl,-wrap,strnlen -Wl,-wrap,strncat -Wl,-wrap,strpbrk +LFLAGS += -Wl,-wrap,strspn -Wl,-wrap,strstr -Wl,-wrap,strtok +LFLAGS += -Wl,-wrap,strxfrm -Wl,-wrap,strsep -Wl,-wrap,strtod +LFLAGS += -Wl,-wrap,strtof -Wl,-wrap,strtold -Wl,-wrap,strtoll +LFLAGS += -Wl,-wrap,strtoul -Wl,-wrap,strtoull -Wl,-wrap,atoi +LFLAGS += -Wl,-wrap,atoui -Wl,-wrap,atol -Wl,-wrap,atoul +LFLAGS += -Wl,-wrap,atoull -Wl,-wrap,atof +LFLAGS += -Wl,-wrap,malloc -Wl,-wrap,realloc +LFLAGS += -Wl,-wrap,calloc -Wl,-wrap,free +LFLAGS += -Wl,-wrap,_malloc_r -Wl,-wrap,_calloc_r -Wl,-wrap,_realloc_r -Wl,-wrap,_free_r +LFLAGS += -Wl,-wrap,memcmp -Wl,-wrap,memcpy +LFLAGS += -Wl,-wrap,memmove -Wl,-wrap,memset +LFLAGS += -Wl,-wrap,printf -Wl,-wrap,sprintf +LFLAGS += -Wl,-wrap,puts -Wl,-wrap,putc -Wl,-wrap,putchar +LFLAGS += -Wl,-wrap,snprintf -Wl,-wrap,vsnprintf +LFLAGS += -Wl,-wrap,aesccmp_construct_mic_iv +LFLAGS += -Wl,-wrap,aesccmp_construct_mic_header1 +LFLAGS += -Wl,-wrap,aesccmp_construct_ctr_preload +LFLAGS += -Wl,-wrap,rom_psk_CalcGTK +LFLAGS += -Wl,-wrap,rom_psk_CalcPTK +LFLAGS += -Wl,-wrap,aes_80211_encrypt +LFLAGS += -Wl,-wrap,aes_80211_decrypt + +ifdef SYSTEM_TIME64_MAKE_OPTION +LFLAGS += -Wl,-wrap,localtime -Wl,-wrap,mktime -Wl,-wrap,ctime +endif + + +LFLAGS += -Wl,-wrap,hal_crypto_engine_init_platform -Wl,-wrap,hal_pinmux_register +LFLAGS += -Wl,-wrap,hal_pinmux_unregister -Wl,-wrap,hal_xip_get_phy +#LFLAGS += -Wl,-wrap,crypto_random_generate +LFLAGS += -Wl,-wrap,hal_efuse_autoload_en +LFLAGS += -Wl,-wrap,hal_efuse_hci_autoload_en +LFLAGS += -Wl,-wrap,hal_efuse_read +LFLAGS += -Wl,-wrap,hal_efuse_write +LFLAGS += -Wl,-wrap,hal_sec_efuse_read +LFLAGS += -Wl,-wrap,hal_sec_efuse_write +LFLAGS += -Wl,-wrap,hal_sec_key_get +LFLAGS += -Wl,-wrap,hal_sec_key_write +LFLAGS += -Wl,-wrap,hal_susec_key_get +LFLAGS += -Wl,-wrap,hal_susec_key_write +LFLAGS += -Wl,-wrap,hal_s_jtag_key_write +LFLAGS += -Wl,-wrap,hal_ns_jtag_key_write +LFLAGS += -Wl,-wrap,hal_user_otp_get +LFLAGS += -Wl,-wrap,hal_user_otp_set +LFLAGS += -Wl,-wrap,hal_efuse_disable_sec_jtag + +LFLAGS += ./gateway_ns.o +LFLAGS += ../../../component/common/file_system/ftl/ftl_crypto_plugin_gcc.o + +LIBFLAGS = +LIBFLAGS += -L$(AMEBAZ2_ROMSYMDIR) +LIBFLAGS += -Wl,--start-group ../../../component/soc/realtek/8710c/fwlib/lib/lib/hal_pmc.a -Wl,--end-group +LIBFLAGS += -Wl,--start-group ../../../component/common/bluetooth/realtek/sdk/board/amebaz2/lib/btgap.a -Wl,--end-group +#LIBFLAGS += -Wl,--start-group ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_prov.a -Wl,--end-group +#LIBFLAGS += -Wl,--start-group ../../../component/common/bluetooth/realtek/sdk/example/bt_mesh/lib/lib/amebaz2/btmesh_dev.a -Wl,--end-group +all: LIBFLAGS += -Wl,--start-group -L../../../component/soc/realtek/8710c/misc/bsp/lib/common/GCC -l_soc_ns -l_wlan_ns -Wl,--end-group +mp: LIBFLAGS += -Wl,--start-group -L../../../component/soc/realtek/8710c/misc/bsp/lib/common/GCC -l_soc_ns -l_wlan_mp_ns -Wl,--end-group +LIBFLAGS += -L../../../component/soc/realtek/8710c/misc/bsp/lib/common/GCC -l_dct_ns -l_eap_ns -l_http_ns -l_p2p_ns -l_websocket_ns -l_wps_ns +#LIBFLAGS += -L../../../component/soc/realtek/8710c/misc/bsp/lib/common/GCC -l_coap_ns + +RAMALL_BIN = +OTA_BIN = + +include toolchain.mk + +# Compile +# ------------------------------------------------------------------- + +.PHONY: application_ns +application_ns: prerequirement $(SRC_O) $(SRAM_O) $(ERAM_O) $(SRC_OO) + $(LD) $(LFLAGS) -o $(BIN_DIR)/$(TARGET).axf $(OBJ_CPP_LIST) -lstdc++ $(OBJ_LIST) $(ROMIMG) $(LIBFLAGS) -T$(LDSCRIPT) + $(OBJCOPY) -j .bluetooth_trace.text -Obinary $(BIN_DIR)/$(TARGET).axf $(BIN_DIR)/APP.trace + $(OBJCOPY) -R .bluetooth_trace.text $(BIN_DIR)/$(TARGET).axf + $(OBJDUMP) -d $(BIN_DIR)/$(TARGET).axf > $(BIN_DIR)/$(TARGET).asm + +# Manipulate Image +# ------------------------------------------------------------------- + +.PHONY: manipulate_images +manipulate_images: | application_ns + @echo =========================================================== + @echo Image manipulating + @echo =========================================================== + # cp $(AMEBAZ2_BOOTLOADERDIR)/bootloader.bin $(BIN_DIR)/bootloader.bin +# ifeq ($(findstring Linux, $(OS)), Linux) +# chmod 0774 $(ELF2BIN) +# endif + # $(ELF2BIN) keygen keycfg.json + # $(ELF2BIN) convert amebaz2_bootloader.json PARTITIONTABLE + # $(ELF2BIN) convert amebaz2_firmware_is.json FIRMWARE + # $(ELF2BIN) combine $(BIN_DIR)/flash_is.bin PTAB=partition.bin,BOOT=$(BIN_DIR)/bootloader.bin,FW1=$(BIN_DIR)/firmware_is.bin + +# Generate build info +# ------------------------------------------------------------------- + +.PHONY: build_info +build_info: + @echo \#define RTL_FW_COMPILE_TIME RTL8710CFW_COMPILE_TIME\ > .ver + @echo \#define RTL_FW_COMPILE_DATE RTL8710CFW_COMPILE_DATE\ >> .ver + @echo \#define UTS_VERSION \"`date +%Y/%m/%d-%T`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_TIME \"`date +%Y/%m/%d-%T`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_DATE \"`date +%Y%m%d`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_BY \"`id -u -n`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_HOST \"`$(HOSTNAME_APP)`\" >> .ver + @if [ -x /bin/dnsdomainname ]; then \ + echo \#define RTL8710CFW_COMPILE_DOMAIN \"`dnsdomainname`\"; \ + elif [ -x /bin/domainname ]; then \ + echo \#define RTL8710CFW_COMPILE_DOMAIN \"`domainname`\"; \ + else \ + echo \#define RTL8710CFW_COMPILE_DOMAIN ; \ + fi >> .ver + + @echo \#define RTL8710CFW_COMPILER \"gcc `$(CC) $(CFLAGS) -dumpversion | tr --delete '\r'`\" >> .ver + @mv -f .ver ../inc/$@.h + +.PHONY: prerequirement +prerequirement: + @if [ ! -d $(ARM_GCC_TOOLCHAIN) ]; then \ + echo ===========================================================; \ + echo Toolchain not found, \"make toolchain\" first!; \ + echo ===========================================================; \ + exit -1; \ + fi + @echo =========================================================== + @echo Build $(TARGET) + @echo =========================================================== + mkdir -p $(OBJ_DIR) + mkdir -p $(BIN_DIR) + mkdir -p $(INFO_DIR) + +$(SRC_OO): %_$(TARGET).oo : %.cpp | prerequirement + $(CC) $(CPPFLAGS) -c $< -o $@ + $(CC) $(CPPFLAGS) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.oo,%.d,$@)) + cp $@ $(OBJ_DIR)/$(notdir $@) + mv $(notdir $*.ii) $(INFO_DIR) +# mv $(notdir $*.s) $(INFO_DIR) + chmod 777 $(OBJ_DIR)/$(notdir $@) + +$(SRC_O): %_$(TARGET).o : %.c | prerequirement + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(CC) $(CFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.o,%.d,$@)) + cp $@ $(OBJ_DIR)/$(notdir $@) + mv $(notdir $*.i) $(INFO_DIR) + mv $(notdir $*.s) $(INFO_DIR) + chmod 777 $(OBJ_DIR)/$(notdir $@) + +$(SRAM_O): %_$(TARGET).o : %.c | prerequirement + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(OBJCOPY) --prefix-alloc-sections .sram $@ + $(CC) $(CFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.o,%.d,$@)) + cp $@ $(OBJ_DIR)/$(notdir $@) + mv $(notdir $*.i) $(INFO_DIR) + mv $(notdir $*.s) $(INFO_DIR) + chmod 777 $(OBJ_DIR)/$(notdir $@) + +$(ERAM_O): %_$(TARGET).o : %.c | prerequirement + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(OBJCOPY) --prefix-alloc-sections .psram $@ + $(CC) $(CFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.o,%.d,$@)) + cp $@ $(OBJ_DIR)/$(notdir $@) + mv $(notdir $*.i) $(INFO_DIR) + mv $(notdir $*.s) $(INFO_DIR) + chmod 777 $(OBJ_DIR)/$(notdir $@) + +-include $(DEPENDENCY_LIST) + +# Only needed for FPGA phase +.PHONY: romdebug +romdebug: +ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh + cmd /c start $(GDB) -x ./rtl_gdb_debug_jlink.txt +else + $(GDB) -x ./rtl_gdb_debug_jlink.txt +endif + +.PHONY: flash +flash: +# @if [ ! -f $(FLASH_TOOLDIR)/rtl_gdb_flash_write.txt ] ; then echo Please do /"make setup GDB_SERVER=[jlink or openocd]/" first; echo && false ; fi +#ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh +#endif + # chmod +rx $(AMEBAZ2_GCCTOOLDIR)/flashloader.sh + # $(AMEBAZ2_GCCTOOLDIR)/flashloader.sh application_ns/Debug/bin/flash_is.bin + # $(GDB) -x $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader_jlink.txt + +.PHONY: debug +debug: + chmod +rx $(AMEBAZ2_GCCTOOLDIR)/debug.sh + $(AMEBAZ2_GCCTOOLDIR)/debug.sh $(BIN_DIR)/$(TARGET).axf + #$(GDB) -x $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug_jlink.txt + +.PHONY: clean +clean: + rm -rf $(TARGET) + rm -f $(SRC_O) $(SRAM_O) $(ERAM_O) $(SRC_OO) + rm -f $(patsubst %.o,%.d,$(SRC_O)) $(patsubst %.o,%.d,$(SRAM_O)) $(patsubst %.o,%.d,$(ERAM_O)) $(patsubst %.oo,%.d,$(SRC_OO)) + rm -f $(patsubst %.o,%.su,$(SRC_O)) $(patsubst %.o,%.su,$(SRAM_O)) $(patsubst %.o,%.su,$(ERAM_O)) $(patsubst %.oo,%.su,$(SRC_OO)) + rm -f *.i + rm -f *.s + diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.tz.mk b/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.tz.mk new file mode 100644 index 00000000..068b869a --- /dev/null +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/application.tz.mk @@ -0,0 +1,174 @@ +# Initialize tool chain +# ------------------------------------------------------------------- + +AMEBAZ2_TOOLDIR = ../../../component/soc/realtek/8710c/misc/iar_utility +AMEBAZ2_GCCTOOLDIR = ../../../component/soc/realtek/8710c/misc/gcc_utility +AMEBAZ2_BSPDIR = ../../../component/soc/realtek/8710c/misc/bsp +AMEBAZ2_BOOTLOADERDIR = $(AMEBAZ2_BSPDIR)/image +AMEBAZ2_ROMSYMDIR = $(AMEBAZ2_BSPDIR)/ROM + +OS := $(shell uname) + +CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi- + +# Compilation tools +AR = $(CROSS_COMPILE)ar +CC = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)as +NM = $(CROSS_COMPILE)nm +LD = $(CROSS_COMPILE)gcc +GDB = $(CROSS_COMPILE)gdb +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + + +# Initialize target name and target object files +# ------------------------------------------------------------------- + +all: build_info application_tz manipulate_images + +#mp: build_info application manipulate_images + +TARGET=application_tz +BOOT_BIN_DIR=bootloader/Debug/bin + +# Compile options +# ------------------------------------------------------------------- + +RAMALL_BIN = +OTA_BIN = + +include toolchain.mk + +# Compile +# ------------------------------------------------------------------- + +.PHONY: application_tz +application_tz: prerequirement + make -f application.s.mk all + make -f application.ns.mk all + +# Manipulate Image +# ------------------------------------------------------------------- + +.PHONY: manipulate_images +manipulate_images: | application_tz + @echo =========================================================== + @echo Image manipulating + @echo =========================================================== + cp $(AMEBAZ2_BOOTLOADERDIR)/bootloader.axf $(BOOT_BIN_DIR)/bootloader.axf +ifeq ($(findstring Linux, $(OS)), Linux) + chmod 0774 $(ELF2BIN) $(CHKSUM) +endif + $(ELF2BIN) keygen keycfg.json + $(ELF2BIN) convert amebaz2_bootloader.json BOOTLOADER secure_bit=0 + $(ELF2BIN) convert amebaz2_bootloader.json PARTITIONTABLE secure_bit=0 + $(ELF2BIN) convert amebaz2_firmware_tz.json FIRMWARE secure_bit=0 + $(CHKSUM) $(TARGET)/firmware_tz.bin + $(ELF2BIN) combine $(TARGET)/flash_tz.bin PTAB=partition.bin,BOOT=$(BOOT_BIN_DIR)/bootloader.bin,FW1=$(TARGET)/firmware_tz.bin + +# Generate build info +# ------------------------------------------------------------------- + +.PHONY: build_info +build_info: + @echo \#define RTL_FW_COMPILE_TIME RTL8710CFW_COMPILE_TIME\ > .ver + @echo \#define RTL_FW_COMPILE_DATE RTL8710CFW_COMPILE_DATE\ >> .ver + @echo \#define UTS_VERSION \"`date +%Y/%m/%d-%T`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_TIME \"`date +%Y/%m/%d-%T`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_DATE \"`date +%Y%m%d`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_BY \"`id -u -n`\" >> .ver + @echo \#define RTL8710CFW_COMPILE_HOST \"`$(HOSTNAME_APP)`\" >> .ver + @if [ -x /bin/dnsdomainname ]; then \ + echo \#define RTL8710CFW_COMPILE_DOMAIN \"`dnsdomainname`\"; \ + elif [ -x /bin/domainname ]; then \ + echo \#define RTL8710CFW_COMPILE_DOMAIN \"`domainname`\"; \ + else \ + echo \#define RTL8710CFW_COMPILE_DOMAIN ; \ + fi >> .ver + + @echo \#define RTL8710CFW_COMPILER \"gcc `$(CC) $(CFLAGS) -dumpversion | tr --delete '\r'`\" >> .ver + @mv -f .ver ../inc/$@.h + +.PHONY: prerequirement +prerequirement: + @if [ ! -d $(ARM_GCC_TOOLCHAIN) ]; then \ + echo ===========================================================; \ + echo Toolchain not found, \"make toolchain\" first!; \ + echo ===========================================================; \ + exit -1; \ + fi + @echo =========================================================== + @echo Build $(TARGET) + @echo =========================================================== + mkdir -p $(TARGET) + mkdir -p $(BOOT_BIN_DIR) + +# Only needed for FPGA phase +.PHONY: romdebug +romdebug: +ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh + cmd /c start $(GDB) -x ./rtl_gdb_debug_jlink.txt +else + $(GDB) -x ./rtl_gdb_debug_jlink.txt +endif + +.PHONY: flash +flash: +# @if [ ! -f $(FLASH_TOOLDIR)/rtl_gdb_flash_write.txt ] ; then echo Please do /"make setup GDB_SERVER=[jlink or openocd]/" first; echo && false ; fi +#ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh +#endif + @if [ ! -e $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader.txt ]; then \ + echo ===========================================================; \ + echo gdb script not found, \"make setup_tz GDB_SERVER=[jlink, pyocd or openocd]\" first!; \ + echo ===========================================================; \ + exit -1; \ + fi + chmod +rx $(AMEBAZ2_GCCTOOLDIR)/flashloader.sh + $(AMEBAZ2_GCCTOOLDIR)/flashloader.sh $(TARGET)/flash_tz.bin + $(GDB) -x $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader.txt + +.PHONY: debug +debug: + @if [ ! -e $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug.txt ]; then \ + echo ===========================================================; \ + echo gdb script not found, \"make setup_tz GDB_SERVER=[jlink, pyocd or openocd]\" first!; \ + echo ===========================================================; \ + exit -1; \ + fi + make -f application.ns.mk debug + make -f application.s.mk debug + $(GDB) -x $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug.txt + + +.PHONY: setup setup_tz +setup: setup_tz + +setup_tz: + @echo "----------------" + @echo Setup $(GDB_SERVER) + @echo "----------------" +ifeq ($(GDB_SERVER), pyocd) + cp -p $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug_pyocd.txt $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug.txt + cp -p $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader_pyocd.txt $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader.txt +else ifeq ($(GDB_SERVER), openocd) + cp -p $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug_openocd.txt $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug.txt + cp -p $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader_openocd.txt $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader.txt +else + cp -p $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug_jlink.txt $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_debug.txt + cp -p $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader_jlink.txt $(AMEBAZ2_GCCTOOLDIR)/rtl_gdb_flashloader.txt +endif + +.PHONY: clean +clean: + make -f application.s.mk clean + make -f application.ns.mk clean + rm -rf $(TARGET) + rm -f $(SRC_O) $(SRAM_O) $(ERAM_O) + rm -f $(patsubst %.o,%.d,$(SRC_O)) $(patsubst %.o,%.d,$(SRAM_O)) $(patsubst %.o,%.d,$(ERAM_O)) + rm -f $(patsubst %.o,%.su,$(SRC_O)) $(patsubst %.o,%.su,$(SRAM_O)) $(patsubst %.o,%.su,$(ERAM_O)) + rm -f *.i + rm -f *.s + diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/bootloader.mk b/project/realtek_amebaz2_v0_example/GCC-RELEASE/bootloader.mk new file mode 100644 index 00000000..d9a100d6 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/bootloader.mk @@ -0,0 +1,275 @@ + +# Initialize tool chain +# ------------------------------------------------------------------- + +AMEBAZ2_TOOLDIR = ../../../component/soc/realtek/8710c/misc/iar_utility +AMEBAZ2_GCCTOOLDIR = ../../../component/soc/realtek/8710c/misc/gcc_utility +AMEBAZ2_BSPDIR = ../../../component/soc/realtek/8710c/misc/bsp +AMEBAZ2_BOOTLOADERDIR = $(AMEBAZ2_BSPDIR)/image +AMEBAZ2_ROMSYMDIR = $(AMEBAZ2_BSPDIR)/ROM + +OS := $(shell uname) + +CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi- + +# Compilation tools +AR = $(CROSS_COMPILE)ar +CC = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)as +NM = $(CROSS_COMPILE)nm +LD = $(CROSS_COMPILE)gcc +GDB = $(CROSS_COMPILE)gdb +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +OS := $(shell uname) + +LDSCRIPT := ./rtl8710c_img1.ld + +# Initialize target name and target object files +# ------------------------------------------------------------------- + +all: bootloader manipulate_images + +TARGET=bootloader + +OBJ_DIR=$(TARGET)/Debug/obj +BIN_DIR=$(TARGET)/Debug/bin +INFO_DIR=$(TARGET)/Debug/info + +# Include folder list +# ------------------------------------------------------------------- + +INCLUDES = +INCLUDES += -I../inc + +INCLUDES += -I../../../component/common/api +INCLUDES += -I../../../component/common/api/platform +INCLUDES += -I../../../component/common/mbed/api +INCLUDES += -I../../../component/common/mbed/hal +INCLUDES += -I../../../component/common/mbed/hal_ext +INCLUDES += -I../../../component/common/mbed/targets/hal/rtl8710c + +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/rtl8710c/include +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/rtl8710c/lib/include +INCLUDES += -I../../../component/soc/realtek/8710c/fwlib/include +INCLUDES += -I../../../component/soc/realtek/8710c/fwlib/lib/include +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/cmsis-core/include +INCLUDES += -I../../../component/soc/realtek/8710c/cmsis/rtl8710c/include +INCLUDES += -I../../../component/soc/realtek/8710c/app/rtl_printf/include +INCLUDES += -I../../../component/soc/realtek/8710c/app/shell +INCLUDES += -I../../../component/soc/realtek/8710c/app/stdio_port +INCLUDES += -I../../../component/soc/realtek/8710c/misc/utilities/include +INCLUDES += -I../../../component/soc/realtek/8710c/misc/platform/lzma + +INCLUDES += -I../../../component/os/freertos +INCLUDES += -I../../../component/os/freertos/freertos_v10.0.1/Source/include +INCLUDES += -I../../../component/os/freertos/freertos_v10.0.1/Source/portable/GCC/ARM_RTL8710C +INCLUDES += -I../../../component/os/os_dep/include + +# Source file list +# ------------------------------------------------------------------- + +SRC_C = + +#mpu +SRC_C += ../../../component/soc/realtek/8710c/cmsis/rtl8710c/source/ram/mpu_config.c + +#libc api wrapper +SRC_C += ../../../component/soc/realtek/8710c/misc/utilities/source/ram/libc_wrap.c + +#console +SRC_C += ../../../component/soc/realtek/8710c/app/shell/cmd_shell.c + +#peripheral - hal +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_s/hal_efuse.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_s/hal_efuse_nsc.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_s/hal_pinmux_nsc.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_gdma.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_uart.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_misc.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram/hal_gpio.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_flash.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_i2c.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_pwm.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_sdio_dev.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_spic.c +SRC_C += ../../../component/soc/realtek/8710c/fwlib/source/ram_ns/hal_ssi.c + +# Generate obj list +# ------------------------------------------------------------------- + +SRC_O = $(patsubst %.c,%_$(TARGET).o,$(SRC_C)) + +SRC_C_LIST = $(notdir $(SRC_C)) +OBJ_LIST = $(addprefix $(OBJ_DIR)/,$(patsubst %.c,%_$(TARGET).o,$(SRC_C_LIST))) +DEPENDENCY_LIST = $(addprefix $(OBJ_DIR)/,$(patsubst %.c,%_$(TARGET).d,$(SRC_C_LIST))) + + +# Compile options +# ------------------------------------------------------------------- + +CFLAGS = +CFLAGS += -march=armv8-m.main+dsp -mthumb -mcmse -mfloat-abi=soft -D__thumb2__ -g -gdwarf-3 -Os +CFLAGS += -D__ARM_ARCH_8M_MAIN__=1 -gdwarf-3 -fstack-usage -fdata-sections -ffunction-sections +CFLAGS += -fdiagnostics-color=always -Wall -Wpointer-arith -Wstrict-prototypes -Wundef -Wno-write-strings +CFLAGS += -Wno-maybe-uninitialized --save-temps -c -MMD +CFLAGS += -DCONFIG_PLATFORM_8710C -DCONFIG_BUILD_RAM=1 +CFLAGS += -DCONFIG_BUILD_BOOT=1 +LIBCFLAGS = +LIBCFLAGS += $(CFLAGS) +LIBCFLAGS += -DCONFIG_BUILD_LIB=1 + +LFLAGS = +LFLAGS += -Os -march=armv8-m.main+dsp -mthumb -mcmse -mfloat-abi=soft -nostartfiles -nodefaultlibs -nostdlib -specs=nosys.specs +LFLAGS += -Wl,--gc-sections -Wl,--warn-section-align -Wl,--cref -Wl,--build-id=none -Wl,--use-blx +LFLAGS += -Wl,-Map=$(BIN_DIR)/$(TARGET).map +# libc api wrapper +LFLAGS += -Wl,-wrap,strcat -Wl,-wrap,strchr -Wl,-wrap,strcmp +LFLAGS += -Wl,-wrap,strncmp -Wl,-wrap,strnicmp -Wl,-wrap,strcpy +LFLAGS += -Wl,-wrap,strncpy -Wl,-wrap,strlcpy -Wl,-wrap,strlen +LFLAGS += -Wl,-wrap,strnlen -Wl,-wrap,strncat -Wl,-wrap,strpbrk +LFLAGS += -Wl,-wrap,strspn -Wl,-wrap,strstr -Wl,-wrap,strtok +LFLAGS += -Wl,-wrap,strxfrm -Wl,-wrap,strsep -Wl,-wrap,strtod +LFLAGS += -Wl,-wrap,strtof -Wl,-wrap,strtold -Wl,-wrap,strtoll +LFLAGS += -Wl,-wrap,strtoul -Wl,-wrap,strtoull -Wl,-wrap,atoi +LFLAGS += -Wl,-wrap,atoui -Wl,-wrap,atol -Wl,-wrap,atoul +LFLAGS += -Wl,-wrap,atoull -Wl,-wrap,atof +LFLAGS += -Wl,-wrap,malloc -Wl,-wrap,realloc -Wl,-wrap,free +LFLAGS += -Wl,-wrap,memcmp -Wl,-wrap,memcpy +LFLAGS += -Wl,-wrap,memmove -Wl,-wrap,memset +LFLAGS += -Wl,-wrap,printf -Wl,-wrap,sprintf +LFLAGS += -Wl,-wrap,snprintf -Wl,-wrap,vsnprintf + +LIBFLAGS = +LIBFLAGS += -L$(AMEBAZ2_ROMSYMDIR) +LIBFLAGS += -L../../../component/soc/realtek/8710c/misc/bsp/lib/common/GCC +LIBFLAGS += -Wl,--whole-archive ../../../component/soc/realtek/8710c/misc/bsp/lib/common/GCC/lib_boot.a -Wl,--no-whole-archive +all: LIBFLAGS += + +include toolchain.mk + +# Compile +# ------------------------------------------------------------------- + +.PHONY: bootloader +bootloader: prerequirement $(SRC_O) + $(LD) $(LFLAGS) -o $(BIN_DIR)/$(TARGET).axf $(OBJ_LIST) $(ROMIMG) $(LIBFLAGS) -T$(LDSCRIPT) + $(OBJDUMP) -d $(BIN_DIR)/$(TARGET).axf > $(BIN_DIR)/$(TARGET).asm + +# Manipulate Image +# ------------------------------------------------------------------- + +.PHONY: manipulate_images +manipulate_images: | bootloader + @echo =========================================================== + @echo Image manipulating + @echo =========================================================== +ifeq ($(findstring Linux, $(OS)), Linux) + chmod 0774 $(ELF2BIN) +endif + $(ELF2BIN) keygen keycfg.json + $(ELF2BIN) convert amebaz2_bootloader.json BOOTLOADER + cp $(BIN_DIR)/$(TARGET).axf $(AMEBAZ2_BOOTLOADERDIR)/$(TARGET).axf + #cp $(BIN_DIR)/$(TARGET).bin $(AMEBAZ2_BOOTLOADERDIR)/$(TARGET).bin + +# Generate build info +# ------------------------------------------------------------------- + +.PHONY: prerequirement +prerequirement: + @if [ ! -d $(ARM_GCC_TOOLCHAIN) ]; then \ + echo ===========================================================; \ + echo Toolchain not found, \"make toolchain\" first!; \ + echo ===========================================================; \ + exit -1; \ + fi + @echo =========================================================== + @echo Build $(TARGET) + @echo =========================================================== + mkdir -p $(OBJ_DIR) + mkdir -p $(BIN_DIR) + mkdir -p $(INFO_DIR) + +$(SRC_O): %_$(TARGET).o : %.c | prerequirement + $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(CC) $(CFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.o,%.d,$@)) + cp $@ $(OBJ_DIR)/$(notdir $@) + mv $(notdir $*.i) $(INFO_DIR) + mv $(notdir $*.s) $(INFO_DIR) + chmod 777 $(OBJ_DIR)/$(notdir $@) + +#$(SRC_LIB_O): %_$(TARGET).o : %.c | prerequirement +# $(CC) $(LIBCFLAGS) $(INCLUDES) -c $< -o $@ +# $(CC) $(LIBCFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.o,%.d,$@)) +# cp $@ $(OBJ_DIR)/$(notdir $@) +# mv $(notdir $*.i) $(INFO_DIR) +# mv $(notdir $*.s) $(INFO_DIR) +# chmod 777 $(OBJ_DIR)/$(notdir $@) + +-include $(DEPENDENCY_LIST) + +# Generate build info +# ------------------------------------------------------------------- +#ifeq (setup,$(firstword $(MAKECMDGOALS))) +# # use the rest as arguments for "run" +# RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) +# # ...and turn them into do-nothing targets +# $(eval $(RUN_ARGS):;@:) +#endif + +#.PHONY: setup +#setup: +# @echo "----------------" +# @echo Setup $(GDB_SERVER) +# @echo "----------------" +#ifeq ($(GDB_SERVER), openocd) +# cp -p $(FLASH_TOOLDIR)/rtl_gdb_debug_openocd.txt $(FLASH_TOOLDIR)/rtl_gdb_debug.txt +# cp -p $(FLASH_TOOLDIR)/rtl_gdb_ramdebug_openocd.txt $(FLASH_TOOLDIR)/rtl_gdb_ramdebug.txt +# cp -p $(FLASH_TOOLDIR)/rtl_gdb_flash_write_openocd.txt $(FLASH_TOOLDIR)/rtl_gdb_flash_write.txt +#else +# cp -p $(FLASH_TOOLDIR)/rtl_gdb_debug_jlink.txt $(FLASH_TOOLDIR)/rtl_gdb_debug.txt +# cp -p $(FLASH_TOOLDIR)/rtl_gdb_ramdebug_jlink.txt $(FLASH_TOOLDIR)/rtl_gdb_ramdebug.txt +# cp -p $(FLASH_TOOLDIR)/rtl_gdb_flash_write_jlink.txt $(FLASH_TOOLDIR)/rtl_gdb_flash_write.txt +#endif + +#.PHONY: flashburn +#flashburn: +# @if [ ! -f $(FLASH_TOOLDIR)/rtl_gdb_flash_write.txt ] ; then echo Please do \"make setup GDB_SERVER=[jlink or openocd]\" first; echo && false ; fi +#ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh +#endif +# cp $(FLASH_TOOLDIR)/target_NORMALB.axf $(FLASH_TOOLDIR)/target_NORMAL.axf +# chmod 777 $(FLASH_TOOLDIR)/target_NORMAL.axf +# chmod +rx $(FLASH_TOOLDIR)/SetupGDB_NORMAL.sh +# $(FLASH_TOOLDIR)/SetupGDB_NORMAL.sh +# $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_flash_write.txt + +#.PHONY: debug +#debug: +# @if [ ! -f $(FLASH_TOOLDIR)/rtl_gdb_debug.txt ] ; then echo Please do \"make setup GDB_SERVER=[jlink or openocd]\" first; echo && false ; fi +#ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh +# cmd /c start $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_debug.txt +#else +# $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_debug.txt +#endif + +#.PHONY: ramdebug +#ramdebug: +# @if [ ! -f $(FLASH_TOOLDIR)/rtl_gdb_ramdebug.txt ] ; then echo Please do \"make setup GDB_SERVER=[jlink or openocd]\" first; echo && false ; fi +#ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +# $(FLASH_TOOLDIR)/Check_Jtag.sh +# cmd /c start $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_ramdebug.txt +#else +# $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_ramdebug.txt +#endif + +.PHONY: clean +clean: + rm -rf $(TARGET) + rm -f $(SRC_O) $(SRC_LIB_O) + rm -f $(patsubst %.o,%.d,$(SRC_O)) $(patsubst %.o,%.d,$(SRC_LIB_O)) + rm -f $(patsubst %.o,%.su,$(SRC_O)) $(patsubst %.o,%.su,$(SRC_LIB_O)) + rm -f *.i + rm -f *.s diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/key.json b/project/realtek_amebaz2_v0_example/GCC-RELEASE/key.json new file mode 100644 index 00000000..5dcc4b09 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/key.json @@ -0,0 +1,15 @@ +{ + "__comment_EFUSE":"should keep these two key in safe place, or secure firmware protection is useless", + "EFUSE":{ + "__comment_privkey_enc":"this key in EFUSE SUPER SECURE ZONE", + "privkey_enc":"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E5F", + "__comment_privkey_hash":"this key in EFUSE SECURE ZONE, encrypted by upper key", + "privkey_hash":"64A7433FCF027D19DDA4D446EEF8E78A22A8C33CB2C337C07366C040612EE0F2" + }, + "TOOL":{ + "__comment_pubkey_enc":"public key for encryption", + "pubkey_enc":"8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F", + "__comment_pubkey_hash":"public key for hash, only for partition table and bootloader", + "pubkey_hash":"8F40C5ADB68F25624AE5B214EA767A6EC94D829D3D7B5E1AD1BA6F3E2138285F" + } +} diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.bin b/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.bin new file mode 100644 index 00000000..670e2141 Binary files /dev/null and b/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.bin differ diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.json b/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.json index 96010765..5deae233 100644 --- a/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.json +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/partition.json @@ -16,6 +16,7 @@ }, "key_exp_op": 2, "user_len": 256, + "user_ext": "FFFFFFFFFFFFFFFFFFFFFFFF", "user_bin":"user.bin", "items":["boot","fw1","fw2"] }, diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/rtl8710c_img1_lzma.ld b/project/realtek_amebaz2_v0_example/GCC-RELEASE/rtl8710c_img1_lzma.ld new file mode 100644 index 00000000..a7d93fd1 --- /dev/null +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/rtl8710c_img1_lzma.ld @@ -0,0 +1,209 @@ +/* Linker script to configure memory regions. */ + +/* !! the include symbole may failed if the symbol file name is too long!! */ +/* this symbol file is from S & NS symbol merged */ +INCLUDE "romsym_is.so" + +MEMORY +{ + /* Internal RAM for program data & text */ + RAM (rwx) : ORIGIN = 0x10020000, LENGTH = 0x10036000 - 0x10020000 + + /* The vector table, it must start with 256 bytes aligned address */ + /* The Reset_Handler also is the NS region code entry function */ + VECTORS_RAM (rwx) : ORIGIN = 0x10036000, LENGTH = 0x10036100 - 0x10036000 + + /* we collect all RO data and put them at the buttom of the image to shorten the image loading time */ + /* RAM functions entry table */ + RAM_FUN_TABLE (rwx) : ORIGIN = 0x10036100, LENGTH = 0x10036180 - 0x10036100 + RAM_RO (rwx) : ORIGIN = 0x10036180, LENGTH = 0x1003EA00 - 0x10036180 + + /* Note: 0x1003FA00 ~ 0x1003FF00 is reserved for ROM code and 0x1003EA00 ~ 0x1003FA00 is reserved as S ROM's stack */ + + /* Note: 0x10040000 - 0x1003FF00 currently is used by NS RAM code, so Boot loader shouldn't touch it */ + + /* External PSRAM for text, rodata & data */ + PSRAM (rwx) : ORIGIN = 0x60000000, LENGTH = 0x60400000 - 0x60000000 + +} + +/* Library configurations */ +GROUP(libgcc.a libc.a libm.a libnosys.a) + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __Vectors_End + * __Vectors_Size + */ +_start_addr = 0x1000; +ENTRY(_start_addr) +__psram_start__ = ORIGIN(PSRAM); +__psram_end__ = ORIGIN(PSRAM) + LENGTH(PSRAM); + +SECTIONS +{ + /* templary BSS for boot loader, it will be recycled + and be used by FW code */ + .boot_temp_use.bss : + { + . = ALIGN(4); + __boot_temp_bss_start__ = .; + KEEP(*(.rom_temp.bss)) + __boot_temp_bss_end__ = .; + __boot_sboot_bss_start__ = .; + KEEP(*(.sboot.bss)) + __boot_sboot_bss_end__ = .; + + } > RAM + + .ram.vector : + { + . = ALIGN(256); + __ram_vector_start__ = .; + KEEP(*(.ram_vector_table)) + __ram_vector_end__ = .; + . = ALIGN(4); + } > VECTORS_RAM + + .ram.func.table : + { + /* Boot image start here. for image decryption, + the image start addr. should be aligned to 16 */ + . = ALIGN(32); + __ram_start_table_start__ = .; + KEEP(*(SORT(.start.ram.data*))) + __ram_start_table_end__ = .; + + } > RAM_FUN_TABLE + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .data : AT (__data_start__) + { + . = ALIGN(16); + __fw_img_start__ = .; + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM_RO + + .ram.code_text : AT (__ram_code_text_start__) + { + . = ALIGN(32); + __ram_code_text_start__ = .; + + __ram_img_signature__ = .; + KEEP(*(.start.ram.sign*)) + + *(.text*) + + __ram_code_text_end__ = .; + } > RAM_RO + + .ram.code_rodata : + { + __ram_code_rodata_start__ = .; + + *(.rodata*) + *(.rodata.str1*) + __ram_code_rodata_end__ = .; + } > RAM_RO + + .system_restore_data : + { + /* data in this section will not be initialed by ram_start() */ + /* some of them will be initialed by boot loader */ + . = ALIGN(32); + *(.sys_restore.bss*) + *(.ram.bss.noinit*) + } > RAM_RO + + .heap (COPY): + { + __HeapBase = .; + __end__ = .; + end = __end__; + KEEP(*(.heap*)) + __HeapLimit = .; + } > RAM + + /* Continue to use the stack memory space initialed by ROM code */ + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + KEEP(*(.stack*)) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ +/* TODO: ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") */ +} diff --git a/project/realtek_amebaz2_v0_example/GCC-RELEASE/toolchain.mk b/project/realtek_amebaz2_v0_example/GCC-RELEASE/toolchain.mk index 19fa4932..d42b5172 100644 --- a/project/realtek_amebaz2_v0_example/GCC-RELEASE/toolchain.mk +++ b/project/realtek_amebaz2_v0_example/GCC-RELEASE/toolchain.mk @@ -2,6 +2,7 @@ ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) ELF2BIN = $(AMEBAZ2_TOOLDIR)/elf2bin.exe CHKSUM = $(AMEBAZ2_TOOLDIR)/checksum.exe + LZMA_PY = $(AMEBAZ2_TOOLDIR)/LZMA_GenCompressedFW.exe TOOLCHAIN_FILENAME_CURR = asdk-6.5.0-cygwin-newlib-build-3215-i686.tar.bz2 TOOLCHAIN_FILENAME_PREV = asdk-6.4.1-cygwin-newlib-build-2778-i686.tar.bz2 TOOLCHAIN_BITS = 32 @@ -18,6 +19,7 @@ endif ifeq ($(findstring Linux, $(OS)), Linux) ELF2BIN = $(AMEBAZ2_GCCTOOLDIR)/elf2bin.linux CHKSUM = $(AMEBAZ2_GCCTOOLDIR)/checksum.linux + LZMA_PY = $(AMEBAZ2_GCCTOOLDIR)/./LZMA_GenCompressedFW_linux TOOLCHAIN_FILENAME_CURR = asdk-6.5.0-linux-newlib-build-3215-x86_64.tar.bz2 TOOLCHAIN_FILENAME_PREV = asdk-6.4.1-linux-newlib-build-3026-x86_64.tar.bz2 TOOLCHAIN_BITS = 64 diff --git a/project/realtek_amebaz2_v0_example/inc/build_info.h b/project/realtek_amebaz2_v0_example/inc/build_info.h index 68418a0e..7be0bb48 100644 --- a/project/realtek_amebaz2_v0_example/inc/build_info.h +++ b/project/realtek_amebaz2_v0_example/inc/build_info.h @@ -1,9 +1,9 @@ -#define RTL_FW_COMPILE_TIME RTL8710CFW_COMPILE_TIME -#define RTL_FW_COMPILE_DATE RTL8710CFW_COMPILE_DATE -#define UTS_VERSION "Mon 09/12/-15:08:34" -#define RTL8710CFW_COMPILE_TIME "Mon 09/12/-15:08:34" -#define RTL8710CFW_COMPILE_DATE "Mon 09/12/" -#define RTL8710CFW_COMPILE_BY "wutanghong" -#define RTL8710CFW_COMPILE_HOST "SGSD2G241-PC" -#define RTL8710CFW_COMPILE_DOMAIN -#define RTL8710CFW_COMPILER "IAR compiler" +#define RTL_FW_COMPILE_TIME RTL8710CFW_COMPILE_TIME +#define RTL_FW_COMPILE_DATE RTL8710CFW_COMPILE_DATE +#define UTS_VERSION "2022/10/04-10:43:33" +#define RTL8710CFW_COMPILE_TIME "2022/10/04-10:43:33" +#define RTL8710CFW_COMPILE_DATE "20221004" +#define RTL8710CFW_COMPILE_BY "wutanghong" +#define RTL8710CFW_COMPILE_HOST "" +#define RTL8710CFW_COMPILE_DOMAIN "realtek-sg.com" +#define RTL8710CFW_COMPILER "gcc 6.4.1" diff --git a/project/realtek_amebaz2_v0_example/inc/platform_opts.h b/project/realtek_amebaz2_v0_example/inc/platform_opts.h index 5d8fe71d..1cd6376f 100644 --- a/project/realtek_amebaz2_v0_example/inc/platform_opts.h +++ b/project/realtek_amebaz2_v0_example/inc/platform_opts.h @@ -134,6 +134,7 @@ /* For SSL/TLS */ #define CONFIG_USE_POLARSSL 0 //polarssl is no longer suppported for AmebaZ2 #define CONFIG_USE_MBEDTLS 1 +#define CONFIG_MBEDTLS_VERSION3 0 #if ((CONFIG_USE_POLARSSL == 0) && (CONFIG_USE_MBEDTLS == 0)) || ((CONFIG_USE_POLARSSL == 1) && (CONFIG_USE_MBEDTLS == 1)) #undef CONFIG_USE_POLARSSL #define CONFIG_USE_POLARSSL 1 @@ -142,6 +143,9 @@ #endif #define CONFIG_SSL_CLIENT_PRIVATE_IN_TZ 1 +/* For Bridge Mode */ +#define CONFIG_BRIDGE 0 + /* For LWIP configuration */ #define CONFIG_LWIP_DHCP_COARSE_TIMER 60 @@ -199,6 +203,9 @@ /* For MQTT example */ #define CONFIG_EXAMPLE_MQTT 0 +#if CONFIG_EXAMPLE_MQTT +//#define MQTTV5 1 +#endif /* For multicast example */ #define CONFIG_EXAMPLE_MCAST 0 @@ -400,4 +407,13 @@ #define CONFIG_MIIO_MP 0 //miio mp test and rw private data #endif +#define CONFIG_EXAMPLE_MBEDTLS_ECDHE 0 + +#endif + +#define CONFIG_UART_UPDATE 0 +#if CONFIG_UART_UPDATE +#undef CONFIG_EXAMPLE_WLAN_FAST_CONNECT +#define CONFIG_EXAMPLE_WLAN_FAST_CONNECT 0 +#define CONFIG_FAST_DHCP 0 #endif diff --git a/project/realtek_amebaz2_v0_example/inc/platform_opts_bt.h b/project/realtek_amebaz2_v0_example/inc/platform_opts_bt.h index 41b7a05d..93c80cf3 100644 --- a/project/realtek_amebaz2_v0_example/inc/platform_opts_bt.h +++ b/project/realtek_amebaz2_v0_example/inc/platform_opts_bt.h @@ -14,6 +14,8 @@ #define CONFIG_BT_FUZZ_TEST 0 #define CONFIG_BT_OTA_CENTRAL_CLIENT 0 #define CONFIG_BT_DATATRANS 0 +#define CONFIG_BT_JOYLINK_ADAPTER 0 +#define CONFIG_BT_ANCS 0 #define CONFIG_BT_MESH_PROVISIONER 0 #define CONFIG_BT_MESH_DEVICE 0 #define CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE 0 @@ -24,7 +26,11 @@ #define CONFIG_BT_MESH_PROVISIONER_RTK_DEMO 0 #define CONFIG_BT_MESH_DEVICE_RTK_DEMO 0 #define CONFIG_BT_MESH_TEST 0 +#define CONFIG_BT_MESH_DEVICE_MATTER 0 +#define CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT 0 #define CONFIG_BT_ONLY_WITHOUT_WLAN 0 +/* For Google seamless setup FreeRTOS SDK example */ +#define CONFIG_BT_GOOGLE_SEAMLESS 0 #endif // CONFIG_BT #if defined CONFIG_BT_SCATTERNET && CONFIG_BT_SCATTERNET @@ -39,9 +45,13 @@ #define CONFIG_BT_WHITE_LIST_TO_FLASH 0 #endif +#if ((defined CONFIG_BT_OTA_CENTRAL_CLIENT && CONFIG_BT_OTA_CENTRAL_CLIENT) || \ + (defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT)) #if defined CONFIG_BT_OTA_CENTRAL_CLIENT && CONFIG_BT_OTA_CENTRAL_CLIENT #define CONFIG_BT_OTA_CENTRAL_CLIENT_SPLIT 0 #endif +#define CONFIG_BT_OTA_CENTRAL_CLIENT_W_REQ_CONFLICT 0 +#endif #if ((defined CONFIG_BT_MESH_PROVISIONER && CONFIG_BT_MESH_PROVISIONER) || \ (defined CONFIG_BT_MESH_DEVICE && CONFIG_BT_MESH_DEVICE) || \ @@ -71,5 +81,31 @@ #error "Only one of CONFIG_BT_MESH_CENTRAL, CONFIG_BT_MESH_PERIPHERAL and CONFIG_BT_MESH_SCATTERNET can be enabled" #endif +#if (defined(CONFIG_BT_MESH_DEVICE_MATTER) && CONFIG_BT_MESH_DEVICE_MATTER) +#if ((defined CONFIG_BT_MESH_PROVISIONER && CONFIG_BT_MESH_PROVISIONER) || \ + (defined CONFIG_BT_MESH_DEVICE && CONFIG_BT_MESH_DEVICE) || \ + (defined CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE && CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE)) +#error "only open CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE and then open CONFIG_BT_MESH_DEVICE_MATTER" +#endif +#if ((defined CONFIG_BT_MESH_CENTRAL && CONFIG_BT_MESH_CENTRAL) || \ + (defined CONFIG_BT_MESH_PERIPHERAL && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined CONFIG_BT_MESH_SCATTERNET && CONFIG_BT_MESH_SCATTERNET)) +#error "CONFIG_BT_MESH_DEVICE_MATTER or CONFIG_BT_MESH_CENTRAL or CONFIG_BT_MESH_PERIPHERAL or CONFIG_BT_MESH_SCATTERNET not open at the same time" +#endif +#endif + +#if defined(CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT) && CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT +#if ((defined CONFIG_BT_MESH_PROVISIONER && CONFIG_BT_MESH_PROVISIONER) || \ + (defined CONFIG_BT_MESH_DEVICE && CONFIG_BT_MESH_DEVICE) || \ + (defined CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE && CONFIG_BT_MESH_DEVICE_MULTIPLE_PROFILE)) +#error "only open CONFIG_BT_MESH_PROVISIONER_MULTIPLE_PROFILE and then open CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT" +#endif +#if ((defined CONFIG_BT_MESH_CENTRAL && CONFIG_BT_MESH_CENTRAL) || \ + (defined CONFIG_BT_MESH_PERIPHERAL && CONFIG_BT_MESH_PERIPHERAL) || \ + (defined CONFIG_BT_MESH_SCATTERNET && CONFIG_BT_MESH_SCATTERNET)) +#error "CONFIG_BT_MESH_PROVISIONER_OTA_CLIENT or CONFIG_BT_MESH_CENTRAL or CONFIG_BT_MESH_PERIPHERAL or CONFIG_BT_MESH_SCATTERNET not open at the same time" +#endif +#endif + #endif // __PLATFORM_OPTS_BT_H__